]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/chat.qc
Fix #2850 "xonotic crashes when pressing restart level after match end in campaign"
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / chat.qc
index 204ed13410defe587a59a540b5bc207a8787e295..5a72b59774478a32cf5aacaf046ad4a864ab510b 100644 (file)
@@ -3,10 +3,12 @@
 #include <common/gamemodes/_mod.qh>
 #include <common/mapobjects/target/location.qh>
 #include <common/mapobjects/triggers.qh>
+#include <common/notifications/all.qh>
 #include <common/teams.qh>
 #include <common/util.qh>
 #include <common/weapons/weapon.qh>
 #include <common/wepent.qh>
+#include <server/command/cmd.qh>
 #include <server/command/common.qh>
 #include <server/gamelog.qh>
 #include <server/main.qh>
  */
 int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodcontrol)
 {
+       if(!autocvar_g_chat_allowed && IS_REAL_CLIENT(source))
+       {
+               Send_Notification(NOTIF_ONE_ONLY, source, MSG_INFO, INFO_CHAT_DISABLED);
+               return 0;
+       }
+
+       if(!autocvar_g_chat_private_allowed && privatesay)
+       {
+               Send_Notification(NOTIF_ONE_ONLY, source, MSG_INFO, INFO_CHAT_PRIVATE_DISABLED);
+               return 0;
+       }
+
+       if(!autocvar_g_chat_spectator_allowed && IS_OBSERVER(source))
+       {
+               Send_Notification(NOTIF_ONE_ONLY, source, MSG_INFO, INFO_CHAT_SPECTATOR_DISABLED);
+               return 0;
+       }
+
+       if(!autocvar_g_chat_team_allowed && teamsay)
+       {
+               Send_Notification(NOTIF_ONE_ONLY, source, MSG_INFO, INFO_CHAT_TEAM_DISABLED);
+               return 0;
+       }
+
        if (!teamsay && !privatesay && substring(msgin, 0, 1) == " ")
                msgin = substring(msgin, 1, -1); // work around DP say bug (say_team does not have this!)
 
@@ -31,7 +57,7 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
                msgin = formatmessage(source, msgin);
 
        string colorstr;
-       if (!(IS_PLAYER(source) || source.caplayer))
+       if (!(IS_PLAYER(source) || INGAME(source)))
                colorstr = "^0"; // black for spectators
        else if(teamplay)
                colorstr = Team_ColorCode(source.team);
@@ -208,7 +234,7 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
        {
                if(autocvar_g_chat_flood_notify_flooder)
                {
-                       sourcemsgstr = strcat(msgstr, "\n^3FLOOD CONTROL: ^7message too long, trimmed\n");
+                       sourcemsgstr = strcat(msgstr, "\n^3CHAT FLOOD CONTROL: ^7message too long, trimmed\n");
                        sourcecmsgstr = "";
                }
                else
@@ -224,7 +250,7 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
                sourcecmsgstr = cmsgstr;
        }
 
-       if (!privatesay && source && !(IS_PLAYER(source) || source.caplayer) && !game_stopped
+       if (!privatesay && source && !(IS_PLAYER(source) || INGAME(source)) && !game_stopped
                && (teamsay || CHAT_NOSPECTATORS()))
        {
                teamsay = -1; // spectators
@@ -247,7 +273,7 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
        {
                if (autocvar_g_chat_flood_notify_flooder)
                {
-                       sprint(source, strcat("^3FLOOD CONTROL: ^7wait ^1", ftos(source.(flood_field) - time), "^3 seconds\n"));
+                       sprint(source, strcat("^3CHAT FLOOD CONTROL: ^7wait ^1", ftos(source.(flood_field) - time), "^3 seconds\n"));
                        ret = 0;
                }
                else
@@ -258,8 +284,8 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
                ret = 1;
        }
 
-       if (privatesay && source && !(IS_PLAYER(source) || source.caplayer) && !game_stopped
-               && (IS_PLAYER(privatesay) || privatesay.caplayer) && CHAT_NOSPECTATORS())
+       if (privatesay && source && !(IS_PLAYER(source) || INGAME(source)) && !game_stopped
+               && (IS_PLAYER(privatesay) || INGAME(privatesay)) && CHAT_NOSPECTATORS())
        {
                ret = -1; // just hide the message completely
        }
@@ -283,6 +309,9 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
                        if (!autocvar_g_chat_tellprivacy) { dedicated_print(msgstr); } // send to server console too if "tellprivacy" is disabled
                        if(!MUTATOR_CALLHOOK(ChatMessageTo, privatesay, source))
                        {
+                               if(IS_REAL_CLIENT(source) && ignore_playerinlist(source, privatesay)) // check ignored players from personal chat log (from "ignore" command)
+                                       return -1; // no sending to this player, thank you very much
+
                                sprint(privatesay, msgstr);
                                if(cmsgstr != "")
                                        centerprint(privatesay, cmsgstr);
@@ -293,6 +322,9 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
                        sprint(source, sourcemsgstr);
                        dedicated_print(msgstr); // send to server console too
                        FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != source && CS(it).active_minigame == CS(source).active_minigame && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
+                               if(IS_REAL_CLIENT(source) && ignore_playerinlist(source, it)) // check ignored players from personal chat log (from "ignore" command)
+                                       continue; // no sending to this player, thank you very much
+
                                sprint(it, msgstr);
                        });
                        event_log_msg = sprintf(":chat_minigame:%d:%s:%s", source.playerid, CS(source).active_minigame.netname, msgin);
@@ -304,7 +336,10 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
                        dedicated_print(msgstr); // send to server console too
                        if(sourcecmsgstr != "")
                                centerprint(source, sourcecmsgstr);
-                       FOREACH_CLIENT((IS_PLAYER(it) || it.caplayer) && IS_REAL_CLIENT(it) && it != source && it.team == source.team && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
+                       FOREACH_CLIENT((IS_PLAYER(it) || INGAME(it)) && IS_REAL_CLIENT(it) && it != source && it.team == source.team && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
+                               if(IS_REAL_CLIENT(source) && ignore_playerinlist(source, it)) // check ignored players from personal chat log (from "ignore" command)
+                                       continue; // no sending to this player, thank you very much
+
                                sprint(it, msgstr);
                                if(cmsgstr != "")
                                        centerprint(it, cmsgstr);
@@ -315,7 +350,10 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
                {
                        sprint(source, sourcemsgstr);
                        dedicated_print(msgstr); // send to server console too
-                       FOREACH_CLIENT(!(IS_PLAYER(it) || it.caplayer) && IS_REAL_CLIENT(it) && it != source && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
+                       FOREACH_CLIENT(!(IS_PLAYER(it) || INGAME(it)) && IS_REAL_CLIENT(it) && it != source && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
+                               if(IS_REAL_CLIENT(source) && ignore_playerinlist(source, it)) // check ignored players from personal chat log (from "ignore" command)
+                                       continue; // no sending to this player, thank you very much
+
                                sprint(it, msgstr);
                        });
                        event_log_msg = sprintf(":chat_spec:%d:%s", source.playerid, strreplace("\n", " ", msgin));
@@ -328,6 +366,9 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
                                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), {
+                               if(IS_REAL_CLIENT(source) && ignore_playerinlist(source, it)) // check ignored players from personal chat log (from "ignore" command)
+                                       continue; // no sending to this player, thank you very much
+
                                sprint(it, msgstr);
                        });
                        event_log_msg = sprintf(":chat:%d:%s", source.playerid, strreplace("\n", " ", msgin));
@@ -348,7 +389,7 @@ entity findnearest(vector point, bool checkitems, vector axismod)
 
     IL_EACH(((checkitems) ? g_items : g_locations), ((checkitems) ? (it.target == "###item###") : (it.classname == "target_location")),
     {
-       if ((it.items == IT_KEY1 || it.items == IT_KEY2) && it.target == "###item###")
+        if ((it.items == IT_KEY1 || it.items == IT_KEY2) && it.target == "###item###")
             dist = it.oldorigin;
         else
             dist = it.origin;
@@ -505,6 +546,8 @@ string formatmessage(entity this, string msg)
                        case "l": replacement = NearestLocation(this.origin); break;
                        case "y": replacement = NearestLocation(cursor); break;
                        case "d": replacement = NearestLocation(this.death_origin); break;
+                       case "o": replacement = vtos(this.origin); break;
+                       case "O": replacement = sprintf("'%f %f %f'", this.origin.x, this.origin.y, this.origin.z); break;
                        case "w": replacement = WeaponNameFromWeaponentity(this, weaponentity); break;
                        case "W": replacement = GetAmmoName(this.(weaponentity).m_weapon.ammo_type); break;
                        case "x": replacement = ((cursor_ent.netname == "" || !cursor_ent) ? "nothing" : cursor_ent.netname); break;