diff --git a/common/strings.cpp b/common/strings.cpp index 4ecb178ec..b4cf5d011 100644 --- a/common/strings.cpp +++ b/common/strings.cpp @@ -695,8 +695,31 @@ std::string Strings::ConvertToDigit(int n, const std::string& suffix) return NUM_TO_ENGLISH_X[n] + suffix; } } + +bool Strings::BeginsWith(const std::string& subject, const std::string& search) +{ + if (subject.length() < search.length()) { + return false; + } + + return subject.starts_with(search); +} + +bool Strings::EndsWith(const std::string& subject, const std::string& search) +{ + if (subject.length() < search.length()) { + return false; + } + + return subject.ends_with(search); +} + bool Strings::Contains(const std::string& subject, const std::string& search) { + if (subject.length() < search.length()) { + return false; + } + return subject.find(search) != std::string::npos; } diff --git a/common/strings.h b/common/strings.h index 3cf30cb31..0ef35f93f 100644 --- a/common/strings.h +++ b/common/strings.h @@ -128,6 +128,8 @@ public: static bool ToBool(const std::string& bool_string); static inline bool EqualFold(const std::string &string_one, const std::string &string_two) { return strcasecmp(string_one.c_str(), string_two.c_str()) == 0; } static std::string Random(size_t length); + static bool BeginsWith(const std::string& subject, const std::string& search); + static bool EndsWith(const std::string& subject, const std::string& search); template static std::string diff --git a/zone/client.cpp b/zone/client.cpp index bb920435f..a74a922df 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -5939,90 +5939,64 @@ void Client::AdventureFinish(bool win, int theme, int points) FastQueuePacket(&outapp); } -void Client::CheckLDoNHail(Mob *target) +void Client::CheckLDoNHail(NPC* n) { - if(!zone->adv_data) - { + if (!zone->adv_data || !n || n->GetOwnerID()) { return; } - if(!target || !target->IsNPC()) - { + auto* ds = (ServerZoneAdventureDataReply_Struct*) zone->adv_data; + if (ds->type != Adventure_Rescue || ds->data_id != n->GetNPCTypeID()) { return; } - if(target->GetOwnerID() != 0) - { + if (entity_list.CheckNPCsClose(n)) { + n->Say( + "You're here to save me? I couldn't possibly risk leaving yet. There are " + "far too many of those horrid things out there waiting to recapture me! Please get " + "rid of some more of those vermin and then we can try to leave." + ); return; } - ServerZoneAdventureDataReply_Struct* ds = (ServerZoneAdventureDataReply_Struct*)zone->adv_data; - if(ds->type != Adventure_Rescue) - { - return; - } - - if(ds->data_id != target->GetNPCTypeID()) - { - return; - } - - if(entity_list.CheckNPCsClose(target) != 0) - { - target->Say("You're here to save me? I couldn't possibly risk leaving yet. There are " - "far too many of those horrid things out there waiting to recapture me! Please get" - " rid of some more of those vermin and then we can try to leave."); - return; - } - - Mob *pet = GetPet(); - if(pet) - { - if(pet->GetPetType() == petCharmed) - { + auto pet = GetPet(); + if (pet) { + if (pet->GetPetType() == petCharmed) { pet->BuffFadeByEffect(SE_Charm); - } - else if(pet->GetPetType() == petNPCFollow) - { + } else if (pet->GetPetType() == petNPCFollow) { pet->SetOwnerID(0); - } - else - { + } else { pet->Depop(); } } - SetPet(target); - target->SetOwnerID(GetID()); - target->Say("Wonderful! Someone to set me free! I feared for my life for so long," - " never knowing when they might choose to end my life. Now that you're here though" - " I can rest easy. Please help me find my way out of here as soon as you can" - " I'll stay close behind you!"); + SetPet(n); + n->SetOwnerID(GetID()); + n->Say( + "Wonderful! Someone to set me free! I feared for my life for so long, " + "never knowing when they might choose to end my life. Now that you're here though " + "I can rest easy. Please help me find my way out of here as soon as you can " + "I'll stay close behind you!" + ); } -void Client::CheckEmoteHail(Mob *target, const char* message) +void Client::CheckEmoteHail(NPC* n, const char* message) { - if( - (message[0] != 'H' && - message[0] != 'h') || - message[1] != 'a' || - message[2] != 'i' || - message[3] != 'l'){ + if ( + !Strings::BeginsWith(message, "hail") && + !Strings::BeginsWith(message, "Hail") + ) { return; } - if(!target || !target->IsNPC()) - { + if (!n || n->GetOwnerID()) { return; } - if(target->GetOwnerID() != 0) - { - return; + const auto emote_id = n->GetEmoteID(); + if (emote_id) { + n->DoNPCEmote(EQ::constants::EmoteEventTypes::Hailed, emote_id); } - uint32 emoteid = target->GetEmoteID(); - if(emoteid != 0) - target->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::Hailed, emoteid); } void Client::MarkSingleCompassLoc(float in_x, float in_y, float in_z, uint8 count) diff --git a/zone/client.h b/zone/client.h index a2c966e3b..c4ef78ca3 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1360,8 +1360,8 @@ public: uint32 GetLDoNLossesTheme(uint32 t); uint32 GetLDoNPointsTheme(uint32 t); void UpdateLDoNWinLoss(uint32 theme_id, bool win = false, bool remove = false); - void CheckLDoNHail(Mob *target); - void CheckEmoteHail(Mob *target, const char* message); + void CheckLDoNHail(NPC* n); + void CheckEmoteHail(NPC* n, const char* message); void HandleLDoNOpen(NPC *target); void HandleLDoNSenseTraps(NPC *target, uint16 skill, uint8 type); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 2043ad57a..fb3b00a6b 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -9147,8 +9147,14 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) } else if (inst->IsClassCommon()) { - if (!RuleB(Skills, RequireTomeHandin) && item->ItemType == EQ::item::ItemTypeSpell && (strstr((const char*)item->Name, "Tome of ") || strstr((const char*)item->Name, "Skill: "))) - { + if ( + !RuleB(Skills, RequireTomeHandin) && + item->ItemType == EQ::item::ItemTypeSpell && + ( + Strings::BeginsWith(item->Name, "Tome of ") || + Strings::BeginsWith(item->Name, "Skill: ") + ) + ) { DeleteItemInInventory(slot_id, 1, true); TrainDiscipline(item->ID); } diff --git a/zone/effects.cpp b/zone/effects.cpp index 06292b28e..0570251f2 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -622,8 +622,8 @@ bool Client::TrainDiscipline(uint32 itemid) { const std::string item_name = item->Name; if ( - item_name.substr(0, 5) != std::string("Tome ") && - item_name.substr(0, 7) != std::string("Skill: ") + !Strings::BeginsWith(item_name, "Tome of ") && + !Strings::BeginsWith(item_name, "Skill: ") ) { Message(Chat::Red, "This item is not a tome."); //summon them the item back... @@ -709,8 +709,8 @@ bool Client::MemorizeSpellFromItem(uint32 item_id) { const std::string item_name = item->Name; if ( - item_name.substr(0, 7) != std::string("Spell: ") && - item_name.substr(0, 6) != std::string("Song: ") + !Strings::BeginsWith(item_name, "Spell: ") && + !Strings::BeginsWith(item_name, "Song: ") ) { Message(Chat::Red, "This item is not a scroll."); SummonItem(item_id); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index cb27ebc66..eb841555d 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -1018,8 +1018,8 @@ bool QuestManager::isdisctome(uint32 item_id) { const std::string item_name = item->Name; if ( - strcmp(item_name.substr(0, 5).c_str(), "Tome ") && - strcmp(item_name.substr(0, 7).c_str(), "Skill: ") + !Strings::BeginsWith(item_name, "Tome of ") && + !Strings::BeginsWith(item_name, "Skill: ") ) { return false; }