From: Mario Date: Sat, 5 Nov 2016 02:43:35 +0000 (+1000) Subject: Merge branch 'master' into Mario/wepent_experimental X-Git-Tag: xonotic-v0.8.2~326^2~35 X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=commitdiff_plain;h=cd4892b9fcd32bd4887f0b3bc2503894520945c7;hp=-c Merge branch 'master' into Mario/wepent_experimental # Conflicts: # qcsrc/client/view.qc # qcsrc/common/weapons/weapon/tuba.qc --- cd4892b9fcd32bd4887f0b3bc2503894520945c7 diff --combined qcsrc/client/defs.qh index 7068340d6e,437e1dd75b..b89ecf55ac --- a/qcsrc/client/defs.qh +++ b/qcsrc/client/defs.qh @@@ -27,7 -27,7 +27,7 @@@ float dmg_take .int team; .int team_size; - float vid_conwidth, vid_conheight; + float vid_conheight; int binddb; // QUALIFYING @@@ -88,7 -88,7 +88,7 @@@ vector lightning_shotorigin[4] float blurtest_time0, blurtest_time1, blurtest_radius, blurtest_power; #endif - float servertime, serverprevtime, serverdeltatime; + float serverprevtime, serverdeltatime; float ticrate; @@@ -98,6 -98,10 +98,6 @@@ const float MAX_DAMAGEEXTRARADIUS = 16 .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; diff --combined qcsrc/client/main.qc index 701d40a0aa,36ca217240..f48c0c530a --- a/qcsrc/client/main.qc +++ b/qcsrc/client/main.qc @@@ -15,6 -15,7 +15,7 @@@ #include #include #include + #include #include #include #include @@@ -493,6 -494,16 +494,6 @@@ NET_HANDLE(ENT_CLIENT_CLIENTDATA, bool 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(); diff --combined qcsrc/client/view.qc index d4e4d60932,12f4c6a1d0..9c19493dce --- a/qcsrc/client/view.qc +++ b/qcsrc/client/view.qc @@@ -13,6 -13,7 +13,7 @@@ #include #include #include + #include #include #include #include @@@ -21,6 -22,8 +22,8 @@@ #include #include + #include + #include #include #include @@@ -281,11 -284,9 +284,11 @@@ void viewmodel_animate(entity this .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; @@@ -294,9 -295,9 +297,9 @@@ 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) @@@ -311,6 -312,7 +314,6 @@@ CSQCModel_Effects_Apply(e); } { - static string name_last; string name = wep.mdl; if(wep == WEP_TUBA) { @@@ -318,10 -320,10 +321,10 @@@ (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; @@@ -360,9 -362,9 +363,9 @@@ 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); @@@ -375,70 -377,65 +378,70 @@@ STATIC_INIT(Porto } 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); } } @@@ -460,17 -457,10 +463,17 @@@ vector GetCurrentFov(float fov 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) @@@ -637,7 -627,7 +640,7 @@@ float EnemyHitCheck( 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; @@@ -650,7 -640,7 +653,7 @@@ ta = trueaim; mv = MOVE_NOMONSTERS; - switch(activeweapon) // WEAPONTODO + switch(wepent.activeweapon) // WEAPONTODO { case WEP_TUBA: // no aim case WEP_PORTO: // shoots from eye @@@ -733,6 -723,7 +736,6 @@@ float camera_mode const float CAMERA_FREE = 1; const float CAMERA_CHASE = 2; float reticle_type; -string reticle_image; string NextFrameCommand; vector freeze_org, freeze_ang; @@@ -824,18 -815,9 +827,18 @@@ void HitSound( { // 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) @@@ -999,9 -981,8 +1002,9 @@@ void HUD_Crosshair(entity this 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; @@@ -1023,8 -1004,7 +1026,8 @@@ 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) @@@ -1169,6 -1149,10 +1172,6 @@@ 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); @@@ -1178,10 -1162,9 +1181,10 @@@ 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; @@@ -1201,20 -1184,27 +1204,20 @@@ 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); @@@ -1224,12 -1214,12 +1227,12 @@@ // 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 + @@@ -1718,8 -1708,7 +1721,8 @@@ void CSQC_UpdateView(entity this, floa // 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); @@@ -1797,36 -1786,39 +1800,36 @@@ 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 @@@ -1954,20 -1946,7 +1957,20 @@@ 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 @@@ -1977,9 -1956,9 +1980,9 @@@ // 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) diff --combined qcsrc/common/weapons/weapon/hagar.qc index aa564565bb,684ee75d37..eff656a6e1 --- a/qcsrc/common/weapons/weapon/hagar.qc +++ b/qcsrc/common/weapons/weapon/hagar.qc @@@ -139,7 -139,7 +139,7 @@@ void W_Hagar_Attack(Weapon thiswep, ent { 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)); @@@ -184,7 -184,7 +184,7 @@@ void W_Hagar_Attack2(Weapon thiswep, en { 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)); @@@ -236,7 -236,7 +236,7 @@@ void W_Hagar_Attack2_Load_Release(entit 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)); @@@ -248,7 -248,7 +248,7 @@@ right = v_right; up = v_up; - shots = actor.hagar_load; + shots = actor.(weaponentity).hagar_load; missile = NULL; for(counter = 0; counter < shots; ++counter) { @@@ -305,28 -305,25 +305,28 @@@ } 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); @@@ -336,21 -333,19 +336,21 @@@ { 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 @@@ -358,49 -353,49 +358,49 @@@ // 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); @@@ -408,15 -403,15 +408,15 @@@ } 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; } } @@@ -424,16 -419,16 +424,16 @@@ 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; } @@@ -452,26 -447,24 +452,26 @@@ 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); @@@ -488,52 -481,47 +488,52 @@@ 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)) diff --combined qcsrc/common/weapons/weapon/tuba.qc index d68de4a353,1f01ef0413..786c960169 --- a/qcsrc/common/weapons/weapon/tuba.qc +++ b/qcsrc/common/weapons/weapon/tuba.qc @@@ -47,6 -47,7 +47,6 @@@ REGISTER_WEAPON(TUBA, tuba, NEW(Tuba)) .entity tuba_note; .float tuba_smoketime; -.float tuba_instrument; #define MAX_TUBANOTES 32 .float tuba_lastnotes_last; @@@ -55,23 -56,23 +55,23 @@@ 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) @@@ -108,13 -109,13 +108,13 @@@ 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)); @@@ -141,7 -142,7 +141,7 @@@ return false; } - pl.tuba_lastnotes_cnt = 0; + pl.(weaponentity).tuba_lastnotes_cnt = 0; return true; } @@@ -153,13 -154,12 +153,13 @@@ void W_Tuba_NoteOff(entity this // 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 != "") @@@ -320,49 -320,47 +320,49 @@@ void W_Tuba_NoteOn(entity actor, .entit 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 @@@ -389,40 -387,73 +389,40 @@@ METHOD(Tuba, wr_think, void(Tuba this, 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; @@@ -434,8 -465,8 +434,8 @@@ #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)) { @@@ -466,12 -497,6 +466,6 @@@ const int TUBA_MIN = -18 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) diff --combined qcsrc/server/bot/default/havocbot/havocbot.qc index 806ffc9c4a,56c36c0745..0613ab403d --- a/qcsrc/server/bot/default/havocbot/havocbot.qc +++ b/qcsrc/server/bot/default/havocbot/havocbot.qc @@@ -9,10 -9,10 +9,11 @@@ #include "../waypoints.qh" #include + #include #include #include #include +#include #include #include @@@ -85,16 -85,10 +86,16 @@@ void havocbot_ai(entity this 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); @@@ -105,6 -99,8 +106,6 @@@ 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; @@@ -112,16 -108,8 +113,16 @@@ } 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 @@@ -168,28 -156,20 +169,28 @@@ // 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; + )); + } } } } @@@ -605,35 -585,25 +606,35 @@@ void havocbot_movetogoal(entity this 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 @@@ -1013,7 -983,7 +1014,7 @@@ LABEL(scan_targets 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. @@@ -1022,11 -992,11 +1023,11 @@@ 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) @@@ -1036,14 -1006,14 +1037,14 @@@ 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; } @@@ -1051,11 -1021,11 +1052,11 @@@ 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; } )); @@@ -1083,7 -1053,7 +1084,7 @@@ 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; @@@ -1099,11 -1069,11 +1100,11 @@@ 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; } } @@@ -1113,11 -1083,11 +1114,11 @@@ 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; } } @@@ -1126,11 -1096,11 +1127,11 @@@ // 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; } } diff --combined qcsrc/server/client.qc index 2a13404086,da66ece3bb..6ce1cd62f9 --- a/qcsrc/server/client.qc +++ b/qcsrc/server/client.qc @@@ -23,7 -23,6 +23,7 @@@ #include "bot/api.qh" #include "../common/ent_cs.qh" +#include "../common/wepent.qh" #include #include @@@ -37,6 -36,7 +37,7 @@@ #include "weapons/weaponsystem.qh" #include "../common/net_notice.qh" + #include "../common/net_linked.qh" #include "../common/physics/player.qh" #include "../common/items/_mod.qh" @@@ -112,6 -112,7 +113,6 @@@ bool ClientData_Send(entity this, entit 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); @@@ -121,6 -122,11 +122,6 @@@ { 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) { @@@ -251,7 -257,7 +252,7 @@@ void PutObserverInServer(entity this this.view_ofs = '0 0 0'; } - RemoveGrapplingHook(this); + RemoveGrapplingHooks(this); Portal_ClearAll(this); Unfreeze(this); SetSpectatee(this, NULL); @@@ -330,6 -336,7 +331,6 @@@ 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; @@@ -338,13 -345,10 +339,13 @@@ 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; @@@ -356,6 -360,10 +357,6 @@@ 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) @@@ -654,8 -662,7 +655,8 @@@ void PutClientInServer(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; @@@ -670,11 -677,7 +671,11 @@@ 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; + } } )); @@@ -695,18 -698,11 +696,18 @@@ 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; @@@ -1260,7 -1256,7 +1261,7 @@@ void ClientDisconnect(entity this Unfreeze(this); - RemoveGrapplingHook(this); + RemoveGrapplingHooks(this); // Here, everything has been done that requires this player to be a client. @@@ -1281,6 -1277,8 +1282,8 @@@ this.playerid = 0; ReadyCount(); if (vote_called && IS_REAL_CLIENT(this)) VoteCount(false); + + ONREMOVE(this); } void ChatBubbleThink(entity this) @@@ -1689,12 -1687,6 +1692,12 @@@ void SpectateCopy(entity this, entity s 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) @@@ -2443,17 -2435,13 +2446,17 @@@ void PlayerPreThink (entity this { 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)) @@@ -2466,12 -2454,8 +2469,12 @@@ // 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); @@@ -2496,15 -2480,11 +2499,15 @@@ // 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) @@@ -2527,12 -2507,8 +2530,12 @@@ // 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) diff --combined qcsrc/server/g_hook.qc index e50a066618,fd725ad35e..36e1e4e52b --- a/qcsrc/server/g_hook.qc +++ b/qcsrc/server/g_hook.qc @@@ -13,6 -13,7 +13,7 @@@ #include "../common/vehicles/all.qh" #include "../common/constants.qh" #include "../common/util.qh" + #include #include #include "../lib/warpzone/common.qh" #include "../lib/warpzone/server.qh" @@@ -70,41 -71,24 +71,41 @@@ And you should be done .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); @@@ -133,7 -117,6 +134,7 @@@ bool GrapplingHookSend(entity this, ent if(sf & 1) { WriteByte(MSG_ENTITY, etof(this.realowner)); + WriteByte(MSG_ENTITY, weaponslot(this.weaponentity_fld)); } if(sf & 2) { @@@ -156,15 -139,14 +157,15 @@@ void GrapplingHookThink(entity this { 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) @@@ -172,7 -154,7 +173,7 @@@ 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); @@@ -224,7 -206,7 +225,7 @@@ 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); @@@ -242,7 -224,7 +243,7 @@@ 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; @@@ -284,7 -266,7 +285,7 @@@ if(frozen_pulling && autocvar_g_balance_grapplehook_pull_frozen == 2 && !STAT(FROZEN, this.aiment)) { - RemoveGrapplingHook(this.realowner); + RemoveHook(this); return; } } @@@ -356,33 -338,36 +357,33 @@@ void GrapplingHook_Damage(entity this, 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; diff --combined qcsrc/server/g_world.qc index 8e8dce9b12,8edcf3b8f5..4a9656d26a --- a/qcsrc/server/g_world.qc +++ b/qcsrc/server/g_world.qc @@@ -19,6 -19,7 +19,7 @@@ #include "teamplay.qh" #include "weapons/weaponstats.qh" #include "../common/constants.qh" + #include #include "../common/deathtypes/all.qh" #include "../common/mapinfo.qh" #include "../common/monsters/_mod.qh" @@@ -2091,6 -2092,10 +2092,6 @@@ void EndFrame( { antilag_record(it, it, altime); }); - FOREACH_CLIENT(PS(it), { - PlayerState s = PS(it); - s.ps_push(s, it); - }); systems_update(); IL_ENDFRAME(); } diff --combined qcsrc/server/miscfunctions.qc index 35f0f227e7,e90dbeb966..220ebc3af1 --- a/qcsrc/server/miscfunctions.qc +++ b/qcsrc/server/miscfunctions.qc @@@ -11,6 -11,7 +11,7 @@@ #include "weapons/selection.qh" #include "../common/command/_mod.qh" #include "../common/constants.qh" + #include #include "../common/deathtypes/all.qh" #include "../common/mapinfo.qh" #include "../common/notifications/all.qh" @@@ -25,7 -26,6 +26,7 @@@ #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" @@@ -260,8 -260,6 +261,8 @@@ string formatmessage(entity this, strin replacement = substring(msg, p, 2); escape = substring(msg, p + 1, 1); + .entity weaponentity = weaponentities[0]; // TODO: unhardcode + switch(escape) { case "%": replacement = "%"; break; @@@ -272,7 -270,7 +273,7 @@@ 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; @@@ -450,14 -448,7 +451,14 @@@ void GetCvars(entity this, int f 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); } @@@ -1083,7 -1074,7 +1084,7 @@@ bool WarpZone_Projectile_Touch_ImpactFi 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); diff --combined qcsrc/server/weapons/selection.qc index b3075928cb,539371a53c..d7d8fc9c1f --- a/qcsrc/server/weapons/selection.qc +++ b/qcsrc/server/weapons/selection.qc @@@ -3,12 -3,12 +3,13 @@@ #include "weaponsystem.qh" #include #include + #include #include #include #include #include #include +#include // switch between weapons void Send_WeaponComplain(entity e, float wpn, float type) @@@ -39,7 -39,7 +40,7 @@@ void Weapon_whereis(Weapon this, entit }); } -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; @@@ -70,11 -70,11 +71,11 @@@ } 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 @@@ -120,7 -120,7 +121,7 @@@ 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. @@@ -131,10 -131,10 +132,10 @@@ 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; @@@ -167,7 -167,7 +168,7 @@@ ++c; - if(!skipmissing || client_hasweapon(this, wep, true, false)) + if(!skipmissing || client_hasweapon(this, wep, weaponentity, true, false)) { if(switchtonext) return weaponwant; @@@ -224,7 -224,7 +225,7 @@@ --c; if(c == 0) { - client_hasweapon(this, wep, true, true); + client_hasweapon(this, wep, weaponentity, true, true); break; } } @@@ -232,94 -232,97 +233,94 @@@ 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); } diff --combined qcsrc/server/weapons/tracing.qc index 8e6d2eabf1,b49ed88f59..1417717e83 --- a/qcsrc/server/weapons/tracing.qc +++ b/qcsrc/server/weapons/tracing.qc @@@ -10,6 -10,7 +10,7 @@@ #include "../antilag.qh" #include + #include #include #include @@@ -27,7 -28,7 +28,7 @@@ void W_SetupShot_Dir_ProjectileSize_Ran 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; @@@ -53,10 -54,10 +54,10 @@@ // 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) @@@ -196,7 -197,7 +197,7 @@@ void W_SetupProjVelocity_Explicit(entit // 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; @@@ -333,7 -334,7 +334,7 @@@ } // 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; @@@ -348,7 -349,7 +349,7 @@@ void fireBullet_trace_callback(vector s 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; @@@ -441,7 -442,7 +442,7 @@@ // 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); } } diff --combined qcsrc/server/weapons/weaponsystem.qc index 0d26aaa403,c0d302e223..6139f2879c --- a/qcsrc/server/weapons/weaponsystem.qc +++ b/qcsrc/server/weapons/weaponsystem.qc @@@ -8,13 -8,13 +8,14 @@@ #include #include #include + #include #include #include #include #include #include #include +#include .int state; @@@ -61,10 -61,8 +62,10 @@@ vector CL_Weapon_GetShotOrg(int wpn return ret; } -..entity weaponentity_fld; .float m_alpha; +.string w_weaponname; +.int w_dmg; +.int w_deadflag; void CL_Weaponentity_Think(entity this) { @@@ -85,16 -83,16 +86,16 @@@ 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 @@@ -113,8 -111,6 +114,8 @@@ 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); @@@ -125,15 -121,15 +126,15 @@@ 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 = ""; @@@ -156,8 -152,8 +157,8 @@@ 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); @@@ -177,14 -173,11 +178,14 @@@ void CL_SpawnWeaponentity(entity actor 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; @@@ -196,8 -189,8 +197,8 @@@ // 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) { @@@ -215,17 -208,17 +216,17 @@@ void w_ready(Weapon thiswep, entity act .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; }); @@@ -234,7 -227,7 +235,7 @@@ 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; @@@ -242,8 -235,8 +243,8 @@@ // 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) @@@ -262,7 -255,7 +263,7 @@@ } else // this weapon is totally unable to fire, switch to another one { - W_SwitchToOtherWeapon(actor); + W_SwitchToOtherWeapon(actor, weaponentity); } return false; @@@ -272,7 -265,7 +273,7 @@@ 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 @@@ -282,13 -275,13 +283,13 @@@ 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; @@@ -308,14 -301,14 +309,14 @@@ void weapon_prepareattack_do(entity act 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"); } @@@ -379,13 -372,14 +380,13 @@@ void weapon_thinkf(entity actor, .entit 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"); @@@ -399,8 -393,8 +400,8 @@@ 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 @@@ -432,27 -426,27 +433,27 @@@ void W_WeaponFrame(Player actor, .entit 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; } @@@ -463,7 -457,7 +464,7 @@@ 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) { @@@ -476,25 -470,26 +477,25 @@@ 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); @@@ -503,17 -498,17 +504,17 @@@ 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; @@@ -528,7 -523,7 +529,7 @@@ // 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 @@@ -537,7 -532,7 +538,7 @@@ { 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; } @@@ -555,11 -550,11 +556,11 @@@ } 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); } } @@@ -570,7 -565,7 +571,7 @@@ if (!block_weapon) { - Weapon e = PS(actor).m_weapon; + Weapon e = this.m_weapon; TC(Weapon, e); if (w != WEP_Null) { @@@ -582,14 -577,14 +583,14 @@@ } } - 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)); } @@@ -631,17 -626,17 +632,17 @@@ void W_AttachToShotorg(entity actor, .e } } -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) { @@@ -671,30 -666,29 +672,30 @@@ void W_ReloadedAndReady(Weapon thiswep { // 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)); } @@@ -702,13 -696,13 +703,13 @@@ void W_Reload(entity actor, .entity wea { 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)); @@@ -721,29 -715,30 +722,29 @@@ } // 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; } @@@ -767,18 -762,18 +768,18 @@@ // 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); }