.int team;
.int team_size;
- float vid_conwidth, vid_conheight;
+ float vid_conheight;
int binddb;
// QUALIFYING
float blurtest_time0, blurtest_time1, blurtest_radius, blurtest_power;
#endif
- float servertime, serverprevtime, serverdeltatime;
+ float serverprevtime, serverdeltatime;
float ticrate;
.float damageextraradius;
.void(entity this, float thisdmg, int hittype, vector org, vector thisforce) event_damage;
-// only for Porto
-float angles_held_status;
-vector angles_held;
-
// weapons
.bool silent;
#include <common/mapinfo.qh>
#include <common/minigames/cl_minigames.qh>
#include <common/minigames/cl_minigames_hud.qh>
+ #include <common/net_linked.qh>
#include <common/net_notice.qh>
#include <common/triggers/include.qh>
#include <common/vehicles/all.qh>
spectatorbutton_zoom = (f & 4);
- if(f & 8)
- {
- angles_held_status = 1;
- angles_held.x = ReadAngle();
- angles_held.y = ReadAngle();
- angles_held.z = 0;
- }
- else
- angles_held_status = 0;
-
if(f & 16)
{
num_spectators = ReadByte();
#include <common/ent_cs.qh>
#include <common/anim.qh>
#include <common/constants.qh>
+ #include <common/net_linked.qh>
#include <common/debug.qh>
#include <common/mapinfo.qh>
#include <common/gamemodes/_mod.qh>
#include <common/triggers/target/music.qh>
#include <common/teams.qh>
+ #include <common/weapons/weapon/tuba.qh>
+
#include <common/vehicles/all.qh>
#include <common/weapons/_all.qh>
#include <common/viewloc.qh>
.float weapon_eta_last;
.float weapon_switchdelay;
+.string name_last;
+
void viewmodel_draw(entity this)
{
- if(!activeweapon || !autocvar_r_drawviewmodel)
+ if(!this.activeweapon || !autocvar_r_drawviewmodel)
return;
int mask = (intermission || (STAT(HEALTH) <= 0) || autocvar_chase_active) ? 0 : MASK_NORMAL;
float a = this.alpha;
if (invehicle) a = -1;
else if (wasinvehicle) a = 1;
wasinvehicle = invehicle;
- Weapon wep = activeweapon;
+ Weapon wep = this.activeweapon;
int c = entcs_GetClientColors(current_player);
- vector g = weaponentity_glowmod(wep, NULL, c);
+ vector g = weaponentity_glowmod(wep, NULL, c, this);
entity me = CSQCModel_server2csqc(player_localentnum - 1);
int fx = ((me.csqcmodel_effects & EFMASK_CHEAP)
| EF_NODEPTHTEST)
CSQCModel_Effects_Apply(e);
}
{
- static string name_last;
string name = wep.mdl;
if(wep == WEP_TUBA)
{
(this.tuba_instrument == 1) ? "akordeon" :
"kleinbottle";
}
- bool swap = name != name_last;
+ bool swap = name != this.name_last;
// if (swap)
{
- name_last = name;
+ this.name_last = name;
CL_WeaponEntity_SetModel(this, name, swap);
this.viewmodel_origin = this.origin;
this.viewmodel_angles = this.angles;
setorigin(this, this.origin);
}
-entity viewmodel;
STATIC_INIT(viewmodel) {
- viewmodel = new(viewmodel);
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ viewmodels[slot] = new(viewmodel);
}
void Porto_Draw(entity this);
}
const int polyline_length = 16;
-vector polyline[polyline_length];
+.vector polyline[polyline_length];
void Porto_Draw(entity this)
{
- if (activeweapon != WEP_PORTO) return;
- if (spectatee_status) return;
- if (WEP_CVAR(porto, secondary)) return;
- if (intermission == 1) return;
- if (intermission == 2) return;
- if (STAT(HEALTH) <= 0) return;
-
- vector pos = view_origin;
- vector dir = view_forward;
- if (angles_held_status)
- {
- makevectors(angles_held);
- dir = v_forward;
- }
-
- polyline[0] = pos;
-
- int portal_number = 0, portal1_idx = 1, portal_max = 2;
- int n = 1 + 2; // 2 lines == 3 points
- for (int idx = 0; idx < n && idx < polyline_length - 1; )
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
- traceline(pos, pos + 65536 * dir, true, this);
- dir = reflect(dir, trace_plane_normal);
- pos = trace_endpos;
- polyline[++idx] = pos;
- if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP)
+ entity wepent = viewmodels[slot];
+
+ if (wepent.activeweapon != WEP_PORTO) continue;
+ if (spectatee_status) continue;
+ if (WEP_CVAR(porto, secondary)) continue;
+ if (intermission == 1) continue;
+ if (intermission == 2) continue;
+ if (STAT(HEALTH) <= 0) continue;
+
+ vector pos = view_origin;
+ vector dir = view_forward;
+ if (wepent.angles_held_status)
{
- n += 1;
- continue;
+ makevectors(wepent.angles_held);
+ dir = v_forward;
}
- if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
- {
- n = max(2, idx);
- break;
- }
- // check size
+
+ wepent.polyline[0] = pos;
+
+ int portal_number = 0, portal1_idx = 1, portal_max = 2;
+ int n = 1 + 2; // 2 lines == 3 points
+ for (int idx = 0; idx < n && idx < polyline_length - 1; )
{
- vector ang = vectoangles2(trace_plane_normal, dir);
- ang.x = -ang.x;
- makevectors(ang);
- if (!CheckWireframeBox(this, pos - 48 * v_right - 48 * v_up + 16 * v_forward, 96 * v_right, 96 * v_up, 96 * v_forward))
+ traceline(pos, pos + 65536 * dir, true, this);
+ dir = reflect(dir, trace_plane_normal);
+ pos = trace_endpos;
+ wepent.polyline[++idx] = pos;
+ if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP)
+ {
+ n += 1;
+ continue;
+ }
+ if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
{
n = max(2, idx);
break;
}
+ // check size
+ {
+ vector ang = vectoangles2(trace_plane_normal, dir);
+ ang.x = -ang.x;
+ makevectors(ang);
+ if (!CheckWireframeBox(this, pos - 48 * v_right - 48 * v_up + 16 * v_forward, 96 * v_right, 96 * v_up, 96 * v_forward))
+ {
+ n = max(2, idx);
+ break;
+ }
+ }
+ portal_number += 1;
+ if (portal_number >= portal_max) break;
+ if (portal_number == 1) portal1_idx = idx;
+ }
+ for (int idx = 0; idx < n - 1; ++idx)
+ {
+ vector p = wepent.polyline[idx], q = wepent.polyline[idx + 1];
+ if (idx == 0) p -= view_up * 16; // line from player
+ vector rgb = (idx < portal1_idx) ? '1 0 0' : '0 0 1';
+ Draw_CylindricLine(p, q, 4, "", 1, 0, rgb, 0.5, DRAWFLAG_NORMAL, view_origin);
}
- portal_number += 1;
- if (portal_number >= portal_max) break;
- if (portal_number == 1) portal1_idx = idx;
- }
- for (int idx = 0; idx < n - 1; ++idx)
- {
- vector p = polyline[idx], q = polyline[idx + 1];
- if (idx == 0) p -= view_up * 16; // line from player
- vector rgb = (idx < portal1_idx) ? '1 0 0' : '0 0 1';
- Draw_CylindricLine(p, q, 4, "", 1, 0, rgb, 0.5, DRAWFLAG_NORMAL, view_origin);
}
}
zoomspeed = 3.5;
zoomdir = button_zoom;
+
if(hud == HUD_NORMAL && !spectatee_status)
- if(switchweapon == activeweapon)
- if((activeweapon == WEP_VORTEX && !WEP_CVAR(vortex, secondary)) || (activeweapon == WEP_RIFLE && !WEP_CVAR(rifle, secondary))) // do NOT use switchweapon here
- zoomdir += button_attack2;
+ {
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ entity wepent = viewmodels[slot];
+ if(wepent.switchweapon == wepent.activeweapon)
+ if((wepent.activeweapon == WEP_VORTEX && !WEP_CVAR(vortex, secondary)) || (wepent.activeweapon == WEP_RIFLE && !WEP_CVAR(rifle, secondary))) // do NOT use switchweapon here
+ zoomdir += button_attack2;
+ }
+ }
if(spectatee_status > 0 || isdemo())
{
if(spectatorbutton_zoom)
return SHOTTYPE_HITENEMY;
}
-float TrueAimCheck()
+float TrueAimCheck(entity wepent)
{
float nudge = 1; // added to traceline target and subtracted from result TOOD(divVerent): do we still need this? Doesn't the engine do this now for us?
vector vecs, trueaimpoint, w_shotorg;
ta = trueaim;
mv = MOVE_NOMONSTERS;
- switch(activeweapon) // WEAPONTODO
+ switch(wepent.activeweapon) // WEAPONTODO
{
case WEP_TUBA: // no aim
case WEP_PORTO: // shoots from eye
const float CAMERA_FREE = 1;
const float CAMERA_CHASE = 2;
float reticle_type;
-string reticle_image;
string NextFrameCommand;
vector freeze_org, freeze_ang;
{
// varying sound pitch
+ bool have_arc = false;
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ entity wepent = viewmodels[slot];
+
+ if(wepent.activeweapon == WEP_ARC)
+ have_arc = true;
+ }
+
static float hitsound_time_prev = 0;
// HACK: the only way to get the arc to sound consistent with pitch shift is to ignore cl_hitsound_antispam_time
- float arc_hack = activeweapon == WEP_ARC && autocvar_cl_hitsound >= 2;
+ bool arc_hack = have_arc && autocvar_cl_hitsound >= 2;
if (arc_hack || COMPARE_INCREASING(time, hitsound_time_prev) > autocvar_cl_hitsound_antispam_time)
{
if (autocvar_cl_hitsound && unaccounted_damage)
if(autocvar_crosshair_hittest)
{
vector wcross_oldorigin;
+ entity thiswep = viewmodels[0]; // TODO: unhardcode
wcross_oldorigin = wcross_origin;
- shottype = TrueAimCheck();
+ shottype = TrueAimCheck(thiswep);
if(shottype == SHOTTYPE_HITWORLD)
{
v = wcross_origin - wcross_oldorigin;
entity e = WEP_Null;
if(autocvar_crosshair_per_weapon || (autocvar_crosshair_color_special == 1))
{
- e = switchingweapon;
+ entity wepent = viewmodels[0]; // TODO: unhardcode
+ e = wepent.switchingweapon;
if(e)
{
if(autocvar_crosshair_per_weapon)
weapon_clipload = STAT(WEAPON_CLIPLOAD);
weapon_clipsize = STAT(WEAPON_CLIPSIZE);
- float ok_ammo_charge, ok_ammo_chargepool;
- ok_ammo_charge = STAT(OK_AMMO_CHARGE);
- ok_ammo_chargepool = STAT(OK_AMMO_CHARGEPOOL);
-
float vortex_charge, vortex_chargepool;
vortex_charge = STAT(VORTEX_CHARGE);
vortex_chargepool = STAT(VORTEX_CHARGEPOOL);
if(vortex_charge_movingavg == 0) // this should only happen if we have just loaded up the game
vortex_charge_movingavg = vortex_charge;
+ entity wepent = viewmodels[0]; // TODO: unhardcode
// handle the values
- if (autocvar_crosshair_ring && activeweapon == WEP_VORTEX && vortex_charge && autocvar_crosshair_ring_vortex) // ring around crosshair representing velocity-dependent damage for the vortex
+ if (autocvar_crosshair_ring && wepent.activeweapon == WEP_VORTEX && vortex_charge && autocvar_crosshair_ring_vortex) // ring around crosshair representing velocity-dependent damage for the vortex
{
if (vortex_chargepool || use_vortex_chargepool) {
use_vortex_chargepool = 1;
ring_rgb = wcross_color;
ring_image = "gfx/crosshair_ring_nexgun.tga";
}
- else if (autocvar_crosshair_ring && activeweapon == WEP_MINE_LAYER && WEP_CVAR(minelayer, limit) && autocvar_crosshair_ring_minelayer)
+ else if (autocvar_crosshair_ring && wepent.activeweapon == WEP_MINE_LAYER && WEP_CVAR(minelayer, limit) && autocvar_crosshair_ring_minelayer)
{
ring_value = bound(0, STAT(LAYED_MINES) / WEP_CVAR(minelayer, limit), 1); // if you later need to use the count of bullets in another place, then add a float for it. For now, no need to.
ring_alpha = autocvar_crosshair_ring_minelayer_alpha;
ring_rgb = wcross_color;
ring_image = "gfx/crosshair_ring.tga";
}
- else if (activeweapon == WEP_HAGAR && STAT(HAGAR_LOAD) && autocvar_crosshair_ring_hagar)
+ else if (wepent.activeweapon == WEP_HAGAR && STAT(HAGAR_LOAD) && autocvar_crosshair_ring_hagar)
{
ring_value = bound(0, STAT(HAGAR_LOAD) / WEP_CVAR_SEC(hagar, load_max), 1);
ring_alpha = autocvar_crosshair_ring_hagar_alpha;
ring_rgb = wcross_color;
ring_image = "gfx/crosshair_ring.tga";
}
- else if (ok_ammo_charge)
- {
- ring_value = ok_ammo_chargepool;
- ring_alpha = autocvar_crosshair_ring_reload_alpha;
- ring_rgb = wcross_color;
- ring_image = "gfx/crosshair_ring.tga";
- }
else if(autocvar_crosshair_ring_reload && weapon_clipsize) // forces there to be only an ammo ring
{
ring_value = bound(0, weapon_clipload / weapon_clipsize, 1);
// Note: This is to stop Taoki from complaining that the image doesn't match all potential balances.
// if a new image for another weapon is added, add the code (and its respective file/value) here
- if ((activeweapon == WEP_RIFLE) && (weapon_clipsize == 80))
+ if ((wepent.activeweapon == WEP_RIFLE) && (weapon_clipsize == 80))
ring_image = "gfx/crosshair_ring_rifle.tga";
else
ring_image = "gfx/crosshair_ring.tga";
}
- else if ( autocvar_crosshair_ring && autocvar_crosshair_ring_arc && arc_heat && activeweapon == WEP_ARC )
+ else if ( autocvar_crosshair_ring && autocvar_crosshair_ring_arc && arc_heat && wepent.activeweapon == WEP_ARC )
{
ring_value = arc_heat;
ring_alpha = (1-arc_heat)*autocvar_crosshair_ring_arc_cold_alpha +
// run viewmodel_draw before updating view_angles to the angles calculated by WarpZone_FixView
// viewmodel_draw needs to use the view_angles set by the engine on every CSQC_UpdateView call
- viewmodel_draw(viewmodel);
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ viewmodel_draw(viewmodels[slot]);
// Render the Scene
view_origin = getpropertyvec(VF_ORIGIN);
ColorTranslateMode = autocvar_cl_stripcolorcodes;
- // currently switching-to weapon (for crosshair)
- switchingweapon = Weapons_from(STAT(SWITCHINGWEAPON));
-
- // actually active weapon (for zoom)
- activeweapon = Weapons_from(STAT(ACTIVEWEAPON));
-
- switchweapon = Weapons_from(STAT(SWITCHWEAPON));
-
- if(last_switchweapon != switchweapon)
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
- weapontime = time;
- last_switchweapon = switchweapon;
- if(button_zoom && autocvar_cl_unpress_zoom_on_weapon_switch)
+ entity wepent = viewmodels[slot];
+
+ if(wepent.last_switchweapon != wepent.switchweapon)
{
- localcmd("-zoom\n");
- button_zoom = false;
+ weapontime = time;
+ wepent.last_switchweapon = wepent.switchweapon;
+ if(slot == 0 && button_zoom && autocvar_cl_unpress_zoom_on_weapon_switch)
+ {
+ localcmd("-zoom\n");
+ button_zoom = false;
+ }
+ if(slot == 0 && autocvar_cl_unpress_attack_on_weapon_switch)
+ {
+ localcmd("-fire\n");
+ localcmd("-fire2\n");
+ button_attack2 = false;
+ }
}
- if(autocvar_cl_unpress_attack_on_weapon_switch)
+ if(wepent.last_activeweapon != wepent.activeweapon)
{
- localcmd("-fire\n");
- localcmd("-fire2\n");
- button_attack2 = false;
- }
- }
- if(last_activeweapon != activeweapon)
- {
- last_activeweapon = activeweapon;
+ wepent.last_activeweapon = wepent.activeweapon;
- e = activeweapon;
- if(e.netname != "")
- localcmd(strcat("\ncl_hook_activeweapon ", e.netname), "\n");
- else
- localcmd("\ncl_hook_activeweapon none\n");
+ e = wepent.activeweapon;
+ if(e.netname != "")
+ localcmd(strcat("\ncl_hook_activeweapon ", e.netname), "\n");
+ else if(slot == 0)
+ localcmd("\ncl_hook_activeweapon none\n");
+ }
}
// ALWAYS Clear Current Scene First
if(autocvar_cl_reticle)
{
- Weapon wep = activeweapon;
+ string reticle_image = "";
+ bool wep_zoomed = false;
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ entity wepe = viewmodels[slot];
+ Weapon wep = wepe.activeweapon;
+ if(wep != WEP_Null && wep.wr_zoom)
+ {
+ bool do_zoom = wep.wr_zoom(wep, NULL);
+ if(wep.w_reticle && wep.w_reticle != "")
+ reticle_image = wep.w_reticle;
+ wep_zoomed += do_zoom;
+ }
+ }
// Draw the aiming reticle for weapons that use it
// reticle_type is changed to the item we are zooming / aiming with, to decide which reticle to use
// It must be a persisted float for fading out to work properly (you let go of the zoom button for
// no zoom reticle while dead
reticle_type = 0;
}
- else if(wep.wr_zoomreticle(wep) && autocvar_cl_reticle_weapon)
+ else if(wep_zoomed && autocvar_cl_reticle_weapon)
{
- if(reticle_image != "") { reticle_type = 2; }
+ if(reticle_image && reticle_image != "") { reticle_type = 2; }
else { reticle_type = 0; }
}
else if(button_zoom || zoomscript_caught)
{
entity missile;
- W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(hagar, ammo));
+ W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(hagar, ammo), weaponentity);
W_SetupShot(actor, weaponentity, false, 2, SND_HAGAR_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(hagar, damage));
{
entity missile;
- W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hagar, ammo));
+ W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hagar, ammo), weaponentity);
W_SetupShot(actor, weaponentity, false, 2, SND_HAGAR_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage));
vector s;
vector forward, right, up;
- if(!actor.hagar_load)
+ if(!actor.(weaponentity).hagar_load)
return;
weapon_prepareattack_do(actor, weaponentity, true, WEP_CVAR_SEC(hagar, refire));
right = v_right;
up = v_up;
- shots = actor.hagar_load;
+ shots = actor.(weaponentity).hagar_load;
missile = NULL;
for(counter = 0; counter < shots; ++counter)
{
}
weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(hagar, load_animtime), w_ready);
- actor.hagar_loadstep = time + WEP_CVAR_SEC(hagar, refire) * W_WeaponRateFactor(actor);
- actor.hagar_load = 0;
+ actor.(weaponentity).hagar_loadstep = time + WEP_CVAR_SEC(hagar, refire) * W_WeaponRateFactor(actor);
+ actor.(weaponentity).hagar_load = 0;
+
+ if(weaponslot(weaponentity) == 0)
+ actor.hagar_load = 0;
}
void W_Hagar_Attack2_Load(Weapon thiswep, entity actor, .entity weaponentity)
{
// loadable hagar secondary attack, must always run each frame
- if(time < game_starttime || PS(actor).m_switchweapon != WEP_HAGAR)
+ if(time < game_starttime)
return;
- bool loaded = actor.hagar_load >= WEP_CVAR_SEC(hagar, load_max);
+ bool loaded = actor.(weaponentity).hagar_load >= WEP_CVAR_SEC(hagar, load_max);
// this is different than WR_CHECKAMMO when it comes to reloading
bool enough_ammo;
if(actor.items & IT_UNLIMITED_WEAPON_AMMO)
enough_ammo = true;
else if(autocvar_g_balance_hagar_reload_ammo)
- enough_ammo = actor.(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_SEC(hagar, ammo);
+ enough_ammo = actor.(weaponentity).(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_SEC(hagar, ammo);
else
enough_ammo = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(hagar, ammo);
{
if(PHYS_INPUT_BUTTON_ATCK(actor) && WEP_CVAR_SEC(hagar, load_abort))
{
- if(actor.hagar_load)
+ if(actor.(weaponentity).hagar_load)
{
// if we pressed primary fire while loading, unload all rockets and abort
actor.(weaponentity).state = WS_READY;
- W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hagar, ammo) * actor.hagar_load * -1); // give back ammo
- actor.hagar_load = 0;
+ W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hagar, ammo) * actor.(weaponentity).hagar_load * -1, weaponentity); // give back ammo
+ actor.(weaponentity).hagar_load = 0;
+ if(weaponslot(weaponentity) == 0)
+ actor.hagar_load = 0;
sound(actor, CH_WEAPON_A, SND_HAGAR_BEEP, VOL_BASE, ATTN_NORM);
// pause until we can load rockets again, once we re-press the alt fire button
- actor.hagar_loadstep = time + WEP_CVAR_SEC(hagar, load_speed) * W_WeaponRateFactor(actor);
+ actor.(weaponentity).hagar_loadstep = time + WEP_CVAR_SEC(hagar, load_speed) * W_WeaponRateFactor(actor);
// require letting go of the alt fire button before we can load again
- actor.hagar_loadblock = true;
+ actor.(weaponentity).hagar_loadblock = true;
}
}
else
// check if we can attempt to load another rocket
if(!stopped)
{
- if(!actor.hagar_loadblock && actor.hagar_loadstep < time)
+ if(!actor.(weaponentity).hagar_loadblock && actor.(weaponentity).hagar_loadstep < time)
{
- W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hagar, ammo));
+ W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hagar, ammo), weaponentity);
actor.(weaponentity).state = WS_INUSE;
- actor.hagar_load += 1;
+ actor.(weaponentity).hagar_load += 1;
sound(actor, CH_WEAPON_B, SND_HAGAR_LOAD, VOL_BASE * 0.8, ATTN_NORM); // sound is too loud according to most
- if(actor.hagar_load >= WEP_CVAR_SEC(hagar, load_max))
+ if(actor.(weaponentity).hagar_load >= WEP_CVAR_SEC(hagar, load_max))
stopped = true;
else
- actor.hagar_loadstep = time + WEP_CVAR_SEC(hagar, load_speed) * W_WeaponRateFactor(actor);
+ actor.(weaponentity).hagar_loadstep = time + WEP_CVAR_SEC(hagar, load_speed) * W_WeaponRateFactor(actor);
}
}
- if(stopped && !actor.hagar_loadbeep && actor.hagar_load) // prevents the beep from playing each frame
+ if(stopped && !actor.(weaponentity).hagar_loadbeep && actor.(weaponentity).hagar_load) // prevents the beep from playing each frame
{
// if this is the last rocket we can load, play a beep sound to notify the player
sound(actor, CH_WEAPON_A, SND_HAGAR_BEEP, VOL_BASE, ATTN_NORM);
- actor.hagar_loadbeep = true;
- actor.hagar_loadstep = time + WEP_CVAR_SEC(hagar, load_hold) * W_WeaponRateFactor(actor);
+ actor.(weaponentity).hagar_loadbeep = true;
+ actor.(weaponentity).hagar_loadstep = time + WEP_CVAR_SEC(hagar, load_hold) * W_WeaponRateFactor(actor);
}
}
}
- else if(actor.hagar_loadblock)
+ else if(actor.(weaponentity).hagar_loadblock)
{
// the alt fire button has been released, so re-enable loading if blocked
- actor.hagar_loadblock = false;
+ actor.(weaponentity).hagar_loadblock = false;
}
- if(actor.hagar_load)
+ if(actor.(weaponentity).hagar_load)
{
// play warning sound if we're about to release
- if(stopped && actor.hagar_loadstep - 0.5 < time && WEP_CVAR_SEC(hagar, load_hold) >= 0)
+ if(stopped && actor.(weaponentity).hagar_loadstep - 0.5 < time && WEP_CVAR_SEC(hagar, load_hold) >= 0)
{
- if(!actor.hagar_warning) // prevents the beep from playing each frame
+ if(!actor.(weaponentity).hagar_warning) // prevents the beep from playing each frame
{
// we're about to automatically release after holding time, play a beep sound to notify the player
sound(actor, CH_WEAPON_A, SND_HAGAR_BEEP, VOL_BASE, ATTN_NORM);
- actor.hagar_warning = true;
+ actor.(weaponentity).hagar_warning = true;
}
}
// release if player let go of button or if they've held it in too long
- if(!PHYS_INPUT_BUTTON_ATCK2(actor) || (stopped && actor.hagar_loadstep < time && WEP_CVAR_SEC(hagar, load_hold) >= 0))
+ if(!PHYS_INPUT_BUTTON_ATCK2(actor) || (stopped && actor.(weaponentity).hagar_loadstep < time && WEP_CVAR_SEC(hagar, load_hold) >= 0))
{
actor.(weaponentity).state = WS_READY;
W_Hagar_Attack2_Load_Release(actor, weaponentity);
}
else
{
- actor.hagar_loadbeep = false;
- actor.hagar_warning = false;
+ actor.(weaponentity).hagar_loadbeep = false;
+ actor.(weaponentity).hagar_warning = false;
// we aren't checking ammo during an attack, so we must do it here
- if(!(thiswep.wr_checkammo1(thiswep, actor) + thiswep.wr_checkammo2(thiswep, actor)))
+ if(!(thiswep.wr_checkammo1(thiswep, actor, weaponentity) + thiswep.wr_checkammo2(thiswep, actor, weaponentity)))
if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
// note: this doesn't force the switch
- W_SwitchToOtherWeapon(actor);
+ W_SwitchToOtherWeapon(actor, weaponentity);
return;
}
}
void W_Hagar_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity, int fire)
{
- if(!(fire & 1) || actor.hagar_load || actor.hagar_loadblock || PS(actor).m_switchweapon != WEP_HAGAR)
+ if(!(fire & 1) || actor.(weaponentity).hagar_load || actor.(weaponentity).hagar_loadblock || actor.(weaponentity).m_switchweapon != WEP_HAGAR)
{
w_ready(thiswep, actor, weaponentity, fire);
return;
}
- if(!thiswep.wr_checkammo1(thiswep, actor))
+ if(!thiswep.wr_checkammo1(thiswep, actor, weaponentity))
if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
- W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+ W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
w_ready(thiswep, actor, weaponentity, fire);
return;
}
weapon_thinkf(actor, weaponentity, theframe, WEP_CVAR_PRI(hagar, refire), W_Hagar_Attack_Auto);
}
-METHOD(Hagar, wr_aim, void(entity thiswep, entity actor))
+METHOD(Hagar, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
{
if(random()>0.15)
- PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, WEP_CVAR_PRI(hagar, speed), 0, WEP_CVAR_PRI(hagar, lifetime), false);
+ PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, WEP_CVAR_PRI(hagar, speed), 0, WEP_CVAR_PRI(hagar, lifetime), false);
else // not using secondary_speed since these are only 15% and should cause some ricochets without re-aiming
- PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, WEP_CVAR_PRI(hagar, speed), 0, WEP_CVAR_PRI(hagar, lifetime), false);
+ PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, weaponentity, WEP_CVAR_PRI(hagar, speed), 0, WEP_CVAR_PRI(hagar, lifetime), false);
}
METHOD(Hagar, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
{
float loadable_secondary;
loadable_secondary = (WEP_CVAR_SEC(hagar, load) && WEP_CVAR(hagar, secondary));
+ if(weaponslot(weaponentity) == 0)
+ actor.hagar_load = actor.(weaponentity).hagar_load;
if(loadable_secondary)
W_Hagar_Attack2_Load(thiswep, actor, weaponentity); // must always run each frame
- if(autocvar_g_balance_hagar_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo))) { // forced reload
+ if(autocvar_g_balance_hagar_reload_ammo && actor.(weaponentity).clip_load < min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo))) { // forced reload
thiswep.wr_reload(thiswep, actor, weaponentity);
}
- else if((fire & 1) && !actor.hagar_load && !actor.hagar_loadblock) // not while secondary is loaded or awaiting reset
+ else if((fire & 1) && !actor.(weaponentity).hagar_load && !actor.(weaponentity).hagar_loadblock) // not while secondary is loaded or awaiting reset
{
if(weapon_prepareattack(thiswep, actor, weaponentity, false, 0))
W_Hagar_Attack_Auto(thiswep, actor, weaponentity, fire);
METHOD(Hagar, wr_gonethink, void(entity thiswep, entity actor, .entity weaponentity))
{
// we lost the weapon and want to prepare switching away
- if(actor.hagar_load)
+ if(actor.(weaponentity).hagar_load)
{
actor.(weaponentity).state = WS_READY;
W_Hagar_Attack2_Load_Release(actor, weaponentity);
}
}
-METHOD(Hagar, wr_setup, void(entity thiswep, entity actor))
+METHOD(Hagar, wr_setup, void(entity thiswep, entity actor, .entity weaponentity))
{
- actor.hagar_loadblock = false;
-
- if(actor.hagar_load)
+ actor.hagar_load = 0;
+ actor.(weaponentity).hagar_loadblock = false;
+ if(actor.(weaponentity).hagar_load)
{
- W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hagar, ammo) * actor.hagar_load * -1); // give back ammo if necessary
- actor.hagar_load = 0;
+ W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hagar, ammo) * actor.(weaponentity).hagar_load * -1, weaponentity); // give back ammo if necessary
+ actor.(weaponentity).hagar_load = 0;
}
}
-METHOD(Hagar, wr_checkammo1, bool(entity thiswep, entity actor))
+METHOD(Hagar, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
{
float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_PRI(hagar, ammo);
- ammo_amount += actor.(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_PRI(hagar, ammo);
+ ammo_amount += actor.(weaponentity).(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_PRI(hagar, ammo);
return ammo_amount;
}
-METHOD(Hagar, wr_checkammo2, bool(entity thiswep, entity actor))
+METHOD(Hagar, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
{
float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(hagar, ammo);
- ammo_amount += actor.(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_SEC(hagar, ammo);
+ ammo_amount += actor.(weaponentity).(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_SEC(hagar, ammo);
return ammo_amount;
}
METHOD(Hagar, wr_resetplayer, void(entity thiswep, entity actor))
{
actor.hagar_load = 0;
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ actor.(weaponentity).hagar_load = 0;
+ }
}
METHOD(Hagar, wr_playerdeath, void(entity thiswep, entity actor, .entity weaponentity))
{
// if we have any rockets loaded when we die, release them
- if(actor.hagar_load && WEP_CVAR_SEC(hagar, load_releasedeath))
+ if(actor.(weaponentity).hagar_load && WEP_CVAR_SEC(hagar, load_releasedeath))
W_Hagar_Attack2_Load_Release(actor, weaponentity);
}
METHOD(Hagar, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
{
- if(!actor.hagar_load) // require releasing loaded rockets first
+ if(!actor.(weaponentity).hagar_load) // require releasing loaded rockets first
W_Reload(actor, weaponentity, min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo)), SND_RELOAD);
}
METHOD(Hagar, wr_suicidemessage, Notification(entity thiswep))
.entity tuba_note;
.float tuba_smoketime;
-.float tuba_instrument;
#define MAX_TUBANOTES 32
.float tuba_lastnotes_last;
spawnfunc(weapon_tuba) { weapon_defaultspawnfunc(this, WEP_TUBA); }
-bool W_Tuba_HasPlayed(entity pl, string melody, int instrument, bool ignorepitch, float mintempo, float maxtempo)
+bool W_Tuba_HasPlayed(entity pl, .entity weaponentity, string melody, int instrument, bool ignorepitch, float mintempo, float maxtempo)
{
float i, j, mmin, mmax, nolength;
float n = tokenize_console(melody);
- if(n > pl.tuba_lastnotes_cnt)
+ if(n > pl.(weaponentity).tuba_lastnotes_cnt)
return false;
float pitchshift = 0;
if(instrument >= 0)
- if(pl.tuba_instrument != instrument)
+ if(pl.(weaponentity).tuba_instrument != instrument)
return false;
// verify notes...
nolength = false;
for(i = 0; i < n; ++i)
{
- vector v = pl.(tuba_lastnotes[(pl.tuba_lastnotes_last - i + MAX_TUBANOTES) % MAX_TUBANOTES]);
+ vector v = pl.(weaponentity).(tuba_lastnotes[(pl.(weaponentity).tuba_lastnotes_last - i + MAX_TUBANOTES) % MAX_TUBANOTES]);
float ai = stof(argv(n - i - 1));
float np = floor(ai);
if(ai == np)
for(i = 0; i < n; ++i)
{
- vector vi = pl.(tuba_lastnotes[(pl.tuba_lastnotes_last - i + MAX_TUBANOTES) % MAX_TUBANOTES]);
+ vector vi = pl.(weaponentity).(tuba_lastnotes[(pl.(weaponentity).tuba_lastnotes_last - i + MAX_TUBANOTES) % MAX_TUBANOTES]);
float ai = stof(argv(n - i - 1));
ti -= 1 / (ai - floor(ai));
float tj = ti;
for(j = i+1; j < n; ++j)
{
- vector vj = pl.(tuba_lastnotes[(pl.tuba_lastnotes_last - j + MAX_TUBANOTES) % MAX_TUBANOTES]);
+ vector vj = pl.(weaponentity).(tuba_lastnotes[(pl.(weaponentity).tuba_lastnotes_last - j + MAX_TUBANOTES) % MAX_TUBANOTES]);
float aj = stof(argv(n - j - 1));
tj -= (aj - floor(aj));
return false;
}
- pl.tuba_lastnotes_cnt = 0;
+ pl.(weaponentity).tuba_lastnotes_cnt = 0;
return true;
}
// on: this.spawnshieldtime
// off: time
// note: this.cnt
- if (actor.tuba_note == this)
+ .entity weaponentity = this.weaponentity_fld;
+ if (actor.(weaponentity).tuba_note == this)
{
- actor.tuba_lastnotes_last = (actor.tuba_lastnotes_last + 1) % MAX_TUBANOTES;
- actor.(tuba_lastnotes[actor.tuba_lastnotes_last]) = eX * this.spawnshieldtime + eY * time + eZ * this.cnt;
- actor.tuba_note = NULL;
- actor.tuba_lastnotes_cnt = bound(0, actor.tuba_lastnotes_cnt + 1, MAX_TUBANOTES);
+ actor.(weaponentity).tuba_lastnotes_last = (actor.(weaponentity).tuba_lastnotes_last + 1) % MAX_TUBANOTES;
+ actor.(weaponentity).(tuba_lastnotes[actor.(weaponentity).tuba_lastnotes_last]) = eX * this.spawnshieldtime + eY * time + eZ * this.cnt;
+ actor.(weaponentity).tuba_note = NULL;
+ actor.(weaponentity).tuba_lastnotes_cnt = bound(0, actor.(weaponentity).tuba_lastnotes_cnt + 1, MAX_TUBANOTES);
string s = trigger_magicear_processmessage_forallears(actor, 0, NULL, string_null);
if (s != "")
n = W_Tuba_GetNote(actor, hittype);
hittype = 0;
- if(actor.tuba_instrument & 1)
+ if(actor.(weaponentity).tuba_instrument & 1)
hittype |= HITTYPE_SECONDARY;
- if(actor.tuba_instrument & 2)
+ if(actor.(weaponentity).tuba_instrument & 2)
hittype |= HITTYPE_BOUNCE;
- if(actor.tuba_note)
+ if(actor.(weaponentity).tuba_note)
{
- if(actor.tuba_note.cnt != n || actor.tuba_note.tuba_instrument != actor.tuba_instrument)
+ if(actor.(weaponentity).tuba_note.cnt != n || actor.(weaponentity).tuba_note.tuba_instrument != actor.(weaponentity).tuba_instrument)
{
- W_Tuba_NoteOff(actor.tuba_note);
+ W_Tuba_NoteOff(actor.(weaponentity).tuba_note);
}
}
- if(!actor.tuba_note)
+ if(!actor.(weaponentity).tuba_note)
{
- actor.tuba_note = new(tuba_note);
- actor.tuba_note.owner = actor.tuba_note.realowner = actor;
- actor.tuba_note.cnt = n;
- actor.tuba_note.tuba_instrument = actor.tuba_instrument;
- setthink(actor.tuba_note, W_Tuba_NoteThink);
- actor.tuba_note.nextthink = time;
- actor.tuba_note.spawnshieldtime = time;
- Net_LinkEntity(actor.tuba_note, false, 0, W_Tuba_NoteSendEntity);
+ entity note = new(tuba_note);
+ note.weaponentity_fld = weaponentity;
+ actor.(weaponentity).tuba_note = note;
+ note.owner = note.realowner = actor;
+ note.cnt = n;
+ note.tuba_instrument = actor.(weaponentity).tuba_instrument;
+ setthink(note, W_Tuba_NoteThink);
+ note.nextthink = time;
+ note.spawnshieldtime = time;
+ Net_LinkEntity(note, false, 0, W_Tuba_NoteSendEntity);
}
- actor.tuba_note.teleport_time = time + WEP_CVAR(tuba, refire) * 2 * W_WeaponRateFactor(actor); // so it can get prolonged safely
+ actor.(weaponentity).tuba_note.teleport_time = time + WEP_CVAR(tuba, refire) * 2 * W_WeaponRateFactor(actor); // so it can get prolonged safely
//sound(actor, c, TUBA_NOTE(n), bound(0, VOL_BASE * cvar("g_balance_tuba_volume"), 1), autocvar_g_balance_tuba_attenuation);
RadiusDamage(actor, actor, WEP_CVAR(tuba, damage), WEP_CVAR(tuba, edgedamage), WEP_CVAR(tuba, radius), NULL, NULL, WEP_CVAR(tuba, force), hittype | WEP_TUBA.m_id, NULL);
o = gettaginfo(actor.exteriorweaponentity, 0);
- if(time > actor.tuba_smoketime)
+ if(time > actor.(weaponentity).tuba_smoketime)
{
Send_Effect(EFFECT_SMOKE_RING, o + v_up * 45 + v_right * -6 + v_forward * 8, v_up * 100, 1);
- actor.tuba_smoketime = time + 0.25;
+ actor.(weaponentity).tuba_smoketime = time + 0.25;
}
}
#endif
#ifdef SVQC
-METHOD(Tuba, wr_aim, void(Tuba this, entity actor))
+METHOD(Tuba, wr_aim, void(Tuba this, entity actor, .entity weaponentity))
{
// bots cannot play the Tuba well yet
// I think they should start with the recorder first
W_Tuba_NoteOn(actor, weaponentity, HITTYPE_SECONDARY);
weapon_thinkf(actor, weaponentity, WFRAME_IDLE, WEP_CVAR(tuba, animtime), w_ready);
}
- if (actor.tuba_note)
+ if (actor.(weaponentity).tuba_note)
{
if (!(fire & 1) && !(fire & 2))
{
- W_Tuba_NoteOff(actor.tuba_note);
+ W_Tuba_NoteOff(actor.(weaponentity).tuba_note);
}
}
}
-void tuba_instrument_send(entity this, int instr);
-METHOD(Tuba, wr_setup, void(Tuba this, entity actor))
+METHOD(Tuba, wr_setup, void(Tuba this, entity actor, .entity weaponentity))
{
- actor.ammo_field = ammo_none;
- actor.tuba_instrument = 0;
- tuba_instrument_send(actor, actor.tuba_instrument);
+ actor.(weaponentity).tuba_instrument = 0;
}
-#endif
-REGISTER_NET_S2C(tuba_instrument)
-#ifdef CSQC
-NET_HANDLE(tuba_instrument, bool)
-{
- int i = ReadByte();
- return = true;
- string s = (i == 0) ? "tuba" :
- (i == 1) ? "akordeon" :
- "kleinbottle" ;
- viewmodel.tuba_instrument = i;
- CL_WeaponEntity_SetModel(viewmodel, s, true);
-}
-#endif
-#ifdef SVQC
-void tuba_instrument_send(entity this, int instr)
-{
- msg_entity = this;
- if (!IS_REAL_CLIENT(this))
- return;
- int chan = MSG_ONE;
- WriteHeader(chan, tuba_instrument);
- WriteByte(chan, instr);
-}
-SPECTATE_COPY()
-{
- if (this.tuba_instrument != spectatee.tuba_instrument)
- tuba_instrument_send(this, this.tuba_instrument = spectatee.tuba_instrument);
-}
METHOD(Tuba, wr_reload, void(Tuba this, entity actor, .entity weaponentity))
{
// switch to alternate instruments :)
if (actor.(weaponentity).state == WS_READY)
{
- switch (actor.tuba_instrument)
+ switch (actor.(weaponentity).tuba_instrument)
{
case 0:
- actor.tuba_instrument = 1;
- actor.weaponname = "akordeon";
+ actor.(weaponentity).tuba_instrument = 1;
+ actor.(weaponentity).weaponname = "akordeon";
break;
case 1:
- actor.tuba_instrument = 2;
- actor.weaponname = "kleinbottle";
+ actor.(weaponentity).tuba_instrument = 2;
+ actor.(weaponentity).weaponname = "kleinbottle";
break;
case 2:
- actor.tuba_instrument = 0;
- actor.weaponname = "tuba";
+ actor.(weaponentity).tuba_instrument = 0;
+ actor.(weaponentity).weaponname = "tuba";
break;
}
- tuba_instrument_send(actor, actor.tuba_instrument);
W_SetupShot(actor, weaponentity, false, 0, SND_Null, 0, 0);
Send_Effect(EFFECT_TELEPORT, w_shotorg, '0 0 0', 1);
actor.(weaponentity).state = WS_INUSE;
#ifdef SVQC
// infinite ammo
-METHOD(Tuba, wr_checkammo1, bool(Tuba this, entity actor)) { return true; }
-METHOD(Tuba, wr_checkammo2, bool(Tuba this, entity actor)) { return true; }
+METHOD(Tuba, wr_checkammo1, bool(Tuba this, entity actor, .entity weaponentity)) { return true; }
+METHOD(Tuba, wr_checkammo2, bool(Tuba this, entity actor, .entity weaponentity)) { return true; }
METHOD(Tuba, wr_suicidemessage, Notification(Tuba this))
{
const int TUBA_MAX = 27;
const int TUBA_INSTRUMENTS = 3;
- entityclass(Tuba);
- class(Tuba) .int note;
- class(Tuba) .bool tuba_attenuate;
- class(Tuba) .float tuba_volume;
- class(Tuba) .float tuba_volume_initial;
-
int Tuba_PitchStep;
void tubasound(entity e, bool restart)
#include "../waypoints.qh"
#include <common/constants.qh>
+ #include <common/net_linked.qh>
#include <common/physics/player.qh>
#include <common/state.qh>
#include <common/items/_mod.qh>
+#include <common/wepent.qh>
#include <common/triggers/teleporters.qh>
#include <common/triggers/trigger/jumppads.qh>
return;
havocbot_chooseenemy(this);
- if (this.bot_chooseweapontime < time )
+
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
- this.bot_chooseweapontime = time + autocvar_bot_ai_chooseweaponinterval;
- havocbot_chooseweapon(this);
+ .entity weaponentity = weaponentities[slot];
+ if(this.(weaponentity).m_weapon != WEP_Null || slot == 0)
+ if(this.(weaponentity).bot_chooseweapontime < time)
+ {
+ this.(weaponentity).bot_chooseweapontime = time + autocvar_bot_ai_chooseweaponinterval;
+ havocbot_chooseweapon(this, weaponentity);
+ }
}
havocbot_aim(this);
lag_update(this);
if(this.weapons)
{
- Weapon w = PS(this).m_weapon;
- w.wr_aim(w, this);
if (autocvar_bot_nofire || IS_INDEPENDENT_PLAYER(this))
{
PHYS_INPUT_BUTTON_ATCK(this) = false;
}
else
{
- if(PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_ATCK2(this))
- this.lastfiredweapon = PS(this).m_weapon.m_id;
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ Weapon w = this.(weaponentity).m_weapon;
+ if(w == WEP_Null && slot != 0)
+ continue;
+ w.wr_aim(w, this, weaponentity);
+ if(PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_ATCK2(this)) // TODO: what if we didn't fire this weapon, but the previous?
+ this.(weaponentity).lastfiredweapon = this.(weaponentity).m_weapon.m_id;
+ }
}
}
else
// if the bot is not attacking, consider reloading weapons
if (!(this.aistatus & AI_STATUS_ATTACKING))
{
- // we are currently holding a weapon that's not fully loaded, reload it
- if(skill >= 2) // bots can only reload the held weapon on purpose past this skill
- if(this.clip_load < this.clip_size)
- this.impulse = 20; // "press" the reload button, not sure if this is done right
-
- // if we're not reloading a weapon, switch to any weapon in our invnetory that's not fully loaded to reload it next
- // the code above executes next frame, starting the reloading then
- if(skill >= 5) // bots can only look for unloaded weapons past this skill
- if(this.clip_load >= 0) // only if we're not reloading a weapon already
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
- FOREACH(Weapons, it != WEP_Null, LAMBDA(
- if((this.weapons & (it.m_wepset)) && (it.spawnflags & WEP_FLAG_RELOADABLE) && (this.weapon_load[it.m_id] < it.reloading_ammo))
- PS(this).m_switchweapon = it;
- ));
+ .entity weaponentity = weaponentities[slot];
+
+ if(this.(weaponentity).m_weapon == WEP_Null && slot != 0)
+ continue;
+
+ // we are currently holding a weapon that's not fully loaded, reload it
+ if(skill >= 2) // bots can only reload the held weapon on purpose past this skill
+ if(this.(weaponentity).clip_load < this.(weaponentity).clip_size)
+ this.impulse = 20; // "press" the reload button, not sure if this is done right
+
+ // if we're not reloading a weapon, switch to any weapon in our invnetory that's not fully loaded to reload it next
+ // the code above executes next frame, starting the reloading then
+ if(skill >= 5) // bots can only look for unloaded weapons past this skill
+ if(this.(weaponentity).clip_load >= 0) // only if we're not reloading a weapon already
+ {
+ FOREACH(Weapons, it != WEP_Null, LAMBDA(
+ if((this.weapons & (it.m_wepset)) && (it.spawnflags & WEP_FLAG_RELOADABLE) && (this.(weaponentity).weapon_load[it.m_id] < it.reloading_ammo))
+ this.(weaponentity).m_switchweapon = it;
+ ));
+ }
}
}
}
else if(this.health>WEP_CVAR(devastator, damage)*0.5)
{
if(this.velocity.z < 0)
- if(client_hasweapon(this, WEP_DEVASTATOR, true, false))
{
- this.movement_x = maxspeed;
-
- if(this.rocketjumptime)
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
- if(time > this.rocketjumptime)
+ .entity weaponentity = weaponentities[slot];
+
+ if(this.(weaponentity).m_weapon == WEP_Null && slot != 0)
+ continue;
+
+ if(client_hasweapon(this, WEP_DEVASTATOR, weaponentity, true, false))
{
- PHYS_INPUT_BUTTON_ATCK2(this) = true;
- this.rocketjumptime = 0;
+ this.movement_x = maxspeed;
+
+ if(this.rocketjumptime)
+ {
+ if(time > this.rocketjumptime)
+ {
+ PHYS_INPUT_BUTTON_ATCK2(this) = true;
+ this.rocketjumptime = 0;
+ }
+ return;
+ }
+
+ this.(weaponentity).m_switchweapon = WEP_DEVASTATOR;
+ this.v_angle_x = 90;
+ PHYS_INPUT_BUTTON_ATCK(this) = true;
+ this.rocketjumptime = time + WEP_CVAR(devastator, detonatedelay);
+ return;
}
- return;
}
-
- PS(this).m_switchweapon = WEP_DEVASTATOR;
- this.v_angle_x = 90;
- PHYS_INPUT_BUTTON_ATCK(this) = true;
- this.rocketjumptime = time + WEP_CVAR(devastator, detonatedelay);
- return;
}
}
else
this.havocbot_stickenemy = false;
}
-float havocbot_chooseweapon_checkreload(entity this, int new_weapon)
+float havocbot_chooseweapon_checkreload(entity this, .entity weaponentity, int new_weapon)
{
// bots under this skill cannot find unloaded weapons to reload idly when not in combat,
// so skip this for them, or they'll never get to reload their weapons at all.
return false;
// if this weapon is scheduled for reloading, don't switch to it during combat
- if (this.weapon_load[new_weapon] < 0)
+ if (this.(weaponentity).weapon_load[new_weapon] < 0)
{
bool other_weapon_available = false;
FOREACH(Weapons, it != WEP_Null, LAMBDA(
- if(it.wr_checkammo1(it, this) + it.wr_checkammo2(it, this))
+ if(it.wr_checkammo1(it, this, weaponentity) + it.wr_checkammo2(it, this, weaponentity))
other_weapon_available = true;
));
if(other_weapon_available)
return false;
}
-void havocbot_chooseweapon(entity this)
+void havocbot_chooseweapon(entity this, .entity weaponentity)
{
int i;
// ;)
if(g_weaponarena_weapons == WEPSET(TUBA))
{
- PS(this).m_switchweapon = WEP_TUBA;
+ this.(weaponentity).m_switchweapon = WEP_TUBA;
return;
}
if(this.enemy==NULL)
{
// If no weapon was chosen get the first available weapon
- if(PS(this).m_weapon==WEP_Null)
+ if(this.(weaponentity).m_weapon==WEP_Null)
FOREACH(Weapons, it != WEP_Null, LAMBDA(
- if(client_hasweapon(this, it, true, false))
+ if(client_hasweapon(this, it, weaponentity, true, false))
{
- PS(this).m_switchweapon = it;
+ this.(weaponentity).m_switchweapon = it;
return;
}
));
combo = false;
if(autocvar_bot_ai_weapon_combo)
- if(PS(this).m_weapon.m_id == this.lastfiredweapon)
+ if(this.(weaponentity).m_weapon.m_id == this.(weaponentity).lastfiredweapon)
if(af > combo_time)
{
combo = true;
if ( distance > bot_distance_far ) {
for(i=0; i < Weapons_COUNT && bot_weapons_far[i] != -1 ; ++i){
w = bot_weapons_far[i];
- if ( client_hasweapon(this, Weapons_from(w), true, false) )
+ if ( client_hasweapon(this, Weapons_from(w), weaponentity, true, false) )
{
- if ((PS(this).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, w))
+ if ((this.(weaponentity).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, weaponentity, w))
continue;
- PS(this).m_switchweapon = Weapons_from(w);
+ this.(weaponentity).m_switchweapon = Weapons_from(w);
return;
}
}
if ( distance > bot_distance_close) {
for(i=0; i < Weapons_COUNT && bot_weapons_mid[i] != -1 ; ++i){
w = bot_weapons_mid[i];
- if ( client_hasweapon(this, Weapons_from(w), true, false) )
+ if ( client_hasweapon(this, Weapons_from(w), weaponentity, true, false) )
{
- if ((PS(this).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, w))
+ if ((this.(weaponentity).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, weaponentity, w))
continue;
- PS(this).m_switchweapon = Weapons_from(w);
+ this.(weaponentity).m_switchweapon = Weapons_from(w);
return;
}
}
// Choose weapons for close distance
for(i=0; i < Weapons_COUNT && bot_weapons_close[i] != -1 ; ++i){
w = bot_weapons_close[i];
- if ( client_hasweapon(this, Weapons_from(w), true, false) )
+ if ( client_hasweapon(this, Weapons_from(w), weaponentity, true, false) )
{
- if ((PS(this).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, w))
+ if ((this.(weaponentity).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, weaponentity, w))
continue;
- PS(this).m_switchweapon = Weapons_from(w);
+ this.(weaponentity).m_switchweapon = Weapons_from(w);
return;
}
}
#include "bot/api.qh"
#include "../common/ent_cs.qh"
+#include "../common/wepent.qh"
#include <common/state.qh>
#include <common/effects/qc/globalsound.qh>
#include "weapons/weaponsystem.qh"
#include "../common/net_notice.qh"
+ #include "../common/net_linked.qh"
#include "../common/physics/player.qh"
#include "../common/items/_mod.qh"
if (e.race_completed) sf |= 1; // forced scoreboard
if (to.spectatee_status) sf |= 2; // spectator ent number follows
if (e.zoomstate) sf |= 4; // zoomed
- if (e.porto_v_angle_held) sf |= 8; // angles held
if (autocvar_sv_showspectators) sf |= 16; // show spectators
WriteHeader(MSG_ENTITY, ENT_CLIENT_CLIENTDATA);
{
WriteByte(MSG_ENTITY, to.spectatee_status);
}
- if (sf & 8)
- {
- WriteAngle(MSG_ENTITY, e.v_angle.x);
- WriteAngle(MSG_ENTITY, e.v_angle.y);
- }
if(sf & 16)
{
this.view_ofs = '0 0 0';
}
- RemoveGrapplingHook(this);
+ RemoveGrapplingHooks(this);
Portal_ClearAll(this);
Unfreeze(this);
SetSpectatee(this, NULL);
this.istypefrag = 0;
setthink(this, func_null);
this.nextthink = 0;
- this.hook_time = 0;
this.deadflag = DEAD_NO;
this.crouch = false;
this.revival_time = 0;
this.weapons = '0 0 0';
this.drawonlytoclient = this;
- this.weaponname = "";
this.weaponmodel = "";
for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
+ if(!this.weaponentities[slot])
+ continue; // first load
+ this.weaponentities[slot].hook_time = 0;
+ this.weaponentities[slot].weaponname = "";
this.weaponentities[slot] = NULL;
}
this.exteriorweaponentity = NULL;
this.oldvelocity = this.velocity;
this.fire_endtime = -1;
this.event_damage = func_null;
-
- STAT(ACTIVEWEAPON, this) = WEP_Null.m_id;
- STAT(SWITCHINGWEAPON, this) = WEP_Null.m_id;
- STAT(SWITCHWEAPON, this) = WEP_Null.m_id;
}
int player_getspecies(entity this)
for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
- CL_SpawnWeaponentity(this, weaponentities[slot]);
+ .entity weaponentity = weaponentities[slot];
+ CL_SpawnWeaponentity(this, weaponentity);
}
this.alpha = default_player_alpha;
this.colormod = '1 1 1' * autocvar_g_player_brightness;
it.wr_resetplayer(it, this);
// reload all reloadable weapons
if (it.spawnflags & WEP_FLAG_RELOADABLE) {
- this.weapon_load[it.m_id] = it.reloading_ammo;
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ this.(weaponentity).weapon_load[it.m_id] = it.reloading_ammo;
+ }
}
));
delete(spot); // usefull for checking if there are spawnpoints, that let drop through the floor
}
- PS(this).m_switchweapon = w_getbestweapon(this);
- this.cnt = -1; // W_LastWeapon will not complain
- PS(this).m_weapon = WEP_Null;
- this.weaponname = "";
- PS(this).m_switchingweapon = WEP_Null;
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(slot == 0)
+ this.(weaponentity).m_switchweapon = w_getbestweapon(this, weaponentity);
+ else
+ this.(weaponentity).m_switchweapon = WEP_Null;
+ this.(weaponentity).m_weapon = WEP_Null;
+ this.(weaponentity).weaponname = "";
+ this.(weaponentity).m_switchingweapon = WEP_Null;
+ this.(weaponentity).cnt = -1;
+ }
if (!warmup_stage && !this.alivetime)
this.alivetime = time;
Unfreeze(this);
- RemoveGrapplingHook(this);
+ RemoveGrapplingHooks(this);
// Here, everything has been done that requires this player to be a client.
this.playerid = 0;
ReadyCount();
if (vote_called && IS_REAL_CLIENT(this)) VoteCount(false);
+
+ ONREMOVE(this);
}
void ChatBubbleThink(entity this)
setsize(this, spectatee.mins, spectatee.maxs);
SetZoomState(this, spectatee.zoomstate);
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ this.(weaponentity) = spectatee.(weaponentity);
+ }
+
anticheat_spectatecopy(this, spectatee);
this.hud = spectatee.hud;
if(spectatee.vehicle)
{
this.items &= ~this.items_added;
- //for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
- //{
- //.entity weaponentity = weaponentities[slot];
- //W_WeaponFrame(this, weaponentity);
- //}
- .entity weaponentity = weaponentities[0]; // TODO
- W_WeaponFrame(this, weaponentity);
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ W_WeaponFrame(this, weaponentity);
+
+ if(slot == 0)
+ {
+ this.clip_load = this.(weaponentity).clip_load;
+ this.clip_size = this.(weaponentity).clip_size;
+ }
+ }
this.items_added = 0;
if (this.items & ITEM_Jetpack.m_itemid && (this.items & ITEM_JetpackRegen.m_itemid || this.ammo_fuel >= 0.01))
// WEAPONTODO: Add a weapon request for this
// rot vortex charge to the charge limit
- if (WEP_CVAR(vortex, charge_rot_rate) && this.vortex_charge > WEP_CVAR(vortex, charge_limit) && this.vortex_charge_rottime < time)
- this.vortex_charge = bound(WEP_CVAR(vortex, charge_limit), this.vortex_charge - WEP_CVAR(vortex, charge_rot_rate) * frametime / W_TICSPERFRAME, 1);
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if (WEP_CVAR(vortex, charge_rot_rate) && this.(weaponentity).vortex_charge > WEP_CVAR(vortex, charge_limit) && this.(weaponentity).vortex_charge_rottime < time)
+ this.(weaponentity).vortex_charge = bound(WEP_CVAR(vortex, charge_limit), this.(weaponentity).vortex_charge - WEP_CVAR(vortex, charge_rot_rate) * frametime / W_TICSPERFRAME, 1);
+ }
if (frametime) player_anim(this);
// WEAPONTODO: Add weapon request for this
if (!zoomstate_set) {
- SetZoomState(this,
- PHYS_INPUT_BUTTON_ZOOM(this) || PHYS_INPUT_BUTTON_ZOOMSCRIPT(this)
- || (PHYS_INPUT_BUTTON_ATCK2(this) && PS(this).m_weapon == WEP_VORTEX)
- || (PHYS_INPUT_BUTTON_ATCK2(this) && PS(this).m_weapon == WEP_RIFLE && WEP_CVAR(rifle, secondary) == 0)
- );
+ bool wep_zoomed = false;
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ Weapon thiswep = this.(weaponentity).m_weapon;
+ if(thiswep != WEP_Null && thiswep.wr_zoom)
+ wep_zoomed += thiswep.wr_zoom(thiswep, this);
+ }
+ SetZoomState(this, PHYS_INPUT_BUTTON_ZOOM(this) || PHYS_INPUT_BUTTON_ZOOMSCRIPT(this) || wep_zoomed);
}
if (this.teamkill_soundtime && time > this.teamkill_soundtime)
// WEAPONTODO: Move into weaponsystem somehow
// if a player goes unarmed after holding a loaded weapon, empty his clip size and remove the crosshair ammo ring
- if (PS(this).m_weapon == WEP_Null)
- this.clip_load = this.clip_size = 0;
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(this.(weaponentity).m_weapon == WEP_Null)
+ this.(weaponentity).clip_load = this.(weaponentity).clip_size = 0;
+ }
}
void DrownPlayer(entity this)
#include "../common/vehicles/all.qh"
#include "../common/constants.qh"
#include "../common/util.qh"
+ #include <common/net_linked.qh>
#include <common/weapons/_all.qh>
#include "../lib/warpzone/common.qh"
#include "../lib/warpzone/server.qh"
.float hook_length;
-void RemoveGrapplingHook(entity pl)
+void RemoveGrapplingHooks(entity pl)
{
- if(pl.hook == NULL)
- return;
- delete(pl.hook);
- pl.hook = NULL;
if(pl.move_movetype == MOVETYPE_FLY)
set_movetype(pl, MOVETYPE_WALK);
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(pl.(weaponentity).hook)
+ {
+ delete(pl.(weaponentity).hook);
+ pl.(weaponentity).hook = NULL;
+ }
+ }
+
//pl.disableclientprediction = false;
}
+void RemoveHook(entity this)
+{
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(this.realowner.(weaponentity).hook == this)
+ this.realowner.(weaponentity).hook = NULL;
+ }
+
+ if(this.realowner.move_movetype == MOVETYPE_FLY)
+ set_movetype(this.realowner, MOVETYPE_WALK);
+ delete(this);
+}
+
void GrapplingHookReset(entity this)
{
- if(this.realowner.hook == this)
- RemoveGrapplingHook(this.owner);
- else // in any case:
- delete(this);
+ RemoveHook(this);
}
void GrapplingHookThink(entity this);
if(sf & 1)
{
WriteByte(MSG_ENTITY, etof(this.realowner));
+ WriteByte(MSG_ENTITY, weaponslot(this.weaponentity_fld));
}
if(sf & 2)
{
{
float spd, dist, minlength, pullspeed, ropestretch, ropeairfriction, rubberforce, newlength, rubberforce_overstretch;
vector dir, org, end, v0, dv, v, myorg, vs;
- if(this.realowner.hook != this) // how did that happen?
+ .entity weaponentity = this.weaponentity_fld;
+ if(this.realowner.(weaponentity).hook != this) // how did that happen?
{
error("Owner lost the hook!\n");
return;
}
if(LostMovetypeFollow(this) || intermission_running || (round_handler_IsActive() && !round_handler_IsRoundStarted()) || ((this.aiment.flags & FL_PROJECTILE) && this.aiment.classname != "nade"))
{
- RemoveGrapplingHook(this.realowner);
+ RemoveHook(this);
return;
}
if(this.aiment)
this.nextthink = time;
- int s = W_GetGunAlignment(this.realowner);
+ int s = W_GunAlign(this.realowner.(weaponentity), STAT(GUNALIGN, this.realowner)) - 1;
vs = hook_shotorigin[s];
makevectors(this.realowner.v_angle);
v = v0 = WarpZone_RefSys_TransformVelocity(pull_entity, this, pull_entity.velocity);
// first pull the rope...
- if(this.realowner.hook_state & HOOK_PULLING)
+ if(this.realowner.(weaponentity).hook_state & HOOK_PULLING)
{
newlength = this.hook_length;
newlength = max(newlength - pullspeed * frametime, minlength);
if(pull_entity.move_movetype == MOVETYPE_FLY)
set_movetype(pull_entity, MOVETYPE_WALK);
- if(this.realowner.hook_state & HOOK_RELEASING)
+ if(this.realowner.(weaponentity).hook_state & HOOK_RELEASING)
{
newlength = dist;
this.hook_length = newlength;
if(frozen_pulling && autocvar_g_balance_grapplehook_pull_frozen == 2 && !STAT(FROZEN, this.aiment))
{
- RemoveGrapplingHook(this.realowner);
+ RemoveHook(this);
return;
}
}
this.realowner.pushltime = time + autocvar_g_maxpushtime;
this.realowner.istypefrag = PHYS_INPUT_BUTTON_CHAT(this.realowner);
}
- RemoveGrapplingHook(this.realowner);
+ RemoveHook(this);
}
}
-void FireGrapplingHook(entity actor)
+void FireGrapplingHook(entity actor, .entity weaponentity)
{
- entity missile;
- vector org;
- vector vs;
-
if(forbidWeaponUse(actor)) return;
if(actor.vehicle) return;
makevectors(actor.v_angle);
- int s = W_GetGunAlignment(actor);
- vs = hook_shotorigin[s];
+ int s = W_GunAlign(actor.(weaponentity), STAT(GUNALIGN, actor)) - 1;
+ vector vs = hook_shotorigin[s];
// UGLY WORKAROUND: play this on CH_WEAPON_B so it can't cut off fire sounds
sound (actor, CH_WEAPON_B, SND_HOOK_FIRE, VOL_BASE, ATTEN_NORM);
- org = actor.origin + actor.view_ofs + v_forward * vs.x + v_right * -vs.y + v_up * vs.z;
+ vector org = actor.origin + actor.view_ofs + v_forward * vs.x + v_right * -vs.y + v_up * vs.z;
tracebox(actor.origin + actor.view_ofs, '-3 -3 -3', '3 3 3', org, MOVE_NORMAL, actor);
org = trace_endpos;
Send_Effect(EFFECT_HOOK_MUZZLEFLASH, org, '0 0 0', 1);
- missile = WarpZone_RefSys_SpawnSameRefSys(actor);
+ entity missile = WarpZone_RefSys_SpawnSameRefSys(actor);
missile.owner = missile.realowner = actor;
- actor.hook = missile;
+ actor.(weaponentity).hook = missile;
+ missile.weaponentity_fld = weaponentity;
missile.reset = GrapplingHookReset;
missile.classname = "grapplinghook";
missile.flags = FL_PROJECTILE;
#include "teamplay.qh"
#include "weapons/weaponstats.qh"
#include "../common/constants.qh"
+ #include <common/net_linked.qh>
#include "../common/deathtypes/all.qh"
#include "../common/mapinfo.qh"
#include "../common/monsters/_mod.qh"
{
antilag_record(it, it, altime);
});
- FOREACH_CLIENT(PS(it), {
- PlayerState s = PS(it);
- s.ps_push(s, it);
- });
systems_update();
IL_ENDFRAME();
}
#include "weapons/selection.qh"
#include "../common/command/_mod.qh"
#include "../common/constants.qh"
+ #include <common/net_linked.qh>
#include "../common/deathtypes/all.qh"
#include "../common/mapinfo.qh"
#include "../common/notifications/all.qh"
#include "../common/items/_mod.qh"
#include "../common/state.qh"
#include "../common/effects/qc/globalsound.qh"
+#include "../common/wepent.qh"
#include "../lib/csqcmodel/sv_model.qh"
#include "../lib/warpzone/anglestransform.qh"
#include "../lib/warpzone/server.qh"
replacement = substring(msg, p, 2);
escape = substring(msg, p + 1, 1);
+ .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+
switch(escape)
{
case "%": replacement = "%"; break;
case "l": replacement = NearestLocation(this.origin); break;
case "y": replacement = NearestLocation(cursor); break;
case "d": replacement = NearestLocation(this.death_origin); break;
- case "w": replacement = ((PS(this).m_weapon == WEP_Null) ? ((PS(this).m_switchweapon == WEP_Null) ? Weapons_from(this.cnt) : PS(this).m_switchweapon) : PS(this).m_weapon).m_name; break;
+ case "w": replacement = ((this.(weaponentity).m_weapon == WEP_Null) ? ((this.(weaponentity).m_switchweapon == WEP_Null) ? Weapons_from(this.(weaponentity).cnt) : this.(weaponentity).m_switchweapon) : this.(weaponentity).m_weapon).m_name; break;
case "W": replacement = ammoitems; break;
case "x": replacement = ((cursor_ent.netname == "" || !cursor_ent) ? "nothing" : cursor_ent.netname); break;
case "s": replacement = ftos(vlen(this.velocity - this.velocity_z * '0 0 1')); break;
if (f > 0)
{
if (s == "cl_weaponpriority")
- if (PS(this)) PS(this).m_switchweapon = w_getbestweapon(this);
+ {
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if (this.(weaponentity) && (this.(weaponentity).m_weapon != WEP_Null || slot == 0))
+ this.(weaponentity).m_switchweapon = w_getbestweapon(this, weaponentity);
+ }
+ }
if (s == "cl_allow_uidtracking")
PlayerStats_GameReport_AddPlayer(this);
}
if(this.classname == "nade")
return false; // no checks here
else if(this.classname == "grapplinghook")
- RemoveGrapplingHook(this.realowner);
+ RemoveHook(this);
else if(this.classname == "spike")
{
W_Crylink_Dequeue(this);
#include "weaponsystem.qh"
#include <common/t_items.qh>
#include <common/constants.qh>
+ #include <common/net_linked.qh>
#include <common/util.qh>
#include <common/items/item.qh>
#include <common/weapons/_all.qh>
#include <common/state.qh>
#include <common/mutators/mutator/waypoints/waypointsprites.qh>
+#include <common/wepent.qh>
// switch between weapons
void Send_WeaponComplain(entity e, float wpn, float type)
});
}
-bool client_hasweapon(entity this, Weapon wpn, float andammo, bool complain)
+bool client_hasweapon(entity this, Weapon wpn, .entity weaponentity, float andammo, bool complain)
{
float f = 0;
}
else
{
- f = wpn.wr_checkammo1(wpn, this) + wpn.wr_checkammo2(wpn, this);
+ f = wpn.wr_checkammo1(wpn, this, weaponentity) + wpn.wr_checkammo2(wpn, this, weaponentity);
// always allow selecting the Mine Layer if we placed mines, so that we can detonate them
if(wpn == WEP_MINE_LAYER)
- IL_EACH(g_mines, it.owner == this,
+ IL_EACH(g_mines, it.owner == this && it.weaponentity_fld == weaponentity,
{
f = 1;
break; // no need to continue
return false;
}
-float W_GetCycleWeapon(entity this, string weaponorder, float dir, float imp, float complain, float skipmissing)
+float W_GetCycleWeapon(entity this, string weaponorder, float dir, float imp, float complain, float skipmissing, .entity weaponentity)
{
// We cannot tokenize in this function, as GiveItems calls this
// function. Thus we must use car/cdr.
float weaponcur;
entity wep;
- if(skipmissing || this.selectweapon == 0)
- weaponcur = PS(this).m_switchweapon.m_id;
+ if(skipmissing || this.(weaponentity).selectweapon == 0)
+ weaponcur = this.(weaponentity).m_switchweapon.m_id;
else
- weaponcur = this.selectweapon;
+ weaponcur = this.(weaponentity).selectweapon;
if(dir == 0)
switchtonext = 1;
++c;
- if(!skipmissing || client_hasweapon(this, wep, true, false))
+ if(!skipmissing || client_hasweapon(this, wep, weaponentity, true, false))
{
if(switchtonext)
return weaponwant;
--c;
if(c == 0)
{
- client_hasweapon(this, wep, true, true);
+ client_hasweapon(this, wep, weaponentity, true, true);
break;
}
}
return 0;
}
-void W_SwitchWeapon_Force(Player this, Weapon wep)
+void W_SwitchWeapon_Force(Player this, Weapon wep, .entity weaponentity)
{
- TC(Player, this); TC(Weapon, wep);
- this.cnt = PS(this).m_switchweapon.m_id;
- PS(this).m_switchweapon = wep;
- this.selectweapon = wep.m_id;
+ TC(Weapon, wep);
+ this.(weaponentity).cnt = this.(weaponentity).m_switchweapon.m_id;
+ this.(weaponentity).m_switchweapon = wep;
+ this.(weaponentity).selectweapon = wep.m_id;
}
// perform weapon to attack (weaponstate and attack_finished check is here)
-void W_SwitchToOtherWeapon(entity this)
+void W_SwitchToOtherWeapon(entity this, .entity weaponentity)
{
// hack to ensure it switches to an OTHER weapon (in case the other fire mode still has ammo, we want that anyway)
Weapon ww;
- WepSet set = WepSet_FromWeapon(PS(this).m_weapon);
+ WepSet set = WepSet_FromWeapon(this.(weaponentity).m_weapon);
if (this.weapons & set)
{
this.weapons &= ~set;
- ww = w_getbestweapon(this);
+ ww = w_getbestweapon(this, weaponentity);
this.weapons |= set;
}
else
{
- ww = w_getbestweapon(this);
+ ww = w_getbestweapon(this, weaponentity);
}
if (ww == WEP_Null) return;
- W_SwitchWeapon_Force(this, ww);
+ W_SwitchWeapon_Force(this, ww, weaponentity);
}
-void W_SwitchWeapon(entity this, Weapon w)
+void W_SwitchWeapon(entity this, Weapon w, .entity weaponentity)
{
- if (PS(this).m_switchweapon != w)
+ if(this.(weaponentity).m_switchweapon != w)
{
- if (client_hasweapon(this, w, true, true))
- W_SwitchWeapon_Force(this, w);
+ if(client_hasweapon(this, w, weaponentity, true, true))
+ W_SwitchWeapon_Force(this, w, weaponentity);
else
- this.selectweapon = w.m_id; // update selectweapon ANYWAY
+ this.(weaponentity).selectweapon = w.m_id; // update selectweapon anyway
}
- else if(!forbidWeaponUse(this)) {
+ else if(!forbidWeaponUse(this))
+ {
entity actor = this;
- for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
- {
- .entity weaponentity = weaponentities[slot];
- w.wr_reload(w, actor, weaponentity);
- }
+ w.wr_reload(w, actor, weaponentity);
}
}
-void W_CycleWeapon(entity this, string weaponorder, float dir)
+void W_CycleWeapon(entity this, string weaponorder, float dir, .entity weaponentity)
{
float w;
- w = W_GetCycleWeapon(this, weaponorder, dir, -1, 1, true);
+ w = W_GetCycleWeapon(this, weaponorder, dir, -1, 1, true, weaponentity);
if(w > 0)
- W_SwitchWeapon(this, Weapons_from(w));
+ W_SwitchWeapon(this, Weapons_from(w), weaponentity);
}
-void W_NextWeaponOnImpulse(entity this, float imp)
+void W_NextWeaponOnImpulse(entity this, float imp, .entity weaponentity)
{
float w;
- w = W_GetCycleWeapon(this, this.cvar_cl_weaponpriority, +1, imp, 1, (this.cvar_cl_weaponimpulsemode == 0));
+ w = W_GetCycleWeapon(this, this.cvar_cl_weaponpriority, +1, imp, 1, (this.cvar_cl_weaponimpulsemode == 0), weaponentity);
if(w > 0)
- W_SwitchWeapon(this, Weapons_from(w));
+ W_SwitchWeapon(this, Weapons_from(w), weaponentity);
}
// next weapon
-void W_NextWeapon(entity this, int list)
+void W_NextWeapon(entity this, int list, .entity weaponentity)
{
if(list == 0)
- W_CycleWeapon(this, weaponorder_byid, -1);
+ W_CycleWeapon(this, weaponorder_byid, -1, weaponentity);
else if(list == 1)
- W_CycleWeapon(this, this.weaponorder_byimpulse, -1);
+ W_CycleWeapon(this, this.weaponorder_byimpulse, -1, weaponentity);
else if(list == 2)
- W_CycleWeapon(this, this.cvar_cl_weaponpriority, -1);
+ W_CycleWeapon(this, this.cvar_cl_weaponpriority, -1, weaponentity);
}
// prev weapon
-void W_PreviousWeapon(entity this, float list)
+void W_PreviousWeapon(entity this, float list, .entity weaponentity)
{
if(list == 0)
- W_CycleWeapon(this, weaponorder_byid, +1);
+ W_CycleWeapon(this, weaponorder_byid, +1, weaponentity);
else if(list == 1)
- W_CycleWeapon(this, this.weaponorder_byimpulse, +1);
+ W_CycleWeapon(this, this.weaponorder_byimpulse, +1, weaponentity);
else if(list == 2)
- W_CycleWeapon(this, this.cvar_cl_weaponpriority, +1);
+ W_CycleWeapon(this, this.cvar_cl_weaponpriority, +1, weaponentity);
}
// previously used if exists and has ammo, (second) best otherwise
-void W_LastWeapon(entity this)
+void W_LastWeapon(entity this, .entity weaponentity)
{
- Weapon wep = Weapons_from(this.cnt);
- if (client_hasweapon(this, wep, true, false))
- W_SwitchWeapon(this, wep);
+ Weapon wep = Weapons_from(this.(weaponentity).cnt);
+ if (client_hasweapon(this, wep, weaponentity, true, false))
+ W_SwitchWeapon(this, wep, weaponentity);
else
- W_SwitchToOtherWeapon(this);
+ W_SwitchToOtherWeapon(this, weaponentity);
}
#include "../antilag.qh"
#include <common/constants.qh>
+ #include <common/net_linked.qh>
#include <common/util.qh>
#include <common/weapons/_all.qh>
float oldsolid;
vector vecs, dv;
oldsolid = ent.dphitcontentsmask;
- if (IS_PLAYER(ent) && PS(ent).m_weapon == WEP_RIFLE)
+ if (IS_PLAYER(ent) && ent.(weaponentity).m_weapon == WEP_RIFLE)
ent.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_CORPSE;
else
ent.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
// track max damage
if (IS_PLAYER(ent) && accuracy_canbegooddamage(ent))
- accuracy_add(ent, PS(ent).m_weapon.m_id, maxdamage, 0);
+ accuracy_add(ent, ent.(weaponentity).m_weapon.m_id, maxdamage, 0);
if(IS_PLAYER(ent))
- W_HitPlotAnalysis(ent, v_forward, v_right, v_up);
+ W_HitPlotAnalysis(ent, weaponentity, v_forward, v_right, v_up);
vector md = ent.(weaponentity).movedir;
if(md.x > 0)
// Ballistics Tracing
// ====================
-void FireRailgunBullet (entity this, vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, int deathtype)
+void FireRailgunBullet (entity this, .entity weaponentity, vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, int deathtype)
{
vector hitloc, force, endpoint, dir;
entity ent, endent;
}
// calculate hits and fired shots for hitscan
- accuracy_add(this, PS(this).m_weapon.m_id, 0, min(bdamage, totaldmg));
+ accuracy_add(this, this.(weaponentity).m_weapon.m_id, 0, min(bdamage, totaldmg));
trace_endpos = endpoint;
trace_ent = endent;
fireBullet_last_hit = NULL;
}
-void fireBullet(entity this, vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, int tracereffects)
+void fireBullet(entity this, .entity weaponentity, vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, int tracereffects)
{
vector end;
// do not exceed 100%
float added_damage = min(damage - total_damage, damage * solid_penetration_left);
total_damage += damage * solid_penetration_left;
- accuracy_add(this, PS(this).m_weapon.m_id, 0, added_damage);
+ accuracy_add(this, this.(weaponentity).m_weapon.m_id, 0, added_damage);
}
}
#include <common/t_items.qh>
#include <common/animdecide.qh>
#include <common/constants.qh>
+ #include <common/net_linked.qh>
#include <common/monsters/_mod.qh>
#include <common/notifications/all.qh>
#include <common/util.qh>
#include <common/weapons/_all.qh>
#include <common/state.qh>
#include <lib/csqcmodel/sv_model.qh>
+#include <common/wepent.qh>
.int state;
return ret;
}
-..entity weaponentity_fld;
.float m_alpha;
+.string w_weaponname;
+.int w_dmg;
+.int w_deadflag;
void CL_Weaponentity_Think(entity this)
{
if (this.weaponchild) this.weaponchild.model = "";
return;
}
- if (this.weaponname != this.owner.weaponname
- || this.dmg != this.owner.modelindex
- || this.deadflag != this.owner.deadflag)
+ if (this.w_weaponname != this.weaponname
+ || this.w_dmg != this.modelindex
+ || this.w_deadflag != this.deadflag)
{
// owner changed weapons; update appearance
- this.weaponname = this.owner.weaponname;
- this.dmg = this.owner.modelindex;
- this.deadflag = this.owner.deadflag;
+ this.w_weaponname = this.weaponname;
+ this.w_dmg = this.modelindex;
+ this.w_deadflag = this.deadflag;
- CL_WeaponEntity_SetModel(this, this.owner.weaponname, true);
+ CL_WeaponEntity_SetModel(this, this.weaponname, true);
}
this.alpha = -1; // TODO: don't render this entity at all
void CL_ExteriorWeaponentity_Think(entity this)
{
this.nextthink = time;
+ .entity weaponentity = this.weaponentity_fld;
+ entity w_ent = this.owner.(weaponentity);
if (this.owner.exteriorweaponentity != this)
{
delete(this);
this.model = "";
return;
}
- if (this.weaponname != this.owner.weaponname || this.dmg != this.owner.modelindex
- || this.deadflag != this.owner.deadflag)
+ if (this.weaponname != w_ent.weaponname || this.dmg != w_ent.modelindex
+ || this.deadflag != w_ent.deadflag)
{
- this.weaponname = this.owner.weaponname;
- this.dmg = this.owner.modelindex;
- this.deadflag = this.owner.deadflag;
- if (this.owner.weaponname != "")
+ this.weaponname = w_ent.weaponname;
+ this.dmg = w_ent.modelindex;
+ this.deadflag = w_ent.deadflag;
+ if (w_ent.weaponname != "")
{
- _setmodel(this, W_Model(strcat("v_", this.owner.weaponname, ".md3")));
+ _setmodel(this, W_Model(strcat("v_", w_ent.weaponname, ".md3")));
setsize(this, '0 0 0', '0 0 0');
}
else this.model = "";
else if (this.owner.alpha != 0) this.alpha = this.owner.alpha;
else this.alpha = 1;
- Weapon wep = PS(this.owner).m_weapon;
- if (wep) this.glowmod = weaponentity_glowmod(wep, this.owner, this.owner.clientcolors);
+ Weapon wep = this.owner.(weaponentity).m_weapon;
+ if (wep) this.glowmod = weaponentity_glowmod(wep, this.owner, this.owner.clientcolors, this.owner.(weaponentity));
this.colormap = this.owner.colormap;
CSQCMODEL_AUTOUPDATE(this);
view.viewmodelforclient = actor;
setcefc(view, CL_Weaponentity_CustomizeEntityForClient);
- if (weaponentity == weaponentities[0])
+ wepent_link(view);
+
+ if (weaponentity == weaponentities[0]) // only one exterior model, thank you very much
{
entity exterior = actor.exteriorweaponentity = new(exteriorweaponentity);
exterior.solid = SOLID_NOT;
exterior.owner = actor;
+ exterior.weaponentity_fld = weaponentity;
setorigin(exterior, '0 0 0');
setthink(exterior, CL_ExteriorWeaponentity_Think);
exterior.nextthink = time;
// Weapon subs
void w_clear(Weapon thiswep, entity actor, .entity weaponentity, int fire)
{
- PS(actor).m_weapon = WEP_Null;
- PS(actor).m_switchingweapon = WEP_Null;
+ actor.(weaponentity).m_weapon = WEP_Null;
+ actor.(weaponentity).m_switchingweapon = WEP_Null;
entity this = actor.(weaponentity);
if (this)
{
.float prevdryfire;
.float prevwarntime;
-bool weapon_prepareattack_checkammo(Weapon thiswep, entity actor, bool secondary)
+bool weapon_prepareattack_checkammo(Weapon thiswep, entity actor, bool secondary, .entity weaponentity)
{
if ((actor.items & IT_UNLIMITED_WEAPON_AMMO)) return true;
bool ammo = false;
- if (secondary) ammo = thiswep.wr_checkammo2(thiswep, actor);
- else ammo = thiswep.wr_checkammo1(thiswep, actor);
+ if (secondary) ammo = thiswep.wr_checkammo2(thiswep, actor, weaponentity);
+ else ammo = thiswep.wr_checkammo1(thiswep, actor, weaponentity);
if (ammo) return true;
// always keep the Mine Layer if we placed mines, so that we can detonate them
if (thiswep == WEP_MINE_LAYER)
{
- IL_EACH(g_mines, it.owner == actor,
+ IL_EACH(g_mines, it.owner == actor && it.weaponentity_fld == weaponentity,
{
return false;
});
if (thiswep == WEP_SHOTGUN)
if (!secondary && WEP_CVAR(shotgun, secondary) == 1) return false; // no clicking, just allow
- if (thiswep == PS(actor).m_switchweapon && time - actor.prevdryfire > 1) // only play once BEFORE starting to switch weapons
+ if (thiswep == actor.(weaponentity).m_switchweapon && time - actor.prevdryfire > 1) // only play once BEFORE starting to switch weapons
{
sound(actor, CH_WEAPON_A, SND_DRYFIRE, VOL_BASE, ATTEN_NORM);
actor.prevdryfire = time;
// check if the other firing mode has enough ammo
bool ammo_other = false;
- if (secondary) ammo_other = thiswep.wr_checkammo1(thiswep, actor);
- else ammo_other = thiswep.wr_checkammo2(thiswep, actor);
+ if (secondary) ammo_other = thiswep.wr_checkammo1(thiswep, actor, weaponentity);
+ else ammo_other = thiswep.wr_checkammo2(thiswep, actor, weaponentity);
if (ammo_other)
{
if (time - actor.prevwarntime > 1)
}
else // this weapon is totally unable to fire, switch to another one
{
- W_SwitchToOtherWeapon(actor);
+ W_SwitchToOtherWeapon(actor, weaponentity);
}
return false;
bool weapon_prepareattack_check(Weapon thiswep, entity actor, .entity weaponentity, bool secondary, float attacktime)
{
if (actor.weaponentity == NULL) return true;
- if (!weapon_prepareattack_checkammo(thiswep, actor, secondary)) return false;
+ if (!weapon_prepareattack_checkammo(thiswep, actor, secondary, weaponentity)) 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
return false;
// do not even think about shooting if switching
- if (PS(actor).m_switchweapon != PS(actor).m_weapon) return false;
+ if (actor.(weaponentity).m_switchweapon != actor.(weaponentity).m_weapon) return false;
if (attacktime >= 0)
{
int slot = weaponslot(weaponentity);
// don't fire if previous attack is not finished
- if (ATTACK_FINISHED(actor, slot) > time + actor.weapon_frametime * 0.5) return false;
+ if (ATTACK_FINISHED(actor, slot) > time + actor.(weaponentity).weapon_frametime * 0.5) return false;
entity this = actor.(weaponentity);
// don't fire while changing weapon
if (this.state != WS_READY) return false;
if (attacktime >= 0)
{
int slot = weaponslot(weaponentity);
- if (ATTACK_FINISHED(actor, slot) < time - actor.weapon_frametime * 1.5)
+ if (ATTACK_FINISHED(actor, slot) < time - this.weapon_frametime * 1.5)
{
ATTACK_FINISHED(actor, slot) = time;
// dprint("resetting attack finished to ", ftos(time), "\n");
}
ATTACK_FINISHED(actor, slot) = ATTACK_FINISHED(actor, slot) + attacktime * W_WeaponRateFactor(actor);
}
- actor.bulletcounter += 1;
+ this.bulletcounter += 1;
// dprint("attack finished ", ftos(ATTACK_FINISHED(actor, slot)), "\n");
}
this.weapon_nextthink = time;
// dprint("started firing at ", ftos(time), "\n");
}
- if (this.weapon_nextthink < time - actor.weapon_frametime * 1.5
- || this.weapon_nextthink > time + actor.weapon_frametime * 1.5)
+ if (this.weapon_nextthink < time - this.weapon_frametime * 1.5
+ || this.weapon_nextthink > time + this.weapon_frametime * 1.5)
{
this.weapon_nextthink = time;
// dprint("reset weapon animation timer at ", ftos(time), "\n");
}
this.weapon_nextthink += t;
- if (weaponentity == weaponentities[0]) STAT(WEAPON_NEXTTHINK, actor) = this.weapon_nextthink;
this.weapon_think = func;
// dprint("next ", ftos(this.weapon_nextthink), "\n");
if ((fr == WFRAME_FIRE1 || fr == WFRAME_FIRE2) && t)
{
- bool primary_melee = boolean(fr == WFRAME_FIRE1 && (PS(actor).m_weapon.spawnflags & WEP_TYPE_MELEE_PRI));
- bool secondary_melee = boolean(fr == WFRAME_FIRE2 && (PS(actor).m_weapon.spawnflags & WEP_TYPE_MELEE_SEC));
+ bool primary_melee = boolean(fr == WFRAME_FIRE1 && (this.m_weapon.spawnflags & WEP_TYPE_MELEE_PRI));
+ bool secondary_melee = boolean(fr == WFRAME_FIRE2 && (this.m_weapon.spawnflags & WEP_TYPE_MELEE_SEC));
int act = (primary_melee || secondary_melee)
? ANIMACTION_MELEE
: ANIMACTION_SHOOT
TC(Player, actor);
TC(PlayerState, PS(actor));
entity this = actor.(weaponentity);
- if (frametime) actor.weapon_frametime = frametime;
+ if (frametime) this.weapon_frametime = frametime;
if (!this || actor.health < 1) return; // Dead player can't use weapons and injure impulse commands
if (forbidWeaponUse(actor))
{
- if (actor.(weaponentity).state != WS_CLEAR)
+ if (this.state != WS_CLEAR)
{
- Weapon wpn = PS(actor).m_weapon;
+ Weapon wpn = this.m_weapon;
w_ready(wpn, actor, weaponentity, PHYS_INPUT_BUTTON_ATCK(actor) | (PHYS_INPUT_BUTTON_ATCK2(actor) << 1));
return;
}
}
- if (PS(actor).m_switchweapon == WEP_Null)
+ if (this.m_switchweapon == WEP_Null)
{
- PS(actor).m_weapon = WEP_Null;
- PS(actor).m_switchingweapon = WEP_Null;
+ this.m_weapon = WEP_Null;
+ this.m_switchingweapon = WEP_Null;
this.state = WS_CLEAR;
- actor.weaponname = "";
+ this.weaponname = "";
// actor.items &= ~IT_AMMO;
return;
}
vector up = v_up;
// Change weapon
- if (PS(actor).m_weapon != PS(actor).m_switchweapon)
+ if (this.m_weapon != this.m_switchweapon)
{
switch (this.state)
{
case WS_CLEAR:
{
// end switching!
- Weapon newwep = PS(actor).m_switchweapon;
- PS(actor).m_switchingweapon = newwep;
+ Weapon newwep = this.m_switchweapon;
+ this.m_switchingweapon = newwep;
// the two weapon entities will notice this has changed and update their models
- PS(actor).m_weapon = newwep;
- actor.weaponname = newwep.mdl;
- actor.bulletcounter = 0;
- actor.ammo_field = newwep.ammo_field;
- newwep.wr_setup(newwep, actor);
+ this.m_weapon = newwep;
+ this.weaponname = newwep.mdl;
+ this.bulletcounter = 0;
+ newwep.wr_setup(newwep, actor, weaponentity);
this.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) && newwep.reloading_ammo) // prevent accessing undefined cvars
{
- actor.clip_load = actor.(weapon_load[PS(actor).m_switchweapon.m_id]);
- actor.clip_size = newwep.reloading_ammo;
+ this.clip_load = this.(weapon_load[this.m_switchweapon.m_id]);
+ this.clip_size = newwep.reloading_ammo;
}
else
{
- actor.clip_load = actor.clip_size = 0;
+ this.clip_load = this.clip_size = 0;
}
weapon_thinkf(actor, weaponentity, WFRAME_IDLE, newwep.switchdelay_raise, w_ready);
case WS_DROP:
{
// in dropping phase we can switch at any time
- PS(actor).m_switchingweapon = PS(actor).m_switchweapon;
+ this.m_switchingweapon = this.m_switchweapon;
break;
}
case WS_READY:
{
// start switching!
- PS(actor).m_switchingweapon = PS(actor).m_switchweapon;
- entity oldwep = PS(actor).m_weapon;
+ this.m_switchingweapon = this.m_switchweapon;
+ entity oldwep = this.m_weapon;
// set up weapon switch think in the future, and start drop anim
- if (INDEPENDENT_ATTACK_FINISHED || ATTACK_FINISHED(actor, weaponslot(weaponentity)) <= time + actor.weapon_frametime * 0.5)
+ if (INDEPENDENT_ATTACK_FINISHED || ATTACK_FINISHED(actor, weaponslot(weaponentity)) <= time + this.weapon_frametime * 0.5)
{
sound(actor, CH_WEAPON_SINGLE, SND_WEAPON_SWITCH, VOL_BASE, ATTN_NORM);
this.state = WS_DROP;
// if (actor.button0)
// print(ftos(frametime), " ", ftos(time), " >= ", ftos(ATTACK_FINISHED(actor, slot)), " >= ", ftos(this.weapon_nextthink), "\n");
- Weapon w = PS(actor).m_weapon;
+ Weapon w = this.m_weapon;
// call the think code which may fire the weapon
// and do so multiple times to resolve framerate dependency issues if the
{
if (w != WEP_Null && !(actor.weapons & WepSet_FromWeapon(w)))
{
- if (PS(actor).m_weapon == PS(actor).m_switchweapon) W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+ if (this.m_weapon == this.m_switchweapon) W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
w = WEP_Null;
}
}
else
{
- if (key_pressed && PS(actor).m_switchweapon != WEP_HOOK && !actor.hook_switchweapon)
- W_SwitchWeapon(actor, WEP_HOOK);
+ if (key_pressed && this.m_switchweapon != WEP_HOOK && !actor.hook_switchweapon)
+ W_SwitchWeapon(actor, WEP_HOOK, weaponentity);
actor.hook_switchweapon = key_pressed;
Weapon h = WEP_HOOK;
- block_weapon = (PS(actor).m_weapon == h && (PHYS_INPUT_BUTTON_ATCK(actor) || key_pressed));
+ block_weapon = (this.m_weapon == h && (PHYS_INPUT_BUTTON_ATCK(actor) || key_pressed));
h.wr_think(h, actor, weaponentity, block_weapon ? 1 : 0);
}
}
if (!block_weapon)
{
- Weapon e = PS(actor).m_weapon;
+ Weapon e = this.m_weapon;
TC(Weapon, e);
if (w != WEP_Null)
{
}
}
- if (time + actor.weapon_frametime * 0.5 >= this.weapon_nextthink)
+ if (time + this.weapon_frametime * 0.5 >= this.weapon_nextthink)
{
if (this.weapon_think)
{
v_forward = fo;
v_right = ri;
v_up = up;
- Weapon wpn = PS(actor).m_weapon;
+ Weapon wpn = this.m_weapon;
this.weapon_think(wpn, actor, weaponentity,
PHYS_INPUT_BUTTON_ATCK(actor) | (PHYS_INPUT_BUTTON_ATCK2(actor) << 1));
}
}
}
-void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use)
+void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use, .entity weaponentity)
{
- if (MUTATOR_CALLHOOK(W_DecreaseAmmo, actor)) return;
+ if (MUTATOR_CALLHOOK(W_DecreaseAmmo, actor, actor.(weaponentity))) return;
if ((actor.items & IT_UNLIMITED_WEAPON_AMMO) && !wep.reloading_ammo) return;
// if this weapon is reloadable, decrease its load. Else decrease the player's ammo
if (wep.reloading_ammo)
{
- actor.clip_load -= ammo_use;
- actor.(weapon_load[PS(actor).m_weapon.m_id]) = actor.clip_load;
+ actor.(weaponentity).clip_load -= ammo_use;
+ actor.(weaponentity).(weapon_load[actor.(weaponentity).m_weapon.m_id]) = actor.(weaponentity).clip_load;
}
else if (wep.ammo_field != ammo_none)
{
{
// finish the reloading process, and do the ammo transfer
- actor.clip_load = actor.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading
+ Weapon wpn = actor.(weaponentity).m_weapon;
+
+ actor.(weaponentity).clip_load = actor.(weaponentity).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 (!actor.reload_ammo_min || actor.items & IT_UNLIMITED_WEAPON_AMMO || actor.ammo_field == ammo_none)
+ if (!actor.(weaponentity).reload_ammo_min || (actor.items & IT_UNLIMITED_WEAPON_AMMO) || wpn.ammo_field == ammo_none)
{
- actor.clip_load = actor.reload_ammo_amount;
+ actor.(weaponentity).clip_load = actor.(weaponentity).reload_ammo_amount;
}
else
{
// make sure we don't add more ammo than we have
- float load = min(actor.reload_ammo_amount - actor.clip_load, actor.(actor.ammo_field));
- actor.clip_load += load;
- actor.(actor.ammo_field) -= load;
+ float load = min(actor.(weaponentity).reload_ammo_amount - actor.(weaponentity).clip_load, actor.(wpn.ammo_field));
+ actor.(weaponentity).clip_load += load;
+ actor.(wpn.ammo_field) -= load;
}
- actor.(weapon_load[PS(actor).m_weapon.m_id]) = actor.clip_load;
+ actor.(weaponentity).(weapon_load[actor.(weaponentity).m_weapon.m_id]) = actor.(weaponentity).clip_load;
// 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,
// so your weapon is disabled for a few seconds without reason
- // ATTACK_FINISHED(actor, slot) -= actor.reload_time - 1;
+ // ATTACK_FINISHED(actor, slot) -= actor.(weaponentity).reload_time - 1;
- Weapon wpn = Weapons_from(PS(actor).m_weapon.m_id);
w_ready(wpn, actor, weaponentity, PHYS_INPUT_BUTTON_ATCK(actor) | (PHYS_INPUT_BUTTON_ATCK2(actor) << 1));
}
{
TC(Sound, sent_sound);
// set global values to work with
- Weapon e = PS(actor).m_weapon;
+ Weapon e = actor.(weaponentity).m_weapon;
if (MUTATOR_CALLHOOK(W_Reload, actor)) return;
- actor.reload_ammo_min = sent_ammo_min;
- actor.reload_ammo_amount = e.reloading_ammo;
- actor.reload_time = e.reloading_time;
+ actor.(weaponentity).reload_ammo_min = sent_ammo_min;
+ actor.(weaponentity).reload_ammo_amount = e.reloading_ammo;
+ actor.(weaponentity).reload_time = e.reloading_time;
if (actor.reload_sound) strunzone(actor.reload_sound);
actor.reload_sound = strzone(Sound_fixpath(sent_sound));
}
// return if reloading is disabled for this weapon
- if (!actor.reload_ammo_amount) return;
+ if (!actor.(weaponentity).reload_ammo_amount) return;
// our weapon is fully loaded, no need to reload
- if (actor.clip_load >= actor.reload_ammo_amount) return;
+ if (actor.(weaponentity).clip_load >= actor.(weaponentity).reload_ammo_amount) return;
// no ammo, so nothing to load
- if (actor.ammo_field != ammo_none)
+ if (e.ammo_field != ammo_none)
{
- if (!actor.(actor.ammo_field) && actor.reload_ammo_min)
+ if (!actor.(e.ammo_field) && actor.(weaponentity).reload_ammo_min)
{
if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
if (IS_REAL_CLIENT(actor) && actor.reload_complain < time)
{
play2(actor, SND(UNAVAILABLE));
- sprint(actor, strcat("You don't have enough ammo to reload the ^2", PS(actor).m_weapon.m_name, "\n"));
+ sprint(actor, strcat("You don't have enough ammo to reload the ^2", actor.(weaponentity).m_weapon.m_name, "\n"));
actor.reload_complain = time + 1;
}
// switch away if the amount of ammo is not enough to keep using this weapon
- Weapon w = PS(actor).m_weapon;
- if (!(w.wr_checkammo1(w, actor) + w.wr_checkammo2(w, actor)))
+ if (!(e.wr_checkammo1(e, actor, weaponentity) + e.wr_checkammo2(e, actor, weaponentity)))
{
- actor.clip_load = -1; // reload later
- W_SwitchToOtherWeapon(actor);
+ actor.(weaponentity).clip_load = -1; // reload later
+ W_SwitchToOtherWeapon(actor, weaponentity);
}
return;
}
// then quickly switch to another weapon and back. Reloading is canceled, but the reload delay is still there,
// so your weapon is disabled for a few seconds without reason
- // ATTACK_FINISHED(actor, slot) = max(time, ATTACK_FINISHED(actor, slot)) + actor.reload_time + 1;
+ // ATTACK_FINISHED(actor, slot) = max(time, ATTACK_FINISHED(actor, slot)) + actor.(weaponentity).reload_time + 1;
- weapon_thinkf(actor, weaponentity, WFRAME_RELOAD, actor.reload_time, W_ReloadedAndReady);
+ weapon_thinkf(actor, weaponentity, WFRAME_RELOAD, this.reload_time, W_ReloadedAndReady);
- if (actor.clip_load < 0) actor.clip_load = 0;
- actor.old_clip_load = actor.clip_load;
- actor.clip_load = actor.(weapon_load[PS(actor).m_weapon.m_id]) = -1;
+ if (this.clip_load < 0) this.clip_load = 0;
+ this.old_clip_load = this.clip_load;
+ this.clip_load = this.(weapon_load[this.m_weapon.m_id]) = -1;
}
-void W_DropEvent(.void(Weapon, entity actor) event, entity player, float weapon_type, entity weapon_item)
+void W_DropEvent(.void(Weapon, entity actor, .entity) event, entity player, float weapon_type, entity weapon_item, .entity weaponentity)
{
Weapon w = Weapons_from(weapon_type);
weapon_dropevent_item = weapon_item;
- w.event(w, player);
+ w.event(w, player, weaponentity);
}