Enhanced Player's dmmessage implementation (say + voice)

This commit is contained in:
smallmodel 2023-11-03 21:56:31 +01:00
parent b31f4bc00c
commit 94d4cbeb82
No known key found for this signature in database
GPG key ID: 9F2D623CEDF08512

View file

@ -58,6 +58,78 @@ const Vector power_color(0.0, 1.0, 0.0);
const Vector acolor(1.0, 1.0, 1.0); const Vector acolor(1.0, 1.0, 1.0);
const Vector bcolor(1.0, 0.0, 0.0); const Vector bcolor(1.0, 0.0, 0.0);
//
// mohaas 2.0 and above
//
const char *pInstantMsgEng[6][9] = {
{"Good job team!",
"Alright!", "We've done it!",
"Wooohoo!", "Objective achieved.",
"We've completed an objective.", "We've lost an objective!",
"The enemy has overrun our objective!", NULL},
{"Squad, move in!",
"Squad, fall back!", "Squad, attack right flank!",
"Squad, attack left flank!", "Squad, hold this position!",
"Squad, covering fire!", "Squad, regroup!",
"Squad, split up!", NULL},
{"Cover me!",
"I'll cover you!", "Follow me!",
"You take point.", "Taking Fire! Need some help!",
"Get ready to move in on my signal.", "Attack!",
"Open fire!", NULL},
{"Yes sir!",
"No sir!", "Enemy Spotted.",
"Sniper!", "Grenade! Take Cover!",
"Area Clear.", "Thanks.",
"I owe you one.", NULL},
{"Who wants more?!",
"Never send boys to do a man's job.", "This is too easy!",
"You mess with the best, you die like the rest.", "Watch that friendly fire!",
"Hey! I'm on your team!", "Come on out you cowards!",
"Where are you hiding?", NULL},
//
// Added in 2.30
//
{"Guard our jail!",
"Capture the enemy jail!", "I'm defending our jail!",
"I'm attacking the enemy jail!", "Rescue the Prisoners!",
"The enemy is attacking our jail!"}
};
//
// for mohaa version 1.11 and below
//
const char *pInstantMsgEng_ver6[5][9] = {
{"Squad, move in!",
"Squad, fall back!", "Squad, attack right flank!",
"Squad, attack left flank!", "Squad, hold this position!",
"Squad, covering fire!", "Squad, regroup!",
"", ""},
{
"Cover me!", "I'll cover you!",
"Follow me!", "You take point.",
"You take the lead.", "Taking Fire! Need some help!",
"Charge!", "Attack!",
"Open fire!", },
{
"Yes sir!", "No sir!",
"Enemy Spotted.", "Sniper!",
"Grenade! Take Cover!", "Area Clear.",
"Great Shot!", "Thanks.",
"I owe you one.", },
{
"Is that all you've got?", "I think they are all out of real men!",
"Go on and run, you yellow-bellies!", "They're a bunch of cowards!",
"Come back when you've had some target practice!", "Come prepared next time!",
"Try again!", "I've seen French school girls shoot better!",
"That made a mess.", },
{"He's going to get us killed!",
"A lot of good men are going to die because of his poor leadership", "Good riddance!",
"That guy is going to get us all killed!", "Hey buddy, get down!",
"Stay out of my foxhole, pal!", "Find your own hiding place!",
"Get out of my way!", ""}
};
qboolean TryPush(int entnum, vec3_t move_origin, vec3_t move_end); qboolean TryPush(int entnum, vec3_t move_origin, vec3_t move_end);
Event EV_Player_DumpState Event EV_Player_DumpState
@ -3166,7 +3238,7 @@ void Player::SetStopwatch(int iDuration, stopWatchType_t type)
void Player::KilledPlayerInDeathmatch(Player *killed) void Player::KilledPlayerInDeathmatch(Player *killed)
{ {
DM_Team* pDMTeam; DM_Team *pDMTeam;
pDMTeam = killed->GetDM_Team(); pDMTeam = killed->GetDM_Team();
@ -3322,7 +3394,7 @@ void Player::DoUse(Event *ev)
continue; continue;
} }
Event* event = new Event(EV_Use); Event *event = new Event(EV_Use);
event->AddListener(this); event->AddListener(this);
hit->entity->ProcessEvent(event); hit->entity->ProcessEvent(event);
@ -3332,8 +3404,7 @@ void Player::DoUse(Event *ev)
} }
} }
if (i < num && m_pVehicle) if (i < num && m_pVehicle) {
{
// //
// Added in 2.30 // Added in 2.30
// Make the vehicle also invincible if the player is invincible // Make the vehicle also invincible if the player is invincible
@ -3834,7 +3905,7 @@ void Player::ClientMove(usercmd_t *ucmd)
client->ps.pm_flags |= PMF_VIEW_JUMP_START; client->ps.pm_flags |= PMF_VIEW_JUMP_START;
} }
*/ */
if (maxs.z == 54.0f ||maxs.z == 60.0f) { if (maxs.z == 54.0f || maxs.z == 60.0f) {
client->ps.pm_flags |= PMF_DUCKED; client->ps.pm_flags |= PMF_DUCKED;
} else if (viewheight == 52) { } else if (viewheight == 52) {
client->ps.pm_flags |= PMF_VIEW_JUMP_START; client->ps.pm_flags |= PMF_VIEW_JUMP_START;
@ -4558,7 +4629,7 @@ void Player::Think(void)
if (!ent->inuse || !ent->entity) { if (!ent->inuse || !ent->entity) {
// Invalid spectate entity // Invalid spectate entity
SetPlayerSpectateRandom(); SetPlayerSpectateRandom();
} else if (ent->entity->deadflag >= DEAD_DEAD || static_cast<Player*>(ent->entity)->IsSpectator() || IsValidSpectatePlayer(static_cast<Player*>(ent->entity))) { } else if (ent->entity->deadflag >= DEAD_DEAD || static_cast<Player *>(ent->entity)->IsSpectator() || IsValidSpectatePlayer(static_cast<Player *>(ent->entity))) {
SetPlayerSpectateRandom(); SetPlayerSpectateRandom();
} }
} }
@ -4581,7 +4652,7 @@ void Player::Think(void)
if (!ent->inuse || !ent->entity) { if (!ent->inuse || !ent->entity) {
// Invalid spectate entity // Invalid spectate entity
SetPlayerSpectateRandom(); SetPlayerSpectateRandom();
} else if (ent->entity->deadflag >= DEAD_DEAD || static_cast<Player*>(ent->entity)->IsSpectator() || IsValidSpectatePlayer(static_cast<Player*>(ent->entity))) { } else if (ent->entity->deadflag >= DEAD_DEAD || static_cast<Player *>(ent->entity)->IsSpectator() || IsValidSpectatePlayer(static_cast<Player *>(ent->entity))) {
SetPlayerSpectateRandom(); SetPlayerSpectateRandom();
} else if (g_gametype->integer >= GT_TEAM && GetTeam() > TEAM_FREEFORALL && static_cast<Player*>(ent->entity)->GetTeam() != GetTeam()) { } else if (g_gametype->integer >= GT_TEAM && GetTeam() > TEAM_FREEFORALL && static_cast<Player*>(ent->entity)->GetTeam() != GetTeam()) {
SetPlayerSpectateRandom(); SetPlayerSpectateRandom();
@ -6221,7 +6292,7 @@ void Player::SetPlayerView(
if (camera->IsSubclassOfPlayer()) { if (camera->IsSubclassOfPlayer()) {
Vector vPos; Vector vPos;
Player* pPlayer = (Player*)camera; Player *pPlayer = (Player *)camera;
GetSpectateFollowOrientation(pPlayer, vPos, vVec); GetSpectateFollowOrientation(pPlayer, vPos, vVec);
@ -6721,7 +6792,7 @@ PlayerAngles
void Player::PlayerAngles(void) void Player::PlayerAngles(void)
{ {
if (getMoveType() == MOVETYPE_PORTABLE_TURRET) { if (getMoveType() == MOVETYPE_PORTABLE_TURRET) {
PortableTurret* portableTurret = static_cast<PortableTurret*>(m_pTurret.Pointer()); PortableTurret *portableTurret = static_cast<PortableTurret *>(m_pTurret.Pointer());
angles[0] = portableTurret->GetGroundPitch(); angles[0] = portableTurret->GetGroundPitch();
angles[1] = portableTurret->GetStartYaw(); angles[1] = portableTurret->GetStartYaw();
} }
@ -8843,7 +8914,7 @@ void Player::SetPlayerSpectate(bool bNext)
m_iPlayerSpectating = 0; m_iPlayerSpectating = 0;
} }
for(i = num; i < game.maxclients && i >= 0; i+= dir) { for (i = num; i < game.maxclients && i >= 0; i += dir) {
ent = &g_entities[i]; ent = &g_entities[i];
if (!ent->inuse || !ent->entity) { if (!ent->inuse || !ent->entity) {
continue; continue;
@ -9260,7 +9331,7 @@ void Player::Disconnect(void)
} }
} }
void Player::CallVote(Event* ev) void Player::CallVote(Event *ev)
{ {
str arg1; str arg1;
str arg2; str arg2;
@ -9289,7 +9360,12 @@ void Player::CallVote(Event* ev)
} }
if (votecount >= MAX_VOTE_COUNT) { if (votecount >= MAX_VOTE_COUNT) {
HUDPrint(va("%s %d %s.\n", gi.LV_ConvertString("You cannot call another vote for"), (unsigned int)(m_fLastVoteTime - level.time + 1), gi.LV_ConvertString("seconds"))); HUDPrint(
va("%s %d %s.\n",
gi.LV_ConvertString("You cannot call another vote for"),
(unsigned int)(m_fLastVoteTime - level.time + 1),
gi.LV_ConvertString("seconds"))
);
return; return;
} }
} }
@ -9314,11 +9390,11 @@ void Player::CallVote(Event* ev)
&& Q_stricmp(arg1.c_str(), "g_gametype") && Q_stricmp(arg1.c_str(), "kick") && Q_stricmp(arg1.c_str(), "g_gametype") && Q_stricmp(arg1.c_str(), "kick")
&& Q_stricmp(arg1.c_str(), "clientkick") && Q_stricmp(arg1.c_str(), "fraglimit")) { && Q_stricmp(arg1.c_str(), "clientkick") && Q_stricmp(arg1.c_str(), "fraglimit")) {
HUDPrint(gi.LV_ConvertString("Invalid vote string.")); HUDPrint(gi.LV_ConvertString("Invalid vote string."));
HUDPrint( HUDPrint(va(
va("%s restart, nextmap, map <mapname>, g_gametype <n>, fraglimit <n>, timelimit <n>, kick <player>, and " "%s restart, nextmap, map <mapname>, g_gametype <n>, fraglimit <n>, timelimit <n>, kick <player>, and "
"clientkick <player #>.", "clientkick <player #>.",
gi.LV_ConvertString("Vote commands are:")) gi.LV_ConvertString("Vote commands are:")
); ));
return; return;
} }
@ -9327,7 +9403,7 @@ void Player::CallVote(Event* ev)
// //
// check for a valid player // check for a valid player
// //
gentity_t* ent; gentity_t *ent;
int i; int i;
for (i = 0; i < game.maxclients; i++) { for (i = 0; i < game.maxclients; i++) {
@ -9349,14 +9425,13 @@ void Player::CallVote(Event* ev)
} }
if (i == game.maxclients) { if (i == game.maxclients) {
HUDPrint(va("%s %s", ent->client->pers.netname, gi.LV_ConvertString("is not a valid player name to kick.")) HUDPrint(
va("%s %s", ent->client->pers.netname, gi.LV_ConvertString("is not a valid player name to kick."))
); );
} }
} } else if (!Q_stricmp(arg1.c_str(), "map") && *sv_nextmap->string) {
else if (!Q_stricmp(arg1.c_str(), "map") && *sv_nextmap->string) {
level.m_voteString = va("%s %s; set next map \"%s\"", arg1.c_str(), arg2.c_str(), arg2.c_str()); level.m_voteString = va("%s %s; set next map \"%s\"", arg1.c_str(), arg2.c_str(), arg2.c_str());
} } else {
else {
level.m_voteString = va("%s %s", arg1.c_str(), arg2.c_str()); level.m_voteString = va("%s %s", arg1.c_str(), arg2.c_str());
} }
@ -9400,18 +9475,15 @@ void Player::CallVote(Event* ev)
HUDPrint(va("%s %s %d", gi.LV_ConvertString("Game Type"), arg1.c_str(), gametypeNum)); HUDPrint(va("%s %s %d", gi.LV_ConvertString("Game Type"), arg1.c_str(), gametypeNum));
return; return;
} }
} } else if (!Q_stricmp(arg1.c_str(), "map")) {
else if (!Q_stricmp(arg1.c_str(), "map")) {
if (*sv_nextmap->string) { if (*sv_nextmap->string) {
level.m_voteString = va("%s %s; set nextmap \"%s\"", arg1.c_str(), arg2.c_str(), sv_nextmap->string); level.m_voteString = va("%s %s; set nextmap \"%s\"", arg1.c_str(), arg2.c_str(), sv_nextmap->string);
} } else {
else {
level.m_voteString = va("%s %s", arg1.c_str(), arg2.c_str()); level.m_voteString = va("%s %s", arg1.c_str(), arg2.c_str());
} }
level.m_voteName = va("Map %s", arg2.c_str()); level.m_voteName = va("Map %s", arg2.c_str());
} } else {
else {
level.m_voteString = va("%s %s", arg1.c_str(), arg2.c_str()); level.m_voteString = va("%s %s", arg1.c_str(), arg2.c_str());
level.m_voteName = level.m_voteString; level.m_voteName = level.m_voteString;
} }
@ -9423,12 +9495,14 @@ void Player::CallVote(Event* ev)
str voteOptionName; str voteOptionName;
str voteOptionSubName; str voteOptionSubName;
voteoptiontype_t optionType; voteoptiontype_t optionType;
union { union {
int optionInteger; int optionInteger;
float optionFloat; float optionFloat;
int optionClientNum; int optionClientNum;
}; };
gentity_t* ent;
gentity_t *ent;
char buffer[64]; char buffer[64];
@ -9449,14 +9523,22 @@ void Player::CallVote(Event* ev)
subListIndex = atoi(arg2.c_str()); subListIndex = atoi(arg2.c_str());
if (!level.GetVoteOptionSub(voteIndex, subListIndex, &voteOptionSubCommand)) { if (!level.GetVoteOptionSub(voteIndex, subListIndex, &voteOptionSubCommand)) {
HUDPrint(va("%s %i %s \"%s\".\n", gi.LV_ConvertString("Invalid vote choice"), subListIndex, gi.LV_ConvertString("for vote option"), voteOptionName.c_str())); HUDPrint(
va("%s %i %s \"%s\".\n",
gi.LV_ConvertString("Invalid vote choice"),
subListIndex,
gi.LV_ConvertString("for vote option"),
voteOptionName.c_str())
);
return; return;
} }
level.m_voteString = va("%s %s", voteOptionCommand.c_str(), voteOptionSubCommand.c_str()); level.m_voteString = va("%s %s", voteOptionCommand.c_str(), voteOptionSubCommand.c_str());
// get the sub-option name // get the sub-option name
level.GetVoteOptionSubName(voteIndex, subListIndex, &voteOptionSubName); level.GetVoteOptionSubName(voteIndex, subListIndex, &voteOptionSubName);
level.m_voteName = va("%s %s", gi.LV_ConvertString(voteOptionName.c_str()), gi.LV_ConvertString(voteOptionSubName.c_str())); level.m_voteName =
va("%s %s", gi.LV_ConvertString(voteOptionName.c_str()), gi.LV_ConvertString(voteOptionSubName.c_str())
);
break; break;
case VOTE_OPTION_TEXT: case VOTE_OPTION_TEXT:
if (strchr(arg2.c_str(), ';')) { if (strchr(arg2.c_str(), ';')) {
@ -9506,11 +9588,17 @@ void Player::CallVote(Event* ev)
} }
level.m_voteString = va("%s %i", voteOptionCommand.c_str(), optionClientNum); level.m_voteString = va("%s %i", voteOptionCommand.c_str(), optionClientNum);
level.m_voteName = va("%s #%i: %s", gi.LV_ConvertString(voteOptionName.c_str()), optionClientNum, ent->client->pers.netname); level.m_voteName =
va("%s #%i: %s", gi.LV_ConvertString(voteOptionName.c_str()), optionClientNum, ent->client->pers.netname
);
break; break;
default: default:
level.GetVoteOptionMainName(voteIndex, &voteOptionName); level.GetVoteOptionMainName(voteIndex, &voteOptionName);
gi.Printf("ERROR: Vote option (\"%s\" \"%s\") with unknown vote option type\n", voteOptionName.c_str(), voteOptionCommand.c_str()); gi.Printf(
"ERROR: Vote option (\"%s\" \"%s\") with unknown vote option type\n",
voteOptionName.c_str(),
voteOptionCommand.c_str()
);
return; return;
} }
} }
@ -9525,13 +9613,13 @@ void Player::CallVote(Event* ev)
numVoters = 0; numVoters = 0;
for (int i = 0; i < game.maxclients; i++) { for (int i = 0; i < game.maxclients; i++) {
gentity_t* ent = &g_entities[i]; gentity_t *ent = &g_entities[i];
if (!ent->client || !ent->inuse) { if (!ent->client || !ent->inuse) {
continue; continue;
} }
Player* p = (Player*)ent->entity; Player *p = (Player *)ent->entity;
p->voted = false; p->voted = false;
numVoters++; numVoters++;
@ -9949,6 +10037,7 @@ void Player::GetTeamDialogPrefix(str& outPrefix)
outPrefix = "allied_"; outPrefix = "allied_";
} }
if (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) {
switch (m_voiceType) { switch (m_voiceType) {
case PVT_ALLIED_AMERICAN: case PVT_ALLIED_AMERICAN:
outPrefix += "american_"; outPrefix += "american_";
@ -9973,6 +10062,60 @@ void Player::GetTeamDialogPrefix(str& outPrefix)
} }
break; break;
} }
} else {
switch (m_voiceType) {
case PVT_ALLIED_AIRBORNE:
outPrefix += "airborne_";
break;
case PVT_ALLIED_MANON:
outPrefix += "manon_";
break;
case PVT_ALLIED_SAS:
outPrefix += "sas_";
break;
case PVT_ALLIED_PILOT:
outPrefix += "pilot_";
break;
case PVT_ALLIED_ARMY:
outPrefix += "army_";
break;
case PVT_ALLIED_RANGER:
outPrefix += "ranger_";
break;
case PVT_AXIS_AXIS1:
outPrefix += "axis1_";
break;
case PVT_AXIS_AXIS2:
outPrefix += "axis2_";
break;
case PVT_AXIS_AXIS3:
outPrefix += "axis3_";
break;
case PVT_AXIS_AXIS4:
outPrefix += "axis4_";
break;
case PVT_AXIS_AXIS5:
outPrefix += "axis5_";
break;
default:
if (dm_team != TEAM_AXIS) {
outPrefix += "army_";
} else {
outPrefix += "axis4_";
}
}
}
} }
void Player::PlayInstantMessageSound(const char *name) void Player::PlayInstantMessageSound(const char *name)
@ -10001,193 +10144,209 @@ void Player::PlayInstantMessageSound(const char *name)
void Player::EventDMMessage(Event *ev) void Player::EventDMMessage(Event *ev)
{ {
int mode; int i;
str stuffstrings; int iStringLength;
str convertedstuff; int iMode = 0;
str string; str sToken;
str voiceName; char szPrintString[MAX_SAY_TEXT]; // it's MAX_STRING_CHARS in mohaa
str soundName; const char *pTmpInstantMsg = "";
AliasListNode_t *list = NULL;
const char *prefix = NULL;
qboolean bInstaMessage = qfalse; qboolean bInstaMessage = qfalse;
qboolean met_comment = false; AliasListNode_t *pSoundAlias = NULL;
const char *pszAliasname = NULL;
str sAliasName;
str sRandomAlias;
gentity_t *ent;
if (g_gametype->integer == GT_SINGLE_PLAYER) { if (g_gametype->integer == GT_SINGLE_PLAYER) {
return; return;
} }
mode = ev->GetInteger(1);
if (ev->NumArgs() <= 1) { if (ev->NumArgs() <= 1) {
return; return;
} }
string = ev->GetString(2); sToken = ev->GetString(2);
// Check for taunts // Check for taunts
if (string.length() == 3 && *string == '*') { if (sToken.length() == 3 && *sToken == '*' && sToken[1] > '0' && sToken[1] <= '9' && sToken[2] > '0'
char num1 = string[1]; && sToken[2] <= '9') {
char num2 = string[2]; unsigned int n1, n2;
if (num1 > '0' && num1 <= '9' && num2 > '0' && num2 <= '9') {
if (IsSpectator() || IsDead()) { if (IsSpectator() || IsDead()) {
// spectators or death players can't talk
return; return;
} }
if (dm_team == TEAM_AXIS) { GetTeamDialogPrefix(sAliasName);
voiceName = "axis_"; sAliasName += va("%c%c", (sToken[1] + '0'), (sToken[2] + '0'));
sRandomAlias = GetRandomAlias(sAliasName, &pSoundAlias);
// find a random alias
if (sRandomAlias.length() > 0) {
pszAliasname = sRandomAlias.c_str();
}
if (!pszAliasname) {
pszAliasname = gi.GlobalAlias_FindRandom(sAliasName, &pSoundAlias);
}
if (!pszAliasname || !pSoundAlias) {
return;
}
n1 = sToken[1] - '1';
n2 = sToken[2] - '1';
if (g_protocol >= PROTOCOL_MOHTA_MIN) {
if (n1 >= ARRAY_LEN(pInstantMsgEng) || n2 >= ARRAY_LEN(pInstantMsgEng[0])) {
return;
}
pTmpInstantMsg = pInstantMsgEng[n1][n2];
} else { } else {
voiceName = "allied_"; if (n1 >= ARRAY_LEN(pInstantMsgEng_ver6) || n2 >= ARRAY_LEN(pInstantMsgEng_ver6[0])) {
} return;
} }
switch (m_voiceType) { // fallback to old version
case PVT_ALLIED_AIRBORNE: pTmpInstantMsg = pInstantMsgEng_ver6[n1][n2];
voiceName += "airborne_";
break;
case PVT_ALLIED_MANON:
voiceName += "manon_";
break;
case PVT_ALLIED_SAS:
voiceName += "sas_";
break;
case PVT_ALLIED_PILOT:
voiceName += "pilot_";
break;
case PVT_ALLIED_ARMY:
voiceName += "army_";
break;
case PVT_ALLIED_RANGER:
voiceName += "ranger_";
break;
case PVT_AXIS_AXIS1:
voiceName += "axis1_";
break;
case PVT_AXIS_AXIS2:
voiceName += "axis2_";
break;
case PVT_AXIS_AXIS3:
voiceName += "axis3_";
break;
case PVT_AXIS_AXIS4:
voiceName += "axis4_";
break;
case PVT_AXIS_AXIS5:
voiceName += "axis5_";
break;
default:
if (dm_team != TEAM_AXIS) {
voiceName += "army_";
} else {
voiceName += "axis4_";
}
} }
voiceName += va("%c%c", num1 + '0', num2 + '0');
FindAlias(soundName, voiceName, &list);
if (list) {
bInstaMessage = qtrue; bInstaMessage = qtrue;
if (g_gametype->integer == GT_FFA) {
iMode = 0;
} else {
if (n1 == 4) {
iMode = 0;
} else {
iMode = -1;
}
if (g_voiceChatTime->value > 0) {
m_fTalkTime = g_voiceChatTime->value + level.time;
}
} }
} }
if (!bInstaMessage) { if (!bInstaMessage) {
for (int i = 2; i <= ev->NumArgs(); i++) { iMode = ev->GetInteger(1);
string = ev->GetString(i); if (g_textChatTime->value > 0) {
m_fTalkTime = g_textChatTime->value + level.time;
}
}
if (strstr(string, "/*")) { strcpy(szPrintString, "print \"" HUD_MESSAGE_CHAT_WHITE);
if (m_bSpectator) {
if (iMode <= 0) {
strcat(szPrintString, "(spectator)");
strcat(szPrintString, " ");
} else if (iMode <= game.maxclients) {
ent = &g_entities[iMode - 1];
if (ent->inuse && ent->entity && !static_cast<Player *>(ent->entity)->IsSpectator()) {
str errorString = gi.LV_ConvertString("Message Error");
str reasonString =
gi.LV_ConvertString("Spectators are not allowed to send private messages to non-spectators");
gi.SendServerCommand(
edict - g_entities,
"print \"" HUD_MESSAGE_CHAT_WHITE "%s: %s.\"",
errorString.c_str(),
reasonString.c_str()
);
return;
}
}
} else if (IsDead() || m_bTempSpectator) {
if (iMode <= 0) {
strcat(szPrintString, "(dead)");
strcat(szPrintString, " ");
} else if (iMode <= game.maxclients) {
ent = &g_entities[iMode - 1];
if (ent->inuse && ent->entity && !static_cast<Player *>(ent->entity)->IsSpectator()) {
str errorString = gi.LV_ConvertString("Message Error");
str reasonString =
gi.LV_ConvertString("Dead players are not allowed to send private messages to active players");
gi.SendServerCommand(
edict - g_entities,
"print \"" HUD_MESSAGE_CHAT_WHITE "%s: %s.\"",
errorString.c_str(),
reasonString.c_str()
);
return;
}
}
} else if (iMode < 0) {
strcat(szPrintString, "(team)");
strcat(szPrintString, " ");
} else if (iMode > 0) {
strcat(szPrintString, "(private)");
strcat(szPrintString, " ");
}
strcat(szPrintString, client->pers.netname);
if (bInstaMessage) {
strcat(szPrintString, ": ");
strcat(szPrintString, gi.LV_ConvertString(pTmpInstantMsg));
} else {
bool met_comment;
strcat(szPrintString, ":");
iStringLength = strlen(szPrintString);
for (i = 2; i <= ev->NumArgs(); i++) {
sToken = ev->GetString(i);
// Added in 2.40
// Special battle language tokens
// So players can easily tell their position, health, etc.
sToken = TranslateBattleLanguageTokens(sToken);
if (iStringLength + sToken.length() > (ARRAY_LEN(szPrintString) - 1)) {
break;
}
// Added in OPM.
// Checks for comments in string (as COM_Parse will parse them)
if (strstr(sToken, "/*")) {
met_comment = true; met_comment = true;
} }
if (strstr(string, "*/") && met_comment) { if (strstr(sToken, "*/") && met_comment) {
G_WarnPlayer(this, "Line comments ('/*' and '*/') are not allowed in messages.\n"); // ignore messages containing comments
return; return;
} }
stuffstrings += " " + string; strcat(szPrintString, " ");
convertedstuff += gi.LV_ConvertString(string); strcat(szPrintString, gi.LV_ConvertString(sToken));
} }
} else {
stuffstrings = " " + str(list->subtitle);
} }
stuffstrings += "\n"; strcat(szPrintString, "\n");
// Protect again buffer overflow exploit // ignore names containing comments
if (stuffstrings.length() >= MAX_STRING_CHARS) { if (strstr(client->pers.netname, "//")
HUDPrint("The message you entered is too long.\n"); || (strstr(client->pers.netname, "/*") && strstr(client->pers.netname, "*/"))) {
return; return;
} }
if (convertedstuff.length() >= MAX_STRING_CHARS) { if (iMode == 0) {
HUDPrint("The message you entered is too long.\n"); //
return; // team message
} //
if (!IsSpectator() || g_spectate_allow_full_chat->integer) {
for (i = 0; i < game.maxclients; i++) {
ent = &g_entities[i];
// Prevent the comment glitch
// ley: The problem seems to be an issue with COM_Parse, which skips all C comments
if (strstr(client->pers.netname, "/*")) {
met_comment = true;
}
if (strstr(client->pers.netname, "//") || strstr(client->pers.netname, "*/")) {
HUDPrint("C comments ('//', '/*' and '*/') are not allowed in names.\n");
return;
}
if (IsSpectator()) {
if (mode > 0 && mode <= game.maxclients) {
const char *error =
"Message Error: Spectators are not allowed to send private messages to non-spectators.\n";
gi.SendServerCommand(client->ps.clientNum, "print \"" HUD_MESSAGE_CHAT_WHITE "%s\"", error);
return;
}
prefix = gi.LV_ConvertString("(spectator) ");
string = prefix + str(client->pers.netname) + ":" + str(stuffstrings);
} else if (IsDead()) {
if (mode > 0 && mode <= game.maxclients) {
const char *error =
"Message Error: Dead players are not allowed to send private messages to active players.\n";
gi.SendServerCommand(client->ps.clientNum, "print \"" HUD_MESSAGE_CHAT_WHITE "%s\"", error);
return;
}
prefix = gi.LV_ConvertString("(dead) ");
string = prefix + str(client->pers.netname) + ":" + str(stuffstrings);
} else {
if (mode == -1) {
string = "(team) " + str(client->pers.netname) + ":" + str(stuffstrings);
} else {
string = str(client->pers.netname) + ":" + str(stuffstrings);
}
}
if (voiceName.length()) {
if (!IsDead() && (!IsSpectator() || g_spectate_allow_full_chat->integer)) {
gentity_t *ent;
int i;
for (i = 0, ent = g_entities; i < game.maxclients; i++, ent++) {
if (!ent->inuse || !ent->entity) { if (!ent->inuse || !ent->entity) {
continue; continue;
} }
gi.SendServerCommand(i, "print \"" HUD_MESSAGE_CHAT_WHITE "%s\"", string.c_str()); gi.SendServerCommand(i, "%s", szPrintString);
if (bInstaMessage) { if (bInstaMessage) {
gi.MSG_SetClient(i); gi.MSG_SetClient(i);
@ -10195,50 +10354,122 @@ void Player::EventDMMessage(Event *ev)
gi.MSG_WriteCoord(m_vViewPos[0]); gi.MSG_WriteCoord(m_vViewPos[0]);
gi.MSG_WriteCoord(m_vViewPos[1]); gi.MSG_WriteCoord(m_vViewPos[1]);
gi.MSG_WriteCoord(m_vViewPos[2]); gi.MSG_WriteCoord(m_vViewPos[2]);
gi.MSG_WriteBits(1, 1); gi.MSG_WriteBits(qtrue, 1);
gi.MSG_WriteBits(edict - g_entities, 6); gi.MSG_WriteBits(edict - g_entities, 6);
gi.MSG_WriteString(voiceName.c_str()); gi.MSG_WriteString(sAliasName.c_str());
gi.MSG_EndCGM(); gi.MSG_EndCGM();
} }
} }
} else {
//
// send a message to spectators
//
for (i = 0; i < game.maxclients; i++) {
ent = &g_entities[i];
return;
}
}
if (mode == -1) {
int i;
gentity_t *ent;
Player *p;
// team message
for (i = 0, ent = g_entities; i < game.maxclients; i++, ent++) {
if (!ent->inuse || !ent->entity) { if (!ent->inuse || !ent->entity) {
continue; continue;
} }
p = (Player *)ent->entity; if (!static_cast<Player *>(ent->entity)->IsSpectator()) {
continue;
}
if (p->GetTeam() == GetTeam()) { gi.SendServerCommand(i, "%s", szPrintString);
gi.SendServerCommand(i, "print \"" HUD_MESSAGE_CHAT_WHITE "%s\"", string.c_str());
} }
} }
} else if (mode > 0) { } else if (iMode < 0) {
gentity_t *ent = g_entities + mode; //
// team message
//
if (IsSpectator()) {
for (i = 0; i < game.maxclients; i++) {
ent = &g_entities[i];
if (!ent->inuse || !ent->entity) {
continue;
}
if (!static_cast<Player *>(ent->entity)->IsSpectator()) {
continue;
}
gi.SendServerCommand(i, "%s", szPrintString);
}
} else {
for (i = 0; i < game.maxclients; i++) {
ent = &g_entities[i];
if (!ent->inuse || !ent->entity) {
continue;
}
if (static_cast<Player *>(ent->entity)->GetTeam() != GetTeam()) {
gi.MSG_SetClient(i);
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_VOICE_CHAT));
gi.MSG_WriteCoord(m_vViewPos[0]);
gi.MSG_WriteCoord(m_vViewPos[1]);
gi.MSG_WriteCoord(m_vViewPos[2]);
gi.MSG_WriteBits(qtrue, 1);
gi.MSG_WriteBits(edict - g_entities, 6);
gi.MSG_WriteString(sAliasName.c_str());
gi.MSG_EndCGM();
continue;
}
gi.SendServerCommand(i, "%s", szPrintString);
if (bInstaMessage) {
gi.MSG_SetClient(i);
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_VOICE_CHAT));
gi.MSG_WriteCoord(m_vViewPos[0]);
gi.MSG_WriteCoord(m_vViewPos[1]);
gi.MSG_WriteCoord(m_vViewPos[2]);
gi.MSG_WriteBits(qfalse, 1);
gi.MSG_WriteBits(edict - g_entities, 6);
gi.MSG_WriteString(sAliasName.c_str());
gi.MSG_EndCGM();
}
}
}
} else if (iMode <= game.maxclients) {
ent = &g_entities[iMode - 1];
if (!ent->inuse || !ent->entity) {
str errorString = gi.LV_ConvertString("Message Error");
str reasonString = gi.LV_ConvertString("is not a connected client");
if (mode > game.maxclients || !ent->inuse || !ent->entity) {
gi.SendServerCommand( gi.SendServerCommand(
client->ps.clientNum, edict - g_entities,
"print \"" HUD_MESSAGE_CHAT_WHITE "Message Error: %d is a bad client number\n\"", "print \"" HUD_MESSAGE_CHAT_WHITE "%s: %i %s.\"",
mode errorString.c_str(),
iMode,
reasonString.c_str()
); );
return; return;
} }
gi.SendServerCommand(client->ps.clientNum, "print \"" HUD_MESSAGE_CHAT_WHITE "%s\"", string.c_str()); gi.SendServerCommand(
} edict - g_entities,
"print \"" HUD_MESSAGE_CHAT_WHITE "%s %i:\"",
gi.LV_ConvertString("Message to player"),
iMode
);
gi.SendServerCommand(edict - g_entities, "%s", szPrintString);
} else {
str errorString = gi.LV_ConvertString("Message Error");
str reasonString = gi.LV_ConvertString("is a bad client number");
gi.SendServerCommand(mode - 1, "print \"" HUD_MESSAGE_CHAT_WHITE "%s\"", string.c_str()); gi.SendServerCommand(
edict - g_entities,
"print \"" HUD_MESSAGE_CHAT_WHITE "%s: %i %s.\"",
errorString.c_str(),
iMode,
reasonString.c_str()
);
return;
}
} }
const char *Player::GetBattleLanguageCondition() const const char *Player::GetBattleLanguageCondition() const
@ -10296,7 +10527,7 @@ const char *Player::GetBattleLanguageDirection() const
const char *Player::GetBattleLanguageLocation() const const char *Player::GetBattleLanguageLocation() const
{ {
return level.GetDMLocation(m_vViewPos).c_str(); return gi.CL_LV_ConvertString(level.GetDMLocation(m_vViewPos).c_str());
} }
const char *Player::GetBattleLanguageLocalFolks() const char *Player::GetBattleLanguageLocalFolks()