From: TimePath Date: Wed, 23 Mar 2016 03:32:01 +0000 (+1100) Subject: Transmute player entities X-Git-Tag: xonotic-v0.8.2~1040 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=911f804869b91d4439573cb47b4a9d3d3f9699b8;p=xonotic%2Fxonotic-data.pk3dir.git Transmute player entities --- diff --git a/qcsrc/client/hud/hud.qc b/qcsrc/client/hud/hud.qc index f62b8992e..fcfa24203 100644 --- a/qcsrc/client/hud/hud.qc +++ b/qcsrc/client/hud/hud.qc @@ -403,9 +403,9 @@ void DrawNumIcon_expanding(vector myPos, vector mySize, float x, string icon, bo drawpic_aspect_skin_expanding(picpos, icon, '1 1 0' * newSize.y, '1 1 1', panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL, fadelerp); } -void DrawNumIcon(vector myPos, vector mySize, float x, string icon, bool vertical, bool icon_right_align, vector color, float theAlpha) +void DrawNumIcon(vector myPos, vector mySize, float x, string icon, bool vertical, int icon_right_align, vector color, float theAlpha) { - TC(bool, vertical); TC(bool, icon_right_align); + TC(bool, vertical); TC(int, icon_right_align); DrawNumIcon_expanding(myPos, mySize, x, icon, vertical, icon_right_align, color, theAlpha, 0); } diff --git a/qcsrc/common/mutators/mutator/superspec/superspec.qc b/qcsrc/common/mutators/mutator/superspec/superspec.qc index fa2a80aa9..5471bcbae 100644 --- a/qcsrc/common/mutators/mutator/superspec/superspec.qc +++ b/qcsrc/common/mutators/mutator/superspec/superspec.qc @@ -26,7 +26,7 @@ const float SSF_ITEMMSG = 4; bool superspec_Spectate(entity _player) {SELFPARAM(); if(Spectate(_player) == 1) - self.classname = STR_SPECTATOR; + TRANSMUTE(Spectator, self); return true; } diff --git a/qcsrc/lib/oo.qh b/qcsrc/lib/oo.qh index d0c770ae3..e4f8d289e 100644 --- a/qcsrc/lib/oo.qh +++ b/qcsrc/lib/oo.qh @@ -112,8 +112,8 @@ void clearentity(entity e) #define NEW(cname, ...) \ OVERLOAD_(spawn##cname, new_pure(cname) P99_IF_EMPTY(__VA_ARGS__)()(, __VA_ARGS__)) - #define TRANSMUTE(cname, this, ...) \ - OVERLOAD_(spawn##cname, (this.transmute = true, this.classname = #cname, this) P99_IF_EMPTY(__VA_ARGS__)()(, __VA_ARGS__)) + #define _TRANSMUTE(cname, this, ...) \ + OVERLOAD_(spawn##cname, this P99_IF_EMPTY(__VA_ARGS__)()(, __VA_ARGS__)) #define CONSTRUCT(cname, ...) \ OVERLOAD_(spawn##cname, this P99_IF_EMPTY(__VA_ARGS__)()(, __VA_ARGS__)) @@ -121,13 +121,22 @@ void clearentity(entity e) #define NEW(cname, ...) \ OVERLOAD(spawn##cname, new_pure(cname),##__VA_ARGS__) - #define TRANSMUTE(cname, this, ...) \ - OVERLOAD(spawn##cname, (this.transmute = true, this.classname = #cname, this),##__VA_ARGS__) + #define _TRANSMUTE(cname, this, ...) \ + OVERLOAD(spawn##cname, this,##__VA_ARGS__) #define CONSTRUCT(cname, ...) \ OVERLOAD(spawn##cname, this,##__VA_ARGS__) #endif +#define TRANSMUTE(cname, this, ...) MACRO_BEGIN \ + entity _e = (this); \ + if (_e.vtblbase != cname##_vtbl) { \ + _e.transmute = true; \ + _e.classname = #cname; \ + _TRANSMUTE(cname, _e, __VA_ARGS__); \ + } \ + MACRO_END + #define CONSTRUCTOR(cname, ...) \ cname OVERLOAD(spawn##cname, cname this, __VA_ARGS__) \ { \ @@ -210,6 +219,7 @@ STATIC_INIT(RegisterClasses) METHOD(cname, dtor, void(cname this)) \ { \ METHOD_REFERENCE(cname, dtorimpl)(this); \ + this.instanceOf##cname = false; \ entity super = SUPER(cname); \ if (super != cname##_vtbl) super.dtor(this); \ } \ diff --git a/qcsrc/server/cl_client.qc b/qcsrc/server/cl_client.qc index b4fd0f900..24d08a43c 100644 --- a/qcsrc/server/cl_client.qc +++ b/qcsrc/server/cl_client.qc @@ -246,7 +246,7 @@ void PutObserverInServer() this.spectatortime = time; this.bot_attack = false; this.hud = HUD_NORMAL; - this.classname = STR_OBSERVER; + TRANSMUTE(Observer, this); this.iscreature = false; this.teleportable = TELEPORT_SIMPLE; this.damagedbycontents = false; @@ -406,14 +406,14 @@ void PutClientInServer() { SELFPARAM(); if (IS_BOT_CLIENT(this)) { - this.classname = STR_PLAYER; + TRANSMUTE(Player, this); } else if (IS_REAL_CLIENT(this)) { msg_entity = this; WriteByte(MSG_ONE, SVC_SETVIEW); WriteEntity(MSG_ONE, this); } if (gameover) { - this.classname = STR_OBSERVER; + TRANSMUTE(Observer, this); } SetSpectatee(this, NULL); @@ -438,7 +438,7 @@ void PutClientInServer() return; // spawn failed } - this.classname = STR_PLAYER; + TRANSMUTE(Player, this); this.wasplayer = true; this.iscreature = true; this.teleportable = TELEPORT_NORMAL; @@ -990,15 +990,12 @@ void ClientConnect() assert(!IS_CLIENT(this), return); assert(player_count >= 0, player_count = 0); TRANSMUTE(Client, this); - this.classname = "player_joining"; #ifdef WATERMARK Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_WATERMARK, WATERMARK); #endif this.version_nagtime = time + 10 + random() * 10; - ClientState_attach(this); - // identify the right forced team if (autocvar_g_campaign) { @@ -1035,21 +1032,19 @@ void ClientConnect() JoinBestTeam(this, false, false); // if the team number is valid, keep it if (autocvar_sv_spectate || autocvar_g_campaign || this.team_forced < 0) { - this.classname = STR_OBSERVER; + TRANSMUTE(Observer, this); } else { if (!teamplay || autocvar_g_balance_teams) { - this.classname = STR_PLAYER; + TRANSMUTE(Player, this); campaign_bots_may_start = 1; } else { - this.classname = STR_OBSERVER; // do it anyway + TRANSMUTE(Observer, this); // do it anyway } } - this.playerid = ++playerid_last; - PlayerStats_GameReport_AddEvent(sprintf("kills-%d", this.playerid)); // always track bots, don't ask for cl_allow_uidtracking @@ -1754,7 +1749,7 @@ void LeaveSpectatorMode() { if(!teamplay || autocvar_g_campaign || autocvar_g_balance_teams || (self.wasplayer && autocvar_g_changeteam_banned) || self.team_forced > 0) { - self.classname = STR_PLAYER; + TRANSMUTE(Player, self); if(autocvar_g_campaign || autocvar_g_balance_teams) { JoinBestTeam(self, false, true); } @@ -1898,7 +1893,7 @@ void ObserverThink() } else if(PHYS_INPUT_BUTTON_ATCK(self) && !self.version_mismatch) { self.flags &= ~FL_JUMPRELEASED; if(SpectateNext()) { - self.classname = STR_SPECTATOR; + TRANSMUTE(Spectator, self); } } else { prefered_movetype = ((!PHYS_INPUT_BUTTON_USE(self) ? self.cvar_cl_clippedspectating : !self.cvar_cl_clippedspectating) ? MOVETYPE_FLY_WORLDONLY : MOVETYPE_NOCLIP); @@ -1932,24 +1927,24 @@ void SpectatorThink() } else if(PHYS_INPUT_BUTTON_ATCK(self) || self.impulse == 10 || self.impulse == 15 || self.impulse == 18 || (self.impulse >= 200 && self.impulse <= 209)) { self.flags &= ~FL_JUMPRELEASED; if(SpectateNext()) { - self.classname = STR_SPECTATOR; + TRANSMUTE(Spectator, self); } else { - self.classname = STR_OBSERVER; + TRANSMUTE(Observer, self); 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 = STR_SPECTATOR; + TRANSMUTE(Spectator, self); } else { - self.classname = STR_OBSERVER; + TRANSMUTE(Observer, self); PutClientInServer(); } self.impulse = 0; } else if (PHYS_INPUT_BUTTON_ATCK2(self)) { self.flags &= ~FL_JUMPRELEASED; - self.classname = STR_OBSERVER; + TRANSMUTE(Observer, self); PutClientInServer(); } else { if(!SpectateUpdate()) diff --git a/qcsrc/server/cl_client.qh b/qcsrc/server/cl_client.qh index 55ef7114c..70df314ea 100644 --- a/qcsrc/server/cl_client.qh +++ b/qcsrc/server/cl_client.qh @@ -1,5 +1,7 @@ #pragma once +void ClientState_attach(entity this); + CLASS(Client, Object) /** Client name */ ATTRIB(Client, netname, string, this.netname) @@ -23,11 +25,67 @@ CLASS(Client, Object) ATTRIB(Client, crypto_encryptmethod, string, this.crypto_encryptmethod) /** the string "HMAC-SHA256" if signing, and string_null if plaintext */ ATTRIB(Client, crypto_signmethod, string, this.crypto_signmethod) + + // custom + + ATTRIB(Client, flags, int, 0) + ATTRIB(Client, playerid, int, 0) + + METHOD(Client, m_unwind, bool(Client this)); + INIT(Client) { + if (this.m_unwind(this)) return this; + this.classname = "player_joining"; this.flags = FL_CLIENT; + static int playerid_last; + this.playerid = ++playerid_last; + ClientState_attach(this); } ENDCLASS(Client) +CLASS(Observer, Client) + INIT(Observer) { + this.classname = STR_OBSERVER; + } + DESTRUCTOR(Observer) { } +ENDCLASS(Observer) + +CLASS(Spectator, Client) + INIT(Spectator) { + this.classname = STR_SPECTATOR; + } + DESTRUCTOR(Spectator) { } +ENDCLASS(Spectator) + +CLASS(Player, Client) + INIT(Player) { + this.classname = STR_PLAYER; + } + DESTRUCTOR(Player) { } +ENDCLASS(Player) + +METHOD(Client, m_unwind, bool(Client this)) +{ + TC(Client, this); + #define UNWIND(class) MACRO_BEGIN if (this.instanceOf##class) { METHOD_REFERENCE(class, dtorimpl)(this); } MACRO_END + switch (this.classname) { + case "Observer": + UNWIND(Spectator); + UNWIND(Player); + return true; + case "Spectator": + UNWIND(Observer); + UNWIND(Player); + return true; + case "Player": + UNWIND(Observer); + UNWIND(Spectator); + return true; + } + #undef UNWIND + return false; +} + float c1, c2, c3, c4; void play_countdown(float finished, Sound samp); diff --git a/qcsrc/server/command/cmd.qc b/qcsrc/server/command/cmd.qc index 23c57ea6e..56ba45c61 100644 --- a/qcsrc/server/command/cmd.qc +++ b/qcsrc/server/command/cmd.qc @@ -117,7 +117,7 @@ void ClientCommand_clientversion(float request, float argc) // internal command } else if (teamplay && !autocvar_sv_spectate && !(self.team_forced > 0)) { - self.classname = STR_OBSERVER; // really? + TRANSMUTE(Observer, self); // really? stuffcmd(self, "menu_showteamselect\n"); } } @@ -178,7 +178,7 @@ void ClientCommand_join(float request) if (nJoinAllowed(self, self)) { if (autocvar_g_campaign) campaign_bots_may_start = 1; - self.classname = STR_PLAYER; + TRANSMUTE(Player, self); PlayerScore_Clear(self); Kill_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CPID_PREVENT_JOIN); Send_Notification(NOTIF_ALL, world, MSG_INFO, ((teamplay && self.team != -1) ? APP_TEAM_ENT(this, INFO_JOIN_PLAY_TEAM) : INFO_JOIN_PLAY), self.netname); diff --git a/qcsrc/server/defs.qh b/qcsrc/server/defs.qh index 3b8a2480d..4b1874f89 100644 --- a/qcsrc/server/defs.qh +++ b/qcsrc/server/defs.qh @@ -171,7 +171,6 @@ bool nJoinAllowed(entity this, entity ignore); .entity flagcarried; .int playerid; -float playerid_last; .float noalign; // if set to 1, the item or spawnpoint won't be dropped to the floor .vector death_origin; diff --git a/qcsrc/server/mutators/mutator/gamemode_ca.qc b/qcsrc/server/mutators/mutator/gamemode_ca.qc index 7f2bd4234..c5dedbae7 100644 --- a/qcsrc/server/mutators/mutator/gamemode_ca.qc +++ b/qcsrc/server/mutators/mutator/gamemode_ca.qc @@ -231,7 +231,7 @@ MUTATOR_HOOKFUNCTION(ca, PutClientInServer) SELFPARAM(); if (!allowed_to_spawn && IS_PLAYER(this)) // this is true even when player is trying to join { - this.classname = STR_OBSERVER; + TRANSMUTE(Observer, this); if (this.jointime != time && !this.caplayer) // not when connecting { this.caplayer = 0.5; @@ -252,7 +252,7 @@ MUTATOR_HOOKFUNCTION(ca, reset_map_players) } if (it.caplayer) { - it.classname = STR_PLAYER; + TRANSMUTE(Player, it); it.caplayer = 1; WITH(entity, self, it, PutClientInServer()); } @@ -263,7 +263,7 @@ MUTATOR_HOOKFUNCTION(ca, reset_map_players) MUTATOR_HOOKFUNCTION(ca, ClientConnect) { SELFPARAM(); - this.classname = STR_OBSERVER; + TRANSMUTE(Observer, this); return true; } diff --git a/qcsrc/server/mutators/mutator/gamemode_lms.qc b/qcsrc/server/mutators/mutator/gamemode_lms.qc index cb5760633..7ecb290ab 100644 --- a/qcsrc/server/mutators/mutator/gamemode_lms.qc +++ b/qcsrc/server/mutators/mutator/gamemode_lms.qc @@ -173,7 +173,7 @@ MUTATOR_HOOKFUNCTION(lms, PutClientInServer) // FIXME fix LMS scoring for new system if(PlayerScore_Add(self, SP_LMS_RANK, 0) > 0) { - self.classname = STR_OBSERVER; + TRANSMUTE(Observer, self); Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_LMS_NOLIVES); } } @@ -214,7 +214,7 @@ MUTATOR_HOOKFUNCTION(lms, MakePlayerObserver) MUTATOR_HOOKFUNCTION(lms, ClientConnect) {SELFPARAM(); - self.classname = STR_PLAYER; + TRANSMUTE(Player, self); campaign_bots_may_start = 1; if(PlayerScore_Add(self, SP_LMS_LIVES, LMS_NewPlayerLives()) <= 0) diff --git a/qcsrc/server/race.qc b/qcsrc/server/race.qc index dd3a11cc0..273be69d7 100644 --- a/qcsrc/server/race.qc +++ b/qcsrc/server/race.qc @@ -740,7 +740,7 @@ void trigger_race_checkpoint_verify() qual = g_race_qualifying; setself(spawn()); - self.classname = STR_PLAYER; + TRANSMUTE(Player, self); if(g_race) {