X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fserver%2Fcl_client.qc;h=781836469bf40192a2941adfe7017857784c0ee6;hp=1438d317c76947d9fd04cec4477a49f1d5b15e15;hb=2c022461b9a9a44b84dbf8fd1b8b3063b5160141;hpb=81389844a546e48635a119927ffcf6e1ee15f689 diff --git a/qcsrc/server/cl_client.qc b/qcsrc/server/cl_client.qc index 1438d317c7..781836469b 100644 --- a/qcsrc/server/cl_client.qc +++ b/qcsrc/server/cl_client.qc @@ -599,13 +599,14 @@ void PutObserverInServer (void) } DropAllRunes(self); + MUTATOR_CALLHOOK(MakePlayerObserver); Portal_ClearAll(self); if(self.flagcarried) DropFlag(self.flagcarried, world, world); - if(self.ballcarried) + if(self.ballcarried && g_nexball) DropBall(self.ballcarried, self.origin + self.ballcarried.origin, self.velocity); WaypointSprite_PlayerDead(); @@ -630,6 +631,8 @@ void PutObserverInServer (void) PlayerScore_Clear(self); // clear scores when needed + accuracy_resend(self); + self.spectatortime = time; self.classname = "observer"; @@ -713,8 +716,6 @@ void PutObserverInServer (void) } else self.frags = FRAGS_SPECTATOR; - - MUTATOR_CALLHOOK(MakePlayerObserver); } float RestrictSkin(float s) @@ -854,6 +855,8 @@ void PutClientInServer (void) entity spot, oldself; float j; + accuracy_resend(self); + if(self.team < 0) JoinBestTeam(self, FALSE, TRUE); @@ -890,7 +893,11 @@ void PutClientInServer (void) self.air_finished = time + 12; self.dmg = 2; if(cvar("g_balance_nex_charge")) + { + if(cvar("g_balance_nex_secondary_charge_pool")) + self.nex_charge_pool_ammo = 1; self.nex_charge = cvar("g_balance_nex_charge_start"); + } if(inWarmupStage) { @@ -916,7 +923,13 @@ void PutClientInServer (void) } if(g_weaponarena_random) + { + if(g_weaponarena_random_with_laser) + self.weapons &~= WEPBIT_LASER; self.weapons = randombits(self.weapons, g_weaponarena_random, FALSE); + if(g_weaponarena_random_with_laser) + self.weapons |= WEPBIT_LASER; + } self.items = start_items; self.jump_interval = time; @@ -1069,6 +1082,9 @@ void PutClientInServer (void) // ctf_playerchanged(); } +.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) { WriteByte(MSG_ENTITY, ENT_CLIENT_INIT); @@ -1093,6 +1109,8 @@ float ClientInit_SendEntity(entity to, float sf) WriteByte(MSG_ENTITY, self.cnt * 255.0); // g_balance_weaponswitchdelay WriteCoord(MSG_ENTITY, self.bouncefactor); // g_balance_grenadelauncher_bouncefactor WriteCoord(MSG_ENTITY, self.bouncestop); // g_balance_grenadelauncher_bouncestop + WriteCoord(MSG_ENTITY, self.ebouncefactor); // g_balance_grenadelauncher_bouncefactor + WriteCoord(MSG_ENTITY, self.ebouncestop); // g_balance_grenadelauncher_bouncestop WriteByte(MSG_ENTITY, cvar("g_balance_nex_secondary")); // client has to know if it should zoom or not WriteByte(MSG_ENTITY, cvar("g_balance_campingrifle_secondary")); // client has to know if it should zoom or not WriteByte(MSG_ENTITY, serverflags); // client has to know if it should zoom or not @@ -1122,6 +1140,16 @@ void ClientInit_CheckUpdate() self.bouncestop = cvar("g_balance_grenadelauncher_bouncestop"); self.SendFlags |= 1; } + if(self.ebouncefactor != cvar("g_balance_electro_secondary_bouncefactor")) + { + self.ebouncefactor = cvar("g_balance_electro_secondary_bouncefactor"); + self.SendFlags |= 1; + } + if(self.ebouncestop != cvar("g_balance_electro_secondary_bouncestop")) + { + self.ebouncestop = cvar("g_balance_electro_secondary_bouncestop"); + self.SendFlags |= 1; + } } void ClientInit_Spawn() @@ -1408,6 +1436,27 @@ void FixClientCvars(entity e) */ } +float PlayerInIDList(entity p, string idlist) +{ + float n, i; + string s; + + // NOTE: we do NOT check crypto_keyfp here, an unsigned ID is fine too for this + if not(p.crypto_idfp) + return 0; + + // this function allows abbreviated player IDs too! + n = tokenize_console(idlist); + for(i = 0; i < n; ++i) + { + s = argv(i); + if(s == substring(p.crypto_idfp, 0, strlen(s))) + return 1; + } + + return 0; +} + /* ============= ClientConnect @@ -1451,6 +1500,7 @@ void ClientConnect (void) PlayerScore_Attach(self); ClientData_Attach(); + accuracy_init(self); bot_clientconnect(); @@ -1463,9 +1513,37 @@ void ClientConnect (void) //if(g_domination) // dom_player_join_team(self); + // identify the right forced team + if(PlayerInIDList(self, cvar_string("g_forced_team_red"))) + self.team_forced = COLOR_TEAM1; + else if(PlayerInIDList(self, cvar_string("g_forced_team_blue"))) + self.team_forced = COLOR_TEAM2; + else if(PlayerInIDList(self, cvar_string("g_forced_team_yellow"))) + self.team_forced = COLOR_TEAM3; + else if(PlayerInIDList(self, cvar_string("g_forced_team_pink"))) + self.team_forced = COLOR_TEAM4; + else if(cvar_string("g_forced_team_otherwise") == "red") + self.team_forced = COLOR_TEAM1; + else if(cvar_string("g_forced_team_otherwise") == "blue") + self.team_forced = COLOR_TEAM2; + else if(cvar_string("g_forced_team_otherwise") == "yellow") + self.team_forced = COLOR_TEAM3; + else if(cvar_string("g_forced_team_otherwise") == "pink") + self.team_forced = COLOR_TEAM4; + else if(cvar_string("g_forced_team_otherwise") == "spectate") + self.team_forced = -1; + else if(cvar_string("g_forced_team_otherwise") == "spectator") + self.team_forced = -1; + else + self.team_forced = 0; + + if(!teams_matter) + if(self.team_forced > 0) + self.team_forced = 0; + JoinBestTeam(self, FALSE, FALSE); // if the team number is valid, keep it - if((cvar("sv_spectate") == 1 && !g_lms) || cvar("g_campaign")) { + if((cvar("sv_spectate") == 1 && !g_lms) || cvar("g_campaign") || self.team_forced < 0) { self.classname = "observer"; } else { if(teams_matter) @@ -1675,7 +1753,7 @@ void ClientDisconnect (void) if(self.flagcarried) DropFlag(self.flagcarried, world, world); - if(self.ballcarried) + if(self.ballcarried && g_nexball) DropBall(self.ballcarried, self.origin + self.ballcarried.origin, self.velocity); // Here, everything has been done that requires this player to be a client. @@ -1695,17 +1773,13 @@ void ClientDisconnect (void) bot_relinkplayerlist(); - // remove laserdot - if(self.weaponentity) - if(self.weaponentity.lasertarget) - remove(self.weaponentity.lasertarget); - if(g_arena) { Spawnqueue_Unmark(self); Spawnqueue_Remove(self); } + accuracy_free(self); ClientData_Detach(); PlayerScore_Detach(self); @@ -1913,6 +1987,9 @@ string getTimeoutText(float addOneSecond) { void player_powerups (void) { + // add a way to see what the items were BEFORE all of these checks for the mutator hook + olditems = self.items; + if((self.items & IT_USING_JETPACK) && !self.deadflag) { SoundEntity_StartSound(self, CHAN_PLAYER, "misc/jetpack_fly.wav", VOL_BASE, cvar("g_jetpack_attenuation")); @@ -1975,64 +2052,67 @@ void player_powerups (void) sprint(self, "^3You are on speed\n"); } } - return; } - - if (self.items & IT_STRENGTH) + else // if we're not in minstagib, continue. I added this else to replace the "return" which was here that broke the callhook for this function -- This code is nasty. { - play_countdown(self.strength_finished, "misc/poweroff.wav"); - self.effects = self.effects | (EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT); - if (time > self.strength_finished && cvar("g_balance_powerup_timer")) + if (self.items & IT_STRENGTH) { - self.items = self.items - (self.items & IT_STRENGTH); - sprint(self, "^3Strength has worn off\n"); + play_countdown(self.strength_finished, "misc/poweroff.wav"); + self.effects = self.effects | (EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT); + if (time > self.strength_finished && cvar("g_balance_powerup_timer")) + { + self.items = self.items - (self.items & IT_STRENGTH); + sprint(self, "^3Strength has worn off\n"); + } } - } - else - { - if (time < self.strength_finished) + else { - self.items = self.items | IT_STRENGTH; - sprint(self, "^3Strength infuses your weapons with devastating power\n"); + if (time < self.strength_finished) + { + self.items = self.items | IT_STRENGTH; + sprint(self, "^3Strength infuses your weapons with devastating power\n"); + } } - } - if (self.items & IT_INVINCIBLE) - { - play_countdown(self.invincible_finished, "misc/poweroff.wav"); - self.effects = self.effects | (EF_RED | EF_ADDITIVE | EF_FULLBRIGHT); - if (time > self.invincible_finished && cvar("g_balance_powerup_timer")) + if (self.items & IT_INVINCIBLE) { - self.items = self.items - (self.items & IT_INVINCIBLE); - sprint(self, "^3Shield has worn off\n"); + play_countdown(self.invincible_finished, "misc/poweroff.wav"); + self.effects = self.effects | (EF_RED | EF_ADDITIVE | EF_FULLBRIGHT); + if (time > self.invincible_finished && cvar("g_balance_powerup_timer")) + { + self.items = self.items - (self.items & IT_INVINCIBLE); + sprint(self, "^3Shield has worn off\n"); + } } - } - else - { - if (time < self.invincible_finished) + else { - self.items = self.items | IT_INVINCIBLE; - sprint(self, "^3Shield surrounds you\n"); + if (time < self.invincible_finished) + { + self.items = self.items | IT_INVINCIBLE; + sprint(self, "^3Shield surrounds you\n"); + } } - } - if(cvar("g_nodepthtestplayers")) - self.effects = self.effects | EF_NODEPTHTEST; + if(cvar("g_nodepthtestplayers")) + self.effects = self.effects | EF_NODEPTHTEST; - if(cvar("g_fullbrightplayers")) - self.effects = self.effects | EF_FULLBRIGHT; + if(cvar("g_fullbrightplayers")) + self.effects = self.effects | EF_FULLBRIGHT; - // midair gamemode: damage only while in the air - // if in midair mode, being on ground grants temporary invulnerability - // (this is so that multishot weapon don't clear the ground flag on the - // first damage in the frame, leaving the player vulnerable to the - // remaining hits in the same frame) - if (self.flags & FL_ONGROUND) - if (g_midair) - self.spawnshieldtime = max(self.spawnshieldtime, time + cvar("g_midair_shieldtime")); + // midair gamemode: damage only while in the air + // if in midair mode, being on ground grants temporary invulnerability + // (this is so that multishot weapon don't clear the ground flag on the + // first damage in the frame, leaving the player vulnerable to the + // remaining hits in the same frame) + if (self.flags & FL_ONGROUND) + if (g_midair) + self.spawnshieldtime = max(self.spawnshieldtime, time + cvar("g_midair_shieldtime")); - if (time >= game_starttime) - if (time < self.spawnshieldtime) - self.effects = self.effects | (EF_ADDITIVE | EF_FULLBRIGHT); + if (time >= game_starttime) + if (time < self.spawnshieldtime) + self.effects = self.effects | (EF_ADDITIVE | EF_FULLBRIGHT); + } + + MUTATOR_CALLHOOK(PlayerPowerups); } float CalcRegen(float current, float stable, float regenfactor, float regenframetime) @@ -2203,33 +2283,13 @@ void GetPressedKeys(void) { self.pressedkeys &~= KEY_CROUCH; } -void update_stats (float number, float hit, float fired) { -// self.stat_hit = number + ((number==0) ? 1 : 64) * hit * sv_accuracy_data_share; -// self.stat_fired = number + ((number==0) ? 1 : 64) * fired * sv_accuracy_data_share; - - if(number) { - self.stat_hit = number + 64 * hit * sv_accuracy_data_share; - self.stat_fired = number + 64 * fired * sv_accuracy_data_share; - } else { - self.stat_hit = hit * sv_accuracy_data_share; - self.stat_fired = fired * sv_accuracy_data_share; - } -} - /* ====================== spectate mode routines ====================== */ -.float weapon_count; void SpectateCopy(entity spectatee) { - if(spectatee.weapon_count < WEP_LAST) { - update_stats (spectatee.weapon_count, spectatee.cvar_cl_accuracy_data_share * floor(spectatee.stats_hit[spectatee.weapon_count - 1]), spectatee.cvar_cl_accuracy_data_share * floor(spectatee.stats_fired[spectatee.weapon_count - 1])); - spectatee.weapon_count ++; - } else - update_stats (0, spectatee.cvar_cl_accuracy_data_share * spectatee.stat_hit, spectatee.cvar_cl_accuracy_data_share * spectatee.stat_fired); - other = spectatee; MUTATOR_CALLHOOK(SpectateCopy); self.armortype = spectatee.armortype; @@ -2297,8 +2357,7 @@ float SpectateNext() { WriteEntity(MSG_ONE, self.enemy); //stuffcmd(self, "set viewsize $tmpviewsize \n"); self.movetype = MOVETYPE_NONE; - - self.enemy.weapon_count = 0; + accuracy_resend(self); if(!SpectateUpdate()) PutObserverInServer(); @@ -2338,7 +2397,7 @@ void ShowRespawnCountdown() void LeaveSpectatorMode() { if(isJoinAllowed()) { - if(!teams_matter || cvar("g_campaign") || cvar("g_balance_teams") || (self.wasplayer && cvar("g_changeteam_banned"))) { + if(!teams_matter || cvar("g_campaign") || cvar("g_balance_teams") || (self.wasplayer && cvar("g_changeteam_banned")) || self.team_forced > 0) { self.classname = "player"; if(cvar("g_campaign") || cvar("g_balance_teams") || cvar("g_balance_teams_force")) @@ -2347,8 +2406,6 @@ void LeaveSpectatorMode() if(cvar("g_campaign")) campaign_bots_may_start = 1; - self.stat_count = WEP_LAST; - PutClientInServer(); if(self.classname == "player") @@ -2379,6 +2436,9 @@ void LeaveSpectatorMode() * @return bool TRUE if the player is allowed to join, false otherwise */ float isJoinAllowed() { + if(self.team_forced < 0) + return FALSE; // forced spectators can never join + if (!cvar("g_maxplayers")) return TRUE; @@ -2407,50 +2467,6 @@ void checkSpectatorBlock() { } } -float vercmp_recursive(string v1, string v2) -{ - float dot1, dot2; - string s1, s2; - float r; - - dot1 = strstrofs(v1, ".", 0); - dot2 = strstrofs(v2, ".", 0); - if(dot1 == -1) - s1 = v1; - else - s1 = substring(v1, 0, dot1); - if(dot2 == -1) - s2 = v2; - else - s2 = substring(v2, 0, dot2); - - r = stof(s1) - stof(s2); - if(r != 0) - return r; - - r = strcasecmp(s1, s2); - if(r != 0) - return r; - - if(dot1 == -1) - if(dot2 == -1) - return 0; - else - return -1; - else - if(dot2 == -1) - return 1; - else - return vercmp_recursive(substring(v1, dot1 + 1, 999), substring(v2, dot2 + 1, 999)); -} - -float vercmp(string v1, string v2) -{ - if(strcasecmp(v1, v2) == 0) // early out check - return 0; - return vercmp_recursive(v1, v2); -} - void ObserverThink() { if (self.flags & FL_JUMPRELEASED) { @@ -2493,14 +2509,12 @@ void SpectatorThink() self.classname = "spectator"; } else { self.classname = "observer"; - self.stat_count = WEP_LAST; PutClientInServer(); } } else if (self.BUTTON_ATCK2) { self.welcomemessage_time = 0; self.flags &~= FL_JUMPRELEASED; self.classname = "observer"; - self.stat_count = WEP_LAST; PutClientInServer(); } else { if(!SpectateUpdate()) @@ -2811,7 +2825,7 @@ void PlayerPreThink (void) player_regen(); // rot nex charge to the charge limit - if(cvar("g_balance_nex_charge_rot_rate") && self.nex_charge > cvar("g_balance_nex_charge_limit")) + if(cvar("g_balance_nex_charge_rot_rate") && self.nex_charge > cvar("g_balance_nex_charge_limit") && self.nex_charge_rottime < time) self.nex_charge = bound(cvar("g_balance_nex_charge_limit"), self.nex_charge - cvar("g_balance_nex_charge_rot_rate") * frametime / W_TICSPERFRAME, 1); if(frametime) @@ -2820,8 +2834,11 @@ void PlayerPreThink (void) if (g_minstagib) minstagib_ammocheck(); - ctf_setstatus(); - nexball_setstatus(); + if(g_ctf) + ctf_setstatus(); + + if(g_nexball) + nexball_setstatus(); self.dmg_team = max(0, self.dmg_team - cvar("g_teamdamage_resetspeed") * frametime); @@ -2935,15 +2952,6 @@ void PlayerPostThink (void) stuffcmd(self, strcat("name ", self.netname, substring(ftos(random()), 2, -1), "\n")); } - // send the clients accuracy stats to the client - if(self.stat_count > 0) - if(frametime) - { - self.stat_hit = self.stat_count + 64 * floor(self.(stats_hit[self.stat_count - 1])); - self.stat_fired = self.stat_count + 64 * floor(self.(stats_fired[self.stat_count - 1])); - self.stat_count -= 1; - } - if(sv_maxidle && frametime) { // WORKAROUND: only use dropclient in server frames (frametime set). Never use it in cl_movement frames (frametime zero).