X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fclient.qc;h=eeded4b25343337a526a6e05584d08bdb250324c;hb=c8988d346ff2d4aaa0f2147d72416b88f328c328;hp=328917336368c11e38341337543f0d227bf1e2c3;hpb=8cb2cb16bb4e54acd682ad3714bbb70535a6afc1;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/client.qc b/qcsrc/server/client.qc index 328917336..eeded4b25 100644 --- a/qcsrc/server/client.qc +++ b/qcsrc/server/client.qc @@ -37,6 +37,7 @@ #include "weapons/weaponsystem.qh" #include "../common/net_notice.qh" +#include "../common/net_linked.qh" #include "../common/physics/player.qh" #include "../common/items/_mod.qh" @@ -55,6 +56,8 @@ #include "../lib/warpzone/server.qh" +#include + STATIC_METHOD(Client, Add, void(Client this, int _team)) { ClientConnect(this); @@ -230,7 +233,7 @@ void PutObserverInServer(entity this) 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)); + setorigin(this, spot.origin + STAT(PL_VIEW_OFS, this)); this.prevorigin = this.origin; if (IS_REAL_CLIENT(this)) { @@ -247,7 +250,7 @@ void PutObserverInServer(entity this) FixPlayermodel(this); } setmodel(this, MDL_Null); - setsize(this, STAT(PL_CROUCH_MIN, NULL), STAT(PL_CROUCH_MAX, NULL)); + setsize(this, STAT(PL_CROUCH_MIN, this), STAT(PL_CROUCH_MAX, this)); this.view_ofs = '0 0 0'; } @@ -278,8 +281,8 @@ void PutObserverInServer(entity this) if (this.killcount != FRAGS_SPECTATOR) { Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_SPECTATE, this.netname); - if(!intermission_running) - if(autocvar_g_chat_nospectators == 1 || (!(warmup_stage || gameover) && autocvar_g_chat_nospectators == 2)) + if(!game_stopped) + if(autocvar_g_chat_nospectators == 1 || (!warmup_stage && autocvar_g_chat_nospectators == 2)) Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_CHAT_NOSPECTATORS); if(this.just_joined == false) { @@ -298,6 +301,8 @@ void PutObserverInServer(entity this) TRANSMUTE(Observer, this); this.iscreature = false; this.teleportable = TELEPORT_SIMPLE; + if(this.damagedbycontents) + IL_REMOVE(g_damagedbycontents, this); this.damagedbycontents = false; this.health = FRAGS_SPECTATOR; SetSpectatee_status(this, etof(this)); @@ -330,6 +335,7 @@ void PutObserverInServer(entity this) this.nextthink = 0; this.deadflag = DEAD_NO; this.crouch = false; + this.revive_progress = 0; this.revival_time = 0; this.items = 0; @@ -339,10 +345,6 @@ void PutObserverInServer(entity this) this.weaponmodel = ""; for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) { - if(!this.weaponentities[slot]) - continue; // first load - this.weaponentities[slot].hook_time = 0; - this.weaponentities[slot].weaponname = ""; this.weaponentities[slot] = NULL; } this.exteriorweaponentity = NULL; @@ -354,6 +356,15 @@ void PutObserverInServer(entity this) this.oldvelocity = this.velocity; this.fire_endtime = -1; this.event_damage = func_null; + + for(int slot = 0; slot < MAX_AXH; ++slot) + { + entity axh = this.(AuxiliaryXhair[slot]); + this.(AuxiliaryXhair[slot]) = NULL; + + if(axh.owner == this && axh != NULL && !wasfreed(axh)) + delete(axh); + } } int player_getspecies(entity this) @@ -374,11 +385,12 @@ void FixPlayermodel(entity player) { if(teamplay) { - string s = Static_Team_ColorName_Lower(player.team); - if (s != "neutral") + switch(player.team) { - defaultmodel = cvar_string(strcat("sv_defaultplayermodel_", s)); - defaultskin = cvar(strcat("sv_defaultplayerskin_", s)); + case NUM_TEAM_1: defaultmodel = autocvar_sv_defaultplayermodel_red; defaultskin = autocvar_sv_defaultplayerskin_red; break; + case NUM_TEAM_2: defaultmodel = autocvar_sv_defaultplayermodel_blue; defaultskin = autocvar_sv_defaultplayerskin_blue; break; + case NUM_TEAM_3: defaultmodel = autocvar_sv_defaultplayermodel_yellow; defaultskin = autocvar_sv_defaultplayerskin_yellow; break; + case NUM_TEAM_4: defaultmodel = autocvar_sv_defaultplayermodel_pink; defaultskin = autocvar_sv_defaultplayerskin_pink; break; } } @@ -409,9 +421,13 @@ void FixPlayermodel(entity player) { if(teamplay) { - string s = Static_Team_ColorName_Lower(player.team); - if (s != "neutral") - defaultskin = cvar(strcat("sv_defaultplayerskin_", s)); + switch(player.team) + { + case NUM_TEAM_1: defaultskin = autocvar_sv_defaultplayerskin_red; break; + case NUM_TEAM_2: defaultskin = autocvar_sv_defaultplayerskin_blue; break; + case NUM_TEAM_3: defaultskin = autocvar_sv_defaultplayerskin_yellow; break; + case NUM_TEAM_4: defaultskin = autocvar_sv_defaultplayerskin_pink; break; + } } if(!defaultskin) @@ -484,9 +500,8 @@ void PutClientInServer(entity this) WriteByte(MSG_ONE, SVC_SETVIEW); WriteEntity(MSG_ONE, this); } - if (gameover) { + if (game_stopped) TRANSMUTE(Observer, this); - } SetSpectatee(this, NULL); @@ -517,6 +532,8 @@ void PutClientInServer(entity this) this.wasplayer = true; this.iscreature = true; this.teleportable = TELEPORT_NORMAL; + if(!this.damagedbycontents) + IL_PUSH(g_damagedbycontents, this); this.damagedbycontents = true; set_movetype(this, MOVETYPE_WALK); this.solid = SOLID_SLIDEBOX; @@ -604,6 +621,7 @@ void PutClientInServer(entity this) this.strength_finished = 0; this.invincible_finished = 0; this.fire_endtime = -1; + this.revive_progress = 0; this.revival_time = 0; this.air_finished = time + 12; @@ -640,6 +658,7 @@ void PutClientInServer(entity this) IL_PUSH(g_bot_targets, this); this.bot_attack = true; this.monster_attack = true; + navigation_dynamicgoal_init(this, false); PHYS_INPUT_BUTTON_ATCK(this) = PHYS_INPUT_BUTTON_JUMP(this) = PHYS_INPUT_BUTTON_ATCK2(this) = false; @@ -651,7 +670,10 @@ void PutClientInServer(entity this) for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) { .entity weaponentity = weaponentities[slot]; + entity oldwep = this.(weaponentity); CL_SpawnWeaponentity(this, weaponentity); + if(oldwep && oldwep.owner == this) + this.(weaponentity).m_gunalign = oldwep.m_gunalign; } this.alpha = default_player_alpha; this.colormod = '1 1 1' * autocvar_g_player_brightness; @@ -704,6 +726,8 @@ void PutClientInServer(entity this) this.(weaponentity).cnt = -1; } + MUTATOR_CALLHOOK(PlayerWeaponSelect, this); + if (!warmup_stage && !this.alivetime) this.alivetime = time; @@ -713,7 +737,6 @@ void PutClientInServer(entity 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? bool ClientInit_SendEntity(entity this, entity to, int sf) @@ -867,7 +890,7 @@ void ClientKill_Now(entity this) } void KillIndicator_Think(entity this) { - if (gameover) + if (game_stopped) { this.owner.killindicator = NULL; delete(this); @@ -911,7 +934,7 @@ void ClientKill_TeamChange (entity this, float targetteam) // 0 = don't change, float killtime; float starttime; - if (gameover) + if (game_stopped) return; killtime = autocvar_g_balance_kill_delay; @@ -1003,7 +1026,7 @@ void ClientKill_TeamChange (entity this, float targetteam) // 0 = don't change, void ClientKill (entity this) { - if(gameover) return; + if(game_stopped) return; if(this.player_blocked) return; if(STAT(FROZEN, this)) return; @@ -1051,8 +1074,8 @@ ClientPreConnect Called once (not at each match start) when a client begins a connection to the server ============= */ -void ClientPreConnect () -{ENGINE_EVENT(); +void ClientPreConnect(entity this) +{ if(autocvar_sv_eventlog) { GameLogEcho(sprintf(":connect:%d:%d:%s", @@ -1141,7 +1164,7 @@ void ClientConnect(entity this) if (IS_BOT_CLIENT(this)) PlayerStats_GameReport_AddPlayer(this); if (autocvar_sv_eventlog) - GameLogEcho(strcat(":join:", ftos(this.playerid), ":", ftos(etof(this)), ":", ((IS_REAL_CLIENT(this)) ? this.netaddress : "bot"), ":", this.netname)); + GameLogEcho(strcat(":join:", ftos(this.playerid), ":", ftos(etof(this)), ":", ((IS_REAL_CLIENT(this)) ? this.netaddress : "bot"), ":", playername(this, false))); LogTeamchange(this.playerid, this.team, 1); @@ -1191,12 +1214,6 @@ void ClientConnect(entity this) if (IS_REAL_CLIENT(this)) { - if (!autocvar_g_campaign) - { - this.motd_actived_time = -1; - Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_MOTD, getwelcomemessage(this)); - } - if (g_weaponarena_weapons == WEPSET(TUBA)) stuffcmd(this, "cl_cmd settemp chase_active 1\n"); } @@ -1205,7 +1222,7 @@ void ClientConnect(entity this) stuffcmd(this, strcat("\nfog ", world.fog, "\nr_fog_exp2 0\nr_drawfog 1\n")); if (autocvar_sv_teamnagger && !(autocvar_bot_vs_human && AvailableTeams() == 2)) - if (!g_ca && !g_cts && !g_race) // teamnagger is currently bad for ca, race & cts + if(!MUTATOR_CALLHOOK(HideTeamNagger, this)) send_CSQC_teamnagger(); CSQCMODEL_AUTOINIT(this); @@ -1216,6 +1233,8 @@ void ClientConnect(entity this) sv_notice_join(this); // update physics stats (players can spawn before physics runs) + STAT(MOVEVARS_HIGHSPEED, this) = autocvar_g_movement_highspeed; + MUTATOR_CALLHOOK(PlayerPhysics_UpdateStats, this); // do it BEFORE the function so we can modify highspeed! Physics_UpdateStats(this, PHYS_HIGHSPEED(this)); IL_EACH(g_initforplayer, it.init_for_player, { @@ -1223,6 +1242,15 @@ void ClientConnect(entity this) }); MUTATOR_CALLHOOK(ClientConnect, this); + + if (IS_REAL_CLIENT(this)) + { + if (!autocvar_g_campaign && !IS_PLAYER(this)) + { + this.motd_actived_time = -1; + Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_MOTD, getwelcomemessage(this)); + } + } } /* ============= @@ -1247,7 +1275,8 @@ void ClientDisconnect(entity this) Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_DISCONNECT, this.netname); - SetSpectatee(this, NULL); + if(IS_SPEC(this)) + SetSpectatee(this, NULL); MUTATOR_CALLHOOK(ClientDisconnect, this); @@ -1278,6 +1307,8 @@ void ClientDisconnect(entity this) this.playerid = 0; ReadyCount(); if (vote_called && IS_REAL_CLIENT(this)) VoteCount(false); + + ONREMOVE(this); } void ChatBubbleThink(entity this) @@ -1380,7 +1411,7 @@ void player_powerups(entity this) // add a way to see what the items were BEFORE all of these checks for the mutator hook int items_prev = this.items; - if((this.items & IT_USING_JETPACK) && !IS_DEAD(this) && !gameover) + if((this.items & IT_USING_JETPACK) && !IS_DEAD(this) && !game_stopped) this.modelflags |= MF_ROCKET; else this.modelflags &= ~MF_ROCKET; @@ -1604,11 +1635,11 @@ void player_regen(entity this) } bool zoomstate_set; -void SetZoomState(entity this, float z) +void SetZoomState(entity this, float newzoom) { - if(z != this.zoomstate) + if(newzoom != this.zoomstate) { - this.zoomstate = z; + this.zoomstate = newzoom; ClientData_Touch(this); } zoomstate_set = true; @@ -1662,10 +1693,13 @@ void SpectateCopy(entity this, entity spectatee) this.hit_time = spectatee.hit_time; this.strength_finished = spectatee.strength_finished; this.invincible_finished = spectatee.invincible_finished; + this.superweapons_finished = spectatee.superweapons_finished; STAT(PRESSED_KEYS, this) = STAT(PRESSED_KEYS, spectatee); this.weapons = spectatee.weapons; this.vortex_charge = spectatee.vortex_charge; this.vortex_chargepool_ammo = spectatee.vortex_chargepool_ammo; + this.okvortex_charge = spectatee.okvortex_charge; + this.okvortex_chargepool_ammo = spectatee.okvortex_chargepool_ammo; this.hagar_load = spectatee.hagar_load; this.arc_heat_percent = spectatee.arc_heat_percent; this.minelayer_mines = spectatee.minelayer_mines; @@ -1686,6 +1720,17 @@ void SpectateCopy(entity this, entity spectatee) setsize(this, spectatee.mins, spectatee.maxs); SetZoomState(this, spectatee.zoomstate); + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + { + .entity weaponentity = weaponentities[slot]; + this.(weaponentity) = spectatee.(weaponentity); + } + + for(int slot = 0; slot < MAX_AXH; ++slot) + { + this.(AuxiliaryXhair[slot]) = spectatee.(AuxiliaryXhair[slot]); + } + anticheat_spectatecopy(this, spectatee); this.hud = spectatee.hud; if(spectatee.vehicle) @@ -2138,7 +2183,7 @@ void PlayerUseKey(entity this) if(this.vehicle) { - if(!gameover) + if(!game_stopped) { vehicles_exit(this.vehicle, VHEF_NORMAL); return; @@ -2148,7 +2193,7 @@ void PlayerUseKey(entity this) { if(!STAT(FROZEN, this)) if(!IS_DEAD(this)) - if(!gameover) + if(!game_stopped) { entity head, closest_target = NULL; head = WarpZone_FindRadius(this.origin, autocvar_g_vehicles_enter_radius, true); @@ -2221,7 +2266,7 @@ void PlayerPreThink (entity this) } if (this.netname != this.netname_previous) { if (autocvar_sv_eventlog) { - GameLogEcho(strcat(":name:", ftos(this.playerid), ":", this.netname)); + GameLogEcho(strcat(":name:", ftos(this.playerid), ":", playername(this, false))); } if (this.netname_previous) strunzone(this.netname_previous); this.netname_previous = strzone(this.netname); @@ -2279,7 +2324,7 @@ void PlayerPreThink (entity this) MUTATOR_CALLHOOK(PlayerPreThink, this); - if(autocvar_g_vehicles_enter && (time > this.last_vehiclecheck) && !gameover && !this.vehicle) + if(autocvar_g_vehicles_enter && (time > this.last_vehiclecheck) && !game_stopped && !this.vehicle) if(IS_PLAYER(this) && !STAT(FROZEN, this) && !IS_DEAD(this)) { FOREACH_ENTITY_RADIUS(this.origin, autocvar_g_vehicles_enter_radius, IS_VEHICLE(it), @@ -2314,8 +2359,10 @@ void PlayerPreThink (entity this) if (IS_PLAYER(this)) { CheckRules_Player(this); - if (intermission_running) { - IntermissionThink(this); + if (game_stopped || intermission_running) { + this.modelflags &= ~MF_ROCKET; + if(intermission_running) + IntermissionThink(this); return; } @@ -2400,8 +2447,18 @@ void PlayerPreThink (entity this) this.prevorigin = this.origin; + bool have_hook = false; + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + { + .entity weaponentity = weaponentities[slot]; + if(this.(weaponentity).hook.state) + { + have_hook = true; + break; + } + } bool do_crouch = PHYS_INPUT_BUTTON_CROUCH(this); - if (this.hook.state) { + if (have_hook) { do_crouch = false; } else if (this.waterlevel >= WATERLEVEL_SWIMMING) { do_crouch = false; @@ -2461,7 +2518,13 @@ void PlayerPreThink (entity this) { .entity weaponentity = weaponentities[slot]; if (WEP_CVAR(vortex, charge_rot_rate) && this.(weaponentity).vortex_charge > WEP_CVAR(vortex, charge_limit) && this.(weaponentity).vortex_charge_rottime < time) + { this.(weaponentity).vortex_charge = bound(WEP_CVAR(vortex, charge_limit), this.(weaponentity).vortex_charge - WEP_CVAR(vortex, charge_rot_rate) * frametime / W_TICSPERFRAME, 1); + } + if (WEP_CVAR(okvortex, charge_rot_rate) && this.(weaponentity).okvortex_charge > WEP_CVAR(okvortex, charge_limit) && this.(weaponentity).okvortex_charge_rottime < time) + { + this.(weaponentity).okvortex_charge = bound(WEP_CVAR(okvortex, charge_limit), this.(weaponentity).okvortex_charge - WEP_CVAR(okvortex, charge_rot_rate) * frametime / W_TICSPERFRAME, 1); + } } if (frametime) player_anim(this); @@ -2474,8 +2537,9 @@ void PlayerPreThink (entity this) this.dmg_team = max(0, this.dmg_team - autocvar_g_teamdamage_resetspeed * frametime); } - else if (gameover) { - if (intermission_running) IntermissionThink(this); + else if (game_stopped || intermission_running) { + if(intermission_running) + IntermissionThink(this); return; } else if (IS_OBSERVER(this)) { @@ -2625,13 +2689,23 @@ void PlayerPostThink (entity this) CheatFrame(this); //CheckPlayerJump(); + if (game_stopped) + { + this.solid = SOLID_NOT; + this.takedamage = DAMAGE_NO; + set_movetype(this, MOVETYPE_NONE); + } if (IS_PLAYER(this)) { DrownPlayer(this); CheckRules_Player(this); UpdateChatBubble(this); if (this.impulse) ImpulseCommands(this); - if (intermission_running) return; // intermission or finale + if (game_stopped) + { + CSQCMODEL_AUTOUPDATE(this); + return; + } GetPressedKeys(this); }