From 4a23086183b11166046c1fd99c6a8c7e6e343163 Mon Sep 17 00:00:00 2001 From: Noudess Date: Thu, 28 May 2020 08:41:10 -0400 Subject: [PATCH] Fixes to #grid show. Added new string utilities. --- common/string_util.cpp | 48 ++++++++++++++++++++++++++++++++++++++++++ common/string_util.h | 17 +++++++++++++++ zone/command.cpp | 37 ++++++++++++++++++++------------ zone/npc.cpp | 21 ++++++++++++------ zone/npc.h | 2 +- 5 files changed, 104 insertions(+), 21 deletions(-) diff --git a/common/string_util.cpp b/common/string_util.cpp index df3790def..6a4555ccf 100644 --- a/common/string_util.cpp +++ b/common/string_util.cpp @@ -527,3 +527,51 @@ bool isAlphaNumeric(const char *text) return true; } + +// Function to convert single digit or two digit number into words +std::string convert2digit(int n, std::string suffix) +{ + // if n is zero + if (n == 0) { + return ""; + } + + // split n if it is more than 19 + if (n > 19) { + return NUM_TO_ENGLISH_Y[n / 10] + NUM_TO_ENGLISH_X[n % 10] + suffix; + } + else { + return NUM_TO_ENGLISH_X[n] + suffix; + } +} + +// Function to convert a given number (max 9-digits) into words +std::string numberToWords(unsigned long long int n) +{ + // string to store word representation of given number + std::string res; + + // this handles digits at ones & tens place + res = convert2digit((n % 100), ""); + + if (n > 100 && n % 100) { + res = "and " + res; + } + + // this handles digit at hundreds place + res = convert2digit(((n / 100) % 10), "Hundred ") + res; + + // this handles digits at thousands & tens thousands place + res = convert2digit(((n / 1000) % 100), "Thousand ") + res; + + // this handles digits at hundred thousands & one millions place + res = convert2digit(((n / 100000) % 100), "Lakh, ") + res; + + // this handles digits at ten millions & hundred millions place + res = convert2digit((n / 10000000) % 100, "Crore, ") + res; + + // this handles digits at ten millions & hundred millions place + res = convert2digit((n / 1000000000) % 100, "Billion, ") + res; + + return res; +} diff --git a/common/string_util.h b/common/string_util.h index 037d6a2d8..3fb5e3ec9 100644 --- a/common/string_util.h +++ b/common/string_util.h @@ -43,6 +43,20 @@ std::vector split(std::string str_to_split, char delimiter); const std::string StringFormat(const char* format, ...); const std::string vStringFormat(const char* format, va_list args); std::string implode(std::string glue, std::vector src); +std::string convert2digit(int n, std::string suffix); +std::string numberToWords(unsigned long long int n); + +// For converstion of numerics into English +// Used for grid nodes, as NPC names remove numerals. +// But general purpose + +const std::string NUM_TO_ENGLISH_X[] = { "", "One ", "Two ", "Three ", "Four ", + "Five ", "Six ", "Seven ", "Eight ", "Nine ", "Ten ", "Eleven ", + "Twelve ", "Thirteen ", "Fourteen ", "Fifteen ", + "Sixteen ", "Seventeen ", "Eighteen ", "Nineteen " }; + +const std::string NUM_TO_ENGLISH_Y[] = { "", "", "Twenty ", "Thirty ", "Forty ", + "Fifty ", "Sixty ", "Seventy ", "Eighty ", "Ninety " }; /** * @param str @@ -189,5 +203,8 @@ uint32 hextoi(const char* num); uint64 hextoi64(const char* num); void MakeLowerString(const char *source, char *target); void RemoveApostrophes(std::string &s); +std::string convert2digit(int n, std::string suffix); +std::string numberToWords(unsigned long long int n); + #endif diff --git a/zone/command.cpp b/zone/command.cpp index 09aa704b1..eef536932 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -2438,10 +2438,10 @@ void command_grid(Client *c, const Seperator *sep) } std::string query = StringFormat( - "SELECT `x`, `y`, `z`, `heading`, `number`, `pause` " + "SELECT `x`, `y`, `z`, `heading`, `number` " "FROM `grid_entries` " "WHERE `zoneid` = %u and `gridid` = %i " - "ORDER BY `number` ", + "ORDER BY `number`", zone->GetZoneID(), target->CastToNPC()->GetGrid() ); @@ -2471,18 +2471,29 @@ void command_grid(Client *c, const Seperator *sep) /** * Spawn grid nodes */ - for (auto row = results.begin(); row != results.end(); ++row) { - auto node_position = glm::vec4(atof(row[0]), atof(row[1]), atof(row[2]), atof(row[3])); + std::map, int32> zoffset; - NPC *npc = NPC::SpawnGridNodeNPC( - target->GetCleanName(), - node_position, - static_cast(target->CastToNPC()->GetGrid()), - static_cast(atoi(row[4])), - static_cast(atoi(row[5])) - ); - npc->SetFlyMode(GravityBehavior::Flying); - npc->GMMove(node_position.x, node_position.y, node_position.z, node_position.w); + for (auto row = results.begin(); row != results.end(); ++row) { + glm::vec4 node_position = glm::vec4(atof(row[0]), atof(row[1]), atof(row[2]), atof(row[3])); + + std::vector node_loc { + node_position.x, node_position.y, node_position.z + }; + + // If we already have a node at this location, set the z offset + // higher from the existing one so we can see it. Adjust so if + // there is another at the same spot we adjust again. + auto search = zoffset.find(node_loc); + if (search != zoffset.end()) { + search->second = search->second + 3; + } + else { + zoffset[node_loc] = 0.0; + } + + node_position.z += zoffset[node_loc]; + + NPC::SpawnGridNodeNPC(node_position,atoi(row[4]),zoffset[node_loc]); } } else if (strcasecmp("delete", sep->arg[1]) == 0) { diff --git a/zone/npc.cpp b/zone/npc.cpp index 1794c6d8c..7f6754f73 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -1068,14 +1068,20 @@ bool NPC::SpawnZoneController() return true; } -NPC * NPC::SpawnGridNodeNPC(std::string name, const glm::vec4 &position, uint32 grid_id, uint32 grid_number, uint32 pause) { +void NPC::SpawnGridNodeNPC(const glm::vec4 &position, int32 grid_number, int32 zoffset) { + auto npc_type = new NPCType; memset(npc_type, 0, sizeof(NPCType)); - sprintf(npc_type->name, "%u_%u", grid_id, grid_number); - sprintf(npc_type->lastname, "Number: %u Grid: %u Pause: %u", grid_number, grid_id, pause); + std::string str_zoffset = numberToWords(zoffset); + std::string str_number= numberToWords(grid_number); - npc_type->current_hp = 4000000; + strcpy(npc_type->name, str_number.c_str()); + if (zoffset != 0) { + strcat(npc_type->name, "(Zoffset)"); + } + + npc_type->current_hp = 4000000; npc_type->max_hp = 4000000; npc_type->race = 2254; npc_type->gender = 2; @@ -1095,11 +1101,12 @@ NPC * NPC::SpawnGridNodeNPC(std::string name, const glm::vec4 &position, uint32 auto node_position = glm::vec4(position.x, position.y, position.z, position.w); auto npc = new NPC(npc_type, nullptr, node_position, GravityBehavior::Flying); + + npc->name[strlen(npc->name)-3] = (char) NULL; + npc->GiveNPCTypeData(npc_type); - entity_list.AddNPC(npc, true, true); - - return npc; + entity_list.AddNPC(npc); } NPC * NPC::SpawnNodeNPC(std::string name, std::string last_name, const glm::vec4 &position) { diff --git a/zone/npc.h b/zone/npc.h index d9f98cfc6..79a98ae94 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -112,7 +112,7 @@ public: virtual ~NPC(); static NPC *SpawnNodeNPC(std::string name, std::string last_name, const glm::vec4 &position); - static NPC *SpawnGridNodeNPC(std::string name, const glm::vec4 &position, uint32 grid_id, uint32 grid_number, uint32 pause); + static void SpawnGridNodeNPC(const glm::vec4 &position, int32 grid_number, int32 zoffset); //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQ::skills::SkillType attack_skill);