Skip to content
Merged
114 changes: 104 additions & 10 deletions addons/sourcemod/scripting/shared/npcs.sp
Original file line number Diff line number Diff line change
Expand Up @@ -2813,12 +2813,28 @@ stock int StrLenMB(const char[] str)
*/

#if defined ZR
void PrintNPCMessageWithPrefixes(int entity, const char[] color, const char[] message, bool messageIsTranslated = false)
void PrintNPCMessageWithPrefixes(int entity, const char[] npcColor, const char[] message, bool messageIsTranslated = false, const char[] customName = "", const char[] messageColor = "default", bool customNameIsTranslated = false)
{
if (c_NpcName[entity][0] == '\0')
{
// This NPC has no name! It might have not been fully initialized yet, try again until it has a name
DataPack pack = new DataPack();
RequestFrame(PrintNPCMessageWithPrefixes_Delay, pack);
pack.WriteCell(EntIndexToEntRef(entity));
pack.WriteString(npcColor);
pack.WriteString(message);
pack.WriteCell(messageIsTranslated);
pack.WriteString(customName);
pack.WriteString(messageColor);
pack.WriteCell(customNameIsTranslated);

return;
}

bool checkedForPrefixes;
bool loud;
char finalColor[32];
char finalMessage[255];
char finalNpcColor[32], finalMessageColor[32];
char finalName[256], finalMessage[256];

// Only copy the message once if it's not translated
if (!messageIsTranslated)
Expand All @@ -2841,20 +2857,44 @@ void PrintNPCMessageWithPrefixes(int entity, const char[] color, const char[] me
if (HasSpecificBuff(entity, "Verde"))
{
// verd e
finalColor = "forestgreen";
finalNpcColor = "forestgreen";
}
else if (HasSpecificBuff(entity, "Ragebaiter Prefix"))
{
// To match the rest of ragebaiter text
finalColor = "crimson";
finalNpcColor = "crimson";
}

if (HasSpecificBuff(entity, "Loud Prefix"))
loud = true;
}

if (finalColor[0] == '\0')
strcopy(finalColor, sizeof(finalColor), color);
if (finalNpcColor[0] == '\0')
{
FormatEx(finalNpcColor, sizeof(finalNpcColor), "{%s}", npcColor);
}
else
{
Format(finalNpcColor, sizeof(finalNpcColor), "{%s}", finalNpcColor);
}

// Sometimes colors are defined with {}, sometimes without... get rid of dupes to accommodate for everything
ReplaceString(finalNpcColor, sizeof(finalNpcColor), "{{", "{");
ReplaceString(finalNpcColor, sizeof(finalNpcColor), "}}", "}");

if (finalMessageColor[0] == '\0')
{
FormatEx(finalMessageColor, sizeof(finalMessageColor), "{%s}", messageColor);
}
else
{
Format(finalMessageColor, sizeof(finalMessageColor), "{%s}", finalMessageColor);
}

// Sometimes colors are defined with {}, sometimes without... get rid of dupes to accommodate for everything
ReplaceString(finalMessageColor, sizeof(finalMessageColor), "{{", "{");
ReplaceString(finalMessageColor, sizeof(finalMessageColor), "}}", "}");


if (!messageIsTranslated && loud)
StringToUpper(finalMessage);
Expand All @@ -2871,10 +2911,64 @@ void PrintNPCMessageWithPrefixes(int entity, const char[] color, const char[] me
StringToUpper(finalMessage);
}

if (!b_NameNoTranslation[entity])
CPrintToChat(client, "{%s}%s%s{default}: %s", finalColor, prefix, c_NpcName[entity], finalMessage);
bool isCustomName = customName[0] != '\0';
if (isCustomName)
{
if (customNameIsTranslated)
FormatEx(finalName, sizeof(finalName), "%T", customName, client);
else
strcopy(finalName, sizeof(finalName), customName);
}
else
CPrintToChat(client, "{%s}%s%t{default}: %s", finalColor, prefix, c_NpcName[entity], finalMessage);
{
if (!b_NameNoTranslation[entity])
FormatEx(finalName, sizeof(finalName), "%T", c_NpcName[entity], client);
else
strcopy(finalName, sizeof(finalName), c_NpcName[entity]);
}

char fullText[512];
FormatEx(fullText, sizeof(fullText), "%s%s%s%s: %s", finalNpcColor, prefix, finalName, finalMessageColor, finalMessage);

if (strlen(fullText) > 250)
{
// Some translations or way too many prefixes might make messages overflow. Split them!
char splitName[256], splitMessage[256];
FormatEx(splitName, sizeof(splitName), "%s%s%s%s:", finalNpcColor, prefix, finalName, finalMessageColor);
FormatEx(splitMessage, sizeof(splitMessage), "%s%s", finalMessageColor, finalMessage);

CPrintToChat(client, splitName);
CPrintToChat(client, splitMessage);
}
else
{
CPrintToChat(client, fullText);
}
}
}

void PrintNPCMessageWithPrefixes_Delay(DataPack pack)
{
pack.Reset();

int entity = EntRefToEntIndex(pack.ReadCell());
if (entity == INVALID_ENT_REFERENCE || b_NpcHasDied[entity])
{
delete pack;
return;
}

char message[255], npcColor[32], messageColor[32], customName[255];

pack.ReadString(npcColor, sizeof(npcColor));
pack.ReadString(message, sizeof(message));
bool messageIsTranslated = pack.ReadCell();
pack.ReadString(customName, sizeof(customName));
pack.ReadString(messageColor, sizeof(messageColor));
bool customNameIsTranslated = pack.ReadCell();

delete pack;

PrintNPCMessageWithPrefixes(entity, npcColor, message, messageIsTranslated, customName, messageColor, customNameIsTranslated);
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ methodmap Donnerkrieg < CClotBody
func_NPCDeath[npc.index] = view_as<Function>(Internal_NPCDeath);
func_NPCOnTakeDamage[npc.index] = view_as<Function>(Internal_OnTakeDamage);
func_NPCThink[npc.index] = view_as<Function>(Internal_ClotThink);

g_b_donner_died=false;

b_enraged=false;
Expand Down Expand Up @@ -205,7 +205,7 @@ methodmap Donnerkrieg < CClotBody

EmitSoundToAll("mvm/mvm_tele_deliver.wav");

CPrintToChatAll("{crimson}Donnerkrieg{default}: I have arrived to render judgement");
NPCTalkMessage(npc.index, "I have arrived to render judgement");

g_b_angered=false;

Expand All @@ -226,6 +226,17 @@ methodmap Donnerkrieg < CClotBody
}
}

static void NPCTalkMessage(int iNPC, const char[] message, bool identityRevealed = false)
{
if (identityRevealed)
{
PrintNPCMessageWithPrefixes(iNPC, "aqua", message, .customName = "Stella", .messageColor = "snow", .customNameIsTranslated = true);
}
else
{
PrintNPCMessageWithPrefixes(iNPC, "crimson", message);
}
}

static void Internal_ClotThink(int iNPC)
{
Expand Down Expand Up @@ -321,11 +332,11 @@ static void Internal_ClotThink(int iNPC)
}
if(GameTime > g_f_blitz_dialogue_timesincehasbeenhurt)
{
CPrintToChatAll("{crimson}Donnerkrieg{default}: Blitzkrieg's army is happy to serve you as thanks for setting us free...");
NPCTalkMessage(npc.index, "Blitzkrieg's army is happy to serve you as thanks for setting us free...");
npc.m_bDissapearOnDeath = true;

CPrintToChatAll("{aqua}Stella{snow}: Oh also our true names are, {aqua}Stella{snow}, that's me.");
CPrintToChatAll("{aqua}Stella{snow}: And he's {crimson}Karlas{snow}!");
NPCTalkMessage(npc.index, "Oh also our true names are, {aqua}Stella{snow}, that's me.", true);
NPCTalkMessage(npc.index, "And he's {crimson}Karlas{snow}!", true);

RequestFrame(KillNpc, EntIndexToEntRef(npc.index));
for (int client = 1; client <= MaxClients; client++)
Expand All @@ -340,42 +351,42 @@ static void Internal_ClotThink(int iNPC)
else if(GameTime + 3.0 > g_f_blitz_dialogue_timesincehasbeenhurt && i_SaidLineAlready[npc.index] < 8)
{
i_SaidLineAlready[npc.index] = 8;
CPrintToChatAll("{crimson}Donnerkrieg{default}: With Blitzkrieg gone, the army has been set free, and so...");
NPCTalkMessage(npc.index, "With Blitzkrieg gone, the army has been set free, and so...");
}
else if(GameTime + 5.0 > g_f_blitz_dialogue_timesincehasbeenhurt && i_SaidLineAlready[npc.index] < 7)
{
i_SaidLineAlready[npc.index] = 7;
CPrintToChatAll("{crimson}Donnerkrieg{default}: However, that doesn't matter anymore.");
NPCTalkMessage(npc.index, "However, that doesn't matter anymore.");
}
else if(GameTime + 8.0 > g_f_blitz_dialogue_timesincehasbeenhurt && i_SaidLineAlready[npc.index] < 6)
{
i_SaidLineAlready[npc.index] = 6;
CPrintToChatAll("{crimson}Donnerkrieg{default}: The corruption had fully gotten to him.");
NPCTalkMessage(npc.index, "The corruption had fully gotten to him.");
}
else if(GameTime + 10.0 > g_f_blitz_dialogue_timesincehasbeenhurt && i_SaidLineAlready[npc.index] < 5)
{
i_SaidLineAlready[npc.index] = 5;
CPrintToChatAll("{crimson}Donnerkrieg{default}: If we hadn't complied he would have destroyed us.");
NPCTalkMessage(npc.index, "If we hadn't complied he would have destroyed us.");
}
else if(GameTime + 12.0 > g_f_blitz_dialogue_timesincehasbeenhurt && i_SaidLineAlready[npc.index] < 4)
{
i_SaidLineAlready[npc.index] = 4;
CPrintToChatAll("{crimson}Donnerkrieg{default}: We had no choice.");
NPCTalkMessage(npc.index, "We had no choice.");
}
else if(GameTime + 14.0 > g_f_blitz_dialogue_timesincehasbeenhurt && i_SaidLineAlready[npc.index] < 3)
{
i_SaidLineAlready[npc.index] = 3;
CPrintToChatAll("{crimson}Donnerkrieg{default}: We don't have to fight anymore, for you see...");
NPCTalkMessage(npc.index, "We don't have to fight anymore, for you see...");
}
else if(GameTime + 16.0 > g_f_blitz_dialogue_timesincehasbeenhurt && i_SaidLineAlready[npc.index] < 2)
{
i_SaidLineAlready[npc.index] = 2;
CPrintToChatAll("{crimson}Donnerkrieg{default}: You stopped The rouge machine.");
NPCTalkMessage(npc.index, "You stopped The rouge machine.");
}
else if(GameTime + 18.0 > g_f_blitz_dialogue_timesincehasbeenhurt && i_SaidLineAlready[npc.index] < 1)
{
i_SaidLineAlready[npc.index] = 1;
CPrintToChatAll("{crimson}Donnerkrieg{default}: Wait no, please stop.");
NPCTalkMessage(npc.index, "Wait no, please stop.");
ReviveAll(true);
}
}
Expand Down Expand Up @@ -611,40 +622,40 @@ static void Donnerkrieg_Nightmare_Logic(int ref, int PrimaryThreatIndex)
{
case 1:
{
CPrintToChatAll("{crimson}Donnerkrieg{default}: {crimson}That's it, {default}I'm going to kill you.");
NPCTalkMessage(npc.index, "{crimson}That's it, {default}I'm going to kill you.");
}
case 2:
{
CPrintToChatAll("{crimson}Donnerkrieg{default}: {crimson}Hm, {default}wonder how this will end...");
NPCTalkMessage(npc.index, "{crimson}Hm, {default}wonder how this will end...");
}
case 3:
{
CPrintToChatAll("{crimson}Donnerkrieg{default}: {crimson}PREPARE {default}Thyself, {yellow}Judgement {default}is near.");
NPCTalkMessage(npc.index, "{crimson}PREPARE {default}Thyself, {yellow}Judgement {default}is near.");
}
case 4:
{
switch(GetRandomInt(0,10))
{
case 5:
{
CPrintToChatAll("{crimson}Donnerkrieg{default}: Oh not again, now train's gone and {crimson}left{default}.");
NPCTalkMessage(npc.index, "Oh not again, now train's gone and {crimson}left{default}.");
npc.m_bFUCKYOU_move_anim = true;
}
default:
{
CPrintToChatAll("{crimson}Donnerkrieg{default}: Oh not again, now cannon's gone and {crimson}recharged{default}.");
NPCTalkMessage(npc.index, "Oh not again, now cannon's gone and {crimson}recharged{default}.");
}

}
}
case 5:
{
CPrintToChatAll("{crimson}Donnerkrieg{default}: Aiming this thing is actually quite {crimson}complex {default}ya know.");
NPCTalkMessage(npc.index, "Aiming this thing is actually quite {crimson}complex {default}ya know.");
npc.m_bFUCKYOU = true;
}
case 6:
{
CPrintToChatAll("{crimson}Donnerkrieg{default}: Ya know, I'm getting quite bored of {crimson}this.");
NPCTalkMessage(npc.index, "Ya know, I'm getting quite bored of {crimson}this.");
}
}

Expand Down Expand Up @@ -672,29 +683,29 @@ static void Donnerkrieg_Nightmare_Logic(int ref, int PrimaryThreatIndex)
{
case 1:
{
CPrintToChatAll("{crimson}Donnerkrieg{default}: {crimson}NIGHTMARE, CANNON!");
NPCTalkMessage(npc.index, "{crimson}NIGHTMARE, CANNON!");
}
case 2:
{
CPrintToChatAll("{crimson}Donnerkrieg{default}: {crimson}JUDGEMENT BE UPON THEE!");
NPCTalkMessage(npc.index, "{crimson}JUDGEMENT BE UPON THEE!");
}
case 3:
{
CPrintToChatAll("{crimson}Donnerkrieg{default}: {crimson}Annihilation!");
NPCTalkMessage(npc.index, "{crimson}Annihilation!");
}
}
}
else
{
if(npc.m_bFUCKYOU_move_anim)
{
CPrintToChatAll("{crimson}Donnerkrieg{default}: {crimson}And the city's too far to walk to the end while I...");
NPCTalkMessage(npc.index, "{crimson}And the city's too far to walk to the end while I...");
npc.m_bFUCKYOU_move_anim = false;
}
else if(npc.m_bFUCKYOU)
{
npc.m_bFUCKYOU = false;
CPrintToChatAll("{crimson}Donnerkrieg{default}: However it's still{crimson} worth the effort.");
NPCTalkMessage(npc.index, "However it's still{crimson} worth the effort.");
}

}
Expand Down
12 changes: 8 additions & 4 deletions addons/sourcemod/scripting/zombie_riot/npc/alt/npc_alt_kahml.sp
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,10 @@ methodmap Kahmlstein < CClotBody
}
}

static void NPCTalkMessage(int iNPC, const char[] message)
{
PrintNPCMessageWithPrefixes(iNPC, "blue", message);
}

static void Internal_ClotThink(int iNPC)
{
Expand Down Expand Up @@ -562,7 +566,7 @@ static void Internal_ClotThink(int iNPC)
fl_attack_timeout[npc.index]=GameTime + 0.5;
EmitSoundToAll("mvm/mvm_tank_horn.wav");
EmitSoundToAll("vo/heavy_domination16.mp3");
CPrintToChatAll("{blue}Kahmlstein{default}: {crimson}I Will BREAK YOU");
NPCTalkMessage(npc.index, "{crimson}I Will BREAK YOU");
fl_kahml_combo_reset_timer[npc.index] = GameTime + 12.5;
i_kahml_combo_offest[npc.index]++;
if(IsValidEntity(npc.m_iWearable1))
Expand Down Expand Up @@ -621,7 +625,7 @@ static void Internal_ClotThink(int iNPC)
}
if(fl_kahml_nano_reset[npc.index] <= GameTime && !b_kahml_annihilation[npc.index] && !b_kahml_inNANOMACHINESSON[npc.index])
{
CPrintToChatAll("{blue}Kahmlstein{default}: I don't have time for this.");
NPCTalkMessage(npc.index, "I don't have time for this.");
fl_kahml_main_melee_damage[npc.index] = 20.0 * fl_kahml_galactic_strenght[npc.index];
fl_kahml_bulletres[npc.index] = 0.75;
fl_kahml_meleeres[npc.index] = 0.9;
Expand Down Expand Up @@ -655,7 +659,7 @@ static void Internal_ClotThink(int iNPC)
fl_kahml_bulletres[npc.index] = 1.0;
fl_kahml_meleeres[npc.index] = 1.0;
fl_kahml_melee_speed[npc.index] = 0.4;
CPrintToChatAll("{blue}Kahmlstein{default}: You Lived, Good work.");
NPCTalkMessage(npc.index, "You Lived, Good work.");
fl_kahml_nano_reset[npc.index] = 120.0 + GameTime;
fl_kahml_combo_reset_timer[npc.index] = 60.0 + GameTime;
i_kahml_combo_offest[npc.index] = 0;
Expand Down Expand Up @@ -937,7 +941,7 @@ static void Internal_NPCDeath(int entity)
npc.PlayDeathSound();
float WorldSpaceVec[3]; WorldSpaceCenter(npc.index, WorldSpaceVec);
ParticleEffectAt(WorldSpaceVec, "teleported_blue", 0.5);
CPrintToChatAll("{blue}Kahmlstein{default}: You're boring me, im leaving.");
NPCTalkMessage(npc.index, "You're boring me, im leaving.");

if(npc.index==EntRefToEntIndex(RaidBossActive))
RaidBossActive=INVALID_ENT_REFERENCE;
Expand Down
Loading
Loading