+ #include "main.qh"
+
+ #include <common/effects/qc/all.qh>
+ #include "hud/all.qh"
#include "mapvoting.qh"
- #include "modeleffects.qh"
- #include "particles.qh"
+ #include "mutators/events.qh"
+ #include "hud/panel/quickmenu.qh"
#include "scoreboard.qh"
#include "shownames.qh"
- #include "target_music.qh"
- #include "tturrets.qh"
- #include "tuba.qh"
+ #include <common/t_items.qh>
#include "wall.qh"
- #include "waypointsprites.qh"
-
- #include "vehicles/vehicles.qh"
-
- #include "../server/vehicles/bumblebee.qh"
-
- #include "../common/net_notice.qh"
-
- #include "../common/monsters/monsters.qh"
-
- #include "../warpzonelib/client.qh"
+ #include "weapons/projectile.qh"
+ #include <common/deathtypes/all.qh>
+ #include <common/items/all.qh>
+ #include <common/mapinfo.qh>
+ #include <common/minigames/cl_minigames.qh>
+ #include <common/minigames/cl_minigames_hud.qh>
+ #include <common/net_notice.qh>
+ #include <common/triggers/include.qh>
+ #include <common/vehicles/all.qh>
+ #include <lib/csqcmodel/cl_model.qh>
+ #include <lib/csqcmodel/interpolate.qh>
+ #include <lib/warpzone/client.qh>
// --------------------------------------------------------------------------
// BEGIN REQUIRED CSQC FUNCTIONS
//include "main.qh"
- entity clearentity_ent;
- void clearentity(entity e)
+ #define DP_CSQC_ENTITY_REMOVE_IS_B0RKED
+
+ void draw_cursor(vector pos, vector ofs, string img, vector col, float a)
{
- if (!clearentity_ent)
- {
- clearentity_ent = spawn();
- clearentity_ent.classname = "clearentity";
- }
- int n = e.entnum;
- copyentity(clearentity_ent, e);
- e.entnum = n;
+ ofs = eX * (ofs.x * SIZE_CURSOR.x) + eY * (ofs.y * SIZE_CURSOR.y);
+ drawpic(pos - ofs, strcat(draw_currentSkin, img), SIZE_CURSOR, col, a, DRAWFLAG_NORMAL);
}
- #define DP_CSQC_ENTITY_REMOVE_IS_B0RKED
- void menu_show_error()
+ void draw_cursor_normal(vector pos, vector col, float a)
{
- drawstring('0 200 0', _("ERROR - MENU IS VISIBLE BUT NO MENU WAS DEFINED!"), '8 8 0', '1 0 0', 1, 0);
+ draw_cursor(pos, OFFSET_CURSOR, "/cursor", col, a);
}
- // CSQC_Init : Called every time the CSQC code is initialized (essentially at map load)
- // Useful for precaching things
-
- void menu_sub_null()
+ void LoadMenuSkinValues()
{
+ int fh = -1;
+ if(cvar_string("menu_skin") != "")
+ {
+ draw_currentSkin = strcat("gfx/menu/", cvar_string("menu_skin"));
+ fh = fopen(strcat(draw_currentSkin, "/skinvalues.txt"), FILE_READ);
+ }
+ if(fh < 0 && cvar_defstring("menu_skin") != "")
+ {
+ cvar_set("menu_skin", cvar_defstring("menu_skin"));
+ draw_currentSkin = strcat("gfx/menu/", cvar_string("menu_skin"));
+ fh = fopen(strcat(draw_currentSkin, "/skinvalues.txt"), FILE_READ);
+ }
+ if(fh < 0)
+ {
+ draw_currentSkin = "gfx/menu/default";
+ fh = fopen(strcat(draw_currentSkin, "/skinvalues.txt"), FILE_READ);
+ }
+
+ draw_currentSkin = strzone(draw_currentSkin);
+
+ if(fh >= 0)
+ {
+ string s;
+ while((s = fgets(fh)))
+ {
+ int n = tokenize_console(s);
+ if (n < 2)
+ continue;
+ if(substring(argv(0), 0, 2) == "//")
+ continue;
+ if(argv(0) == "SIZE_CURSOR")
+ SIZE_CURSOR = stov(substring(s, argv_start_index(1), argv_end_index(-1) - argv_start_index(1)));
+ else if(argv(0) == "OFFSET_CURSOR")
+ OFFSET_CURSOR = stov(substring(s, argv_start_index(1), argv_end_index(-1) - argv_start_index(1)));
+ }
+ fclose(fh);
+ }
}
- string forcefog;
- void WaypointSprite_Load();
+ // CSQC_Init : Called every time the CSQC code is initialized (essentially at map load)
+ // Useful for precaching things
+
void ConsoleCommand_macro_init();
- void CSQC_Init(void)
+ void CSQC_Init()
{
- prvm_language = cvar_string("prvm_language");
+ prvm_language = strzone(cvar_string("prvm_language"));
#ifdef WATERMARK
- dprintf("^4CSQC Build information: ^1%s\n", WATERMARK);
+ LOG_INFOF("^4CSQC Build information: ^1%s\n", WATERMARK);
#endif
- int i;
+ {
+ int i = 0;
+ for ( ; i < 255; ++i)
+ if (getplayerkeyvalue(i, "viewentity") == "")
+ break;
+ maxclients = i;
+ }
+
+ // needs to be done so early because of the constants they create
+ static_init();
+ static_init_late();
+ static_init_precache();
binddb = db_create();
tempdb = db_create();
compressShortVector_init();
draw_endBoldFont();
- menu_visible = false;
- menu_show = menu_show_error;
- menu_action = func_null;
-
- for(i = 0; i < 255; ++i)
- if(getplayerkeyvalue(i, "viewentity") == "")
- break;
- maxclients = i;
//registercommand("hud_configure");
//registercommand("hud_save");
registercvar("cl_nade_type", "3");
registercvar("cl_pokenade_type", "zombie");
+ registercvar("cl_jumpspeedcap_min", "");
+ registercvar("cl_jumpspeedcap_max", "");
+
+ registercvar("cl_multijump", "1");
+
+ registercvar("cl_spawn_near_teammate", "1");
+
gametype = 0;
// hud_fields uses strunzone on the titles!
- for(i = 0; i < MAX_HUD_FIELDS; ++i)
+ for(int i = 0; i < MAX_HUD_FIELDS; ++i)
hud_title[i] = strzone("(null)");
Cmd_HUD_SetFields(0);
GetTeam(NUM_SPECTATOR, true); // add specs first
- // needs to be done so early because of the constants they create
- CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
- CALL_ACCUMULATED_FUNCTION(RegisterMonsters);
- CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
- CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
- CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
- CALL_ACCUMULATED_FUNCTION(RegisterHUD_Panels);
- CALL_ACCUMULATED_FUNCTION(RegisterBuffs);
-
- WaypointSprite_Load();
-
// precaches
- precache_model("null");
- precache_sound("misc/hit.wav");
- precache_sound("misc/typehit.wav");
-
- Projectile_Precache();
- Hook_Precache();
- GibSplash_Precache();
- Casings_Precache();
- Vehicles_Precache();
- turrets_precache();
- Tuba_Precache();
- CSQCPlayer_Precache();
if(autocvar_cl_reticle)
{
// weapon reticles are precached in weapon files
}
- get_mi_min_max_texcoords(1); // try the CLEVER way first
- minimapname = strcat("gfx/", mi_shortname, "_radar.tga");
- shortmapname = mi_shortname;
-
- if(precache_pic(minimapname) == "")
{
- // but maybe we have a non-clever minimap
- minimapname = strcat("gfx/", mi_shortname, "_mini.tga");
- if(precache_pic(minimapname) == "")
- minimapname = ""; // FAIL
- else
- get_mi_min_max_texcoords(0); // load new texcoords
- }
+ get_mi_min_max_texcoords(1); // try the CLEVER way first
+ minimapname = strcat("gfx/", mi_shortname, "_radar.tga");
+ shortmapname = mi_shortname;
- mi_center = (mi_min + mi_max) * 0.5;
- mi_scale = mi_max - mi_min;
- minimapname = strzone(minimapname);
+ if (precache_pic(minimapname) == "")
+ {
+ // but maybe we have a non-clever minimap
+ minimapname = strcat("gfx/", mi_shortname, "_mini.tga");
+ if (precache_pic(minimapname) == "")
+ minimapname = ""; // FAIL
+ else
+ get_mi_min_max_texcoords(0); // load new texcoords
+ }
- WarpZone_Init();
+ mi_center = (mi_min + mi_max) * 0.5;
+ mi_scale = mi_max - mi_min;
+ minimapname = strzone(minimapname);
+ }
hud_skin_path = strzone(strcat("gfx/hud/", autocvar_hud_skin));
- draw_currentSkin = strzone(strcat("gfx/menu/", cvar_string("menu_skin")));
+ LoadMenuSkinValues();
}
// CSQC_Shutdown : Called every time the CSQC code is shutdown (changing maps, quitting, etc)
- void Shutdown(void)
+ void Shutdown()
{
WarpZone_Shutdown();
if(autocvar_chase_active < 0)
cvar_set("chase_active", "0");
+ cvar_set("slowmo", cvar_defstring("slowmo")); // reset it back to 'default'
+
if (!isdemo())
{
if (!(calledhooks & HOOK_START))
if (!(calledhooks & HOOK_END))
localcmd("\ncl_hook_gameend\n");
}
+
+ deactivate_minigame();
+ HUD_MinigameMenu_Close(NULL, NULL, NULL);
}
.float has_team;
float SetTeam(entity o, int Team)
{
+ TC(int, Team);
+ devassert_once(Team);
entity tm;
if(teamplay)
{
default:
if(GetTeam(Team, false) == world)
{
- dprintf("trying to switch to unsupported team %d\n", Team);
+ LOG_TRACEF("trying to switch to unsupported team %d\n", Team);
Team = NUM_SPECTATOR;
}
break;
default:
if(GetTeam(Team, false) == world)
{
- dprintf("trying to switch to unsupported team %d\n", Team);
+ LOG_TRACEF("trying to switch to unsupported team %d\n", Team);
Team = NUM_SPECTATOR;
}
break;
return false;
}
- void Playerchecker_Think()
+ void Playerchecker_Think(entity this)
{
int i;
entity e;
for(i = 0; i < maxclients; ++i)
{
e = playerslots[i];
- if(GetPlayerName(i) == "")
+ if(entcs_GetName(i) == "")
{
if(e.sort_prev)
{
{
// player connected
if (!e)
- playerslots[i] = e = spawn();
+ {
+ playerslots[i] = e = new_pure(playerslot);
+ }
e.sv_entnum = i;
e.ping = 0;
e.ping_packetloss = 0;
e.ping_movementloss = 0;
//e.gotscores = 0; // we might already have the scores...
- SetTeam(e, GetPlayerColor(i)); // will not hurt; later updates come with HUD_UpdatePlayerTeams
+ int t = entcs_GetScoreTeam(i);
+ if (t) SetTeam(e, t); // will not hurt; later updates come with HUD_UpdatePlayerTeams
RegisterPlayer(e);
HUD_UpdatePlayerPos(e);
}
}
}
- self.nextthink = time + 0.2;
+ this.nextthink = time + 0.2;
}
- void Porto_Init();
void TrueAim_Init();
- void PostInit(void)
+ void PostInit()
{
- entity playerchecker;
- playerchecker = spawn();
- playerchecker.think = Playerchecker_Think;
+ entity playerchecker = new_pure(playerchecker);
+ setthink(playerchecker, Playerchecker_Think);
playerchecker.nextthink = time + 0.2;
- Porto_Init();
TrueAim_Init();
postinit = true;
// In the case of keyboard input, nPrimary is the ascii code, and nSecondary is 0.
// In the case of mouse input, nPrimary is xdelta, nSecondary is ydelta.
// In the case of mouse input after a setcursormode(1) call, nPrimary is xpos, nSecondary is ypos.
- float CSQC_InputEvent(float bInputType, float nPrimary, float nSecondary)
+ float CSQC_InputEvent(int bInputType, float nPrimary, float nSecondary)
{
- float bSkipKey;
- bSkipKey = false;
-
+ TC(int, bInputType);
if (HUD_Panel_InputEvent(bInputType, nPrimary, nSecondary))
return true;
+ if (QuickMenu_InputEvent(bInputType, nPrimary, nSecondary))
+ return true;
+
+ if (HUD_Radar_InputEvent(bInputType, nPrimary, nSecondary))
+ return true;
+
if (MapVote_InputEvent(bInputType, nPrimary, nSecondary))
return true;
- if(menu_visible && menu_action)
- if(menu_action(bInputType, nPrimary, nSecondary))
- return true;
+ if (HUD_Minigame_InputEvent(bInputType, nPrimary, nSecondary))
+ return true;
- return bSkipKey;
+ return false;
}
// END REQUIRED CSQC FUNCTIONS
// --------------------------------------------------------------------------
// BEGIN OPTIONAL CSQC FUNCTIONS
- void Ent_RemoveEntCS()
- {
- entcs_receiver[self.sv_entnum] = world;
- }
- void Ent_ReadEntCS()
- {
- int sf;
- InterpolateOrigin_Undo();
- self.classname = "entcs_receiver";
- sf = ReadByte();
+ void Ent_Remove(entity this);
- if(sf & 1)
- self.sv_entnum = ReadByte();
- if(sf & 2)
- {
- self.origin_x = ReadShort();
- self.origin_y = ReadShort();
- self.origin_z = ReadShort();
- setorigin(self, self.origin);
- }
- if(sf & 4)
- {
- self.angles_y = ReadByte() * 360.0 / 256;
- self.angles_x = self.angles_z = 0;
- }
- if(sf & 8)
- self.healthvalue = ReadByte() * 10;
- if(sf & 16)
- self.armorvalue = ReadByte() * 10;
-
- entcs_receiver[self.sv_entnum] = self;
- self.entremove = Ent_RemoveEntCS;
- self.iflags |= IFLAG_ORIGIN;
-
- InterpolateOrigin_Note();
- }
-
- void Ent_Remove();
-
- void Ent_RemovePlayerScore()
+ void Ent_RemovePlayerScore(entity this)
{
- if(self.owner) {
- SetTeam(self.owner, -1);
- self.owner.gotscores = 0;
+ if(this.owner) {
+ SetTeam(this.owner, -1);
+ this.owner.gotscores = 0;
for(int i = 0; i < MAX_SCORE; ++i) {
- self.owner.(scores[i]) = 0; // clear all scores
+ this.owner.(scores[i]) = 0; // clear all scores
}
}
}
- void Ent_ReadPlayerScore()
+ NET_HANDLE(ENT_CLIENT_SCORES, bool isnew)
{
+ make_pure(this);
int i, n;
bool isNew;
entity o;
// damnit -.- don't want to go change every single .sv_entnum in hud.qc AGAIN
// (no I've never heard of M-x replace-string, sed, or anything like that)
- isNew = !self.owner; // workaround for DP bug
+ isNew = !this.owner; // workaround for DP bug
n = ReadByte()-1;
#ifdef DP_CSQC_ENTITY_REMOVE_IS_B0RKED
- if(!isNew && n != self.sv_entnum)
+ if(!isNew && n != this.sv_entnum)
{
//print("A CSQC entity changed its owner!\n");
- printf("A CSQC entity changed its owner! (edict: %d, classname: %s)\n", num_for_edict(self), self.classname);
+ LOG_INFOF("A CSQC entity changed its owner! (edict: %d, classname: %s)\n", etof(this), this.classname);
isNew = true;
- Ent_Remove();
- self.enttype = ENT_CLIENT_SCORES;
+ Ent_Remove(this);
}
#endif
- self.sv_entnum = n;
+ this.sv_entnum = n;
- if (!(playerslots[self.sv_entnum]))
- playerslots[self.sv_entnum] = spawn();
- o = self.owner = playerslots[self.sv_entnum];
- o.sv_entnum = self.sv_entnum;
+ o = playerslots[this.sv_entnum];
+ if (!o)
+ {
+ o = playerslots[this.sv_entnum] = new_pure(playerslot);
+ }
+ this.owner = o;
+ o.sv_entnum = this.sv_entnum;
o.gotscores = 1;
//if (!o.sort_prev)
o.(scores[i]) = ReadChar();
}
+ return = true;
+
if(o.sort_prev)
HUD_UpdatePlayerPos(o); // if not registered, we cannot do this yet!
- self.entremove = Ent_RemovePlayerScore;
+ this.entremove = Ent_RemovePlayerScore;
}
- void Ent_ReadTeamScore()
+ NET_HANDLE(ENT_CLIENT_TEAMSCORES, bool isnew)
{
+ make_pure(this);
int i;
entity o;
- self.team = ReadByte();
- o = self.owner = GetTeam(self.team, true); // these team numbers can always be trusted
+ this.team = ReadByte();
+ o = this.owner = GetTeam(this.team, true); // these team numbers can always be trusted
int sf, lf;
#if MAX_TEAMSCORE <= 8
o.(teamscores[i]) = ReadChar();
}
+ return = true;
+
HUD_UpdateTeamPos(o);
}
- void Ent_ClientData()
+ NET_HANDLE(ENT_CLIENT_CLIENTDATA, bool isnew)
{
+ make_pure(this);
float newspectatee_status;
int f = ReadByte();
else
angles_held_status = 0;
+ if(f & 16)
+ {
+ num_spectators = ReadByte();
+
+ float i, slot;
+
+ for(i = 0; i < MAX_SPECTATORS; ++i)
+ spectatorlist[i] = 0; // reset list first
+
+ for(i = 0; i < num_spectators; ++i)
+ {
+ slot = ReadByte();
+ spectatorlist[i] = slot - 1;
+ }
+ }
+
+ return = true;
+
if(newspectatee_status != spectatee_status)
{
// clear race stuff
race_laptime = 0;
race_checkpointtime = 0;
+ hud_dynamic_shake_factor = -1;
}
if (autocvar_hud_panel_healtharmor_progressbar_gfx)
{
// we could get rid of spectatee_status, and derive it from player_localentnum and player_localnum
}
- void Ent_Nagger()
+ NET_HANDLE(ENT_CLIENT_NAGGER, bool isnew)
{
+ make_pure(this);
int i, j, b, f;
int nags = ReadByte(); // NAGS NAGS NAGS NAGS NAGS NAGS NADZ NAGS NAGS NAGS
- if(!(nags & 4))
+ if(!(nags & BIT(2)))
{
if(vote_called_vote)
strunzone(vote_called_vote);
vote_active = 1;
}
- if(nags & 64)
+ if(nags & BIT(6))
{
vote_yescount = ReadByte();
vote_nocount = ReadByte();
vote_highlighted = ReadChar();
}
- if(nags & 128)
+ if(nags & BIT(7))
{
if(vote_called_vote)
strunzone(vote_called_vote);
}
}
- ready_waiting = (nags & 1);
- ready_waiting_for_me = (nags & 2);
- vote_waiting = (nags & 4);
- vote_waiting_for_me = (nags & 8);
- warmup_stage = (nags & 16);
+ return = true;
+
+ ready_waiting = (nags & BIT(0));
+ ready_waiting_for_me = (nags & BIT(1));
+ vote_waiting = (nags & BIT(2));
+ vote_waiting_for_me = (nags & BIT(3));
+ warmup_stage = (nags & BIT(4));
}
- void Ent_EliminatedPlayers()
+ NET_HANDLE(ENT_CLIENT_ELIMINATEDPLAYERS, bool isnew)
{
+ make_pure(this);
int i, j, b, f;
int sf = ReadByte();
playerslots[j].eliminated = 0;
}
}
+ return true;
}
- void Ent_RandomSeed()
+ NET_HANDLE(ENT_CLIENT_RANDOMSEED, bool isnew)
{
- float s;
+ make_pure(this);
prandom_debug();
- s = ReadShort();
+ float s = ReadShort();
psrandom(s);
+ return true;
}
- void Ent_ReadAccuracy(void)
+ NET_HANDLE(ENT_CLIENT_ACCURACY, bool isnew)
{
- int f, w;
+ make_pure(this);
int sf = ReadInt24_t();
- if(sf == 0)
- {
- for(w = 0; w <= WEP_LAST - WEP_FIRST; ++w)
+ if (sf == 0) {
+ for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w)
weapon_accuracy[w] = -1;
- return;
+ return true;
}
- for(w = 0, f = 1; w <= WEP_LAST - WEP_FIRST; ++w)
- {
- if(sf & f)
- {
+ int f = 1;
+ for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w) {
+ if (sf & f) {
int b = ReadByte();
- if(b == 0)
+ if (b == 0)
weapon_accuracy[w] = -1;
- else if(b == 255)
+ else if (b == 255)
weapon_accuracy[w] = 1.0; // no better error handling yet, sorry
else
weapon_accuracy[w] = (b - 1.0) / 100.0;
}
- if(f == 0x800000)
- f = 1;
- else
- f *= 2;
+ f = (f == 0x800000) ? 1 : f * 2;
}
+ return true;
}
- void Spawn_Draw(void)
+ void Spawn_Draw(entity this)
{
- pointparticles(self.cnt, self.origin + '0 0 28', '0 0 2', bound(0, frametime, 0.1));
+ __pointparticles(this.cnt, this.origin + '0 0 28', '0 0 2', bound(0, frametime, 0.1));
}
- void Ent_ReadSpawnPoint(float is_new) // entity for spawnpoint
+ void Spawn_PreDraw(entity this)
+ {
+ float alph;
+ vector org = getpropertyvec(VF_ORIGIN);
+ if(this.fade_start)
+ alph = bound(0, (this.fade_end - vlen(org - this.origin - 0.5 * (this.mins + this.maxs))) / (this.fade_end - this.fade_start), 1);
+ else
+ alph = 1;
+ //printf("%v <-> %v\n", view_origin, this.origin + 0.5 * (this.mins + this.maxs));
+ this.alpha = alph;
+ if(alph <= 0)
+ this.drawmask = 0;
+ else
+ this.drawmask = MASK_NORMAL;
+ }
+
+ NET_HANDLE(ENT_CLIENT_SPAWNPOINT, bool is_new)
{
float teamnum = (ReadByte() - 1);
vector spn_origin;
- spn_origin.x = ReadShort();
- spn_origin.y = ReadShort();
- spn_origin.z = ReadShort();
+ spn_origin.x = ReadCoord();
+ spn_origin.y = ReadCoord();
+ spn_origin.z = ReadCoord();
- if(is_new)
- {
- self.origin = spn_origin;
- setsize(self, PL_MIN, PL_MAX);
- droptofloor();
+ //if(is_new)
+ //{
+ this.origin = spn_origin;
+ setsize(this, PL_MIN_CONST, PL_MAX_CONST);
+ //droptofloor();
/*if(autocvar_cl_spawn_point_model) // needs a model first
{
- self.mdl = "models/spawnpoint.md3";
- self.colormod = Team_ColorRGB(teamnum);
- precache_model(self.mdl);
- setmodel(self, self.mdl);
- self.drawmask = MASK_NORMAL;
- //self.movetype = MOVETYPE_NOCLIP;
- //self.draw = Spawn_Draw;
+ this.mdl = "models/spawnpoint.md3";
+ this.colormod = Team_ColorRGB(teamnum);
+ precache_model(this.mdl);
+ setmodel(this, this.mdl);
+ this.drawmask = MASK_NORMAL;
+ //this.movetype = MOVETYPE_NOCLIP;
+ //this.draw = Spawn_Draw;
}*/
if(autocvar_cl_spawn_point_particles)
{
{
switch(teamnum)
{
- case NUM_TEAM_1: self.cnt = particleeffectnum("spawn_point_red"); break;
- case NUM_TEAM_2: self.cnt = particleeffectnum("spawn_point_blue"); break;
- case NUM_TEAM_3: self.cnt = particleeffectnum("spawn_point_yellow"); break;
- case NUM_TEAM_4: self.cnt = particleeffectnum("spawn_point_pink"); break;
- default: self.cnt = particleeffectnum("spawn_point_neutral"); break;
+ case NUM_TEAM_1: this.cnt = particleeffectnum(EFFECT_SPAWNPOINT_RED); break;
+ case NUM_TEAM_2: this.cnt = particleeffectnum(EFFECT_SPAWNPOINT_BLUE); break;
+ case NUM_TEAM_3: this.cnt = particleeffectnum(EFFECT_SPAWNPOINT_YELLOW); break;
+ case NUM_TEAM_4: this.cnt = particleeffectnum(EFFECT_SPAWNPOINT_PINK); break;
+ default: this.cnt = particleeffectnum(EFFECT_SPAWNPOINT_NEUTRAL); break;
}
}
- else { self.cnt = particleeffectnum("spawn_point_neutral"); }
+ else { this.cnt = particleeffectnum(EFFECT_SPAWNPOINT_NEUTRAL); }
- self.draw = Spawn_Draw;
+ this.draw = Spawn_Draw;
+ setpredraw(this, Spawn_PreDraw);
+ this.fade_start = autocvar_cl_spawn_point_dist_min;
+ this.fade_end = autocvar_cl_spawn_point_dist_max;
}
- }
+ //}
- //printf("Ent_ReadSpawnPoint(is_new = %d); origin = %s, team = %d, effect = %d\n", is_new, vtos(self.origin), teamnum, self.cnt);
+ //printf("Ent_ReadSpawnPoint(is_new = %d); origin = %s, team = %d, effect = %d\n", is_new, vtos(this.origin), teamnum, this.cnt);
+ return true;
}
- void Ent_ReadSpawnEvent(float is_new)
+ NET_HANDLE(ENT_CLIENT_SPAWNEVENT, bool is_new)
{
// If entnum is 0, ONLY do the local spawn actions
// this way the server can disable the sending of
if(entnum)
{
- self.origin_x = ReadShort();
- self.origin_y = ReadShort();
- self.origin_z = ReadShort();
+ this.origin_x = ReadCoord();
+ this.origin_y = ReadCoord();
+ this.origin_z = ReadCoord();
if(is_new)
{
- float teamnum = GetPlayerColor(entnum - 1);
+ float teamnum = entcs_GetTeam(entnum - 1);
if(autocvar_cl_spawn_event_particles)
{
switch(teamnum)
{
- case NUM_TEAM_1: pointparticles(particleeffectnum("spawn_event_red"), self.origin, '0 0 0', 1); break;
- case NUM_TEAM_2: pointparticles(particleeffectnum("spawn_event_blue"), self.origin, '0 0 0', 1); break;
- case NUM_TEAM_3: pointparticles(particleeffectnum("spawn_event_yellow"), self.origin, '0 0 0', 1); break;
- case NUM_TEAM_4: pointparticles(particleeffectnum("spawn_event_pink"), self.origin, '0 0 0', 1); break;
- default: pointparticles(particleeffectnum("spawn_event_neutral"), self.origin, '0 0 0', 1); break;
+ case NUM_TEAM_1: pointparticles(EFFECT_SPAWN_RED, this.origin, '0 0 0', 1); break;
+ case NUM_TEAM_2: pointparticles(EFFECT_SPAWN_BLUE, this.origin, '0 0 0', 1); break;
+ case NUM_TEAM_3: pointparticles(EFFECT_SPAWN_YELLOW, this.origin, '0 0 0', 1); break;
+ case NUM_TEAM_4: pointparticles(EFFECT_SPAWN_PINK, this.origin, '0 0 0', 1); break;
+ default: pointparticles(EFFECT_SPAWN_NEUTRAL, this.origin, '0 0 0', 1); break;
}
}
if(autocvar_cl_spawn_event_sound)
{
- sound(self, CH_TRIGGER, "misc/spawn.wav", VOL_BASE, ATTEN_NORM);
+ sound(this, CH_TRIGGER, SND_SPAWN, VOL_BASE, ATTEN_NORM);
}
}
}
+ return = true;
// local spawn actions
if(is_new && (!entnum || (entnum == player_localentnum)))
button_zoom = false;
}
}
-
- //printf("Ent_ReadSpawnEvent(is_new = %d); origin = %s, entnum = %d, localentnum = %d\n", is_new, vtos(self.origin), entnum, player_localentnum);
+ HUD_Radar_Hide_Maximized();
+ //printf("Ent_ReadSpawnEvent(is_new = %d); origin = %s, entnum = %d, localentnum = %d\n", is_new, vtos(this.origin), entnum, player_localentnum);
}
// CSQC_Ent_Update : Called every frame that the server has indicated an update to the SSQC / CSQC entity has occured.
// The only parameter reflects if the entity is "new" to the client, meaning it just came into the client's PVS.
- void Ent_RadarLink();
- void Ent_Init();
- void Ent_ScoresInfo();
- void CSQC_Ent_Update(float bIsNewEntity)
- {
- float t;
- float savetime;
- t = ReadByte();
-
- if(autocvar_developer_csqcentities)
- printf("CSQC_Ent_Update(%d) with self=%i self.entnum=%d self.enttype=%d t=%d\n", bIsNewEntity, self, self.entnum, self.enttype, t);
+ void CSQC_Ent_Update(bool isnew)
+ {ENGINE_EVENT();
+ this.sourceLoc = __FILE__ ":" STR(__LINE__);
+ int t = ReadByte();
// set up the "time" global for received entities to be correct for interpolation purposes
- savetime = time;
+ float savetime = time;
if(servertime)
{
time = servertime;
else
{
serverprevtime = time;
- serverdeltatime = getstatf(STAT_MOVEVARS_TICRATE) * getstatf(STAT_MOVEVARS_TIMESCALE);
+ serverdeltatime = STAT(MOVEVARS_TICRATE) * STAT(MOVEVARS_TIMESCALE);
time = serverprevtime + serverdeltatime;
}
#ifdef DP_CSQC_ENTITY_REMOVE_IS_B0RKED
- if(self.enttype)
+ if (this.enttype)
{
- if(t != self.enttype || bIsNewEntity)
+ if (t != this.enttype || isnew)
{
- //print("A CSQC entity changed its type!\n");
- printf("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)\n", num_for_edict(self), self.entnum, self.enttype, t);
- Ent_Remove();
- clearentity(self);
- bIsNewEntity = 1;
+ LOG_INFOF("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)\n", etof(this), this.entnum, this.enttype, t);
+ Ent_Remove(this);
+ clearentity(this);
+ isnew = true;
}
}
else
{
- if(!bIsNewEntity)
+ if (!isnew)
{
- printf("A CSQC entity appeared out of nowhere! (edict: %d, server: %d, type: %d)\n", num_for_edict(self), self.entnum, t);
- bIsNewEntity = 1;
+ LOG_INFOF("A CSQC entity appeared out of nowhere! (edict: %d, server: %d, type: %d)\n", etof(this), this.entnum, t);
+ isnew = true;
}
}
#endif
- self.enttype = t;
- switch(t)
+ this.enttype = t;
+ bool done = false;
+ FOREACH(LinkedEntities, it.m_id == t, {
+ if (isnew) this.classname = it.netname;
+ if (autocvar_developer_csqcentities)
+ LOG_INFOF("CSQC_Ent_Update(%d) at %f with this=%i {.entnum=%d, .enttype=%d} t=%s (%d)\n", isnew, savetime, this, this.entnum, this.enttype, this.classname, t);
+ done = it.m_read(this, NULL, isnew);
+ break;
+ });
+ time = savetime;
+ if (!done)
{
- case ENT_CLIENT_ENTCS: Ent_ReadEntCS(); break;
- case ENT_CLIENT_SCORES: Ent_ReadPlayerScore(); break;
- case ENT_CLIENT_TEAMSCORES: Ent_ReadTeamScore(); break;
- case ENT_CLIENT_POINTPARTICLES: Ent_PointParticles(); break;
- case ENT_CLIENT_RAINSNOW: Ent_RainOrSnow(); break;
- case ENT_CLIENT_LASER: Ent_Laser(); break;
- case ENT_CLIENT_NAGGER: Ent_Nagger(); break;
- case ENT_CLIENT_ELIMINATEDPLAYERS: Ent_EliminatedPlayers(); break;
- case ENT_CLIENT_WAYPOINT: Ent_WaypointSprite(); break;
- case ENT_CLIENT_RADARLINK: Ent_RadarLink(); break;
- case ENT_CLIENT_PROJECTILE: Ent_Projectile(); break;
- case ENT_CLIENT_GIBSPLASH: Ent_GibSplash(bIsNewEntity); break;
- case ENT_CLIENT_DAMAGEINFO: Ent_DamageInfo(bIsNewEntity); break;
- case ENT_CLIENT_CASING: Ent_Casing(bIsNewEntity); break;
- case ENT_CLIENT_INIT: Ent_Init(); break;
- case ENT_CLIENT_SCORES_INFO: Ent_ScoresInfo(); break;
- case ENT_CLIENT_MAPVOTE: Ent_MapVote(); break;
- case ENT_CLIENT_CLIENTDATA: Ent_ClientData(); break;
- case ENT_CLIENT_RANDOMSEED: Ent_RandomSeed(); break;
- case ENT_CLIENT_WALL: Ent_Wall(); break;
- case ENT_CLIENT_MODELEFFECT: Ent_ModelEffect(bIsNewEntity); break;
- case ENT_CLIENT_TUBANOTE: Ent_TubaNote(bIsNewEntity); break;
- case ENT_CLIENT_WARPZONE: WarpZone_Read(bIsNewEntity); break;
- case ENT_CLIENT_WARPZONE_CAMERA: WarpZone_Camera_Read(bIsNewEntity); break;
- case ENT_CLIENT_WARPZONE_TELEPORTED: WarpZone_Teleported_Read(bIsNewEntity); break;
- case ENT_CLIENT_TRIGGER_MUSIC: Ent_ReadTriggerMusic(); break;
- case ENT_CLIENT_HOOK: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_HOOK); break;
- case ENT_CLIENT_ARC_BEAM: Ent_ReadArcBeam(bIsNewEntity); break;
- case ENT_CLIENT_ACCURACY: Ent_ReadAccuracy(); break;
- case ENT_CLIENT_AUXILIARYXHAIR: Net_AuXair2(bIsNewEntity); break;
- case ENT_CLIENT_TURRET: ent_turret(); break;
- case ENT_CLIENT_MODEL: CSQCModel_Read(bIsNewEntity); break;
- case ENT_CLIENT_ITEM: ItemRead(bIsNewEntity); break;
- case ENT_CLIENT_BUMBLE_RAYGUN: bumble_raygun_read(bIsNewEntity); break;
- case ENT_CLIENT_SPAWNPOINT: Ent_ReadSpawnPoint(bIsNewEntity); break;
- case ENT_CLIENT_SPAWNEVENT: Ent_ReadSpawnEvent(bIsNewEntity); break;
- case ENT_CLIENT_NOTIFICATION: Read_Notification(bIsNewEntity); break;
- case ENT_CLIENT_HEALING_ORB: ent_healer(); break;
-
- default:
- //error(strcat(_("unknown entity type in CSQC_Ent_Update: %d\n"), self.enttype));
- error(sprintf("Unknown entity type in CSQC_Ent_Update (enttype: %d, edict: %d, classname: %s)\n", self.enttype, num_for_edict(self), self.classname));
- break;
+ LOG_FATALF("CSQC_Ent_Update(%d) at %f with this=%i {.entnum=%d, .enttype=%d} t=%s (%d)\n", isnew, savetime, this, this.entnum, this.enttype, this.classname, t);
}
-
- time = savetime;
}
+
// Destructor, but does NOT deallocate the entity by calling remove(). Also
// used when an entity changes its type. For an entity that someone interacts
// with others, make sure it can no longer do so.
- void Ent_Remove()
+ void Ent_Remove(entity this)
{
- if(self.entremove)
- self.entremove();
+ if(this.entremove) this.entremove(this);
- if(self.skeletonindex)
+ if(this.skeletonindex)
{
- skel_delete(self.skeletonindex);
- self.skeletonindex = 0;
+ skel_delete(this.skeletonindex);
+ this.skeletonindex = 0;
}
- if(self.snd_looping > 0)
+ if(this.snd_looping > 0)
{
- sound(self, self.snd_looping, "misc/null.wav", VOL_BASE, autocvar_g_jetpack_attenuation);
- self.snd_looping = 0;
+ sound(this, this.snd_looping, SND_Null, VOL_BASE, autocvar_g_jetpack_attenuation);
+ this.snd_looping = 0;
}
- self.enttype = 0;
- self.classname = "";
- self.draw = menu_sub_null;
- self.entremove = menu_sub_null;
+ this.enttype = 0;
+ this.classname = "";
+ this.draw = func_null;
+ this.entremove = func_null;
// TODO possibly set more stuff to defaults
}
- // CSQC_Ent_Remove : Called when the server requests a SSQC / CSQC entity to be removed. Essentially call remove(self) as well.
+ // CSQC_Ent_Remove : Called when the server requests a SSQC / CSQC entity to be removed. Essentially call remove(this) as well.
void CSQC_Ent_Remove()
- {
- if(autocvar_developer_csqcentities)
- printf("CSQC_Ent_Remove() with self=%i self.entnum=%d self.enttype=%d\n", self, self.entnum, self.enttype);
-
- if(wasfreed(self))
+ {ENGINE_EVENT();
+ if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Ent_Remove() with this=%i {.entnum=%d, .enttype=%d}\n", this, this.entnum, this.enttype);
+ if (wasfreed(this))
{
- print("WARNING: CSQC_Ent_Remove called for already removed entity. Packet loss?\n");
+ LOG_WARNING("CSQC_Ent_Remove called for already removed entity. Packet loss?\n");
return;
}
- if(self.enttype)
- Ent_Remove();
- remove(self);
+ if (this.enttype) Ent_Remove(this);
+ remove(this);
}
void Gamemode_Init()
// CSQC_Parse_StuffCmd : Provides the stuffcmd string in the first parameter that the server provided. To execute standard behavior, simply execute localcmd with the string.
void CSQC_Parse_StuffCmd(string strMessage)
{
- if(autocvar_developer_csqcentities)
- printf("CSQC_Parse_StuffCmd(\"%s\")\n", strMessage);
-
+ if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Parse_StuffCmd(\"%s\")\n", strMessage);
localcmd(strMessage);
}
// CSQC_Parse_Print : Provides the print string in the first parameter that the server provided. To execute standard behavior, simply execute print with the string.
void CSQC_Parse_Print(string strMessage)
{
- if(autocvar_developer_csqcentities)
- printf("CSQC_Parse_Print(\"%s\")\n", strMessage);
-
+ if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Parse_Print(\"%s\")\n", strMessage);
print(ColorTranslateRGB(strMessage));
}
// CSQC_Parse_CenterPrint : Provides the centerprint_hud string in the first parameter that the server provided.
void CSQC_Parse_CenterPrint(string strMessage)
{
- if(autocvar_developer_csqcentities)
- printf("CSQC_Parse_CenterPrint(\"%s\")\n", strMessage);
-
+ if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Parse_CenterPrint(\"%s\")\n", strMessage);
centerprint_hud(strMessage);
}
- string notranslate_fogcmd1 = "\nfog ";
- string notranslate_fogcmd2 = "\nr_fog_exp2 0\nr_drawfog 1\n";
- void Fog_Force()
+ // CSQC_Parse_TempEntity : Handles all temporary entity network data in the CSQC layer.
+ // You must ALWAYS first acquire the temporary ID, which is sent as a byte.
+ // Return value should be 1 if CSQC handled the temporary entity, otherwise return 0 to have the engine process the event.
+ bool CSQC_Parse_TempEntity()
{
- // TODO somehow thwart prvm_globalset client ...
+ // Acquire TE ID
+ int nTEID = ReadByte();
+
+ FOREACH(TempEntities, it.m_id == nTEID, {
+ if (autocvar_developer_csqcentities)
+ LOG_INFOF("CSQC_Parse_TempEntity() nTEID=%s (%d)\n", it.netname, nTEID);
+ return it.m_read(NULL, NULL, true);
+ });
+
+ if (autocvar_developer_csqcentities)
+ LOG_INFOF("CSQC_Parse_TempEntity() with nTEID=%d\n", nTEID);
+
+ // No special logic for this temporary entity; return 0 so the engine can handle it
+ return false;
+ }
- if(autocvar_cl_orthoview && autocvar_cl_orthoview_nofog)
- { localcmd("\nr_drawfog 0\n"); }
- else if(forcefog != "")
- { localcmd(strcat(notranslate_fogcmd1, forcefog, notranslate_fogcmd2)); }
+ string forcefog;
+ void Fog_Force()
+ {
+ if (autocvar_cl_orthoview && autocvar_cl_orthoview_nofog)
+ localcmd("\nr_drawfog 0\n");
+ else if (forcefog != "")
+ localcmd(sprintf("\nfog %s\nr_fog_exp2 0\nr_drawfog 1\n", forcefog));
}
void Gamemode_Init();
- void Ent_ScoresInfo()
+ NET_HANDLE(ENT_CLIENT_SCORES_INFO, bool isnew)
{
- int i;
- self.classname = "ent_client_scores_info";
+ make_pure(this);
gametype = ReadInt24_t();
HUD_ModIcons_SetFunc();
- for(i = 0; i < MAX_SCORE; ++i)
+ for (int i = 0; i < MAX_SCORE; ++i)
{
- if(scores_label[i])
- strunzone(scores_label[i]);
+ if (scores_label[i]) strunzone(scores_label[i]);
scores_label[i] = strzone(ReadString());
scores_flags[i] = ReadByte();
}
- for(i = 0; i < MAX_TEAMSCORE; ++i)
+ for (int i = 0; i < MAX_TEAMSCORE; ++i)
{
- if(teamscores_label[i])
- strunzone(teamscores_label[i]);
+ if (teamscores_label[i]) strunzone(teamscores_label[i]);
teamscores_label[i] = strzone(ReadString());
teamscores_flags[i] = ReadByte();
}
+ return = true;
HUD_InitScores();
Gamemode_Init();
}
- void Ent_Init()
+ NET_HANDLE(ENT_CLIENT_INIT, bool isnew)
{
- self.classname = "ent_client_init";
-
nb_pb_period = ReadByte() / 32; //Accuracy of 1/32th
hook_shotorigin[0] = decompressShotOrigin(ReadInt24_t());
arc_shotorigin[2] = decompressShotOrigin(ReadInt24_t());
arc_shotorigin[3] = decompressShotOrigin(ReadInt24_t());
- if(forcefog)
- strunzone(forcefog);
+ if (forcefog) strunzone(forcefog);
forcefog = strzone(ReadString());
armorblockpercent = ReadByte() / 255.0;
- g_balance_mortar_bouncefactor = ReadCoord();
- g_balance_mortar_bouncestop = ReadCoord();
- g_balance_electro_secondary_bouncefactor = ReadCoord();
- g_balance_electro_secondary_bouncestop = ReadCoord();
-
- vortex_scope = !ReadByte();
- rifle_scope = !ReadByte();
-
serverflags = ReadByte();
- minelayer_maxmines = ReadByte();
+ g_trueaim_minrange = ReadCoord();
- hagar_maxrockets = ReadByte();
+ return = true;
- g_trueaim_minrange = ReadCoord();
- g_balance_porto_secondary = ReadByte();
+ MUTATOR_CALLHOOK(Ent_Init);
- if(!postinit)
- PostInit();
+ if (!postinit) PostInit();
}
- void Net_ReadRace()
+ NET_HANDLE(TE_CSQC_RACE, bool isNew)
{
- float b;
+ int b = ReadByte();
- b = ReadByte();
-
- switch(b)
+ switch (b)
{
case RACE_NET_CHECKPOINT_HIT_QUALIFYING:
race_checkpoint = ReadByte();
strunzone(grecordholder[pos-1]);
grecordholder[pos-1] = strzone(ReadString());
grecordtime[pos-1] = ReadInt24_t();
- if(grecordholder[pos-1] == GetPlayerName(player_localnum))
+ if(grecordholder[pos-1] == entcs_GetName(player_localnum))
race_myrank = pos;
break;
case RACE_NET_SERVER_STATUS:
strunzone(race_status_name);
race_status_name = strzone(ReadString());
}
+ return true;
}
- void Net_TeamNagger()
+ NET_HANDLE(TE_CSQC_TEAMNAGGER, bool isNew)
{
teamnagger = 1;
+ return true;
}
- void Net_ReadPingPLReport()
+ NET_HANDLE(TE_CSQC_PINGPLREPORT, bool isNew)
{
- int e, pi, pl, ml;
- e = ReadByte();
- pi = ReadShort();
- pl = ReadByte();
- ml = ReadByte();
- if (!(playerslots[e]))
- return;
- playerslots[e].ping = pi;
- playerslots[e].ping_packetloss = pl / 255.0;
- playerslots[e].ping_movementloss = ml / 255.0;
+ int i = ReadByte();
+ int pi = ReadShort();
+ int pl = ReadByte();
+ int ml = ReadByte();
+ return = true;
+ entity e = playerslots[i];
+ if (!e) return;
+ e.ping = pi;
+ e.ping_packetloss = pl / 255.0;
+ e.ping_movementloss = ml / 255.0;
}
- void Net_WeaponComplain()
+ NET_HANDLE(TE_CSQC_WEAPONCOMPLAIN, bool isNew)
{
complain_weapon = ReadByte();
-
- if(complain_weapon_name)
- strunzone(complain_weapon_name);
- complain_weapon_name = strzone(WEP_NAME(complain_weapon));
-
complain_weapon_type = ReadByte();
+ return = true;
complain_weapon_time = time;
weapontime = time; // ping the weapon panel
}
}
- // CSQC_Parse_TempEntity : Handles all temporary entity network data in the CSQC layer.
- // You must ALWAYS first acquire the temporary ID, which is sent as a byte.
- // Return value should be 1 if CSQC handled the temporary entity, otherwise return 0 to have the engine process the event.
- float CSQC_Parse_TempEntity()
- {
- float bHandled;
- bHandled = true;
- // Acquire TE ID
- float nTEID;
- nTEID = ReadByte();
-
- if(autocvar_developer_csqcentities)
- printf("CSQC_Parse_TempEntity() with nTEID=%d\n", nTEID);
-
- // NOTE: Could just do return instead of break...
- switch(nTEID)
- {
- case TE_CSQC_TARGET_MUSIC:
- Net_TargetMusic();
- bHandled = true;
- break;
- case TE_CSQC_PICTURE:
- Net_MapVote_Picture();
- bHandled = true;
- break;
- case TE_CSQC_RACE:
- Net_ReadRace();
- bHandled = true;
- break;
- case TE_CSQC_VORTEXBEAMPARTICLE:
- Net_ReadVortexBeamParticle();
- bHandled = true;
- break;
- case TE_CSQC_TEAMNAGGER:
- Net_TeamNagger();
- bHandled = true;
- break;
- case TE_CSQC_ARC:
- Net_ReadArc();
- bHandled = true;
- break;
- case TE_CSQC_PINGPLREPORT:
- Net_ReadPingPLReport();
- bHandled = true;
- break;
- case TE_CSQC_WEAPONCOMPLAIN:
- Net_WeaponComplain();
- bHandled = true;
- break;
- case TE_CSQC_VEHICLESETUP:
- Net_VehicleSetup();
- bHandled = true;
- break;
- case TE_CSQC_SVNOTICE:
- cl_notice_read();
- bHandled = true;
- break;
- case TE_CSQC_SHOCKWAVEPARTICLE:
- Net_ReadShockwaveParticle();
- bHandled = true;
- break;
- default:
- // No special logic for this temporary entity; return 0 so the engine can handle it
- bHandled = false;
- break;
- }
-
- return bHandled;
- }
-
string getcommandkey(string text, string command)
{
string keys;
keys = db_get(binddb, command);
if (keys == "")
{
+ bool joy_detected = cvar("joy_detected");
n = tokenize(findkeysforcommand(command, 0)); // uses '...' strings
for(j = 0; j < n; ++j)
{
k = stof(argv(j));
if(k != -1)
{
- if ("" == keys)
- keys = keynumtostring(k);
+ string key = keynumtostring(k);
+ if(!joy_detected && substring(key, 0, 3) == "JOY")
+ continue;
+
+ if (keys == "")
+ keys = key;
else
- keys = strcat(keys, ", ", keynumtostring(k));
+ keys = strcat(keys, ", ", key);
++l;
if (autocvar_hud_showbinds_limit > 0 && autocvar_hud_showbinds_limit <= l)
- #include "waypointsprites.qh"
+ #include "cl_client.qh"
+ #include "anticheat.qh"
#include "cl_impulse.qh"
#include "cl_player.qh"
- #include "ent_cs.qh"
- #include "g_subs.qh"
#include "ipban.qh"
#include "miscfunctions.qh"
#include "portals.qh"
#include "teamplay.qh"
#include "playerdemo.qh"
- #include "secret.qh"
+ #include "spawnpoints.qh"
+ #include "g_damage.qh"
+ #include "g_hook.qh"
+ #include "command/common.qh"
+ #include "cheats.qh"
+ #include "g_world.qh"
+ #include "race.qh"
+ #include "antilag.qh"
+ #include "campaign.qh"
+ #include "command/common.qh"
#include "bot/bot.qh"
#include "bot/navigation.qh"
+ #include "../common/ent_cs.qh"
+ #include <common/state.qh>
+
+ #include <common/effects/qc/globalsound.qh>
+
+ #include "../common/triggers/teleporters.qh"
+
+ #include "../common/vehicles/all.qh"
+
#include "weapons/hitplot.qh"
#include "weapons/weaponsystem.qh"
#include "../common/net_notice.qh"
+ #include "../common/physics/player.qh"
+
+ #include "../common/items/all.qc"
+
+ #include "../common/mutators/mutator/waypoints/all.qh"
+
+ #include "../common/triggers/subs.qh"
+ #include "../common/triggers/triggers.qh"
+ #include "../common/triggers/trigger/secret.qh"
+
+ #include "../common/minigames/sv_minigames.qh"
+
+ #include "../common/items/inventory.qh"
#include "../common/monsters/sv_monsters.qh"
- #include "../warpzonelib/server.qh"
+ #include "../lib/warpzone/server.qh"
+
+ STATIC_METHOD(Client, Add, void(Client this, int _team))
+ {
+ WITHSELF(this, ClientConnect());
+ TRANSMUTE(Player, this);
+ this.frame = 12; // 7
+ this.team = _team;
+ WITHSELF(this, PutClientInServer());
+ }
+
+ void PutObserverInServer(entity this);
+ void ClientDisconnect();
- float c1, c2, c3, c4;
+ STATIC_METHOD(Client, Remove, void(Client this))
+ {
+ TRANSMUTE(Observer, this);
+ WITHSELF(this, PutClientInServer());
+ WITHSELF(this, ClientDisconnect());
+ }
void send_CSQC_teamnagger() {
- WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
- WriteByte(MSG_BROADCAST, TE_CSQC_TEAMNAGGER);
+ WriteHeader(MSG_BROADCAST, TE_CSQC_TEAMNAGGER);
}
- entity head;
- float spec_count = 0;
- FOR_EACH_REALCLIENT(head)
+int CountSpectators(entity player, entity to)
+{
+ if(!player) { return 0; } // not sure how, but best to be safe
+
- if(IS_SPEC(head))
- if(head != to)
- if(head.enemy == player)
- spec_count += 1;
- }
++ int spec_count = 0;
++
++ FOREACH_CLIENT(IS_REAL_CLIENT(it) && IS_SPEC(it) && it != to && it.enemy == player,
+ {
- entity head;
- FOR_EACH_REALCLIENT(head)
++ spec_count++;
++ });
+
+ return spec_count;
+}
+
+void WriteSpectators(entity player, entity to)
+{
+ if(!player) { return; } // not sure how, but best to be safe
+
- if(IS_SPEC(head))
- if(head != to)
- if(head.enemy == player)
- WriteByte(MSG_ENTITY, num_for_edict(head));
- }
++ FOREACH_CLIENT(IS_REAL_CLIENT(it) && IS_SPEC(it) && it != to && it.enemy == player,
+ {
- bool ClientData_Send(entity to, int sf)
++ WriteByte(MSG_ENTITY, num_for_edict(it));
++ });
+}
+
+ bool ClientData_Send(entity this, entity to, int sf)
{
- if(to != self.owner)
- {
- error("wtf");
- return false;
- }
+ assert(to == this.owner, return false);
- entity e;
-
- e = to;
- if(IS_SPEC(to))
- e = to.enemy;
+ entity e = to;
+ if (IS_SPEC(e)) e = e.enemy;
sf = 0;
+ 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
++ sf |= 16; // always check spectators
- 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
- // always check spectators
- sf |= 16; // spectator handling?
-
- WriteByte(MSG_ENTITY, ENT_CLIENT_CLIENTDATA);
+ WriteHeader(MSG_ENTITY, ENT_CLIENT_CLIENTDATA);
WriteByte(MSG_ENTITY, sf);
- if(sf & 2)
+ if (sf & 2)
+ {
WriteByte(MSG_ENTITY, to.spectatee_status);
-
- if(sf & 8)
+ }
+ if (sf & 8)
{
WriteAngle(MSG_ENTITY, e.v_angle.x);
WriteAngle(MSG_ENTITY, e.v_angle.y);
}
+
+ if(sf & 16)
+ {
+ float specs = CountSpectators(e, to);
+ WriteByte(MSG_ENTITY, specs);
+ WriteSpectators(e, to);
+ }
+
return true;
}
- void ClientData_Attach()
+ void ClientData_Attach(entity this)
{
- Net_LinkEntity(self.clientdata = spawn(), false, 0, ClientData_Send);
- self.clientdata.drawonlytoclient = self;
- self.clientdata.owner = self;
+ Net_LinkEntity(this.clientdata = new_pure(clientdata), false, 0, ClientData_Send);
+ this.clientdata.drawonlytoclient = this;
+ this.clientdata.owner = this;
}
- void ClientData_Detach()
+ void ClientData_Detach(entity this)
{
- remove(self.clientdata);
- self.clientdata = world;
+ remove(this.clientdata);
+ this.clientdata = NULL;
}
void ClientData_Touch(entity e)
e.clientdata.SendFlags = 1;
// make it spectatable
- entity e2;
- FOR_EACH_REALCLIENT(e2)
- {
- if(e2 != e)
- if(IS_SPEC(e2))
- if(e2.enemy == e)
- e2.clientdata.SendFlags = 1;
- }
+ FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != e && IS_SPEC(it) && it.enemy == e, LAMBDA(it.clientdata.SendFlags = 1));
}
.string netname_previous;
- void SetSpectator(entity player, entity spectatee);
+ void SetSpectatee(entity player, entity spectatee);
/*
void setplayermodel(entity e, string modelname)
{
precache_model(modelname);
- setmodel(e, modelname);
- player_setupanimsformodel();
- UpdatePlayerSounds();
+ _setmodel(e, modelname);
+ player_setupanimsformodel(e);
+ if(!autocvar_g_debug_globalsounds)
+ UpdatePlayerSounds(e);
}
- /*
- =============
- PutObserverInServer
-
- putting a client as observer in the server
- =============
- */
- void FixPlayermodel();
- void PutObserverInServer (void)
+ void FixPlayermodel(entity player);
+ /** putting a client as observer in the server */
+ void PutObserverInServer(entity this)
{
- entity spot;
-
- SetSpectator(self, world);
-
- self.hud = HUD_NORMAL;
-
- if(IS_PLAYER(self)) { pointparticles(particleeffectnum("spawn_event_neutral"), self.origin, '0 0 0', 1); }
+ bool mutator_returnvalue = MUTATOR_CALLHOOK(MakePlayerObserver, this);
+ PlayerState_detach(this);
- spot = SelectSpawnPoint (true);
- if(!spot)
- error("No spawnpoints for observers?!?\n");
- RemoveGrapplingHook(self); // Wazat's Grappling Hook
-
- if(IS_REAL_CLIENT(self))
- {
- msg_entity = self;
- WriteByte(MSG_ONE, SVC_SETVIEW);
- WriteEntity(MSG_ONE, self);
- }
-
- self.frags = FRAGS_SPECTATOR;
-
- MUTATOR_CALLHOOK(MakePlayerObserver);
+ if (IS_PLAYER(this) && this.health >= 1) {
+ // despawn effect
+ Send_Effect(EFFECT_SPAWN_NEUTRAL, this.origin, '0 0 0', 1);
+ }
- Portal_ClearAll(self);
+ {
+ entity spot = SelectSpawnPoint(this, true);
+ if (!spot) LOG_FATAL("No spawnpoints for observers?!?");
+ this.angles = spot.angles;
+ this.angles_z = 0;
+ this.fixangle = true;
+ // offset it so that the spectator spawns higher off the ground, looks better this way
+ setorigin(this, spot.origin + STAT(PL_VIEW_OFS, NULL));
+ this.prevorigin = this.origin;
+ if (IS_REAL_CLIENT(this))
+ {
+ msg_entity = this;
+ WriteByte(MSG_ONE, SVC_SETVIEW);
+ WriteEntity(MSG_ONE, this);
+ }
+ // give the spectator some space between walls for MOVETYPE_FLY_WORLDONLY
+ // so that your view doesn't go into the ceiling with MOVETYPE_FLY_WORLDONLY, previously "PL_VIEW_OFS"
+ if(!autocvar_g_debug_globalsounds)
+ {
+ // needed for player sounds
+ this.model = "";
+ FixPlayermodel(this);
+ }
+ setmodel(this, MDL_Null);
+ setsize(this, STAT(PL_CROUCH_MIN, NULL), STAT(PL_CROUCH_MAX, NULL));
+ this.view_ofs = '0 0 0';
+ }
- Unfreeze(self);
+ RemoveGrapplingHook(this);
+ Portal_ClearAll(this);
+ Unfreeze(this);
++ SetSpectatee(this, world);
- if(self.alivetime)
+ if (this.alivetime)
{
- if(!warmup_stage)
- PS_GR_P_ADDVAL(self, PLAYERSTATS_ALIVETIME, time - self.alivetime);
- self.alivetime = 0;
+ if (!warmup_stage)
+ PS_GR_P_ADDVAL(this, PLAYERSTATS_ALIVETIME, time - this.alivetime);
+ this.alivetime = 0;
}
- if(self.vehicle)
- vehicles_exit(VHEF_RELESE);
+ if (this.vehicle) vehicles_exit(this.vehicle, VHEF_RELEASE);
- WaypointSprite_PlayerDead();
+ WaypointSprite_PlayerDead(this);
- if (!g_ca) // don't reset teams when moving a ca player to the spectators
- self.team = -1; // move this as it is needed to log the player spectating in eventlog
+ if (mutator_returnvalue) {
+ // mutator prevents resetting teams+score
+ } else {
+ this.team = -1; // move this as it is needed to log the player spectating in eventlog
+ this.frags = FRAGS_SPECTATOR;
+ PlayerScore_Clear(this); // clear scores when needed
+ }
- if(self.killcount != -666)
+ if (this.killcount != FRAGS_SPECTATOR)
{
- Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_QUIT_SPECTATE, self.netname);
- if(autocvar_g_chat_nospectators == 1 || (cvar("g_warmup") && !(warmup_stage || gameover) && autocvar_g_chat_nospectators == 2))
- Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_CHAT_NOSPECTATORS);
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_QUIT_SPECTATE, this.netname);
+ if(!intermission_running)
+ if(autocvar_g_chat_nospectators == 1 || (!(warmup_stage || gameover) && autocvar_g_chat_nospectators == 2))
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_CHAT_NOSPECTATORS);
- if(self.just_joined == false) {
- LogTeamchange(self.playerid, -1, 4);
+ if(this.just_joined == false) {
+ LogTeamchange(this.playerid, -1, 4);
} else
- self.just_joined = false;
- }
-
- PlayerScore_Clear(self); // clear scores when needed
-
- accuracy_resend(self);
-
- self.spectatortime = time;
-
- self.classname = "observer";
- self.iscreature = false;
- self.teleportable = TELEPORT_SIMPLE;
- self.damagedbycontents = false;
- self.health = -666;
- self.takedamage = DAMAGE_NO;
- self.solid = SOLID_NOT;
- self.movetype = MOVETYPE_FLY_WORLDONLY; // user preference is controlled by playerprethink
- self.flags = FL_CLIENT | FL_NOTARGET;
- self.armorvalue = 666;
- self.effects = 0;
- self.armorvalue = autocvar_g_balance_armor_start;
- self.pauserotarmor_finished = 0;
- self.pauserothealth_finished = 0;
- self.pauseregen_finished = 0;
- self.damageforcescale = 0;
- self.death_time = 0;
- self.respawn_flags = 0;
- self.respawn_time = 0;
- self.stat_respawn_time = 0;
- self.alpha = 0;
- self.scale = 0;
- self.fade_time = 0;
- self.pain_frame = 0;
- self.pain_finished = 0;
- self.strength_finished = 0;
- self.invincible_finished = 0;
- self.superweapons_finished = 0;
- self.pushltime = 0;
- self.istypefrag = 0;
- self.think = func_null;
- self.nextthink = 0;
- self.hook_time = 0;
- self.deadflag = DEAD_NO;
- self.angles = spot.angles;
- self.angles_z = 0;
- self.fixangle = true;
- self.crouch = false;
- self.revival_time = 0;
-
- setorigin (self, (spot.origin + PL_VIEW_OFS)); // offset it so that the spectator spawns higher off the ground, looks better this way
- self.prevorigin = self.origin;
- self.items = 0;
- self.weapons = '0 0 0';
- self.model = "";
- FixPlayermodel();
- setmodel(self, "null");
- self.drawonlytoclient = self;
-
- setsize (self, PL_CROUCH_MIN, PL_CROUCH_MAX); // give the spectator some space between walls for MOVETYPE_FLY_WORLDONLY
- self.view_ofs = '0 0 0'; // so that your view doesn't go into the ceiling with MOVETYPE_FLY_WORLDONLY, previously "PL_VIEW_OFS"
-
- self.weapon = 0;
- self.weaponname = "";
- self.switchingweapon = 0;
- self.weaponmodel = "";
- self.weaponentity = world;
- self.exteriorweaponentity = world;
- self.killcount = -666;
- self.velocity = '0 0 0';
- self.avelocity = '0 0 0';
- self.punchangle = '0 0 0';
- self.punchvector = '0 0 0';
- self.oldvelocity = self.velocity;
- self.fire_endtime = -1;
- self.event_damage = func_null;
+ this.just_joined = false;
+ }
+
+ accuracy_resend(this);
+
+ this.spectatortime = time;
+ this.bot_attack = false;
+ this.hud = HUD_NORMAL;
+ TRANSMUTE(Observer, this);
+ this.iscreature = false;
+ this.teleportable = TELEPORT_SIMPLE;
+ this.damagedbycontents = false;
+ this.health = FRAGS_SPECTATOR;
+ this.takedamage = DAMAGE_NO;
+ this.solid = SOLID_NOT;
+ this.movetype = MOVETYPE_FLY_WORLDONLY; // user preference is controlled by playerprethink
+ this.flags = FL_CLIENT | FL_NOTARGET;
+ this.armorvalue = 666;
+ this.effects = 0;
+ this.armorvalue = autocvar_g_balance_armor_start;
+ this.pauserotarmor_finished = 0;
+ this.pauserothealth_finished = 0;
+ this.pauseregen_finished = 0;
+ this.damageforcescale = 0;
+ this.death_time = 0;
+ this.respawn_flags = 0;
+ this.respawn_time = 0;
+ this.stat_respawn_time = 0;
+ this.alpha = 0;
+ this.scale = 0;
+ this.fade_time = 0;
+ this.pain_frame = 0;
+ this.pain_finished = 0;
+ this.strength_finished = 0;
+ this.invincible_finished = 0;
+ this.superweapons_finished = 0;
+ this.pushltime = 0;
+ this.istypefrag = 0;
+ setthink(this, func_null);
+ this.nextthink = 0;
+ this.hook_time = 0;
+ this.deadflag = DEAD_NO;
+ this.crouch = false;
+ this.revival_time = 0;
+
+ this.items = 0;
+ this.weapons = '0 0 0';
+ this.drawonlytoclient = this;
+
+ this.weaponname = "";
+ this.weaponmodel = "";
+ for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ this.weaponentities[slot] = NULL;
+ }
+ this.exteriorweaponentity = NULL;
+ this.killcount = FRAGS_SPECTATOR;
+ this.velocity = '0 0 0';
+ this.avelocity = '0 0 0';
+ this.punchangle = '0 0 0';
+ this.punchvector = '0 0 0';
+ this.oldvelocity = this.velocity;
+ this.fire_endtime = -1;
+ this.event_damage = func_null;
}
- .float model_randomizer;
- void FixPlayermodel()
+ int player_getspecies(entity this)
{
- string defaultmodel;
- float defaultskin, chmdl, oldskin, n, i;
- vector m1, m2;
-
- defaultmodel = "";
- defaultskin = 0;
- chmdl = false;
+ get_model_parameters(this.model, this.skin);
+ int s = get_model_parameters_species;
+ get_model_parameters(string_null, 0);
+ if (s < 0) return SPECIES_HUMAN;
+ return s;
+ }
- if(autocvar_sv_defaultcharacter == 1)
+ .float model_randomizer;
+ void FixPlayermodel(entity player)
+ {
+ string defaultmodel = "";
+ int defaultskin = 0;
+ if(autocvar_sv_defaultcharacter)
{
if(teamplay)
{
- string s;
- s = Static_Team_ColorName_Lower(self.team);
- if(s != "neutral")
+ string s = Static_Team_ColorName_Lower(player.team);
+ if (s != "neutral")
{
defaultmodel = cvar_string(strcat("sv_defaultplayermodel_", s));
defaultskin = cvar(strcat("sv_defaultplayerskin_", s));
defaultskin = autocvar_sv_defaultplayerskin;
}
- n = tokenize_console(defaultmodel);
+ int n = tokenize_console(defaultmodel);
if(n > 0)
{
- defaultmodel = argv(floor(n * self.model_randomizer));
+ defaultmodel = argv(floor(n * player.model_randomizer));
// However, do NOT randomize if the player-selected model is in the list.
- for (i = 0; i < n; ++i)
- if ((argv(i) == self.playermodel && defaultskin == stof(self.playerskin)) || argv(i) == strcat(self.playermodel, ":", self.playerskin))
+ for (int i = 0; i < n; ++i)
+ if ((argv(i) == player.playermodel && defaultskin == stof(player.playerskin)) || argv(i) == strcat(player.playermodel, ":", player.playerskin))
defaultmodel = argv(i);
}
- i = strstrofs(defaultmodel, ":", 0);
+ int i = strstrofs(defaultmodel, ":", 0);
if(i >= 0)
{
defaultskin = stof(substring(defaultmodel, i+1, -1));
defaultmodel = substring(defaultmodel, 0, i);
}
}
+ if(autocvar_sv_defaultcharacterskin && !defaultskin)
+ {
+ if(teamplay)
+ {
+ string s = Static_Team_ColorName_Lower(player.team);
+ if (s != "neutral")
+ defaultskin = cvar(strcat("sv_defaultplayerskin_", s));
+ }
+
+ if(!defaultskin)
+ defaultskin = autocvar_sv_defaultplayerskin;
+ }
+ MUTATOR_CALLHOOK(FixPlayermodel, defaultmodel, defaultskin, player);
+ defaultmodel = M_ARGV(0, string);
+ defaultskin = M_ARGV(1, int);
+
+ bool chmdl = false;
+ int oldskin;
if(defaultmodel != "")
{
- if (defaultmodel != self.model)
+ if (defaultmodel != player.model)
{
- m1 = self.mins;
- m2 = self.maxs;
- setplayermodel (self, defaultmodel);
- setsize (self, m1, m2);
+ vector m1 = player.mins;
+ vector m2 = player.maxs;
+ setplayermodel (player, defaultmodel);
+ setsize (player, m1, m2);
chmdl = true;
}
- oldskin = self.skin;
- self.skin = defaultskin;
+ oldskin = player.skin;
+ player.skin = defaultskin;
} else {
- if (self.playermodel != self.model || self.playermodel == "")
+ if (player.playermodel != player.model || player.playermodel == "")
{
- self.playermodel = CheckPlayerModel(self.playermodel); // this is never "", so no endless loop
- m1 = self.mins;
- m2 = self.maxs;
- setplayermodel (self, self.playermodel);
- setsize (self, m1, m2);
+ player.playermodel = CheckPlayerModel(player.playermodel); // this is never "", so no endless loop
+ vector m1 = player.mins;
+ vector m2 = player.maxs;
+ setplayermodel (player, player.playermodel);
+ setsize (player, m1, m2);
chmdl = true;
}
- oldskin = self.skin;
- self.skin = stof(self.playerskin);
+ if(!autocvar_sv_defaultcharacterskin)
+ {
+ oldskin = player.skin;
+ player.skin = stof(player.playerskin);
+ }
+ else
+ {
+ oldskin = player.skin;
+ player.skin = defaultskin;
+ }
}
- if(chmdl || oldskin != self.skin) // model or skin has changed
+ if(chmdl || oldskin != player.skin) // model or skin has changed
{
- self.species = player_getspecies(); // update species
- UpdatePlayerSounds(); // update skin sounds
+ player.species = player_getspecies(player); // update species
+ if(!autocvar_g_debug_globalsounds)
+ UpdatePlayerSounds(player); // update skin sounds
}
if(!teamplay)
if(strlen(autocvar_sv_defaultplayercolors))
- if(self.clientcolors != stof(autocvar_sv_defaultplayercolors))
- setcolor(self, stof(autocvar_sv_defaultplayercolors));
+ if(player.clientcolors != stof(autocvar_sv_defaultplayercolors))
+ setcolor(player, stof(autocvar_sv_defaultplayercolors));
}
- /*
- =============
- PutClientInServer
- Called when a client spawns in the server
- =============
- */
- void PutClientInServer (void)
- {
- if(IS_BOT_CLIENT(self))
- self.classname = "player";
- else if(IS_REAL_CLIENT(self))
- {
- msg_entity = self;
+ /** Called when a client spawns in the server */
+ void PutClientInServer()
+ {ENGINE_EVENT();
+ if (IS_BOT_CLIENT(this)) {
+ TRANSMUTE(Player, this);
+ } else if (IS_REAL_CLIENT(this)) {
+ msg_entity = this;
WriteByte(MSG_ONE, SVC_SETVIEW);
- WriteEntity(MSG_ONE, self);
+ WriteEntity(MSG_ONE, this);
+ }
+ if (gameover) {
+ TRANSMUTE(Observer, this);
}
- SetSpectator(self, world);
+ SetSpectatee(this, NULL);
// reset player keys
- self.itemkeys = 0;
-
- MUTATOR_CALLHOOK(PutClientInServer);
-
- if(gameover)
- self.classname = "observer";
+ this.itemkeys = 0;
- if(IS_PLAYER(self))
- {
- entity spot, oldself;
- float j;
+ MUTATOR_CALLHOOK(PutClientInServer, this);
- accuracy_resend(self);
+ if (IS_OBSERVER(this)) {
+ PutObserverInServer(this);
+ } else if (IS_PLAYER(this)) {
+ PlayerState_attach(this);
+ accuracy_resend(this);
- if(self.team < 0)
- JoinBestTeam(self, false, true);
+ if (this.team < 0)
+ JoinBestTeam(this, false, true);
- spot = SelectSpawnPoint (false);
- if(!spot)
- {
- Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_JOIN_NOSPAWNS);
+ entity spot = SelectSpawnPoint(this, false);
+ if (!spot) {
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_JOIN_NOSPAWNS);
return; // spawn failed
}
- RemoveGrapplingHook(self); // Wazat's Grappling Hook
-
- if(self.vehicle)
- vehicles_exit(VHEF_RELESE);
-
- self.classname = "player";
- self.wasplayer = true;
- self.iscreature = true;
- self.teleportable = TELEPORT_NORMAL;
- self.damagedbycontents = true;
- self.movetype = MOVETYPE_WALK;
- self.solid = SOLID_SLIDEBOX;
- self.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_SOLID;
- if(autocvar_g_playerclip_collisions)
- self.dphitcontentsmask |= DPCONTENTS_PLAYERCLIP;
- if(IS_BOT_CLIENT(self) && autocvar_g_botclip_collisions)
- self.dphitcontentsmask |= DPCONTENTS_BOTCLIP;
- self.frags = FRAGS_PLAYER;
- if(INDEPENDENT_PLAYERS)
- MAKE_INDEPENDENT_PLAYER(self);
- self.flags = FL_CLIENT;
- if(autocvar__notarget)
- self.flags |= FL_NOTARGET;
- self.takedamage = DAMAGE_AIM;
- self.effects = 0;
- self.effects |= EF_TELEPORT_BIT | EF_RESTARTANIM_BIT;
- self.air_finished = time + 12;
- self.dmg = 2;
- if(WEP_CVAR(vortex, charge))
- {
- if(WEP_CVAR_SEC(vortex, chargepool))
- self.vortex_chargepool_ammo = 1;
- self.vortex_charge = WEP_CVAR(vortex, charge_start);
- }
-
- if(warmup_stage)
- {
- self.ammo_shells = warmup_start_ammo_shells;
- self.ammo_nails = warmup_start_ammo_nails;
- self.ammo_rockets = warmup_start_ammo_rockets;
- self.ammo_cells = warmup_start_ammo_cells;
- self.ammo_plasma = warmup_start_ammo_plasma;
- self.ammo_fuel = warmup_start_ammo_fuel;
- self.health = warmup_start_health;
- self.armorvalue = warmup_start_armorvalue;
- self.weapons = WARMUP_START_WEAPONS;
- }
- else
- {
- self.ammo_shells = start_ammo_shells;
- self.ammo_nails = start_ammo_nails;
- self.ammo_rockets = start_ammo_rockets;
- self.ammo_cells = start_ammo_cells;
- self.ammo_plasma = start_ammo_plasma;
- self.ammo_fuel = start_ammo_fuel;
- self.health = start_health;
- self.armorvalue = start_armorvalue;
- self.weapons = start_weapons;
- }
-
- if(self.weapons & WEPSET_SUPERWEAPONS)
- self.superweapons_finished = time + autocvar_g_balance_superweapons_time;
- else
- self.superweapons_finished = 0;
-
- if(g_weaponarena_random) // WEAPONTODO: more stuff that should be in a mutator. also: rename those cvars
- {
- if(g_weaponarena_random_with_blaster)
- self.weapons &= ~WEPSET_BLASTER;
- W_RandomWeapons(self, g_weaponarena_random);
- if(g_weaponarena_random_with_blaster)
- self.weapons |= WEPSET_BLASTER;
+ TRANSMUTE(Player, this);
+ this.wasplayer = true;
+ this.iscreature = true;
+ this.teleportable = TELEPORT_NORMAL;
+ this.damagedbycontents = true;
+ this.movetype = MOVETYPE_WALK;
+ this.solid = SOLID_SLIDEBOX;
+ this.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_SOLID;
+ if (autocvar_g_playerclip_collisions)
+ this.dphitcontentsmask |= DPCONTENTS_PLAYERCLIP;
+ if (IS_BOT_CLIENT(this) && autocvar_g_botclip_collisions)
+ this.dphitcontentsmask |= DPCONTENTS_BOTCLIP;
+ this.frags = FRAGS_PLAYER;
+ if (INDEPENDENT_PLAYERS) MAKE_INDEPENDENT_PLAYER(this);
+ this.flags = FL_CLIENT | FL_PICKUPITEMS;
+ if (autocvar__notarget)
+ this.flags |= FL_NOTARGET;
+ this.takedamage = DAMAGE_AIM;
+ this.effects = EF_TELEPORT_BIT | EF_RESTARTANIM_BIT;
+ this.dmg = 2; // WTF
+
+ if (warmup_stage) {
+ this.ammo_shells = warmup_start_ammo_shells;
+ this.ammo_nails = warmup_start_ammo_nails;
+ this.ammo_rockets = warmup_start_ammo_rockets;
+ this.ammo_cells = warmup_start_ammo_cells;
+ this.ammo_plasma = warmup_start_ammo_plasma;
+ this.ammo_fuel = warmup_start_ammo_fuel;
+ this.health = warmup_start_health;
+ this.armorvalue = warmup_start_armorvalue;
+ this.weapons = WARMUP_START_WEAPONS;
+ } else {
+ this.ammo_shells = start_ammo_shells;
+ this.ammo_nails = start_ammo_nails;
+ this.ammo_rockets = start_ammo_rockets;
+ this.ammo_cells = start_ammo_cells;
+ this.ammo_plasma = start_ammo_plasma;
+ this.ammo_fuel = start_ammo_fuel;
+ this.health = start_health;
+ this.armorvalue = start_armorvalue;
+ this.weapons = start_weapons;
}
- self.items = start_items;
-
- self.spawnshieldtime = time + autocvar_g_spawnshieldtime;
- self.pauserotarmor_finished = time + autocvar_g_balance_pause_armor_rot_spawn;
- self.pauserothealth_finished = time + autocvar_g_balance_pause_health_rot_spawn;
- self.pauserotfuel_finished = time + autocvar_g_balance_pause_fuel_rot_spawn;
- self.pauseregen_finished = time + autocvar_g_balance_pause_health_regen_spawn;
- //extend the pause of rotting if client was reset at the beginning of the countdown
- if(!autocvar_sv_ready_restart_after_countdown && time < game_starttime) { // TODO why is this cvar NOTted?
- self.spawnshieldtime += game_starttime - time;
- self.pauserotarmor_finished += game_starttime - time;
- self.pauserothealth_finished += game_starttime - time;
- self.pauseregen_finished += game_starttime - time;
+ this.superweapons_finished = (this.weapons & WEPSET_SUPERWEAPONS) ? time + autocvar_g_balance_superweapons_time : 0;
+
+ this.items = start_items;
+
+ this.spawnshieldtime = time + autocvar_g_spawnshieldtime;
+ this.pauserotarmor_finished = time + autocvar_g_balance_pause_armor_rot_spawn;
+ this.pauserothealth_finished = time + autocvar_g_balance_pause_health_rot_spawn;
+ this.pauserotfuel_finished = time + autocvar_g_balance_pause_fuel_rot_spawn;
+ this.pauseregen_finished = time + autocvar_g_balance_pause_health_regen_spawn;
+ // extend the pause of rotting if client was reset at the beginning of the countdown
+ if (!autocvar_sv_ready_restart_after_countdown && time < game_starttime) { // TODO why is this cvar NOTted?
+ float f = game_starttime - time;
+ this.spawnshieldtime += f;
+ this.pauserotarmor_finished += f;
+ this.pauserothealth_finished += f;
+ this.pauseregen_finished += f;
}
- self.damageforcescale = 2;
- self.death_time = 0;
- self.respawn_flags = 0;
- self.respawn_time = 0;
- self.stat_respawn_time = 0;
- self.scale = 0;
- self.fade_time = 0;
- self.pain_frame = 0;
- self.pain_finished = 0;
- self.strength_finished = 0;
- self.invincible_finished = 0;
- self.pushltime = 0;
- // players have no think function
- self.think = func_null;
- self.nextthink = 0;
- self.hook_time = 0;
- self.dmg_team = 0;
- self.ballistics_density = autocvar_g_ballistics_density_player;
-
- self.metertime = 0;
-
- self.deadflag = DEAD_NO;
-
- self.angles = spot.angles;
-
- self.angles_z = 0; // never spawn tilted even if the spot says to
- if(IS_BOT_CLIENT(self))
- self.v_angle = self.angles;
- self.fixangle = true; // turn this way immediately
- self.velocity = '0 0 0';
- self.avelocity = '0 0 0';
- self.punchangle = '0 0 0';
- self.punchvector = '0 0 0';
- self.oldvelocity = self.velocity;
- self.fire_endtime = -1;
- self.revival_time = 0;
-
- entity spawnevent = spawn();
- spawnevent.owner = self;
+ this.damageforcescale = 2;
+ this.death_time = 0;
+ this.respawn_flags = 0;
+ this.respawn_time = 0;
+ this.stat_respawn_time = 0;
+ this.scale = autocvar_sv_player_scale;
+ this.fade_time = 0;
+ this.pain_frame = 0;
+ this.pain_finished = 0;
+ this.pushltime = 0;
+ setthink(this, func_null); // players have no think function
+ this.nextthink = 0;
+ this.dmg_team = 0;
+ this.ballistics_density = autocvar_g_ballistics_density_player;
+
+ this.deadflag = DEAD_NO;
+
+ this.angles = spot.angles;
+ this.angles_z = 0; // never spawn tilted even if the spot says to
+ if (IS_BOT_CLIENT(this))
+ this.v_angle = this.angles;
+ this.fixangle = true; // turn this way immediately
+ this.oldvelocity = this.velocity = '0 0 0';
+ this.avelocity = '0 0 0';
+ this.punchangle = '0 0 0';
+ this.punchvector = '0 0 0';
+
+ this.strength_finished = 0;
+ this.invincible_finished = 0;
+ this.fire_endtime = -1;
+ this.revival_time = 0;
+ this.air_finished = time + 12;
+
+ entity spawnevent = new_pure(spawnevent);
+ spawnevent.owner = this;
Net_LinkEntity(spawnevent, false, 0.5, SpawnEvent_Send);
// Cut off any still running player sounds.
- stopsound(self, CH_PLAYER_SINGLE);
+ stopsound(this, CH_PLAYER_SINGLE);
- self.model = "";
- FixPlayermodel();
- self.drawonlytoclient = world;
+ this.model = "";
+ FixPlayermodel(this);
+ this.drawonlytoclient = NULL;
- self.crouch = false;
- self.view_ofs = PL_VIEW_OFS;
- setsize (self, PL_MIN, PL_MAX);
- self.spawnorigin = spot.origin;
- setorigin (self, spot.origin + '0 0 1' * (1 - self.mins.z - 24));
+ this.crouch = false;
+ this.view_ofs = STAT(PL_VIEW_OFS, NULL);
+ setsize(this, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL));
+ this.spawnorigin = spot.origin;
+ setorigin(this, spot.origin + '0 0 1' * (1 - this.mins.z - 24));
// don't reset back to last position, even if new position is stuck in solid
- self.oldorigin = self.origin;
- self.prevorigin = self.origin;
- self.lastrocket = world; // stop rocket guiding, no revenge from the grave!
- self.lastteleporttime = time; // prevent insane speeds due to changing origin
- self.hud = HUD_NORMAL;
+ this.oldorigin = this.origin;
+ this.prevorigin = this.origin;
+ this.lastteleporttime = time; // prevent insane speeds due to changing origin
+ this.conveyor = NULL; // prevent conveyors at the previous location from moving a freshly spawned player
+ this.hud = HUD_NORMAL;
- self.event_damage = PlayerDamage;
+ this.event_damage = PlayerDamage;
- self.bot_attack = true;
- self.monster_attack = true;
+ this.bot_attack = true;
+ this.monster_attack = true;
- self.spider_slowness = 0;
+ PHYS_INPUT_BUTTON_ATCK(this) = PHYS_INPUT_BUTTON_JUMP(this) = PHYS_INPUT_BUTTON_ATCK2(this) = false;
- self.BUTTON_ATCK = self.BUTTON_JUMP = self.BUTTON_ATCK2 = 0;
-
- if(self.killcount == -666) {
- PlayerScore_Clear(self);
- self.killcount = 0;
+ if (this.killcount == FRAGS_SPECTATOR) {
+ PlayerScore_Clear(this);
+ this.killcount = 0;
}
- CL_SpawnWeaponentity();
- self.alpha = default_player_alpha;
- self.colormod = '1 1 1' * autocvar_g_player_brightness;
- self.exteriorweaponentity.alpha = default_weapon_alpha;
-
- self.speedrunning = false;
+ for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ CL_SpawnWeaponentity(this, weaponentities[slot]);
+ }
+ this.alpha = default_player_alpha;
+ this.colormod = '1 1 1' * autocvar_g_player_brightness;
+ this.exteriorweaponentity.alpha = default_weapon_alpha;
- //stuffcmd(self, "chase_active 0");
- //stuffcmd(self, "set viewsize $tmpviewsize \n");
+ this.speedrunning = false;
- target_voicescript_clear(self);
+ target_voicescript_clear(this);
// reset fields the weapons may use
- for (j = WEP_FIRST; j <= WEP_LAST; ++j)
- {
- WEP_ACTION(j, WR_RESETPLAYER);
+ FOREACH(Weapons, true, LAMBDA(
+ it.wr_resetplayer(it, this);
+ // reload all reloadable weapons
+ if (it.spawnflags & WEP_FLAG_RELOADABLE) {
+ this.weapon_load[it.m_id] = it.reloading_ammo;
+ }
+ ));
- // all weapons must be fully loaded when we spawn
- entity e = get_weaponinfo(j);
- if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars
- self.(weapon_load[j]) = e.reloading_ammo;
+ {
+ string s = spot.target;
+ spot.target = string_null;
+ SUB_UseTargets(spot, this, NULL);
+ spot.target = s;
}
- oldself = self;
- self = spot;
- activator = oldself;
- string s;
- s = self.target;
- self.target = string_null;
- SUB_UseTargets();
- self.target = s;
- activator = world;
- self = oldself;
-
- Unfreeze(self);
+ Unfreeze(this);
- spawn_spot = spot;
- MUTATOR_CALLHOOK(PlayerSpawn);
+ MUTATOR_CALLHOOK(PlayerSpawn, this, spot);
- if(autocvar_spawn_debug)
+ if (autocvar_spawn_debug)
{
- sprint(self, strcat("spawnpoint origin: ", vtos(spot.origin), "\n"));
- remove(spot); // usefull for checking if there are spawnpoints, that let drop through the floor
+ sprint(this, strcat("spawnpoint origin: ", vtos(spot.origin), "\n"));
+ remove(spot); // usefull for checking if there are spawnpoints, that let drop through the floor
}
- self.switchweapon = w_getbestweapon(self);
- self.cnt = -1; // W_LastWeapon will not complain
- self.weapon = 0;
- self.weaponname = "";
- self.switchingweapon = 0;
+ 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;
- if(!warmup_stage)
- if(!self.alivetime)
- self.alivetime = time;
+ if (!warmup_stage && !this.alivetime)
+ this.alivetime = time;
- antilag_clear(self);
- }
- else if(IS_OBSERVER(self))
- {
- PutObserverInServer ();
+ antilag_clear(this, CS(this));
}
}
+ void ClientInit_misc(entity this);
+
.float ebouncefactor, ebouncestop; // electro's values
// TODO do we need all these fields, or should we stop autodetecting runtime
// changes and just have a console command to update this?
- float ClientInit_SendEntity(entity to, float sf)
+ bool ClientInit_SendEntity(entity this, entity to, int sf)
{
- WriteByte(MSG_ENTITY, ENT_CLIENT_INIT);
- WriteByte(MSG_ENTITY, g_nexball_meter_period * 32);
- WriteInt24_t(MSG_ENTITY, compressShotOrigin(hook_shotorigin[0]));
- WriteInt24_t(MSG_ENTITY, compressShotOrigin(hook_shotorigin[1]));
- WriteInt24_t(MSG_ENTITY, compressShotOrigin(hook_shotorigin[2]));
- WriteInt24_t(MSG_ENTITY, compressShotOrigin(hook_shotorigin[3]));
- WriteInt24_t(MSG_ENTITY, compressShotOrigin(arc_shotorigin[0]));
- WriteInt24_t(MSG_ENTITY, compressShotOrigin(arc_shotorigin[1]));
- WriteInt24_t(MSG_ENTITY, compressShotOrigin(arc_shotorigin[2]));
- WriteInt24_t(MSG_ENTITY, compressShotOrigin(arc_shotorigin[3]));
+ WriteHeader(MSG_ENTITY, _ENT_CLIENT_INIT);
+ return = true;
+ msg_entity = to;
+ // MSG_INIT replacement
+ // TODO: make easier to use
+ Registry_send_all();
+ W_PROP_reload(MSG_ONE, to);
+ ClientInit_misc(this);
+ MUTATOR_CALLHOOK(Ent_Init);
+ }
+ void ClientInit_misc(entity this)
+ {
+ int channel = MSG_ONE;
+ WriteHeader(channel, ENT_CLIENT_INIT);
+ WriteByte(channel, g_nexball_meter_period * 32);
+ WriteInt24_t(channel, compressShotOrigin(hook_shotorigin[0]));
+ WriteInt24_t(channel, compressShotOrigin(hook_shotorigin[1]));
+ WriteInt24_t(channel, compressShotOrigin(hook_shotorigin[2]));
+ WriteInt24_t(channel, compressShotOrigin(hook_shotorigin[3]));
+ WriteInt24_t(channel, compressShotOrigin(arc_shotorigin[0]));
+ WriteInt24_t(channel, compressShotOrigin(arc_shotorigin[1]));
+ WriteInt24_t(channel, compressShotOrigin(arc_shotorigin[2]));
+ WriteInt24_t(channel, compressShotOrigin(arc_shotorigin[3]));
if(sv_foginterval && world.fog != "")
- WriteString(MSG_ENTITY, world.fog);
+ WriteString(channel, world.fog);
else
- WriteString(MSG_ENTITY, "");
- WriteByte(MSG_ENTITY, self.count * 255.0); // g_balance_armor_blockpercent
- WriteCoord(MSG_ENTITY, self.bouncefactor); // g_balance_mortar_bouncefactor // WEAPONTODO
- WriteCoord(MSG_ENTITY, self.bouncestop); // g_balance_mortar_bouncestop
- WriteCoord(MSG_ENTITY, self.ebouncefactor); // g_balance_mortar_bouncefactor
- WriteCoord(MSG_ENTITY, self.ebouncestop); // g_balance_mortar_bouncestop
- WriteByte(MSG_ENTITY, WEP_CVAR(vortex, secondary)); // client has to know if it should zoom or not // WEAPONTODO
- WriteByte(MSG_ENTITY, WEP_CVAR(rifle, secondary)); // client has to know if it should zoom or not // WEAPONTODO
- WriteByte(MSG_ENTITY, serverflags); // client has to know if it should zoom or not
- WriteByte(MSG_ENTITY, WEP_CVAR(minelayer, limit)); // minelayer max mines // WEAPONTODO
- WriteByte(MSG_ENTITY, WEP_CVAR_SEC(hagar, load_max)); // hagar max loadable rockets // WEAPONTODO
- WriteCoord(MSG_ENTITY, autocvar_g_trueaim_minrange);
- WriteByte(MSG_ENTITY, WEP_CVAR(porto, secondary)); // WEAPONTODO
- return true;
+ WriteString(channel, "");
+ WriteByte(channel, this.count * 255.0); // g_balance_armor_blockpercent
+ WriteByte(channel, serverflags); // client has to know if it should zoom or not
+ WriteCoord(channel, autocvar_g_trueaim_minrange);
}
- void ClientInit_CheckUpdate()
+ void ClientInit_CheckUpdate(entity this)
{
- self.nextthink = time;
- if(self.count != autocvar_g_balance_armor_blockpercent)
- {
- self.count = autocvar_g_balance_armor_blockpercent;
- self.SendFlags |= 1;
- }
- if(self.bouncefactor != autocvar_g_balance_mortar_bouncefactor) // WEAPONTODO
- {
- self.bouncefactor = autocvar_g_balance_mortar_bouncefactor;
- self.SendFlags |= 1;
- }
- if(self.bouncestop != autocvar_g_balance_mortar_bouncestop)
- {
- self.bouncestop = autocvar_g_balance_mortar_bouncestop;
- self.SendFlags |= 1;
- }
- if(self.ebouncefactor != autocvar_g_balance_electro_secondary_bouncefactor)
+ this.nextthink = time;
+ if(this.count != autocvar_g_balance_armor_blockpercent)
{
- self.ebouncefactor = autocvar_g_balance_electro_secondary_bouncefactor;
- self.SendFlags |= 1;
- }
- if(self.ebouncestop != autocvar_g_balance_electro_secondary_bouncestop)
- {
- self.ebouncestop = autocvar_g_balance_electro_secondary_bouncestop;
- self.SendFlags |= 1;
+ this.count = autocvar_g_balance_armor_blockpercent;
+ this.SendFlags |= 1;
}
}
void ClientInit_Spawn()
{
- entity o;
- entity e;
- e = spawn();
- e.classname = "clientinit";
- e.think = ClientInit_CheckUpdate;
+ entity e = new_pure(clientinit);
+ setthink(e, ClientInit_CheckUpdate);
Net_LinkEntity(e, false, 0, ClientInit_SendEntity);
- o = self;
- self = e;
- ClientInit_CheckUpdate();
- self = o;
+ ClientInit_CheckUpdate(e);
}
/*
SetNewParms
=============
*/
- void SetNewParms (void)
+ void SetNewParms ()
{
// initialize parms for a new player
parm1 = -(86400 * 366);
+
+ MUTATOR_CALLHOOK(SetNewParms);
}
/*
SetChangeParms
=============
*/
- void SetChangeParms (void)
- {
+ void SetChangeParms ()
+ {ENGINE_EVENT();
// save parms for level change
- parm1 = self.parm_idlesince - time;
+ parm1 = this.parm_idlesince - time;
+
+ MUTATOR_CALLHOOK(SetChangeParms);
}
/*
DecodeLevelParms
=============
*/
- void DecodeLevelParms (void)
+ void DecodeLevelParms(entity this)
{
// load parms
- self.parm_idlesince = parm1;
- if(self.parm_idlesince == -(86400 * 366))
- self.parm_idlesince = time;
+ this.parm_idlesince = parm1;
+ if (this.parm_idlesince == -(86400 * 366))
+ this.parm_idlesince = time;
// whatever happens, allow 60 seconds of idling directly after connect for map loading
- self.parm_idlesince = max(self.parm_idlesince, time - sv_maxidle + 60);
+ this.parm_idlesince = max(this.parm_idlesince, time - sv_maxidle + 60);
+
+ MUTATOR_CALLHOOK(DecodeLevelParms);
}
/*
*/
.float clientkill_nexttime;
- void ClientKill_Now_TeamChange()
+ void ClientKill_Now_TeamChange(entity this)
{
- if(self.killindicator_teamchange == -1)
+ if(this.killindicator_teamchange == -1)
{
- JoinBestTeam( self, false, true );
+ JoinBestTeam( this, false, true );
}
- else if(self.killindicator_teamchange == -2)
+ else if(this.killindicator_teamchange == -2)
{
if(blockSpectators)
- Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime);
- PutObserverInServer();
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime);
+ PutObserverInServer(this);
}
else
- SV_ChangeTeam(self.killindicator_teamchange - 1);
- self.killindicator_teamchange = 0;
+ WITHSELF(this, SV_ChangeTeam(this.killindicator_teamchange - 1));
+ this.killindicator_teamchange = 0;
}
- void ClientKill_Now()
+ void ClientKill_Now(entity this)
{
- if(self.vehicle)
+ if(this.vehicle)
{
- vehicles_exit(VHEF_RELESE);
- if(!self.killindicator_teamchange)
+ vehicles_exit(this.vehicle, VHEF_RELEASE);
+ if(!this.killindicator_teamchange)
{
- self.vehicle_health = -1;
- Damage(self, self, self, 1 , DEATH_KILL, self.origin, '0 0 0');
+ this.vehicle_health = -1;
+ Damage(this, this, this, 1 , DEATH_KILL.m_id, this.origin, '0 0 0');
}
}
- if(self.killindicator && !wasfreed(self.killindicator))
- remove(self.killindicator);
+ if(this.killindicator && !wasfreed(this.killindicator))
+ remove(this.killindicator);
- self.killindicator = world;
+ this.killindicator = world;
- if(self.killindicator_teamchange)
- ClientKill_Now_TeamChange();
+ if(this.killindicator_teamchange)
+ ClientKill_Now_TeamChange(this);
- if(IS_PLAYER(self))
- Damage(self, self, self, 100000, DEATH_KILL, self.origin, '0 0 0');
+ if(IS_PLAYER(this))
+ Damage(this, this, this, 100000, DEATH_KILL.m_id, this.origin, '0 0 0');
// now I am sure the player IS dead
}
- void KillIndicator_Think()
+ void KillIndicator_Think(entity this)
{
if (gameover)
{
- self.owner.killindicator = world;
- remove(self);
+ this.owner.killindicator = world;
+ remove(this);
return;
}
- if (self.owner.alpha < 0 && !self.owner.vehicle)
+ if (this.owner.alpha < 0 && !this.owner.vehicle)
{
- self.owner.killindicator = world;
- remove(self);
+ this.owner.killindicator = world;
+ remove(this);
return;
}
- if(self.cnt <= 0)
+ if(this.cnt <= 0)
{
- self = self.owner;
- ClientKill_Now(); // no oldself needed
+ ClientKill_Now(this.owner);
return;
}
- else if(g_cts && self.health == 1) // health == 1 means that it's silent
+ else if(g_cts && this.health == 1) // health == 1 means that it's silent
{
- self.nextthink = time + 1;
- self.cnt -= 1;
+ this.nextthink = time + 1;
+ this.cnt -= 1;
}
else
{
- if(self.cnt <= 10)
- setmodel(self, strcat("models/sprites/", ftos(self.cnt), ".spr32"));
- if(IS_REAL_CLIENT(self.owner))
+ if(this.cnt <= 10)
+ setmodel(this, MDL_NUM(this.cnt));
+ if(IS_REAL_CLIENT(this.owner))
{
- if(self.cnt <= 10)
- { Send_Notification(NOTIF_ONE, self.owner, MSG_ANNCE, Announcer_PickNumber(CNT_KILL, self.cnt)); }
+ if(this.cnt <= 10)
+ { Send_Notification(NOTIF_ONE, this.owner, MSG_ANNCE, Announcer_PickNumber(CNT_KILL, this.cnt)); }
}
- self.nextthink = time + 1;
- self.cnt -= 1;
+ this.nextthink = time + 1;
+ this.cnt -= 1;
}
}
float clientkilltime;
- void ClientKill_TeamChange (float targetteam) // 0 = don't change, -1 = auto, -2 = spec
+ void ClientKill_TeamChange (entity this, float targetteam) // 0 = don't change, -1 = auto, -2 = spec
{
float killtime;
float starttime;
if(g_race_qualifying || g_cts)
killtime = 0;
- if(g_cts && self.killindicator && self.killindicator.health == 1) // self.killindicator.health == 1 means that the kill indicator was spawned by CTS_ClientKill
- {
- remove(self.killindicator);
- self.killindicator = world;
-
- ClientKill_Now(); // allow instant kill in this case
- return;
- }
+ if(MUTATOR_CALLHOOK(ClientKill, this, killtime))
+ return;
- self.killindicator_teamchange = targetteam;
+ this.killindicator_teamchange = targetteam;
- if(!self.killindicator)
+ if(!this.killindicator)
{
- if(self.deadflag == DEAD_NO)
+ if(!IS_DEAD(this))
{
- killtime = max(killtime, self.clientkill_nexttime - time);
- self.clientkill_nexttime = time + killtime + autocvar_g_balance_kill_antispam;
+ killtime = max(killtime, this.clientkill_nexttime - time);
+ this.clientkill_nexttime = time + killtime + autocvar_g_balance_kill_antispam;
}
- if(killtime <= 0 || !IS_PLAYER(self) || self.deadflag != DEAD_NO)
+ if(killtime <= 0 || !IS_PLAYER(this) || IS_DEAD(this))
{
- ClientKill_Now();
+ ClientKill_Now(this);
}
else
{
starttime = max(time, clientkilltime);
- self.killindicator = spawn();
- self.killindicator.owner = self;
- self.killindicator.scale = 0.5;
- setattachment(self.killindicator, self, "");
- setorigin(self.killindicator, '0 0 52');
- self.killindicator.think = KillIndicator_Think;
- self.killindicator.nextthink = starttime + (self.lip) * 0.05;
- clientkilltime = max(clientkilltime, self.killindicator.nextthink + 0.05);
- self.killindicator.cnt = ceil(killtime);
- self.killindicator.count = bound(0, ceil(killtime), 10);
- //sprint(self, strcat("^1You'll be dead in ", ftos(self.killindicator.cnt), " seconds\n"));
+ this.killindicator = spawn();
+ this.killindicator.owner = this;
+ this.killindicator.scale = 0.5;
+ setattachment(this.killindicator, this, "");
+ setorigin(this.killindicator, '0 0 52');
+ setthink(this.killindicator, KillIndicator_Think);
+ this.killindicator.nextthink = starttime + (this.lip) * 0.05;
+ clientkilltime = max(clientkilltime, this.killindicator.nextthink + 0.05);
+ this.killindicator.cnt = ceil(killtime);
+ this.killindicator.count = bound(0, ceil(killtime), 10);
+ //sprint(this, strcat("^1You'll be dead in ", ftos(this.killindicator.cnt), " seconds\n"));
for(e = world; (e = find(e, classname, "body")) != world; )
{
- if(e.enemy != self)
+ if(e.enemy != this)
continue;
e.killindicator = spawn();
e.killindicator.owner = e;
e.killindicator.scale = 0.5;
setattachment(e.killindicator, e, "");
setorigin(e.killindicator, '0 0 52');
- e.killindicator.think = KillIndicator_Think;
+ setthink(e.killindicator, KillIndicator_Think);
e.killindicator.nextthink = starttime + (e.lip) * 0.05;
clientkilltime = max(clientkilltime, e.killindicator.nextthink + 0.05);
e.killindicator.cnt = ceil(killtime);
}
- self.lip = 0;
+ this.lip = 0;
}
}
- if(self.killindicator)
+ if(this.killindicator)
{
if(targetteam == 0) // just die
{
- self.killindicator.colormod = '0 0 0';
- if(IS_REAL_CLIENT(self))
- if(self.killindicator.cnt > 0)
- Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_TEAMCHANGE_SUICIDE, self.killindicator.cnt);
+ this.killindicator.colormod = '0 0 0';
+ if(IS_REAL_CLIENT(this))
+ if(this.killindicator.cnt > 0)
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_TEAMCHANGE_SUICIDE, this.killindicator.cnt);
}
else if(targetteam == -1) // auto
{
- self.killindicator.colormod = '0 1 0';
- if(IS_REAL_CLIENT(self))
- if(self.killindicator.cnt > 0)
- Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_TEAMCHANGE_AUTO, self.killindicator.cnt);
+ this.killindicator.colormod = '0 1 0';
+ if(IS_REAL_CLIENT(this))
+ if(this.killindicator.cnt > 0)
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_TEAMCHANGE_AUTO, this.killindicator.cnt);
}
else if(targetteam == -2) // spectate
{
- self.killindicator.colormod = '0.5 0.5 0.5';
- if(IS_REAL_CLIENT(self))
- if(self.killindicator.cnt > 0)
- Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_TEAMCHANGE_SPECTATE, self.killindicator.cnt);
+ this.killindicator.colormod = '0.5 0.5 0.5';
+ if(IS_REAL_CLIENT(this))
+ if(this.killindicator.cnt > 0)
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_TEAMCHANGE_SPECTATE, this.killindicator.cnt);
}
else
{
- self.killindicator.colormod = Team_ColorRGB(targetteam);
- if(IS_REAL_CLIENT(self))
- if(self.killindicator.cnt > 0)
- Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, APP_TEAM_NUM_4(targetteam, CENTER_TEAMCHANGE_), self.killindicator.cnt);
+ this.killindicator.colormod = Team_ColorRGB(targetteam);
+ if(IS_REAL_CLIENT(this))
+ if(this.killindicator.cnt > 0)
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, APP_TEAM_NUM(targetteam, CENTER_TEAMCHANGE), this.killindicator.cnt);
}
}
}
- void ClientKill (void)
- {
+ void ClientKill ()
+ {ENGINE_EVENT();
if(gameover) return;
- if(self.player_blocked) return;
- if(self.frozen) return;
-
- ClientKill_TeamChange(0);
- }
+ if(this.player_blocked) return;
+ if(STAT(FROZEN, this)) return;
- void CTS_ClientKill (entity e) // silent version of ClientKill, used when player finishes a CTS run. Useful to prevent cheating by running back to the start line and starting out with more speed
- {
- e.killindicator = spawn();
- e.killindicator.owner = e;
- e.killindicator.think = KillIndicator_Think;
- e.killindicator.nextthink = time + (e.lip) * 0.05;
- e.killindicator.cnt = ceil(autocvar_g_cts_finish_kill_delay);
- e.killindicator.health = 1; // this is used to indicate that it should be silent
- e.lip = 0;
+ ClientKill_TeamChange(this, 0);
}
void FixClientCvars(entity e)
{
// send prediction settings to the client
stuffcmd(e, "\nin_bindmap 0 0\n");
- if(g_race || g_cts)
- stuffcmd(e, "cl_cmd settemp cl_movecliptokeyboard 2\n");
if(autocvar_g_antilag == 3) // client side hitscan
stuffcmd(e, "cl_cmd settemp cl_prydoncursor_notrace 0\n");
if(autocvar_sv_gentle)
stuffcmd(e, "cl_cmd settemp cl_gentle 1\n");
+
+ MUTATOR_CALLHOOK(FixClientCvars, e);
}
float PlayerInIDList(entity p, string idlist)
Called once (not at each match start) when a client begins a connection to the server
=============
*/
- void ClientPreConnect (void)
- {
+ void ClientPreConnect ()
+ {ENGINE_EVENT();
if(autocvar_sv_eventlog)
{
GameLogEcho(sprintf(":connect:%d:%d:%s",
- self.playerid,
- num_for_edict(self),
- ((IS_REAL_CLIENT(self)) ? self.netaddress : "bot")
+ this.playerid,
+ etof(this),
+ ((IS_REAL_CLIENT(this)) ? this.netaddress : "bot")
));
}
}
#endif
- /*
+ /**
=============
ClientConnect
Called when a client connects to the server
=============
*/
- void DecodeLevelParms (void);
- //void dom_player_join_team(entity pl);
- void set_dom_state(entity e);
- void ClientConnect (void)
- {
- float t;
-
- if(IS_CLIENT(self))
- {
- print("Warning: ClientConnect, but already connected!\n");
- return;
- }
-
- if(Ban_MaybeEnforceBanOnce(self))
- return;
-
- DecodeLevelParms();
+ void ClientConnect()
+ {ENGINE_EVENT();
+ if (Ban_MaybeEnforceBanOnce(this)) return;
+ assert(!IS_CLIENT(this), return);
+ this.flags |= FL_CLIENT;
+ assert(player_count >= 0, player_count = 0);
#ifdef WATERMARK
- Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_WATERMARK, WATERMARK);
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_WATERMARK, WATERMARK);
#endif
-
- self.classname = "player_joining";
-
- self.flags = FL_CLIENT;
- self.version_nagtime = time + 10 + random() * 10;
-
- if(player_count<0)
- {
- dprint("BUG player count is lower than zero, this cannot happen!\n");
- player_count = 0;
- }
-
- if(IS_REAL_CLIENT(self)) { PlayerStats_PlayerBasic_CheckUpdate(self); }
-
- PlayerScore_Attach(self);
- ClientData_Attach();
- accuracy_init(self);
-
- bot_clientconnect();
-
- playerdemo_init();
-
- anticheat_init();
+ this.version_nagtime = time + 10 + random() * 10;
+ TRANSMUTE(Client, this);
// identify the right forced team
- if(autocvar_g_campaign)
+ if (autocvar_g_campaign)
{
- if(IS_REAL_CLIENT(self)) // only players, not bots
+ if (IS_REAL_CLIENT(this)) // only players, not bots
{
- switch(autocvar_g_campaign_forceteam)
+ switch (autocvar_g_campaign_forceteam)
{
- case 1: self.team_forced = NUM_TEAM_1; break;
- case 2: self.team_forced = NUM_TEAM_2; break;
- case 3: self.team_forced = NUM_TEAM_3; break;
- case 4: self.team_forced = NUM_TEAM_4; break;
- default: self.team_forced = 0;
+ case 1: this.team_forced = NUM_TEAM_1; break;
+ case 2: this.team_forced = NUM_TEAM_2; break;
+ case 3: this.team_forced = NUM_TEAM_3; break;
+ case 4: this.team_forced = NUM_TEAM_4; break;
+ default: this.team_forced = 0;
}
}
}
- else if(PlayerInIDList(self, autocvar_g_forced_team_red))
- self.team_forced = NUM_TEAM_1;
- else if(PlayerInIDList(self, autocvar_g_forced_team_blue))
- self.team_forced = NUM_TEAM_2;
- else if(PlayerInIDList(self, autocvar_g_forced_team_yellow))
- self.team_forced = NUM_TEAM_3;
- else if(PlayerInIDList(self, autocvar_g_forced_team_pink))
- self.team_forced = NUM_TEAM_4;
- else if(autocvar_g_forced_team_otherwise == "red")
- self.team_forced = NUM_TEAM_1;
- else if(autocvar_g_forced_team_otherwise == "blue")
- self.team_forced = NUM_TEAM_2;
- else if(autocvar_g_forced_team_otherwise == "yellow")
- self.team_forced = NUM_TEAM_3;
- else if(autocvar_g_forced_team_otherwise == "pink")
- self.team_forced = NUM_TEAM_4;
- else if(autocvar_g_forced_team_otherwise == "spectate")
- self.team_forced = -1;
- else if(autocvar_g_forced_team_otherwise == "spectator")
- self.team_forced = -1;
- else
- self.team_forced = 0;
-
- if(!teamplay)
- if(self.team_forced > 0)
- self.team_forced = 0;
+ else if (PlayerInIDList(this, autocvar_g_forced_team_red)) this.team_forced = NUM_TEAM_1;
+ else if (PlayerInIDList(this, autocvar_g_forced_team_blue)) this.team_forced = NUM_TEAM_2;
+ else if (PlayerInIDList(this, autocvar_g_forced_team_yellow)) this.team_forced = NUM_TEAM_3;
+ else if (PlayerInIDList(this, autocvar_g_forced_team_pink)) this.team_forced = NUM_TEAM_4;
+ else switch (autocvar_g_forced_team_otherwise)
+ {
+ default: this.team_forced = 0; break;
+ case "red": this.team_forced = NUM_TEAM_1; break;
+ case "blue": this.team_forced = NUM_TEAM_2; break;
+ case "yellow": this.team_forced = NUM_TEAM_3; break;
+ case "pink": this.team_forced = NUM_TEAM_4; break;
+ case "spectate":
+ case "spectator":
+ this.team_forced = -1;
+ break;
+ }
+ if (!teamplay && this.team_forced > 0) this.team_forced = 0;
- JoinBestTeam(self, false, false); // if the team number is valid, keep it
+ {
+ int id = this.playerid;
+ this.playerid = 0; // silent
+ JoinBestTeam(this, false, false); // if the team number is valid, keep it
+ this.playerid = id;
+ }
- if((autocvar_sv_spectate == 1) || autocvar_g_campaign || self.team_forced < 0) {
- self.classname = "observer";
+ if (autocvar_sv_spectate || autocvar_g_campaign || this.team_forced < 0) {
+ TRANSMUTE(Observer, this);
} else {
- if(teamplay)
- {
- if(autocvar_g_balance_teams)
- {
- self.classname = "player";
- campaign_bots_may_start = 1;
- }
- else
- {
- self.classname = "observer"; // do it anyway
- }
- }
- else
- {
- self.classname = "player";
- campaign_bots_may_start = 1;
+ if (!teamplay || autocvar_g_balance_teams) {
+ TRANSMUTE(Player, this);
+ campaign_bots_may_start = true;
+ } else {
+ TRANSMUTE(Observer, this); // do it anyway
}
}
- self.playerid = (playerid_last = playerid_last + 1);
-
- PlayerStats_GameReport_AddEvent(sprintf("kills-%d", self.playerid));
-
- if(IS_BOT_CLIENT(self))
- PlayerStats_GameReport_AddPlayer(self);
-
- if(autocvar_sv_eventlog)
- GameLogEcho(strcat(":join:", ftos(self.playerid), ":", ftos(num_for_edict(self)), ":", ((IS_REAL_CLIENT(self)) ? self.netaddress : "bot"), ":", self.netname));
-
- LogTeamchange(self.playerid, self.team, 1);
+ PlayerStats_GameReport_AddEvent(sprintf("kills-%d", this.playerid));
- self.just_joined = true; // stop spamming the eventlog with additional lines when the client connects
+ // always track bots, don't ask for cl_allow_uidtracking
+ if (IS_BOT_CLIENT(this)) PlayerStats_GameReport_AddPlayer(this);
- self.netname_previous = strzone(self.netname);
+ if (autocvar_sv_eventlog)
+ GameLogEcho(strcat(":join:", ftos(this.playerid), ":", ftos(etof(this)), ":", ((IS_REAL_CLIENT(this)) ? this.netaddress : "bot"), ":", this.netname));
- if(IS_PLAYER(self) && teamplay)
- Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_4(self, INFO_JOIN_CONNECT_TEAM_), self.netname);
- else
- Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_JOIN_CONNECT, self.netname);
+ LogTeamchange(this.playerid, this.team, 1);
- stuffcmd(self, strcat(clientstuff, "\n"));
- stuffcmd(self, "cl_particles_reloadeffects\n"); // TODO do we still need this?
+ this.just_joined = true; // stop spamming the eventlog with additional lines when the client connects
- FixClientCvars(self);
+ this.netname_previous = strzone(this.netname);
- // spawnfunc_waypoint sprites
- WaypointSprite_InitClient(self);
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, ((teamplay && IS_PLAYER(this)) ? APP_TEAM_ENT(this, INFO_JOIN_CONNECT_TEAM) : INFO_JOIN_CONNECT), this.netname);
- // Wazat's grappling hook
- SetGrappleHookBindings();
+ stuffcmd(this, clientstuff, "\n");
+ stuffcmd(this, "cl_particles_reloadeffects\n"); // TODO do we still need this?
- // Jetpack binds
- stuffcmd(self, "alias +jetpack +button10\n");
- stuffcmd(self, "alias -jetpack -button10\n");
+ FixClientCvars(this);
// get version info from player
- stuffcmd(self, "cmd clientversion $gameversion\n");
-
- // get other cvars from player
- GetCvars(0);
+ stuffcmd(this, "cmd clientversion $gameversion\n");
// notify about available teams
- if(teamplay)
+ if (teamplay)
{
- CheckAllowedTeams(self);
- t = 0; if(c1 >= 0) t |= 1; if(c2 >= 0) t |= 2; if(c3 >= 0) t |= 4; if(c4 >= 0) t |= 8;
- stuffcmd(self, strcat("set _teams_available ", ftos(t), "\n"));
+ CheckAllowedTeams(this);
+ int t = 0;
+ if (c1 >= 0) t |= BIT(0);
+ if (c2 >= 0) t |= BIT(1);
+ if (c3 >= 0) t |= BIT(2);
+ if (c4 >= 0) t |= BIT(3);
+ stuffcmd(this, sprintf("set _teams_available %d\n", t));
}
else
- stuffcmd(self, "set _teams_available 0\n");
-
- attach_entcs();
+ {
+ stuffcmd(this, "set _teams_available 0\n");
+ }
bot_relinkplayerlist();
- self.spectatortime = time;
- if(blockSpectators)
+ this.spectatortime = time;
+ if (blockSpectators)
{
- Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime);
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime);
}
- self.jointime = time;
- self.allowed_timeouts = autocvar_sv_timeout_number;
+ this.jointime = time;
+ this.allowed_timeouts = autocvar_sv_timeout_number;
- if(IS_REAL_CLIENT(self))
+ if (IS_REAL_CLIENT(this))
{
- if(!autocvar_g_campaign)
+ if (!autocvar_g_campaign)
{
- self.motd_actived_time = -1;
- Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_MOTD, getwelcomemessage());
+ this.motd_actived_time = -1;
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_MOTD, getwelcomemessage(this));
}
- if(autocvar_g_bugrigs || (g_weaponarena_weapons == WEPSET_TUBA))
- stuffcmd(self, "cl_cmd settemp chase_active 1\n");
+ if (g_weaponarena_weapons == WEPSET(TUBA))
+ stuffcmd(this, "cl_cmd settemp chase_active 1\n");
}
- if(!sv_foginterval && world.fog != "")
- stuffcmd(self, strcat("\nfog ", world.fog, "\nr_fog_exp2 0\nr_drawfog 1\n"));
-
- W_HitPlotOpen(self);
-
- if(autocvar_sv_teamnagger && !(autocvar_bot_vs_human && (c3==-1 && c4==-1)) && !g_ca && !g_cts && !g_race) // teamnagger is currently bad for ca, race & cts
- send_CSQC_teamnagger();
+ if (!sv_foginterval && world.fog != "")
+ stuffcmd(this, strcat("\nfog ", world.fog, "\nr_fog_exp2 0\nr_drawfog 1\n"));
- CheatInitClient();
+ if (autocvar_sv_teamnagger && !(autocvar_bot_vs_human && (c3==-1 && c4==-1)))
+ if (!g_ca && !g_cts && !g_race) // teamnagger is currently bad for ca, race & cts
+ send_CSQC_teamnagger();
- CSQCMODEL_AUTOINIT();
+ CSQCMODEL_AUTOINIT(this);
- self.model_randomizer = random();
+ this.model_randomizer = random();
- if(IS_REAL_CLIENT(self))
- sv_notice_join();
+ if (IS_REAL_CLIENT(this))
+ sv_notice_join(this);
- for (entity e = world; (e = findfloat(e, init_for_player_needed, 1)); ) {
- entity oldself = self;
- self = e;
- e.init_for_player(oldself);
- self = oldself;
- }
+ FOREACH_ENTITY_FLOAT(init_for_player_needed, true, {
+ it.init_for_player(it, this);
+ });
- MUTATOR_CALLHOOK(ClientConnect);
+ MUTATOR_CALLHOOK(ClientConnect, this);
}
/*
=============
*/
.entity chatbubbleentity;
void ReadyCount();
- void ClientDisconnect (void)
- {
- if(self.vehicle)
- vehicles_exit(VHEF_RELESE);
-
- if (!IS_CLIENT(self))
- {
- print("Warning: ClientDisconnect without ClientConnect\n");
- return;
- }
-
- PlayerStats_GameReport_FinalizePlayer(self);
-
- SetSpectator(self, world);
-
- if(IS_PLAYER(self)) { pointparticles(particleeffectnum("spawn_event_neutral"), self.origin, '0 0 0', 1); }
+ void ClientDisconnect()
+ {ENGINE_EVENT();
+ assert(IS_CLIENT(this), return);
- CheatShutdownClient();
+ PlayerStats_GameReport_FinalizePlayer(this);
+ if (this.vehicle) vehicles_exit(this.vehicle, VHEF_RELEASE);
+ if (this.active_minigame) part_minigame(this);
+ if (IS_PLAYER(this)) Send_Effect(EFFECT_SPAWN_NEUTRAL, this.origin, '0 0 0', 1);
- W_HitPlotClose(self);
+ if (autocvar_sv_eventlog)
+ GameLogEcho(strcat(":part:", ftos(this.playerid)));
- anticheat_report();
- anticheat_shutdown();
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_QUIT_DISCONNECT, this.netname);
- playerdemo_shutdown();
++ SetSpectatee(this, NULL);
+
- bot_clientdisconnect();
+ MUTATOR_CALLHOOK(ClientDisconnect, this);
- if(self.entcs)
- detach_entcs();
+ ClientState_detach(this);
- if(autocvar_sv_eventlog)
- GameLogEcho(strcat(":part:", ftos(self.playerid)));
-
- Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_QUIT_DISCONNECT, self.netname);
-
- MUTATOR_CALLHOOK(ClientDisconnect);
+ Portal_ClearAll(this);
- Portal_ClearAll(self);
+ Unfreeze(this);
- Unfreeze(self);
-
- RemoveGrapplingHook(self);
+ RemoveGrapplingHook(this);
// Here, everything has been done that requires this player to be a client.
- self.flags &= ~FL_CLIENT;
-
- if (self.chatbubbleentity)
- remove (self.chatbubbleentity);
+ this.flags &= ~FL_CLIENT;
- if (self.killindicator)
- remove (self.killindicator);
+ if (this.chatbubbleentity) remove(this.chatbubbleentity);
+ if (this.killindicator) remove(this.killindicator);
- WaypointSprite_PlayerGone();
+ WaypointSprite_PlayerGone(this);
bot_relinkplayerlist();
- accuracy_free(self);
- ClientData_Detach();
- PlayerScore_Detach(self);
-
- if(self.netname_previous)
- strunzone(self.netname_previous);
- if(self.clientstatus)
- strunzone(self.clientstatus);
- if(self.weaponorder_byimpulse)
- strunzone(self.weaponorder_byimpulse);
+ if (this.netname_previous) strunzone(this.netname_previous);
+ if (this.clientstatus) strunzone(this.clientstatus);
+ if (this.weaponorder_byimpulse) strunzone(this.weaponorder_byimpulse);
+ if (this.personal) remove(this.personal);
- ClearPlayerSounds();
-
- if(self.personal)
- remove(self.personal);
-
- self.playerid = 0;
+ this.playerid = 0;
ReadyCount();
-
- // free cvars
- GetCvars(-1);
+ if (vote_called && IS_REAL_CLIENT(this)) VoteCount(false);
}
- .float BUTTON_CHAT;
- void ChatBubbleThink()
+ void ChatBubbleThink(entity this)
{
- self.nextthink = time;
- if ((self.owner.alpha < 0) || self.owner.chatbubbleentity != self)
+ this.nextthink = time;
+ if ((this.owner.alpha < 0) || this.owner.chatbubbleentity != this)
{
- if(self.owner) // but why can that ever be world?
- self.owner.chatbubbleentity = world;
- remove(self);
+ if(this.owner) // but why can that ever be world?
+ this.owner.chatbubbleentity = world;
+ remove(this);
return;
}
- if ((self.owner.BUTTON_CHAT && !self.owner.deadflag)
- #ifdef TETRIS
- || self.owner.tetris_on
- #endif
- )
- self.model = self.mdl;
- else
- self.model = "";
+
+ this.mdl = "";
+
+ if ( !IS_DEAD(this.owner) && IS_PLAYER(this.owner) )
+ {
+ if ( this.owner.active_minigame )
+ this.mdl = "models/sprites/minigame_busy.iqm";
+ else if (PHYS_INPUT_BUTTON_CHAT(this.owner))
+ this.mdl = "models/misc/chatbubble.spr";
+ }
+
+ if ( this.model != this.mdl )
+ _setmodel(this, this.mdl);
+
}
- void UpdateChatBubble()
+ void UpdateChatBubble(entity this)
{
- if (self.alpha < 0)
+ if (this.alpha < 0)
return;
// spawn a chatbubble entity if needed
- if (!self.chatbubbleentity)
- {
- self.chatbubbleentity = spawn();
- self.chatbubbleentity.owner = self;
- self.chatbubbleentity.exteriormodeltoclient = self;
- self.chatbubbleentity.think = ChatBubbleThink;
- self.chatbubbleentity.nextthink = time;
- setmodel(self.chatbubbleentity, "models/misc/chatbubble.spr"); // precision set below
- //setorigin(self.chatbubbleentity, self.origin + '0 0 15' + self.maxs_z * '0 0 1');
- setorigin(self.chatbubbleentity, '0 0 15' + self.maxs.z * '0 0 1');
- setattachment(self.chatbubbleentity, self, ""); // sticks to moving player better, also conserves bandwidth
- self.chatbubbleentity.mdl = self.chatbubbleentity.model;
- self.chatbubbleentity.model = "";
- self.chatbubbleentity.effects = EF_LOWPRECISION;
+ if (!this.chatbubbleentity)
+ {
+ this.chatbubbleentity = new(chatbubbleentity);
+ this.chatbubbleentity.owner = this;
+ this.chatbubbleentity.exteriormodeltoclient = this;
+ setthink(this.chatbubbleentity, ChatBubbleThink);
+ this.chatbubbleentity.nextthink = time;
+ setmodel(this.chatbubbleentity, MDL_CHAT); // precision set below
+ //setorigin(this.chatbubbleentity, this.origin + '0 0 15' + this.maxs_z * '0 0 1');
+ setorigin(this.chatbubbleentity, '0 0 15' + this.maxs_z * '0 0 1');
+ setattachment(this.chatbubbleentity, this, ""); // sticks to moving player better, also conserves bandwidth
+ this.chatbubbleentity.mdl = this.chatbubbleentity.model;
+ //this.chatbubbleentity.model = "";
+ this.chatbubbleentity.effects = EF_LOWPRECISION;
}
}
/*void UpdateColorModHack()
{
float c;
- c = self.clientcolors & 15;
+ c = this.clientcolors & 15;
// LordHavoc: only bothering to support white, green, red, yellow, blue
- if (!teamplay) self.colormod = '0 0 0';
- else if (c == 0) self.colormod = '1.00 1.00 1.00';
- else if (c == 3) self.colormod = '0.10 1.73 0.10';
- else if (c == 4) self.colormod = '1.73 0.10 0.10';
- else if (c == 12) self.colormod = '1.22 1.22 0.10';
- else if (c == 13) self.colormod = '0.10 0.10 1.73';
- else self.colormod = '1 1 1';
+ if (!teamplay) this.colormod = '0 0 0';
+ else if (c == 0) this.colormod = '1.00 1.00 1.00';
+ else if (c == 3) this.colormod = '0.10 1.73 0.10';
+ else if (c == 4) this.colormod = '1.73 0.10 0.10';
+ else if (c == 12) this.colormod = '1.22 1.22 0.10';
+ else if (c == 13) this.colormod = '0.10 0.10 1.73';
+ else this.colormod = '1 1 1';
}*/
- void respawn(void)
+ void respawn(entity this)
{
- if(self.alpha >= 0 && autocvar_g_respawn_ghosts)
- {
- self.solid = SOLID_NOT;
- self.takedamage = DAMAGE_NO;
- self.movetype = MOVETYPE_FLY;
- self.velocity = '0 0 1' * autocvar_g_respawn_ghosts_speed;
- self.avelocity = randomvec() * autocvar_g_respawn_ghosts_speed * 3 - randomvec() * autocvar_g_respawn_ghosts_speed * 3;
- self.effects |= CSQCMODEL_EF_RESPAWNGHOST;
- pointparticles(particleeffectnum("respawn_ghost"), self.origin, '0 0 0', 1);
+ if(this.alpha >= 0 && autocvar_g_respawn_ghosts)
+ {
+ this.solid = SOLID_NOT;
+ this.takedamage = DAMAGE_NO;
+ this.movetype = MOVETYPE_FLY;
+ this.velocity = '0 0 1' * autocvar_g_respawn_ghosts_speed;
+ this.avelocity = randomvec() * autocvar_g_respawn_ghosts_speed * 3 - randomvec() * autocvar_g_respawn_ghosts_speed * 3;
+ this.effects |= CSQCMODEL_EF_RESPAWNGHOST;
+ Send_Effect(EFFECT_RESPAWN_GHOST, this.origin, '0 0 0', 1);
if(autocvar_g_respawn_ghosts_maxtime)
- SUB_SetFade (self, time + autocvar_g_respawn_ghosts_maxtime / 2 + random () * (autocvar_g_respawn_ghosts_maxtime - autocvar_g_respawn_ghosts_maxtime / 2), 1.5);
+ SUB_SetFade (this, time + autocvar_g_respawn_ghosts_maxtime / 2 + random () * (autocvar_g_respawn_ghosts_maxtime - autocvar_g_respawn_ghosts_maxtime / 2), 1.5);
}
- CopyBody(1);
+ CopyBody(this, 1);
- self.effects |= EF_NODRAW; // prevent another CopyBody
- PutClientInServer();
+ this.effects |= EF_NODRAW; // prevent another CopyBody
+ WITHSELF(this, PutClientInServer());
}
- void play_countdown(float finished, string samp)
+ void play_countdown(entity this, float finished, Sound samp)
{
- if(IS_REAL_CLIENT(self))
+ TC(Sound, samp);
+ if(IS_REAL_CLIENT(this))
if(floor(finished - time - frametime) != floor(finished - time))
if(finished - time < 6)
- sound (self, CH_INFO, samp, VOL_BASE, ATTEN_NORM);
+ sound (this, CH_INFO, samp, VOL_BASE, ATTEN_NORM);
}
- void player_powerups (void)
+ void player_powerups(entity this)
{
// add a way to see what the items were BEFORE all of these checks for the mutator hook
- olditems = self.items;
+ int items_prev = this.items;
- if((self.items & IT_USING_JETPACK) && !self.deadflag && !gameover)
- self.modelflags |= MF_ROCKET;
+ if((this.items & IT_USING_JETPACK) && !IS_DEAD(this) && !gameover)
+ this.modelflags |= MF_ROCKET;
else
- self.modelflags &= ~MF_ROCKET;
+ this.modelflags &= ~MF_ROCKET;
- self.effects &= ~(EF_RED | EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT | EF_FLAME | EF_NODEPTHTEST);
+ this.effects &= ~(EF_RED | EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT | EF_FLAME | EF_NODEPTHTEST);
- if((self.alpha < 0 || self.deadflag) && !self.vehicle) // don't apply the flags if the player is gibbed
+ if((this.alpha < 0 || IS_DEAD(this)) && !this.vehicle) // don't apply the flags if the player is gibbed
return;
- Fire_ApplyDamage(self);
- Fire_ApplyEffect(self);
+ Fire_ApplyDamage(this);
+ Fire_ApplyEffect(this);
if (!g_instagib)
{
- if (self.items & IT_STRENGTH)
+ if (this.items & ITEM_Strength.m_itemid)
{
- play_countdown(self.strength_finished, "misc/poweroff.wav");
- self.effects = self.effects | (EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT);
- if (time > self.strength_finished)
+ play_countdown(this, this.strength_finished, SND_POWEROFF);
+ this.effects = this.effects | (EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT);
+ if (time > this.strength_finished)
{
- self.items = self.items - (self.items & IT_STRENGTH);
- //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERDOWN_STRENGTH, self.netname);
- Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_STRENGTH);
+ this.items = this.items - (this.items & ITEM_Strength.m_itemid);
+ //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERDOWN_STRENGTH, this.netname);
+ Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_POWERDOWN_STRENGTH);
}
}
else
{
- if (time < self.strength_finished)
+ if (time < this.strength_finished)
{
- self.items = self.items | IT_STRENGTH;
- Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_STRENGTH, self.netname);
- Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_STRENGTH);
+ this.items = this.items | ITEM_Strength.m_itemid;
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_STRENGTH, this.netname);
+ Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_POWERUP_STRENGTH);
}
}
- if (self.items & IT_INVINCIBLE)
+ if (this.items & ITEM_Shield.m_itemid)
{
- play_countdown(self.invincible_finished, "misc/poweroff.wav");
- self.effects = self.effects | (EF_RED | EF_ADDITIVE | EF_FULLBRIGHT);
- if (time > self.invincible_finished)
+ play_countdown(this, this.invincible_finished, SND_POWEROFF);
+ this.effects = this.effects | (EF_RED | EF_ADDITIVE | EF_FULLBRIGHT);
+ if (time > this.invincible_finished)
{
- self.items = self.items - (self.items & IT_INVINCIBLE);
- //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERDOWN_SHIELD, self.netname);
- Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_SHIELD);
+ this.items = this.items - (this.items & ITEM_Shield.m_itemid);
+ //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERDOWN_SHIELD, this.netname);
+ Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_POWERDOWN_SHIELD);
}
}
else
{
- if (time < self.invincible_finished)
+ if (time < this.invincible_finished)
{
- self.items = self.items | IT_INVINCIBLE;
- Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_SHIELD, self.netname);
- Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_SHIELD);
+ this.items = this.items | ITEM_Shield.m_itemid;
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_SHIELD, this.netname);
+ Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_POWERUP_SHIELD);
}
}
- if (self.items & IT_SUPERWEAPON)
+ if (this.items & IT_SUPERWEAPON)
{
- if (!(self.weapons & WEPSET_SUPERWEAPONS))
+ if (!(this.weapons & WEPSET_SUPERWEAPONS))
{
- self.superweapons_finished = 0;
- self.items = self.items - (self.items & IT_SUPERWEAPON);
- //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_SUPERWEAPON_LOST, self.netname);
- Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_SUPERWEAPON_LOST);
+ this.superweapons_finished = 0;
+ this.items = this.items - (this.items & IT_SUPERWEAPON);
+ //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_SUPERWEAPON_LOST, this.netname);
+ Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_SUPERWEAPON_LOST);
}
- else if (self.items & IT_UNLIMITED_SUPERWEAPONS)
+ else if (this.items & IT_UNLIMITED_SUPERWEAPONS)
{
// don't let them run out
}
else
{
- play_countdown(self.superweapons_finished, "misc/poweroff.wav");
- if (time > self.superweapons_finished)
+ play_countdown(this, this.superweapons_finished, SND_POWEROFF);
+ if (time > this.superweapons_finished)
{
- self.items = self.items - (self.items & IT_SUPERWEAPON);
- self.weapons &= ~WEPSET_SUPERWEAPONS;
- //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_SUPERWEAPON_BROKEN, self.netname);
- Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_SUPERWEAPON_BROKEN);
+ this.items = this.items - (this.items & IT_SUPERWEAPON);
+ this.weapons &= ~WEPSET_SUPERWEAPONS;
+ //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_SUPERWEAPON_BROKEN, this.netname);
+ Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_SUPERWEAPON_BROKEN);
}
}
}
- else if(self.weapons & WEPSET_SUPERWEAPONS)
+ else if(this.weapons & WEPSET_SUPERWEAPONS)
{
- if (time < self.superweapons_finished || (self.items & IT_UNLIMITED_SUPERWEAPONS))
+ if (time < this.superweapons_finished || (this.items & IT_UNLIMITED_SUPERWEAPONS))
{
- self.items = self.items | IT_SUPERWEAPON;
- Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_SUPERWEAPON_PICKUP, self.netname);
- Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_SUPERWEAPON_PICKUP);
+ this.items = this.items | IT_SUPERWEAPON;
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_SUPERWEAPON_PICKUP, this.netname);
+ Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_SUPERWEAPON_PICKUP);
}
else
{
- self.superweapons_finished = 0;
- self.weapons &= ~WEPSET_SUPERWEAPONS;
+ this.superweapons_finished = 0;
+ this.weapons &= ~WEPSET_SUPERWEAPONS;
}
}
else
{
- self.superweapons_finished = 0;
+ this.superweapons_finished = 0;
}
}
if(autocvar_g_nodepthtestplayers)
- self.effects = self.effects | EF_NODEPTHTEST;
+ this.effects = this.effects | EF_NODEPTHTEST;
if(autocvar_g_fullbrightplayers)
- self.effects = self.effects | EF_FULLBRIGHT;
+ this.effects = this.effects | EF_FULLBRIGHT;
if (time >= game_starttime)
- if (time < self.spawnshieldtime)
- self.effects = self.effects | (EF_ADDITIVE | EF_FULLBRIGHT);
+ if (time < this.spawnshieldtime)
+ this.effects = this.effects | (EF_ADDITIVE | EF_FULLBRIGHT);
- MUTATOR_CALLHOOK(PlayerPowerups);
+ MUTATOR_CALLHOOK(PlayerPowerups, this, items_prev);
}
float CalcRegen(float current, float stable, float regenfactor, float regenframetime)
return current;
}
- void player_regen (void)
+ void player_regen(entity this)
{
float max_mod, regen_mod, rot_mod, limit_mod;
max_mod = regen_mod = rot_mod = limit_mod = 1;
- regen_mod_max = max_mod;
- regen_mod_regen = regen_mod;
- regen_mod_rot = rot_mod;
- regen_mod_limit = limit_mod;
- if(!MUTATOR_CALLHOOK(PlayerRegen))
- if(!self.frozen)
- {
- float minh, mina, maxh, maxa, limith, limita;
- maxh = autocvar_g_balance_health_rotstable;
+
+ float regen_health = autocvar_g_balance_health_regen;
+ float regen_health_linear = autocvar_g_balance_health_regenlinear;
+ float regen_health_rot = autocvar_g_balance_health_rot;
+ float regen_health_rotlinear = autocvar_g_balance_health_rotlinear;
+ float regen_health_stable = autocvar_g_balance_health_regenstable;
+ float regen_health_rotstable = autocvar_g_balance_health_rotstable;
+ bool mutator_returnvalue = MUTATOR_CALLHOOK(PlayerRegen, this, max_mod, regen_mod, rot_mod, limit_mod, regen_health, regen_health_linear, regen_health_rot,
+ regen_health_rotlinear, regen_health_stable, regen_health_rotstable);
+ max_mod = M_ARGV(1, float);
+ regen_mod = M_ARGV(2, float);
+ rot_mod = M_ARGV(3, float);
+ limit_mod = M_ARGV(4, float);
+ regen_health = M_ARGV(5, float);
+ regen_health_linear = M_ARGV(6, float);
+ regen_health_rot = M_ARGV(7, float);
+ regen_health_rotlinear = M_ARGV(8, float);
+ regen_health_stable = M_ARGV(9, float);
+ regen_health_rotstable = M_ARGV(10, float);
+
+
+ if(!mutator_returnvalue)
+ if(!STAT(FROZEN, this))
+ {
+ float mina, maxa, limith, limita;
maxa = autocvar_g_balance_armor_rotstable;
- minh = autocvar_g_balance_health_regenstable;
mina = autocvar_g_balance_armor_regenstable;
limith = autocvar_g_balance_health_limit;
limita = autocvar_g_balance_armor_limit;
- max_mod = regen_mod_max;
- regen_mod = regen_mod_regen;
- rot_mod = regen_mod_rot;
- limit_mod = regen_mod_limit;
-
- maxh = maxh * max_mod;
- minh = minh * max_mod;
+ regen_health_rotstable = regen_health_rotstable * max_mod;
+ regen_health_stable = regen_health_stable * max_mod;
limith = limith * limit_mod;
limita = limita * limit_mod;
- self.armorvalue = CalcRotRegen(self.armorvalue, mina, autocvar_g_balance_armor_regen, autocvar_g_balance_armor_regenlinear, regen_mod * frametime * (time > self.pauseregen_finished), maxa, autocvar_g_balance_armor_rot, autocvar_g_balance_armor_rotlinear, rot_mod * frametime * (time > self.pauserotarmor_finished), limita);
- self.health = CalcRotRegen(self.health, minh, autocvar_g_balance_health_regen, autocvar_g_balance_health_regenlinear, regen_mod * frametime * (time > self.pauseregen_finished), maxh, autocvar_g_balance_health_rot, autocvar_g_balance_health_rotlinear, rot_mod * frametime * (time > self.pauserothealth_finished), limith);
+ this.armorvalue = CalcRotRegen(this.armorvalue, mina, autocvar_g_balance_armor_regen, autocvar_g_balance_armor_regenlinear, regen_mod * frametime * (time > this.pauseregen_finished), maxa, autocvar_g_balance_armor_rot, autocvar_g_balance_armor_rotlinear, rot_mod * frametime * (time > this.pauserotarmor_finished), limita);
+ this.health = CalcRotRegen(this.health, regen_health_stable, regen_health, regen_health_linear, regen_mod * frametime * (time > this.pauseregen_finished), regen_health_rotstable, regen_health_rot, regen_health_rotlinear, rot_mod * frametime * (time > this.pauserothealth_finished), limith);
}
// if player rotted to death... die!
// check this outside above checks, as player may still be able to rot to death
- if(self.health < 1)
- self.event_damage(self, self, 1, DEATH_ROT, self.origin, '0 0 0');
+ if(this.health < 1)
+ {
+ if(this.vehicle)
+ vehicles_exit(this.vehicle, VHEF_RELEASE);
+ if(this.event_damage)
+ this.event_damage(this, this, this, 1, DEATH_ROT.m_id, this.origin, '0 0 0');
+ }
- if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+ if (!(this.items & IT_UNLIMITED_WEAPON_AMMO))
{
float minf, maxf, limitf;
minf = autocvar_g_balance_fuel_regenstable;
limitf = autocvar_g_balance_fuel_limit;
- self.ammo_fuel = CalcRotRegen(self.ammo_fuel, minf, autocvar_g_balance_fuel_regen, autocvar_g_balance_fuel_regenlinear, frametime * (time > self.pauseregen_finished) * ((self.items & IT_FUEL_REGEN) != 0), maxf, autocvar_g_balance_fuel_rot, autocvar_g_balance_fuel_rotlinear, frametime * (time > self.pauserotfuel_finished), limitf);
+ this.ammo_fuel = CalcRotRegen(this.ammo_fuel, minf, autocvar_g_balance_fuel_regen, autocvar_g_balance_fuel_regenlinear, frametime * (time > this.pauseregen_finished) * ((this.items & ITEM_JetpackRegen.m_itemid) != 0), maxf, autocvar_g_balance_fuel_rot, autocvar_g_balance_fuel_rotlinear, frametime * (time > this.pauserotfuel_finished), limitf);
}
}
- float zoomstate_set;
- void SetZoomState(float z)
+ bool zoomstate_set;
+ void SetZoomState(entity this, float z)
{
- if(z != self.zoomstate)
+ if(z != this.zoomstate)
{
- self.zoomstate = z;
- ClientData_Touch(self);
+ this.zoomstate = z;
+ ClientData_Touch(this);
}
- zoomstate_set = 1;
+ zoomstate_set = true;
}
- void GetPressedKeys(void) {
- MUTATOR_CALLHOOK(GetPressedKeys);
- if (self.movement.x > 0) // get if movement keys are pressed
- { // forward key pressed
- self.pressedkeys |= KEY_FORWARD;
- self.pressedkeys &= ~KEY_BACKWARD;
- }
- else if (self.movement.x < 0)
- { // backward key pressed
- self.pressedkeys |= KEY_BACKWARD;
- self.pressedkeys &= ~KEY_FORWARD;
- }
- else
- { // no x input
- self.pressedkeys &= ~KEY_FORWARD;
- self.pressedkeys &= ~KEY_BACKWARD;
- }
-
- if (self.movement.y > 0)
- { // right key pressed
- self.pressedkeys |= KEY_RIGHT;
- self.pressedkeys &= ~KEY_LEFT;
- }
- else if (self.movement.y < 0)
- { // left key pressed
- self.pressedkeys |= KEY_LEFT;
- self.pressedkeys &= ~KEY_RIGHT;
- }
- else
- { // no y input
- self.pressedkeys &= ~KEY_RIGHT;
- self.pressedkeys &= ~KEY_LEFT;
- }
-
- if (self.BUTTON_JUMP) // get if jump and crouch keys are pressed
- self.pressedkeys |= KEY_JUMP;
- else
- self.pressedkeys &= ~KEY_JUMP;
- if (self.BUTTON_CROUCH)
- self.pressedkeys |= KEY_CROUCH;
- else
- self.pressedkeys &= ~KEY_CROUCH;
-
- if (self.BUTTON_ATCK)
- self.pressedkeys |= KEY_ATCK;
- else
- self.pressedkeys &= ~KEY_ATCK;
- if (self.BUTTON_ATCK2)
- self.pressedkeys |= KEY_ATCK2;
- else
- self.pressedkeys &= ~KEY_ATCK2;
+ void GetPressedKeys(entity this)
+ {
+ MUTATOR_CALLHOOK(GetPressedKeys, this);
+ int keys = this.pressedkeys;
+ keys = BITSET(keys, KEY_FORWARD, this.movement.x > 0);
+ keys = BITSET(keys, KEY_BACKWARD, this.movement.x < 0);
+ keys = BITSET(keys, KEY_RIGHT, this.movement.y > 0);
+ keys = BITSET(keys, KEY_LEFT, this.movement.y < 0);
+
+ keys = BITSET(keys, KEY_JUMP, PHYS_INPUT_BUTTON_JUMP(this));
+ keys = BITSET(keys, KEY_CROUCH, PHYS_INPUT_BUTTON_CROUCH(this));
+ keys = BITSET(keys, KEY_ATCK, PHYS_INPUT_BUTTON_ATCK(this));
+ keys = BITSET(keys, KEY_ATCK2, PHYS_INPUT_BUTTON_ATCK2(this));
+ this.pressedkeys = keys;
}
/*
======================
*/
- void SpectateCopy(entity spectatee) {
- other = spectatee;
- MUTATOR_CALLHOOK(SpectateCopy);
- self.armortype = spectatee.armortype;
- self.armorvalue = spectatee.armorvalue;
- self.ammo_cells = spectatee.ammo_cells;
- self.ammo_plasma = spectatee.ammo_plasma;
- self.ammo_shells = spectatee.ammo_shells;
- self.ammo_nails = spectatee.ammo_nails;
- self.ammo_rockets = spectatee.ammo_rockets;
- self.ammo_fuel = spectatee.ammo_fuel;
- self.clip_load = spectatee.clip_load;
- self.clip_size = spectatee.clip_size;
- self.effects = spectatee.effects & EFMASK_CHEAP; // eat performance
- self.health = spectatee.health;
- self.impulse = 0;
- self.items = spectatee.items;
- self.last_pickup = spectatee.last_pickup;
- self.hit_time = spectatee.hit_time;
- self.metertime = spectatee.metertime;
- self.strength_finished = spectatee.strength_finished;
- self.invincible_finished = spectatee.invincible_finished;
- self.pressedkeys = spectatee.pressedkeys;
- self.weapons = spectatee.weapons;
- self.switchweapon = spectatee.switchweapon;
- self.switchingweapon = spectatee.switchingweapon;
- self.weapon = spectatee.weapon;
- self.vortex_charge = spectatee.vortex_charge;
- self.vortex_chargepool_ammo = spectatee.vortex_chargepool_ammo;
- self.hagar_load = spectatee.hagar_load;
- self.arc_heat_percent = spectatee.arc_heat_percent;
- self.minelayer_mines = spectatee.minelayer_mines;
- self.punchangle = spectatee.punchangle;
- self.view_ofs = spectatee.view_ofs;
- self.velocity = spectatee.velocity;
- self.dmg_take = spectatee.dmg_take;
- self.dmg_save = spectatee.dmg_save;
- self.dmg_inflictor = spectatee.dmg_inflictor;
- self.v_angle = spectatee.v_angle;
- self.angles = spectatee.v_angle;
- self.frozen = spectatee.frozen;
- self.revive_progress = spectatee.revive_progress;
- if(!self.BUTTON_USE)
- self.fixangle = true;
- setorigin(self, spectatee.origin);
- setsize(self, spectatee.mins, spectatee.maxs);
- SetZoomState(spectatee.zoomstate);
-
- anticheat_spectatecopy(spectatee);
- self.hud = spectatee.hud;
+ void SpectateCopy(entity this, entity spectatee)
+ {
+ TC(Client, this); TC(Client, spectatee);
+
+ MUTATOR_CALLHOOK(SpectateCopy, spectatee, this);
+ PS(this) = PS(spectatee);
+ this.armortype = spectatee.armortype;
+ this.armorvalue = spectatee.armorvalue;
+ this.ammo_cells = spectatee.ammo_cells;
+ this.ammo_plasma = spectatee.ammo_plasma;
+ this.ammo_shells = spectatee.ammo_shells;
+ this.ammo_nails = spectatee.ammo_nails;
+ this.ammo_rockets = spectatee.ammo_rockets;
+ this.ammo_fuel = spectatee.ammo_fuel;
+ this.clip_load = spectatee.clip_load;
+ this.clip_size = spectatee.clip_size;
+ this.effects = spectatee.effects & EFMASK_CHEAP; // eat performance
+ this.health = spectatee.health;
+ this.impulse = 0;
+ this.items = spectatee.items;
+ this.last_pickup = spectatee.last_pickup;
+ this.hit_time = spectatee.hit_time;
+ this.strength_finished = spectatee.strength_finished;
+ this.invincible_finished = spectatee.invincible_finished;
+ this.pressedkeys = spectatee.pressedkeys;
+ this.weapons = spectatee.weapons;
+ this.vortex_charge = spectatee.vortex_charge;
+ this.vortex_chargepool_ammo = spectatee.vortex_chargepool_ammo;
+ this.hagar_load = spectatee.hagar_load;
+ this.arc_heat_percent = spectatee.arc_heat_percent;
+ this.minelayer_mines = spectatee.minelayer_mines;
+ this.punchangle = spectatee.punchangle;
+ this.view_ofs = spectatee.view_ofs;
+ this.velocity = spectatee.velocity;
+ this.dmg_take = spectatee.dmg_take;
+ this.dmg_save = spectatee.dmg_save;
+ this.dmg_inflictor = spectatee.dmg_inflictor;
+ this.v_angle = spectatee.v_angle;
+ this.angles = spectatee.v_angle;
+ STAT(FROZEN, this) = STAT(FROZEN, spectatee);
+ this.revive_progress = spectatee.revive_progress;
+ if(!PHYS_INPUT_BUTTON_USE(this))
+ this.fixangle = true;
+ setorigin(this, spectatee.origin);
+ setsize(this, spectatee.mins, spectatee.maxs);
+ SetZoomState(this, spectatee.zoomstate);
+
+ anticheat_spectatecopy(this, spectatee);
+ this.hud = spectatee.hud;
if(spectatee.vehicle)
{
- self.fixangle = false;
- //self.velocity = spectatee.vehicle.velocity;
- self.vehicle_health = spectatee.vehicle_health;
- self.vehicle_shield = spectatee.vehicle_shield;
- self.vehicle_energy = spectatee.vehicle_energy;
- self.vehicle_ammo1 = spectatee.vehicle_ammo1;
- self.vehicle_ammo2 = spectatee.vehicle_ammo2;
- self.vehicle_reload1 = spectatee.vehicle_reload1;
- self.vehicle_reload2 = spectatee.vehicle_reload2;
-
- msg_entity = self;
+ this.fixangle = false;
+ //this.velocity = spectatee.vehicle.velocity;
+ this.vehicle_health = spectatee.vehicle_health;
+ this.vehicle_shield = spectatee.vehicle_shield;
+ this.vehicle_energy = spectatee.vehicle_energy;
+ this.vehicle_ammo1 = spectatee.vehicle_ammo1;
+ this.vehicle_ammo2 = spectatee.vehicle_ammo2;
+ this.vehicle_reload1 = spectatee.vehicle_reload1;
+ this.vehicle_reload2 = spectatee.vehicle_reload2;
+
+ msg_entity = this;
WriteByte (MSG_ONE, SVC_SETVIEWANGLES);
WriteAngle(MSG_ONE, spectatee.v_angle.x);
WriteAngle(MSG_ONE, spectatee.v_angle.z);
//WriteByte (MSG_ONE, SVC_SETVIEW);
- // WriteEntity(MSG_ONE, self);
+ // WriteEntity(MSG_ONE, this);
//makevectors(spectatee.v_angle);
- //setorigin(self, spectatee.origin - v_forward * 400 + v_up * 300);*/
+ //setorigin(this, spectatee.origin - v_forward * 400 + v_up * 300);*/
}
}
- float SpectateUpdate()
+ bool SpectateUpdate(entity this)
{
- if(!self.enemy)
- return 0;
+ if(!this.enemy)
+ return false;
- if(!IS_PLAYER(self.enemy) || self == self.enemy)
+ if(!IS_PLAYER(this.enemy) || this == this.enemy)
{
- SetSpectator(self, world);
- return 0;
+ SetSpectatee(this, NULL);
+ return false;
}
- SpectateCopy(self.enemy);
+ SpectateCopy(this, this.enemy);
- return 1;
+ return true;
}
- float SpectateSet()
+ bool SpectateSet(entity this)
{
- if(!IS_PLAYER(self.enemy))
+ if(!IS_PLAYER(this.enemy))
return false;
- ClientData_Touch(self.enemy);
++ ClientData_Touch(this.enemy);
+
- msg_entity = self;
+ msg_entity = this;
WriteByte(MSG_ONE, SVC_SETVIEW);
- WriteEntity(MSG_ONE, self.enemy);
- //stuffcmd(self, "set viewsize $tmpviewsize \n");
- self.movetype = MOVETYPE_NONE;
- accuracy_resend(self);
+ WriteEntity(MSG_ONE, this.enemy);
+ this.movetype = MOVETYPE_NONE;
+ accuracy_resend(this);
- if(!SpectateUpdate())
- PutObserverInServer();
+ if(!SpectateUpdate(this))
+ PutObserverInServer(this);
return true;
}
- void SetSpectator(entity player, entity spectatee)
+ void SetSpectatee(entity this, entity spectatee)
{
- entity old_spectatee = player.enemy;
+ entity old_spectatee = this.enemy;
- player.enemy = spectatee;
+ this.enemy = spectatee;
// WEAPONTODO
// these are required to fix the spectator bug with arc
if(old_spectatee && old_spectatee.arc_beam) { old_spectatee.arc_beam.SendFlags |= ARC_SF_SETTINGS; }
- if(player.enemy && player.enemy.arc_beam) { player.enemy.arc_beam.SendFlags |= ARC_SF_SETTINGS; }
+ if(this.enemy && this.enemy.arc_beam) { this.enemy.arc_beam.SendFlags |= ARC_SF_SETTINGS; }
+
+ // needed to update spectator list
+ if(old_spectatee) { ClientData_Touch(old_spectatee); }
}
- float Spectate(entity pl)
- {
- if(g_ca && !autocvar_g_ca_spectate_enemies && self.caplayer)
- if(DIFF_TEAM(pl, self))
- return 0;
-
- SetSpectator(self, pl);
- return SpectateSet();
- }
-
- // Returns next available player to spectate if g_ca_spectate_enemies == 0
- entity CA_SpectateNext(entity start)
+ bool Spectate(entity this, entity pl)
{
- if(SAME_TEAM(start, self)) { return start; }
-
- other = start;
- // continue from current player
- while(other && DIFF_TEAM(other, self))
- other = find(other, classname, "player");
-
- if (!other)
- {
- // restart from begining
- other = find(other, classname, "player");
- while(other && DIFF_TEAM(other, self))
- other = find(other, classname, "player");
- }
+ if(MUTATOR_CALLHOOK(SpectateSet, this, pl))
+ return false;
+ pl = M_ARGV(1, entity);
- return other;
+ SetSpectatee(this, pl);
+ return SpectateSet(this);
}
- float SpectateNext()
+ bool SpectateNext(entity this)
{
- other = find(self.enemy, classname, "player");
+ other = find(this.enemy, classname, STR_PLAYER);
- if (g_ca && !autocvar_g_ca_spectate_enemies && self.caplayer)
- {
- // CA and ca players when spectating enemies is forbidden
- other = CA_SpectateNext(other);
- }
- else
- {
- // other modes and ca spectators or spectating enemies is allowed
- if (!other)
- other = find(other, classname, "player");
- }
+ if (MUTATOR_CALLHOOK(SpectateNext, this, other))
+ other = M_ARGV(1, entity);
+ else if (!other)
+ other = find(other, classname, STR_PLAYER);
- if(other) { SetSpectator(self, other); }
+ if(other) { SetSpectatee(this, other); }
- return SpectateSet();
+ return SpectateSet(this);
}
- float SpectatePrev()
+ bool SpectatePrev(entity this)
{
// NOTE: chain order is from the highest to the lower entnum (unlike find)
- other = findchain(classname, "player");
+ other = findchain(classname, STR_PLAYER);
if (!other) // no player
return false;
entity first = other;
// skip players until current spectated player
- if(self.enemy)
- while(other && other != self.enemy)
+ if(this.enemy)
+ while(other && other != this.enemy)
other = other.chain;
- if (g_ca && !autocvar_g_ca_spectate_enemies && self.caplayer)
+ switch (MUTATOR_CALLHOOK(SpectatePrev, this, other, first))
{
- do { other = other.chain; }
- while(other && other.team != self.team);
-
- if (!other)
+ case MUT_SPECPREV_FOUND:
+ other = M_ARGV(1, entity);
+ break;
+ case MUT_SPECPREV_RETURN:
+ other = M_ARGV(1, entity);
+ return true;
+ case MUT_SPECPREV_CONTINUE:
+ default:
{
- other = first;
- while(other.team != self.team)
+ if(other.chain)
other = other.chain;
- if(other == self.enemy)
- return true;
+ else
+ other = first;
+ break;
}
}
- else
- {
- if(other.chain)
- other = other.chain;
- else
- other = first;
- }
- SetSpectator(self, other);
- return SpectateSet();
+
+ SetSpectatee(this, other);
+ return SpectateSet(this);
}
/*
Update a respawn countdown display.
=============
*/
- void ShowRespawnCountdown()
+ void ShowRespawnCountdown(entity this)
{
float number;
- if(self.deadflag == DEAD_NO) // just respawned?
+ if(!IS_DEAD(this)) // just respawned?
return;
else
{
- number = ceil(self.respawn_time - time);
+ number = ceil(this.respawn_time - time);
if(number <= 0)
return;
- if(number <= self.respawn_countdown)
+ if(number <= this.respawn_countdown)
{
- self.respawn_countdown = number - 1;
- if(ceil(self.respawn_time - (time + 0.5)) == number) // only say it if it is the same number even in 0.5s; to prevent overlapping sounds
- { Send_Notification(NOTIF_ONE, self, MSG_ANNCE, Announcer_PickNumber(CNT_RESPAWN, number)); }
+ this.respawn_countdown = number - 1;
+ if(ceil(this.respawn_time - (time + 0.5)) == number) // only say it if it is the same number even in 0.5s; to prevent overlapping sounds
+ { Send_Notification(NOTIF_ONE, this, MSG_ANNCE, Announcer_PickNumber(CNT_RESPAWN, number)); }
}
}
}
- void LeaveSpectatorMode()
+ void LeaveSpectatorMode(entity this)
{
- if(self.caplayer)
+ if(this.caplayer)
return;
- if(nJoinAllowed(self))
+ if(nJoinAllowed(this, this))
{
- if(!teamplay || autocvar_g_campaign || autocvar_g_balance_teams || (self.wasplayer && autocvar_g_changeteam_banned) || self.team_forced > 0)
+ if(!teamplay || autocvar_g_campaign || autocvar_g_balance_teams || (this.wasplayer && autocvar_g_changeteam_banned) || this.team_forced > 0)
{
- self.classname = "player";
- nades_RemoveBonus(self);
+ TRANSMUTE(Player, this);
- SetSpectator(self, world);
++ SetSpectatee(self, world);
+
if(autocvar_g_campaign || autocvar_g_balance_teams)
- { JoinBestTeam(self, false, true); }
+ { JoinBestTeam(this, false, true); }
if(autocvar_g_campaign)
- { campaign_bots_may_start = 1; }
+ { campaign_bots_may_start = true; }
- Kill_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER_CPID, CPID_PREVENT_JOIN);
+ Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_PREVENT_JOIN);
- PutClientInServer();
+ WITHSELF(this, PutClientInServer());
- if(IS_PLAYER(self)) { Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_JOIN_PLAY, self.netname); }
+ if(IS_PLAYER(this)) { Send_Notification(NOTIF_ALL, world, MSG_INFO, ((teamplay && this.team != -1) ? APP_TEAM_ENT(this, INFO_JOIN_PLAY_TEAM) : INFO_JOIN_PLAY), this.netname); }
}
else
- stuffcmd(self, "menu_showteamselect\n");
+ stuffcmd(this, "menu_showteamselect\n");
}
else
{
// Player may not join because g_maxplayers is set
- Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_JOIN_PREVENT);
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_JOIN_PREVENT);
}
}
* it checks whether the number of currently playing players exceeds g_maxplayers.
* @return int number of free slots for players, 0 if none
*/
- float nJoinAllowed(entity ignore) {
+ bool nJoinAllowed(entity this, entity ignore)
+ {
if(!ignore)
// this is called that way when checking if anyone may be able to join (to build qcstatus)
// so report 0 free slots if restricted
{
if(autocvar_g_forced_team_otherwise == "spectate")
- return 0;
+ return false;
if(autocvar_g_forced_team_otherwise == "spectator")
- return 0;
+ return false;
}
- if(self.team_forced < 0)
- return 0; // forced spectators can never join
+ if(this.team_forced < 0)
+ return false; // forced spectators can never join
// TODO simplify this
- entity e;
- float totalClients = 0;
- FOR_EACH_CLIENT(e)
- if(e != ignore)
- totalClients += 1;
+ int totalClients = 0;
+ int currentlyPlaying = 0;
+ FOREACH_CLIENT(true, LAMBDA(
+ if(it != ignore)
+ ++totalClients;
+ if(IS_REAL_CLIENT(it))
+ if(IS_PLAYER(it) || it.caplayer)
+ ++currentlyPlaying;
+ ));
if (!autocvar_g_maxplayers)
return maxclients - totalClients;
- float currentlyPlaying = 0;
- FOR_EACH_REALCLIENT(e)
- if(IS_PLAYER(e) || e.caplayer)
- currentlyPlaying += 1;
-
if(currentlyPlaying < autocvar_g_maxplayers)
return min(maxclients - totalClients, autocvar_g_maxplayers - currentlyPlaying);
- return 0;
+ return false;
}
/**
* Checks whether the client is an observer or spectator, if so, he will get kicked after
* g_maxplayers_spectator_blocktime seconds
*/
- void checkSpectatorBlock() {
- if(IS_SPEC(self) || IS_OBSERVER(self))
- if(!self.caplayer)
- if(IS_REAL_CLIENT(self))
- {
- if( time > (self.spectatortime + autocvar_g_maxplayers_spectator_blocktime) ) {
- Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_QUIT_KICK_SPECTATING);
- dropclient(self);
+ void checkSpectatorBlock(entity this)
+ {
+ if(IS_SPEC(this) || IS_OBSERVER(this))
+ if(!this.caplayer)
+ if(IS_REAL_CLIENT(this))
+ {
+ if( time > (this.spectatortime + autocvar_g_maxplayers_spectator_blocktime) ) {
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_QUIT_KICK_SPECTATING);
+ dropclient(this);
}
}
}
- void PrintWelcomeMessage()
+ void PrintWelcomeMessage(entity this)
{
- if(self.motd_actived_time == 0)
+ if(this.motd_actived_time == 0)
{
if (autocvar_g_campaign) {
- if ((IS_PLAYER(self) && self.BUTTON_INFO) || (!IS_PLAYER(self))) {
- self.motd_actived_time = time;
- Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_MOTD, campaign_message);
+ if ((IS_PLAYER(this) && PHYS_INPUT_BUTTON_INFO(this)) || (!IS_PLAYER(this))) {
+ this.motd_actived_time = time;
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_MOTD, campaign_message);
}
} else {
- if (self.BUTTON_INFO) {
- self.motd_actived_time = time;
- Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_MOTD, getwelcomemessage());
+ if (PHYS_INPUT_BUTTON_INFO(this)) {
+ this.motd_actived_time = time;
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_MOTD, getwelcomemessage(this));
}
}
}
- else if(self.motd_actived_time > 0) // showing MOTD or campaign message
+ else if(this.motd_actived_time > 0) // showing MOTD or campaign message
{
if (autocvar_g_campaign) {
- if (self.BUTTON_INFO)
- self.motd_actived_time = time;
- else if ((time - self.motd_actived_time > 2) && IS_PLAYER(self)) { // hide it some seconds after BUTTON_INFO has been released
- self.motd_actived_time = 0;
- Kill_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER_CPID, CPID_MOTD);
+ if (PHYS_INPUT_BUTTON_INFO(this))
+ this.motd_actived_time = time;
+ else if ((time - this.motd_actived_time > 2) && IS_PLAYER(this)) { // hide it some seconds after BUTTON_INFO has been released
+ this.motd_actived_time = 0;
+ Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_MOTD);
}
} else {
- if (self.BUTTON_INFO)
- self.motd_actived_time = time;
- else if (time - self.motd_actived_time > 2) { // hide it some seconds after BUTTON_INFO has been released
- self.motd_actived_time = 0;
- Kill_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER_CPID, CPID_MOTD);
+ if (PHYS_INPUT_BUTTON_INFO(this))
+ this.motd_actived_time = time;
+ else if (time - this.motd_actived_time > 2) { // hide it some seconds after BUTTON_INFO has been released
+ this.motd_actived_time = 0;
+ Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_MOTD);
}
}
}
- else //if(self.motd_actived_time < 0) // just connected, motd is active
+ else //if(this.motd_actived_time < 0) // just connected, motd is active
{
- if(self.BUTTON_INFO) // BUTTON_INFO hides initial MOTD
- self.motd_actived_time = -2; // wait until BUTTON_INFO gets released
- else if(self.motd_actived_time == -2 || IS_PLAYER(self))
+ if(PHYS_INPUT_BUTTON_INFO(this)) // BUTTON_INFO hides initial MOTD
+ this.motd_actived_time = -2; // wait until BUTTON_INFO gets released
+ else if(this.motd_actived_time == -2 || IS_PLAYER(this) || IS_SPEC(this))
{
// instanctly hide MOTD
- self.motd_actived_time = 0;
- Kill_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER_CPID, CPID_MOTD);
+ this.motd_actived_time = 0;
+ Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_MOTD);
}
}
}
- void ObserverThink()
+ void ObserverThink(entity this)
{
+ if ( this.impulse )
+ {
+ MinigameImpulse(this, this.impulse);
+ this.impulse = 0;
+ }
float prefered_movetype;
- if (self.flags & FL_JUMPRELEASED) {
- if (self.BUTTON_JUMP && !self.version_mismatch) {
- self.flags &= ~FL_JUMPRELEASED;
- self.flags |= FL_SPAWNING;
- } else if(self.BUTTON_ATCK && !self.version_mismatch) {
- self.flags &= ~FL_JUMPRELEASED;
- if(SpectateNext()) {
- self.classname = "spectator";
+ if (this.flags & FL_JUMPRELEASED) {
+ if (PHYS_INPUT_BUTTON_JUMP(this) && !this.version_mismatch) {
+ this.flags &= ~FL_JUMPRELEASED;
+ this.flags |= FL_SPAWNING;
+ } else if(PHYS_INPUT_BUTTON_ATCK(this) && !this.version_mismatch) {
+ this.flags &= ~FL_JUMPRELEASED;
+ if(SpectateNext(this)) {
+ TRANSMUTE(Spectator, this);
}
} else {
- prefered_movetype = ((!self.BUTTON_USE ? self.cvar_cl_clippedspectating : !self.cvar_cl_clippedspectating) ? MOVETYPE_FLY_WORLDONLY : MOVETYPE_NOCLIP);
- if (self.movetype != prefered_movetype)
- self.movetype = prefered_movetype;
+ prefered_movetype = ((!PHYS_INPUT_BUTTON_USE(this) ? this.cvar_cl_clippedspectating : !this.cvar_cl_clippedspectating) ? MOVETYPE_FLY_WORLDONLY : MOVETYPE_NOCLIP);
+ if (this.movetype != prefered_movetype)
+ this.movetype = prefered_movetype;
}
} else {
- if (!(self.BUTTON_ATCK || self.BUTTON_JUMP)) {
- self.flags |= FL_JUMPRELEASED;
- if(self.flags & FL_SPAWNING)
+ if (!(PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_JUMP(this))) {
+ this.flags |= FL_JUMPRELEASED;
+ if(this.flags & FL_SPAWNING)
{
- self.flags &= ~FL_SPAWNING;
- LeaveSpectatorMode();
+ this.flags &= ~FL_SPAWNING;
+ LeaveSpectatorMode(this);
return;
}
}
}
}
- void SpectatorThink()
+ void SpectatorThink(entity this)
{
- if (self.flags & FL_JUMPRELEASED) {
- if (self.BUTTON_JUMP && !self.version_mismatch) {
- self.flags &= ~FL_JUMPRELEASED;
- self.flags |= FL_SPAWNING;
- } else if(self.BUTTON_ATCK || self.impulse == 10 || self.impulse == 15 || self.impulse == 18 || (self.impulse >= 200 && self.impulse <= 209)) {
- self.flags &= ~FL_JUMPRELEASED;
- if(SpectateNext()) {
- self.classname = "spectator";
+ if ( this.impulse )
+ {
+ if(MinigameImpulse(this, this.impulse))
+ this.impulse = 0;
+ }
+ if (this.flags & FL_JUMPRELEASED) {
+ if (PHYS_INPUT_BUTTON_JUMP(this) && !this.version_mismatch) {
+ this.flags &= ~FL_JUMPRELEASED;
+ this.flags |= FL_SPAWNING;
+ } else if(PHYS_INPUT_BUTTON_ATCK(this) || this.impulse == 10 || this.impulse == 15 || this.impulse == 18 || (this.impulse >= 200 && this.impulse <= 209)) {
+ this.flags &= ~FL_JUMPRELEASED;
+ if(SpectateNext(this)) {
+ TRANSMUTE(Spectator, this);
} else {
- self.classname = "observer";
- PutClientInServer();
+ TRANSMUTE(Observer, this);
+ WITHSELF(this, PutClientInServer());
}
- self.impulse = 0;
- } else if(self.impulse == 12 || self.impulse == 16 || self.impulse == 19 || (self.impulse >= 220 && self.impulse <= 229)) {
- self.flags &= ~FL_JUMPRELEASED;
- if(SpectatePrev()) {
- self.classname = "spectator";
+ this.impulse = 0;
+ } else if(this.impulse == 12 || this.impulse == 16 || this.impulse == 19 || (this.impulse >= 220 && this.impulse <= 229)) {
+ this.flags &= ~FL_JUMPRELEASED;
+ if(SpectatePrev(this)) {
+ TRANSMUTE(Spectator, this);
} else {
- self.classname = "observer";
- PutClientInServer();
+ TRANSMUTE(Observer, this);
+ WITHSELF(this, PutClientInServer());
}
- self.impulse = 0;
- } else if (self.BUTTON_ATCK2) {
- self.flags &= ~FL_JUMPRELEASED;
- self.classname = "observer";
- PutClientInServer();
+ this.impulse = 0;
+ } else if (PHYS_INPUT_BUTTON_ATCK2(this)) {
+ this.flags &= ~FL_JUMPRELEASED;
+ TRANSMUTE(Observer, this);
+ WITHSELF(this, PutClientInServer());
} else {
- if(!SpectateUpdate())
- PutObserverInServer();
+ if(!SpectateUpdate(this))
+ PutObserverInServer(this);
}
} else {
- if (!(self.BUTTON_ATCK || self.BUTTON_ATCK2)) {
- self.flags |= FL_JUMPRELEASED;
- if(self.flags & FL_SPAWNING)
+ if (!(PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_ATCK2(this))) {
+ this.flags |= FL_JUMPRELEASED;
+ if(this.flags & FL_SPAWNING)
{
- self.flags &= ~FL_SPAWNING;
- LeaveSpectatorMode();
+ this.flags &= ~FL_SPAWNING;
+ LeaveSpectatorMode(this);
return;
}
}
- if(!SpectateUpdate())
- PutObserverInServer();
+ if(!SpectateUpdate(this))
+ PutObserverInServer(this);
}
- self.flags |= FL_CLIENT | FL_NOTARGET;
+ this.flags |= FL_CLIENT | FL_NOTARGET;
}
- void PlayerUseKey()
+ void vehicles_enter (entity pl, entity veh);
+ void PlayerUseKey(entity this)
{
- if (!IS_PLAYER(self))
+ if (!IS_PLAYER(this))
return;
- if(self.vehicle)
+ if(this.vehicle)
{
- vehicles_exit(VHEF_NORMAL);
- return;
+ if(!gameover)
+ {
+ vehicles_exit(this.vehicle, VHEF_NORMAL);
+ return;
+ }
}
-
- // a use key was pressed; call handlers
- MUTATOR_CALLHOOK(PlayerUseKey);
- }
-
- float isInvisibleString(string s)
- {
- float i, n, c;
- s = strdecolorize(s);
- for((i = 0), (n = strlen(s)); i < n; ++i)
+ else if(autocvar_g_vehicles_enter)
{
- c = str2chr(s, i);
- switch(c)
+ if(!STAT(FROZEN, this))
+ if(!IS_DEAD(this))
+ if(!gameover)
{
- case 0:
- case 32: // space
- break;
- case 192: // charmap space
- if (!autocvar_utf8_enable)
- break;
- return false;
- case 160: // space in unicode fonts
- case 0xE000 + 192: // utf8 charmap space
- if (autocvar_utf8_enable)
- break;
- default:
- return false;
+ entity head, closest_target = world;
+ head = WarpZone_FindRadius(this.origin, autocvar_g_vehicles_enter_radius, true);
+
+ while(head) // find the closest acceptable target to enter
+ {
+ if(head.vehicle_flags & VHF_ISVEHICLE)
+ if(!IS_DEAD(head))
+ if(!head.owner || ((head.vehicle_flags & VHF_MULTISLOT) && SAME_TEAM(head.owner, this)))
+ if(head.takedamage != DAMAGE_NO)
+ {
+ if(closest_target)
+ {
+ if(vlen2(this.origin - head.origin) < vlen2(this.origin - closest_target.origin))
+ { closest_target = head; }
+ }
+ else { closest_target = head; }
+ }
+
+ head = head.chain;
+ }
+
+ if(closest_target) { vehicles_enter(this, closest_target); return; }
}
}
- return true;
+
+ // a use key was pressed; call handlers
+ MUTATOR_CALLHOOK(PlayerUseKey, this);
}
+
/*
=============
PlayerPreThink
=============
*/
.float usekeypressed;
- void() nexball_setstatus;
+ .float last_vehiclecheck;
.int items_added;
- void PlayerPreThink (void)
- {
- WarpZone_PlayerPhysics_FixVAngle();
+ void PlayerPreThink ()
+ {ENGINE_EVENT();
+ WarpZone_PlayerPhysics_FixVAngle(this);
- self.stat_game_starttime = game_starttime;
- self.stat_round_starttime = round_starttime;
- self.stat_allow_oldvortexbeam = autocvar_g_allow_oldvortexbeam;
- self.stat_leadlimit = autocvar_leadlimit;
+ STAT(GAMESTARTTIME, this) = game_starttime;
+ STAT(ROUNDSTARTTIME, this) = round_starttime;
+ STAT(ALLOW_OLDVORTEXBEAM, this) = autocvar_g_allow_oldvortexbeam;
+ STAT(LEADLIMIT, this) = autocvar_leadlimit;
- if(frametime)
- {
+ STAT(WEAPONSINMAP, this) = weaponsInMap;
+
+ if (frametime) {
// physics frames: update anticheat stuff
- anticheat_prethink();
+ anticheat_prethink(this);
}
- if(blockSpectators && frametime)
- // WORKAROUND: only use dropclient in server frames (frametime set). Never use it in cl_movement frames (frametime zero).
- checkSpectatorBlock();
+ if (blockSpectators && frametime) {
+ // WORKAROUND: only use dropclient in server frames (frametime set).
+ // Never use it in cl_movement frames (frametime zero).
+ checkSpectatorBlock(this);
+ }
- zoomstate_set = 0;
+ zoomstate_set = false;
- // Savage: Check for nameless players
- if (isInvisibleString(self.netname)) {
- string new_name = strzone(strcat("Player@", ftos(self.playerid)));
- if(autocvar_sv_eventlog)
- GameLogEcho(strcat(":name:", ftos(self.playerid), ":", new_name));
- if(self.netname_previous)
- strunzone(self.netname_previous);
- self.netname_previous = strzone(new_name);
- self.netname = self.netname_previous;
- // stuffcmd(self, strcat("name ", self.netname, "\n"));
- } else if(self.netname_previous != self.netname) {
- if(autocvar_sv_eventlog)
- GameLogEcho(strcat(":name:", ftos(self.playerid), ":", self.netname));
- if(self.netname_previous)
- strunzone(self.netname_previous);
- self.netname_previous = strzone(self.netname);
+ // Check for nameless players
+ if (isInvisibleString(this.netname)) {
+ this.netname = strzone(sprintf("Player#%d", this.playerid));
+ // stuffcmd(this, strcat("name ", this.netname, "\n")); // maybe?
+ }
+ if (this.netname != this.netname_previous) {
+ if (autocvar_sv_eventlog) {
+ GameLogEcho(strcat(":name:", ftos(this.playerid), ":", this.netname));
+ }
+ if (this.netname_previous) strunzone(this.netname_previous);
+ this.netname_previous = strzone(this.netname);
}
// version nagging
- if(self.version_nagtime)
- if(self.cvar_g_xonoticversion)
- if(time > self.version_nagtime)
- {
- // don't notify git users
- if(strstr(self.cvar_g_xonoticversion, "git", 0) < 0 && strstr(self.cvar_g_xonoticversion, "autobuild", 0) < 0)
- {
- if(strstr(autocvar_g_xonoticversion, "git", 0) >= 0 || strstr(autocvar_g_xonoticversion, "autobuild", 0) >= 0)
- {
- // notify release users if connecting to git
- dprint("^1NOTE^7 to ", self.netname, "^7 - the server is running ^3Xonotic ", autocvar_g_xonoticversion, " (beta)^7, you have ^3Xonotic ", self.cvar_g_xonoticversion, "^1\n");
- Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_VERSION_BETA, autocvar_g_xonoticversion, self.cvar_g_xonoticversion);
- }
- else
- {
- float r;
- r = vercmp(self.cvar_g_xonoticversion, autocvar_g_xonoticversion);
- if(r < 0)
- {
- // give users new version
- dprint("^1NOTE^7 to ", self.netname, "^7 - ^3Xonotic ", autocvar_g_xonoticversion, "^7 is out, and you still have ^3Xonotic ", self.cvar_g_xonoticversion, "^1 - get the update from ^4http://www.xonotic.org/^1!\n");
- Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_VERSION_OUTDATED, autocvar_g_xonoticversion, self.cvar_g_xonoticversion);
- }
- else if(r > 0)
- {
- // notify users about old server version
- print("^1NOTE^7 to ", self.netname, "^7 - the server is running ^3Xonotic ", autocvar_g_xonoticversion, "^7, you have ^3Xonotic ", self.cvar_g_xonoticversion, "^1\n");
- Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_VERSION_OLD, autocvar_g_xonoticversion, self.cvar_g_xonoticversion);
- }
- }
- }
- self.version_nagtime = 0;
- }
+ if (this.version_nagtime && this.cvar_g_xonoticversion && time > this.version_nagtime) {
+ this.version_nagtime = 0;
+ if (strstrofs(this.cvar_g_xonoticversion, "git", 0) >= 0 || strstrofs(this.cvar_g_xonoticversion, "autobuild", 0) >= 0) {
+ // git client
+ } else if (strstrofs(autocvar_g_xonoticversion, "git", 0) >= 0 || strstrofs(autocvar_g_xonoticversion, "autobuild", 0) >= 0) {
+ // git server
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_VERSION_BETA, autocvar_g_xonoticversion, this.cvar_g_xonoticversion);
+ } else {
+ int r = vercmp(this.cvar_g_xonoticversion, autocvar_g_xonoticversion);
+ if (r < 0) { // old client
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_VERSION_OUTDATED, autocvar_g_xonoticversion, this.cvar_g_xonoticversion);
+ } else if (r > 0) { // old server
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_VERSION_OLD, autocvar_g_xonoticversion, this.cvar_g_xonoticversion);
+ }
+ }
+ }
// GOD MODE info
- if(!(self.flags & FL_GODMODE)) if(self.max_armorvalue)
+ if (!(this.flags & FL_GODMODE) && this.max_armorvalue)
{
- Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_GODMODE_OFF, self.max_armorvalue);
- self.max_armorvalue = 0;
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_GODMODE_OFF, this.max_armorvalue);
+ this.max_armorvalue = 0;
}
- #ifdef TETRIS
- if (TetrisPreFrame())
- return;
- #endif
-
- if(self.frozen == 2)
+ if (STAT(FROZEN, this) == 2)
{
- self.revive_progress = bound(0, self.revive_progress + frametime * self.revive_speed, 1);
- self.health = max(1, self.revive_progress * start_health);
- self.iceblock.alpha = bound(0.2, 1 - self.revive_progress, 1);
+ this.revive_progress = bound(0, this.revive_progress + frametime * this.revive_speed, 1);
+ this.health = max(1, this.revive_progress * start_health);
+ this.iceblock.alpha = bound(0.2, 1 - this.revive_progress, 1);
- if(self.revive_progress >= 1)
- Unfreeze(self);
+ if (this.revive_progress >= 1)
+ Unfreeze(this);
}
- else if(self.frozen == 3)
+ else if (STAT(FROZEN, this) == 3)
{
- self.revive_progress = bound(0, self.revive_progress - frametime * self.revive_speed, 1);
- self.health = max(0, autocvar_g_nades_ice_health + (start_health-autocvar_g_nades_ice_health) * self.revive_progress );
+ this.revive_progress = bound(0, this.revive_progress - frametime * this.revive_speed, 1);
+ this.health = max(0, autocvar_g_nades_ice_health + (start_health-autocvar_g_nades_ice_health) * this.revive_progress );
- if(self.health < 1)
+ if (this.health < 1)
{
- if(self.vehicle)
- vehicles_exit(VHEF_RELESE);
- self.event_damage(self, self.frozen_by, 1, DEATH_NADE_ICE_FREEZE, self.origin, '0 0 0');
+ if (this.vehicle)
+ vehicles_exit(this.vehicle, VHEF_RELEASE);
+ if(this.event_damage)
+ this.event_damage(this, this, this.frozen_by, 1, DEATH_NADE_ICE_FREEZE.m_id, this.origin, '0 0 0');
}
- else if ( self.revive_progress <= 0 )
- Unfreeze(self);
+ else if (this.revive_progress <= 0)
+ Unfreeze(this);
}
- MUTATOR_CALLHOOK(PlayerPreThink);
+ MUTATOR_CALLHOOK(PlayerPreThink, this);
- if(!self.cvar_cl_newusekeysupported) // FIXME remove this - it was a stupid idea to begin with, we can JUST use the button
+ if(autocvar_g_vehicles_enter)
+ if(time > this.last_vehiclecheck)
+ if(IS_PLAYER(this))
+ if(!gameover)
+ if(!STAT(FROZEN, this))
+ if(!this.vehicle)
+ if(!IS_DEAD(this))
{
- if(self.BUTTON_USE && !self.usekeypressed)
- PlayerUseKey();
- self.usekeypressed = self.BUTTON_USE;
- }
+ entity veh;
+ for(veh = world; (veh = findflags(veh, vehicle_flags, VHF_ISVEHICLE)); )
+ if(vdist(veh.origin - this.origin, <, autocvar_g_vehicles_enter_radius))
+ if(!IS_DEAD(veh))
+ if(veh.takedamage != DAMAGE_NO)
+ if((veh.vehicle_flags & VHF_MULTISLOT) && SAME_TEAM(veh.owner, this))
+ Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_VEHICLE_ENTER_GUNNER);
+ else if(!veh.owner)
+ if(!veh.team || SAME_TEAM(this, veh))
+ Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_VEHICLE_ENTER);
+ else if(autocvar_g_vehicles_steal)
+ Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_VEHICLE_ENTER_STEAL);
- if(IS_REAL_CLIENT(self))
- PrintWelcomeMessage();
+ this.last_vehiclecheck = time + 1;
+ }
- if(IS_PLAYER(self))
+ if(!this.cvar_cl_newusekeysupported) // FIXME remove this - it was a stupid idea to begin with, we can JUST use the button
{
+ if(PHYS_INPUT_BUTTON_USE(this) && !this.usekeypressed)
+ PlayerUseKey(this);
+ this.usekeypressed = PHYS_INPUT_BUTTON_USE(this);
+ }
- CheckRules_Player();
+ if (IS_REAL_CLIENT(this))
+ PrintWelcomeMessage(this);
- if (intermission_running)
- {
- IntermissionThink (); // otherwise a button could be missed between
- return; // the think tics
- }
+ if (IS_PLAYER(this)) {
+ CheckRules_Player(this);
- //don't allow the player to turn around while game is paused!
- if(timeout_status == TIMEOUT_ACTIVE) {
- // FIXME turn this into CSQC stuff
- self.v_angle = self.lastV_angle;
- self.angles = self.lastV_angle;
- self.fixangle = true;
+ if (intermission_running) {
+ IntermissionThink(this);
+ return;
}
- if(frametime)
- {
- if(self.weapon == WEP_VORTEX && WEP_CVAR(vortex, charge))
- {
- self.weaponentity_glowmod_x = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit));
- self.weaponentity_glowmod_y = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit));
- self.weaponentity_glowmod_z = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit));
-
- if(self.vortex_charge > WEP_CVAR(vortex, charge_animlimit))
- {
- self.weaponentity_glowmod_x = self.weaponentity_glowmod.x + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit));
- self.weaponentity_glowmod_y = self.weaponentity_glowmod.y + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit));
- self.weaponentity_glowmod_z = self.weaponentity_glowmod.z + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit));
- }
- }
- else
- self.weaponentity_glowmod = colormapPaletteColor(self.clientcolors & 0x0F, true) * 2;
-
- player_powerups();
+ if (timeout_status == TIMEOUT_ACTIVE) {
+ // don't allow the player to turn around while game is paused
+ // FIXME turn this into CSQC stuff
+ this.v_angle = this.lastV_angle;
+ this.angles = this.lastV_angle;
+ this.fixangle = true;
}
- if (self.deadflag != DEAD_NO)
- {
- if(self.personal && g_race_qualifying)
- {
- if(time > self.respawn_time)
- {
- self.respawn_time = time + 1; // only retry once a second
- self.stat_respawn_time = self.respawn_time;
- respawn();
- self.impulse = 141;
- }
- }
- else
- {
- float button_pressed;
- if(frametime)
- player_anim();
- button_pressed = (self.BUTTON_ATCK || self.BUTTON_JUMP || self.BUTTON_ATCK2 || self.BUTTON_HOOK || self.BUTTON_USE);
+ if (frametime) player_powerups(this);
- if (self.deadflag == DEAD_DYING)
- {
- if((self.respawn_flags & RESPAWN_FORCE) && !autocvar_g_respawn_delay_max)
- self.deadflag = DEAD_RESPAWNING;
- else if(!button_pressed)
- self.deadflag = DEAD_DEAD;
- }
- else if (self.deadflag == DEAD_DEAD)
- {
- if(button_pressed)
- self.deadflag = DEAD_RESPAWNABLE;
- else if(time >= self.respawn_time_max && (self.respawn_flags & RESPAWN_FORCE))
- self.deadflag = DEAD_RESPAWNING;
- }
- else if (self.deadflag == DEAD_RESPAWNABLE)
- {
- if(!button_pressed)
- self.deadflag = DEAD_RESPAWNING;
+ if (IS_DEAD(this)) {
+ if (this.personal && g_race_qualifying) {
+ if (time > this.respawn_time) {
+ STAT(RESPAWN_TIME, this) = this.respawn_time = time + 1; // only retry once a second
+ respawn(this);
+ this.impulse = CHIMPULSE_SPEEDRUN.impulse;
}
- else if (self.deadflag == DEAD_RESPAWNING)
- {
- if(time > self.respawn_time)
- {
- self.respawn_time = time + 1; // only retry once a second
- self.respawn_time_max = self.respawn_time;
- respawn();
+ } else {
+ if (frametime) player_anim(this);
+ bool button_pressed = (PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_JUMP(this) || PHYS_INPUT_BUTTON_ATCK2(this) || PHYS_INPUT_BUTTON_HOOK(this) || PHYS_INPUT_BUTTON_USE(this));
+
+ if (this.deadflag == DEAD_DYING) {
+ if ((this.respawn_flags & RESPAWN_FORCE) && !(this.respawn_time < this.respawn_time_max)) {
+ this.deadflag = DEAD_RESPAWNING;
+ } else if (!button_pressed) {
+ this.deadflag = DEAD_DEAD;
+ }
+ } else if (this.deadflag == DEAD_DEAD) {
+ if (button_pressed) {
+ this.deadflag = DEAD_RESPAWNABLE;
+ } else if (time >= this.respawn_time_max && (this.respawn_flags & RESPAWN_FORCE)) {
+ this.deadflag = DEAD_RESPAWNING;
+ }
+ } else if (this.deadflag == DEAD_RESPAWNABLE) {
+ if (!button_pressed) {
+ this.deadflag = DEAD_RESPAWNING;
+ }
+ } else if (this.deadflag == DEAD_RESPAWNING) {
+ if (time > this.respawn_time) {
+ this.respawn_time = time + 1; // only retry once a second
+ this.respawn_time_max = this.respawn_time;
+ respawn(this);
}
}
- ShowRespawnCountdown();
+ ShowRespawnCountdown(this);
- if(self.respawn_flags & RESPAWN_SILENT)
- self.stat_respawn_time = 0;
- else if((self.respawn_flags & RESPAWN_FORCE) && autocvar_g_respawn_delay_max)
- self.stat_respawn_time = self.respawn_time_max;
+ if (this.respawn_flags & RESPAWN_SILENT)
+ STAT(RESPAWN_TIME, this) = 0;
+ else if ((this.respawn_flags & RESPAWN_FORCE) && this.respawn_time < this.respawn_time_max)
+ {
+ if (time < this.respawn_time)
+ STAT(RESPAWN_TIME, this) = this.respawn_time;
+ else if (this.deadflag != DEAD_RESPAWNING)
+ STAT(RESPAWN_TIME, this) = -this.respawn_time_max;
+ }
else
- self.stat_respawn_time = self.respawn_time;
+ STAT(RESPAWN_TIME, this) = this.respawn_time;
}
// if respawning, invert stat_respawn_time to indicate this, the client translates it
- if(self.deadflag == DEAD_RESPAWNING && self.stat_respawn_time > 0)
- self.stat_respawn_time *= -1;
+ if (this.deadflag == DEAD_RESPAWNING && STAT(RESPAWN_TIME, this) > 0)
+ STAT(RESPAWN_TIME, this) *= -1;
return;
}
- self.prevorigin = self.origin;
-
- float do_crouch = self.BUTTON_CROUCH;
- if(self.hook.state)
- do_crouch = 0;
- if(self.vehicle)
- do_crouch = 0;
- if(self.frozen)
- do_crouch = 0;
-
- // WEAPONTODO: THIS SHIT NEEDS TO GO EVENTUALLY
- // It cannot be predicted by the engine!
- if((self.weapon == WEP_SHOCKWAVE || self.weapon == WEP_SHOTGUN) && self.weaponentity.wframe == WFRAME_FIRE2 && time < self.weapon_nextthink)
- do_crouch = 0;
-
- if (do_crouch)
- {
- if (!self.crouch)
- {
- self.crouch = true;
- self.view_ofs = PL_CROUCH_VIEW_OFS;
- setsize (self, PL_CROUCH_MIN, PL_CROUCH_MAX);
- // setanim(self, self.anim_duck, false, true, true); // this anim is BROKEN anyway
- }
- }
- else
- {
- if (self.crouch)
- {
- tracebox(self.origin, PL_MIN, PL_MAX, self.origin, false, self);
- if (!trace_startsolid)
- {
- self.crouch = false;
- self.view_ofs = PL_VIEW_OFS;
- setsize (self, PL_MIN, PL_MAX);
- }
+ this.prevorigin = this.origin;
+
+ bool do_crouch = PHYS_INPUT_BUTTON_CROUCH(this);
+ .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+ if (this.hook.state) {
+ do_crouch = false;
+ } else if (this.vehicle) {
+ do_crouch = false;
+ } else if (STAT(FROZEN, this)) {
+ do_crouch = false;
+ } else if ((PS(this).m_weapon == WEP_SHOTGUN || PS(this).m_weapon == WEP_SHOCKWAVE) && this.(weaponentity).wframe == WFRAME_FIRE2 && time < this.(weaponentity).weapon_nextthink) {
+ // WEAPONTODO: predict
+ do_crouch = false;
+ }
+
+ if (do_crouch) {
+ if (!this.crouch) {
+ this.crouch = true;
+ this.view_ofs = STAT(PL_CROUCH_VIEW_OFS, this);
+ setsize(this, STAT(PL_CROUCH_MIN, this), STAT(PL_CROUCH_MAX, this));
+ // setanim(this, this.anim_duck, false, true, true); // this anim is BROKEN anyway
}
+ } else if (this.crouch) {
+ tracebox(this.origin, STAT(PL_MIN, this), STAT(PL_MAX, this), this.origin, false, this);
+ if (!trace_startsolid) {
+ this.crouch = false;
+ this.view_ofs = STAT(PL_VIEW_OFS, this);
+ setsize(this, STAT(PL_MIN, this), STAT(PL_MAX, this));
+ }
}
- FixPlayermodel();
-
- GrapplingHookFrame();
+ FixPlayermodel(this);
// LordHavoc: allow firing on move frames (sub-ticrate), this gives better timing on slow servers
//if(frametime)
{
- self.items &= ~self.items_added;
+ this.items &= ~this.items_added;
- W_WeaponFrame();
+ W_WeaponFrame(this);
- self.items_added = 0;
- if(self.items & IT_JETPACK)
- if(self.items & IT_FUEL_REGEN || self.ammo_fuel >= 0.01)
- self.items_added |= IT_FUEL;
+ this.items_added = 0;
+ if (this.items & ITEM_Jetpack.m_itemid && (this.items & ITEM_JetpackRegen.m_itemid || this.ammo_fuel >= 0.01))
+ this.items_added |= IT_FUEL;
- self.items |= self.items_added;
+ this.items |= this.items_added;
}
- player_regen();
+ player_regen(this);
// WEAPONTODO: Add a weapon request for this
// rot vortex charge to the charge limit
- if(WEP_CVAR(vortex, charge_rot_rate) && self.vortex_charge > WEP_CVAR(vortex, charge_limit) && self.vortex_charge_rottime < time)
- self.vortex_charge = bound(WEP_CVAR(vortex, charge_limit), self.vortex_charge - WEP_CVAR(vortex, charge_rot_rate) * frametime / W_TICSPERFRAME, 1);
+ 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);
- if(frametime)
- player_anim();
+ if (frametime) player_anim(this);
// secret status
- secrets_setstatus();
+ secrets_setstatus(this);
// monsters status
- monsters_setstatus();
+ monsters_setstatus(this);
- self.dmg_team = max(0, self.dmg_team - autocvar_g_teamdamage_resetspeed * frametime);
-
- //self.angles_y=self.v_angle_y + 90; // temp
- } else if(gameover) {
- if (intermission_running)
- IntermissionThink (); // otherwise a button could be missed between
+ this.dmg_team = max(0, this.dmg_team - autocvar_g_teamdamage_resetspeed * frametime);
+ }
+ else if (gameover) {
+ if (intermission_running) IntermissionThink(this);
return;
- } else if(IS_OBSERVER(self)) {
- ObserverThink();
- } else if(IS_SPEC(self)) {
- SpectatorThink();
+ }
+ else if (IS_OBSERVER(this)) {
+ ObserverThink(this);
+ }
+ else if (IS_SPEC(this)) {
+ SpectatorThink(this);
}
// WEAPONTODO: Add weapon request for this
- if(!zoomstate_set)
- SetZoomState(self.BUTTON_ZOOM || self.BUTTON_ZOOMSCRIPT || (self.BUTTON_ATCK2 && self.weapon == WEP_VORTEX) || (self.BUTTON_ATCK2 && self.weapon == WEP_RIFLE && WEP_CVAR(rifle, secondary) == 0)); // WEAPONTODO
-
- float oldspectatee_status;
- oldspectatee_status = self.spectatee_status;
- if(IS_SPEC(self))
- self.spectatee_status = num_for_edict(self.enemy);
- else if(IS_OBSERVER(self))
- self.spectatee_status = num_for_edict(self);
- else
- self.spectatee_status = 0;
- if(self.spectatee_status != oldspectatee_status)
- {
- ClientData_Touch(self);
+ 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)
+ );
+ }
+
+ int oldspectatee_status = this.spectatee_status;
+ if (IS_SPEC(this)) {
+ this.spectatee_status = etof(this.enemy);
+ } else if (IS_OBSERVER(this)) {
+ this.spectatee_status = etof(this);
+ } else {
+ this.spectatee_status = 0;
+ }
+ if (this.spectatee_status != oldspectatee_status) {
+ ClientData_Touch(this);
+ if (g_race || g_cts) race_InitSpectator();
}
- if(self.teamkill_soundtime)
- if(time > self.teamkill_soundtime)
+ if (this.teamkill_soundtime && time > this.teamkill_soundtime)
{
- self.teamkill_soundtime = 0;
-
- entity oldpusher, oldself;
-
- oldself = self; self = self.teamkill_soundsource;
- oldpusher = self.pusher; self.pusher = oldself;
+ this.teamkill_soundtime = 0;
- PlayerSound(playersound_teamshoot, CH_VOICE, VOICETYPE_LASTATTACKER_ONLY);
-
- self.pusher = oldpusher;
- self = oldself;
+ entity e = this.teamkill_soundsource;
+ entity oldpusher = e.pusher;
+ e.pusher = this;
+ PlayerSound(e, playersound_teamshoot, CH_VOICE, VOICETYPE_LASTATTACKER_ONLY);
+ e.pusher = oldpusher;
}
- if(self.taunt_soundtime)
- if(time > self.taunt_soundtime)
- {
- self.taunt_soundtime = 0;
- PlayerSound(playersound_taunt, CH_VOICE, VOICETYPE_AUTOTAUNT);
+ if (this.taunt_soundtime && time > this.taunt_soundtime) {
+ this.taunt_soundtime = 0;
+ PlayerSound(this, playersound_taunt, CH_VOICE, VOICETYPE_AUTOTAUNT);
}
- target_voicescript_next(self);
+ target_voicescript_next(this);
// 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(!self.weapon)
- self.clip_load = self.clip_size = 0;
+ if (PS(this).m_weapon == WEP_Null)
+ this.clip_load = this.clip_size = 0;
+ }
+
+ void DrownPlayer(entity this)
+ {
+ if(IS_DEAD(this))
+ return;
+
+ if (this.waterlevel != WATERLEVEL_SUBMERGED)
+ {
+ if(this.air_finished < time)
+ PlayerSound(this, playersound_gasp, CH_PLAYER, VOICETYPE_PLAYERSOUND);
+ this.air_finished = time + autocvar_g_balance_contents_drowndelay;
+ this.dmg = 2;
+ }
+ else if (this.air_finished < time)
+ { // drown!
+ if (this.pain_finished < time)
+ {
+ Damage (this, world, world, autocvar_g_balance_contents_playerdamage_drowning * autocvar_g_balance_contents_damagerate, DEATH_DROWN.m_id, this.origin, '0 0 0');
+ this.pain_finished = time + 0.5;
+ }
+ }
}
/*
=============
*/
.float idlekick_lasttimeleft;
- void PlayerPostThink (void)
- {
- if(sv_maxidle > 0 && frametime) // WORKAROUND: only use dropclient in server frames (frametime set). Never use it in cl_movement frames (frametime zero).
- if(IS_PLAYER(self) || sv_maxidle_spectatorsareidle)
- {
- if (time - self.parm_idlesince < 1) // instead of (time == self.parm_idlesince) to support sv_maxidle <= 10
+ void PlayerPostThink ()
+ {ENGINE_EVENT();
+ if (sv_maxidle > 0)
+ if (frametime) // WORKAROUND: only use dropclient in server frames (frametime set). Never use it in cl_movement frames (frametime zero).
+ if (IS_REAL_CLIENT(this))
+ if (IS_PLAYER(this) || sv_maxidle_spectatorsareidle)
+ {
+ if (time - this.parm_idlesince < 1) // instead of (time == this.parm_idlesince) to support sv_maxidle <= 10
{
- if(self.idlekick_lasttimeleft)
+ if (this.idlekick_lasttimeleft)
{
- self.idlekick_lasttimeleft = 0;
- Kill_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER_CPID, CPID_IDLING);
+ this.idlekick_lasttimeleft = 0;
+ Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_IDLING);
}
}
else
{
- float timeleft;
- timeleft = ceil(sv_maxidle - (time - self.parm_idlesince));
- if(timeleft == min(10, sv_maxidle - 1)) // - 1 to support sv_maxidle <= 10
- {
- if(!self.idlekick_lasttimeleft)
- Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_DISCONNECT_IDLING, timeleft);
+ float timeleft = ceil(sv_maxidle - (time - this.parm_idlesince));
+ if (timeleft == min(10, sv_maxidle - 1)) { // - 1 to support sv_maxidle <= 10
+ if (!this.idlekick_lasttimeleft)
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_DISCONNECT_IDLING, timeleft);
}
- if(timeleft <= 0)
- {
- Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_QUIT_KICK_IDLING, self.netname);
- dropclient(self);
+ if (timeleft <= 0) {
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_QUIT_KICK_IDLING, this.netname);
+ dropclient(this);
return;
}
- else if(timeleft <= 10)
- {
- if(timeleft != self.idlekick_lasttimeleft)
- { Send_Notification(NOTIF_ONE, self, MSG_ANNCE, Announcer_PickNumber(CNT_IDLE, timeleft)); }
- self.idlekick_lasttimeleft = timeleft;
+ else if (timeleft <= 10) {
+ if (timeleft != this.idlekick_lasttimeleft) {
+ Send_Notification(NOTIF_ONE, this, MSG_ANNCE, Announcer_PickNumber(CNT_IDLE, timeleft));
+ }
+ this.idlekick_lasttimeleft = timeleft;
}
}
}
- #ifdef TETRIS
- if(self.impulse == 100)
- ImpulseCommands();
- if (!TetrisPostFrame())
- {
- #endif
-
- CheatFrame();
+ CheatFrame(this);
//CheckPlayerJump();
- if(IS_PLAYER(self)) {
- CheckRules_Player();
- UpdateChatBubble();
- if (self.impulse)
- ImpulseCommands();
- if (intermission_running)
- return; // intermission or finale
- GetPressedKeys();
- }
-
- #ifdef TETRIS
- }
- #endif
-
- /*
- float i;
- for(i = 0; i < 1000; ++i)
- {
- vector end;
- end = self.origin + '0 0 1024' + 512 * randomvec();
- tracebox(self.origin, self.mins, self.maxs, end, MOVE_NORMAL, self);
- if(trace_fraction < 1)
- if(!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT))
- {
- print("I HIT SOLID: ", vtos(self.origin), " -> ", vtos(end), "\n");
- break;
- }
+ if (IS_PLAYER(this)) {
+ DrownPlayer(this);
+ CheckRules_Player(this);
+ UpdateChatBubble(this);
+ if (this.impulse) ImpulseCommands(this);
+ if (intermission_running) return; // intermission or finale
+ GetPressedKeys(this);
}
- */
- if(self.waypointsprite_attachedforcarrier)
- WaypointSprite_UpdateHealth(self.waypointsprite_attachedforcarrier, '1 0 0' * healtharmor_maxdamage(self.health, self.armorvalue, autocvar_g_balance_armor_blockpercent, DEATH_WEAPON));
+ if (this.waypointsprite_attachedforcarrier) {
+ vector v = healtharmor_maxdamage(this.health, this.armorvalue, autocvar_g_balance_armor_blockpercent, DEATH_WEAPON.m_id);
+ WaypointSprite_UpdateHealth(this.waypointsprite_attachedforcarrier, '1 0 0' * v);
+ }
- playerdemo_write();
+ playerdemo_write(this);
- CSQCMODEL_AUTOUPDATE();
+ CSQCMODEL_AUTOUPDATE(this);
}