+#include "weaponsystem.qh"
+#include "../_all.qh"
+
+#include "selection.qh"
+
+#include "../command/common.qh"
+#include "../mutators/mutators_include.qh"
+#include "../round_handler.qh"
+#include "../t_items.qh"
+#include "../../common/animdecide.qh"
+#include "../../common/constants.qh"
+#include "../../common/monsters/all.qh"
+#include "../../common/notifications.qh"
+#include "../../common/util.qh"
+#include "../../common/weapons/all.qh"
+#include "../../csqcmodellib/sv_model.qh"
+
/*
===========================================================================
float t;
t = 1.0 / g_weaponratefactor;
+ weapon_rate = t;
+ MUTATOR_CALLHOOK(WeaponRateFactor);
+ t = weapon_rate;
+
return t;
}
-void W_SwitchWeapon_Force(entity e, float w)
+float W_WeaponSpeedFactor()
{
- e.cnt = e.switchweapon;
- e.switchweapon = w;
- e.selectweapon = w;
-}
-
-.float antilag_debug;
-
-// VorteX: static frame globals
-float WFRAME_DONTCHANGE = -1;
-float WFRAME_FIRE1 = 0;
-float WFRAME_FIRE2 = 1;
-float WFRAME_IDLE = 2;
-float WFRAME_RELOAD = 3;
-.float wframe;
-
-void(float fr, float t, void() func) weapon_thinkf;
+ float t;
+ t = 1.0 * g_weaponspeedfactor;
-vector w_shotorg;
-vector w_shotdir;
-vector w_shotend;
+ ret_float = t;
+ MUTATOR_CALLHOOK(WeaponSpeedFactor);
+ t = ret_float;
-.float prevstrengthsound;
-.float prevstrengthsoundattempt;
-void W_PlayStrengthSound(entity player) // void W_PlayStrengthSound
-{
- if((player.items & IT_STRENGTH)
- && ((time > player.prevstrengthsound + autocvar_sv_strengthsound_antispam_time) // prevent insane sound spam
- || (time > player.prevstrengthsoundattempt + autocvar_sv_strengthsound_antispam_refire_threshold)))
- {
- sound(player, CH_TRIGGER, "weapons/strength_fire.wav", VOL_BASE, ATTN_NORM);
- player.prevstrengthsound = time;
- }
- player.prevstrengthsoundattempt = time;
+ return t;
}
-// this function calculates w_shotorg and w_shotdir based on the weapon model
-// offset, trueaim and antilag, and won't put w_shotorg inside a wall.
-// make sure you call makevectors first (FIXME?)
-void W_SetupShot_Dir_ProjectileSize_Range(entity ent, vector s_forward, vector mi, vector ma, float antilag, float recoil, string snd, float chan, float maxdamage, float range)
-{
- float nudge = 1; // added to traceline target and subtracted from result
- float oldsolid;
- vector vecs, dv;
- oldsolid = ent.dphitcontentsmask;
- if(ent.weapon == WEP_RIFLE)
- ent.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_CORPSE;
- else
- ent.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
- if(antilag)
- WarpZone_traceline_antilag(world, ent.origin + ent.view_ofs, ent.origin + ent.view_ofs + s_forward * range, MOVE_NORMAL, ent, ANTILAG_LATENCY(ent));
- // passing world, because we do NOT want it to touch dphitcontentsmask
- else
- WarpZone_TraceLine(ent.origin + ent.view_ofs, ent.origin + ent.view_ofs + s_forward * range, MOVE_NOMONSTERS, ent);
- ent.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
-
- vector vf, vr, vu;
- vf = v_forward;
- vr = v_right;
- vu = v_up;
- w_shotend = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos); // warpzone support
- v_forward = vf;
- v_right = vr;
- v_up = vu;
-
- // un-adjust trueaim if shotend is too close
- if(vlen(w_shotend - (ent.origin + ent.view_ofs)) < autocvar_g_trueaim_minrange)
- w_shotend = ent.origin + ent.view_ofs + s_forward * autocvar_g_trueaim_minrange;
-
- // track max damage
- if(accuracy_canbegooddamage(ent))
- accuracy_add(ent, ent.weapon, maxdamage, 0);
-
- W_HitPlotAnalysis(ent, v_forward, v_right, v_up);
-
- if(ent.weaponentity.movedir_x > 0)
- vecs = ent.weaponentity.movedir;
- else
- vecs = '0 0 0';
-
- dv = v_right * -vecs_y + v_up * vecs_z;
- w_shotorg = ent.origin + ent.view_ofs + dv;
-
- // now move the shotorg forward as much as requested if possible
- if(antilag)
- {
- if(ent.antilag_debug)
- tracebox_antilag(ent, w_shotorg, mi, ma, w_shotorg + v_forward * (vecs_x + nudge), MOVE_NORMAL, ent, ent.antilag_debug);
- else
- tracebox_antilag(ent, w_shotorg, mi, ma, w_shotorg + v_forward * (vecs_x + nudge), MOVE_NORMAL, ent, ANTILAG_LATENCY(ent));
- }
- else
- tracebox(w_shotorg, mi, ma, w_shotorg + v_forward * (vecs_x + nudge), MOVE_NORMAL, ent);
- w_shotorg = trace_endpos - v_forward * nudge;
- // calculate the shotdir from the chosen shotorg
- w_shotdir = normalize(w_shotend - w_shotorg);
-
- if (antilag)
- if (!ent.cvar_cl_noantilag)
- {
- if (autocvar_g_antilag == 1) // switch to "ghost" if not hitting original
- {
- traceline(w_shotorg, w_shotorg + w_shotdir * range, MOVE_NORMAL, ent);
- if (!trace_ent.takedamage)
- {
- traceline_antilag_force (ent, w_shotorg, w_shotorg + w_shotdir * range, MOVE_NORMAL, ent, ANTILAG_LATENCY(ent));
- if (trace_ent.takedamage && IS_PLAYER(trace_ent))
- {
- entity e;
- e = trace_ent;
- traceline(w_shotorg, e.origin, MOVE_NORMAL, ent);
- if(trace_ent == e)
- w_shotdir = normalize(trace_ent.origin - w_shotorg);
- }
- }
- }
- else if(autocvar_g_antilag == 3) // client side hitscan
- {
- // this part MUST use prydon cursor
- if (ent.cursor_trace_ent) // client was aiming at someone
- if (ent.cursor_trace_ent != ent) // just to make sure
- if (ent.cursor_trace_ent.takedamage) // and that person is killable
- if (IS_PLAYER(ent.cursor_trace_ent)) // and actually a player
- {
- // verify that the shot would miss without antilag
- // (avoids an issue where guns would always shoot at their origin)
- traceline(w_shotorg, w_shotorg + w_shotdir * range, MOVE_NORMAL, ent);
- if (!trace_ent.takedamage)
- {
- // verify that the shot would hit if altered
- traceline(w_shotorg, ent.cursor_trace_ent.origin, MOVE_NORMAL, ent);
- if (trace_ent == ent.cursor_trace_ent)
- w_shotdir = normalize(ent.cursor_trace_ent.origin - w_shotorg);
- else
- print("antilag fail\n");
- }
- }
- }
- }
-
- ent.dphitcontentsmask = oldsolid; // restore solid type (generally SOLID_SLIDEBOX)
-
- if (!g_norecoil)
- ent.punchangle_x = recoil * -1;
-
- if (snd != "")
- {
- sound (ent, chan, snd, VOL_BASE, ATTN_NORM);
- W_PlayStrengthSound(ent);
- }
- // nudge w_shotend so a trace to w_shotend hits
- w_shotend = w_shotend + normalize(w_shotend - w_shotorg) * nudge;
-}
-
-#define W_SetupShot_Dir_ProjectileSize(ent,s_forward,mi,ma,antilag,recoil,snd,chan,maxdamage) W_SetupShot_Dir_ProjectileSize_Range(ent, s_forward, mi, ma, antilag, recoil, snd, chan, maxdamage, MAX_SHOT_DISTANCE)
-#define W_SetupShot_ProjectileSize(ent,mi,ma,antilag,recoil,snd,chan,maxdamage) W_SetupShot_Dir_ProjectileSize(ent, v_forward, mi, ma, antilag, recoil, snd, chan, maxdamage)
-#define W_SetupShot_Dir(ent,s_forward,antilag,recoil,snd,chan,maxdamage) W_SetupShot_Dir_ProjectileSize(ent, s_forward, '0 0 0', '0 0 0', antilag, recoil, snd, chan, maxdamage)
-#define W_SetupShot(ent,antilag,recoil,snd,chan,maxdamage) W_SetupShot_ProjectileSize(ent, '0 0 0', '0 0 0', antilag, recoil, snd, chan, maxdamage)
-#define W_SetupShot_Range(ent,antilag,recoil,snd,chan,maxdamage,range) W_SetupShot_Dir_ProjectileSize_Range(ent, v_forward, '0 0 0', '0 0 0', antilag, recoil, snd, chan, maxdamage, range)
+void(float fr, float t, void() func) weapon_thinkf;
float CL_Weaponentity_CustomizeEntityForClient()
{
if(IS_SPEC(other))
if(other.enemy == self.owner)
self.viewmodelforclient = other;
- return TRUE;
+ return true;
}
/*
self.view_ofs = '0 0 0';
- if(self.movedir_x >= 0)
+ if(self.movedir.x >= 0)
{
vector v0;
v0 = self.movedir;
- self.movedir = shotorg_adjust(v0, FALSE, FALSE);
- self.view_ofs = shotorg_adjust(v0, FALSE, TRUE) - v0;
+ self.movedir = shotorg_adjust(v0, false, false);
+ self.view_ofs = shotorg_adjust(v0, false, true) - v0;
}
self.owner.stat_shotorg = compressShotOrigin(self.movedir);
self.movedir = decompressShotOrigin(self.owner.stat_shotorg); // make them match perfectly
setorigin(self, self.view_ofs);
// reset animstate now
self.wframe = WFRAME_IDLE;
- setanim(self, self.anim_idle, TRUE, FALSE, TRUE);
+ setanim(self, self.anim_idle, true, false, true);
}
vector CL_Weapon_GetShotOrg(float wpn)
void CL_Weaponentity_Think()
{
- float tb;
+ int tb;
self.nextthink = time;
if (intermission_running)
- self.frame = self.anim_idle_x;
+ self.frame = self.anim_idle.x;
if (self.owner.weaponentity != self)
{
if (self.weaponentity)
tb = (self.effects & (EF_TELEPORT_BIT | EF_RESTARTANIM_BIT));
self.effects = self.owner.effects & EFMASK_CHEAP;
- self.effects &~= EF_LOWPRECISION;
- self.effects &~= EF_FULLBRIGHT; // can mask team color, so get rid of it
- self.effects &~= EF_TELEPORT_BIT;
- self.effects &~= EF_RESTARTANIM_BIT;
+ self.effects &= ~EF_LOWPRECISION;
+ self.effects &= ~EF_FULLBRIGHT; // can mask team color, so get rid of it
+ self.effects &= ~EF_TELEPORT_BIT;
+ self.effects &= ~EF_RESTARTANIM_BIT;
self.effects |= tb;
if(self.owner.alpha == default_player_alpha)
}
self.angles = '0 0 0';
-
+
float f = (self.owner.weapon_nextthink - time);
if (self.state == WS_RAISE && !intermission_running)
{
entity newwep = get_weaponinfo(self.owner.switchweapon);
f = f * g_weaponratefactor / max(f, newwep.switchdelay_raise);
- //print(sprintf("CL_Weaponentity_Think(): cvar: %s, value: %f, nextthink: %f\n", sprintf("g_balance_%s_switchdelay_raise", newwep.netname), cvar(sprintf("g_balance_%s_switchdelay_raise", newwep.netname)), (self.owner.weapon_nextthink - time)));
self.angles_x = -90 * f * f;
}
else if (self.state == WS_DROP && !intermission_running)
{
entity oldwep = get_weaponinfo(self.owner.weapon);
f = 1 - f * g_weaponratefactor / max(f, oldwep.switchdelay_drop);
- //print(sprintf("CL_Weaponentity_Think(): cvar: %s, value: %f, nextthink: %f\n", sprintf("g_balance_%s_switchdelay_drop", oldwep.netname), cvar(sprintf("g_balance_%s_switchdelay_drop", oldwep.netname)), (self.owner.weapon_nextthink - time)));
self.angles_x = -90 * f * f;
}
else if (self.state == WS_CLEAR)
.float prevwarntime;
float weapon_prepareattack_checkammo(float secondary)
{
- if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+ if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
if (!WEP_ACTION(self.weapon, WR_CHECKAMMO1 + secondary))
{
// always keep the Mine Layer if we placed mines, so that we can detonate them
entity mine;
if(self.weapon == WEP_MINE_LAYER)
for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self)
- return FALSE;
+ return false;
+
+ if(self.weapon == WEP_SHOTGUN)
+ if(!secondary && WEP_CVAR(shotgun, secondary) == 1)
+ return false; // no clicking, just allow
if(self.weapon == self.switchweapon && time - self.prevdryfire > 1) // only play once BEFORE starting to switch weapons
{
- sound (self, CH_WEAPON_A, "weapons/dryfire.wav", VOL_BASE, ATTN_NORM);
+ sound (self, CH_WEAPON_A, "weapons/dryfire.wav", VOL_BASE, ATTEN_NORM);
self.prevdryfire = time;
}
{
W_SwitchToOtherWeapon(self);
}
-
- return FALSE;
+
+ return false;
}
- return TRUE;
+ return true;
}
.float race_penalty;
float weapon_prepareattack_check(float secondary, float attacktime)
{
if(!weapon_prepareattack_checkammo(secondary))
- return FALSE;
+ 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;
+ return false;
}
if (timeout_status == TIMEOUT_ACTIVE) //don't allow the player to shoot while game is paused
- return FALSE;
+ return false;
// do not even think about shooting if switching
if(self.switchweapon != self.weapon)
- return FALSE;
+ return false;
if(attacktime >= 0)
{
// don't fire if previous attack is not finished
if (ATTACK_FINISHED(self) > time + self.weapon_frametime * 0.5)
- return FALSE;
+ return false;
// don't fire while changing weapon
if (self.weaponentity.state != WS_READY)
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
float weapon_prepareattack_do(float secondary, float attacktime)
{
}
self.bulletcounter += 1;
//dprint("attack finished ", ftos(ATTACK_FINISHED(self)), "\n");
- return TRUE;
+ return true;
}
float weapon_prepareattack(float secondary, float attacktime)
{
if(weapon_prepareattack_check(secondary, attacktime))
{
weapon_prepareattack_do(secondary, attacktime);
- return TRUE;
+ return true;
}
else
- return FALSE;
+ return false;
}
void weapon_thinkf(float fr, float t, void() func)
if(fr == WFRAME_DONTCHANGE)
{
fr = self.weaponentity.wframe;
- restartanim = FALSE;
+ restartanim = false;
}
else if (fr == WFRAME_IDLE)
- restartanim = FALSE;
+ restartanim = false;
else
- restartanim = TRUE;
+ restartanim = true;
of = v_forward;
or = v_right;
a = self.weaponentity.anim_fire2;
else // if (fr == WFRAME_RELOAD)
a = self.weaponentity.anim_reload;
- a_z *= g_weaponratefactor;
- setanim(self.weaponentity, a, restartanim == FALSE, restartanim, restartanim);
+ a.z *= g_weaponratefactor;
+ setanim(self.weaponentity, a, restartanim == false, restartanim, restartanim);
}
v_forward = of;
if((fr == WFRAME_FIRE1 || fr == WFRAME_FIRE2) && t)
{
- if(self.weapon == WEP_SHOTGUN && fr == WFRAME_FIRE2)
+ if((self.weapon == WEP_SHOCKWAVE || self.weapon == WEP_SHOTGUN) && fr == WFRAME_FIRE2)
animdecide_setaction(self, ANIMACTION_MELEE, restartanim);
else
animdecide_setaction(self, ANIMACTION_SHOOT, restartanim);
return 1;
if(self.player_blocked)
return 1;
- if(self.freezetag_frozen)
+ if(self.frozen)
+ return 1;
+ if(self.weapon_blocked)
return 1;
return 0;
}
self.switchingweapon = 0;
self.weaponentity.state = WS_CLEAR;
self.weaponname = "";
- self.items &~= IT_AMMO;
+ //self.items &= ~IT_AMMO;
return;
}
self.switchingweapon = self.switchweapon;
entity newwep = get_weaponinfo(self.switchweapon);
- self.items &~= IT_AMMO;
- self.items = self.items | (newwep.items & IT_AMMO);
-
// the two weapon entities will notice this has changed and update their models
self.weapon = self.switchweapon;
self.weaponname = newwep.mdl;
- self.bulletcounter = 0; // WEAPONTODO
+ self.bulletcounter = 0;
+ self.ammo_field = newwep.ammo_field;
WEP_ACTION(self.switchweapon, WR_SETUP);
self.weaponentity.state = WS_RAISE;
// set our clip load to the load of the weapon we switched to, if it's reloadable
- if(newwep.spawnflags & WEP_FLAG_RELOADABLE && cvar(strcat("g_balance_", newwep.netname, "_reload_ammo"))) // prevent accessing undefined cvars
+ if(newwep.spawnflags & WEP_FLAG_RELOADABLE && newwep.reloading_ammo) // prevent accessing undefined cvars
{
self.clip_load = self.(weapon_load[self.switchweapon]);
- self.clip_size = cvar(strcat("g_balance_", newwep.netname, "_reload_ammo"));
+ self.clip_size = newwep.reloading_ammo;
}
else
self.clip_load = self.clip_size = 0;
- // VorteX: add player model weapon select frame here
- // setcustomframe(PlayerWeaponRaise);
weapon_thinkf(WFRAME_IDLE, newwep.switchdelay_raise, w_ready);
- //print(sprintf("W_WeaponFrame(): cvar: %s, value: %f\n", sprintf("g_balance_%s_switchdelay_raise", newwep.netname), cvar(sprintf("g_balance_%s_switchdelay_raise", newwep.netname))));
- weapon_boblayer1(PLAYER_WEAPONSELECTION_SPEED, '0 0 0');
}
else if (self.weaponentity.state == WS_DROP)
{
{
// start switching!
self.switchingweapon = self.switchweapon;
-
entity oldwep = get_weaponinfo(self.weapon);
-
-#ifndef INDEPENDENT_ATTACK_FINISHED
+
+ // set up weapon switch think in the future, and start drop anim
+ #ifndef INDEPENDENT_ATTACK_FINISHED
if(ATTACK_FINISHED(self) <= time + self.weapon_frametime * 0.5)
{
-#endif
- sound (self, CH_WEAPON_SINGLE, "weapons/weapon_switch.wav", VOL_BASE, ATTN_NORM);
- self.weaponentity.state = WS_DROP;
- // set up weapon switch think in the future, and start drop anim
- weapon_thinkf(WFRAME_DONTCHANGE, oldwep.switchdelay_drop, w_clear);
- //print(sprintf("W_WeaponFrame(): cvar: %s, value: %f\n", sprintf("g_balance_%s_switchdelay_drop", oldwep.netname), cvar(sprintf("g_balance_%s_switchdelay_drop", oldwep.netname))));
- weapon_boblayer1(PLAYER_WEAPONSELECTION_SPEED, PLAYER_WEAPONSELECTION_RANGE);
-#ifndef INDEPENDENT_ATTACK_FINISHED
+ #endif
+ sound(self, CH_WEAPON_SINGLE, "weapons/weapon_switch.wav", VOL_BASE, ATTN_NORM);
+ self.weaponentity.state = WS_DROP;
+ weapon_thinkf(WFRAME_DONTCHANGE, oldwep.switchdelay_drop, w_clear);
+ #ifndef INDEPENDENT_ATTACK_FINISHED
}
-#endif
+ #endif
}
}
while (c < W_TICSPERFRAME)
{
c = c + 1;
- if(w && !WEPSET_CONTAINS_EW(self, w))
+ if(w && !(self.weapons & WepSet_FromWeapon(w)))
{
if(self.weapon == self.switchweapon)
W_SwitchWeapon_Force(self, w_getbestweapon(self));
bprint("\{1}^1ERROR: undefined weapon think function for ", self.netname, "\n");
}
}
-
-#if 0
- if (self.items & IT_CELLS)
- self.currentammo = self.ammo_cells;
- else if (self.items & IT_ROCKETS)
- self.currentammo = self.ammo_rockets;
- else if (self.items & IT_NAILS)
- self.currentammo = self.ammo_nails;
- else if (self.items & IT_SHELLS)
- self.currentammo = self.ammo_shells;
- else
- self.currentammo = 1;
-#endif
-}
-
-void weapon_boblayer1(float spd, vector org)
-{
- // VorteX: haste can be added here
-}
-
-vector W_CalculateProjectileVelocity(vector pvelocity, vector mvelocity, float forceAbsolute)
-{
- vector mdirection;
- float mspeed;
- vector outvelocity;
-
- mvelocity = mvelocity * g_weaponspeedfactor;
-
- mdirection = normalize(mvelocity);
- mspeed = vlen(mvelocity);
-
- outvelocity = get_shotvelocity(pvelocity, mdirection, mspeed, (forceAbsolute ? 0 : autocvar_g_projectiles_newton_style), autocvar_g_projectiles_newton_style_2_minfactor, autocvar_g_projectiles_newton_style_2_maxfactor);
-
- return outvelocity;
}
void W_AttachToShotorg(entity flash, vector offset)
flash.viewmodelforclient = self;
- if(self.weaponentity.oldorigin_x > 0)
+ if(self.weaponentity.oldorigin.x > 0)
{
setattachment(xflash, self.exteriorweaponentity, "");
setorigin(xflash, self.weaponentity.oldorigin + offset);
}
}
-#if 0
-float mspercallsum;
-float mspercallsstyle;
-float mspercallcount;
-#endif
-void W_SetupProjectileVelocityEx(entity missile, vector dir, vector upDir, float pSpeed, float pUpSpeed, float pZSpeed, float spread, float forceAbsolute)
+void W_DecreaseAmmo(float ammo_use)
{
- if(missile.owner == world)
- error("Unowned missile");
-
- dir = dir + upDir * (pUpSpeed / pSpeed);
- dir_z += pZSpeed / pSpeed;
- pSpeed *= vlen(dir);
- dir = normalize(dir);
+ entity wep = get_weaponinfo(self.weapon);
-#if 0
- if(autocvar_g_projectiles_spread_style != mspercallsstyle)
+ if(cvar("g_overkill"))
+ if(self.ok_use_ammocharge)
{
- mspercallsum = mspercallcount = 0;
- mspercallsstyle = autocvar_g_projectiles_spread_style;
+ ok_DecreaseCharge(self, self.weapon);
+ return; // TODO
}
- mspercallsum -= gettime(GETTIME_HIRES);
-#endif
- dir = W_CalculateSpread(dir, spread, g_weaponspreadfactor, autocvar_g_projectiles_spread_style);
-#if 0
- mspercallsum += gettime(GETTIME_HIRES);
- mspercallcount += 1;
- print("avg: ", ftos(mspercallcount / mspercallsum), " per sec\n");
-#endif
-
- missile.velocity = W_CalculateProjectileVelocity(missile.owner.velocity, pSpeed * dir, forceAbsolute);
-}
-
-void W_SetupProjectileVelocity(entity missile, float pSpeed, float spread)
-{
- W_SetupProjectileVelocityEx(missile, w_shotdir, v_up, pSpeed, 0, 0, spread, FALSE);
-}
-
-#define W_SETUPPROJECTILEVELOCITY_UP(m,s) W_SetupProjectileVelocityEx(m, w_shotdir, v_up, cvar(#s "_speed"), cvar(#s "_speed_up"), cvar(#s "_speed_z"), cvar(#s "_spread"), FALSE)
-#define W_SETUPPROJECTILEVELOCITY(m,s) W_SetupProjectileVelocityEx(m, w_shotdir, v_up, cvar(#s "_speed"), 0, 0, cvar(#s "_spread"), FALSE)
-void W_DecreaseAmmo(.float ammo_type, float ammo_use, float ammo_reload) // WEAPONTODO: why does this have ammo_type?
-{
- if((self.items & IT_UNLIMITED_WEAPON_AMMO) && !ammo_reload)
+ if((self.items & IT_UNLIMITED_WEAPON_AMMO) && !wep.reloading_ammo)
return;
// if this weapon is reloadable, decrease its load. Else decrease the player's ammo
- if(ammo_reload)
+ if(wep.reloading_ammo)
{
self.clip_load -= ammo_use;
self.(weapon_load[self.weapon]) = self.clip_load;
}
- else
- self.(self.current_ammo) -= ammo_use;
+ else if(wep.ammo_field != ammo_none)
+ {
+ self.(wep.ammo_field) -= ammo_use;
+ if(self.(wep.ammo_field) < 0)
+ {
+ backtrace(sprintf(
+ "W_DecreaseAmmo(%.2f): '%s' subtracted too much %s from '%s', resulting with '%.2f' left... "
+ "Please notify Samual immediately with a copy of this backtrace!\n",
+ ammo_use,
+ wep.netname,
+ GetAmmoPicture(wep.ammo_field),
+ self.netname,
+ self.(wep.ammo_field)
+ ));
+ }
+ }
}
// weapon reloading code
self.clip_load = self.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading
// if the gun uses no ammo, max out weapon load, else decrease ammo as we increase weapon load
- if(!self.reload_ammo_min || self.items & IT_UNLIMITED_WEAPON_AMMO)
+ if(!self.reload_ammo_min || self.items & IT_UNLIMITED_WEAPON_AMMO || self.ammo_field == ammo_none)
self.clip_load = self.reload_ammo_amount;
else
{
- while(self.clip_load < self.reload_ammo_amount && self.(self.current_ammo)) // make sure we don't add more ammo than we have
- {
- self.clip_load += 1;
- self.(self.current_ammo) -= 1;
- }
+ // make sure we don't add more ammo than we have
+ float load = min(self.reload_ammo_amount - self.clip_load, self.(self.ammo_field));
+ self.clip_load += load;
+ self.(self.ammo_field) -= load;
}
self.(weapon_load[self.weapon]) = self.clip_load;
w_ready();
}
-void W_Reload(float sent_ammo_min, float sent_ammo_amount, float sent_time, string sent_sound)
+void W_Reload(float sent_ammo_min, string sent_sound)
{
// set global values to work with
+ entity e;
+ e = get_weaponinfo(self.weapon);
+
+ if(cvar("g_overkill"))
+ if(self.ok_use_ammocharge)
+ return; // TODO
self.reload_ammo_min = sent_ammo_min;
- self.reload_ammo_amount = sent_ammo_amount;
- self.reload_time = sent_time;
+ self.reload_ammo_amount = e.reloading_ammo;
+ self.reload_time = e.reloading_time;
self.reload_sound = sent_sound;
- // check if we meet the necessary conditions to reload
-
- entity e;
- e = get_weaponinfo(self.weapon);
-
// don't reload weapons that don't have the RELOADABLE flag
- if not(e.spawnflags & WEP_FLAG_RELOADABLE)
+ if (!(e.spawnflags & WEP_FLAG_RELOADABLE))
{
dprint("Warning: Attempted to reload a weapon that does not have the WEP_FLAG_RELOADABLE flag. Fix your code!\n");
return;
return;
// no ammo, so nothing to load
- if(!self.(self.current_ammo) && self.reload_ammo_min)
- if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+ if(self.ammo_field != ammo_none)
+ if(!self.(self.ammo_field) && self.reload_ammo_min)
+ if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
{
if(IS_REAL_CLIENT(self) && self.reload_complain < time)
{
play2(self, "weapons/unavailable.wav");
- sprint(self, strcat("You don't have enough ammo to reload the ^2", W_Name(self.weapon), "\n"));
+ sprint(self, strcat("You don't have enough ammo to reload the ^2", WEP_NAME(self.weapon), "\n"));
self.reload_complain = time + 1;
}
// switch away if the amount of ammo is not enough to keep using this weapon
- if not(WEP_ACTION(self.weapon, WR_CHECKAMMO1) + WEP_ACTION(self.weapon, WR_CHECKAMMO2))
+ if (!(WEP_ACTION(self.weapon, WR_CHECKAMMO1) + WEP_ACTION(self.weapon, WR_CHECKAMMO2)))
{
self.clip_load = -1; // reload later
W_SwitchToOtherWeapon(self);
// now begin the reloading process
- sound (self, CH_WEAPON_SINGLE, self.reload_sound, VOL_BASE, ATTN_NORM);
+ sound(self, CH_WEAPON_SINGLE, self.reload_sound, VOL_BASE, ATTEN_NORM);
// do not set ATTACK_FINISHED in reload code any more. This causes annoying delays if eg: You start reloading a weapon,
// then quickly switch to another weapon and back. Reloading is canceled, but the reload delay is still there,
self.old_clip_load = self.clip_load;
self.clip_load = self.(weapon_load[self.weapon]) = -1;
}
+
+void W_DropEvent(float event, entity player, float weapon_type, entity weapon_item)
+{
+ entity oldself = self;
+ self = player;
+ weapon_dropevent_item = weapon_item;
+ WEP_ACTION(weapon_type, event);
+ self = oldself;
+}