]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Further cleanup miscfunctions, document the need to use intrusive lists on entities...
authorMario <mario.mario@y7mail.com>
Fri, 25 Sep 2020 10:02:50 +0000 (20:02 +1000)
committerMario <mario.mario@y7mail.com>
Fri, 25 Sep 2020 10:02:50 +0000 (20:02 +1000)
36 files changed:
qcsrc/client/miscfunctions.qc
qcsrc/client/miscfunctions.qh
qcsrc/client/shownames.qc
qcsrc/common/gamemodes/gamemode/domination/sv_domination.qc
qcsrc/common/gamemodes/gamemode/onslaught/sv_onslaught.qc
qcsrc/common/monsters/monster/spider.qc
qcsrc/common/notifications/all.qc
qcsrc/common/playerstats.qc
qcsrc/common/state.qc
qcsrc/common/turrets/sv_turrets.qc
qcsrc/common/util.qc
qcsrc/common/util.qh
qcsrc/ecs/README.md
qcsrc/lib/warpzone/server.qc
qcsrc/server/chat.qc
qcsrc/server/cheats.qc
qcsrc/server/client.qc
qcsrc/server/command/cmd.qc
qcsrc/server/command/common.qc
qcsrc/server/command/getreplies.qc
qcsrc/server/command/getreplies.qh
qcsrc/server/command/sv_cmd.qc
qcsrc/server/command/vote.qc
qcsrc/server/items/items.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/miscfunctions.qh
qcsrc/server/player.qc
qcsrc/server/player.qh
qcsrc/server/race.qc
qcsrc/server/race.qh
qcsrc/server/scores.qc
qcsrc/server/weapons/common.qc
qcsrc/server/weapons/common.qh
qcsrc/server/weapons/hitplot.qc
qcsrc/server/world.qc
qcsrc/server/world.qh

index a653f4bf1e5ca0af486b06dd58d6f61aafd143a1..34d87b7722909485f5a13349a38ca4cd38725258 100644 (file)
@@ -159,20 +159,6 @@ float PreviewExists(string name)
        return false;
 }
 
-// decolorizes and team colors the player name when needed
-string playername(string thename, float teamid)
-{
-    TC(int, teamid);
-    string t;
-    if (teamplay)
-    {
-        t = Team_ColorCode(teamid);
-        return strcat(t, strdecolorize(thename));
-    }
-    else
-        return strdecolorize(thename);
-}
-
 float cvar_or(string cv, float v)
 {
        string s;
index 5641215ae950cdee1d5a0fe8c31c4851a601743e..f92633a41221697b7c6cc6d24e2a175d0a9ab301 100644 (file)
@@ -36,10 +36,6 @@ vector Rotate(vector v, float a);
 
 #define IS_DEAD(s) (((s).classname == "csqcmodel") ? (s).csqcmodel_isdead : (GetResource((s), RES_HEALTH) <= 0))
 
-
-// decolorizes and team colors the player name when needed
-string playername(string thename, float teamid);
-
 float cvar_or(string cv, float v);
 
 vector project_3d_to_2d(vector vec);
index 7c126f10fa95778931b8290ecea12a0607adf365..ad05c4a2a4c9705c15289cdd81e59406e29829bf 100644 (file)
@@ -177,7 +177,7 @@ void Draw_ShowNames(entity this)
                }
                string s = entcs_GetName(this.sv_entnum - 1);
                if ((autocvar_hud_shownames_decolorize == 1 && teamplay) || autocvar_hud_shownames_decolorize == 2)
-                       s = playername(s, entcs_GetTeam(this.sv_entnum - 1));
+                       s = playername(s, entcs_GetTeam(this.sv_entnum - 1), true);
                drawfontscale = '1 1 0' * resize;
                s = textShortenToWidth(s, namewidth, '1 1 0' * autocvar_hud_shownames_fontsize, stringwidth_colors);
                float width = stringwidth(s, true, '1 1 0' * autocvar_hud_shownames_fontsize);
index 0a6ee791a6d91073353a1fca81e2dcb1d96c9816..d8e2bb3627d42ce3ef012ed950bccb9956ac0eed 100644 (file)
@@ -6,6 +6,7 @@
 #include <server/gamelog.qh>
 #include <server/items/items.qh>
 #include <server/teamplay.qh>
+#include <server/world.qh>
 #include <common/mapobjects/platforms.qh>
 #include <common/mapobjects/triggers.qh>
 
index 1c87e9af684d01992334551b1f3937d002bcdba2..f9011c7d90dfa702f1cfd157594b0d06e1bbfb18 100644 (file)
@@ -6,6 +6,7 @@
 #include <server/command/vote.qh>
 #include <server/damage.qh>
 #include <server/items/items.qh>
+#include <server/world.qh>
 #include <common/mapobjects/defs.qh>
 #include <common/mapobjects/triggers.qh>
 
index 08d28218786524d462b6cf2d321b91aa38e899b0..d965448820e4018d869e89ae9bbe70c35a225e35 100644 (file)
@@ -125,8 +125,6 @@ void M_Spider_Attack_Web_Touch(entity this, entity toucher)
        M_Spider_Attack_Web_Explode(this);
 }
 
-void adaptor_think2use_hittype_splash(entity this);
-
 void M_Spider_Attack_Web(entity this)
 {
        sound(this, CH_SHOTS, SND_ELECTRO_FIRE2, VOL_BASE, ATTEN_NORM);
index e7eaa7cb2ec658e3a6f7ffe3f5468e3d64d119e2..e2c1e185afbea1b4e16e5f0d1599327bd95023bd 100644 (file)
@@ -7,6 +7,7 @@
        #include <common/net_linked.qh>
        #include <common/teams.qh>
        #include <server/autocvars.qh>
+       #include <server/command/getreplies.qh>
        #include <server/world.qh>
        #include <server/mutators/_mod.qh>
 #endif
index 6760ea0435d905df04b43043a2320ed0379efaa8..cbf7f9eef4207c06b783b830ca17235c5d4b29f9 100644 (file)
@@ -136,7 +136,7 @@ void PlayerStats_GameReport_FinalizePlayer(entity p)
        db_put(PS_GR_OUT_DB, sprintf("%s:_playerid", p.playerstats_id), ftos(p.playerid));
 
        if(CS(p).cvar_cl_allow_uid2name == 1 || IS_BOT_CLIENT(p))
-               db_put(PS_GR_OUT_DB, sprintf("%s:_netname", p.playerstats_id), playername(p, false));
+               db_put(PS_GR_OUT_DB, sprintf("%s:_netname", p.playerstats_id), playername(p.netname, p.team, false));
 
        if(teamplay)
                db_put(PS_GR_OUT_DB, sprintf("%s:_team", p.playerstats_id), ftos(p.team));
index 14b22e991cceed2ad0bccdd2222ee899fbcab040..f117340ed948971560eaaffc383c2e7b27d57a92 100644 (file)
@@ -1,5 +1,7 @@
 #include "state.qh"
 
+#include <server/command/getreplies.qh>
+
 void Inventory_new(PlayerState this);
 void Inventory_delete(entity this);
 
@@ -27,7 +29,6 @@ void PlayerState_detach(entity this)
        delete(ps);
 }
 
-void GetCvars(entity this, entity store, int);
 void DecodeLevelParms(entity this);
 void PlayerScore_Attach(entity this);
 void ClientData_Attach(entity this);
index e2a9ab2e4131bee26615108eb55873baef2c27a1..98490610a2470c1aacd575ce26f812764c7b3f65 100644 (file)
@@ -5,6 +5,7 @@
 #include <server/damage.qh>
 #include <server/weapons/common.qh>
 #include <server/weapons/weaponsystem.qh>
+#include <server/world.qh>
 #include <common/mapobjects/defs.qh>
 
 // Generic aiming
index ae0c2ae77ae5c49e6aa00ef3c5b42a0035783be6..4ad1d105dcd52c15f8647de71ea8fd6f18512974 100644 (file)
@@ -1894,3 +1894,133 @@ int Mod_Q1BSP_NativeContentsFromSuperContents(int supercontents)
        return CONTENT_EMPTY;
 }
 #endif
+
+#ifdef SVQC
+void attach_sameorigin(entity e, entity to, string tag)
+{
+    vector org, t_forward, t_left, t_up, e_forward, e_up;
+    float tagscale;
+
+    org = e.origin - gettaginfo(to, gettagindex(to, tag));
+    tagscale = (vlen(v_forward) ** -2); // undo a scale on the tag
+    t_forward = v_forward * tagscale;
+    t_left = v_right * -tagscale;
+    t_up = v_up * tagscale;
+
+    e.origin_x = org * t_forward;
+    e.origin_y = org * t_left;
+    e.origin_z = org * t_up;
+
+    // current forward and up directions
+    if (substring(e.model, 0, 1) == "*") // bmodels have their own rules
+               e.angles = AnglesTransform_FromVAngles(e.angles);
+       else
+               e.angles = AnglesTransform_FromAngles(e.angles);
+    fixedmakevectors(e.angles);
+
+    // untransform forward, up!
+    e_forward.x = v_forward * t_forward;
+    e_forward.y = v_forward * t_left;
+    e_forward.z = v_forward * t_up;
+    e_up.x = v_up * t_forward;
+    e_up.y = v_up * t_left;
+    e_up.z = v_up * t_up;
+
+    e.angles = fixedvectoangles2(e_forward, e_up);
+    if (substring(e.model, 0, 1) == "*") // bmodels have their own rules
+               e.angles = AnglesTransform_ToVAngles(e.angles);
+       else
+               e.angles = AnglesTransform_ToAngles(e.angles);
+
+    setattachment(e, to, tag);
+    setorigin(e, e.origin);
+}
+
+void detach_sameorigin(entity e)
+{
+    vector org;
+    org = gettaginfo(e, 0);
+    e.angles = fixedvectoangles2(v_forward, v_up);
+    if (substring(e.model, 0, 1) == "*") // bmodels have their own rules
+               e.angles = AnglesTransform_ToVAngles(e.angles);
+       else
+               e.angles = AnglesTransform_ToAngles(e.angles);
+    setorigin(e, org);
+    setattachment(e, NULL, "");
+    setorigin(e, e.origin);
+}
+
+void follow_sameorigin(entity e, entity to)
+{
+    set_movetype(e, MOVETYPE_FOLLOW); // make the hole follow
+    e.aiment = to; // make the hole follow bmodel
+    e.punchangle = to.angles; // the original angles of bmodel
+    e.view_ofs = e.origin - to.origin; // relative origin
+    e.v_angle = e.angles - to.angles; // relative angles
+}
+
+#if 0
+// TODO: unused, likely for a reason, possibly needs extensions (allow setting the new movetype as a parameter?)
+void unfollow_sameorigin(entity e)
+{
+    set_movetype(e, MOVETYPE_NONE);
+}
+#endif
+
+.string aiment_classname;
+.float aiment_deadflag;
+void SetMovetypeFollow(entity ent, entity e)
+{
+       // FIXME this may not be warpzone aware
+       set_movetype(ent, MOVETYPE_FOLLOW); // make the hole follow
+       ent.solid = SOLID_NOT; // MOVETYPE_FOLLOW is always non-solid - this means this cannot be teleported by warpzones any more! Instead, we must notice when our owner gets teleported.
+       ent.aiment = e; // make the hole follow bmodel
+       ent.punchangle = e.angles; // the original angles of bmodel
+       ent.view_ofs = ent.origin - e.origin; // relative origin
+       ent.v_angle = ent.angles - e.angles; // relative angles
+       ent.aiment_classname = strzone(e.classname);
+       ent.aiment_deadflag = e.deadflag;
+}
+void UnsetMovetypeFollow(entity ent)
+{
+       set_movetype(ent, MOVETYPE_FLY);
+       PROJECTILE_MAKETRIGGER(ent);
+       ent.aiment = NULL;
+}
+float LostMovetypeFollow(entity ent)
+{
+/*
+       if(ent.move_movetype != MOVETYPE_FOLLOW)
+               if(ent.aiment)
+                       error("???");
+*/
+       if(ent.aiment)
+       {
+               if(ent.aiment.classname != ent.aiment_classname)
+                       return 1;
+               if(ent.aiment.deadflag != ent.aiment_deadflag)
+                       return 1;
+       }
+       return 0;
+}
+#endif
+
+#ifdef GAMEQC
+// decolorizes and team colors the player name when needed
+string playername(string thename, int teamid, bool team_colorize)
+{
+       TC(int, teamid);
+       bool do_colorize = (teamplay && team_colorize);
+#ifdef SVQC
+       if(do_colorize && !intermission_running)
+#else
+       if(do_colorize)
+#endif
+    {
+        string t = Team_ColorCode(teamid);
+        return strcat(t, strdecolorize(thename));
+    }
+    else
+        return thename;
+}
+#endif
index 756e02cf51ffeb8aa85970233bfe7007d60818b9..82a0f01c66d252f11646d17a1c881e386393b3b9 100644 (file)
@@ -227,3 +227,21 @@ int Mod_Q1BSP_NativeContentsFromSuperContents(int supercontents);
 
 // Returns the correct difference between two always increasing numbers
 #define COMPARE_INCREASING(to,from) (to < from ? from + to + 2 : to - from)
+
+#ifdef SVQC
+void attach_sameorigin(entity e, entity to, string tag);
+
+void detach_sameorigin(entity e);
+
+void follow_sameorigin(entity e, entity to);
+
+void SetMovetypeFollow(entity ent, entity e);
+
+void UnsetMovetypeFollow(entity ent);
+
+float LostMovetypeFollow(entity ent);
+#endif
+
+#ifdef GAMEQC
+string playername(string thename, int teamid, bool team_colorize);
+#endif
index d49094f7b48c68019752dd871f46ee360bd7478e..7273ed70da1b287f67d0c3be2a10f66584348f7f 100644 (file)
@@ -21,6 +21,7 @@
 ## entities
 
     entity e = new(foo);
+    IL_PUSH(g_components, e);
     e.com_$component = true;
     e.com_$component_$property = 42;
 
index 1036ab0c8d2e1177981f957d0044e37913da3f5e..1bb1aeb6a404d0b8ed4ec2e3200c8c92446204e6 100644 (file)
@@ -12,6 +12,7 @@
        #include <common/weapons/_all.qh>
        #include <common/stats.qh>
        #include <server/utils.qh>
+       #include <server/weapons/common.qh>
 #endif
 
 #ifdef SVQC
index 2ed7fa1ed62528b69800e6e1b8ab7d267d5c51c0..3362ab53962f98c5626c7d8f37301cdca5e21e98 100644 (file)
@@ -60,7 +60,7 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
 
        string namestr = "";
        if (source)
-               namestr = playername(source, autocvar_g_chat_teamcolors);
+               namestr = playername(source.netname, source.team, (autocvar_g_chat_teamcolors && IS_PLAYER(source)));
 
        string colorprefix = (strdecolorize(namestr) == namestr) ? "^3" : "^7";
 
@@ -93,7 +93,7 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
                        privatemsgprefixlen = strlen(msgstr);
                        msgstr = strcat(msgstr, msgin);
                        cmsgstr = strcat(colorstr, colorprefix, namestr, "^3 tells you:\n^7", msgin);
-                       privatemsgprefix = strcat("\{1}\{13}* ^3You tell ", playername(privatesay, autocvar_g_chat_teamcolors), ": ^7");
+                       privatemsgprefix = strcat("\{1}\{13}* ^3You tell ", playername(privatesay.netname, privatesay.team, (autocvar_g_chat_teamcolors && IS_PLAYER(privatesay))), ": ^7");
                }
                else if(teamsay)
                {
@@ -229,7 +229,7 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
        }
 
        if(flood)
-               LOG_INFO("NOTE: ", playername(source, true), "^7 is flooding.");
+               LOG_INFO("NOTE: ", playername(source.netname, source.team, IS_PLAYER(source)), "^7 is flooding.");
 
        // build sourcemsgstr by cutting off a prefix and replacing it by the other one
        if(privatesay)
@@ -323,7 +323,7 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
                        if (source) {
                                sprint(source, sourcemsgstr);
                                dedicated_print(msgstr); // send to server console too
-                               MX_Say(strcat(playername(source, true), "^7: ", msgin));
+                               MX_Say(strcat(playername(source.netname, source.team, IS_PLAYER(source)), "^7: ", msgin));
                        }
                        FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != source && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
                                sprint(it, msgstr);
index eb0b95e078ec6d2a1ca47cc411291fc6615cc3fb..3ce3ae0b4a11f5de3e939347413b1d0e3e6336b7 100644 (file)
@@ -84,13 +84,13 @@ float CheatsAllowed(entity this, float i, int argc, float fr) // the cheat gets
 
        // if we get here, player is not allowed to cheat. Log it.
        if(i)
-               bprintf("Player %s^7 tried to use cheat 'impulse %d'\n", playername(this, false), i);
+               bprintf("Player %s^7 tried to use cheat 'impulse %d'\n", playername(this.netname, this.team, false), i);
        else if(argc)
-               bprintf("Player %s^7 tried to use cheat '%s'\n", playername(this, false), argv(0));
+               bprintf("Player %s^7 tried to use cheat '%s'\n", playername(this.netname, this.team, false), argv(0));
        else if(fr)
-               bprintf("Player %s^7 tried to use cheat frame %d\n", playername(this, false), fr);
+               bprintf("Player %s^7 tried to use cheat frame %d\n", playername(this.netname, this.team, false), fr);
        else
-               bprintf("Player %s^7 tried to use an unknown cheat\n", playername(this, false));
+               bprintf("Player %s^7 tried to use an unknown cheat\n", playername(this.netname, this.team, false));
 
        return 0;
 }
index 04fba80931100cd0c171d10b10bf2800167c39b9..f2c2614105f907bf6169c2d343ea44b1a45e9eba 100644 (file)
@@ -1123,7 +1123,7 @@ void ClientConnect(entity this)
                CS(this).allowed_timeouts = autocvar_sv_timeout_number;
 
        if (autocvar_sv_eventlog)
-               GameLogEcho(strcat(":join:", ftos(this.playerid), ":", ftos(etof(this)), ":", ((IS_REAL_CLIENT(this)) ? GameLog_ProcessIP(this.netaddress) : "bot"), ":", playername(this, false)));
+               GameLogEcho(strcat(":join:", ftos(this.playerid), ":", ftos(etof(this)), ":", ((IS_REAL_CLIENT(this)) ? GameLog_ProcessIP(this.netaddress) : "bot"), ":", playername(this.netname, this.team, false)));
 
        CS(this).just_joined = true;  // stop spamming the eventlog with additional lines when the client connects
 
@@ -2476,7 +2476,7 @@ void PlayerPreThink (entity this)
                        // stuffcmd(this, strcat("name ", this.netname, "\n")); // maybe?
                }
                if (!assume_unchanged && autocvar_sv_eventlog)
-                       GameLogEcho(strcat(":name:", ftos(this.playerid), ":", playername(this, false)));
+                       GameLogEcho(strcat(":name:", ftos(this.playerid), ":", playername(this.netname, this.team, false)));
                strcpy(CS(this).netname_previous, this.netname);
        }
 
index c2c7c099287c0dfd3cdb60dfea664ae796935adb..8ffc52b24aa5dc0a7855f46894de47c6d5bc2001 100644 (file)
@@ -7,6 +7,7 @@
 #include <common/command/_mod.qh>
 
 #include "common.qh"
+#include "getreplies.qh"
 #include "vote.qh"
 
 #include "../bot/api.qh"
@@ -395,13 +396,13 @@ void ClientCommand_ready(entity caller, int request)  // todo: anti-spam for tog
                                                {
                                                        caller.ready = false;
                                                        if(IS_PLAYER(caller) || caller.caplayer == 1)
-                                                               bprint(playername(caller, false), "^2 is ^1NOT^2 ready\n");
+                                                               bprint(playername(caller.netname, caller.team, false), "^2 is ^1NOT^2 ready\n");
                                                }
                                                else
                                                {
                                                        caller.ready = true;
                                                        if(IS_PLAYER(caller) || caller.caplayer == 1)
-                                                               bprint(playername(caller, false), "^2 is ready\n");
+                                                               bprint(playername(caller.netname, caller.team, false), "^2 is ready\n");
                                                }
 
                                                // cannot reset the game while a timeout is active!
index c5622ead3bc8ed6bd22cc1f52f1a62ee4d5591a4..d679272821c589e1c4ca81dba9c1ed101afaa5fd 100644 (file)
@@ -32,7 +32,7 @@ string GetCommandPrefix(entity caller)
 // if client return player nickname, or if server return admin nickname
 string GetCallerName(entity caller)
 {
-       if (caller) return playername(caller, false);
+       if (caller) return playername(caller.netname, caller.team, false);
        else return ((autocvar_sv_adminnick != "") ? autocvar_sv_adminnick : "SERVER ADMIN"); // autocvar_hostname
 }
 
index 1cf124ad3c054d5c77999367d6573fea38f222dd..95ee35a36f52348480366a6a7e257c113f7f023a 100644 (file)
@@ -1,6 +1,7 @@
 #include "getreplies.qh"
 
 #include <common/weapons/_all.qh>
+#include <common/wepent.qh>
 #include <common/stats.qh>
 #include <server/intermission.qh>
 #include <server/world.qh>
@@ -300,3 +301,137 @@ string getmonsterlist()
 
        return sprintf("^7Monsters available: %s\n", monsterlist);
 }
+
+/*
+=============
+GetCvars
+=============
+Called with:
+  0:  sends the request
+  >0: receives a cvar from name=argv(f) value=argv(f+1)
+*/
+void GetCvars_handleString(entity this, entity store, string thisname, float f, .string field, string name)
+{
+       if (f < 0)
+       {
+               strfree(store.(field));
+       }
+       else if (f > 0)
+       {
+               if (thisname == name)
+               {
+                       strcpy(store.(field), argv(f + 1));
+               }
+       }
+       else
+               stuffcmd(this, strcat("cl_cmd sendcvar ", name, "\n"));
+}
+void GetCvars_handleString_Fixup(entity this, entity store, string thisname, float f, .string field, string name, string(entity, string) func)
+{
+       GetCvars_handleString(this, store, thisname, f, field, name);
+       if (f >= 0) // also initialize to the fitting value for "" when sending cvars out
+               if (thisname == name)
+               {
+                       string s = func(this, strcat1(store.(field)));
+                       if (s != store.(field))
+                       {
+                               strcpy(store.(field), s);
+                       }
+               }
+}
+void GetCvars_handleFloat(entity this, entity store, string thisname, float f, .float field, string name)
+{
+       if (f < 0)
+       {
+       }
+       else if (f > 0)
+       {
+               if (thisname == name)
+                       store.(field) = stof(argv(f + 1));
+       }
+       else
+               stuffcmd(this, strcat("cl_cmd sendcvar ", name, "\n"));
+}
+void GetCvars_handleFloatOnce(entity this, entity store, string thisname, float f, .float field, string name)
+{
+       if (f < 0)
+       {
+       }
+       else if (f > 0)
+       {
+               if (thisname == name)
+               {
+                       if (!store.(field))
+                       {
+                               store.(field) = stof(argv(f + 1));
+                               if (!store.(field))
+                                       store.(field) = -1;
+                       }
+               }
+       }
+       else
+       {
+               if (!store.(field))
+                       stuffcmd(this, strcat("cl_cmd sendcvar ", name, "\n"));
+       }
+}
+string W_FixWeaponOrder_ForceComplete_AndBuildImpulseList(entity this, string wo)
+{
+       string o = W_FixWeaponOrder_ForceComplete(wo);
+       strcpy(CS(this).weaponorder_byimpulse, W_FixWeaponOrder_BuildImpulseList(o));
+       return o;
+}
+
+/**
+ * @param f -1: cleanup, 0: request, 1: receive
+ */
+void GetCvars(entity this, entity store, int f)
+{
+       string s = string_null;
+
+       if (f == 0)
+               LOG_INFO("Warning: requesting cvar values is deprecated. Client should send them automatically using REPLICATE.\n");
+
+       if (f > 0)
+               s = strcat1(argv(f));
+
+       get_cvars_f = f;
+       get_cvars_s = s;
+       MUTATOR_CALLHOOK(GetCvars);
+
+       Notification_GetCvars(this);
+
+       ReplicateVars(this, store, s, f);
+
+       GetCvars_handleString_Fixup(this, store, s, f, cvar_cl_weaponpriority, "cl_weaponpriority", W_FixWeaponOrder_ForceComplete_AndBuildImpulseList);
+       GetCvars_handleString_Fixup(this, store, s, f, cvar_cl_weaponpriorities[0], "cl_weaponpriority0", W_FixWeaponOrder_AllowIncomplete);
+       GetCvars_handleString_Fixup(this, store, s, f, cvar_cl_weaponpriorities[1], "cl_weaponpriority1", W_FixWeaponOrder_AllowIncomplete);
+       GetCvars_handleString_Fixup(this, store, s, f, cvar_cl_weaponpriorities[2], "cl_weaponpriority2", W_FixWeaponOrder_AllowIncomplete);
+       GetCvars_handleString_Fixup(this, store, s, f, cvar_cl_weaponpriorities[3], "cl_weaponpriority3", W_FixWeaponOrder_AllowIncomplete);
+       GetCvars_handleString_Fixup(this, store, s, f, cvar_cl_weaponpriorities[4], "cl_weaponpriority4", W_FixWeaponOrder_AllowIncomplete);
+       GetCvars_handleString_Fixup(this, store, s, f, cvar_cl_weaponpriorities[5], "cl_weaponpriority5", W_FixWeaponOrder_AllowIncomplete);
+       GetCvars_handleString_Fixup(this, store, s, f, cvar_cl_weaponpriorities[6], "cl_weaponpriority6", W_FixWeaponOrder_AllowIncomplete);
+       GetCvars_handleString_Fixup(this, store, s, f, cvar_cl_weaponpriorities[7], "cl_weaponpriority7", W_FixWeaponOrder_AllowIncomplete);
+       GetCvars_handleString_Fixup(this, store, s, f, cvar_cl_weaponpriorities[8], "cl_weaponpriority8", W_FixWeaponOrder_AllowIncomplete);
+       GetCvars_handleString_Fixup(this, store, s, f, cvar_cl_weaponpriorities[9], "cl_weaponpriority9", W_FixWeaponOrder_AllowIncomplete);
+
+       GetCvars_handleFloat(this, store, s, f, cvar_cl_allow_uidtracking, "cl_allow_uidtracking");
+
+       // fixup of switchweapon (needed for LMS or when spectating is disabled, as PutClientInServer comes too early)
+       if (f > 0)
+       {
+               if (s == "cl_weaponpriority")
+               {
+                       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+                       {
+                               .entity weaponentity = weaponentities[slot];
+                               if (this.(weaponentity) && (this.(weaponentity).m_weapon != WEP_Null || slot == 0))
+                                       this.(weaponentity).m_switchweapon = w_getbestweapon(this, weaponentity);
+                       }
+               }
+               if (s == "cl_allow_uidtracking")
+                       PlayerStats_GameReport_AddPlayer(this);
+               //if (s == "cl_gunalign")
+                       //W_ResetGunAlign(this, store.cvar_cl_gunalign);
+       }
+}
index 3ababeec576028bb07b69722714e9ee16a2b2746..f45bbe0166f5158bee09a82a28778318feb7888c 100644 (file)
@@ -20,3 +20,9 @@ string getladder();
 string getmaplist();
 string getlsmaps();
 string getmonsterlist();
+
+void GetCvars_handleFloat(entity this, entity store, string thisname, float f, .float field, string name);
+
+void GetCvars_handleString(entity this, entity store, string thisname, float f, .string field, string name);
+
+void GetCvars(entity this, entity store, int f);
index 281297b049e8a90ed2c1ab23f364dc2ba286c8d0..86755c7e3a8404068ea6df254009ca8684e2edd9 100644 (file)
@@ -134,8 +134,8 @@ void GameCommand_adminmsg(int request, int argc)
                                                sprint(client, strcat("\{1}\{13}^3", GetCallerName(NULL), "^7: ", admin_message, "\n"));
                                        }
 
-                                       successful = strcat(successful, (successful ? ", " : ""), playername(client, false));
-                                       LOG_TRACE("Message sent to ", playername(client, false));
+                                       successful = strcat(successful, (successful ? ", " : ""), playername(client.netname, client.team, false));
+                                       LOG_TRACE("Message sent to ", playername(client.netname, client.team, false));
                                        continue;
                                }
 
@@ -532,7 +532,7 @@ void GameCommand_defer_clear(int request, int argc)
                                if (accepted > 0)
                                {
                                        stuffcmd(client, "defer clear\n");
-                                       LOG_INFO("defer clear stuffed to ", playername(client, false));
+                                       LOG_INFO("defer clear stuffed to ", playername(client.netname, client.team, false));
                                }
                                else { LOG_INFO("defer_clear: ", GetClientErrorString(accepted, argv(1)), "."); }
 
@@ -1011,11 +1011,11 @@ void GameCommand_moveplayer(int request, int argc)
                                                        if (client.caplayer) client.caplayer = 0;
                                                        PutObserverInServer(client);
 
-                                                       successful = strcat(successful, (successful ? ", " : ""), playername(client, false));
+                                                       successful = strcat(successful, (successful ? ", " : ""), playername(client.netname, client.team, false));
                                                }
                                                else
                                                {
-                                                       LOG_INFO("Player ", ftos(GetFilteredNumber(t)), " (", playername(client, false), ") is already spectating.");
+                                                       LOG_INFO("Player ", ftos(GetFilteredNumber(t)), " (", playername(client.netname, client.team, false), ") is already spectating.");
                                                }
                                                continue;
                                        }
@@ -1035,7 +1035,7 @@ void GameCommand_moveplayer(int request, int argc)
                                                                if (team_num == client.team)  // already on the destination team
                                                                {
                                                                        // keep the forcing undone
-                                                                       LOG_INFO("Player ", ftos(GetFilteredNumber(t)), " (", playername(client, false), ") is already on the ", Team_ColoredFullName(client.team), (targets ? "^7, skipping to next player.\n" : "^7."));
+                                                                       LOG_INFO("Player ", ftos(GetFilteredNumber(t)), " (", playername(client.netname, client.team, false), ") is already on the ", Team_ColoredFullName(client.team), (targets ? "^7, skipping to next player.\n" : "^7."));
                                                                        continue;
                                                                }
                                                                else if (team_num == 0)  // auto team
@@ -1069,12 +1069,12 @@ void GameCommand_moveplayer(int request, int argc)
                                                                Player_SetForcedTeamIndex(client, TEAM_FORCE_DEFAULT);
                                                                if (MoveToTeam(client, team_id, 6))
                                                                {
-                                                                       successful = strcat(successful, (successful ? ", " : ""), playername(client, false));
-                                                                       LOG_INFO("Player ", ftos(GetFilteredNumber(t)), " (", playername(client, false), ") has been moved to the ", Team_ColoredFullName(team_id), "^7.");
+                                                                       successful = strcat(successful, (successful ? ", " : ""), playername(client.netname, client.team, false));
+                                                                       LOG_INFO("Player ", ftos(GetFilteredNumber(t)), " (", playername(client.netname, client.team, false), ") has been moved to the ", Team_ColoredFullName(team_id), "^7.");
                                                                }
                                                                else
                                                                {
-                                                                       LOG_INFO("Unable to move player ", ftos(GetFilteredNumber(t)), " (", playername(client, false), ")");
+                                                                       LOG_INFO("Unable to move player ", ftos(GetFilteredNumber(t)), " (", playername(client.netname, client.team, false), ")");
                                                                }
                                                                continue;
                                                        }
index 3d0cb29749baf3501a92360cd4a2014c23a832e4..0f85507fd48f09b4754be4044bb4eba5ae49b11a 100644 (file)
@@ -120,7 +120,7 @@ void Nagger_ReadyCounted()
 // If the vote_caller is still here, return their name, otherwise vote_caller_name
 string OriginalCallerName()
 {
-       if (IS_REAL_CLIENT(vote_caller)) return playername(vote_caller, false);
+       if (IS_REAL_CLIENT(vote_caller)) return playername(vote_caller.netname, vote_caller.team, false);
        return vote_caller_name;
 }
 
index 861b21eed2b566df931eef6a382f4b848139ec7c..41c7eca4ea7f384410f37ed08976884807b4c43f 100644 (file)
@@ -11,6 +11,7 @@
 #include <server/mutators/_mod.qh>
 
 #include <server/teamplay.qh>
+#include <server/world.qh>
 
 #include <server/weapons/common.qh>
 #include <server/weapons/selection.qh>
index 9a0c4ae6531df63260b0581f1d630f841e5fd89c..78ffd9a8bb13dd1129e147f3858c2c830a213ee2 100644 (file)
@@ -90,153 +90,6 @@ void WarpZone_crosshair_trace(entity pl)
        WarpZone_traceline_antilag(pl, CS(pl).cursor_trace_start, CS(pl).cursor_trace_start + normalize(CS(pl).cursor_trace_endpos - CS(pl).cursor_trace_start) * max_shot_distance, MOVE_NORMAL, pl, ANTILAG_LATENCY(pl));
 }
 
-/*
-=============
-GetCvars
-=============
-Called with:
-  0:  sends the request
-  >0: receives a cvar from name=argv(f) value=argv(f+1)
-*/
-void GetCvars_handleString(entity this, entity store, string thisname, float f, .string field, string name)
-{
-       if (f < 0)
-       {
-               strfree(store.(field));
-       }
-       else if (f > 0)
-       {
-               if (thisname == name)
-               {
-                       strcpy(store.(field), argv(f + 1));
-               }
-       }
-       else
-               stuffcmd(this, strcat("cl_cmd sendcvar ", name, "\n"));
-}
-void GetCvars_handleString_Fixup(entity this, entity store, string thisname, float f, .string field, string name, string(entity, string) func)
-{
-       GetCvars_handleString(this, store, thisname, f, field, name);
-       if (f >= 0) // also initialize to the fitting value for "" when sending cvars out
-               if (thisname == name)
-               {
-                       string s = func(this, strcat1(store.(field)));
-                       if (s != store.(field))
-                       {
-                               strcpy(store.(field), s);
-                       }
-               }
-}
-void GetCvars_handleFloat(entity this, entity store, string thisname, float f, .float field, string name)
-{
-       if (f < 0)
-       {
-       }
-       else if (f > 0)
-       {
-               if (thisname == name)
-                       store.(field) = stof(argv(f + 1));
-       }
-       else
-               stuffcmd(this, strcat("cl_cmd sendcvar ", name, "\n"));
-}
-void GetCvars_handleFloatOnce(entity this, entity store, string thisname, float f, .float field, string name)
-{
-       if (f < 0)
-       {
-       }
-       else if (f > 0)
-       {
-               if (thisname == name)
-               {
-                       if (!store.(field))
-                       {
-                               store.(field) = stof(argv(f + 1));
-                               if (!store.(field))
-                                       store.(field) = -1;
-                       }
-               }
-       }
-       else
-       {
-               if (!store.(field))
-                       stuffcmd(this, strcat("cl_cmd sendcvar ", name, "\n"));
-       }
-}
-string W_FixWeaponOrder_ForceComplete_AndBuildImpulseList(entity this, string wo)
-{
-       string o = W_FixWeaponOrder_ForceComplete(wo);
-       strcpy(CS(this).weaponorder_byimpulse, W_FixWeaponOrder_BuildImpulseList(o));
-       return o;
-}
-
-/**
- * @param f -1: cleanup, 0: request, 1: receive
- */
-void GetCvars(entity this, entity store, int f)
-{
-       string s = string_null;
-
-       if (f == 0)
-               LOG_INFO("Warning: requesting cvar values is deprecated. Client should send them automatically using REPLICATE.\n");
-
-       if (f > 0)
-               s = strcat1(argv(f));
-
-       get_cvars_f = f;
-       get_cvars_s = s;
-       MUTATOR_CALLHOOK(GetCvars);
-
-       Notification_GetCvars(this);
-
-       ReplicateVars(this, store, s, f);
-
-       GetCvars_handleString_Fixup(this, store, s, f, cvar_cl_weaponpriority, "cl_weaponpriority", W_FixWeaponOrder_ForceComplete_AndBuildImpulseList);
-       GetCvars_handleString_Fixup(this, store, s, f, cvar_cl_weaponpriorities[0], "cl_weaponpriority0", W_FixWeaponOrder_AllowIncomplete);
-       GetCvars_handleString_Fixup(this, store, s, f, cvar_cl_weaponpriorities[1], "cl_weaponpriority1", W_FixWeaponOrder_AllowIncomplete);
-       GetCvars_handleString_Fixup(this, store, s, f, cvar_cl_weaponpriorities[2], "cl_weaponpriority2", W_FixWeaponOrder_AllowIncomplete);
-       GetCvars_handleString_Fixup(this, store, s, f, cvar_cl_weaponpriorities[3], "cl_weaponpriority3", W_FixWeaponOrder_AllowIncomplete);
-       GetCvars_handleString_Fixup(this, store, s, f, cvar_cl_weaponpriorities[4], "cl_weaponpriority4", W_FixWeaponOrder_AllowIncomplete);
-       GetCvars_handleString_Fixup(this, store, s, f, cvar_cl_weaponpriorities[5], "cl_weaponpriority5", W_FixWeaponOrder_AllowIncomplete);
-       GetCvars_handleString_Fixup(this, store, s, f, cvar_cl_weaponpriorities[6], "cl_weaponpriority6", W_FixWeaponOrder_AllowIncomplete);
-       GetCvars_handleString_Fixup(this, store, s, f, cvar_cl_weaponpriorities[7], "cl_weaponpriority7", W_FixWeaponOrder_AllowIncomplete);
-       GetCvars_handleString_Fixup(this, store, s, f, cvar_cl_weaponpriorities[8], "cl_weaponpriority8", W_FixWeaponOrder_AllowIncomplete);
-       GetCvars_handleString_Fixup(this, store, s, f, cvar_cl_weaponpriorities[9], "cl_weaponpriority9", W_FixWeaponOrder_AllowIncomplete);
-
-       GetCvars_handleFloat(this, store, s, f, cvar_cl_allow_uidtracking, "cl_allow_uidtracking");
-
-       // fixup of switchweapon (needed for LMS or when spectating is disabled, as PutClientInServer comes too early)
-       if (f > 0)
-       {
-               if (s == "cl_weaponpriority")
-               {
-                       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
-                       {
-                               .entity weaponentity = weaponentities[slot];
-                               if (this.(weaponentity) && (this.(weaponentity).m_weapon != WEP_Null || slot == 0))
-                                       this.(weaponentity).m_switchweapon = w_getbestweapon(this, weaponentity);
-                       }
-               }
-               if (s == "cl_allow_uidtracking")
-                       PlayerStats_GameReport_AddPlayer(this);
-               //if (s == "cl_gunalign")
-                       //W_ResetGunAlign(this, store.cvar_cl_gunalign);
-       }
-}
-
-// decolorizes and team colors the player name when needed
-string playername(entity p, bool team_colorize)
-{
-    string t;
-    if (team_colorize && teamplay && !intermission_running && IS_PLAYER(p))
-    {
-        t = Team_ColorCode(p.team);
-        return strcat(t, strdecolorize(p.netname));
-    }
-    else
-        return p.netname;
-}
-
 float want_weapon(entity weaponinfo, float allguns)
 {
        int d = 0;
@@ -580,81 +433,6 @@ void readplayerstartcvars()
        warmup_start_ammo_fuel = max(0, warmup_start_ammo_fuel);
 }
 
-void precache_playermodel(string m)
-{
-       int globhandle, i, n;
-       string f;
-
-       // remove :<skinnumber> suffix
-       int j = strstrofs(m, ":", 0);
-       if(j >= 0)
-               m = substring(m, 0, j);
-
-       if(substring(m, -9, 5) == "_lod1")
-               return;
-       if(substring(m, -9, 5) == "_lod2")
-               return;
-       precache_model(m);
-       f = strcat(substring(m, 0, -5), "_lod1", substring(m, -4, -1));
-       if(fexists(f))
-               precache_model(f);
-       f = strcat(substring(m, 0, -5), "_lod2", substring(m, -4, -1));
-       if(fexists(f))
-               precache_model(f);
-
-       globhandle = search_begin(strcat(m, "_*.sounds"), true, false);
-       if (globhandle < 0)
-               return;
-       n = search_getsize(globhandle);
-       for (i = 0; i < n; ++i)
-       {
-               //print(search_getfilename(globhandle, i), "\n");
-               f = search_getfilename(globhandle, i);
-               PrecachePlayerSounds(f);
-       }
-       search_end(globhandle);
-}
-void precache_all_playermodels(string pattern)
-{
-       int globhandle = search_begin(pattern, true, false);
-       if (globhandle < 0) return;
-       int n = search_getsize(globhandle);
-       for (int i = 0; i < n; ++i)
-       {
-               string s = search_getfilename(globhandle, i);
-               precache_playermodel(s);
-       }
-       search_end(globhandle);
-}
-
-void precache_playermodels(string s)
-{
-       FOREACH_WORD(s, true, { precache_playermodel(it); });
-}
-
-PRECACHE(PlayerModels)
-{
-    // Precache all player models if desired
-    if (autocvar_sv_precacheplayermodels)
-    {
-        PrecachePlayerSounds("sound/player/default.sounds");
-        precache_all_playermodels("models/player/*.zym");
-        precache_all_playermodels("models/player/*.dpm");
-        precache_all_playermodels("models/player/*.md3");
-        precache_all_playermodels("models/player/*.psk");
-        precache_all_playermodels("models/player/*.iqm");
-    }
-
-    if (autocvar_sv_defaultcharacter)
-    {
-               precache_playermodels(autocvar_sv_defaultplayermodel_red);
-               precache_playermodels(autocvar_sv_defaultplayermodel_blue);
-               precache_playermodels(autocvar_sv_defaultplayermodel_yellow);
-               precache_playermodels(autocvar_sv_defaultplayermodel_pink);
-               precache_playermodels(autocvar_sv_defaultplayermodel);
-    }
-}
-
 void InitializeEntity(entity e, void(entity this) func, int order)
 {
     entity prev, cur;
@@ -726,27 +504,6 @@ void InitializeEntitiesRun()
     delete_fn = remove_unsafely;
 }
 
-void adaptor_think2use_hittype_splash(entity this) // for timed projectile detonation
-{
-       if(!(IS_ONGROUND(this))) // if onground, we ARE touching something, but HITTYPE_SPLASH is to be networked if the damage causing projectile is not touching ANYTHING
-               this.projectiledeathtype |= HITTYPE_SPLASH;
-       adaptor_think2use(this);
-}
-
-// deferred dropping
-void DropToFloor_Handler(entity this)
-{
-    WITHSELF(this, builtin_droptofloor());
-    this.dropped_origin = this.origin;
-}
-
-void droptofloor(entity this)
-{
-    InitializeEntity(this, DropToFloor_Handler, INITPRIO_DROPTOFLOOR);
-}
-
-
-
 float trace_hits_box_a0, trace_hits_box_a1;
 
 float trace_hits_box_1d(float end, float thmi, float thma)
@@ -796,59 +553,6 @@ float tracebox_hits_box(vector start, vector mi, vector ma, vector end, vector t
     return trace_hits_box(start, end, thmi - ma, thma - mi);
 }
 
-bool SUB_NoImpactCheck(entity this, entity toucher)
-{
-       // zero hitcontents = this is not the real impact, but either the
-       // mirror-impact of something hitting the projectile instead of the
-       // projectile hitting the something, or a touchareagrid one. Neither of
-       // these stop the projectile from moving, so...
-       if(trace_dphitcontents == 0)
-       {
-               LOG_TRACEF("A hit from a projectile happened with no hit contents! DEBUG THIS, this should never happen for projectiles! Projectile will self-destruct. (edict: %i, classname: %s, origin: %v)", this, this.classname, this.origin);
-               checkclient(this); // TODO: .health is checked in the engine with this, possibly replace with a QC function?
-       }
-    if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
-        return true;
-    if (toucher == NULL && this.size != '0 0 0')
-    {
-        vector tic;
-        tic = this.velocity * sys_frametime;
-        tic = tic + normalize(tic) * vlen(this.maxs - this.mins);
-        traceline(this.origin - tic, this.origin + tic, MOVE_NORMAL, this);
-        if (trace_fraction >= 1)
-        {
-            LOG_TRACE("Odd... did not hit...?");
-        }
-        else if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
-        {
-            LOG_TRACE("Detected and prevented the sky-grapple bug.");
-            return true;
-        }
-    }
-
-    return false;
-}
-
-bool WarpZone_Projectile_Touch_ImpactFilter_Callback(entity this, entity toucher)
-{
-       // owner check
-       if(toucher && toucher == this.owner)
-               return true;
-       if(SUB_NoImpactCheck(this, toucher))
-       {
-               if(this.classname == "nade")
-                       return false; // no checks here
-               else if(this.classname == "grapplinghook")
-                       RemoveHook(this);
-               else
-                       delete(this);
-               return true;
-       }
-       if(trace_ent && trace_ent.solid > SOLID_TRIGGER)
-               UpdateCSQCProjectile(this);
-       return false;
-}
-
 /** engine callback */
 void URI_Get_Callback(float id, float status, string data)
 {
@@ -1027,122 +731,3 @@ float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, f
 {
        return MoveToRandomLocationWithinBounds(e, world.mins, world.maxs, goodcontents, badcontents, badsurfaceflags, attempts, maxaboveground, minviewdistance);
 }
-
-void write_recordmarker(entity pl, float tstart, float dt)
-{
-    GameLogEcho(strcat(":recordset:", ftos(pl.playerid), ":", ftos(dt)));
-
-    // also write a marker into demo files for demotc-race-record-extractor to find
-    stuffcmd(pl,
-             strcat(
-                 strcat("//", strconv(2, 0, 0, GetGametype()), " RECORD SET ", TIME_ENCODED_TOSTRING(TIME_ENCODE(dt))),
-                 " ", ftos(tstart), " ", ftos(dt), "\n"));
-}
-
-void attach_sameorigin(entity e, entity to, string tag)
-{
-    vector org, t_forward, t_left, t_up, e_forward, e_up;
-    float tagscale;
-
-    org = e.origin - gettaginfo(to, gettagindex(to, tag));
-    tagscale = (vlen(v_forward) ** -2); // undo a scale on the tag
-    t_forward = v_forward * tagscale;
-    t_left = v_right * -tagscale;
-    t_up = v_up * tagscale;
-
-    e.origin_x = org * t_forward;
-    e.origin_y = org * t_left;
-    e.origin_z = org * t_up;
-
-    // current forward and up directions
-    if (substring(e.model, 0, 1) == "*") // bmodels have their own rules
-               e.angles = AnglesTransform_FromVAngles(e.angles);
-       else
-               e.angles = AnglesTransform_FromAngles(e.angles);
-    fixedmakevectors(e.angles);
-
-    // untransform forward, up!
-    e_forward.x = v_forward * t_forward;
-    e_forward.y = v_forward * t_left;
-    e_forward.z = v_forward * t_up;
-    e_up.x = v_up * t_forward;
-    e_up.y = v_up * t_left;
-    e_up.z = v_up * t_up;
-
-    e.angles = fixedvectoangles2(e_forward, e_up);
-    if (substring(e.model, 0, 1) == "*") // bmodels have their own rules
-               e.angles = AnglesTransform_ToVAngles(e.angles);
-       else
-               e.angles = AnglesTransform_ToAngles(e.angles);
-
-    setattachment(e, to, tag);
-    setorigin(e, e.origin);
-}
-
-void detach_sameorigin(entity e)
-{
-    vector org;
-    org = gettaginfo(e, 0);
-    e.angles = fixedvectoangles2(v_forward, v_up);
-    if (substring(e.model, 0, 1) == "*") // bmodels have their own rules
-               e.angles = AnglesTransform_ToVAngles(e.angles);
-       else
-               e.angles = AnglesTransform_ToAngles(e.angles);
-    setorigin(e, org);
-    setattachment(e, NULL, "");
-    setorigin(e, e.origin);
-}
-
-void follow_sameorigin(entity e, entity to)
-{
-    set_movetype(e, MOVETYPE_FOLLOW); // make the hole follow
-    e.aiment = to; // make the hole follow bmodel
-    e.punchangle = to.angles; // the original angles of bmodel
-    e.view_ofs = e.origin - to.origin; // relative origin
-    e.v_angle = e.angles - to.angles; // relative angles
-}
-
-#if 0
-// TODO: unused, likely for a reason, possibly needs extensions (allow setting the new movetype as a parameter?)
-void unfollow_sameorigin(entity e)
-{
-    set_movetype(e, MOVETYPE_NONE);
-}
-#endif
-
-.string aiment_classname;
-.float aiment_deadflag;
-void SetMovetypeFollow(entity ent, entity e)
-{
-       // FIXME this may not be warpzone aware
-       set_movetype(ent, MOVETYPE_FOLLOW); // make the hole follow
-       ent.solid = SOLID_NOT; // MOVETYPE_FOLLOW is always non-solid - this means this cannot be teleported by warpzones any more! Instead, we must notice when our owner gets teleported.
-       ent.aiment = e; // make the hole follow bmodel
-       ent.punchangle = e.angles; // the original angles of bmodel
-       ent.view_ofs = ent.origin - e.origin; // relative origin
-       ent.v_angle = ent.angles - e.angles; // relative angles
-       ent.aiment_classname = strzone(e.classname);
-       ent.aiment_deadflag = e.deadflag;
-}
-void UnsetMovetypeFollow(entity ent)
-{
-       set_movetype(ent, MOVETYPE_FLY);
-       PROJECTILE_MAKETRIGGER(ent);
-       ent.aiment = NULL;
-}
-float LostMovetypeFollow(entity ent)
-{
-/*
-       if(ent.move_movetype != MOVETYPE_FOLLOW)
-               if(ent.aiment)
-                       error("???");
-*/
-       if(ent.aiment)
-       {
-               if(ent.aiment.classname != ent.aiment_classname)
-                       return 1;
-               if(ent.aiment.deadflag != ent.aiment_deadflag)
-                       return 1;
-       }
-       return 0;
-}
index 87b02725ba07a998512b0022f3846d1b5df48647..b5a4d067906c8128f3dc7ce005aff1239b1a456c 100644 (file)
 
 .vector dropped_origin;
 
-void write_recordmarker(entity pl, float tstart, float dt);
-
-void GetCvars_handleFloat(entity this, entity store, string thisname, float f, .float field, string name);
-
-void GetCvars_handleString(entity this, entity store, string thisname, float f, .string field, string name);
-
-void precache_all_playermodels(string pattern);
-
 void InitializeEntitiesRun();
 
-void droptofloor(entity this);
-
 float trace_hits_box_1d(float end, float thmi, float thma);
 
 float trace_hits_box(vector start, vector end, vector thmi, vector thma);
 
 float tracebox_hits_box(vector start, vector mi, vector ma, vector end, vector thmi, vector thma);
 
-void attach_sameorigin(entity e, entity to, string tag);
-
 void crosshair_trace(entity pl);
 
 void crosshair_trace_plusvisibletriggers(entity pl);
 void WarpZone_crosshair_trace_plusvisibletriggers(entity pl);
 void crosshair_trace_plusvisibletriggers__is_wz(entity pl, bool is_wz);
 
-void detach_sameorigin(entity e);
-
-void follow_sameorigin(entity e, entity to);
-
-void GetCvars(entity this, entity store, int f);
-
-float LostMovetypeFollow(entity ent);
-
 string uid2name(string myuid);
 
 bool MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundmax, float goodcontents, float badcontents, float badsurfaceflags, int attempts, float maxaboveground, float minviewdistance);
 
 float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance);
 
-string playername(entity p, bool team_colorize);
-
-void SetMovetypeFollow(entity ent, entity e);
-
 float tracebox_hits_box(vector start, vector mi, vector ma, vector end, vector thmi, vector thma);
 
 void traceline_antilag (entity source, vector v1, vector v2, float nomonst, entity forent, float lag);
index ef60454033748a5c25acbdb3a74cefc8f4cf3447..bd73d34947f5f6bc8b3720ad3b673997ffa5912e 100644 (file)
@@ -609,3 +609,78 @@ bool PlayerHeal(entity targ, entity inflictor, float amount, float limit)
        GiveResourceWithLimit(targ, RES_HEALTH, amount, limit);
        return true;
 }
+
+void precache_playermodel(string m)
+{
+       int globhandle, i, n;
+       string f;
+
+       // remove :<skinnumber> suffix
+       int j = strstrofs(m, ":", 0);
+       if(j >= 0)
+               m = substring(m, 0, j);
+
+       if(substring(m, -9, 5) == "_lod1")
+               return;
+       if(substring(m, -9, 5) == "_lod2")
+               return;
+       precache_model(m);
+       f = strcat(substring(m, 0, -5), "_lod1", substring(m, -4, -1));
+       if(fexists(f))
+               precache_model(f);
+       f = strcat(substring(m, 0, -5), "_lod2", substring(m, -4, -1));
+       if(fexists(f))
+               precache_model(f);
+
+       globhandle = search_begin(strcat(m, "_*.sounds"), true, false);
+       if (globhandle < 0)
+               return;
+       n = search_getsize(globhandle);
+       for (i = 0; i < n; ++i)
+       {
+               //print(search_getfilename(globhandle, i), "\n");
+               f = search_getfilename(globhandle, i);
+               PrecachePlayerSounds(f);
+       }
+       search_end(globhandle);
+}
+void precache_all_playermodels(string pattern)
+{
+       int globhandle = search_begin(pattern, true, false);
+       if (globhandle < 0) return;
+       int n = search_getsize(globhandle);
+       for (int i = 0; i < n; ++i)
+       {
+               string s = search_getfilename(globhandle, i);
+               precache_playermodel(s);
+       }
+       search_end(globhandle);
+}
+
+void precache_playermodels(string s)
+{
+       FOREACH_WORD(s, true, { precache_playermodel(it); });
+}
+
+PRECACHE(PlayerModels)
+{
+    // Precache all player models if desired
+    if (autocvar_sv_precacheplayermodels)
+    {
+        PrecachePlayerSounds("sound/player/default.sounds");
+        precache_all_playermodels("models/player/*.zym");
+        precache_all_playermodels("models/player/*.dpm");
+        precache_all_playermodels("models/player/*.md3");
+        precache_all_playermodels("models/player/*.psk");
+        precache_all_playermodels("models/player/*.iqm");
+    }
+
+    if (autocvar_sv_defaultcharacter)
+    {
+               precache_playermodels(autocvar_sv_defaultplayermodel_red);
+               precache_playermodels(autocvar_sv_defaultplayermodel_blue);
+               precache_playermodels(autocvar_sv_defaultplayermodel_yellow);
+               precache_playermodels(autocvar_sv_defaultplayermodel_pink);
+               precache_playermodels(autocvar_sv_defaultplayermodel);
+    }
+}
index 86433d456f726c62b2d37218b0d3f713e992b7fa..523a573a9d69527a80063a85b1e571c668c76de8 100644 (file)
@@ -21,5 +21,7 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
 
 bool PlayerHeal(entity targ, entity inflictor, float amount, float limit);
 
+void precache_all_playermodels(string pattern);
+
 IntrusiveList g_clones;
 STATIC_INIT(g_clones) { g_clones = IL_NEW(); }
index 5014e02aedb0836af94e33a7405f58c2899a764e..7c04ea1da88dda0542b2daf328fdd1af5a4a75b3 100644 (file)
@@ -3,6 +3,7 @@
 #include <common/weapons/_all.qh>
 #include <common/stats.qh>
 #include <server/damage.qh>
+#include <server/gamelog.qh>
 #include <server/intermission.qh>
 #include <server/world.qh>
 #include <server/miscfunctions.qh>
 #include <common/vehicles/sv_vehicles.qh>
 #include "../common/mutators/mutator/waypoints/waypointsprites.qh"
 
+void write_recordmarker(entity pl, float tstart, float dt)
+{
+    GameLogEcho(strcat(":recordset:", ftos(pl.playerid), ":", ftos(dt)));
+
+    // also write a marker into demo files for demotc-race-record-extractor to find
+    stuffcmd(pl,
+             strcat(
+                 strcat("//", strconv(2, 0, 0, GetGametype()), " RECORD SET ", TIME_ENCODED_TOSTRING(TIME_ENCODE(dt))),
+                 " ", ftos(tstart), " ", ftos(dt), "\n"));
+}
+
 IntrusiveList g_race_targets;
 IntrusiveList g_racecheckpoints;
 STATIC_INIT(g_race)
index 129e99da1b7b6e0c7eff802568c3771afc39802a..496fd3874b76a226933fc2b8fe8bd4511f0b0739 100644 (file)
@@ -34,6 +34,8 @@ float race_completing;
 .entity race_respawn_spotref; // try THIS spawn in case you respawn
 
 // definitions for functions used outside race.qc
+void write_recordmarker(entity pl, float tstart, float dt);
+
 float race_PreviousCheckpoint(float f);
 float race_NextCheckpoint(float f);
 void race_AbandonRaceCheck(entity p);
index 7bd776989b6d0cc5a8e73e5c93d829f84285b506..de298e220c5b34e0e8b6fa1fcb59eb569475bb0c 100644 (file)
@@ -863,7 +863,7 @@ void Score_NicePrint_Player(entity to, entity p, float w)
 
        sk = CS(p).scorekeeper;
 
-       s = strcat(s, playername(p, false));
+       s = strcat(s, playername(p.netname, p.team, false));
        for (;;)
        {
                i = strlennocol(s) - NAMEWIDTH;
@@ -895,7 +895,7 @@ void Score_NicePrint_Spectators(entity to)
 
 void Score_NicePrint_Spectator(entity to, entity p)
 {
-       print_to(to, strcat("  ", playername(p, false)));
+       print_to(to, strcat("  ", playername(p.netname, p.team, false)));
 }
 
 .float score_dummyfield;
index 7cd56faa758925ee1c37ddce9459361aa3184409..a1a5ad964a7937e32807a44b5e877c5fb166c47e 100644 (file)
@@ -1,5 +1,6 @@
 #include "common.qh"
 
+#include <server/command/common.qh>
 #include <common/weapons/_all.qh>
 #include <common/stats.qh>
 #include <server/damage.qh>
@@ -113,3 +114,63 @@ void W_PrepareExplosionByDamage(entity this, entity attacker, void(entity this)
        this.nextthink = time;
        setthink(this, explode);
 }
+
+void adaptor_think2use_hittype_splash(entity this) // for timed projectile detonation
+{
+       if(!(IS_ONGROUND(this))) // if onground, we ARE touching something, but HITTYPE_SPLASH is to be networked if the damage causing projectile is not touching ANYTHING
+               this.projectiledeathtype |= HITTYPE_SPLASH;
+       adaptor_think2use(this);
+}
+
+bool SUB_NoImpactCheck(entity this, entity toucher)
+{
+       // zero hitcontents = this is not the real impact, but either the
+       // mirror-impact of something hitting the projectile instead of the
+       // projectile hitting the something, or a touchareagrid one. Neither of
+       // these stop the projectile from moving, so...
+       if(trace_dphitcontents == 0)
+       {
+               LOG_TRACEF("A hit from a projectile happened with no hit contents! DEBUG THIS, this should never happen for projectiles! Projectile will self-destruct. (edict: %i, classname: %s, origin: %v)", this, this.classname, this.origin);
+               checkclient(this); // TODO: .health is checked in the engine with this, possibly replace with a QC function?
+       }
+    if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
+        return true;
+    if (toucher == NULL && this.size != '0 0 0')
+    {
+        vector tic;
+        tic = this.velocity * sys_frametime;
+        tic = tic + normalize(tic) * vlen(this.maxs - this.mins);
+        traceline(this.origin - tic, this.origin + tic, MOVE_NORMAL, this);
+        if (trace_fraction >= 1)
+        {
+            LOG_TRACE("Odd... did not hit...?");
+        }
+        else if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
+        {
+            LOG_TRACE("Detected and prevented the sky-grapple bug.");
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool WarpZone_Projectile_Touch_ImpactFilter_Callback(entity this, entity toucher)
+{
+       // owner check
+       if(toucher && toucher == this.owner)
+               return true;
+       if(SUB_NoImpactCheck(this, toucher))
+       {
+               if(this.classname == "nade")
+                       return false; // no checks here
+               else if(this.classname == "grapplinghook")
+                       RemoveHook(this);
+               else
+                       delete(this);
+               return true;
+       }
+       if(trace_ent && trace_ent.solid > SOLID_TRIGGER)
+               UpdateCSQCProjectile(this);
+       return false;
+}
index 83df91eaaf902dc9701a924dd2b97130b3f2810f..c8e3eb533b836a99ce46eeb7e547d815ff7cea86 100644 (file)
@@ -8,6 +8,10 @@ void W_PlayStrengthSound(entity player);
 float W_CheckProjectileDamage(entity inflictor, entity projowner, int deathtype, float exception);
 void W_PrepareExplosionByDamage(entity this, entity attacker, void(entity this) explode);
 
+void adaptor_think2use_hittype_splash(entity this);
+
+bool WarpZone_Projectile_Touch_ImpactFilter_Callback(entity this, entity toucher);
+
 .float misc_bulletcounter;
 
 .int projectiledeathtype;
index 0407ad79923966caaa7a5ea9acbc87e35d3f2e54..2d56b783f232616e4dc0a67ae4926f5a3f8ad18e 100644 (file)
@@ -85,7 +85,7 @@ void W_HitPlotOpen(entity player)
        if(autocvar_g_hitplots || strhasword(autocvar_g_hitplots_individuals, player.netaddress))
        {
                CS(player).hitplotfh = fopen(strcat("hits-", matchid, "-", player.netaddress, "-", ftos(player.playerid), ".plot"), FILE_WRITE);
-               fputs(CS(player).hitplotfh, strcat("#name ", playername(player, false), "\n"));
+               fputs(CS(player).hitplotfh, strcat("#name ", playername(player.netname, player.team, false), "\n"));
        }
        else { CS(player).hitplotfh = -1; }
 }
index 329aab0876c3e337fb53ae93476ff0c35be4d188..83bd283f783ab740755537452c2cdfe0cc27b2d2 100644 (file)
@@ -1088,11 +1088,11 @@ void DumpStats(float final)
                        s = strcat(s, "spectator:");
 
                if(to_console)
-                       LOG_INFO(s, playername(it, false));
+                       LOG_INFO(s, playername(it.netname, it.team, false));
                if(to_eventlog)
-                       GameLogEcho(strcat(s, ftos(it.playerid), ":", playername(it, false)));
+                       GameLogEcho(strcat(s, ftos(it.playerid), ":", playername(it.netname, it.team, false)));
                if(to_file)
-                       fputs(file, strcat(s, playername(it, false), "\n"));
+                       fputs(file, strcat(s, playername(it.netname, it.team, false), "\n"));
        });
 
        if(teamplay)
@@ -1171,7 +1171,7 @@ void NextLevel()
        FOREACH_CLIENT(IS_PLAYER(it), {
                FixIntermissionClient(it);
                if(it.winning)
-                       bprint(playername(it, false), " ^7wins.\n");
+                       bprint(playername(it.netname, it.team, false), " ^7wins.\n");
        });
 
        target_music_kill();
@@ -1568,6 +1568,18 @@ void CheckRules_World()
        }
 }
 
+// deferred dropping
+void DropToFloor_Handler(entity this)
+{
+       WITHSELF(this, builtin_droptofloor());
+       this.dropped_origin = this.origin;
+}
+
+void droptofloor(entity this)
+{
+       InitializeEntity(this, DropToFloor_Handler, INITPRIO_DROPTOFLOOR);
+}
+
 bool autocvar_sv_gameplayfix_multiplethinksperframe = true;
 void RunThink(entity this)
 {
index 3d8ca997300665db47da85ebb49661b320b93cd1..cf1c150fddf1525dc8be63f5ba8045e7aa93b873 100644 (file)
@@ -48,5 +48,7 @@ void DumpStats(float final);
 void CheckRules_World();
 float RedirectionThink();
 
+void droptofloor(entity this);
+
 IntrusiveList g_moveables;
 STATIC_INIT(g_moveables) { g_moveables = IL_NEW(); }