ModernUO/Projects/UOContent/Misc/InhumanSpeech.cs
Kamron Batman 8f8b650ab5
fix(core): Converts healthbar packets (#367)
- [X] Converts healthbar packets
2020-12-27 23:22:21 -08:00

596 lines
22 KiB
C#

using System;
using System.Collections.Generic;
using Server.Buffers;
namespace Server.Misc
{
[Flags]
public enum IHSFlags
{
None = 0x00,
OnDamaged = 0x01,
OnDeath = 0x02,
OnMovement = 0x04,
OnSpeech = 0x08,
All = OnDamaged | OnDeath | OnMovement
} // NOTE: To enable monster conversations, add " | OnSpeech" to the "All" line
public class InhumanSpeech
{
private static InhumanSpeech m_RatmanSpeech;
private static InhumanSpeech m_OrcSpeech;
private static InhumanSpeech m_LizardmanSpeech;
private static InhumanSpeech m_WispSpeech;
private Dictionary<string, string> m_KeywordHash;
private string[] m_Keywords;
public static InhumanSpeech Ratman
{
get
{
if (m_RatmanSpeech == null)
{
m_RatmanSpeech = new InhumanSpeech();
m_RatmanSpeech.Hue = 149;
m_RatmanSpeech.Sound = 438;
m_RatmanSpeech.Flags = IHSFlags.All;
m_RatmanSpeech.Keywords = new[]
{
"meat", "gold", "kill", "killing", "slay",
"sword", "axe", "spell", "magic", "spells",
"swords", "axes", "mace", "maces", "monster",
"monsters", "food", "run", "escape", "away",
"help", "dead", "die", "dying", "lose",
"losing", "life", "lives", "death", "ghost",
"ghosts", "british", "blackthorn", "guild",
"guilds", "dragon", "dragons", "game", "games",
"ultima", "silly", "stupid", "dumb", "idiot",
"idiots", "cheesy", "cheezy", "crazy", "dork",
"jerk", "fool", "foolish", "ugly", "insult", "scum"
};
m_RatmanSpeech.Responses = new[]
{
"meat", "kill", "pound", "crush", "yum yum",
"crunch", "destroy", "murder", "eat", "munch",
"massacre", "food", "monster", "evil", "run",
"die", "lose", "dumb", "idiot", "fool", "crazy",
"dinner", "lunch", "breakfast", "fight", "battle",
"doomed", "rip apart", "tear apart", "smash",
"edible?", "shred", "disembowel", "ugly", "smelly",
"stupid", "hideous", "smell", "tasty", "invader",
"attack", "raid", "plunder", "pillage", "treasure",
"loser", "lose", "scum"
};
m_RatmanSpeech.Syllables = new[]
{
"skrit",
"ch", "ch",
"it", "ti", "it", "ti",
"ak", "ek", "ik", "ok", "uk", "yk",
"ka", "ke", "ki", "ko", "ku", "ky",
"at", "et", "it", "ot", "ut", "yt",
"cha", "che", "chi", "cho", "chu", "chy",
"ach", "ech", "ich", "och", "uch", "ych",
"att", "ett", "itt", "ott", "utt", "ytt",
"tat", "tet", "tit", "tot", "tut", "tyt",
"tta", "tte", "tti", "tto", "ttu", "tty",
"tak", "tek", "tik", "tok", "tuk", "tyk",
"ack", "eck", "ick", "ock", "uck", "yck",
"cka", "cke", "cki", "cko", "cku", "cky",
"rak", "rek", "rik", "rok", "ruk", "ryk",
"tcha", "tche", "tchi", "tcho", "tchu", "tchy",
"rach", "rech", "rich", "roch", "ruch", "rych",
"rrap", "rrep", "rrip", "rrop", "rrup", "rryp",
"ccka", "ccke", "ccki", "ccko", "ccku", "ccky"
};
}
return m_RatmanSpeech;
}
}
public static InhumanSpeech Orc
{
get
{
if (m_OrcSpeech == null)
{
m_OrcSpeech = new InhumanSpeech();
m_OrcSpeech.Hue = 34;
m_OrcSpeech.Sound = 432;
m_OrcSpeech.Flags = IHSFlags.All;
m_OrcSpeech.Keywords = new[]
{
"meat", "gold", "kill", "killing", "slay",
"sword", "axe", "spell", "magic", "spells",
"swords", "axes", "mace", "maces", "monster",
"monsters", "food", "run", "escape", "away",
"help", "dead", "die", "dying", "lose",
"losing", "life", "lives", "death", "ghost",
"ghosts", "british", "blackthorn", "guild",
"guilds", "dragon", "dragons", "game", "games",
"ultima", "silly", "stupid", "dumb", "idiot",
"idiots", "cheesy", "cheezy", "crazy", "dork",
"jerk", "fool", "foolish", "ugly", "insult", "scum"
};
m_OrcSpeech.Responses = new[]
{
"meat", "kill", "pound", "crush", "yum yum",
"crunch", "destroy", "murder", "eat", "munch",
"massacre", "food", "monster", "evil", "run",
"die", "lose", "dumb", "idiot", "fool", "crazy",
"dinner", "lunch", "breakfast", "fight", "battle",
"doomed", "rip apart", "tear apart", "smash",
"edible?", "shred", "disembowel", "ugly", "smelly",
"stupid", "hideous", "smell", "tasty", "invader",
"attack", "raid", "plunder", "pillage", "treasure",
"loser", "lose", "scum"
};
m_OrcSpeech.Syllables = new[]
{
"bu", "du", "fu", "ju", "gu",
"ulg", "gug", "gub", "gur", "oog",
"gub", "log", "ru", "stu", "glu",
"ug", "ud", "og", "log", "ro", "flu",
"bo", "duf", "fun", "nog", "dun", "bog",
"dug", "gh", "ghu", "gho", "nug", "ig",
"igh", "ihg", "luh", "duh", "bug", "dug",
"dru", "urd", "gurt", "grut", "grunt",
"snarf", "urgle", "igg", "glu", "glug",
"foo", "bar", "baz", "ghat", "ab", "ad",
"gugh", "guk", "ag", "alm", "thu", "log",
"bilge", "augh", "gha", "gig", "goth",
"zug", "pig", "auh", "gan", "azh", "bag",
"hig", "oth", "dagh", "gulg", "ugh", "ba",
"bid", "gug", "bug", "rug", "hat", "brui",
"gagh", "buad", "buil", "buim", "bum",
"hug", "hug", "buo", "ma", "buor", "ghed",
"buu", "ca", "guk", "clog", "thurg", "car",
"cro", "thu", "da", "cuk", "gil", "cur", "dak",
"dar", "deak", "der", "dil", "dit", "at", "ag",
"dor", "gar", "dre", "tk", "dri", "gka", "rim",
"eag", "egg", "ha", "rod", "eg", "lat", "eichel",
"ek", "ep", "ka", "it", "ut", "ewk", "ba", "dagh",
"faugh", "foz", "fog", "fid", "fruk", "gag", "fub",
"fud", "fur", "bog", "fup", "hagh", "gaa", "kt",
"rekk", "lub", "lug", "tug", "gna", "urg", "l",
"gno", "gnu", "gol", "gom", "kug", "ukk", "jak",
"jek", "rukk", "jja", "akt", "nuk", "hok", "hrol",
"olm", "natz", "i", "i", "o", "u", "ikk", "ign",
"juk", "kh", "kgh", "ka", "hig", "ke", "ki", "klap",
"klu", "knod", "kod", "knu", "thnu", "krug", "nug",
"nar", "nag", "neg", "neh", "oag", "ob", "ogh", "oh",
"om", "dud", "oo", "pa", "hrak", "qo", "quad", "quil",
"ghig", "rur", "sag", "sah", "sg"
};
}
return m_OrcSpeech;
}
}
public static InhumanSpeech Lizardman
{
get
{
if (m_LizardmanSpeech == null)
{
m_LizardmanSpeech = new InhumanSpeech();
m_LizardmanSpeech.Hue = 58;
m_LizardmanSpeech.Sound = 418;
m_LizardmanSpeech.Flags = IHSFlags.All;
m_LizardmanSpeech.Keywords = new[]
{
"meat", "gold", "kill", "killing", "slay",
"sword", "axe", "spell", "magic", "spells",
"swords", "axes", "mace", "maces", "monster",
"monsters", "food", "run", "escape", "away",
"help", "dead", "die", "dying", "lose",
"losing", "life", "lives", "death", "ghost",
"ghosts", "british", "blackthorn", "guild",
"guilds", "dragon", "dragons", "game", "games",
"ultima", "silly", "stupid", "dumb", "idiot",
"idiots", "cheesy", "cheezy", "crazy", "dork",
"jerk", "fool", "foolish", "ugly", "insult", "scum"
};
m_LizardmanSpeech.Responses = new[]
{
"meat", "kill", "pound", "crush", "yum yum",
"crunch", "destroy", "murder", "eat", "munch",
"massacre", "food", "monster", "evil", "run",
"die", "lose", "dumb", "idiot", "fool", "crazy",
"dinner", "lunch", "breakfast", "fight", "battle",
"doomed", "rip apart", "tear apart", "smash",
"edible?", "shred", "disembowel", "ugly", "smelly",
"stupid", "hideous", "smell", "tasty", "invader",
"attack", "raid", "plunder", "pillage", "treasure",
"loser", "lose", "scum"
};
m_LizardmanSpeech.Syllables = new[]
{
"ss", "sth", "iss", "is", "ith", "kth",
"sith", "this", "its", "sit", "tis", "tsi",
"ssi", "sil", "lis", "sis", "lil", "thil",
"lith", "sthi", "lish", "shi", "shash", "sal",
"miss", "ra", "tha", "thes", "ses", "sas", "las",
"les", "sath", "sia", "ais", "isa", "asi", "asth",
"stha", "sthi", "isth", "asa", "ath", "tha", "als",
"sla", "thth", "ci", "ce", "cy", "yss", "ys", "yth",
"syth", "thys", "yts", "syt", "tys", "tsy", "ssy",
"syl", "lys", "sys", "lyl", "thyl", "lyth", "sthy",
"lysh", "shy", "myss", "ysa", "sthy", "ysth"
};
}
return m_LizardmanSpeech;
}
}
public static InhumanSpeech Wisp
{
get
{
if (m_WispSpeech == null)
{
m_WispSpeech = new InhumanSpeech();
m_WispSpeech.Hue = 89;
m_WispSpeech.Sound = 466;
m_WispSpeech.Flags = IHSFlags.OnMovement;
m_WispSpeech.Syllables = new[]
{
"b", "c", "d", "f", "g", "h", "i",
"j", "k", "l", "m", "n", "p", "r",
"s", "t", "v", "w", "x", "z", "c",
"c", "x", "x", "x", "x", "x", "y",
"y", "y", "y", "t", "t", "k", "k",
"l", "l", "m", "m", "m", "m", "z"
};
}
return m_WispSpeech;
}
}
public string[] Syllables { get; set; }
public string[] Keywords
{
get => m_Keywords;
set
{
m_Keywords = value;
m_KeywordHash = new Dictionary<string, string>(m_Keywords.Length, StringComparer.OrdinalIgnoreCase);
for (var i = 0; i < m_Keywords.Length; ++i)
{
m_KeywordHash[m_Keywords[i]] = m_Keywords[i];
}
}
}
public string[] Responses { get; set; }
public int Hue { get; set; }
public int Sound { get; set; }
public IHSFlags Flags { get; set; }
public string GetRandomSyllable() => Syllables.RandomElement();
public string ConstructWord(int syllableCount)
{
var syllables = new string[syllableCount];
for (var i = 0; i < syllableCount; ++i)
{
syllables[i] = GetRandomSyllable();
}
return string.Concat(syllables);
}
// TODO: Should be changed a preset table that is built
public string ConstructSentence(int wordCount)
{
using var sentence = new ValueStringBuilder(stackalloc char[256]);
var needUpperCase = true;
for (var i = 0; i < wordCount; ++i)
{
if (i > 0) // not first word)
{
var random = Utility.RandomMinMax(1, 15);
if (random < 11)
{
sentence.Append(' ');
}
else
{
needUpperCase = true;
sentence.Append(random > 13 ? "! " : ". ");
}
}
var syllableCount = Utility.Random(1, Utility.Random(100) < 30 ? 5 : 3);
var word = ConstructWord(syllableCount);
sentence.Append(word);
if (needUpperCase)
{
sentence.Replace(word[0], char.ToUpper(word[0]), sentence.Length - word.Length, 1);
}
needUpperCase = false;
}
sentence.Append(Utility.RandomMinMax(1, 5) == 1 ? '!' : '.');
return sentence.ToString();
}
public void SayRandomTranslate(Mobile mob, params string[] sentancesInEnglish)
{
SaySentance(mob, Utility.RandomMinMax(2, 3));
mob.Say(sentancesInEnglish.RandomElement());
}
private string GetRandomResponseWord(List<string> keywordsFound)
{
var random = Utility.Random(keywordsFound.Count + Responses.Length);
return random < keywordsFound.Count ? keywordsFound[random] : Responses[random - keywordsFound.Count];
}
public bool OnSpeech(Mobile mob, Mobile speaker, string text)
{
if ((Flags & IHSFlags.OnSpeech) == 0 || m_Keywords == null || Responses == null || m_KeywordHash == null)
{
return false; // not enabled
}
if (!speaker.Alive)
{
return false;
}
if (!speaker.InRange(mob, 3))
{
return false;
}
if ((speaker.Direction & Direction.Mask) != speaker.GetDirectionTo(mob))
{
return false;
}
if ((mob.Direction & Direction.Mask) != mob.GetDirectionTo(speaker))
{
return false;
}
var split = text.Split(' ');
var keywordsFound = new List<string>();
for (var i = 0; i < split.Length; ++i)
{
if (m_KeywordHash.TryGetValue(split[i], out var keyword))
{
keywordsFound.Add(keyword);
}
}
if (keywordsFound.Count > 0)
{
var responseWord = Utility.RandomBool() ?
GetRandomResponseWord(keywordsFound) : keywordsFound.RandomElement();
var secondResponseWord = GetRandomResponseWord(keywordsFound);
using var response = new ValueStringBuilder(stackalloc char[256]);
switch (Utility.Random(6))
{
default:
case 0:
{
response.Append("Me ");
response.Append(responseWord);
response.Append('?');
break;
}
case 1:
{
response.Append(responseWord);
response.Append(" thee!");
response.Replace(responseWord[0], char.ToUpper(responseWord[0]), 0, 1);
break;
}
case 2:
{
response.Append(responseWord);
response.Append('?');
response.Replace(responseWord[0], char.ToUpper(responseWord[0]), 0, 1);
break;
}
case 3:
{
response.Append(responseWord);
response.Append("! ");
response.Append(secondResponseWord);
response.Append('.');
response.Replace(responseWord[0], char.ToUpper(responseWord[0]), 0, 1);
response.Replace(
secondResponseWord[0],
char.ToUpper(secondResponseWord[0]),
responseWord.Length + 2,
1
);
break;
}
case 4:
{
response.Append(responseWord);
response.Append('.');
response.Replace(responseWord[0], char.ToUpper(responseWord[0]), 0, 1);
break;
}
case 5:
{
response.Append(responseWord);
response.Append("? ");
response.Append(secondResponseWord);
response.Append('.');
response.Replace(responseWord[0], char.ToUpper(responseWord[0]), 0, 1);
response.Replace(
secondResponseWord[0],
char.ToUpper(secondResponseWord[0]),
responseWord.Length + 2,
1
);
break;
}
}
var maxWords = Math.Clamp(split.Length / 2 + 1, 2, 6);
SaySentance(mob, Utility.RandomMinMax(2, maxWords));
mob.Say(response.ToString());
return true;
}
return false;
}
public void OnDeath(Mobile mob)
{
if ((Flags & IHSFlags.OnDeath) == 0)
{
return; // not enabled
}
if (Utility.Random(100) < 90)
{
return; // 90% chance to do nothing; 10% chance to talk
}
SayRandomTranslate(
mob,
"Revenge!",
"NOOooo!",
"I... I...",
"Me no die!",
"Me die!",
"Must... not die...",
"Oooh, me hurt...",
"Me dying?"
);
}
public void OnMovement(Mobile mob, Mobile mover, Point3D oldLocation)
{
if ((Flags & IHSFlags.OnMovement) == 0)
{
return; // not enabled
}
if (!mover.Player || mover.Hidden && mover.AccessLevel > AccessLevel.Player)
{
return;
}
if (!mob.InRange(mover, 5) || mob.InRange(oldLocation, 5))
{
return; // only talk when they enter 5 tile range
}
if (Utility.Random(100) < 90)
{
return; // 90% chance to do nothing; 10% chance to talk
}
SaySentance(mob, 6);
}
public void OnDamage(Mobile mob, int amount)
{
if ((Flags & IHSFlags.OnDamaged) == 0)
{
return; // not enabled
}
if (Utility.Random(100) < 90)
{
return; // 90% chance to do nothing; 10% chance to talk
}
if (amount < 5)
{
SayRandomTranslate(
mob,
"Ouch!",
"Me not hurt bad!",
"Thou fight bad.",
"Thy blows soft!",
"You bad with weapon!"
);
}
else
{
SayRandomTranslate(
mob,
"Ouch! Me hurt!",
"No, kill me not!",
"Me hurt!",
"Away with thee!",
"Oof! That hurt!",
"Aaah! That hurt...",
"Good blow!"
);
}
}
public void OnConstruct(Mobile mob)
{
mob.SpeechHue = Hue;
}
public void SaySentance(Mobile mob, int wordCount)
{
mob.Say(ConstructSentence(wordCount));
mob.PlaySound(Sound);
}
}
}