void W_SwitchWeapon_Force(entity e, float w)
{
+ backtrace("switch");
e.cnt = e.switchweapon;
e.switchweapon = w;
e.selectweapon = w;
};
// 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;
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
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)
{
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;
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)
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)
{
{
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");
}
}