From f3f8a50d3c6749fca1a1715aa61c07971af8f740 Mon Sep 17 00:00:00 2001 From: Kinglykrab <89047260+Kinglykrab@users.noreply.github.com> Date: Tue, 11 Oct 2022 22:29:54 -0400 Subject: [PATCH] [Bug Fix] Allow Songs to be scribed from scrolls (#2460) * [Bug Fix] Allow Songs to be scribed from scrolls Songs weren't capable of being scribed from scrolls because we didn't check for `Song: ` in the name. Converted old logic to substrings, can probably do it cleaner, but it's better than it was. Removed extraneous `initiator->IsClient()` calls as `initiator` is **always** a client. * Fix substr logic. --- zone/effects.cpp | 149 +++++++++++++++++++++------------------------- zone/questmgr.cpp | 136 +++++++++++++++++++----------------------- zone/questmgr.h | 4 +- 3 files changed, 132 insertions(+), 157 deletions(-) diff --git a/zone/effects.cpp b/zone/effects.cpp index bbced07f8..0a87237e7 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -514,109 +514,100 @@ bool Client::TrainDiscipline(uint32 itemid) { //get the item info const EQ::ItemData *item = database.GetItem(itemid); - if(item == nullptr) { + if (!item) { Message(Chat::Red, "Unable to find the tome you turned in!"); - LogError("Unable to find turned in tome id [{}]\n", (unsigned long)itemid); - return(false); + LogError("Unable to find turned in tome id [{}]", itemid); + return false; } if (!item->IsClassCommon() || item->ItemType != EQ::item::ItemTypeSpell) { Message(Chat::Red, "Invalid item type, you cannot learn from this item."); //summon them the item back... SummonItem(itemid); - return(false); + return false; } //Need a way to determine the difference between a spell and a tome //so they cant turn in a spell and get it as a discipline //this is kinda a hack: - if(!( - item->Name[0] == 'T' && - item->Name[1] == 'o' && - item->Name[2] == 'm' && - item->Name[3] == 'e' && - item->Name[4] == ' ' - ) && !( - item->Name[0] == 'S' && - item->Name[1] == 'k' && - item->Name[2] == 'i' && - item->Name[3] == 'l' && - item->Name[4] == 'l' && - item->Name[5] == ':' && - item->Name[6] == ' ' - )) { + const std::string item_name = item->Name; + + if ( + item_name.substr(0, 5) != std::string("Tome ") && + item_name.substr(0, 7) != std::string("Skill: ") + ) { Message(Chat::Red, "This item is not a tome."); //summon them the item back... SummonItem(itemid); - return(false); + return false; } - int myclass = GetClass(); - if(myclass == WIZARD || myclass == ENCHANTER || myclass == MAGICIAN || myclass == NECROMANCER) { + const auto player_class = GetClass(); + if (player_class == WIZARD || player_class == ENCHANTER || player_class == MAGICIAN || player_class == NECROMANCER) { Message(Chat::Red, "Your class cannot learn from this tome."); //summon them the item back... SummonItem(itemid); - return(false); + return false; } //make sure we can train this... //can we use the item? - uint32 cbit = 1 << (myclass-1); - if(!(item->Classes & cbit)) { + const auto class_bit = static_cast(1 << (player_class - 1)); + if (!(item->Classes & class_bit)) { Message(Chat::Red, "Your class cannot learn from this tome."); //summon them the item back... SummonItem(itemid); - return(false); + return false; } - uint32 spell_id = item->Scroll.Effect; - if(!IsValidSpell(spell_id)) { + const auto spell_id = static_cast(item->Scroll.Effect); + if (!IsValidSpell(spell_id)) { Message(Chat::Red, "This tome Contains invalid knowledge."); - return(false); + return false; } //can we use the spell? - const SPDat_Spell_Struct &spell = spells[spell_id]; - uint8 level_to_use = spell.classes[myclass - 1]; - if(level_to_use == 255) { + const auto& spell = spells[spell_id]; + const auto level_to_use = spell.classes[player_class - 1]; + if (level_to_use == 255) { Message(Chat::Red, "Your class cannot learn from this tome."); //summon them the item back... SummonItem(itemid); - return(false); + return false; } - if(level_to_use > GetLevel()) { - Message(Chat::Red, "You must be at least level %d to learn this discipline.", level_to_use); + if (level_to_use > GetLevel()) { + Message(Chat::Red, fmt::format("You must be at least level {} to learn this discipline.", level_to_use).c_str()); //summon them the item back... SummonItem(itemid); - return(false); + return false; } //add it to PP. - int r; - for(r = 0; r < MAX_PP_DISCIPLINES; r++) { - if(m_pp.disciplines.values[r] == spell_id) { + for (int r = 0; r < MAX_PP_DISCIPLINES; r++) { + if (m_pp.disciplines.values[r] == spell_id) { Message(Chat::Red, "You already know this discipline."); //summon them the item back... SummonItem(itemid); - return(false); - } else if(m_pp.disciplines.values[r] == 0) { + return false; + } else if (m_pp.disciplines.values[r] == 0) { m_pp.disciplines.values[r] = spell_id; database.SaveCharacterDisc(CharacterID(), r, spell_id); SendDisciplineUpdate(); - Message(0, "You have learned a new discipline!"); - return(true); + Message(Chat::White, "You have learned a new discipline!"); + return true; } } + Message(Chat::Red, "You have learned too many disciplines and can learn no more."); - return(false); + return false; } bool Client::MemorizeSpellFromItem(uint32 item_id) { - const EQ::ItemData *item = database.GetItem(item_id); - if(item == nullptr) { + const auto& item = database.GetItem(item_id); + if (!item) { Message(Chat::Red, "Unable to find the scroll!"); - LogError("Unable to find scroll id [{}]\n", (unsigned long)item_id); + LogError("Unable to find scroll id [{}]", item_id); return false; } @@ -626,43 +617,41 @@ bool Client::MemorizeSpellFromItem(uint32 item_id) { return false; } - if(!( - item->Name[0] == 'S' && - item->Name[1] == 'p' && - item->Name[2] == 'e' && - item->Name[3] == 'l' && - item->Name[4] == 'l' && - item->Name[5] == ':' && - item->Name[6] == ' ' - )) { + const std::string item_name = item->Name; + + if ( + item_name.substr(0, 7) != std::string("Spell: ") && + item_name.substr(0, 6) != std::string("Song: ") + ) { Message(Chat::Red, "This item is not a scroll."); SummonItem(item_id); return false; } - int player_class = GetClass(); - uint32 cbit = 1 << (player_class - 1); - if(!(item->Classes & cbit)) { + + const auto class_bit = static_cast(1 << (GetClass() - 1)); + + if (!(item->Classes & class_bit)) { Message(Chat::Red, "Your class cannot learn from this scroll."); SummonItem(item_id); return false; } - uint32 spell_id = item->Scroll.Effect; - if(!IsValidSpell(spell_id)) { + const auto spell_id = static_cast(item->Scroll.Effect); + if (!IsValidSpell(spell_id)) { Message(Chat::Red, "This scroll Contains invalid knowledge."); return false; } - const SPDat_Spell_Struct &spell = spells[spell_id]; - uint8 level_to_use = spell.classes[player_class - 1]; - if(level_to_use == 255) { + const auto& spell = spells[spell_id]; + const auto level_to_use = spell.classes[GetClass() - 1]; + if (level_to_use == 255) { Message(Chat::Red, "Your class cannot learn from this scroll."); SummonItem(item_id); return false; } - if(level_to_use > GetLevel()) { - Message(Chat::Red, "You must be at least level %d to learn this spell.", level_to_use); + if (level_to_use > GetLevel()) { + Message(Chat::Red, fmt::format("You must be at least level {} to learn this spell.", level_to_use).c_str()); SummonItem(item_id); return false; } @@ -673,19 +662,19 @@ bool Client::MemorizeSpellFromItem(uint32 item_id) { if (next_slot != -1) { ScribeSpell(spell_id, next_slot); return true; - } - else { + } else { Message( Chat::Red, - "Unable to scribe spell %s (%i) to spellbook: no more spell book slots available.", - ((spell_id >= 0 && spell_id < SPDAT_RECORDS) ? spells[spell_id].name : "Out-of-range"), - spell_id + fmt::format( + "Unable to scribe {} ({}) to spellbook, no more spell book slots available.", + ((spell_id >= 0 && spell_id < SPDAT_RECORDS) ? spells[spell_id].name : "Out-of-range"), + spell_id + ).c_str() ); SummonItem(item_id); return false; } - } - else { + } else { Message(Chat::Red, "You already know this spell."); SummonItem(item_id); return false; @@ -741,7 +730,7 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) { if (IsAmnesiad()) { MessageString(Chat::Red, MELEE_SILENCE); } - return(false); + return false; } //make sure we have the spell... @@ -751,12 +740,12 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) { break; } if(r == MAX_PP_DISCIPLINES) - return(false); //not found. + return false; //not found. //make sure we can use it.. if(!IsValidSpell(spell_id)) { Message(Chat::Red, "This tome Contains invalid knowledge."); - return(false); + return false; } if (DivineAura() && !IgnoreCastingRestriction(spell_id)) { @@ -769,18 +758,18 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) { if(level_to_use == 255) { Message(Chat::Red, "Your class cannot learn from this tome."); //should summon them a new one... - return(false); + return false; } if(level_to_use > GetLevel()) { MessageString(Chat::Red, DISC_LEVEL_USE_ERROR); //should summon them a new one... - return(false); + return false; } if(GetEndurance() < spell.endurance_cost) { Message(11, "You are too fatigued to use this skill right now."); - return(false); + return false; } // sneak attack discs require you to be hidden for 4 seconds before use @@ -852,7 +841,7 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) { CastSpell(spell_id, target, EQ::spells::CastingSlot::Discipline); } } - return(true); + return true; } uint32 Client::GetDisciplineTimer(uint32 timer_id) { diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index e72c527ef..9bff6d27b 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -398,7 +398,7 @@ void QuestManager::addloot(int item_id, int charges, bool equipitem, int aug1, i void QuestManager::Zone(const char *zone_name) { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) + if (initiator) { initiator->MoveZone(zone_name); } @@ -406,7 +406,7 @@ void QuestManager::Zone(const char *zone_name) { void QuestManager::ZoneGroup(const char *zone_name) { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) { + if (initiator) { if (!initiator->GetGroup()) { initiator->MoveZone(zone_name); } else { @@ -423,7 +423,7 @@ void QuestManager::ZoneGroup(const char *zone_name) { void QuestManager::ZoneRaid(const char *zone_name) { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) { + if (initiator) { if (!initiator->GetRaid()) { initiator->MoveZone(zone_name); } else { @@ -935,96 +935,82 @@ void QuestManager::changedeity(int deity_id) { //Changes the deity. if(initiator) { - if(initiator->IsClient()) - { - initiator->SetDeity(deity_id); - initiator->Message(Chat::Yellow,"Your Deity has been changed/set to: %i", deity_id); - initiator->Save(1); - initiator->Kick("Deity change by QuestManager"); - } - else - { - initiator->Message(Chat::Yellow,"Error changing Deity"); - } + initiator->SetDeity(deity_id); + initiator->Message(Chat::Yellow,"Your Deity has been changed/set to: %i", deity_id); + initiator->Save(1); + initiator->Kick("Deity change by QuestManager"); } } void QuestManager::exp(int amt) { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) + if (initiator) initiator->AddEXP(amt); } void QuestManager::level(int newlevel) { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) + if (initiator) initiator->SetLevel(newlevel, true); } -void QuestManager::traindisc(int discipline_tome_item_id) { +void QuestManager::traindisc(uint32 discipline_tome_item_id) { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) + if (initiator) { initiator->TrainDiscipline(discipline_tome_item_id); + } } -bool QuestManager::isdisctome(int item_id) { - const EQ::ItemData *item = database.GetItem(item_id); - if(item == nullptr) { - return(false); +bool QuestManager::isdisctome(uint32 item_id) { + const auto &item = database.GetItem(item_id); + if (!item) { + return false; } if (!item->IsClassCommon() || item->ItemType != EQ::item::ItemTypeSpell) { - return(false); + return false; } //Need a way to determine the difference between a spell and a tome //so they cant turn in a spell and get it as a discipline //this is kinda a hack: - if(!( - item->Name[0] == 'T' && - item->Name[1] == 'o' && - item->Name[2] == 'm' && - item->Name[3] == 'e' && - item->Name[4] == ' ' - ) && !( - item->Name[0] == 'S' && - item->Name[1] == 'k' && - item->Name[2] == 'i' && - item->Name[3] == 'l' && - item->Name[4] == 'l' && - item->Name[5] == ':' && - item->Name[6] == ' ' - )) { - return(false); + + 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: ") + ) { + return false; } //we know for sure none of the int casters get disciplines - uint32 cbit = 0; - cbit |= 1 << (WIZARD-1); - cbit |= 1 << (ENCHANTER-1); - cbit |= 1 << (MAGICIAN-1); - cbit |= 1 << (NECROMANCER-1); - if(item->Classes & cbit) { - return(false); + uint32 class_bit = 0; + class_bit |= 1 << (WIZARD - 1); + class_bit |= 1 << (ENCHANTER - 1); + class_bit |= 1 << (MAGICIAN - 1); + class_bit |= 1 << (NECROMANCER - 1); + if (item->Classes & class_bit) { + return false; } - uint32 spell_id = item->Scroll.Effect; - if(!IsValidSpell(spell_id)) { - return(false); + const auto& spell_id = static_cast(item->Scroll.Effect); + if (!IsValidSpell(spell_id)) { + return false; } //we know for sure none of the int casters get disciplines - const SPDat_Spell_Struct &spell = spells[spell_id]; + const auto& spell = spells[spell_id]; if( spell.classes[WIZARD - 1] != 255 && spell.classes[ENCHANTER - 1] != 255 && spell.classes[MAGICIAN - 1] != 255 && spell.classes[NECROMANCER - 1] != 255 ) { - return(false); + return false; } - return(true); + return true; } std::string QuestManager::getracename(uint16 race_id) { @@ -1066,7 +1052,7 @@ std::string QuestManager::getconsiderlevelname(uint8 consider_level) { void QuestManager::safemove() { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) + if (initiator) initiator->GoToSafeCoords(zone->GetZoneID(), zone->GetInstanceID()); } @@ -1091,7 +1077,7 @@ void QuestManager::snow(int weather) { void QuestManager::rename(std::string name) { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) { + if (initiator) { std::string current_name = initiator->GetName(); if (initiator->ChangeFirstName(name.c_str(), current_name.c_str())) { initiator->Message( @@ -1117,7 +1103,7 @@ void QuestManager::rename(std::string name) { void QuestManager::surname(std::string last_name) { QuestManagerCurrentQuestVars(); //Changes the last name. - if (initiator && initiator->IsClient()) { + if (initiator) { initiator->ChangeLastName(last_name); initiator->Message( Chat::White, @@ -1208,19 +1194,19 @@ void QuestManager::pvp(const char *mode) { void QuestManager::movepc(int zone_id, float x, float y, float z, float heading) { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) + if (initiator) initiator->MovePC(zone_id, x, y, z, heading); } void QuestManager::gmmove(float x, float y, float z) { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) + if (initiator) initiator->GMMove(x, y, z); } void QuestManager::movegrp(int zoneid, float x, float y, float z) { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) + if (initiator) { Group *g = entity_list.GetGroupByClient(initiator); if (g != nullptr) { @@ -1253,13 +1239,13 @@ void QuestManager::addskill(int skill_id, int value) { QuestManagerCurrentQuestVars(); if (skill_id < 0 || skill_id > EQ::skills::HIGHEST_SKILL) return; - if (initiator && initiator->IsClient()) + if (initiator) initiator->AddSkill((EQ::skills::SkillType) skill_id, value); } void QuestManager::setlanguage(int skill_id, int value) { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) + if (initiator) initiator->SetLanguageSkill(skill_id, value); } @@ -1267,7 +1253,7 @@ void QuestManager::setskill(int skill_id, int value) { QuestManagerCurrentQuestVars(); if (skill_id < 0 || skill_id > EQ::skills::HIGHEST_SKILL) return; - if (initiator && initiator->IsClient()) + if (initiator) initiator->SetSkill((EQ::skills::SkillType) skill_id, value); } @@ -1275,7 +1261,7 @@ void QuestManager::setallskill(int value) { QuestManagerCurrentQuestVars(); if (!initiator) return; - if (initiator && initiator->IsClient()) { + if (initiator) { EQ::skills::SkillType sk; for (sk = EQ::skills::Skill1HBlunt; sk <= EQ::skills::HIGHEST_SKILL; sk = (EQ::skills::SkillType)(sk + 1)) { initiator->SetSkill(sk, value); @@ -1329,14 +1315,14 @@ void QuestManager::attacknpctype(int npc_type_id) { void QuestManager::save() { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) + if (initiator) initiator->Save(); } void QuestManager::faction(int faction_id, int faction_value, int temp) { QuestManagerCurrentQuestVars(); running_quest run = quests_running_.top(); - if(run.owner->IsCharmed() == false && initiator && initiator->IsClient()) { + if(run.owner->IsCharmed() == false && initiator) { if(faction_id != 0 && faction_value != 0) { initiator->SetFactionLevel2( initiator->CharacterID(), @@ -1352,7 +1338,7 @@ void QuestManager::faction(int faction_id, int faction_value, int temp) { void QuestManager::rewardfaction(int faction_id, int faction_value) { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) { + if (initiator) { if (faction_id != 0 && faction_value != 0) { initiator->RewardFaction(faction_id, faction_value); } @@ -1371,7 +1357,7 @@ void QuestManager::setsky(uint8 new_sky) { void QuestManager::setguild(uint32 new_guild_id, uint8 new_rank) { QuestManagerCurrentQuestVars(); - if (initiator && initiator->IsClient()) { + if (initiator) { guild_mgr.SetGuild(initiator->CharacterID(), new_guild_id, new_rank); } } @@ -1495,7 +1481,7 @@ void QuestManager::setglobal(const char *varname, const char *newvalue, int opti 7 all all all */ - if (initiator && initiator->IsClient()){ // some events like waypoint and spawn don't have a player involved + if (initiator){ // some events like waypoint and spawn don't have a player involved qgCharid=initiator->CharacterID(); } else { @@ -1516,7 +1502,7 @@ void QuestManager::setglobal(const char *varname, const char *newvalue, int opti InsertQuestGlobal(qgCharid, qgNpcid, qgZoneid, varname, newvalue, QGVarDuration(duration)); /* QS: PlayerLogQGlobalUpdate */ - if (RuleB(QueryServ, PlayerLogQGlobalUpdate) && qgCharid && qgCharid > 0 && initiator && initiator->IsClient()){ + if (RuleB(QueryServ, PlayerLogQGlobalUpdate) && qgCharid && qgCharid > 0 && initiator){ std::string event_desc = StringFormat("Update :: qglobal:%s to qvalue:%s zoneid:%i instid:%i", varname, newvalue, initiator->GetZoneID(), initiator->GetInstanceID()); QServ->PlayerLogEvent(Player_Log_QGlobal_Update, qgCharid, event_desc); } @@ -1601,13 +1587,13 @@ void QuestManager::delglobal(const char *varname) { int qgCharid = 0; int qgNpcid = owner ? owner->GetNPCTypeID() : 0; // encounter scripts don't have an owner - if (initiator && initiator->IsClient()) // some events like waypoint and spawn don't have a player involved + if (initiator) // some events like waypoint and spawn don't have a player involved qgCharid=initiator->CharacterID(); else qgCharid=-qgNpcid; // make char id negative npc id as a fudge /* QS: PlayerLogQGlobalUpdate */ - if (RuleB(QueryServ, PlayerLogQGlobalUpdate) && qgCharid && qgCharid > 0 && initiator && initiator->IsClient()){ + if (RuleB(QueryServ, PlayerLogQGlobalUpdate) && qgCharid && qgCharid > 0 && initiator){ std::string event_desc = StringFormat("Deleted :: qglobal:%s zoneid:%i instid:%i", varname, initiator->GetZoneID(), initiator->GetInstanceID()); QServ->PlayerLogEvent(Player_Log_QGlobal_Update, qgCharid, event_desc); } @@ -1701,21 +1687,21 @@ int QuestManager::QGVarDuration(const char *fmt) void QuestManager::ding() { QuestManagerCurrentQuestVars(); //makes a sound. - if (initiator && initiator->IsClient()) + if (initiator) initiator->SendSound(); } void QuestManager::rebind(int zone_id, const glm::vec3& location) { QuestManagerCurrentQuestVars(); - if(initiator && initiator->IsClient()) { + if(initiator) { initiator->SetBindPoint(0, zone_id, 0, location); } } void QuestManager::rebind(int zone_id, const glm::vec4& location) { QuestManagerCurrentQuestVars(); - if(initiator && initiator->IsClient()) { + if(initiator) { initiator->SetBindPoint2(0, zone_id, 0, location); } } @@ -2244,7 +2230,7 @@ bool QuestManager::createBot(const char *name, const char *lastname, uint8 level QuestManagerCurrentQuestVars(); uint32 MaxBotCreate = RuleI(Bots, CreationLimit); - if (initiator && initiator->IsClient()) + if (initiator) { if(Bot::SpawnedBotCount(initiator->CharacterID()) >= MaxBotCreate) { @@ -2571,7 +2557,7 @@ int QuestManager::getlevel(uint8 type) else return (initiator->GetLevel()); } - else if(type == 4 && initiator->IsClient()) + else if(type == 4) { return (initiator->CastToClient()->GetLevel2()); } diff --git a/zone/questmgr.h b/zone/questmgr.h index 17e94f171..e7815a902 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -113,8 +113,8 @@ public: void changedeity(int deity_id); void exp(int amt); void level(int newlevel); - void traindisc(int discipline_tome_item_id); - bool isdisctome(int item_id); + void traindisc(uint32 discipline_tome_item_id); + bool isdisctome(uint32 item_id); std::string getracename(uint16 race_id); std::string getspellname(uint32 spell_id); std::string getskillname(int skill_id);