diff --git a/zone/aa.cpp b/zone/aa.cpp index 2fe75e4fc..a66b533f6 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1254,37 +1254,37 @@ void Client::SendAA(uint32 id, int seq) { if (RuleB(AA, Stacking) && (GetClientVersionBit() >= 4) && (saa2->hotkey_sid == 4294967295u)) aa_stack = true; - if (aa_stack){ - uint32 aa_AA = 0; - uint32 aa_value = 0; - for (int i = 0; i < MAX_PP_AA_ARRAY; i++) { - if (aa[i]) { - aa_AA = aa[i]->AA; - aa_value = aa[i]->value; - - if (aa_AA){ - - if (aa_value > 0) - aa_AA -= aa_value-1; - - saa_pp = zone->FindAA(aa_AA); - - if (saa_pp){ - - if (saa_pp->sof_next_skill == saa2->sof_next_skill){ - - if (saa_pp->id == saa2->id) - break; //You already have this in the player profile. - else if ((saa_pp->sof_current_level < saa2->sof_current_level) && (aa_value < saa_pp->max_level)) - return; //DISABLE DISPLAY HIGHER - You have not reached max level yet of your current AA. - else if ((saa_pp->sof_current_level < saa2->sof_current_level) && (aa_value == saa_pp->max_level) && (saa_pp->sof_next_id == saa2->id)) - IsBaseLevel = false; //ALLOW DISPLAY HIGHER - } - } - } - } - } - } + //if (aa_stack){ + // uint32 aa_AA = 0; + // uint32 aa_value = 0; + // for (int i = 0; i < MAX_PP_AA_ARRAY; i++) { + // if (aa[i]) { + // aa_AA = aa[i]->AA; + // aa_value = aa[i]->value; + // + // if (aa_AA){ + // + // if (aa_value > 0) + // aa_AA -= aa_value-1; + // + // saa_pp = zone->FindAA(aa_AA); + // + // if (saa_pp){ + // + // if (saa_pp->sof_next_skill == saa2->sof_next_skill){ + // + // if (saa_pp->id == saa2->id) + // break; //You already have this in the player profile. + // else if ((saa_pp->sof_current_level < saa2->sof_current_level) && (aa_value < saa_pp->max_level)) + // return; //DISABLE DISPLAY HIGHER - You have not reached max level yet of your current AA. + // else if ((saa_pp->sof_current_level < saa2->sof_current_level) && (aa_value == saa_pp->max_level) && (saa_pp->sof_next_id == saa2->id)) + // IsBaseLevel = false; //ALLOW DISPLAY HIGHER + // } + // } + // } + // } + // } + //} //Hide higher tiers of multi tiered AA's if the base level is not fully purchased. if (aa_stack && IsBaseLevel && saa2->sof_current_level > 0) @@ -1399,51 +1399,6 @@ void Client::SendAAList(){ } } -uint32 Client::GetAA(uint32 aa_id) const { - std::map::const_iterator res; - res = aa_points.find(aa_id); - if(res != aa_points.end()) { - return(res->second); - } - return(0); -} - -bool Client::SetAA(uint32 aa_id, uint32 new_value) { - aa_points[aa_id] = new_value; - uint32 cur; - auto sendaa = zone->FindAA(aa_id); // this is a bit hacky - uint32 charges = sendaa->special_category == 7 && new_value ? 1 : 0; - for(cur=0;cur < MAX_PP_AA_ARRAY;cur++){ - if((aa[cur]->value > 1) && ((aa[cur]->AA - aa[cur]->value + 1)== aa_id)){ - aa[cur]->value = new_value; - if(new_value > 0) - aa[cur]->AA++; - aa[cur]->charges = charges; - return true; - } - else if((aa[cur]->value == 1) && (aa[cur]->AA == aa_id)){ - aa[cur]->value = new_value; - if(new_value > 0) - aa[cur]->AA++; - aa[cur]->charges = charges; - return true; - } - // hack to prevent expendable exploit, we should probably be reshuffling the array to fix the hole - else if(aa[cur]->value == 0 && new_value == 1 && aa[cur]->AA == aa_id) { - aa[cur]->value = new_value; - aa[cur]->charges = charges; - return true; - } - else if(aa[cur]->AA==0){ //end of list - aa[cur]->AA = aa_id; - aa[cur]->value = new_value; - aa[cur]->charges = charges; - return true; - } - } - return false; -} - SendAA_Struct* Zone::FindAA(uint32 id) { return aas_send[id]; } @@ -1503,39 +1458,39 @@ bool ZoneDatabase::LoadAAEffects2() { } void Client::ResetAA(){ - RefundAA(); - uint32 i; - for (i=0; i < MAX_PP_AA_ARRAY; i++) { - aa[i]->AA = 0; - aa[i]->value = 0; - aa[i]->charges = 0; - m_pp.aa_array[i].AA = 0; - m_pp.aa_array[i].value = 0; - m_pp.aa_array[i].charges= 0; - } - - std::map::iterator itr; - for(itr = aa_points.begin(); itr != aa_points.end(); ++itr) - aa_points[itr->first] = 0; - - for(int i = 0; i < _maxLeaderAA; ++i) - m_pp.leader_abilities.ranks[i] = 0; - - m_pp.group_leadership_points = 0; - m_pp.raid_leadership_points = 0; - m_pp.group_leadership_exp = 0; - m_pp.raid_leadership_exp = 0; - - database.DeleteCharacterAAs(this->CharacterID()); - SaveAA(); - SendClearAA(); - SendAAList(); - SendAATable(); - SendAAStats(); - database.DeleteCharacterLeadershipAAs(this->CharacterID()); - // undefined for these clients - if (GetClientVersionBit() & BIT_TitaniumAndEarlier) - Kick(); +// RefundAA(); +// uint32 i; +// for (i=0; i < MAX_PP_AA_ARRAY; i++) { +// aa[i]->AA = 0; +// aa[i]->value = 0; +// aa[i]->charges = 0; +// m_pp.aa_array[i].AA = 0; +// m_pp.aa_array[i].value = 0; +// m_pp.aa_array[i].charges= 0; +// } +// +// std::map::iterator itr; +// for(itr = aa_points.begin(); itr != aa_points.end(); ++itr) +// aa_points[itr->first] = 0; +// +// for(int i = 0; i < _maxLeaderAA; ++i) +// m_pp.leader_abilities.ranks[i] = 0; +// +// m_pp.group_leadership_points = 0; +// m_pp.raid_leadership_points = 0; +// m_pp.group_leadership_exp = 0; +// m_pp.raid_leadership_exp = 0; +// +// database.DeleteCharacterAAs(this->CharacterID()); +// SaveAA(); +// SendClearAA(); +// SendAAList(); +// SendAATable(); +// SendAAStats(); +// database.DeleteCharacterLeadershipAAs(this->CharacterID()); +// // undefined for these clients +// if (GetClientVersionBit() & BIT_TitaniumAndEarlier) +// Kick(); } void Client::SendClearAA() @@ -2096,19 +2051,23 @@ Mob *AA_SwarmPetInfo::GetOwner() return entity_list.GetMobID(owner_id); } -void Client::SendAlternateAdvancementList() { - //for(auto &aa : zone->aa_abilities) { - // SendAlternateAdvancement(aa.first, 5); - //} - - SendAlternateAdvancementRank(1, 5); - SendAlternateAdvancementRank(1, 6); - SendAlternateAdvancementRank(2, 1); - //SendAlternateAdvancement(1, 5); - //SendAlternateAdvancement(2, 5); +//New AA +void Client::SendAlternateAdvancementTable() { + for(auto &aa : zone->aa_abilities) { + auto ranks = GetAA(aa.second->first_rank_id); + if(ranks) { + if(aa.second->GetMaxLevel() == ranks) { + SendAlternateAdvancementRank(aa.first, ranks); + } else { + SendAlternateAdvancementRank(aa.first, ranks); + SendAlternateAdvancementRank(aa.first, ranks + 1); + } + } else { + SendAlternateAdvancementRank(aa.first, 1); + } + } } -//New AA void Client::SendAlternateAdvancementRank(int aa_id, int level) { if(!zone) return; @@ -2126,53 +2085,9 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) { if(!rank) return; - if(rank->account_time_required) { - if((Timer::GetTimeSeconds() - account_creation) < rank->account_time_required) - { - return; - } - } - - // Hide Quest/Progression AAs unless player has been granted the first level using $client->IncrementAA(skill_id). - if(ability->category == 1 || ability->category == 2) { - //if(GetAA(saa2->id) == 0) - // return; - - if(rank->expansion > 0) { - AA::Ability *qaa = zone->GetAlternateAdvancementAbility(aa_id + 1); - //if(qaa && qaa->expansion == rank->expansion && GetAA(aa_id) > 0) { - // return; - //} - } - } - - // Passive and Active Shroud AAs - // For now we skip them - if(ability->category == 3 || ability->category == 4) { + if(!CanUseAlternateAdvancementRank(rank)) { return; } - - // Check for racial/Drakkin blood line AAs - if(ability->category == 8) - { - uint32 client_race = GetBaseRace(); - - // Drakkin Bloodlines - if(rank->expansion > 522) - { - if(client_race != 522) - return; - - int heritage = this->GetDrakkinHeritage() + 523; // 523 = Drakkin Race(522) + Bloodline - - if(heritage != rank->expansion) - return; - } - else if(client_race != rank->expansion) - { - return; - } - } int size = sizeof(AARankInfo_Struct) + (sizeof(AARankEffect_Struct) * rank->effects.size()) + (sizeof(AARankPrereq_Struct) * rank->prereqs.size()); EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, size); @@ -2220,10 +2135,126 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) { safe_delete(outapp); } +AA::Ability *Zone::GetAlternateAdvancementAbility(int id) { + auto iter = aa_abilities.find(id); + if(iter != aa_abilities.end()) { + return iter->second.get(); + } + + return nullptr; +} + +AA::Ability *Zone::GetAlternateAdvancementAbilityByRank(int rank_id) { + AA::Rank *rank = GetAlternateAdvancementRank(rank_id); + + if(!rank) + return nullptr; + + return rank->base_ability; +} + +AA::Rank *Zone::GetAlternateAdvancementRank(int rank_id) { + auto iter = aa_ranks.find(rank_id); + if(iter != aa_ranks.end()) { + return iter->second.get(); + } + + return nullptr; +} + +uint32 Mob::GetAA(uint32 rank_id) const { + if(zone) { + AA::Ability *ability = zone->GetAlternateAdvancementAbilityByRank(rank_id); + if(!ability) + return 0; + + auto iter = aa_ranks.find(ability->id); + if(iter != aa_ranks.end()) { + return iter->second; + } + } + return 0; +} + +bool Mob::SetAA(uint32 rank_id, uint32 new_value) { + if(zone) { + AA::Ability *ability = zone->GetAlternateAdvancementAbilityByRank(rank_id); + + if(!ability) { + return false; + } + + if(new_value > ability->GetMaxLevel()) { + return false; + } + + aa_ranks[ability->id] = new_value; + } + + return false; +} + + +bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) { + AA::Ability *ability = rank->base_ability; + + if(!ability) + return false; + + // Passive and Active Shroud AAs + // For now we skip them + if(ability->category == 3 || ability->category == 4) { + return false; + } + + // Check for racial/Drakkin blood line AAs + if(ability->category == 8) + { + uint32 client_race = GetBaseRace(); + + // Drakkin Bloodlines + if(rank->expansion > 522) + { + if(client_race != 522) + return false; + + int heritage = this->GetDrakkinHeritage() + 523; // 523 = Drakkin Race(522) + Bloodline + + if(heritage != rank->expansion) + return false; + } + else if(client_race != rank->expansion) + { + return false; + } + } + + return true; +} + +bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank) { + AA::Ability *ability = rank->base_ability; + + if(!ability) + return false; + + if(!CanUseAlternateAdvancementRank(rank)) { + return false; + } + + //You can't purchase grant only AAs they can only be assigned + if(ability->grant_only) { + return false; + } + + //check other stuff like price later + return true; +} + void Zone::LoadAlternateAdvancement() { Log.Out(Logs::General, Logs::Status, "Loading Alternate Advancement Data..."); - if(!database.LoadAlternateAdvancementAbilities(aa_abilities, - aa_ranks)) + if(!database.LoadAlternateAdvancementAbilities(aa_abilities, + aa_ranks)) { aa_abilities.clear(); aa_ranks.clear(); @@ -2244,7 +2275,8 @@ void Zone::LoadAlternateAdvancement() { if(current->prev) { current->total_cost = current->cost + current->prev->total_cost; - } else { + } + else { current->total_cost = current->cost; } @@ -2257,24 +2289,6 @@ void Zone::LoadAlternateAdvancement() { Log.Out(Logs::General, Logs::Status, "Loaded Alternate Advancement Data"); } -AA::Ability *Zone::GetAlternateAdvancementAbility(int id) { - auto iter = aa_abilities.find(id); - if(iter != aa_abilities.end()) { - return iter->second.get(); - } - - return nullptr; -} - -AA::Rank *Zone::GetAlternateAdvancementRank(int rank_id) { - auto iter = aa_ranks.find(rank_id); - if(iter != aa_ranks.end()) { - return iter->second.get(); - } - - return nullptr; -} - bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map> &abilities, std::unordered_map> &ranks) { @@ -2285,7 +2299,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_mapid = atoi(row[0]); ability->name = row[1]; ability->category = atoi(row[2]); ability->classes = atoi(row[3]); @@ -2295,7 +2309,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_mapfirst_rank_id = atoi(row[7]); ability->first = nullptr; - abilities[id] = std::unique_ptr(ability); + abilities[ability->id] = std::unique_ptr(ability); } } else { Log.Out(Logs::General, Logs::Error, "Failed to load Alternate Advancement Abilities"); @@ -2312,8 +2326,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_mapid = id; + rank->id = atoi(row[0]); rank->upper_hotkey_sid = atoi(row[1]); rank->lower_hotkey_sid = atoi(row[2]); rank->title_sid = atoi(row[3]); @@ -2332,7 +2345,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_mapnext = nullptr; rank->prev = nullptr; - ranks[id] = std::unique_ptr(rank); + ranks[rank->id] = std::unique_ptr(rank); } } else { Log.Out(Logs::General, Logs::Error, "Failed to load Alternate Advancement Ability Ranks"); diff --git a/zone/aa_ability.h b/zone/aa_ability.h index d1ef49105..a31bc06e3 100644 --- a/zone/aa_ability.h +++ b/zone/aa_ability.h @@ -41,6 +41,7 @@ public: Rank *GetRankByPointsSpent(int current_level); int GetMaxLevel(bool force_calc = false); + int id; std::string name; int category; int classes; diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 5dd7440f6..a2a180cef 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -639,20 +639,21 @@ void Client::CalcAABonuses(StatBonuses* newbon) { uint32 slots = 0; uint32 aa_AA = 0; uint32 aa_value = 0; - if(this->aa) { - for (i = 0; i < MAX_PP_AA_ARRAY; i++) { //iterate through all of the client's AAs - if (this->aa[i]) { // make sure aa exists or we'll crash zone - aa_AA = this->aa[i]->AA; //same as aaid from the aa_effects table - aa_value = this->aa[i]->value; //how many points in it - if (aa_AA > 0 || aa_value > 0) { //do we have the AA? if 1 of the 2 is set, we can assume we do - //slots = database.GetTotalAALevels(aa_AA); //find out how many effects from aa_effects table - slots = zone->GetTotalAALevels(aa_AA); //find out how many effects from aa_effects, which is loaded into memory - if (slots > 0) //and does it have any effects? may be able to put this above, not sure if it runs on each iteration - ApplyAABonuses(aa_AA, slots, newbon); //add the bonuses - } - } - } - } + //aa old + //if(this->aa) { + // for (i = 0; i < MAX_PP_AA_ARRAY; i++) { //iterate through all of the client's AAs + // if (this->aa[i]) { // make sure aa exists or we'll crash zone + // aa_AA = this->aa[i]->AA; //same as aaid from the aa_effects table + // aa_value = this->aa[i]->value; //how many points in it + // if (aa_AA > 0 || aa_value > 0) { //do we have the AA? if 1 of the 2 is set, we can assume we do + // //slots = database.GetTotalAALevels(aa_AA); //find out how many effects from aa_effects table + // slots = zone->GetTotalAALevels(aa_AA); //find out how many effects from aa_effects, which is loaded into memory + // if (slots > 0) //and does it have any effects? may be able to put this above, not sure if it runs on each iteration + // ApplyAABonuses(aa_AA, slots, newbon); //add the bonuses + // } + // } + // } + //} } diff --git a/zone/client.cpp b/zone/client.cpp index 53d39ea7b..dc32745e4 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -176,7 +176,6 @@ Client::Client(EQStreamInterface* ieqs) admin = 0; lsaccountid = 0; shield_target = nullptr; - SQL_log = nullptr; guild_id = GUILD_NONE; guildrank = 0; GuildBanker = false; @@ -524,47 +523,48 @@ void Client::ReportConnectingState() { } bool Client::SaveAA(){ - int first_entry = 0; - std::string rquery; - /* Save Player AA */ - int spentpoints = 0; - for (int a = 0; a < MAX_PP_AA_ARRAY; a++) { - uint32 points = aa[a]->value; - if (points > HIGHEST_AA_VALUE) { - aa[a]->value = HIGHEST_AA_VALUE; - points = HIGHEST_AA_VALUE; - } - if (points > 0) { - SendAA_Struct* curAA = zone->FindAA(aa[a]->AA - aa[a]->value + 1); - if (curAA) { - for (int rank = 0; rank::iterator RequiredLevel = AARequiredLevelAndCost.find(aa[a]->AA - aa[a]->value + 1 + rank); - if (RequiredLevel != AARequiredLevelAndCost.end()) { - spentpoints += RequiredLevel->second.Cost; - } - else - spentpoints += (curAA->cost + (curAA->cost_inc * rank)); - } - } - } - } - m_pp.aapoints_spent = spentpoints + m_epp.expended_aa; - int highest = 0; - for (int a = 0; a < MAX_PP_AA_ARRAY; a++) { - if (aa[a]->AA > 0) { // those with value 0 will be cleaned up on next load - if (first_entry != 1){ - rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value, charges)" - " VALUES (%u, %u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value, aa[a]->charges); - first_entry = 1; - } else { - rquery = rquery + StringFormat(", (%u, %u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value, aa[a]->charges); - } - highest = a; - } - } - auto results = database.QueryDatabase(rquery); - /* This is another part of the hack to clean up holes left by expendable AAs */ - rquery = StringFormat("DELETE FROM `character_alternate_abilities` WHERE `id` = %u AND `slot` > %d", character_id, highest); + //aa old + //int first_entry = 0; + //std::string rquery; + ///* Save Player AA */ + //int spentpoints = 0; + //for (int a = 0; a < MAX_PP_AA_ARRAY; a++) { + // uint32 points = aa[a]->value; + // if (points > HIGHEST_AA_VALUE) { + // aa[a]->value = HIGHEST_AA_VALUE; + // points = HIGHEST_AA_VALUE; + // } + // if (points > 0) { + // SendAA_Struct* curAA = zone->FindAA(aa[a]->AA - aa[a]->value + 1); + // if (curAA) { + // for (int rank = 0; rank::iterator RequiredLevel = AARequiredLevelAndCost.find(aa[a]->AA - aa[a]->value + 1 + rank); + // if (RequiredLevel != AARequiredLevelAndCost.end()) { + // spentpoints += RequiredLevel->second.Cost; + // } + // else + // spentpoints += (curAA->cost + (curAA->cost_inc * rank)); + // } + // } + // } + //} + //m_pp.aapoints_spent = spentpoints + m_epp.expended_aa; + //int highest = 0; + //for (int a = 0; a < MAX_PP_AA_ARRAY; a++) { + // if (aa[a]->AA > 0) { // those with value 0 will be cleaned up on next load + // if (first_entry != 1){ + // rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value, charges)" + // " VALUES (%u, %u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value, aa[a]->charges); + // first_entry = 1; + // } else { + // rquery = rquery + StringFormat(", (%u, %u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value, aa[a]->charges); + // } + // highest = a; + // } + //} + //auto results = database.QueryDatabase(rquery); + ///* This is another part of the hack to clean up holes left by expendable AAs */ + //rquery = StringFormat("DELETE FROM `character_alternate_abilities` WHERE `id` = %u AND `slot` > %d", character_id, highest); return true; } diff --git a/zone/client.h b/zone/client.h index 1a1e32c6f..c2d3b1f63 100644 --- a/zone/client.h +++ b/zone/client.h @@ -761,7 +761,7 @@ public: //New AA Methods void SendAlternateAdvancementRank(int aa_id, int level); - void SendAlternateAdvancementList(); + void SendAlternateAdvancementTable(); //old AA Methods void SendAAList(); @@ -787,8 +787,6 @@ public: void DisableAAEffect(aaEffectType type); bool CheckAAEffect(aaEffectType type); void HandleAAAction(aaID activate); - uint32 GetAA(uint32 aa_id) const; - bool SetAA(uint32 aa_id, uint32 new_value); inline uint32 GetAAPointsSpent() { return m_pp.aapoints_spent; } int16 CalcAAFocusEffect(focusType type, uint16 focus_spell, uint16 spell_id); int16 CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id); @@ -1493,11 +1491,7 @@ private: uint32 tribute_master_id; - FILE *SQL_log; uint32 max_AAXP; - uint32 staminacount; - AA_Array* aa[MAX_PP_AA_ARRAY]; //this list contains pointers into our player profile - std::map aa_points; bool npcflag; uint8 npclevel; bool feigned; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 77431ecd9..c242d50e2 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1091,7 +1091,7 @@ void Client::Handle_Connect_OP_SendAAStats(const EQApplicationPacket *app) void Client::Handle_Connect_OP_SendAATable(const EQApplicationPacket *app) { - SendAlternateAdvancementList(); + SendAlternateAdvancementTable(); return; } @@ -1440,58 +1440,60 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if (m_pp.ldon_points_available < 0 || m_pp.ldon_points_available > 2000000000){ m_pp.ldon_points_available = 0; } /* Initialize AA's : Move to function eventually */ - for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++) - aa[a] = &m_pp.aa_array[a]; - query = StringFormat( - "SELECT " - "slot, " - "aa_id, " - "aa_value, " - "charges " - "FROM " - "`character_alternate_abilities` " - "WHERE `id` = %u ORDER BY `slot`", this->CharacterID()); - results = database.QueryDatabase(query); i = 0; - int offset = 0; // offset to fix the hole from expendables - for (auto row = results.begin(); row != results.end(); ++row) { - i = atoi(row[0]) - offset; - m_pp.aa_array[i].AA = atoi(row[1]); - m_pp.aa_array[i].value = atoi(row[2]); - m_pp.aa_array[i].charges = atoi(row[3]); - /* A used expendable could cause there to be a "hole" in the array, this is very bad. Bad things like keeping your expendable after use. - We could do a few things, one of them being reshuffling when the hole is created or defer the fixing until a later point, like during load! - Or just never making a hole in the array and just have hacks every where. Fixing the hole at load really just keeps 1 hack in Client::SendAATable - and keeping this offset that will cause the next AA to be pushed back over the hole. We also need to clean up on save so we don't have multiple - entries for a single AA. - */ - if (m_pp.aa_array[i].value == 0) - offset++; - } - for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++){ - uint32 id = aa[a]->AA; - //watch for invalid AA IDs - if (id == aaNone) - continue; - if (id >= aaHighestID) { - aa[a]->AA = aaNone; - aa[a]->value = 0; - continue; - } - if (aa[a]->value == 0) { - aa[a]->AA = aaNone; - continue; - } - if (aa[a]->value > HIGHEST_AA_VALUE) { - aa[a]->AA = aaNone; - aa[a]->value = 0; - continue; - } - - if (aa[a]->value > 1) /* hack in some stuff for sony's new AA method (where each level of each aa.has a seperate ID) */ - aa_points[(id - aa[a]->value + 1)] = aa[a]->value; - else - aa_points[id] = aa[a]->value; - } + //aa old + //for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++) + // aa[a] = &m_pp.aa_array[a]; + //query = StringFormat( + // "SELECT " + // "slot, " + // "aa_id, " + // "aa_value, " + // "charges " + // "FROM " + // "`character_alternate_abilities` " + // "WHERE `id` = %u ORDER BY `slot`", this->CharacterID()); + //results = database.QueryDatabase(query); i = 0; + //int offset = 0; // offset to fix the hole from expendables + //for (auto row = results.begin(); row != results.end(); ++row) { + // i = atoi(row[0]) - offset; + // m_pp.aa_array[i].AA = atoi(row[1]); + // m_pp.aa_array[i].value = atoi(row[2]); + // m_pp.aa_array[i].charges = atoi(row[3]); + // /* A used expendable could cause there to be a "hole" in the array, this is very bad. Bad things like keeping your expendable after use. + // We could do a few things, one of them being reshuffling when the hole is created or defer the fixing until a later point, like during load! + // Or just never making a hole in the array and just have hacks every where. Fixing the hole at load really just keeps 1 hack in Client::SendAATable + // and keeping this offset that will cause the next AA to be pushed back over the hole. We also need to clean up on save so we don't have multiple + // entries for a single AA. + // */ + // if (m_pp.aa_array[i].value == 0) + // offset++; + //} + //for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++){ + // uint32 id = aa[a]->AA; + // //watch for invalid AA IDs + // if (id == aaNone) + // continue; + // if (id >= aaHighestID) { + // aa[a]->AA = aaNone; + // aa[a]->value = 0; + // continue; + // } + // if (aa[a]->value == 0) { + // aa[a]->AA = aaNone; + // continue; + // } + // if (aa[a]->value > HIGHEST_AA_VALUE) { + // aa[a]->AA = aaNone; + // aa[a]->value = 0; + // continue; + // } + // + // //aa old +// // if (aa[a]->value > 1) /* hack in some stuff for sony's new AA method (where each level of each aa.has a seperate ID) */ +// // aa_points[(id - aa[a]->value + 1)] = aa[a]->value; +// // else +// // aa_points[id] = aa[a]->value; + //} if (SPDAT_RECORDS > 0) { for (uint32 z = 0; z #include #include @@ -860,7 +861,6 @@ public: uint32 GetZoneID() const; //for perl virtual int32 CheckAggroAmount(uint16 spell_id, bool isproc = false); virtual int32 CheckHealAggroAmount(uint16 spell_id, uint32 heal_possible = 0); - virtual uint32 GetAA(uint32 aa_id) const { return(0); } uint32 GetInstrumentMod(uint16 spell_id) const; int CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level = 1, uint32 instrument_mod = 10, Mob *caster = nullptr, int ticsremaining = 0); @@ -956,6 +956,12 @@ public: void Tune_FindAccuaryByHitChance(Mob* defender, Mob *attacker, float hit_chance, int interval, int max_loop, int avoid_override, int Msg = 0); void Tune_FindAvoidanceByHitChance(Mob* defender, Mob *attacker, float hit_chance, int interval, int max_loop, int acc_override, int Msg = 0); + //aa new + uint32 GetAA(uint32 rank_id) const; + bool SetAA(uint32 rank_id, uint32 new_value); + bool CanUseAlternateAdvancementRank(AA::Rank *rank); + bool CanPurchaseAlternateAdvancementRank(AA::Rank *ran); + protected: void CommonDamage(Mob* other, int32 &damage, const uint16 spell_id, const SkillUseTypes attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic); static uint16 GetProcID(uint16 spell_id, uint8 effect_index); @@ -969,7 +975,6 @@ protected: virtual bool AI_PursueCastCheck() { return(false); } virtual bool AI_IdleCastCheck() { return(false); } - bool IsFullHP; bool moved; @@ -1311,6 +1316,8 @@ protected: bool bEnraged; bool destructibleobject; + std::unordered_map aa_ranks; + private: void _StopSong(); //this is not what you think it is Mob* target; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index b331113bd..7e91550c5 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -5231,24 +5231,25 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { uint32 aa_AA = 0; uint32 aa_value = 0; - for (int i = 0; i < MAX_PP_AA_ARRAY; i++) - { - aa_AA = this->aa[i]->AA; - aa_value = this->aa[i]->value; - if (aa_AA < 1 || aa_value < 1) - continue; - - if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS) - continue; - - proc_spellid = CalcAAFocus(type, aa_AA, spell_id); - - if (IsValidSpell(proc_spellid)){ - ProcChance = GetSympatheticProcChances(spell_id, GetAABase1(aa_AA, 1)); - if(zone->random.Roll(ProcChance)) - SympatheticProcList.push_back(proc_spellid); - } - } + //aa old + //for (int i = 0; i < MAX_PP_AA_ARRAY; i++) + //{ + // aa_AA = this->aa[i]->AA; + // aa_value = this->aa[i]->value; + // if (aa_AA < 1 || aa_value < 1) + // continue; + // + // if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS) + // continue; + // + // proc_spellid = CalcAAFocus(type, aa_AA, spell_id); + // + // if (IsValidSpell(proc_spellid)){ + // ProcChance = GetSympatheticProcChances(spell_id, GetAABase1(aa_AA, 1)); + // if(zone->random.Roll(ProcChance)) + // SympatheticProcList.push_back(proc_spellid); + // } + //} } if (SympatheticProcList.size() > 0) @@ -5503,21 +5504,22 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) { uint32 aa_AA = 0; uint32 aa_value = 0; - for (int i = 0; i < MAX_PP_AA_ARRAY; i++) - { - aa_AA = this->aa[i]->AA; - aa_value = this->aa[i]->value; - if (aa_AA < 1 || aa_value < 1) - continue; - - Total3 = CalcAAFocus(type, aa_AA, spell_id); - if (Total3 > 0 && realTotal3 >= 0 && Total3 > realTotal3) { - realTotal3 = Total3; - } - else if (Total3 < 0 && Total3 < realTotal3) { - realTotal3 = Total3; - } - } + //aa old + //for (int i = 0; i < MAX_PP_AA_ARRAY; i++) + //{ + // aa_AA = this->aa[i]->AA; + // aa_value = this->aa[i]->value; + // if (aa_AA < 1 || aa_value < 1) + // continue; + // + // Total3 = CalcAAFocus(type, aa_AA, spell_id); + // if (Total3 > 0 && realTotal3 >= 0 && Total3 > realTotal3) { + // realTotal3 = Total3; + // } + // else if (Total3 < 0 && Total3 < realTotal3) { + // realTotal3 = Total3; + // } + //} } if(type == focusReagentCost && IsSummonPetSpell(spell_id) && GetAA(aaElementalPact)) diff --git a/zone/zone.h b/zone/zone.h index fbe1b48d1..536ff048c 100644 --- a/zone/zone.h +++ b/zone/zone.h @@ -117,6 +117,7 @@ public: //new AA void LoadAlternateAdvancement(); AA::Ability *GetAlternateAdvancementAbility(int id); + AA::Ability *GetAlternateAdvancementAbilityByRank(int rank_id); AA::Rank *GetAlternateAdvancementRank(int rank_id); //old AA