/* EQ2Emulator: Everquest II Server Emulator Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net) This file is part of EQ2Emulator. EQ2Emulator is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. EQ2Emulator is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with EQ2Emulator. If not, see . */ #include "HeroicOp.h" #include "../../common/Log.h" #include "../Rules/Rules.h" extern MasterHeroicOPList master_ho_list; extern RuleManager rule_manager; HeroicOP::HeroicOP() { m_complete = 0; m_currentStage = 0; m_wheel = 0; m_target = 0; m_startTime = 0; m_totalTime = 0; m_shifted = false; for (int8 i = 0; i < 6; i++) countered[i] = 0; } HeroicOP::~HeroicOP() { starters.clear(); } void HeroicOP::SetWheel(HeroicOPWheel* val) { if (!m_wheel) m_wheel = val; else LogWrite(SPELL__ERROR, 0, "HO", "Attempted to set the wheel on a heroic op with a wheel already set"); } void HeroicOP::SetTarget(int32 val) { m_target = val; } bool HeroicOP::UpdateHeroicOP(int16 icon) { bool ret = false; vector::iterator itr; vector temp; HeroicOPStarter* starter = 0; LogWrite(SPELL__ERROR, 0, "HO", "Current Stage %u, wheel exists: %u, looking for icon %u", m_currentStage, m_wheel ? 1 : 0, icon); // If no wheel is set we are dealing with a starter chain still. if (!m_wheel) { // Loop through the starter chains for (itr = starters.begin(); itr != starters.end(); itr++) { starter = *itr; // See if the icon matches the ability at our current stage, if not add it to a list to be removed if (starter->abilities[m_currentStage] == icon) ret = true; else temp.push_back(*itr); } if (ret) { // ret = true so we had a match, first thing to do is remove those that didn't match vector::iterator remove_itr; for (remove_itr = temp.begin(); remove_itr != temp.end(); remove_itr++) { std::vector::iterator it = std::find(starters.begin(), starters.end(), *remove_itr); starters.erase(it); } // now advance the current stage m_currentStage++; // Temp pointer to hold the completed chain, if any HeroicOPStarter* complete_starter = 0; // now loop through those that are left and check the next stage abilities for a 0xFFFF for (itr = starters.begin(); itr != starters.end(); itr++) { starter = *itr; // Found one that is 0xFFFF, means the starter chain is done, get a wheel and reset the stage to 0 if ((starter->abilities[m_currentStage] == 0xFFFF)) { LogWrite(SPELL__ERROR, 0, "HO", "Current Stage %u, starter reset (new stage 0)", m_currentStage); // reset the stage ResetStage(); // geth the wheel m_wheel = master_ho_list.GetWheel(starter); // store the starter chain that is completed complete_starter = starter; // set the start time to now SetStartTime(Timer::GetCurrentTime2()); // set the total time to complete the real to was the admin set in rules (default 10.0f) SetTotalTime(rule_manager.GetGlobalRule(R_Zone, HOTime)->GetFloat()); // We set a wheel so we are done, kill the loop break; } } // Check to see if the completed start chain pointer was set if (complete_starter) { LogWrite(SPELL__ERROR, 0, "HO", "Current Stage %u, complete_starter set", m_currentStage); // clear the starter list starters.clear(); // add the completed starter back in, we do this in case we need this starter again we can just do starters.at(0), for example shifting the wheel starters.push_back(complete_starter); } } } else { LogWrite(SPELL__ERROR, 0, "HO", "Current Stage %u, wheel order: %u", m_currentStage, m_wheel->order); // Wheel was set so we need to check the order it needs to be completed in. if (m_wheel->order == 0) { // No order // Flag used to see if we can shift the wheel bool can_shift = true; // Check the icons and flag the ability as countered if there is a match for (int8 i = 0; i < 6; i++) { if (countered[i] == 1) { // progress made on this wheel so we can't shift it can_shift = false; } if (m_wheel->abilities[i] == icon) { countered[i] = 1; ret = true; } } if (ret) { // As we found a match lets loop through to see if we completed the ho bool finished = true; for (int8 i = 0; i < 6; i++) { // if the ability is not 0xFFFF and countered is 0 then we still have more to go if (m_wheel->abilities[i] != 0xFFFF && countered[i] == 0) { finished = false; break; } } // is we finished the ho set the complete flag if (finished) SetComplete(2); } if (!ret && can_shift && m_wheel->shift_icon == icon) { // can shift, icon matched shift icon, and no progress made ret = ShiftWheel(); } } else { // In order // Check to see if we can shift the wheel if (countered[0] == 0 && icon == m_wheel->shift_icon) { // Can only shift the icon if nothing has completed yet (countered[0] = 0) ret = ShiftWheel(); } // Check the current stage and compare it to the icon else if (m_wheel->abilities[m_currentStage] == icon) { // Is a match so flag this stage as done countered[m_currentStage] = 1; // Advance the stage m_currentStage++; // Set the return value to true ret = true; // Check the next stage, if it is over 6 or equal to 0xFFFF flag the HO as complete if (m_currentStage > 6 || m_wheel->abilities[m_currentStage] == 0xFFFF) SetComplete(2); } } } return ret; } void HeroicOP::AddStarterChain(HeroicOPStarter* starter) { starters.push_back(starter); } bool HeroicOP::ShiftWheel() { // Can only shift once so if we already have return out if (HasShifted()) return false; // Clear the wheel m_wheel = 0; // Get a new Wheel SetWheel(master_ho_list.GetWheel(starters.at(0))); // Set the ho as shifted m_shifted = true; return true; } MasterHeroicOPList::MasterHeroicOPList() { } MasterHeroicOPList::~MasterHeroicOPList() { map > >::iterator itr; map >::iterator itr2; vector::iterator itr3; vector temp; vector::iterator itr4; // loop through the m_hoList to delete the pointers for (itr = m_hoList.begin(); itr != m_hoList.end(); itr++) { // loop through the second map of the m_hoList for (itr2 = itr->second.begin(); itr2 != itr->second.end(); itr2++) { // loop through the vector of the second map and delete the pointers for (itr3 = itr2->second.begin(); itr3 != itr2->second.end(); itr3++) safe_delete(*itr3); // clear the vector itr2->second.clear(); // put the starter in a temp list to delete later temp.push_back(itr2->first); } // clear the seond map itr->second.clear(); } // clear the m_hoList m_hoList.clear(); // Delete the starters for (itr4 = temp.begin(); itr4 != temp.end(); itr4++) safe_delete(*itr4); // clear the temp vector temp.clear(); } void MasterHeroicOPList::AddStarter(int8 start_class, HeroicOPStarter* starter) { if (m_hoList.count(start_class) == 0 || m_hoList[start_class].count(starter) == 0) { m_hoList[start_class][starter]; // This adds the starter with out giving it a vector of wheels yet. } } void MasterHeroicOPList::AddWheel(int32 starter_id, HeroicOPWheel* wheel) { map > >::iterator itr; map >::iterator itr2; bool found = false; // Loop through the list and add the wheel to the correct starter for (itr = m_hoList.begin(); itr != m_hoList.end(); itr++) { for (itr2 = itr->second.begin(); itr2 != itr->second.end(); itr2++) { if (itr2->first->id == starter_id) { // Found a match, add the wheel, set the flag to break the first loop, and break this loop itr2->second.push_back(wheel); found = true; break; } } // If we found a match break the first loop if (found) break; } // No match found give an error. if (!found) LogWrite(SPELL__ERROR, 0, "HO", "Attempted to add a wheel to a starter (%u) that doesn't exsist", starter_id); } HeroicOP* MasterHeroicOPList::GetHeroicOP(int8 class_id) { if (m_hoList.count(class_id) == 0) { LogWrite(SPELL__ERROR, 0, "HO", "No HO's found for the given class (%i)", class_id); return 0; } map >::iterator itr; HeroicOP* ret = new HeroicOP(); // Loop through the starters for this class and add them to the HO for (itr = m_hoList[class_id].begin(); itr != m_hoList[class_id].end(); itr++) ret->AddStarterChain(itr->first); return ret; } HeroicOPWheel* MasterHeroicOPList::GetWheel(HeroicOPStarter* starter) { if (!starter) return 0; if (m_hoList.count(starter->start_class) == 0) { LogWrite(SPELL__ERROR, 0, "HO", "Start class (%u) not found", starter->start_class); return 0; } if (m_hoList[starter->start_class].count(starter) == 0) { LogWrite(SPELL__ERROR, 0, "HO", "Wheel not found for the provided starter (%u)", starter->id); return 0; } int index = MakeRandomInt(0, m_hoList[starter->start_class][starter].size() - 1); if(index < m_hoList[starter->start_class][starter].size()) return m_hoList[starter->start_class][starter].at(index); else LogWrite(SPELL__ERROR, 0, "HO", "Wheel index %u for heroic_ops starter ID %u NOT Found!! Wheel starter_class %u, wheel size: %u. Wheels that match starter_link_id -> Starter 'id' missing.", index, starter->id, starter->start_class, m_hoList[starter->start_class][starter].size()); return nullptr; }