.float weapon_eta_last;
.float weapon_switchdelay;
+.string name_last;
+
void viewmodel_draw(entity this)
{
- if(!activeweapon || !autocvar_r_drawviewmodel)
+ if(!this.activeweapon || !autocvar_r_drawviewmodel)
return;
int mask = (intermission || (STAT(HEALTH) <= 0) || autocvar_chase_active) ? 0 : MASK_NORMAL;
float a = this.alpha;
if (invehicle) a = -1;
else if (wasinvehicle) a = 1;
wasinvehicle = invehicle;
- Weapon wep = activeweapon;
- int c = stof(getplayerkeyvalue(current_player, "colors"));
- vector g = weaponentity_glowmod(wep, c);
+ Weapon wep = this.activeweapon;
+ int c = entcs_GetClientColors(current_player);
+ vector g = weaponentity_glowmod(wep, NULL, c, this);
entity me = CSQCModel_server2csqc(player_localentnum - 1);
int fx = ((me.csqcmodel_effects & EFMASK_CHEAP)
| EF_NODEPTHTEST)
CSQCModel_Effects_Apply(e);
}
{
- static string name_last;
string name = wep.mdl;
- bool swap = name != name_last;
+ bool swap = name != this.name_last;
// if (swap)
{
- name_last = name;
+ this.name_last = name;
CL_WeaponEntity_SetModel(this, name, swap);
this.viewmodel_origin = this.origin;
this.viewmodel_angles = this.angles;
setorigin(this, this.origin);
}
-entity viewmodel;
+entity viewmodels[MAX_WEAPONSLOTS];
STATIC_INIT(viewmodel) {
- viewmodel = new(viewmodel);
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ viewmodels[slot] = new(viewmodel);
}
void Porto_Draw(entity this);
vector polyline[polyline_length];
void Porto_Draw(entity this)
{
- if (activeweapon != WEP_PORTO) return;
+ entity wepent = viewmodels[0]; // TODO: unhardcode
+ if (wepent.activeweapon != WEP_PORTO) return;
if (spectatee_status) return;
if (WEP_CVAR(porto, secondary)) return;
if (intermission == 1) return;
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)
ta = trueaim;
mv = MOVE_NOMONSTERS;
- switch(activeweapon) // WEAPONTODO
+ entity wepent = viewmodels[0]; // TODO: unhardcode
+
+ switch(wepent.activeweapon) // WEAPONTODO
{
case WEP_TUBA: // no aim
case WEP_PORTO: // shoots from eye
void PostInit();
void CSQC_Demo_Camera();
-float Scoreboard_WouldDraw();
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;
{
// varying sound pitch
+ entity wepent = viewmodels[0]; // TODO: unhardcode
+
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;
+ float arc_hack = wepent.activeweapon == WEP_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)
v = wcross_origin - wcross_oldorigin;
v.x /= vid_conwidth;
v.y /= vid_conheight;
- if(vlen(v) > 0.01)
+ if(vdist(v, >, 0.01))
shottype = SHOTTYPE_HITOBSTRUCTION;
}
if(!autocvar_crosshair_hittest_showimpact)
entity e = WEP_Null;
if(autocvar_crosshair_per_weapon || (autocvar_crosshair_color_special == 1))
{
- e = switchingweapon;
+ entity wepent = viewmodels[0]; // TODO: unhardcode
+ e = wepent.switchingweapon;
if(e)
{
if(autocvar_crosshair_per_weapon)
weapon_clipload = STAT(WEAPON_CLIPLOAD);
weapon_clipsize = STAT(WEAPON_CLIPSIZE);
- float ok_ammo_charge, ok_ammo_chargepool;
- ok_ammo_charge = STAT(OK_AMMO_CHARGE);
- ok_ammo_chargepool = STAT(OK_AMMO_CHARGEPOOL);
-
float vortex_charge, vortex_chargepool;
vortex_charge = STAT(VORTEX_CHARGE);
vortex_chargepool = STAT(VORTEX_CHARGEPOOL);
if(vortex_charge_movingavg == 0) // this should only happen if we have just loaded up the game
vortex_charge_movingavg = vortex_charge;
+ entity wepent = viewmodels[0]; // TODO: unhardcode
// handle the values
- if (autocvar_crosshair_ring && activeweapon == WEP_VORTEX && vortex_charge && autocvar_crosshair_ring_vortex) // ring around crosshair representing velocity-dependent damage for the vortex
+ if (autocvar_crosshair_ring && wepent.activeweapon == WEP_VORTEX && vortex_charge && autocvar_crosshair_ring_vortex) // ring around crosshair representing velocity-dependent damage for the vortex
{
if (vortex_chargepool || use_vortex_chargepool) {
use_vortex_chargepool = 1;
ring_rgb = wcross_color;
ring_image = "gfx/crosshair_ring_nexgun.tga";
}
- else if (autocvar_crosshair_ring && activeweapon == WEP_MINE_LAYER && WEP_CVAR(minelayer, limit) && autocvar_crosshair_ring_minelayer)
+ else if (autocvar_crosshair_ring && wepent.activeweapon == WEP_MINE_LAYER && WEP_CVAR(minelayer, limit) && autocvar_crosshair_ring_minelayer)
{
ring_value = bound(0, STAT(LAYED_MINES) / WEP_CVAR(minelayer, limit), 1); // if you later need to use the count of bullets in another place, then add a float for it. For now, no need to.
ring_alpha = autocvar_crosshair_ring_minelayer_alpha;
ring_rgb = wcross_color;
ring_image = "gfx/crosshair_ring.tga";
}
- else if (activeweapon == WEP_HAGAR && STAT(HAGAR_LOAD) && autocvar_crosshair_ring_hagar)
+ else if (wepent.activeweapon == WEP_HAGAR && STAT(HAGAR_LOAD) && autocvar_crosshair_ring_hagar)
{
ring_value = bound(0, STAT(HAGAR_LOAD) / WEP_CVAR_SEC(hagar, load_max), 1);
ring_alpha = autocvar_crosshair_ring_hagar_alpha;
ring_rgb = wcross_color;
ring_image = "gfx/crosshair_ring.tga";
}
- else if (ok_ammo_charge)
- {
- ring_value = ok_ammo_chargepool;
- ring_alpha = autocvar_crosshair_ring_reload_alpha;
- ring_rgb = wcross_color;
- ring_image = "gfx/crosshair_ring.tga";
- }
else if(autocvar_crosshair_ring_reload && weapon_clipsize) // forces there to be only an ammo ring
{
ring_value = bound(0, weapon_clipload / weapon_clipsize, 1);
// Note: This is to stop Taoki from complaining that the image doesn't match all potential balances.
// if a new image for another weapon is added, add the code (and its respective file/value) here
- if ((activeweapon == WEP_RIFLE) && (weapon_clipsize == 80))
+ if ((wepent.activeweapon == WEP_RIFLE) && (weapon_clipsize == 80))
ring_image = "gfx/crosshair_ring_rifle.tga";
else
ring_image = "gfx/crosshair_ring.tga";
}
- else if ( autocvar_crosshair_ring && autocvar_crosshair_ring_arc && arc_heat && activeweapon == WEP_ARC )
+ else if ( autocvar_crosshair_ring && autocvar_crosshair_ring_arc && arc_heat && wepent.activeweapon == WEP_ARC )
{
ring_value = arc_heat;
ring_alpha = (1-arc_heat)*autocvar_crosshair_ring_arc_cold_alpha +
void HUD_Draw(entity this)
{
+ // if we don't know gametype and scores yet avoid drawing the scoreboard
+ // also in the very first frames, player state may be inconsistent so avoid drawing the hud at all
+ // e.g. since initial player's health is 0 hud would display the hud_damage effect,
+ // cl_deathscoreboard would show the scoreboard and so on
+ if(!gametype)
+ return;
+
if(!intermission)
if (MUTATOR_CALLHOOK(HUD_Draw_overlay))
{
cvar_set("chase_active", "0");
float vehicle_chase = (hud != HUD_NORMAL && (autocvar_cl_eventchase_vehicle || spectatee_status > 0));
- float ons_roundlost = (gametype == MAPINFO_TYPE_ONSLAUGHT && STAT(ROUNDLOST));
- entity gen = NULL;
float vehicle_viewdist = 0;
vector vehicle_viewofs = '0 0 0';
}
}
- if(ons_roundlost)
- {
- FOREACH_ENTITY_CLASS("onslaught_generator", it.health <= 0, {
- gen = it;
- break;
- });
- if(!gen)
- ons_roundlost = false; // don't enforce the 3rd person camera if there is no dead generator to show
- }
- if(WantEventchase(this) || (!autocvar_cl_orthoview && ons_roundlost))
+ if(WantEventchase(this))
{
+ vector current_view_origin_override = '0 0 0';
+ vector view_offset_override = '0 0 0';
+ float chase_distance_override = 0;
+ bool custom_eventchase = MUTATOR_CALLHOOK(CustomizeEventchase, this);
+ if(custom_eventchase)
+ {
+ current_view_origin_override = M_ARGV(0, vector);
+ view_offset_override = M_ARGV(1, vector);
+ chase_distance_override = M_ARGV(0, float);
+ }
eventchase_running = true;
entity local_player = ((csqcplayer) ? csqcplayer : CSQCModel_server2csqc(player_localentnum - 1));
// make special vector since we can't use view_origin (It is one frame old as of this code, it gets set later with the results this code makes.)
vector current_view_origin = (csqcplayer ? csqcplayer.origin : pmove_org);
- if(ons_roundlost) { current_view_origin = gen.origin; }
+ if (custom_eventchase)
+ current_view_origin = current_view_origin_override;
// detect maximum viewoffset and use it
vector view_offset = autocvar_cl_eventchase_viewoffset;
else
view_offset = autocvar_cl_eventchase_vehicle_viewoffset;
}
- if(ons_roundlost) { view_offset = autocvar_cl_eventchase_generator_viewoffset; }
+ if (custom_eventchase)
+ view_offset = view_offset_override;
if(view_offset)
{
else
chase_distance = autocvar_cl_eventchase_vehicle_distance;
}
- if(ons_roundlost) { chase_distance = autocvar_cl_eventchase_generator_distance; }
+ if (custom_eventchase)
+ chase_distance = chase_distance_override;
if(autocvar_cl_eventchase_speed && eventchase_current_distance < chase_distance)
eventchase_current_distance += autocvar_cl_eventchase_speed * (chase_distance - eventchase_current_distance) * frametime; // slow down the further we get
// 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);
if(!postinit)
PostInit();
+ if(intermission && !gameover_time)
+ gameover_time = time;
+
if(intermission && !isdemo() && !(calledhooks & HOOK_END))
{
if(calledhooks & HOOK_START)
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));
-
- f = (serverflags & SERVERFLAG_TEAMPLAY);
- if(f != teamplay)
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
- teamplay = f;
- Scoreboard_InitScores();
- }
+ entity wepent = viewmodels[slot];
- if(last_switchweapon != switchweapon)
- {
- weapontime = time;
- last_switchweapon = switchweapon;
- if(button_zoom && autocvar_cl_unpress_zoom_on_weapon_switch)
+ if(wepent.last_switchweapon != wepent.switchweapon)
{
- localcmd("-zoom\n");
- button_zoom = false;
+ weapontime = time;
+ wepent.last_switchweapon = wepent.switchweapon;
+ if(slot == 0 && button_zoom && autocvar_cl_unpress_zoom_on_weapon_switch)
+ {
+ localcmd("-zoom\n");
+ button_zoom = false;
+ }
+ if(slot == 0 && autocvar_cl_unpress_attack_on_weapon_switch)
+ {
+ localcmd("-fire\n");
+ localcmd("-fire2\n");
+ button_attack2 = false;
+ }
}
- if(autocvar_cl_unpress_attack_on_weapon_switch)
+ if(wepent.last_activeweapon != wepent.activeweapon)
{
- localcmd("-fire\n");
- localcmd("-fire2\n");
- button_attack2 = false;
- }
- }
- if(last_activeweapon != activeweapon)
- {
- last_activeweapon = activeweapon;
+ wepent.last_activeweapon = wepent.activeweapon;
- e = activeweapon;
- if(e.netname != "")
- localcmd(strcat("\ncl_hook_activeweapon ", e.netname), "\n");
- else
- localcmd("\ncl_hook_activeweapon none\n");
+ e = wepent.activeweapon;
+ if(e.netname != "")
+ localcmd(strcat("\ncl_hook_activeweapon ", e.netname), "\n");
+ else if(slot == 0)
+ localcmd("\ncl_hook_activeweapon none\n");
+ }
}
// ALWAYS Clear Current Scene First
if(autocvar_cl_reticle)
{
- Weapon wep = activeweapon;
+ string reticle_image = "";
+ bool wep_zoomed = false;
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ entity wepe = viewmodels[slot];
+ Weapon wep = wepe.activeweapon;
+ if(wep != WEP_Null && wep.wr_zoom)
+ {
+ bool do_zoom = wep.wr_zoom(wep, NULL);
+ if(wep.w_reticle && wep.w_reticle != "")
+ reticle_image = wep.w_reticle;
+ wep_zoomed += do_zoom;
+ }
+ }
// Draw the aiming reticle for weapons that use it
// reticle_type is changed to the item we are zooming / aiming with, to decide which reticle to use
// It must be a persisted float for fading out to work properly (you let go of the zoom button for
// no zoom reticle while dead
reticle_type = 0;
}
- else if(wep.wr_zoomreticle(wep) && autocvar_cl_reticle_weapon)
+ else if(wep_zoomed && autocvar_cl_reticle_weapon)
{
- if(reticle_image != "") { reticle_type = 2; }
+ if(reticle_image && reticle_image != "") { reticle_type = 2; }
else { reticle_type = 0; }
}
else if(button_zoom || zoomscript_caught)
if(autocvar__hud_configure)
HUD_Panel_Mouse();
- else if ( HUD_MinigameMenu_IsOpened() || minigame_isactive() )
+ else if (HUD_MinigameMenu_IsOpened() || active_minigame)
HUD_Minigame_Mouse();
else if(QuickMenu_IsOpened())
QuickMenu_Mouse();