From 89be55254ea229234752763d364b75d431b68347 Mon Sep 17 00:00:00 2001 From: catapultam-habeo <97849758+catapultam-habeo@users.noreply.github.com> Date: Mon, 26 Feb 2024 23:15:40 -0600 Subject: [PATCH] [Character Creation] Improved Random Name Generator (#4081) * test against vanilla branch * use existing methods to validate name instead of raw sql * Revert "use existing methods to validate name instead of raw sql" This reverts commit 43750c6f4f597864f3e433885f9e3f84144e3d65. * ReserveName doesn't work like that. Oops. Well, check against Name Filter at least. * That db access condition was wrong. * that isn't how CheckNameFilter works, either. * apply editorconfig w/ trivial change * Actually apply editorconfig changes. --- world/client.cpp | 114 ++++++++++++++++++++--------------------------- 1 file changed, 49 insertions(+), 65 deletions(-) diff --git a/world/client.cpp b/world/client.cpp index fe4b6f5fc..b39a00a89 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -599,79 +599,63 @@ bool Client::HandleNameApprovalPacket(const EQApplicationPacket *app) } bool Client::HandleGenerateRandomNamePacket(const EQApplicationPacket *app) { - // creates up to a 10 char name - char vowels[18]="aeiouyaeiouaeioe"; - char cons[48]="bcdfghjklmnpqrstvwxzybcdgklmnprstvwbcdgkpstrkd"; - char rndname[17]="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; - char paircons[33]="ngrkndstshthphsktrdrbrgrfrclcr"; - int rndnum=emu_random.Int(0, 75),n=1; - bool dlc=false; - bool vwl=false; - bool dbl=false; - if (rndnum>63) - { // rndnum is 0 - 75 where 64-75 is cons pair, 17-63 is cons, 0-16 is vowel - rndnum=(rndnum-61)*2; // name can't start with "ng" "nd" or "rk" - rndname[0]=paircons[rndnum]; - rndname[1]=paircons[rndnum+1]; - n=2; - } - else if (rndnum>16) - { - rndnum-=17; - rndname[0]=cons[rndnum]; - } - else - { - rndname[0]=vowels[rndnum]; - vwl=true; - } - int namlen=emu_random.Int(5, 10); - for (int i=n;i46) - { // pick a cons pair - if (i>namlen-3) // last 2 chars in name? - { // name can only end in cons pair "rk" "st" "sh" "th" "ph" "sk" "nd" or "ng" - rndnum=emu_random.Int(0, 7)*2; - } - else - { // pick any from the set - rndnum=(rndnum-47)*2; - } - rndname[i]=paircons[rndnum]; - rndname[i+1]=paircons[rndnum+1]; - dlc=true; // flag keeps second letter from being doubled below - i+=1; - } - else - { // select a single cons - rndname[i]=cons[rndnum]; + char newName[17] = {0}; + bool unique = false; + + while (!unique) { + std::string cons = "bcdfghjklmnpqrstvwxyz"; + std::string vows = "aeou"; + std::string allVows = "aeiou"; + std::vector endPhon = {"a", "e", "i", "o", "u", "os", "as", "us", "is", "y", "an", "en", "in", "on", "un"}; + + std::random_device rd; + std::mt19937 gen(rd()); + + std::uniform_int_distribution lenDist(5, 10); + std::uniform_int_distribution firstCharDist(0, 1); + std::uniform_int_distribution consDist(0, cons.size() - 1); + std::uniform_int_distribution vowDist(0, vows.size() - 1); + std::uniform_int_distribution allVowDist(0, allVows.size() - 1); + std::uniform_int_distribution endPhonDist(0, endPhon.size() - 1); + + int len = 0; + memset(newName, 0, sizeof(newName)); + + if (firstCharDist(gen) == 0) { + newName[len++] = vows[vowDist(gen)]; + newName[len++] = cons[consDist(gen)]; + } else { + newName[len++] = cons[consDist(gen)]; + newName[len++] = allVows[allVowDist(gen)]; + } + + newName[0] = toupper(newName[0]); + + while (len < lenDist(gen) - 1) { + if (len % 2 == 0) { + newName[len++] = cons[consDist(gen)]; + } else { + newName[len++] = allVows[allVowDist(gen)]; } } - else - { // select a vowel - rndname[i]=vowels[emu_random.Int(0, 16)]; + + std::string end = endPhon[endPhonDist(gen)]; + for (char c : end) { + if (len < 10) newName[len++] = c; } - vwl=!vwl; - if (!dbl && !dlc) - { // one chance at double letters in name - if (!emu_random.Int(0, i+9)) // chances decrease towards end of name - { - rndname[i+1]=rndname[i]; - dbl=true; - i+=1; + + if (database.CheckNameFilter(newName)) { + std::string query = StringFormat("SELECT `name` FROM `character_data` WHERE `name` = '%s'", newName); + auto res = database.QueryDatabase(query); + if (res.Success() && res.RowCount() == 0) { + unique = true; } } } - rndname[0]=toupper(rndname[0]); NameGeneration_Struct* ngs = (NameGeneration_Struct*)app->pBuffer; - memset(ngs->name,0,64); - strcpy(ngs->name,rndname); + memset(ngs->name, 0, 64); + strcpy(ngs->name, newName); QueuePacket(app); return true;