X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fcl_client.qc;h=6c3e2ec0c5860c7759d95c156501781d65d16948;hb=c26d994a788be2bc2eadf6891da23916cf428311;hp=c104091979a709578477e48c10f18c679b76098c;hpb=b683bf23a495d3b1b3f6df3bda75bfe0f069ab05;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/cl_client.qc b/qcsrc/server/cl_client.qc index c10409197..6c3e2ec0c 100644 --- a/qcsrc/server/cl_client.qc +++ b/qcsrc/server/cl_client.qc @@ -3,7 +3,6 @@ #include "anticheat.qh" #include "cl_impulse.qh" #include "cl_player.qh" -#include "ent_cs.qh" #include "ipban.qh" #include "miscfunctions.qh" #include "portals.qh" @@ -23,14 +22,18 @@ #include "bot/bot.qh" #include "bot/navigation.qh" -#include "../common/vehicles/all.qh" +#include "../common/ent_cs.qh" +#include "../common/state.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.qh" +#include "../common/physics/player.qh" #include "../common/items/all.qc" @@ -50,8 +53,7 @@ void send_CSQC_teamnagger() { - WriteByte(MSG_BROADCAST, SVC_TEMPENTITY); - WriteByte(MSG_BROADCAST, TE_CSQC_TEAMNAGGER); + WriteHeader(MSG_BROADCAST, TE_CSQC_TEAMNAGGER); } bool ClientData_Send(entity this, entity to, int sf) @@ -79,7 +81,7 @@ bool ClientData_Send(entity this, entity to, int sf) if(e.porto_v_angle_held) sf |= 8; // angles held - WriteByte(MSG_ENTITY, ENT_CLIENT_CLIENTDATA); + WriteHeader(MSG_ENTITY, ENT_CLIENT_CLIENTDATA); WriteByte(MSG_ENTITY, sf); if(sf & 2) @@ -176,7 +178,6 @@ void setplayermodel(entity e, string modelname) precache_model(modelname); _setmodel(e, modelname); player_setupanimsformodel(); - UpdatePlayerSounds(); } /* @@ -188,7 +189,9 @@ putting a client as observer in the server */ void FixPlayermodel(entity player); void PutObserverInServer() -{SELFPARAM(); +{ + SELFPARAM(); + PlayerState_detach(this); entity spot; self.hud = HUD_NORMAL; @@ -301,13 +304,13 @@ void PutObserverInServer() 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; + PS(self).m_weapon = WEP_Null; self.weaponname = ""; - self.switchingweapon = 0; + PS(self).m_switchingweapon = WEP_Null; self.weaponmodel = ""; for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) { - self.weaponentity[slot] = NULL; + self.weaponentities[slot] = NULL; } self.exteriorweaponentity = world; self.killcount = FRAGS_SPECTATOR; @@ -320,6 +323,15 @@ void PutObserverInServer() self.event_damage = func_null; } +int player_getspecies(entity this) +{ + 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; +} + .float model_randomizer; void FixPlayermodel(entity player) { @@ -396,8 +408,7 @@ void FixPlayermodel(entity player) if(chmdl || oldskin != player.skin) // model or skin has changed { - player.species = player_getspecies(); // update species - UpdatePlayerSounds(); // update skin sounds + player.species = player_getspecies(player); // update species } if(!teamplay) @@ -432,6 +443,7 @@ void PutClientInServer() if (IS_OBSERVER(this)) { PutObserverInServer(); } else if (IS_PLAYER(this)) { + PlayerState_attach(this); accuracy_resend(this); if (this.team < 0) @@ -564,8 +576,6 @@ void PutClientInServer() this.bot_attack = true; this.monster_attack = true; - this.spider_slowness = 0; - this.BUTTON_ATCK = this.BUTTON_JUMP = this.BUTTON_ATCK2 = false; if (this.killcount == FRAGS_SPECTATOR) { @@ -575,7 +585,7 @@ void PutClientInServer() for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) { - CL_SpawnWeaponentity(this, slot); + CL_SpawnWeaponentity(this, weaponentities[slot]); } this.alpha = default_player_alpha; this.colormod = '1 1 1' * autocvar_g_player_brightness; @@ -613,11 +623,11 @@ void PutClientInServer() remove(spot); // usefull for checking if there are spawnpoints, that let drop through the floor } - this.switchweapon = w_getbestweapon(this); + PS(this).m_switchweapon = w_getbestweapon(this); this.cnt = -1; // W_LastWeapon will not complain - this.weapon = 0; + PS(this).m_weapon = WEP_Null; this.weaponname = ""; - this.switchingweapon = 0; + PS(this).m_switchingweapon = WEP_Null; if (!warmup_stage && !this.alivetime) this.alivetime = time; @@ -626,41 +636,44 @@ void PutClientInServer() } } +void ClientInit_misc(); + .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? 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(); + MUTATOR_CALLHOOK(Ent_Init); +} +void ClientInit_misc() +{ + 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 - - MUTATOR_CALLHOOK(Ent_Init); - return true; + WriteString(channel, ""); + WriteByte(channel, self.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() @@ -671,26 +684,6 @@ void ClientInit_CheckUpdate() 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) - { - 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; - } } void ClientInit_Spawn() @@ -709,7 +702,7 @@ void ClientInit_Spawn() SetNewParms ============= */ -void SetNewParms (void) +void SetNewParms () { // initialize parms for a new player parm1 = -(86400 * 366); @@ -722,7 +715,7 @@ void SetNewParms (void) SetChangeParms ============= */ -void SetChangeParms (void) +void SetChangeParms () {SELFPARAM(); // save parms for level change parm1 = self.parm_idlesince - time; @@ -735,7 +728,7 @@ void SetChangeParms (void) DecodeLevelParms ============= */ -void DecodeLevelParms (void) +void DecodeLevelParms () {SELFPARAM(); // load parms self.parm_idlesince = parm1; @@ -938,7 +931,7 @@ void ClientKill_TeamChange (float targetteam) // 0 = don't change, -1 = auto, -2 } -void ClientKill (void) +void ClientKill () {SELFPARAM(); if(gameover) return; if(self.player_blocked) return; @@ -955,6 +948,8 @@ void FixClientCvars(entity e) 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) @@ -986,13 +981,13 @@ ClientPreConnect Called once (not at each match start) when a client begins a connection to the server ============= */ -void ClientPreConnect (void) +void ClientPreConnect () {SELFPARAM(); if(autocvar_sv_eventlog) { GameLogEcho(sprintf(":connect:%d:%d:%s", self.playerid, - num_for_edict(self), + etof(self), ((IS_REAL_CLIENT(self)) ? self.netaddress : "bot") )); } @@ -1006,9 +1001,11 @@ ClientConnect Called when a client connects to the server ============= */ -void DecodeLevelParms (void); -void ClientConnect (void) -{SELFPARAM(); +void DecodeLevelParms (); +void ClientConnect () +{ + SELFPARAM(); + ClientState_attach(this); float t; if(IS_CLIENT(self)) @@ -1037,7 +1034,8 @@ void ClientConnect (void) player_count = 0; } - if(IS_REAL_CLIENT(self)) { PlayerStats_PlayerBasic_CheckUpdate(self); } + // TODO: xonstat elo.txt support, until then just 404s + if(false && IS_REAL_CLIENT(self)) { PlayerStats_PlayerBasic_CheckUpdate(self); } PlayerScore_Attach(self); ClientData_Attach(); @@ -1124,7 +1122,7 @@ void ClientConnect (void) 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)); + GameLogEcho(strcat(":join:", ftos(self.playerid), ":", ftos(etof(self)), ":", ((IS_REAL_CLIENT(self)) ? self.netaddress : "bot"), ":", self.netname)); LogTeamchange(self.playerid, self.team, 1); @@ -1168,7 +1166,7 @@ void ClientConnect (void) else stuffcmd(self, "set _teams_available 0\n"); - attach_entcs(self); + entcs_attach(self); bot_relinkplayerlist(); @@ -1189,7 +1187,7 @@ void ClientConnect (void) Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_MOTD, getwelcomemessage()); } - if(autocvar_g_bugrigs || (g_weaponarena_weapons == WEPSET(TUBA))) + if(g_weaponarena_weapons == WEPSET(TUBA)) stuffcmd(self, "cl_cmd settemp chase_active 1\n"); } @@ -1208,7 +1206,7 @@ void ClientConnect (void) self.model_randomizer = random(); if(IS_REAL_CLIENT(self)) - sv_notice_join(); + sv_notice_join(self); for (entity e = world; (e = findfloat(e, init_for_player_needed, 1)); ) { WITH(entity, self, e, e.init_for_player(this)); @@ -1225,8 +1223,10 @@ Called when a client disconnects from the server */ .entity chatbubbleentity; void ReadyCount(); -void ClientDisconnect (void) -{SELFPARAM(); +void ClientDisconnect () +{ + SELFPARAM(); + ClientState_detach(this); if(self.vehicle) vehicles_exit(VHEF_RELEASE); @@ -1254,7 +1254,7 @@ void ClientDisconnect (void) bot_clientdisconnect(); - detach_entcs(self); + entcs_detach(self); if(autocvar_sv_eventlog) GameLogEcho(strcat(":part:", ftos(self.playerid))); @@ -1295,8 +1295,6 @@ void ClientDisconnect (void) if(self.weaponorder_byimpulse) strunzone(self.weaponorder_byimpulse); - ClearPlayerSounds(); - if(self.personal) remove(self.personal); @@ -1373,7 +1371,7 @@ void UpdateChatBubble() else self.colormod = '1 1 1'; }*/ -void respawn(void) +void respawn() {SELFPARAM(); if(self.alpha >= 0 && autocvar_g_respawn_ghosts) { @@ -1402,7 +1400,7 @@ void play_countdown(float finished, string samp) _sound (self, CH_INFO, samp, VOL_BASE, ATTEN_NORM); } -void player_powerups (void) +void player_powerups () {SELFPARAM(); // add a way to see what the items were BEFORE all of these checks for the mutator hook int items_prev = self.items; @@ -1565,7 +1563,7 @@ float CalcRotRegen(float current, float regenstable, float regenfactor, float re return current; } -void player_regen (void) +void player_regen () {SELFPARAM(); float max_mod, regen_mod, rot_mod, limit_mod; max_mod = regen_mod = rot_mod = limit_mod = 1; @@ -1609,7 +1607,8 @@ void player_regen (void) { if(self.vehicle) vehicles_exit(VHEF_RELEASE); - self.event_damage(self, self, 1, DEATH_ROT.m_id, self.origin, '0 0 0'); + if(self.event_damage) + self.event_damage(self, self, 1, DEATH_ROT.m_id, self.origin, '0 0 0'); } if (!(self.items & IT_UNLIMITED_WEAPON_AMMO)) @@ -1636,19 +1635,20 @@ void SetZoomState(float z) } void GetPressedKeys() -{SELFPARAM(); +{ + SELFPARAM(); MUTATOR_CALLHOOK(GetPressedKeys); - #define X(var,bit,flag) (flag ? var |= bit : var &= ~bit) - X(self.pressedkeys, KEY_FORWARD, self.movement_x > 0); - X(self.pressedkeys, KEY_BACKWARD, self.movement_x < 0); - X(self.pressedkeys, KEY_RIGHT, self.movement_y > 0); - X(self.pressedkeys, KEY_LEFT, self.movement_y < 0); - - X(self.pressedkeys, KEY_JUMP, PHYS_INPUT_BUTTON_JUMP(self)); - X(self.pressedkeys, KEY_CROUCH, PHYS_INPUT_BUTTON_CROUCH(self)); - X(self.pressedkeys, KEY_ATCK, PHYS_INPUT_BUTTON_ATCK(self)); - X(self.pressedkeys, KEY_ATCK2, PHYS_INPUT_BUTTON_ATCK2(self)); - #undef X + 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; } /* @@ -1657,8 +1657,8 @@ spectate mode routines ====================== */ -void SpectateCopy(entity spectatee) -{SELFPARAM(); +void SpectateCopy(entity this, entity spectatee) +{ MUTATOR_CALLHOOK(SpectateCopy, spectatee, self); self.armortype = spectatee.armortype; self.armorvalue = spectatee.armorvalue; @@ -1680,9 +1680,9 @@ void SpectateCopy(entity spectatee) 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; + PS(self).m_switchweapon = PS(spectatee).m_switchweapon; + PS(self).m_switchingweapon = PS(spectatee).m_switchingweapon; + PS(self).m_weapon = PS(spectatee).m_weapon; self.vortex_charge = spectatee.vortex_charge; self.vortex_chargepool_ammo = spectatee.vortex_chargepool_ammo; self.hagar_load = spectatee.hagar_load; @@ -1743,7 +1743,7 @@ bool SpectateUpdate() return false; } - SpectateCopy(self.enemy); + SpectateCopy(this, this.enemy); return true; } @@ -1867,12 +1867,11 @@ void LeaveSpectatorMode() {SELFPARAM(); if(self.caplayer) return; - if(nJoinAllowed(self)) + if(nJoinAllowed(self, self)) { if(!teamplay || autocvar_g_campaign || autocvar_g_balance_teams || (self.wasplayer && autocvar_g_changeteam_banned) || self.team_forced > 0) { self.classname = STR_PLAYER; - nades_RemoveBonus(self); if(autocvar_g_campaign || autocvar_g_balance_teams) { JoinBestTeam(self, false, true); } @@ -1902,40 +1901,39 @@ void LeaveSpectatorMode() * 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) -{SELFPARAM(); +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; } /** @@ -2006,7 +2004,7 @@ void ObserverThink() {SELFPARAM(); if ( self.impulse ) { - MinigameImpulse(self.impulse); + MinigameImpulse(self, self.impulse); self.impulse = 0; } float prefered_movetype; @@ -2041,7 +2039,7 @@ void SpectatorThink() {SELFPARAM(); if ( self.impulse ) { - if(MinigameImpulse(self.impulse)) + if(MinigameImpulse(self, self.impulse)) self.impulse = 0; } if (self.flags & FL_JUMPRELEASED) { @@ -2140,32 +2138,6 @@ void PlayerUseKey() MUTATOR_CALLHOOK(PlayerUseKey); } -float isInvisibleString(string s) -{ - float i, n, c; - s = strdecolorize(s); - for((i = 0), (n = strlen(s)); i < n; ++i) - { - c = str2chr(s, i); - switch(c) - { - 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; - } - } - return true; -} /* ============= @@ -2178,7 +2150,7 @@ Called every frame for each client before the physics are run void() nexball_setstatus; .float last_vehiclecheck; .int items_added; -void PlayerPreThink (void) +void PlayerPreThink () {SELFPARAM(); WarpZone_PlayerPhysics_FixVAngle(); @@ -2342,22 +2314,6 @@ void PlayerPreThink (void) if(frametime) { - if(self.weapon == WEP_VORTEX.m_id && 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(); } @@ -2438,8 +2394,8 @@ void PlayerPreThink (void) // WEAPONTODO: THIS SHIT NEEDS TO GO EVENTUALLY // It cannot be predicted by the engine! - int slot = 0; // TODO: unhardcode - if((self.weapon == WEP_SHOCKWAVE.m_id || self.weapon == WEP_SHOTGUN.m_id) && self.weaponentity[slot].wframe == WFRAME_FIRE2 && time < self.weapon_nextthink) + .entity weaponentity = weaponentities[0]; // TODO: unhardcode + if((PS(self).m_weapon == WEP_SHOCKWAVE || PS(self).m_weapon == WEP_SHOTGUN) && self.(weaponentity).wframe == WFRAME_FIRE2 && time < self.(weaponentity).weapon_nextthink) do_crouch = 0; if (do_crouch) @@ -2447,8 +2403,8 @@ void PlayerPreThink (void) if (!self.crouch) { self.crouch = true; - self.view_ofs = self.stat_pl_crouch_view_ofs; - setsize (self, self.stat_pl_crouch_min, self.stat_pl_crouch_max); + self.view_ofs = STAT(PL_CROUCH_VIEW_OFS, self); + setsize (self, STAT(PL_CROUCH_MIN, self), STAT(PL_CROUCH_MAX, self)); // setanim(self, self.anim_duck, false, true, true); // this anim is BROKEN anyway } } @@ -2456,12 +2412,12 @@ void PlayerPreThink (void) { if (self.crouch) { - tracebox(self.origin, self.stat_pl_min, self.stat_pl_max, self.origin, false, self); + tracebox(self.origin, STAT(PL_MIN, self), STAT(PL_MAX, self), self.origin, false, self); if (!trace_startsolid) { self.crouch = false; - self.view_ofs = self.stat_pl_view_ofs; - setsize (self, self.stat_pl_min, self.stat_pl_max); + self.view_ofs = STAT(PL_VIEW_OFS, self); + setsize (self, STAT(PL_MIN, self), STAT(PL_MAX, self)); } } } @@ -2514,19 +2470,26 @@ void PlayerPreThink (void) // WEAPONTODO: Add weapon request for this if(!zoomstate_set) - SetZoomState(self.BUTTON_ZOOM || self.BUTTON_ZOOMSCRIPT || (self.BUTTON_ATCK2 && self.weapon == WEP_VORTEX.m_id) || (self.BUTTON_ATCK2 && self.weapon == WEP_RIFLE.m_id && WEP_CVAR(rifle, secondary) == 0)); // WEAPONTODO + SetZoomState( + self.BUTTON_ZOOM + || self.BUTTON_ZOOMSCRIPT + || (self.BUTTON_ATCK2 && PS(self).m_weapon == WEP_VORTEX) + || (self.BUTTON_ATCK2 && PS(self).m_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); + self.spectatee_status = etof(self.enemy); else if(IS_OBSERVER(self)) - self.spectatee_status = num_for_edict(self); + self.spectatee_status = etof(self); else self.spectatee_status = 0; if(self.spectatee_status != oldspectatee_status) { ClientData_Touch(self); + if(g_race || g_cts) + race_InitSpectator(); } if(self.teamkill_soundtime) @@ -2534,31 +2497,50 @@ void PlayerPreThink (void) { self.teamkill_soundtime = 0; - setself(self.teamkill_soundsource); - entity oldpusher = self.pusher; - self.pusher = this; - - PlayerSound(playersound_teamshoot, CH_VOICE, VOICETYPE_LASTATTACKER_ONLY); - - self.pusher = oldpusher; - setself(this); + entity e = self.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); + PlayerSound(self, playersound_taunt, CH_VOICE, VOICETYPE_AUTOTAUNT); } target_voicescript_next(self); // 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) + if (PS(self).m_weapon == WEP_Null) self.clip_load = self.clip_size = 0; } +void DrownPlayer(entity this) +{ + if(this.deadflag != DEAD_NO) + 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; + } + } +} + /* ============= PlayerPostThink @@ -2567,7 +2549,7 @@ Called every frame for each client after the physics are run ============= */ .float idlekick_lasttimeleft; -void PlayerPostThink (void) +void PlayerPostThink () {SELFPARAM(); 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_REAL_CLIENT(self)) @@ -2610,10 +2592,11 @@ void PlayerPostThink (void) //CheckPlayerJump(); if(IS_PLAYER(self)) { + DrownPlayer(self); CheckRules_Player(); UpdateChatBubble(); if (self.impulse) - ImpulseCommands(); + ImpulseCommands(self); if (intermission_running) return; // intermission or finale GetPressedKeys();