]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/cl_player.qc
Purge self from the damage/death mutator hooks
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / cl_player.qc
index 42904695c693b35e39835bed217e3c78ef2635c8..3b04a492217d062c5188859dea37909cc8b612f3 100644 (file)
@@ -37,16 +37,16 @@ void Drop_Special_Items(entity player)
        MUTATOR_CALLHOOK(DropSpecialItems, player);
 }
 
-void CopyBody_Think()
-{SELFPARAM();
+void CopyBody_Think(entity this)
+{
        if(this.CopyBody_nextthink && time > this.CopyBody_nextthink)
        {
-               this.CopyBody_think();
+               this.CopyBody_think(this);
                if(wasfreed(this))
                        return;
                this.CopyBody_nextthink = this.nextthink;
-               this.CopyBody_think = this.think;
-               this.think = CopyBody_Think;
+               this.CopyBody_think = getthink(this);
+               setthink(this, CopyBody_Think);
        }
        CSQCMODEL_AUTOUPDATE(this);
        this.nextthink = time;
@@ -95,7 +95,7 @@ void CopyBody(entity this, float keepvelocity)
        clone.solid = this.solid;
        clone.ballistics_density = this.ballistics_density;
        clone.takedamage = this.takedamage;
-       clone.customizeentityforclient = this.customizeentityforclient;
+       setcefc(clone, getcefc(this));
        clone.uncustomizeentityforclient = this.uncustomizeentityforclient;
        clone.uncustomizeentityforclient_set = this.uncustomizeentityforclient_set;
        if (keepvelocity == 1)
@@ -118,9 +118,9 @@ void CopyBody(entity this, float keepvelocity)
 
        CSQCMODEL_AUTOINIT(clone);
        clone.CopyBody_nextthink = this.nextthink;
-       clone.CopyBody_think = this.think;
+       clone.CopyBody_think = getthink(this);
        clone.nextthink = time;
-       clone.think = CopyBody_Think;
+       setthink(clone, CopyBody_Think);
        // "bake" the current animation frame for clones (they don't get clientside animation)
        animdecide_load_if_needed(clone);
        animdecide_setframes(clone, false, frame, frame1time, frame2, frame2time);
@@ -384,10 +384,9 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
                save = v.y;
        }
 
-       frag_damage = damage;
-       MUTATOR_CALLHOOK(PlayerDamage_SplitHealthArmor, inflictor, attacker, this, force, take, save);
-       take = bound(0, damage_take, this.health);
-       save = bound(0, damage_save, this.armorvalue);
+       MUTATOR_CALLHOOK(PlayerDamage_SplitHealthArmor, inflictor, attacker, this, force, take, save, deathtype, damage);
+       take = bound(0, M_ARGV(4, float), this.health);
+       save = bound(0, M_ARGV(5, float), this.armorvalue);
        excess = max(0, damage - take - save);
 
        if(sound_allowed(MSG_BROADCAST, attacker))
@@ -552,11 +551,11 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
        if(accuracy_isgooddamage(attacker, this))
         attacker.accuracy.(accuracy_frags[w.m_id-1]) += 1;
 
-               MUTATOR_CALLHOOK(PlayerDies, inflictor, attacker, this, deathtype);
-               excess = frag_damage;
+               MUTATOR_CALLHOOK(PlayerDies, inflictor, attacker, this, deathtype, excess);
+               excess = M_ARGV(4, float);
 
                Weapon wep = PS(this).m_weapon;
-               WITHSELF(this, wep.wr_playerdeath(wep));
+               WITHSELF(this, wep.wr_playerdeath(wep, this));
 
                RemoveGrapplingHook(this);
 
@@ -622,10 +621,10 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
                // set up to fade out later
                SUB_SetFade (this, time + 6 + random (), 1);
                // reset body think wrapper broken by SUB_SetFade
-               if(this.classname == "body" && this.think != CopyBody_Think) {
-                       this.CopyBody_think = this.think;
+               if(this.classname == "body" && getthink(this) != CopyBody_Think) {
+                       this.CopyBody_think = getthink(this);
                        this.CopyBody_nextthink = this.nextthink;
-                       this.think = CopyBody_Think;
+                       setthink(this, CopyBody_Think);
                        this.nextthink = time;
                }
 
@@ -637,7 +636,7 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
 
                // reset fields the weapons may use just in case
                FOREACH(Weapons, it != WEP_Null, LAMBDA(
-                       WITHSELF(this, it.wr_resetplayer(it));
+                       WITHSELF(this, it.wr_resetplayer(it, this));
                        for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
                        {
                                ATTACK_FINISHED_FOR(this, it.m_id, slot) = 0;
@@ -657,6 +656,12 @@ void MoveToTeam(entity client, int team_colour, int type)
        LogTeamchange(client.playerid, client.team, type);
 }
 
+/** print(), but only print if the server is not local */
+void dedicated_print(string input)
+{
+       if (server_is_dedicated) print(input);
+}
+
 /**
  * message "": do not say, just test flood control
  * return value:
@@ -664,20 +669,14 @@ void MoveToTeam(entity client, int team_colour, int type)
  *   0 = reject
  *  -1 = fake accept
  */
-int Say(entity source, float teamsay, entity privatesay, string msgin, bool floodcontrol)
+int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodcontrol)
 {
-       string msgstr, colorstr, cmsgstr, namestr, fullmsgstr, sourcemsgstr, fullcmsgstr, sourcecmsgstr, colorprefix;
-       float flood;
-       var .float flood_field;
-       float ret;
-       string privatemsgprefix = string_null; float privatemsgprefixlen = 0;
-
-       if(!teamsay && !privatesay)
-               if(substring(msgin, 0, 1) == " ")
-                       msgin = substring(msgin, 1, strlen(msgin) - 1); // work around DP say bug (say_team does not have this!)
+       if (!teamsay && !privatesay) if (substring(msgin, 0, 1) == " ")
+        msgin = substring(msgin, 1, -1); // work around DP say bug (say_team does not have this!)
 
-       msgin = formatmessage(msgin);
+       msgin = formatmessage(source, msgin);
 
+    string colorstr;
        if (!IS_PLAYER(source))
                colorstr = "^0"; // black for spectators
        else if(teamplay)
@@ -691,6 +690,11 @@ int Say(entity source, float teamsay, entity privatesay, string msgin, bool floo
        if(intermission_running)
                teamsay = false;
 
+    if (!source) {
+               colorstr = "";
+               teamsay = false;
+    }
+
        if(msgin != "")
                msgin = trigger_magicear_processmessage_forallears(source, teamsay, privatesay, msgin);
 
@@ -705,18 +709,18 @@ int Say(entity source, float teamsay, entity privatesay, string msgin, bool floo
        }
        */
 
-       if(autocvar_g_chat_teamcolors)
-               namestr = playername(source);
-       else
-               namestr = source.netname;
+    string namestr = "";
+    if (source)
+        namestr = autocvar_g_chat_teamcolors ? playername(source) : source.netname;
 
-       if(strdecolorize(namestr) == namestr)
-               colorprefix = "^3";
-       else
-               colorprefix = "^7";
+    string colorprefix = (strdecolorize(namestr) == namestr) ? "^3" : "^7";
 
-       if(msgin != "")
-       {
+    string msgstr, cmsgstr;
+    string privatemsgprefix = string_null;
+    int privatemsgprefixlen = 0;
+       if (msgin == "") {
+        msgstr = cmsgstr = "";
+       } else {
                if(privatesay)
                {
                        msgstr = strcat("\{1}\{13}* ", colorprefix, namestr, "^3 tells you: ^7");
@@ -750,23 +754,22 @@ int Say(entity source, float teamsay, entity privatesay, string msgin, bool floo
                                msgin = strreplace("/me", strcat(colorprefix, namestr), msgin);
                                msgstr = strcat("\{1}^4* ", "^7", msgin);
                        }
-                       else
-                               msgstr = strcat("\{1}", colorprefix, namestr, "^7: ", msgin);
+                       else {
+                msgstr = "\{1}";
+                msgstr = strcat(msgstr, (namestr != "") ? strcat(colorprefix, namestr, "^7: ") : "^7");
+                msgstr = strcat(msgstr, msgin);
+            }
                        cmsgstr = "";
                }
                msgstr = strcat(strreplace("\n", " ", msgstr), "\n"); // newlines only are good for centerprint
        }
-       else
-       {
-               msgstr = cmsgstr = "";
-       }
 
-       fullmsgstr = msgstr;
-       fullcmsgstr = cmsgstr;
+       string fullmsgstr = msgstr;
+       string fullcmsgstr = cmsgstr;
 
        // FLOOD CONTROL
-       flood = 0;
-       flood_field = floodcontrol_chat;
+       int flood = 0;
+       var .float flood_field = floodcontrol_chat;
        if(floodcontrol)
        {
                float flood_spl;
@@ -838,6 +841,7 @@ int Say(entity source, float teamsay, entity privatesay, string msgin, bool floo
                        source.(flood_field) = flood = 0;
        }
 
+    string sourcemsgstr, sourcecmsgstr;
        if(flood == 2) // cannot happen for empty msgstr
        {
                if(autocvar_g_chat_flood_notify_flooder)
@@ -858,8 +862,7 @@ int Say(entity source, float teamsay, entity privatesay, string msgin, bool floo
                sourcecmsgstr = cmsgstr;
        }
 
-       if(!privatesay)
-       if (!IS_PLAYER(source))
+       if (!privatesay && source && !IS_PLAYER(source))
        {
                if (!intermission_running)
                        if(teamsay || (autocvar_g_chat_nospectators == 1) || (autocvar_g_chat_nospectators == 2 && !(warmup_stage || gameover)))
@@ -873,6 +876,7 @@ int Say(entity source, float teamsay, entity privatesay, string msgin, bool floo
        if(privatesay)
                sourcemsgstr = strcat(privatemsgprefix, substring(sourcemsgstr, privatemsgprefixlen, -1));
 
+    int ret;
        if(source.muted)
        {
                // always fake the message
@@ -913,7 +917,7 @@ int Say(entity source, float teamsay, entity privatesay, string msgin, bool floo
                {
                        sprint(source, sourcemsgstr);
                        dedicated_print(msgstr); // send to server console too
-                       FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != source && it.active_minigame == source.active_minigame, LAMBDA(sprint(it, msgstr)));
+                       FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != source && it.active_minigame == source.active_minigame, sprint(it, msgstr));
                }
                else if(teamsay > 0) // team message, only sent to team mates
                {
@@ -921,26 +925,27 @@ int Say(entity source, float teamsay, entity privatesay, string msgin, bool floo
                        dedicated_print(msgstr); // send to server console too
                        if(sourcecmsgstr != "")
                                centerprint(source, sourcecmsgstr);
-                       FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it) && it != source && it.team == source.team, LAMBDA(
+                       FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it) && it != source && it.team == source.team, {
                                sprint(it, msgstr);
                                if(cmsgstr != "")
                                        centerprint(it, cmsgstr);
-                       ));
+                       });
                }
                else if(teamsay < 0) // spectator message, only sent to spectators
                {
                        sprint(source, sourcemsgstr);
                        dedicated_print(msgstr); // send to server console too
-                       FOREACH_CLIENT(!IS_PLAYER(it) && IS_REAL_CLIENT(it) && it != source, LAMBDA(sprint(it, msgstr)));
-               }
-               else if(sourcemsgstr != msgstr) // trimmed/server fixed message, sent to all players
-               {
-                       sprint(source, sourcemsgstr);
-                       dedicated_print(msgstr); // send to server console too
-                       FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != source, LAMBDA(sprint(it, msgstr)));
+                       FOREACH_CLIENT(!IS_PLAYER(it) && IS_REAL_CLIENT(it) && it != source, sprint(it, msgstr));
                }
                else
-                       bprint(msgstr); // entirely normal message, sent to all players -- bprint sends to server console too.
+               {
+            if (source) {
+                sprint(source, sourcemsgstr);
+                dedicated_print(msgstr); // send to server console too
+                MX_Say(strcat(playername(source), "^7: ", msgin));
+            }
+            FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != source, sprint(it, msgstr));
+        }
        }
 
        return ret;