X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fserver%2Fclient.qc;h=58e512a38255aa825cd207ba8b013df1583d492f;hp=71c2b22654633f0b311497a9628b45e360499200;hb=cbca1a79315fe08c4796273a490a4d12b7d3291d;hpb=59cb391f9f3830ee3581ac705ed62e1697d5d99b diff --git a/qcsrc/server/client.qc b/qcsrc/server/client.qc index 71c2b22654..58e512a382 100644 --- a/qcsrc/server/client.qc +++ b/qcsrc/server/client.qc @@ -23,6 +23,7 @@ #include "bot/api.qh" #include "../common/ent_cs.qh" +#include "../common/wepent.qh" #include #include @@ -36,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" @@ -111,7 +113,6 @@ bool ClientData_Send(entity this, entity to, int sf) 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 if (autocvar_sv_showspectators) sf |= 16; // show spectators WriteHeader(MSG_ENTITY, ENT_CLIENT_CLIENTDATA); @@ -121,11 +122,6 @@ bool ClientData_Send(entity this, entity to, int sf) { WriteByte(MSG_ENTITY, to.spectatee_status); } - if (sf & 8) - { - WriteAngle(MSG_ENTITY, e.v_angle.x); - WriteAngle(MSG_ENTITY, e.v_angle.y); - } if(sf & 16) { @@ -256,7 +252,7 @@ void PutObserverInServer(entity this) this.view_ofs = '0 0 0'; } - RemoveGrapplingHook(this); + RemoveGrapplingHooks(this); Portal_ClearAll(this); Unfreeze(this); SetSpectatee(this, NULL); @@ -303,6 +299,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)); @@ -333,7 +331,6 @@ void PutObserverInServer(entity this) 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; @@ -342,10 +339,13 @@ void PutObserverInServer(entity this) this.weapons = '0 0 0'; this.drawonlytoclient = this; - this.weaponname = ""; 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; @@ -357,10 +357,6 @@ void PutObserverInServer(entity this) this.oldvelocity = this.velocity; this.fire_endtime = -1; this.event_damage = func_null; - - STAT(ACTIVEWEAPON, this) = WEP_Null.m_id; - STAT(SWITCHINGWEAPON, this) = WEP_Null.m_id; - STAT(SWITCHWEAPON, this) = WEP_Null.m_id; } int player_getspecies(entity this) @@ -524,6 +520,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; @@ -625,9 +623,11 @@ void PutClientInServer(entity this) FixPlayermodel(this); this.drawonlytoclient = NULL; + this.viewloc = NULL; + this.crouch = false; - this.view_ofs = STAT(PL_VIEW_OFS, NULL); - setsize(this, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL)); + this.view_ofs = STAT(PL_VIEW_OFS, this); + setsize(this, STAT(PL_MIN, this), STAT(PL_MAX, this)); 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 @@ -655,7 +655,8 @@ void PutClientInServer(entity this) for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) { - CL_SpawnWeaponentity(this, weaponentities[slot]); + .entity weaponentity = weaponentities[slot]; + CL_SpawnWeaponentity(this, weaponentity); } this.alpha = default_player_alpha; this.colormod = '1 1 1' * autocvar_g_player_brightness; @@ -670,7 +671,11 @@ void PutClientInServer(entity this) it.wr_resetplayer(it, this); // reload all reloadable weapons if (it.spawnflags & WEP_FLAG_RELOADABLE) { - this.weapon_load[it.m_id] = it.reloading_ammo; + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + { + .entity weaponentity = weaponentities[slot]; + this.(weaponentity).weapon_load[it.m_id] = it.reloading_ammo; + } } )); @@ -691,11 +696,18 @@ void PutClientInServer(entity this) delete(spot); // usefull for checking if there are spawnpoints, that let drop through the floor } - 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; + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + { + .entity weaponentity = weaponentities[slot]; + if(slot == 0) + this.(weaponentity).m_switchweapon = w_getbestweapon(this, weaponentity); + else + this.(weaponentity).m_switchweapon = WEP_Null; + this.(weaponentity).m_weapon = WEP_Null; + this.(weaponentity).weaponname = ""; + this.(weaponentity).m_switchingweapon = WEP_Null; + this.(weaponentity).cnt = -1; + } if (!warmup_stage && !this.alivetime) this.alivetime = time; @@ -706,7 +718,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) @@ -1044,8 +1055,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", @@ -1142,7 +1153,10 @@ void ClientConnect(entity this) this.netname_previous = strzone(this.netname); - Send_Notification(NOTIF_ALL, NULL, MSG_INFO, ((teamplay && IS_PLAYER(this)) ? APP_TEAM_ENT(this, INFO_JOIN_CONNECT_TEAM) : INFO_JOIN_CONNECT), this.netname); + if(teamplay && IS_PLAYER(this)) + Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(this.team, INFO_JOIN_CONNECT_TEAM), this.netname); + else + Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_JOIN_CONNECT, this.netname); stuffcmd(this, clientstuff, "\n"); stuffcmd(this, "cl_particles_reloadeffects\n"); // TODO do we still need this? @@ -1205,6 +1219,9 @@ void ClientConnect(entity this) if (IS_REAL_CLIENT(this)) sv_notice_join(this); + // update physics stats (players can spawn before physics runs) + Physics_UpdateStats(this, PHYS_HIGHSPEED(this)); + IL_EACH(g_initforplayer, it.init_for_player, { it.init_for_player(it, this); }); @@ -1244,7 +1261,7 @@ void ClientDisconnect(entity this) Unfreeze(this); - RemoveGrapplingHook(this); + RemoveGrapplingHooks(this); // Here, everything has been done that requires this player to be a client. @@ -1265,6 +1282,8 @@ void ClientDisconnect(entity this) this.playerid = 0; ReadyCount(); if (vote_called && IS_REAL_CLIENT(this)) VoteCount(false); + + ONREMOVE(this); } void ChatBubbleThink(entity this) @@ -1591,11 +1610,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; @@ -1604,7 +1623,7 @@ void SetZoomState(entity this, float z) void GetPressedKeys(entity this) { MUTATOR_CALLHOOK(GetPressedKeys, this); - int keys = this.pressedkeys; + int keys = STAT(PRESSED_KEYS, this); 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); @@ -1614,7 +1633,9 @@ void GetPressedKeys(entity 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; + this.pressedkeys = keys; // store for other users + + STAT(PRESSED_KEYS, this) = keys; } /* @@ -1647,7 +1668,7 @@ 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.pressedkeys = spectatee.pressedkeys; + 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; @@ -1664,12 +1685,19 @@ void SpectateCopy(entity this, entity spectatee) this.angles = spectatee.v_angle; STAT(FROZEN, this) = STAT(FROZEN, spectatee); this.revive_progress = spectatee.revive_progress; + this.viewloc = spectatee.viewloc; if(!PHYS_INPUT_BUTTON_USE(this) && STAT(CAMERA_SPECTATOR, this) != 2) this.fixangle = true; setorigin(this, spectatee.origin); 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); + } + anticheat_spectatecopy(this, spectatee); this.hud = spectatee.hud; if(spectatee.vehicle) @@ -1878,8 +1906,6 @@ void Join(entity this) { TRANSMUTE(Player, this); - SetSpectatee(this, NULL); - if(!this.team_selected) if(autocvar_g_campaign || autocvar_g_balance_teams) JoinBestTeam(this, false, true); @@ -1890,10 +1916,11 @@ void Join(entity this) Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_PREVENT_JOIN); PutClientInServer(this); - if(!this.team_selected) - PlayerScore_Clear(this); - Send_Notification(NOTIF_ALL, NULL, MSG_INFO, ((teamplay && this.team != -1) ? APP_TEAM_ENT(this, INFO_JOIN_PLAY_TEAM) : INFO_JOIN_PLAY), this.netname); + if(teamplay && this.team != -1) + Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(this.team, INFO_JOIN_PLAY_TEAM), this.netname); + else + Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_JOIN_PLAY, this.netname); this.team_selected = false; } @@ -2331,7 +2358,7 @@ void PlayerPreThink (entity this) { if ((this.respawn_flags & RESPAWN_FORCE) && !(this.respawn_time < this.respawn_time_max)) this.deadflag = DEAD_RESPAWNING; - else if (!button_pressed || (this.respawn_flags & RESPAWN_FORCE)) + else if (!button_pressed || (time >= this.respawn_time_max && (this.respawn_flags & RESPAWN_FORCE))) this.deadflag = DEAD_DEAD; break; } @@ -2419,13 +2446,17 @@ void PlayerPreThink (entity this) { this.items &= ~this.items_added; - //for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) - //{ - //.entity weaponentity = weaponentities[slot]; - //W_WeaponFrame(this, weaponentity); - //} - .entity weaponentity = weaponentities[0]; // TODO - W_WeaponFrame(this, weaponentity); + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + { + .entity weaponentity = weaponentities[slot]; + W_WeaponFrame(this, weaponentity); + + if(slot == 0) + { + this.clip_load = this.(weaponentity).clip_load; + this.clip_size = this.(weaponentity).clip_size; + } + } this.items_added = 0; if (this.items & ITEM_Jetpack.m_itemid && (this.items & ITEM_JetpackRegen.m_itemid || this.ammo_fuel >= 0.01)) @@ -2438,8 +2469,12 @@ void PlayerPreThink (entity this) // WEAPONTODO: Add a weapon request for this // rot vortex charge to the charge limit - 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); + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + { + .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 (frametime) player_anim(this); @@ -2464,11 +2499,15 @@ void PlayerPreThink (entity this) // WEAPONTODO: Add weapon request for this 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) - ); + bool wep_zoomed = false; + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + { + .entity weaponentity = weaponentities[slot]; + Weapon thiswep = this.(weaponentity).m_weapon; + if(thiswep != WEP_Null && thiswep.wr_zoom) + wep_zoomed += thiswep.wr_zoom(thiswep, this); + } + SetZoomState(this, PHYS_INPUT_BUTTON_ZOOM(this) || PHYS_INPUT_BUTTON_ZOOMSCRIPT(this) || wep_zoomed); } if (this.teamkill_soundtime && time > this.teamkill_soundtime) @@ -2491,8 +2530,12 @@ void PlayerPreThink (entity 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 (PS(this).m_weapon == WEP_Null) - this.clip_load = this.clip_size = 0; + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + { + .entity weaponentity = weaponentities[slot]; + if(this.(weaponentity).m_weapon == WEP_Null) + this.(weaponentity).clip_load = this.(weaponentity).clip_size = 0; + } } void DrownPlayer(entity this)