rifle: "bullet hail" feature: empty whole magazine (not enabled)
authorRudolf Polzer <divverent@alientrap.org>
Fri, 21 May 2010 07:36:35 +0000 (09:36 +0200)
committerRudolf Polzer <divverent@alientrap.org>
Fri, 21 May 2010 08:14:33 +0000 (10:14 +0200)
balance.cfg
balance25.cfg
balanceSamual.cfg
balanceXPM.cfg
qcsrc/server/cl_weaponsystem.qc
qcsrc/server/w_campingrifle.qc

index d8c62d1c1814934594a911dfdd3c1b5aaed1b7cf..dbe328c7af37795a5b215571678250be29cba85d 100644 (file)
@@ -515,6 +515,7 @@ set g_balance_campingrifle_primary_animtime 0.3
 set g_balance_campingrifle_primary_ammo 10
 set g_balance_campingrifle_primary_bulletconstant 130 // 56.3qu
 set g_balance_campingrifle_primary_burstcost 0.35 // require same cooldown as secondary, note it's smaller than primary refire time
+set g_balance_campingrifle_primary_bullethail 0
 set g_balance_campingrifle_secondary_damage 15
 set g_balance_campingrifle_secondary_headshotaddeddamage 25
 set g_balance_campingrifle_secondary_spread 0.02
@@ -526,6 +527,7 @@ set g_balance_campingrifle_secondary_animtime 0.1
 set g_balance_campingrifle_secondary_ammo 4
 set g_balance_campingrifle_secondary_bulletconstant 130 // 18.3qu
 set g_balance_campingrifle_secondary_burstcost 0.35
+set g_balance_campingrifle_secondary_bullethail 0
 // }}}
 // {{{ tuba
 set g_balance_tuba_refire 0.05
index db772801e79ce2a325f3a1d1278cf53dba8bbf76..e1079db5fb3a75343621a655f8b7681591050a69 100644 (file)
@@ -515,6 +515,7 @@ set g_balance_campingrifle_primary_animtime 0.3
 set g_balance_campingrifle_primary_ammo 10
 set g_balance_campingrifle_primary_bulletconstant 130 // 56.3qu
 set g_balance_campingrifle_primary_burstcost 0
+set g_balance_campingrifle_primary_bullethail 0 // empty magazine on shot
 set g_balance_campingrifle_secondary_damage 35
 set g_balance_campingrifle_secondary_headshotaddeddamage 15 // 50 damage only on head
 set g_balance_campingrifle_secondary_spread 0.008
@@ -526,6 +527,7 @@ set g_balance_campingrifle_secondary_animtime 0.1
 set g_balance_campingrifle_secondary_ammo 10
 set g_balance_campingrifle_secondary_bulletconstant 130 // 18.3qu
 set g_balance_campingrifle_secondary_burstcost 0
+set g_balance_campingrifle_secondary_bullethail 0 // empty magazine on shot
 // }}}
 // {{{ tuba
 set g_balance_tuba_refire 0.05
index b86be9dc2b17ee6b5ea64db443f271088f822df4..dd2bd1cd104fa370c279cc42fb1c5101adee7569 100644 (file)
@@ -515,6 +515,7 @@ set g_balance_campingrifle_primary_animtime 0.3
 set g_balance_campingrifle_primary_ammo 10
 set g_balance_campingrifle_primary_bulletconstant 130 // 56.3qu
 set g_balance_campingrifle_primary_burstcost 0.35 // require same cooldown as secondary, note it's smaller than primary refire time
+set g_balance_campingrifle_primary_bullethail 0
 set g_balance_campingrifle_secondary_damage 15
 set g_balance_campingrifle_secondary_headshotaddeddamage 25
 set g_balance_campingrifle_secondary_spread 0.02
@@ -526,6 +527,7 @@ set g_balance_campingrifle_secondary_animtime 0.1
 set g_balance_campingrifle_secondary_ammo 4
 set g_balance_campingrifle_secondary_bulletconstant 130 // 18.3qu
 set g_balance_campingrifle_secondary_burstcost 0.35
+set g_balance_campingrifle_secondary_bullethail 0
 // }}}
 // {{{ tuba
 set g_balance_tuba_refire 0.05
index faf5d247287aa8138320408491c8cd774bdb128f..b89adf56886b34f09ebe1b5b3f63c61990e5e7f4 100644 (file)
@@ -516,6 +516,7 @@ set g_balance_campingrifle_primary_animtime 0.7
 set g_balance_campingrifle_primary_ammo 10
 set g_balance_campingrifle_primary_bulletconstant 130 // 56.3qu
 set g_balance_campingrifle_primary_burstcost 0.35 // require same cooldown as secondary, note it's smaller than primary refire time
+set g_balance_campingrifle_primary_bullethail 0
 set g_balance_campingrifle_secondary_damage 15
 set g_balance_campingrifle_secondary_headshotaddeddamage 25
 set g_balance_campingrifle_secondary_spread 0.02
@@ -527,6 +528,7 @@ set g_balance_campingrifle_secondary_animtime 0.1
 set g_balance_campingrifle_secondary_ammo 4
 set g_balance_campingrifle_secondary_bulletconstant 130 // 18.3qu
 set g_balance_campingrifle_secondary_burstcost 0.35
+set g_balance_campingrifle_secondary_bullethail 0
 // }}}
 // {{{ tuba
 set g_balance_tuba_refire 0.05
index e17c346d283373e2c96de40c34ab709685806872..b343862ba54250f8515ab864f10f641df50bcc1b 100644 (file)
@@ -34,6 +34,7 @@ float W_WeaponRateFactor()
 
 void W_SwitchWeapon_Force(entity e, float w)
 {
+       backtrace("switch");
        e.cnt = e.switchweapon;
        e.switchweapon = w;
        e.selectweapon = w;
@@ -1031,29 +1032,39 @@ void weapon_setup(float windex)
 };
 
 // perform weapon to attack (weaponstate and attack_finished check is here)
+void W_SwitchToOtherWeapon(entity pl)
+{
+       // hack to ensure it switches to an OTHER weapon (in case the other fire mode still has ammo, we want that anyway)
+       float w, ww;
+       w = W_WeaponBit(pl.weapon);
+       pl.weapons &~= w;
+       ww = w_getbestweapon(pl);
+       pl.weapons |= w;
+       if(ww)
+               W_SwitchWeapon_Force(pl, ww);
+}
+float weapon_prepareattack_checkammo(float secondary)
+{
+       if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+       if (!weapon_action(self.weapon, WR_CHECKAMMO1 + secondary))
+       {
+               W_SwitchToOtherWeapon(self);
+               return FALSE;
+       }
+       return TRUE;
+}
 .float race_penalty;
-float weapon_prepareattack(float secondary, float attacktime)
+float weapon_prepareattack_check(float secondary, float attacktime)
 {
+       if(!weapon_prepareattack_checkammo(secondary))
+               return FALSE;
+
        //if sv_ready_restart_after_countdown is set, don't allow the player to shoot
        //if all players readied up and the countdown is running
        if(time < game_starttime || time < self.race_penalty) {
                return FALSE;
        }
 
-       if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-       if (!weapon_action(self.weapon, WR_CHECKAMMO1 + secondary))
-       {
-               // hack to ensure it switches to an OTHER weapon (in case the other fire mode still has ammo, we want that anyway)
-               float w, ww;
-               w = W_WeaponBit(self.weapon);
-               self.weapons &~= w;
-               ww = w_getbestweapon(self);
-               self.weapons |= w;
-               if(ww)
-                       W_SwitchWeapon_Force(self, ww);
-               return FALSE;
-       }
-
        if (timeoutStatus == 2) //don't allow the player to shoot while game is paused
                return FALSE;
 
@@ -1070,6 +1081,11 @@ float weapon_prepareattack(float secondary, float attacktime)
                if (self.weaponentity.state != WS_READY)
                        return FALSE;
        }
+
+       return TRUE;
+}
+float weapon_prepareattack_do(float secondary, float attacktime)
+{
        self.weaponentity.state = WS_INUSE;
 
        self.spawnshieldtime = min(self.spawnshieldtime, time); // kill spawn shield when you fire
@@ -1087,7 +1103,17 @@ float weapon_prepareattack(float secondary, float attacktime)
        self.bulletcounter += 1;
        //dprint("attack finished ", ftos(ATTACK_FINISHED(self)), "\n");
        return TRUE;
-};
+}
+float weapon_prepareattack(float secondary, float attacktime)
+{
+       if(weapon_prepareattack_check(secondary, attacktime))
+       {
+               weapon_prepareattack_do(secondary, attacktime);
+               return TRUE;
+       }
+       else
+               return FALSE;
+}
 
 void weapon_thinkf(float fr, float t, void() func)
 {
index f0ac7307bededa0d525fa31b0ff19ececbbe21fd..8f6a9104946ce3f6dc263191d5520853f1065e57 100644 (file)
@@ -31,24 +31,27 @@ void W_CampingRifle_ReloadedAndReady()
        w_ready();
 }
 
-void W_CampingRifle_Reload()
+float W_CampingRifle_Reload()
 {
        float t;
 
        W_CampingRifle_CheckMaxBullets(TRUE);
-       if (self.campingrifle_bulletcounter >= cvar("g_balance_campingrifle_magazinecapacity"))
-               return;
 
-       if(self.ammo_nails < min(cvar("g_balance_campingrifle_primary_ammo"), cvar("g_balance_campingrifle_secondary_ammo")))
+       if(self.ammo_nails < min(cvar("g_balance_campingrifle_primary_ammo"), cvar("g_balance_campingrifle_secondary_ammo"))) // when we get here, bulletcounter must be 0 or -1
        {
+               print("cannot reload... not enough bullets\n");
                self.campingrifle_bulletcounter = -1; // reload later
-               return;
+               W_SwitchToOtherWeapon(self);
+               return 0;
        }
        
+       if (self.campingrifle_bulletcounter >= cvar("g_balance_campingrifle_magazinecapacity"))
+               return 0;
+
        if (self.weaponentity)
        {
                if (self.weaponentity.wframe == WFRAME_RELOAD)
-                       return;
+                       return 0;
 
                // allow to switch away while reloading, but this will cause a new reload!
                self.weaponentity.state = WS_READY;
@@ -62,15 +65,16 @@ void W_CampingRifle_Reload()
        weapon_thinkf(WFRAME_RELOAD, cvar("g_balance_campingrifle_reloadtime"), W_CampingRifle_ReloadedAndReady);
 
        self.campingrifle_bulletcounter = -1;
+
+       return 1;
 }
 
 void W_CampingRifle_CheckReloadAndReady()
 {
        w_ready();
-       if (self.campingrifle_bulletcounter <= 0)
-               W_CampingRifle_Reload();
-       else
-               w_ready();
+       if(self.campingrifle_bulletcounter <= 0)
+               if(W_CampingRifle_Reload())
+                       return;
 }
 
 void W_CampingRifle_FireBullet(float pSpread, float pDamage, float pHeadshotAddedDamage, float pForce, float pSpeed, float pLifetime, float pAmmo, float deathtype, float pBulletConstant)
@@ -116,6 +120,57 @@ void spawnfunc_weapon_campingrifle (void)
        weapon_defaultspawnfunc(WEP_CAMPINGRIFLE);
 }
 
+.void(void) campingrifle_bullethail_attackfunc;
+.float campingrifle_bullethail_frame;
+.float campingrifle_bullethail_animtime;
+.float campingrifle_bullethail_refire;
+void W_CampingRifle_BulletHail_Continue()
+{
+       float r, sw, af;
+       W_CampingRifle_CheckReloadAndReady();
+       if(self.campingrifle_bulletcounter < 0)
+               return; // reloading, so we are done
+       sw = self.switchweapon; // make it not detect weapon changes as reason to abort firing
+       af = ATTACK_FINISHED(self);
+       self.switchweapon = self.weapon;
+       ATTACK_FINISHED(self) = time;
+       print(ftos(self.ammo_nails), "\n");
+       r = weapon_prepareattack(self.campingrifle_bullethail_frame == WFRAME_FIRE2, self.campingrifle_bullethail_refire);
+       if(self.switchweapon == self.weapon)
+               self.switchweapon = sw;
+       if(r)
+       {
+               self.campingrifle_bullethail_attackfunc();
+               weapon_thinkf(self.campingrifle_bullethail_frame, self.campingrifle_bullethail_animtime, W_CampingRifle_BulletHail_Continue);
+               print("thinkf set\n");
+       }
+       else
+       {
+               ATTACK_FINISHED(self) = af; // reset attack_finished if we didn't fire, so the last shot enforces the refire time
+               print("out of ammo... ", ftos(self.weaponentity.state), "\n");
+       }
+}
+
+void W_CampingRifle_BulletHail(float mode, void(void) AttackFunc, float fr, float animtime, float refire)
+{
+       // if we get here, we have at least one bullet to fire
+       AttackFunc();
+       if(mode)
+       {
+               // continue hail
+               self.campingrifle_bullethail_attackfunc = AttackFunc;
+               self.campingrifle_bullethail_frame = fr;
+               self.campingrifle_bullethail_animtime = animtime;
+               self.campingrifle_bullethail_refire = refire;
+               weapon_thinkf(fr, animtime, W_CampingRifle_BulletHail_Continue);
+       }
+       else
+       {
+               // just one shot
+               weapon_thinkf(fr, animtime, W_CampingRifle_CheckReloadAndReady);
+       }
+}
+
 .float bot_secondary_campingriflemooth;
 float w_campingrifle(float req)
 {
@@ -155,19 +210,19 @@ float w_campingrifle(float req)
                {
                        self.campingrifle_accumulator = bound(time - cvar("g_balance_campingrifle_bursttime"), self.campingrifle_accumulator, time);
                        if (self.BUTTON_ATCK)
+                       if (weapon_prepareattack_check(0, cvar("g_balance_campingrifle_primary_refire")))
                        if (time >= self.campingrifle_accumulator + cvar("g_balance_campingrifle_primary_burstcost"))
-                       if (weapon_prepareattack(0, cvar("g_balance_campingrifle_primary_refire")))
                        {
-                               W_CampingRifle_Attack();
-                               weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_campingrifle_primary_animtime"), W_CampingRifle_CheckReloadAndReady);
+                               weapon_prepareattack_do(0, cvar("g_balance_campingrifle_primary_refire"));
+                               W_CampingRifle_BulletHail(cvar("g_balance_campingrifle_primary_bullethail"), W_CampingRifle_Attack, WFRAME_FIRE1, cvar("g_balance_campingrifle_primary_animtime"), cvar("g_balance_campingrifle_primary_refire"));
                                self.campingrifle_accumulator += cvar("g_balance_campingrifle_primary_burstcost");
                        }
                        if (self.BUTTON_ATCK2)
+                       if (weapon_prepareattack_check(1, cvar("g_balance_campingrifle_secondary_refire")))
                        if (time >= self.campingrifle_accumulator + cvar("g_balance_campingrifle_secondary_burstcost"))
-                       if (weapon_prepareattack(1, cvar("g_balance_campingrifle_secondary_refire")))
                        {
-                               W_CampingRifle_Attack2();
-                               weapon_thinkf(WFRAME_FIRE2, cvar("g_balance_campingrifle_secondary_animtime"), W_CampingRifle_CheckReloadAndReady);
+                               weapon_prepareattack_do(1, cvar("g_balance_campingrifle_secondary_refire"));
+                               W_CampingRifle_BulletHail(cvar("g_balance_campingrifle_secondary_bullethail"), W_CampingRifle_Attack2, WFRAME_FIRE2, cvar("g_balance_campingrifle_secondary_animtime"), cvar("g_balance_campingrifle_primary_refire"));
                                self.campingrifle_accumulator += cvar("g_balance_campingrifle_secondary_burstcost");
                        }
                }