diff --git a/config/killmessages.cfg b/config/killmessages.cfg
new file mode 100644
index 00000000..fbff964f
--- /dev/null
+++ b/config/killmessages.cfg
@@ -0,0 +1,25 @@
+// kill messages
+
+// sets frag and gib messages
+// they will appear on the HUD (client) and in the logs (server)
+// e.g. fragmessage 2 "picked off" => set "picked off" as carbine's kill message :
+// you picked off unarmed
+
+// WARNING : since this file is used by both client and server
+// you can't use cubescript here.
+// But if you really need to, you can use separate files
+// using -E switch to set another kill messages file in your server command line
+
+fragmessage 0 busted // pistol
+fragmessage 2 "picked off" // carbine
+fragmessage 3 peppered // shotgun
+fragmessage 4 sprayed // smg
+fragmessage 5 punctured // sniper
+fragmessage 6 shredded // assault rifle
+fragmessage 7 busted // cpistol
+fragmessage 9 busted // akimbo
+gibmessage 0 slashed // knife
+gibmessage 3 splattered // shotgun gib
+gibmessage 5 headshot // sniper gib
+gibmessage 8 gibbed // nade gib
+
diff --git a/config/servercmdline.txt b/config/servercmdline.txt
index 609275d4..68ea7be0 100644
--- a/config/servercmdline.txt
+++ b/config/servercmdline.txt
@@ -37,6 +37,7 @@
// -X // server passwords file, default config/serverpwd.cfg
// -B // server IP blacklist file, default config/serverblacklist.cfg
// -K // server nickname blacklist file, default config/nicknameblacklist.cfg
+// -E // server kill messages file, default config/killmessages.cfg
// -P // voting permission string (read docs/commandline.html)
// k kick players
// b ban players (and remove bans)
diff --git a/docs/reference.xml b/docs/reference.xml
index c81ef853..447181d8 100644
--- a/docs/reference.xml
+++ b/docs/reference.xml
@@ -341,15 +341,6 @@
-
-
- Ranged random value
-
-
-
-
-
-
Determines if two strings are equal.
@@ -1945,42 +1936,10 @@ bind PRINT [ if (strcmp $last_server "") [ remember_server ]
You won't see any further game chat or hear any more voice com messages from that player.
-
-
-
-
-
-
-
-
- Ignores all players currently on the server.
-
-
-
-
-
-
-
-
-
- Un-ignores all players currently on the server.
-
-
-
-
-
-
-
Print a list of all players that you are currently ignoring.
-
-
-
-
-
-
@@ -2777,18 +2736,18 @@ Output:
-
- Returns the number of solid walls contained into the current selection.
-
-
-
-
-
-
- Output: The selection contains 3 solid wall(s)
-
-
-
+
+ Returns the number of solid walls contained into the current selection.
+
+
+
+
+
+
+ Output: The selection contains 3 solid wall(s)
+
+
+
Pastes a previously copied entity.
@@ -3405,37 +3364,6 @@ Output:
Find what media the map depends on, this is used for mediapack providers.
-
-
- Randomly generates a valid hexadecimal color value.
-
-
-
- Example output: Trying hexadecimal color: 0x2FCAF1
-
-
-
-
-
-
-
-
-
- Randomly generates a valid watercolour value.
-
-
-
- Example output: Trying water color: 2 17 29
-
-
-
- You must be in edit-mode for this command to function.
-
-
-
-
-
-
@@ -4434,6 +4362,36 @@ Output:
make dead players instantly pop out of existence, instead of falling over and sinking into the ground.
+
+
+ set the frag message corresponding to a weapon (appearing on the hud or in server logs)
+
+
+
+
+
+
+ fragmessage 5 sniped // set "sniped" message for frags with sniper.
+
+ It will display "you sniped unarmed" on the hud when you frag unarmed with sniper.
+ In server logs you will get "[127.0.0.1] killer subgunned unarmed".
+
+
+
+
+ This command can be read by both client and server, but the server can't read the cfg if it contains anything else than fragmessage or gibmessage calls.
+
+
+
+
+
+ set the gib message corresponding to a weapon (appearing on the hud or in server logs)
+
+
+ This command is identical to fragmessage (above)
+
+
+
change at what position to truncate the map title string
@@ -5493,7 +5451,6 @@ Output:
Sets the fog and clearing colour.
-
diff --git a/source/src/clientgame.cpp b/source/src/clientgame.cpp
index 6986e570..745e9ae3 100644
--- a/source/src/clientgame.cpp
+++ b/source/src/clientgame.cpp
@@ -695,6 +695,41 @@ void dodamage(int damage, playerent *pl, playerent *actor, int gun, bool gib, bo
else audiomgr.playsound(S_PAIN1+rnd(5), pl);
}
+void setkillmessage(int gun, bool gib, const char *message)
+{
+ if(gun < 0 || gun >= NUMGUNS)
+ {
+ conoutf("invalid gun specified");
+ return;
+ }
+ if(strlen(message)==0)
+ {
+ conoutf("invalid message");
+ return;
+ }
+ if(strlen(message)>MAXKILLMSGLEN)
+ {
+ conoutf("message is too long (max len is %i)", MAXKILLMSGLEN);
+ return;
+ }
+
+ if(gib) formatstring(gibmessages[gun])("%s", message);
+ else formatstring(fragmessages[gun])("%s", message);
+}
+
+void fragmessage(const char *gun, const char *message)
+{
+ setkillmessage(atoi(gun), false, message);
+}
+
+void gibmessage(const char *gun, const char *message)
+{
+ setkillmessage(atoi(gun), true, message);
+}
+
+COMMAND(fragmessage, ARG_2STR);
+COMMAND(gibmessage, ARG_2STR);
+
void dokill(playerent *pl, playerent *act, bool gib, int gun)
{
if(pl->state!=CS_ALIVE || intermission) return;
@@ -702,7 +737,8 @@ void dokill(playerent *pl, playerent *act, bool gib, int gun)
string pname, aname, death;
copystring(pname, pl==player1 ? "you" : colorname(pl));
copystring(aname, act==player1 ? "you" : colorname(act));
- copystring(death, gib ? gib_message(gun) : "fragged");
+ copystring(death, killmessage(gun, gib));
+ copystring(death, killmessage(gun, gib));
void (*outf)(const char *s, ...) = (pl == player1 || act == player1) ? hudoutf : conoutf;
if(pl==act)
diff --git a/source/src/entity.h b/source/src/entity.h
index e6f1a81d..5f0b29c9 100644
--- a/source/src/entity.h
+++ b/source/src/entity.h
@@ -614,6 +614,12 @@ public:
enum {MD_FRAGS = 0, MD_DEATHS, END_MDS};
struct medalsst {bool assigned; int cn; int item;};
+#define MAXKILLMSGLEN 16
+extern char fragmessages[NUMGUNS][MAXKILLMSGLEN];
+extern char gibmessages[NUMGUNS][MAXKILLMSGLEN];
+extern inline char *killmessage(int gun, bool gib);
+
+// deprecated ?!
inline const char * gib_message(int gun)
{
switch (gun)
@@ -624,4 +630,4 @@ inline const char * gib_message(int gun)
case GUN_GRENADE:
default: return "gibbed";
}
-}
+}
\ No newline at end of file
diff --git a/source/src/protos.h b/source/src/protos.h
index 8189f4e0..b3f4845e 100644
--- a/source/src/protos.h
+++ b/source/src/protos.h
@@ -851,7 +851,7 @@ struct serverconfigfile
struct servercommandline
{
int uprate, serverport, syslogfacility, filethres, syslogthres, maxdemos, maxclients, kickthreshold, banthreshold, verbose, incoming_limit, afk_limit, ban_time, demotimelocal;
- const char *ip, *master, *logident, *serverpassword, *adminpasswd, *demopath, *maprot, *pwdfile, *blfile, *nbfile, *infopath, *motdpath, *forbidden, *demofilenameformat, *demotimestampformat;
+ const char *ip, *master, *logident, *serverpassword, *adminpasswd, *demopath, *maprot, *pwdfile, *blfile, *nbfile, *infopath, *motdpath, *forbidden, *killmessages, *demofilenameformat, *demotimestampformat;
bool logtimestamp, demo_interm;
string motd, servdesc_full, servdesc_pre, servdesc_suf, voteperm, mapperm;
int clfilenesting;
@@ -861,7 +861,7 @@ struct servercommandline
maxclients(DEFAULTCLIENTS), kickthreshold(-5), banthreshold(-6), verbose(0), incoming_limit(10), afk_limit(45000), ban_time(20*60*1000), demotimelocal(0),
ip(""), master(NULL), logident(""), serverpassword(""), adminpasswd(""), demopath(""),
maprot("config/maprot.cfg"), pwdfile("config/serverpwd.cfg"), blfile("config/serverblacklist.cfg"), nbfile("config/nicknameblacklist.cfg"),
- infopath("config/serverinfo"), motdpath("config/motd"), forbidden("config/forbidden.cfg"),
+ infopath("config/serverinfo"), motdpath("config/motd"), forbidden("config/forbidden.cfg"), killmessages("config/killmessages.cfg"),
logtimestamp(false), demo_interm(false),
clfilenesting(0)
{
@@ -878,7 +878,7 @@ struct servercommandline
int ai = atoi(a);
// client: dtwhzbsave
switch(arg[1])
- { // todo: gjlqEGHJQUYZ
+ { // todo: gjlqGHJQUYZ
case '-':
if(!strncmp(arg, "--demofilenameformat=", 21))
{
@@ -942,6 +942,7 @@ struct servercommandline
case 'X': pwdfile = a; break;
case 'B': blfile = a; break;
case 'K': nbfile = a; break;
+ case 'E': killmessages = a; break;
case 'I': infopath = a; break;
case 'o': filterrichtext(motd, a); break;
case 'O': motdpath = a; break;
diff --git a/source/src/server.cpp b/source/src/server.cpp
index 0fda9ad1..419aa6a5 100644
--- a/source/src/server.cpp
+++ b/source/src/server.cpp
@@ -19,6 +19,7 @@ servernickblacklist nickblacklist;
serverforbiddenlist forbiddenlist;
serverpasswords passwords;
serverinfofile infofiles;
+killmessagesfile killmessages;
// server state
bool isdedicated = false;
@@ -1461,7 +1462,7 @@ void serverdamage(client *target, client *actor, int damage, int gun, bool gib,
target->position.setsize(0);
ts.state = CS_DEAD;
ts.lastdeath = gamemillis;
- if(!suic) logline(ACLOG_INFO, "[%s] %s %s%s %s", actor->hostname, actor->name, gib ? gib_message(gun) : "fragged", tk ? " their teammate" : "", target->name);
+ if(!suic) logline(ACLOG_INFO, "[%s] %s %s%s %s", actor->hostname, actor->name, killmessage(gun), tk ? " their teammate" : "", target->name);
if(m_flags && targethasflag >= 0)
{
if(m_ctf)
@@ -3560,6 +3561,7 @@ void rereadcfgs(void)
nickblacklist.read();
forbiddenlist.read();
passwords.read();
+ killmessages.read();
}
void loggamestatus(const char *reason)
@@ -4069,6 +4071,7 @@ void initserver(bool dedicated, int argc, char **argv)
ipblacklist.init(scl.blfile);
nickblacklist.init(scl.nbfile);
forbiddenlist.init(scl.forbidden);
+ killmessages.init(scl.killmessages);
infofiles.init(scl.infopath, scl.motdpath);
infofiles.getinfo("en"); // cache 'en' serverinfo
logline(ACLOG_VERBOSE, "holding up to %d recorded demos in memory", scl.maxdemos);
diff --git a/source/src/server.h b/source/src/server.h
index 1adf93de..d5e2a83b 100644
--- a/source/src/server.h
+++ b/source/src/server.h
@@ -495,3 +495,13 @@ guninfo guns[NUMGUNS] =
const char *teamnames[TEAM_NUM+1] = {"CLA", "RVSF", "CLA-SPECT", "RVSF-SPECT", "SPECTATOR", "void"};
const char *teamnames_s[TEAM_NUM+1] = {"CLA", "RVSF", "CSPC", "RSPC", "SPEC", "void"};
+// for both client and server
+// default messages are hardcoded ! (in case there's a problem with cfgs)
+char fragmessages[NUMGUNS][MAXKILLMSGLEN] = { "", "busted", "shredded", "peppered", "sprayed", "punctured", "picked off", "busted", "", "busted" };
+char gibmessages[NUMGUNS][MAXKILLMSGLEN] = { "slashed", "", "", "splattered", "", "headshot", "", "", "gibbed", "" };
+
+inline char *killmessage(int gun, bool gib = false)
+{
+ if(gib) return gibmessages[gun];
+ else return fragmessages[gun];
+}
\ No newline at end of file
diff --git a/source/src/serverfiles.h b/source/src/serverfiles.h
index a535a2e4..359848fb 100644
--- a/source/src/serverfiles.h
+++ b/source/src/serverfiles.h
@@ -887,3 +887,85 @@ struct serverinfofile
return getinfocache(motdbase, "en");
}
};
+
+struct killmessagesfile : serverconfigfile
+{
+ void init(const char *name) { serverconfigfile::init(name); }
+ void read()
+ {
+ if(getfilesize(filename) == filelen) return;
+ if(!load()) return;
+
+ char *l, *s, *p = buf;
+ const char *sep = " \"";
+ int line = 0;
+ logline(ACLOG_VERBOSE,"reading kill messages file '%s'", filename);
+ while(p < buf + filelen)
+ {
+ l = p; p += strlen(p) + 1;
+ l = strtok(l, sep);
+
+
+ char *message = "";
+ if(l)
+ {
+ s = strtok(NULL, sep);
+ if(s && (!strcmp(l, "fragmessage") || !strcmp(l, "gibmessage")))
+ {
+ int errors = 0;
+ int gun = atoi(s);
+
+ s += strlen(s) + 1;
+ while(s[0] == ' ') s++;
+ int hasquotes = strspn(s, "\"");
+ s += hasquotes;
+ message = s;
+ // TODO : what's following is too much complicated for nothing.
+ // it has to remove ending char (space, or quote if there was a first quote)
+ char endingchar = ' ';
+ char *end;
+
+ if(hasquotes) endingchar = '"';
+
+ end = strchr(message, endingchar);
+
+ if(end) message[end-message] = '\0';
+ else
+ {
+ if(hasquotes)
+ {
+ logline(ACLOG_INFO, " error in line %i, ending quote missing (%s)", line, message);
+ errors++;
+ }
+ }
+
+ if(gun < 0 || gun >= NUMGUNS)
+ {
+ logline(ACLOG_INFO, " error in line %i, invalid gun : %i", line, gun);
+ errors++;
+ }
+ if(strlen(message)>MAXKILLMSGLEN)
+ {
+ logline(ACLOG_INFO, " error in line %i, too long message : string length is %i, max allowed i %i", line, strlen(message), MAXKILLMSGLEN);
+ errors++;
+ }
+ if(!errors)
+ {
+ if(!strcmp(l, "fragmessage"))
+ {
+ formatstring(fragmessages[gun])("%s", message);
+ logline(ACLOG_VERBOSE, " added msg '%s' for frags with weapon %i ", message, gun);
+ }
+ else
+ {
+ formatstring(gibmessages[gun])("%s", message);
+ logline(ACLOG_VERBOSE, " added msg '%s' for gibs with weapon %i ", message, gun);
+ }
+ }
+ s = NULL;
+ line++;
+ }
+ }
+ }
+ }
+};
\ No newline at end of file