]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Transmute player entities
authorTimePath <andrew.hardaker1995@gmail.com>
Wed, 23 Mar 2016 03:32:01 +0000 (14:32 +1100)
committerTimePath <andrew.hardaker1995@gmail.com>
Wed, 23 Mar 2016 03:32:01 +0000 (14:32 +1100)
qcsrc/client/hud/hud.qc
qcsrc/common/mutators/mutator/superspec/superspec.qc
qcsrc/lib/oo.qh
qcsrc/server/cl_client.qc
qcsrc/server/cl_client.qh
qcsrc/server/command/cmd.qc
qcsrc/server/defs.qh
qcsrc/server/mutators/mutator/gamemode_ca.qc
qcsrc/server/mutators/mutator/gamemode_lms.qc
qcsrc/server/race.qc

index f62b8992e14111773fb9f7c482b235246fcfa98b..fcfa24203cd15907925220e0d874802bd0b2266e 100644 (file)
@@ -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);
 }
 
index fa2a80aa9e3cd98ee0ed5b854cb6a5b7bc86645a..5471bcbae06fac3e3e8422442d61f98136ffa908 100644 (file)
@@ -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;
 }
index d0c770ae3160a7f6f32612182929a6452493398e..e4f8d289ebf4d5587310179bdd49977d9aeb8620 100644 (file)
@@ -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); \
     } \
index b4fd0f900c75ed59c050c0b234b1818b4e0accf2..24d08a43cc69c67e609824a97c91dfbeb064ac69 100644 (file)
@@ -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())
index 55ef7114c35e8ccb2d84a60fee179159380f7efb..70df314ea034655c7e71a9afca71e7b4fe0b00ff 100644 (file)
@@ -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);
index 23c57ea6e29d254dae14d6505aa08c2898f4a916..56ba45c61240a07c8b6bc67f8cbe77099a653c65 100644 (file)
@@ -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);
index 3b8a2480d8fbf6936c9b3802b751adf262d70003..4b1874f89fdd7e679bc2394ab319a074f9964bad 100644 (file)
@@ -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;
index 7f2bd42347d08d0b56d05148e34b731d4f25faec..c5dedbae705081f573db6757c13c1ed5cc60c61a 100644 (file)
@@ -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;
 }
 
index cb57606337f2ff8eb4ceaec6a10a03508d087480..7ecb290ab64f0c8bad066a0f355f06acc3381c92 100644 (file)
@@ -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)
index dd3a11cc0929cca2c1760004755d4728c780e128..273be69d7444c45b37183b01501a93aaa602b722 100644 (file)
@@ -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)
        {