diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 0c4335016..e562a94e5 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -4243,7 +4243,7 @@ struct AARankInfo_Struct int32 total_cost; int32 expansion; int32 category; - uint8 charges; + uint32 charges; uint8 grant_only; uint32 total_effects; uint32 total_prereqs; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 096467edf..a4f484a9e 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -2466,7 +2466,8 @@ namespace RoF2 outapp->WriteUInt32(emu->lastlogin); outapp->WriteUInt32(emu->timePlayedMin); outapp->WriteUInt32(emu->timeentitledonaccount); - outapp->WriteUInt32(0x0007ffff); // Expansion bitmask + outapp->WriteUInt32(emu->expansions); + //outapp->WriteUInt32(0x0007ffff); // Expansion bitmask outapp->WriteUInt32(structs::MAX_PP_LANGUAGE); diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 80201da1e..69bb7f4c1 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1677,8 +1677,8 @@ namespace SoD OUT(copper_bank); OUT(platinum_shared); // OUT(unknown13156[84]); - //OUT(expansions); - eq->expansions = 16383; + OUT(expansions); + //eq->expansions = 16383; // OUT(unknown13244[12]); OUT(autosplit); // OUT(unknown13260[16]); diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 7b0e14c1c..2d8ec8d3a 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1335,8 +1335,8 @@ namespace SoF OUT(copper_bank); OUT(platinum_shared); // OUT(unknown13156[84]); - //OUT(expansions); - eq->expansions = 16383; + OUT(expansions); + //eq->expansions = 16383; // OUT(unknown13244[12]); OUT(autosplit); // OUT(unknown13260[16]); diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 81ad197d6..5b879af9d 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -1804,15 +1804,13 @@ namespace UF // OUT(unknown00224[48]); //NOTE: new client supports 300 AAs, our internal rep/PP //only supports 240.. - //for (r = 0; r < MAX_PP_AA_ARRAY; r++) { - // OUT(aa_array[r].AA); - // OUT(aa_array[r].value); - // OUT(aa_array[r].charges); - //} - // OUT(unknown02220[4]); + for (r = 0; r < MAX_PP_AA_ARRAY; r++) { + eq->aa_array[r].AA = emu->aa_array[r].AA; + eq->aa_array[r].value = emu->aa_array[r].value; + eq->aa_array[r].charges = emu->aa_array[r].charges; + } - eq->aa_array[0].AA = 6; - eq->aa_array[0].value = 5; + // OUT(unknown02220[4]); OUT(mana); OUT(cur_hp); @@ -1943,8 +1941,8 @@ namespace UF OUT(copper_bank); OUT(platinum_shared); // OUT(unknown13156[84]); - //OUT(expansions); - eq->expansions = 0xffff; + OUT(expansions); + //eq->expansions = 0x1ffff; // OUT(unknown13244[12]); OUT(autosplit); // OUT(unknown13260[16]); @@ -2149,7 +2147,6 @@ namespace UF ENCODE(OP_SendAATable) { -#if 1 EQApplicationPacket *inapp = *p; *p = nullptr; AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer; @@ -2180,8 +2177,8 @@ namespace UF eq->last_id = emu->prev_id; eq->next_id = emu->next_id; eq->cost2 = emu->total_cost; - eq->grant_only = emu->grant_only > 0 ? true : false; - eq->expendable_charges = emu->charges ? 1 : 0; + eq->grant_only = emu->grant_only; + eq->expendable_charges = emu->charges; eq->aa_expansion = emu->expansion; eq->special_category = emu->category; eq->total_abilities = emu->total_effects; @@ -2194,65 +2191,13 @@ namespace UF } if(emu->total_prereqs > 0) { - eq->prereq_skill = -(int)inapp->ReadUInt32(); + eq->prereq_skill = inapp->ReadUInt32(); eq->prereq_minpoints = inapp->ReadUInt32(); } - Log.Out(Logs::General, Logs::Status, "%s", DumpPacketToString(outapp).c_str()); + //Log.Out(Logs::General, Logs::Status, "%s", DumpPacketToString(outapp).c_str()); dest->FastQueuePacket(&outapp); delete inapp; -#else - ENCODE_LENGTH_ATLEAST(SendAA_Struct); - SETUP_VAR_ENCODE(SendAA_Struct); - ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability)); - - // Check clientver field to verify this AA should be sent for SoF - // clientver 1 is for all clients and 6 is for Underfoot - if(emu->clientver <= 6) - { - OUT(id); - eq->unknown004 = 1; - //eq->hotkey_sid = (emu->hotkey_sid==4294967295UL)?0:(emu->id - emu->current_level + 1); - //eq->hotkey_sid2 = (emu->hotkey_sid2==4294967295UL)?0:(emu->id - emu->current_level + 1); - //eq->title_sid = emu->id - emu->current_level + 1; - //eq->desc_sid = emu->id - emu->current_level + 1; - eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? 0 : (emu->sof_next_skill); - eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? 0 : (emu->sof_next_skill); - eq->title_sid = emu->sof_next_skill; - eq->desc_sid = emu->sof_next_skill; - OUT(class_type); - OUT(cost); - OUT(seq); - OUT(current_level); - OUT(prereq_skill); - OUT(prereq_minpoints); - eq->type = emu->sof_type; - OUT(spellid); - OUT(spell_type); - OUT(spell_refresh); - OUT(classes); - //OUT(berserker); - //eq->max_level = emu->sof_max_level; - OUT(max_level); - OUT(last_id); - OUT(next_id); - OUT(cost2); - eq->aa_expansion = emu->aa_expansion; - eq->special_category = emu->special_category; - eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number - OUT(total_abilities); - unsigned int r; - for(r = 0; r < emu->total_abilities; r++) { - OUT(abilities[r].skill_id); - OUT(abilities[r].base1); - OUT(abilities[r].base2); - OUT(abilities[r].slot); - } - } - - Log.Out(Logs::General, Logs::Status, "%s", DumpPacketToString(__packet).c_str()); - FINISH_ENCODE(); -#endif } ENCODE(OP_SendCharInfo) diff --git a/common/ptimer.h b/common/ptimer.h index 8a559a148..7194ab49b 100644 --- a/common/ptimer.h +++ b/common/ptimer.h @@ -139,8 +139,4 @@ protected: std::map _list; }; -//code prettying macros -#define AA_Choose3(val, v1, v2, v3) (val==1?v1:(val==2?v2:v3)) -#define AA_Choose5(val, v1, v2, v3, v4, v5) (val==1?v1:(val==2?v2:(val==3?v3:(val==4?v4:v5)))) - #endif diff --git a/zone/aa.cpp b/zone/aa.cpp index c9fa78ab2..4bbdf88a6 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -37,35 +37,28 @@ Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) extern QueryServ* QServ; - -AA_DBAction AA_Actions[aaHighestID][MAX_AA_ACTION_RANKS]; //[aaid][rank] -std::mapaas_send; -std::map > aa_effects; //stores the effects from the aa_effects table in memory -std::map AARequiredLevelAndCost; - - int Client::GetAATimerID(aaID activate) { - SendAA_Struct* aa2 = zone->FindAA(activate); - - if(!aa2) - { - for(int i = 1;i < MAX_AA_ACTION_RANKS; ++i) - { - int a = activate - i; - - if(a <= 0) - break; - - aa2 = zone->FindAA(a); - - if(aa2 != nullptr) - break; - } - } - - if(aa2) - return aa2->spell_type; + //SendAA_Struct* aa2 = zone->FindAA(activate); + // + //if(!aa2) + //{ + // for(int i = 1;i < MAX_AA_ACTION_RANKS; ++i) + // { + // int a = activate - i; + // + // if(a <= 0) + // break; + // + // aa2 = zone->FindAA(a); + // + // if(aa2 != nullptr) + // break; + // } + //} + // + //if(aa2) + // return aa2->spell_type; return 0; } @@ -96,400 +89,400 @@ int Client::CalcAAReuseTimer(const AA_DBAction *caa) { } void Client::ActivateAA(aaID activate){ - if(activate < 0 || activate >= aaHighestID) - return; - if(IsStunned() || IsFeared() || IsMezzed() || IsSilenced() || IsPet() || IsSitting() || GetFeigned()) - return; - - int AATimerID = GetAATimerID(activate); - - SendAA_Struct* aa2 = nullptr; - aaID aaid = activate; - uint8 activate_val = GetAA(activate); - //this wasn't taking into acct multi tiered act talents before... - if(activate_val == 0){ - aa2 = zone->FindAA(activate); - if(!aa2){ - int i; - int a; - for(i=1;iFindAA(a); - if(aa2 != nullptr) - break; - } - } - if(aa2){ - aaid = (aaID) aa2->id; - activate_val = GetAA(aa2->id); - } - } - - if (activate_val == 0){ - return; - } - - if(aa2) - { - if(aa2->account_time_required) - { - if((Timer::GetTimeSeconds() + account_creation) < aa2->account_time_required) - { - return; - } - } - } - - if(!p_timers.Expired(&database, AATimerID + pTimerAAStart)) - { - uint32 aaremain = p_timers.GetRemainingTime(AATimerID + pTimerAAStart); - uint32 aaremain_hr = aaremain / (60 * 60); - uint32 aaremain_min = (aaremain / 60) % 60; - uint32 aaremain_sec = aaremain % 60; - - if(aa2) { - if (aaremain_hr >= 1) //1 hour or more - Message(13, "You can use the ability %s again in %u hour(s) %u minute(s) %u seconds", - aa2->name, aaremain_hr, aaremain_min, aaremain_sec); - else //less than an hour - Message(13, "You can use the ability %s again in %u minute(s) %u seconds", - aa2->name, aaremain_min, aaremain_sec); - } else { - if (aaremain_hr >= 1) //1 hour or more - Message(13, "You can use this ability again in %u hour(s) %u minute(s) %u seconds", - aaremain_hr, aaremain_min, aaremain_sec); - else //less than an hour - Message(13, "You can use this ability again in %u minute(s) %u seconds", - aaremain_min, aaremain_sec); - } - return; - } - - if(activate_val > MAX_AA_ACTION_RANKS) - activate_val = MAX_AA_ACTION_RANKS; - activate_val--; //to get array index. - - //get our current node, now that the indices are well bounded - const AA_DBAction *caa = &AA_Actions[aaid][activate_val]; - - if((aaid == aaImprovedHarmTouch || aaid == aaLeechTouch) && !p_timers.Expired(&database, pTimerHarmTouch)){ - Message(13,"Ability recovery time not yet met."); - return; - } - - //everything should be configured out now - - uint16 target_id = 0; - - //figure out our target - switch(caa->target) { - case aaTargetUser: - case aaTargetGroup: - target_id = GetID(); - break; - case aaTargetCurrent: - case aaTargetCurrentGroup: - if(GetTarget() == nullptr) { - Message_StringID(MT_DefaultText, AA_NO_TARGET); //You must first select a target for this ability! - p_timers.Clear(&database, AATimerID + pTimerAAStart); - return; - } - target_id = GetTarget()->GetID(); - break; - case aaTargetPet: - if(GetPet() == nullptr) { - Message(0, "A pet is required for this skill."); - return; - } - target_id = GetPetID(); - break; - } - - //handle non-spell action - if(caa->action != aaActionNone) { - if(caa->mana_cost > 0) { - if(GetMana() < caa->mana_cost) { - Message_StringID(13, INSUFFICIENT_MANA); - return; - } - SetMana(GetMana() - caa->mana_cost); - } - if(caa->reuse_time > 0) - { - uint32 timer_base = CalcAAReuseTimer(caa); - if(activate == aaImprovedHarmTouch || activate == aaLeechTouch) - { - p_timers.Start(pTimerHarmTouch, HarmTouchReuseTime); - } - p_timers.Start(AATimerID + pTimerAAStart, timer_base); - SendAATimer(AATimerID, 0, 0); - } - HandleAAAction(aaid); - } - - //cast the spell, if we have one - if(caa->spell_id > 0 && caa->spell_id < SPDAT_RECORDS) { - - if(caa->reuse_time > 0) - { - uint32 timer_base = CalcAAReuseTimer(caa); - SendAATimer(AATimerID, 0, 0); - p_timers.Start(AATimerID + pTimerAAStart, timer_base); - if(activate == aaImprovedHarmTouch || activate == aaLeechTouch) - { - p_timers.Start(pTimerHarmTouch, HarmTouchReuseTime); - } - // Bards can cast instant cast AAs while they are casting another song - if (spells[caa->spell_id].cast_time == 0 && GetClass() == BARD && IsBardSong(casting_spell_id)) { - if(!SpellFinished(caa->spell_id, entity_list.GetMob(target_id), 10, -1, -1, spells[caa->spell_id].ResistDiff, false)) { - //Reset on failed cast - SendAATimer(AATimerID, 0, 0xFFFFFF); - Message_StringID(15,ABILITY_FAILED); - p_timers.Clear(&database, AATimerID + pTimerAAStart); - return; - } - } else { - if (!CastSpell(caa->spell_id, target_id, USE_ITEM_SPELL_SLOT, -1, -1, 0, -1, AATimerID + pTimerAAStart, timer_base, 1)) { - //Reset on failed cast - SendAATimer(AATimerID, 0, 0xFFFFFF); - Message_StringID(15,ABILITY_FAILED); - p_timers.Clear(&database, AATimerID + pTimerAAStart); - return; - } - } - } - else - { - if(!CastSpell(caa->spell_id, target_id)) - return; - } - } - // Check if AA is expendable - if (aas_send[activate - activate_val]->special_category == 7) { - - // Add the AA cost to the extended profile to track overall total - m_epp.expended_aa += aas_send[activate]->cost; - - SetAA(activate, 0); - - SaveAA(); /* Save Character AA */ - SendAA(activate); - SendAATable(); - } +// if(activate < 0 || activate >= aaHighestID) +// return; +// if(IsStunned() || IsFeared() || IsMezzed() || IsSilenced() || IsPet() || IsSitting() || GetFeigned()) +// return; +// +// int AATimerID = GetAATimerID(activate); +// +// SendAA_Struct* aa2 = nullptr; +// aaID aaid = activate; +// uint8 activate_val = GetAA(activate); +// //this wasn't taking into acct multi tiered act talents before... +// if(activate_val == 0){ +// aa2 = zone->FindAA(activate); +// if(!aa2){ +// int i; +// int a; +// for(i=1;iFindAA(a); +// if(aa2 != nullptr) +// break; +// } +// } +// if(aa2){ +// aaid = (aaID) aa2->id; +// activate_val = GetAA(aa2->id); +// } +// } +// +// if (activate_val == 0){ +// return; +// } +// +// if(aa2) +// { +// if(aa2->account_time_required) +// { +// if((Timer::GetTimeSeconds() + account_creation) < aa2->account_time_required) +// { +// return; +// } +// } +// } +// +// if(!p_timers.Expired(&database, AATimerID + pTimerAAStart)) +// { +// uint32 aaremain = p_timers.GetRemainingTime(AATimerID + pTimerAAStart); +// uint32 aaremain_hr = aaremain / (60 * 60); +// uint32 aaremain_min = (aaremain / 60) % 60; +// uint32 aaremain_sec = aaremain % 60; +// +// if(aa2) { +// if (aaremain_hr >= 1) //1 hour or more +// Message(13, "You can use the ability %s again in %u hour(s) %u minute(s) %u seconds", +// aa2->name, aaremain_hr, aaremain_min, aaremain_sec); +// else //less than an hour +// Message(13, "You can use the ability %s again in %u minute(s) %u seconds", +// aa2->name, aaremain_min, aaremain_sec); +// } else { +// if (aaremain_hr >= 1) //1 hour or more +// Message(13, "You can use this ability again in %u hour(s) %u minute(s) %u seconds", +// aaremain_hr, aaremain_min, aaremain_sec); +// else //less than an hour +// Message(13, "You can use this ability again in %u minute(s) %u seconds", +// aaremain_min, aaremain_sec); +// } +// return; +// } +// +// if(activate_val > MAX_AA_ACTION_RANKS) +// activate_val = MAX_AA_ACTION_RANKS; +// activate_val--; //to get array index. +// +// //get our current node, now that the indices are well bounded +// const AA_DBAction *caa = &AA_Actions[aaid][activate_val]; +// +// if((aaid == aaImprovedHarmTouch || aaid == aaLeechTouch) && !p_timers.Expired(&database, pTimerHarmTouch)){ +// Message(13,"Ability recovery time not yet met."); +// return; +// } +// +// //everything should be configured out now +// +// uint16 target_id = 0; +// +// //figure out our target +// switch(caa->target) { +// case aaTargetUser: +// case aaTargetGroup: +// target_id = GetID(); +// break; +// case aaTargetCurrent: +// case aaTargetCurrentGroup: +// if(GetTarget() == nullptr) { +// Message_StringID(MT_DefaultText, AA_NO_TARGET); //You must first select a target for this ability! +// p_timers.Clear(&database, AATimerID + pTimerAAStart); +// return; +// } +// target_id = GetTarget()->GetID(); +// break; +// case aaTargetPet: +// if(GetPet() == nullptr) { +// Message(0, "A pet is required for this skill."); +// return; +// } +// target_id = GetPetID(); +// break; +// } +// +// //handle non-spell action +// if(caa->action != aaActionNone) { +// if(caa->mana_cost > 0) { +// if(GetMana() < caa->mana_cost) { +// Message_StringID(13, INSUFFICIENT_MANA); +// return; +// } +// SetMana(GetMana() - caa->mana_cost); +// } +// if(caa->reuse_time > 0) +// { +// uint32 timer_base = CalcAAReuseTimer(caa); +// if(activate == aaImprovedHarmTouch || activate == aaLeechTouch) +// { +// p_timers.Start(pTimerHarmTouch, HarmTouchReuseTime); +// } +// p_timers.Start(AATimerID + pTimerAAStart, timer_base); +// SendAATimer(AATimerID, 0, 0); +// } +// HandleAAAction(aaid); +// } +// +// //cast the spell, if we have one +// if(caa->spell_id > 0 && caa->spell_id < SPDAT_RECORDS) { +// +// if(caa->reuse_time > 0) +// { +// uint32 timer_base = CalcAAReuseTimer(caa); +// SendAATimer(AATimerID, 0, 0); +// p_timers.Start(AATimerID + pTimerAAStart, timer_base); +// if(activate == aaImprovedHarmTouch || activate == aaLeechTouch) +// { +// p_timers.Start(pTimerHarmTouch, HarmTouchReuseTime); +// } +// // Bards can cast instant cast AAs while they are casting another song +// if (spells[caa->spell_id].cast_time == 0 && GetClass() == BARD && IsBardSong(casting_spell_id)) { +// if(!SpellFinished(caa->spell_id, entity_list.GetMob(target_id), 10, -1, -1, spells[caa->spell_id].ResistDiff, false)) { +// //Reset on failed cast +// SendAATimer(AATimerID, 0, 0xFFFFFF); +// Message_StringID(15,ABILITY_FAILED); +// p_timers.Clear(&database, AATimerID + pTimerAAStart); +// return; +// } +// } else { +// if (!CastSpell(caa->spell_id, target_id, USE_ITEM_SPELL_SLOT, -1, -1, 0, -1, AATimerID + pTimerAAStart, timer_base, 1)) { +// //Reset on failed cast +// SendAATimer(AATimerID, 0, 0xFFFFFF); +// Message_StringID(15,ABILITY_FAILED); +// p_timers.Clear(&database, AATimerID + pTimerAAStart); +// return; +// } +// } +// } +// else +// { +// if(!CastSpell(caa->spell_id, target_id)) +// return; +// } +// } +// // Check if AA is expendable +// if (aas_send[activate - activate_val]->special_category == 7) { +// +// // Add the AA cost to the extended profile to track overall total +// m_epp.expended_aa += aas_send[activate]->cost; +// +// SetAA(activate, 0); +// +// SaveAA(); /* Save Character AA */ +// SendAA(activate); +// SendAATable(); +// } } void Client::HandleAAAction(aaID activate) { - if(activate < 0 || activate >= aaHighestID) - return; - - uint8 activate_val = GetAA(activate); - - if (activate_val == 0) - return; - - if(activate_val > MAX_AA_ACTION_RANKS) - activate_val = MAX_AA_ACTION_RANKS; - activate_val--; //to get array index. - - //get our current node, now that the indices are well bounded - const AA_DBAction *caa = &AA_Actions[activate][activate_val]; - - uint16 timer_id = 0; - uint16 timer_duration = caa->duration; - aaTargetType target = aaTargetUser; - - uint16 spell_id = SPELL_UNKNOWN; //gets cast at the end if not still unknown - - switch(caa->action) { - case aaActionAETaunt: - entity_list.AETaunt(this); - break; - - case aaActionFlamingArrows: - //toggle it - if(CheckAAEffect(aaEffectFlamingArrows)) - EnableAAEffect(aaEffectFlamingArrows); - else - DisableAAEffect(aaEffectFlamingArrows); - break; - - case aaActionFrostArrows: - if(CheckAAEffect(aaEffectFrostArrows)) - EnableAAEffect(aaEffectFrostArrows); - else - DisableAAEffect(aaEffectFrostArrows); - break; - - case aaActionRampage: - EnableAAEffect(aaEffectRampage, 10); - break; - - case aaActionSharedHealth: - if(CheckAAEffect(aaEffectSharedHealth)) - EnableAAEffect(aaEffectSharedHealth); - else - DisableAAEffect(aaEffectSharedHealth); - break; - - case aaActionCelestialRegen: { - //special because spell_id depends on a different AA - switch (GetAA(aaCelestialRenewal)) { - case 1: - spell_id = 3250; - break; - case 2: - spell_id = 3251; - break; - default: - spell_id = 2740; - break; - } - target = aaTargetCurrent; - break; - } - - case aaActionDireCharm: { - //special because spell_id depends on class - switch (GetClass()) - { - case DRUID: - spell_id = 2760; //2644? - break; - case NECROMANCER: - spell_id = 2759; //2643? - break; - case ENCHANTER: - spell_id = 2761; //2642? - break; - } - target = aaTargetCurrent; - break; - } - - case aaActionImprovedFamiliar: { - //Spell IDs might be wrong... - if (GetAA(aaAllegiantFamiliar)) - spell_id = 3264; //1994? - else - spell_id = 2758; //2155? - break; - } - - case aaActionActOfValor: - if(GetTarget() != nullptr) { - int curhp = GetTarget()->GetHP(); - target = aaTargetCurrent; - GetTarget()->HealDamage(curhp, this); - Death(this, 0, SPELL_UNKNOWN, SkillHandtoHand); - } - break; - - case aaActionSuspendedMinion: - if (GetPet()) { - target = aaTargetPet; - switch (GetAA(aaSuspendedMinion)) { - case 1: - spell_id = 3248; - break; - case 2: - spell_id = 3249; - break; - } - //do we really need to cast a spell? - - Message(0,"You call your pet to your side."); - GetPet()->WipeHateList(); - GetPet()->GMMove(GetX(),GetY(),GetZ()); - if (activate_val > 1) - entity_list.ClearFeignAggro(GetPet()); - } else { - Message(0,"You have no pet to call."); - } - break; - - case aaActionEscape: - Escape(); - break; - - // Don't think this code is used any longer for Bestial Alignment as the aa.has a spell_id and no nonspell_action. - case aaActionBeastialAlignment: - switch(GetBaseRace()) { - case BARBARIAN: - spell_id = AA_Choose3(activate_val, 4521, 4522, 4523); - break; - case TROLL: - spell_id = AA_Choose3(activate_val, 4524, 4525, 4526); - break; - case OGRE: - spell_id = AA_Choose3(activate_val, 4527, 4527, 4529); - break; - case IKSAR: - spell_id = AA_Choose3(activate_val, 4530, 4531, 4532); - break; - case VAHSHIR: - spell_id = AA_Choose3(activate_val, 4533, 4534, 4535); - break; - } - - case aaActionLeechTouch: - target = aaTargetCurrent; - spell_id = SPELL_HARM_TOUCH2; - EnableAAEffect(aaEffectLeechTouch, 1000); - break; - - case aaActionFadingMemories: - // Do nothing since spell effect works correctly, but mana isn't used. - break; - - default: - Log.Out(Logs::General, Logs::Error, "Unknown AA nonspell action type %d", caa->action); - return; - } - - - uint16 target_id = 0; - //figure out our target - switch(target) { - case aaTargetUser: - case aaTargetGroup: - target_id = GetID(); - break; - case aaTargetCurrent: - case aaTargetCurrentGroup: - if(GetTarget() == nullptr) { - Message_StringID(MT_DefaultText, AA_NO_TARGET); //You must first select a target for this ability! - p_timers.Clear(&database, timer_id + pTimerAAEffectStart); - return; - } - target_id = GetTarget()->GetID(); - break; - case aaTargetPet: - if(GetPet() == nullptr) { - Message(0, "A pet is required for this skill."); - return; - } - target_id = GetPetID(); - break; - } - - //cast the spell, if we have one - if(IsValidSpell(spell_id)) { - int aatid = GetAATimerID(activate); - if (!CastSpell(spell_id, target_id, USE_ITEM_SPELL_SLOT, -1, -1, 0, -1, pTimerAAStart + aatid, CalcAAReuseTimer(caa), 1)) { - SendAATimer(aatid, 0, 0xFFFFFF); - Message_StringID(15,ABILITY_FAILED); - p_timers.Clear(&database, pTimerAAStart + aatid); - return; - } - } - - //handle the duration timer if we have one. - if(timer_id > 0 && timer_duration > 0) { - p_timers.Start(pTimerAAEffectStart + timer_id, timer_duration); - } +// if(activate < 0 || activate >= aaHighestID) +// return; +// +// uint8 activate_val = GetAA(activate); +// +// if (activate_val == 0) +// return; +// +// if(activate_val > MAX_AA_ACTION_RANKS) +// activate_val = MAX_AA_ACTION_RANKS; +// activate_val--; //to get array index. +// +// //get our current node, now that the indices are well bounded +// const AA_DBAction *caa = &AA_Actions[activate][activate_val]; +// +// uint16 timer_id = 0; +// uint16 timer_duration = caa->duration; +// aaTargetType target = aaTargetUser; +// +// uint16 spell_id = SPELL_UNKNOWN; //gets cast at the end if not still unknown +// +// switch(caa->action) { +// case aaActionAETaunt: +// entity_list.AETaunt(this); +// break; +// +// case aaActionFlamingArrows: +// //toggle it +// if(CheckAAEffect(aaEffectFlamingArrows)) +// EnableAAEffect(aaEffectFlamingArrows); +// else +// DisableAAEffect(aaEffectFlamingArrows); +// break; +// +// case aaActionFrostArrows: +// if(CheckAAEffect(aaEffectFrostArrows)) +// EnableAAEffect(aaEffectFrostArrows); +// else +// DisableAAEffect(aaEffectFrostArrows); +// break; +// +// case aaActionRampage: +// EnableAAEffect(aaEffectRampage, 10); +// break; +// +// case aaActionSharedHealth: +// if(CheckAAEffect(aaEffectSharedHealth)) +// EnableAAEffect(aaEffectSharedHealth); +// else +// DisableAAEffect(aaEffectSharedHealth); +// break; +// +// case aaActionCelestialRegen: { +// //special because spell_id depends on a different AA +// switch (GetAA(aaCelestialRenewal)) { +// case 1: +// spell_id = 3250; +// break; +// case 2: +// spell_id = 3251; +// break; +// default: +// spell_id = 2740; +// break; +// } +// target = aaTargetCurrent; +// break; +// } +// +// case aaActionDireCharm: { +// //special because spell_id depends on class +// switch (GetClass()) +// { +// case DRUID: +// spell_id = 2760; //2644? +// break; +// case NECROMANCER: +// spell_id = 2759; //2643? +// break; +// case ENCHANTER: +// spell_id = 2761; //2642? +// break; +// } +// target = aaTargetCurrent; +// break; +// } +// +// case aaActionImprovedFamiliar: { +// //Spell IDs might be wrong... +// if (GetAA(aaAllegiantFamiliar)) +// spell_id = 3264; //1994? +// else +// spell_id = 2758; //2155? +// break; +// } +// +// case aaActionActOfValor: +// if(GetTarget() != nullptr) { +// int curhp = GetTarget()->GetHP(); +// target = aaTargetCurrent; +// GetTarget()->HealDamage(curhp, this); +// Death(this, 0, SPELL_UNKNOWN, SkillHandtoHand); +// } +// break; +// +// case aaActionSuspendedMinion: +// if (GetPet()) { +// target = aaTargetPet; +// switch (GetAA(aaSuspendedMinion)) { +// case 1: +// spell_id = 3248; +// break; +// case 2: +// spell_id = 3249; +// break; +// } +// //do we really need to cast a spell? +// +// Message(0,"You call your pet to your side."); +// GetPet()->WipeHateList(); +// GetPet()->GMMove(GetX(),GetY(),GetZ()); +// if (activate_val > 1) +// entity_list.ClearFeignAggro(GetPet()); +// } else { +// Message(0,"You have no pet to call."); +// } +// break; +// +// case aaActionEscape: +// Escape(); +// break; +// +// // Don't think this code is used any longer for Bestial Alignment as the aa.has a spell_id and no nonspell_action. +// case aaActionBeastialAlignment: +// switch(GetBaseRace()) { +// case BARBARIAN: +// spell_id = AA_Choose3(activate_val, 4521, 4522, 4523); +// break; +// case TROLL: +// spell_id = AA_Choose3(activate_val, 4524, 4525, 4526); +// break; +// case OGRE: +// spell_id = AA_Choose3(activate_val, 4527, 4527, 4529); +// break; +// case IKSAR: +// spell_id = AA_Choose3(activate_val, 4530, 4531, 4532); +// break; +// case VAHSHIR: +// spell_id = AA_Choose3(activate_val, 4533, 4534, 4535); +// break; +// } +// +// case aaActionLeechTouch: +// target = aaTargetCurrent; +// spell_id = SPELL_HARM_TOUCH2; +// EnableAAEffect(aaEffectLeechTouch, 1000); +// break; +// +// case aaActionFadingMemories: +// // Do nothing since spell effect works correctly, but mana isn't used. +// break; +// +// default: +// Log.Out(Logs::General, Logs::Error, "Unknown AA nonspell action type %d", caa->action); +// return; +// } +// +// +// uint16 target_id = 0; +// //figure out our target +// switch(target) { +// case aaTargetUser: +// case aaTargetGroup: +// target_id = GetID(); +// break; +// case aaTargetCurrent: +// case aaTargetCurrentGroup: +// if(GetTarget() == nullptr) { +// Message_StringID(MT_DefaultText, AA_NO_TARGET); //You must first select a target for this ability! +// p_timers.Clear(&database, timer_id + pTimerAAEffectStart); +// return; +// } +// target_id = GetTarget()->GetID(); +// break; +// case aaTargetPet: +// if(GetPet() == nullptr) { +// Message(0, "A pet is required for this skill."); +// return; +// } +// target_id = GetPetID(); +// break; +// } +// +// //cast the spell, if we have one +// if(IsValidSpell(spell_id)) { +// int aatid = GetAATimerID(activate); +// if (!CastSpell(spell_id, target_id, USE_ITEM_SPELL_SLOT, -1, -1, 0, -1, pTimerAAStart + aatid, CalcAAReuseTimer(caa), 1)) { +// SendAATimer(aatid, 0, 0xFFFFFF); +// Message_StringID(15,ABILITY_FAILED); +// p_timers.Clear(&database, pTimerAAStart + aatid); +// return; +// } +// } +// +// //handle the duration timer if we have one. +// if(timer_id > 0 && timer_duration > 0) { +// p_timers.Start(pTimerAAEffectStart + timer_id, timer_duration); +// } } void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, uint32 duration_override, bool followme, bool sticktarg) { @@ -937,130 +930,119 @@ bool Client::CheckAAEffect(aaEffectType type) { return(false); } -void Client::SendAAStats() { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_AAExpUpdate, sizeof(AltAdvStats_Struct)); - AltAdvStats_Struct *aps = (AltAdvStats_Struct *)outapp->pBuffer; - aps->experience = m_pp.expAA; - aps->experience = (uint32)(((float)330.0f * (float)m_pp.expAA) / (float)max_AAXP); - aps->unspent = m_pp.aapoints; - aps->percentage = m_epp.perAA; - QueuePacket(outapp); - safe_delete(outapp); -} - void Client::BuyAA(AA_Action* action) { - Log.Out(Logs::Detail, Logs::AA, "Starting to buy AA %d", action->ability); - - //find the AA information from the database - SendAA_Struct* aa2 = zone->FindAA(action->ability); - if(!aa2) { - //hunt for a lower level... - int i; - int a; - for(i=1;iability - i; - if(a <= 0) - break; - Log.Out(Logs::Detail, Logs::AA, "Could not find AA %d, trying potential parent %d", action->ability, a); - aa2 = zone->FindAA(a); - if(aa2 != nullptr) - break; - } - } - if(aa2 == nullptr) - return; //invalid ability... - - if(aa2->special_category == 1 || aa2->special_category == 2) - return; // Not purchasable progression style AAs - - if(aa2->special_category == 8 && aa2->cost == 0) - return; // Not purchasable racial AAs(set a cost to make them purchasable) - - uint32 cur_level = GetAA(aa2->id); - if((aa2->id + cur_level) != action->ability) { //got invalid AA - Log.Out(Logs::Detail, Logs::AA, "Unable to find or match AA %d (found %d + lvl %d)", action->ability, aa2->id, cur_level); - return; - } - - if(aa2->account_time_required) - { - if((Timer::GetTimeSeconds() - account_creation) < aa2->account_time_required) - { - return; - } - } - - uint32 real_cost; - uint8 req_level; - std::map::iterator RequiredLevel = AARequiredLevelAndCost.find(action->ability); - - if(RequiredLevel != AARequiredLevelAndCost.end()) { - real_cost = RequiredLevel->second.Cost; - req_level = RequiredLevel->second.Level; - } - else { - real_cost = aa2->cost + (aa2->cost_inc * cur_level); - req_level = aa2->class_type + (aa2->level_inc * cur_level); - } - - if (req_level > GetLevel()) - return; //Cheater trying to Buy AA... - - if (m_pp.aapoints >= real_cost && cur_level < aa2->max_level) { - SetAA(aa2->id, cur_level + 1); - - Log.Out(Logs::Detail, Logs::AA, "Set AA %d to level %d", aa2->id, cur_level + 1); - - m_pp.aapoints -= real_cost; - - /* Do Player Profile rank calculations and set player profile */ - SaveAA(); - /* Save to Database to avoid having to write the whole AA array to the profile, only write changes*/ - // database.SaveCharacterAA(this->CharacterID(), aa2->id, (cur_level + 1)); - - if ((RuleB(AA, Stacking) && (GetClientVersionBit() >= 4) && (aa2->hotkey_sid == 4294967295u)) - && ((aa2->max_level == (cur_level + 1)) && aa2->sof_next_id)){ - SendAA(aa2->id); - SendAA(aa2->sof_next_id); - } - else - SendAA(aa2->id); - - SendAATable(); - - /* - We are building these messages ourself instead of using the stringID to work around patch discrepencies - these are AA_GAIN_ABILITY (410) & AA_IMPROVE (411), respectively, in both Titanium & SoF. not sure about 6.2 - */ - - /* Initial purchase of an AA ability */ - if (cur_level < 1){ - Message(15, "You have gained the ability \"%s\" at a cost of %d ability %s.", aa2->name, real_cost, (real_cost>1) ? "points" : "point"); - - /* QS: Player_Log_AA_Purchases */ - if (RuleB(QueryServ, PlayerLogAAPurchases)){ - std::string event_desc = StringFormat("Initial AA Purchase :: aa_name:%s aa_id:%i at cost:%i in zoneid:%i instid:%i", aa2->name, aa2->id, real_cost, this->GetZoneID(), this->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc); - } - } - /* Ranked purchase of an AA ability */ - else{ - Message(15, "You have improved %s %d at a cost of %d ability %s.", aa2->name, cur_level + 1, real_cost, (real_cost > 1) ? "points" : "point"); - - /* QS: Player_Log_AA_Purchases */ - if (RuleB(QueryServ, PlayerLogAAPurchases)){ - std::string event_desc = StringFormat("Ranked AA Purchase :: aa_name:%s aa_id:%i at cost:%i in zoneid:%i instid:%i", aa2->name, aa2->id, real_cost, this->GetZoneID(), this->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc); - } - } - - SendAAStats(); - - CalcBonuses(); - if(title_manager.IsNewAATitleAvailable(m_pp.aapoints_spent, GetBaseClass())) - NotifyNewTitlesAvailable(); - } + //Log.Out(Logs::Detail, Logs::AA, "Starting to buy AA %d", action->ability); + // + ////find the AA information from the database + //SendAA_Struct* aa2 = zone->FindAA(action->ability); + ////if(!aa2) { + //// //hunt for a lower level... + //// int i; + //// int a; + //// for(i=1;iability - i; + //// if(a <= 0) + //// break; + //// Log.Out(Logs::Detail, Logs::AA, "Could not find AA %d, trying potential parent %d", action->ability, a); + //// aa2 = zone->FindAA(a); + //// if(aa2 != nullptr) + //// break; + //// } + ////} + //if(aa2 == nullptr) + // return; //invalid ability... + // + //if(aa2->special_category == 1 || aa2->special_category == 2) + // return; // Not purchasable progression style AAs + // + //if(aa2->special_category == 8 && aa2->cost == 0) + // return; // Not purchasable racial AAs(set a cost to make them purchasable) + // + //uint32 cur_level = GetAA(aa2->id); + //if((aa2->id + cur_level) != action->ability) { //got invalid AA + // Log.Out(Logs::Detail, Logs::AA, "Unable to find or match AA %d (found %d + lvl %d)", action->ability, aa2->id, cur_level); + // return; + //} + // + //if(aa2->account_time_required) + //{ + // if((Timer::GetTimeSeconds() - account_creation) < aa2->account_time_required) + // { + // return; + // } + //} + // + //uint32 real_cost; + //uint8 req_level; + ////std::map::iterator RequiredLevel = AARequiredLevelAndCost.find(action->ability); + //// + ////if(RequiredLevel != AARequiredLevelAndCost.end()) { + //// real_cost = RequiredLevel->second.Cost; + //// req_level = RequiredLevel->second.Level; + ////} + ////else { + //// real_cost = aa2->cost + (aa2->cost_inc * cur_level); + //// req_level = aa2->class_type + (aa2->level_inc * cur_level); + ////} + // + //if (req_level > GetLevel()) + // return; //Cheater trying to Buy AA... + // + //if (m_pp.aapoints >= real_cost && cur_level < aa2->max_level) { + // SetAA(aa2->id, cur_level + 1); + // + // Log.Out(Logs::Detail, Logs::AA, "Set AA %d to level %d", aa2->id, cur_level + 1); + // + // m_pp.aapoints -= real_cost; + // + // /* Do Player Profile rank calculations and set player profile */ + // SaveAA(); + // /* Save to Database to avoid having to write the whole AA array to the profile, only write changes*/ + // // database.SaveCharacterAA(this->CharacterID(), aa2->id, (cur_level + 1)); + // + // if ((RuleB(AA, Stacking) && (GetClientVersionBit() >= 4) && (aa2->hotkey_sid == 4294967295u)) + // && ((aa2->max_level == (cur_level + 1)) && aa2->sof_next_id)){ + // SendAA(aa2->id); + // SendAA(aa2->sof_next_id); + // } + // else + // SendAA(aa2->id); + // + // SendAATable(); + // + // /* + // We are building these messages ourself instead of using the stringID to work around patch discrepencies + // these are AA_GAIN_ABILITY (410) & AA_IMPROVE (411), respectively, in both Titanium & SoF. not sure about 6.2 + // */ + // + // /* Initial purchase of an AA ability */ + // if (cur_level < 1){ + // Message(15, "You have gained the ability \"%s\" at a cost of %d ability %s.", aa2->name, real_cost, (real_cost>1) ? "points" : "point"); + // + // /* QS: Player_Log_AA_Purchases */ + // if (RuleB(QueryServ, PlayerLogAAPurchases)){ + // std::string event_desc = StringFormat("Initial AA Purchase :: aa_name:%s aa_id:%i at cost:%i in zoneid:%i instid:%i", aa2->name, aa2->id, real_cost, this->GetZoneID(), this->GetInstanceID()); + // QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc); + // } + // } + // /* Ranked purchase of an AA ability */ + // else{ + // Message(15, "You have improved %s %d at a cost of %d ability %s.", aa2->name, cur_level + 1, real_cost, (real_cost > 1) ? "points" : "point"); + // + // /* QS: Player_Log_AA_Purchases */ + // if (RuleB(QueryServ, PlayerLogAAPurchases)){ + // std::string event_desc = StringFormat("Ranked AA Purchase :: aa_name:%s aa_id:%i at cost:%i in zoneid:%i instid:%i", aa2->name, aa2->id, real_cost, this->GetZoneID(), this->GetInstanceID()); + // QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc); + // } + // } + // + // //SendAAStats(); + // + // CalcBonuses(); + // if(title_manager.IsNewAATitleAvailable(m_pp.aapoints_spent, GetBaseClass())) + // NotifyNewTitlesAvailable(); + //} } void Client::SendAATimer(uint32 ability, uint32 begin, uint32 end) { @@ -1096,114 +1078,50 @@ void Client::SendAATimers() { safe_delete(outapp); } -void Client::SendAATable() { - //Log.Out(Logs::General, Logs::Status, "SendAATable()"); - //EQApplicationPacket* outapp = new EQApplicationPacket(OP_RespondAA, sizeof(AATable_Struct)); - // - //AATable_Struct* aa2 = (AATable_Struct *)outapp->pBuffer; - //aa2->aa_spent = 10; - //aa2->aa_list[0].AA = 6; - //aa2->aa_list[0].value = 4; - //aa2->aa_list[0].charges = 0; - //aa2->aa_list[1].AA = 11; - //aa2->aa_list[1].value = 4; - //aa2->aa_list[1].charges = 0; - // - ////aa2->aa_spent = GetAAPointsSpent(); - //// - ////uint32 i; - ////for(i=0;i < MAX_PP_AA_ARRAY;i++){ - //// aa2->aa_list[i].AA = aa[i]->value ? aa[i]->AA : 0; // bit of a hack to prevent expendables punching a hole - //// aa2->aa_list[i].value = aa[i]->value; - //// aa2->aa_list[i].charges = aa[i]->charges; - ////} - //QueuePacket(outapp); - //safe_delete(outapp); -} - void Client::SendPreviousAA(uint32 id, int seq){ - Log.Out(Logs::General, Logs::Status, "SendPreviousAA(%u, %i)", id, seq); - uint32 value=0; - SendAA_Struct* saa2 = nullptr; - if(id==0) - saa2 = zone->GetAABySequence(seq); - else - saa2 = zone->FindAA(id); - if(!saa2) - return; - int size=sizeof(SendAA_Struct)+sizeof(AA_Ability)*saa2->total_abilities; - uchar* buffer = new uchar[size]; - SendAA_Struct* saa=(SendAA_Struct*)buffer; - value = GetAA(saa2->id); - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SendAATable); - outapp->size=size; - outapp->pBuffer=(uchar*)saa; - value--; - memcpy(saa,saa2,size); - - if(value>0){ - if(saa->spellid==0) - saa->spellid=0xFFFFFFFF; - saa->id+=value; - saa->next_id=saa->id+1; - if(value==1) - saa->last_id=saa2->id; - else - saa->last_id=saa->id-1; - saa->current_level=value+1; - saa->cost2 = 0; //cost 2 is what the client uses to calc how many points we've spent, so we have to add up the points in order - for(uint32 i = 0; i < (value+1); i++) { - saa->cost2 += saa->cost + (saa->cost_inc * i); - } - } - - database.FillAAEffects(saa); - Log.Out(Logs::General, Logs::Status, "%s", DumpPacketToString(outapp).c_str()); - QueuePacket(outapp); - safe_delete(outapp); } void Client::SendAA(uint32 id, int seq) { - Log.Out(Logs::General, Logs::Status, "SendAA(%u, %i)", id, seq); - - uint32 value=0; - SendAA_Struct* saa2 = nullptr; - SendAA_Struct* qaa = nullptr; - SendAA_Struct* saa_pp = nullptr; - bool IsBaseLevel = true; - bool aa_stack = false; - - if(id==0) - saa2 = zone->GetAABySequence(seq); - else - saa2 = zone->FindAA(id); - if(!saa2) - return; - - uint16 classes = saa2->classes; - if(!(classes & (1 << GetClass())) && (GetClass()!=BERSERKER || saa2->berserker==0)){ - return; - } - - if(saa2->account_time_required) - { - if((Timer::GetTimeSeconds() - account_creation) < saa2->account_time_required) - { - return; - } - } - - // Hide Quest/Progression AAs unless player has been granted the first level using $client->IncrementAA(skill_id). - if (saa2->special_category == 1 || saa2->special_category == 2 ) { - if(GetAA(saa2->id) == 0) - return; - // For Quest line AA(demiplane AEs) where only 1 is visible at a time, check to make sure only the highest level obtained is shown - if(saa2->aa_expansion > 0) { - qaa = zone->FindAA(saa2->id+1); - if(qaa && (saa2->aa_expansion == qaa->aa_expansion) && GetAA(qaa->id) > 0) - return; - } - } + //Log.Out(Logs::General, Logs::Status, "SendAA(%u, %i)", id, seq); + // + //uint32 value=0; + //SendAA_Struct* saa2 = nullptr; + //SendAA_Struct* qaa = nullptr; + //SendAA_Struct* saa_pp = nullptr; + //bool IsBaseLevel = true; + //bool aa_stack = false; + // + //if(id==0) + // saa2 = zone->GetAABySequence(seq); + //else + // saa2 = zone->FindAA(id); + //if(!saa2) + // return; + // + //uint16 classes = saa2->classes; + //if(!(classes & (1 << GetClass())) && (GetClass()!=BERSERKER || saa2->berserker==0)){ + // return; + //} + // + //if(saa2->account_time_required) + //{ + // if((Timer::GetTimeSeconds() - account_creation) < saa2->account_time_required) + // { + // return; + // } + //} + // + //// Hide Quest/Progression AAs unless player has been granted the first level using $client->IncrementAA(skill_id). + //if (saa2->special_category == 1 || saa2->special_category == 2 ) { + // if(GetAA(saa2->id) == 0) + // return; + // // For Quest line AA(demiplane AEs) where only 1 is visible at a time, check to make sure only the highest level obtained is shown + // if(saa2->aa_expansion > 0) { + // qaa = zone->FindAA(saa2->id+1); + // if(qaa && (saa2->aa_expansion == qaa->aa_expansion) && GetAA(qaa->id) > 0) + // return; + // } + //} /* Beginning of Shroud AAs, these categories are for Passive and Active Shroud AAs Eventually with a toggle we could have it show player list or shroud list @@ -1211,250 +1129,182 @@ void Client::SendAA(uint32 id, int seq) { return; */ // Check for racial/Drakkin blood line AAs - if (saa2->special_category == 8) - { - uint32 client_race = this->GetBaseRace(); - - // Drakkin Bloodlines - if (saa2->aa_expansion > 522) - { - if (client_race != 522) - return; // Check for Drakkin Race - - int heritage = this->GetDrakkinHeritage() + 523; // 523 = Drakkin Race(522) + Bloodline - - if (heritage != saa2->aa_expansion) - return; - } - // Racial AAs - else if (client_race != saa2->aa_expansion) - { - return; - } - } - - /* - AA stacking on SoF+ clients. - - Note: There were many ways to achieve this effect - The method used proved to be the most straight forward and consistent. - Stacking does not currently work ideally for AA's that use hotkeys, therefore they will be excluded at this time. - - TODO: Problem with aa.hotkeys - When you reach max rank of an AA tier (ie 5/5), it automatically displays the next AA in - the series and you can not transfer the hotkey to the next AA series. To the best of the my ability and through many - different variations of coding I could not find an ideal solution to this issue. - - How stacking works: - Utilizes two new fields: sof_next_id (which is the next id in the series), sof_current_level (ranks the AA's as the current level) - 1) If no AA's purchased only display the base levels of each AA series. - 2) When you purchase an AA and its rank is maxed it sends the packet for the completed AA, and the packet - for the next aa in the series. The previous tier is removed from your window, and the new AA is displayed. - 3) When you zone/buy your player profile will be checked and determine what AA can be displayed base on what you have already. - */ - - 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 (saa2->special_category == 8) + //{ + // uint32 client_race = this->GetBaseRace(); // - // if (aa_AA){ + // // Drakkin Bloodlines + // if (saa2->aa_expansion > 522) + // { + // if (client_race != 522) + // return; // Check for Drakkin Race // - // if (aa_value > 0) - // aa_AA -= aa_value-1; + // int heritage = this->GetDrakkinHeritage() + 523; // 523 = Drakkin Race(522) + Bloodline // - // 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 (heritage != saa2->aa_expansion) + // return; + // } + // // Racial AAs + // else if (client_race != saa2->aa_expansion) + // { + // return; // } //} - - //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) - return; - - int size=sizeof(SendAA_Struct)+sizeof(AA_Ability)*saa2->total_abilities; - - if(size == 0) - return; - - uchar* buffer = new uchar[size]; - SendAA_Struct* saa=(SendAA_Struct*)buffer; - memcpy(saa,saa2,size); - - if(saa->spellid==0) - saa->spellid=0xFFFFFFFF; - - value=GetAA(saa->id); - uint32 orig_val = value; - - if(value && saa->id){ - - if(value < saa->max_level){ - saa->id+=value; - saa->next_id=saa->id+1; - value++; - } - - else if (aa_stack && saa->sof_next_id){ - saa->id+=value-1; - saa->next_id=saa->sof_next_id; - - //Prevent removal of previous AA from window if next AA belongs to a higher client version. - SendAA_Struct* saa_next = nullptr; - saa_next = zone->FindAA(saa->sof_next_id); - - // this check should work as long as we continue to just add the clients and just increase - // each number .... - if (saa_next && static_cast(GetClientVersion()) < saa_next->clientver - 1) { - saa->next_id=0xFFFFFFFF; - } - } - - else{ - saa->id+=value-1; - saa->next_id=0xFFFFFFFF; - } - - uint32 current_level_mod = 0; - if (aa_stack) - current_level_mod = saa->sof_current_level; - - saa->last_id=saa->id-1; - saa->current_level=value+(current_level_mod); - saa->cost = saa2->cost + (saa2->cost_inc*(value-1)); - saa->cost2 = 0; - for(uint32 i = 0; i < value; i++) { - saa->cost2 += saa2->cost + (saa2->cost_inc * i); - } - saa->class_type = saa2->class_type + (saa2->level_inc*(value-1)); - } - - if (aa_stack){ - - if (saa->sof_current_level >= 1 && value == 0) - saa->current_level = saa->sof_current_level+1; - - saa->max_level = saa->sof_max_level; - } - - database.FillAAEffects(saa); - - if(value > 0) - { - // AA_Action stores the base ID - const AA_DBAction *caa = &AA_Actions[saa->id - value + 1][value - 1]; - - if(caa && caa->reuse_time > 0) - saa->spell_refresh = CalcAAReuseTimer(caa); - } - - //You can now use the level_inc field in the altadv_vars table to accomplish this, though still needed - //for special cases like LOH/HT due to inability to implement correct stacking of AA's that use hotkeys. - std::map::iterator RequiredLevel = AARequiredLevelAndCost.find(saa->id); - - if(RequiredLevel != AARequiredLevelAndCost.end()) - { - saa->class_type = RequiredLevel->second.Level; - saa->cost = RequiredLevel->second.Cost; - } - - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_SendAATable); - outapp->size=size; - outapp->pBuffer=(uchar*)saa; - - if(id==0 && value && (orig_val < saa->max_level)) //send previous AA only on zone in - SendPreviousAA(id, seq); - - QueuePacket(outapp); - safe_delete(outapp); - //will outapp delete the buffer for us even though it didnt make it? --- Yes, it should -} - -void Client::SendAAList(){ - Log.Out(Logs::General, Logs::Status, "SendAAList()"); - int total = zone->GetTotalAAs(); - - total = total > 2 ? 2 : total; - for(int i=0;i < total;i++){ - SendAA(0,i); - } -} - -SendAA_Struct* Zone::FindAA(uint32 id) { - return aas_send[id]; -} - -void Zone::LoadAAs() { - Log.Out(Logs::General, Logs::Status, "Loading AA information..."); - totalAAs = database.CountAAs(); - if(totalAAs == 0) { - Log.Out(Logs::General, Logs::Error, "Failed to load AAs!"); - aas = nullptr; - return; - } - aas = new SendAA_Struct *[totalAAs]; - - database.LoadAAs(aas); - - int i; - for(i=0; i < totalAAs; i++){ - SendAA_Struct* aa = aas[i]; - aas_send[aa->id] = aa; - } - - //load AA Effects into aa_effects - Log.Out(Logs::General, Logs::Status, "Loading AA Effects..."); - if (database.LoadAAEffects2()) - Log.Out(Logs::General, Logs::Status, "Loaded %d AA Effects.", aa_effects.size()); - else - Log.Out(Logs::General, Logs::Error, "Failed to load AA Effects!"); -} - -bool ZoneDatabase::LoadAAEffects2() { - aa_effects.clear(); //start fresh - - const std::string query = "SELECT aaid, slot, effectid, base1, base2 FROM aa_effects ORDER BY aaid ASC, slot ASC"; - auto results = QueryDatabase(query); - if (!results.Success()) { - return false; - } - - if (!results.RowCount()) { //no results - return false; - } - - for(auto row = results.begin(); row != results.end(); ++row) { - int aaid = atoi(row[0]); - int slot = atoi(row[1]); - int effectid = atoi(row[2]); - int base1 = atoi(row[3]); - int base2 = atoi(row[4]); - aa_effects[aaid][slot].skill_id = effectid; - aa_effects[aaid][slot].base1 = base1; - aa_effects[aaid][slot].base2 = base2; - aa_effects[aaid][slot].slot = slot; //not really needed, but we'll populate it just in case - } - - return true; + // + ///* + //AA stacking on SoF+ clients. + // + //Note: There were many ways to achieve this effect - The method used proved to be the most straight forward and consistent. + //Stacking does not currently work ideally for AA's that use hotkeys, therefore they will be excluded at this time. + // + //TODO: Problem with aa.hotkeys - When you reach max rank of an AA tier (ie 5/5), it automatically displays the next AA in + //the series and you can not transfer the hotkey to the next AA series. To the best of the my ability and through many + //different variations of coding I could not find an ideal solution to this issue. + // + //How stacking works: + //Utilizes two new fields: sof_next_id (which is the next id in the series), sof_current_level (ranks the AA's as the current level) + //1) If no AA's purchased only display the base levels of each AA series. + //2) When you purchase an AA and its rank is maxed it sends the packet for the completed AA, and the packet + //for the next aa in the series. The previous tier is removed from your window, and the new AA is displayed. + //3) When you zone/buy your player profile will be checked and determine what AA can be displayed base on what you have already. + //*/ + // + //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 + //// } + //// } + //// } + //// } + //// } + ////} + // + ////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) + // return; + // + //int size=sizeof(SendAA_Struct)+sizeof(AA_Ability)*saa2->total_abilities; + // + //if(size == 0) + // return; + // + //uchar* buffer = new uchar[size]; + //SendAA_Struct* saa=(SendAA_Struct*)buffer; + //memcpy(saa,saa2,size); + // + //if(saa->spellid==0) + // saa->spellid=0xFFFFFFFF; + // + //value=GetAA(saa->id); + //uint32 orig_val = value; + // + //if(value && saa->id){ + // + // if(value < saa->max_level){ + // saa->id+=value; + // saa->next_id=saa->id+1; + // value++; + // } + // + // else if (aa_stack && saa->sof_next_id){ + // saa->id+=value-1; + // saa->next_id=saa->sof_next_id; + // + // //Prevent removal of previous AA from window if next AA belongs to a higher client version. + // SendAA_Struct* saa_next = nullptr; + // saa_next = zone->FindAA(saa->sof_next_id); + // + // // this check should work as long as we continue to just add the clients and just increase + // // each number .... + // if (saa_next && static_cast(GetClientVersion()) < saa_next->clientver - 1) { + // saa->next_id=0xFFFFFFFF; + // } + // } + // + // else{ + // saa->id+=value-1; + // saa->next_id=0xFFFFFFFF; + // } + // + // uint32 current_level_mod = 0; + // if (aa_stack) + // current_level_mod = saa->sof_current_level; + // + // saa->last_id=saa->id-1; + // saa->current_level=value+(current_level_mod); + // saa->cost = saa2->cost + (saa2->cost_inc*(value-1)); + // saa->cost2 = 0; + // for(uint32 i = 0; i < value; i++) { + // saa->cost2 += saa2->cost + (saa2->cost_inc * i); + // } + // saa->class_type = saa2->class_type + (saa2->level_inc*(value-1)); + //} + // + //if (aa_stack){ + // + // if (saa->sof_current_level >= 1 && value == 0) + // saa->current_level = saa->sof_current_level+1; + // + // saa->max_level = saa->sof_max_level; + //} + // + ////database.FillAAEffects(saa); + // + ////if(value > 0) + ////{ + //// // AA_Action stores the base ID + //// const AA_DBAction *caa = &AA_Actions[saa->id - value + 1][value - 1]; + //// + //// if(caa && caa->reuse_time > 0) + //// saa->spell_refresh = CalcAAReuseTimer(caa); + ////} + // + ////You can now use the level_inc field in the altadv_vars table to accomplish this, though still needed + ////for special cases like LOH/HT due to inability to implement correct stacking of AA's that use hotkeys. + ////std::map::iterator RequiredLevel = AARequiredLevelAndCost.find(saa->id); + //// + ////if(RequiredLevel != AARequiredLevelAndCost.end()) + ////{ + //// saa->class_type = RequiredLevel->second.Level; + //// saa->cost = RequiredLevel->second.Cost; + ////} + // + // + //EQApplicationPacket* outapp = new EQApplicationPacket(OP_SendAATable); + //outapp->size=size; + //outapp->pBuffer=(uchar*)saa; + // + //if(id==0 && value && (orig_val < saa->max_level)) //send previous AA only on zone in + // SendPreviousAA(id, seq); + // + //QueuePacket(outapp); + //safe_delete(outapp); + ////will outapp delete the buffer for us even though it didnt make it? --- Yes, it should } void Client::ResetAA(){ @@ -1768,262 +1618,6 @@ void Client::InspectBuffs(Client* Inspector, int Rank) Inspector->FastQueuePacket(&outapp); } -//this really need to be renamed to LoadAAActions() -bool ZoneDatabase::LoadAAEffects() { - memset(AA_Actions, 0, sizeof(AA_Actions)); //I hope the compiler is smart about this size... - - const std::string query = "SELECT aaid, rank, reuse_time, spell_id, target, " - "nonspell_action, nonspell_mana, nonspell_duration, " - "redux_aa, redux_rate, redux_aa2, redux_rate2 FROM aa_actions"; - auto results = QueryDatabase(query); - if (!results.Success()) { - return false; - } - - for (auto row = results.begin(); row != results.end(); ++row) { - - int aaid = atoi(row[0]); - int rank = atoi(row[1]); - if(aaid < 0 || aaid >= aaHighestID || rank < 0 || rank >= MAX_AA_ACTION_RANKS) - continue; - AA_DBAction *caction = &AA_Actions[aaid][rank]; - - caction->reuse_time = atoi(row[2]); - caction->spell_id = atoi(row[3]); - caction->target = (aaTargetType) atoi(row[4]); - caction->action = (aaNonspellAction) atoi(row[5]); - caction->mana_cost = atoi(row[6]); - caction->duration = atoi(row[7]); - caction->redux_aa = (aaID) atoi(row[8]); - caction->redux_rate = atoi(row[9]); - caction->redux_aa2 = (aaID) atoi(row[10]); - caction->redux_rate2 = atoi(row[11]); - - } - - return true; -} - -//Returns the number effects an aa.has when we send them to the client -//For the purposes of sizing a packet because every skill does not -//have the same number effects, they can range from none to a few depending on AA. -//counts the # of effects by counting the different slots of an AAID in the DB. - -//AndMetal: this may now be obsolete since we have Zone::GetTotalAALevels() -uint8 ZoneDatabase::GetTotalAALevels(uint32 skill_id) { - - std::string query = StringFormat("SELECT count(slot) FROM aa_effects WHERE aaid = %i", skill_id); - auto results = QueryDatabase(query); - if (!results.Success()) { - return 0; - } - - if (results.RowCount() != 1) - return 0; - - auto row = results.begin(); - - return atoi(row[0]); -} - -//this will allow us to count the number of effects for an AA by pulling the info from memory instead of the database. hopefully this will same some CPU cycles -uint8 Zone::GetTotalAALevels(uint32 skill_id) { - size_t sz = aa_effects[skill_id].size(); - return sz >= 255 ? 255 : static_cast(sz); -} - -/* -Every AA can send the client effects, which are purely for client side effects. -Essentially it's like being able to attach a very simple version of a spell to -Any given AA, it has 4 fields: -skill_id = spell effect id -slot = ID slot, doesn't appear to have any impact on stacking like real spells, just needs to be unique. -base1 = the base field of a spell -base2 = base field 2 of a spell, most AAs do not utilize this -example: - skill_id = SE_STA - slot = 1 - base1 = 15 - This would if you filled the abilities struct with this make the client show if it had - that AA an additional 15 stamina on the client's stats -*/ -void ZoneDatabase::FillAAEffects(SendAA_Struct* aa_struct){ - if(!aa_struct) - return; - - auto it = aa_effects.find(aa_struct->id); - if (it != aa_effects.end()) { - for (uint32 slot = 0; slot < aa_struct->total_abilities; slot++) { - // aa_effects is a map of a map, so the slot reference does not start at 0 - aa_struct->abilities[slot].skill_id = it->second[slot + 1].skill_id; - aa_struct->abilities[slot].base1 = it->second[slot + 1].base1; - aa_struct->abilities[slot].base2 = it->second[slot + 1].base2; - aa_struct->abilities[slot].slot = it->second[slot + 1].slot; - } - } -} - -uint32 ZoneDatabase::CountAAs(){ - - const std::string query = "SELECT count(title_sid) FROM altadv_vars"; - auto results = QueryDatabase(query); - if (!results.Success()) { - return 0; - } - - if (results.RowCount() != 1) - return 0; - - auto row = results.begin(); - - return atoi(row[0]);; -} - -uint32 ZoneDatabase::CountAAEffects() { - - const std::string query = "SELECT count(id) FROM aa_effects"; - auto results = QueryDatabase(query); - if (!results.Success()) { - return 0; - } - - if (results.RowCount() != 1) - return 0; - - auto row = results.begin(); - - return atoi(row[0]); -} - -uint32 ZoneDatabase::GetSizeAA(){ - int size=CountAAs()*sizeof(SendAA_Struct); - if(size>0) - size+=CountAAEffects()*sizeof(AA_Ability); - return size; -} - -void ZoneDatabase::LoadAAs(SendAA_Struct **load){ - if(!load) - return; - - std::string query = "SELECT skill_id FROM altadv_vars ORDER BY skill_id"; - auto results = QueryDatabase(query); - if (results.Success()) { - int skill = 0, index = 0; - for (auto row = results.begin(); row != results.end(); ++row, ++index) { - skill = atoi(row[0]); - load[index] = GetAASkillVars(skill); - load[index]->seq = index+1; - } - } else { - } - - AARequiredLevelAndCost.clear(); - query = "SELECT skill_id, level, cost from aa_required_level_cost order by skill_id"; - results = QueryDatabase(query); - if (!results.Success()) { - return; - } - - AALevelCost_Struct aalcs; - for (auto row = results.begin(); row != results.end(); ++row) { - aalcs.Level = atoi(row[1]); - aalcs.Cost = atoi(row[2]); - AARequiredLevelAndCost[atoi(row[0])] = aalcs; - } -} - -SendAA_Struct* ZoneDatabase::GetAASkillVars(uint32 skill_id) -{ - std::string query = "SET @row = 0"; //initialize "row" variable in database for next query - auto results = QueryDatabase(query); - if (!results.Success()) { - return nullptr; - } - - query = StringFormat("SELECT a.cost, a.max_level, a.hotkey_sid, a.hotkey_sid2, a.title_sid, a.desc_sid, a.type, " - "COALESCE(" //So we can return 0 if it's null. - "(" // this is our derived table that has the row # - // that we can SELECT from, because the client is stupid. - "SELECT p.prereq_index_num " - "FROM (SELECT a2.skill_id, @row := @row + 1 AS prereq_index_num " - "FROM altadv_vars a2) AS p " - "WHERE p.skill_id = a.prereq_skill), 0) " - "AS prereq_skill_index, a.prereq_minpoints, a.spell_type, a.spell_refresh, a.classes, " - "a.berserker, a.spellid, a.class_type, a.name, a.cost_inc, a.aa_expansion, a.special_category, " - "a.sof_type, a.sof_cost_inc, a.sof_max_level, a.sof_next_skill, " - "a.clientver, " // Client Version 0 = None, 1 = All, 2 = Titanium/6.2, 4 = SoF 5 = SOD 6 = UF - "a.account_time_required, a.sof_current_level, a.sof_next_id, a.level_inc " - "FROM altadv_vars a WHERE skill_id=%i", skill_id); - results = QueryDatabase(query); - if (!results.Success()) { - return nullptr; - } - - if (results.RowCount() != 1) - return nullptr; - - int total_abilities = GetTotalAALevels(skill_id); //eventually we'll want to use zone->GetTotalAALevels(skill_id) since it should save queries to the DB - int totalsize = total_abilities * sizeof(AA_Ability) + sizeof(SendAA_Struct); - - SendAA_Struct* sendaa = nullptr; - uchar* buffer; - - buffer = new uchar[totalsize]; - memset(buffer,0,totalsize); - sendaa = (SendAA_Struct*)buffer; - - auto row = results.begin(); - - //ATOI IS NOT UNSIGNED LONG-SAFE!!! - - sendaa->cost = atoul(row[0]); - sendaa->cost2 = sendaa->cost; - sendaa->max_level = atoul(row[1]); - sendaa->hotkey_sid = atoul(row[2]); - sendaa->id = skill_id; - sendaa->hotkey_sid2 = atoul(row[3]); - sendaa->title_sid = atoul(row[4]); - sendaa->desc_sid = atoul(row[5]); - sendaa->type = atoul(row[6]); - sendaa->prereq_skill = atoul(row[7]); - sendaa->prereq_minpoints = atoul(row[8]); - sendaa->spell_type = atoul(row[9]); - sendaa->spell_refresh = atoul(row[10]); - sendaa->classes = static_cast(atoul(row[11])); - sendaa->berserker = static_cast(atoul(row[12])); - sendaa->last_id = 0xFFFFFFFF; - sendaa->current_level=1; - sendaa->spellid = atoul(row[13]); - sendaa->class_type = atoul(row[14]); - strcpy(sendaa->name,row[15]); - - sendaa->total_abilities=total_abilities; - if(sendaa->max_level > 1) - sendaa->next_id=skill_id+1; - else - sendaa->next_id=0xFFFFFFFF; - - sendaa->cost_inc = atoi(row[16]); - - // Begin SoF Specific/Adjusted AA Fields - sendaa->aa_expansion = atoul(row[17]); - sendaa->special_category = atoul(row[18]); - sendaa->sof_type = atoul(row[19]); - sendaa->sof_cost_inc = atoi(row[20]); - sendaa->sof_max_level = atoul(row[21]); - sendaa->sof_next_skill = atoul(row[22]); - sendaa->clientver = atoul(row[23]); - sendaa->account_time_required = atoul(row[24]); - - //Internal use only - not sent to client - sendaa->sof_current_level = atoul(row[25]); - sendaa->sof_next_id = atoul(row[26]); - sendaa->level_inc = static_cast(atoul(row[27])); - - return sendaa; -} - void Client::DurationRampage(uint32 duration) { if(duration) { @@ -2032,6 +1626,56 @@ void Client::DurationRampage(uint32 duration) } } +void Client::RefundAA() { +// int cur = 0; +// bool refunded = false; +// +// for(int x = 0; x < aaHighestID; x++) { +// cur = GetAA(x); +// if(cur > 0){ +// SendAA_Struct* curaa = zone->FindAA(x); +// if(cur){ +// SetAA(x, 0); +// for(int j = 0; j < cur; j++) { +// m_pp.aapoints += curaa->cost + (curaa->cost_inc * j); +// refunded = true; +// } +// } +// else +// { +// m_pp.aapoints += cur; +// SetAA(x, 0); +// refunded = true; +// } +// } +// } +// +// if(refunded) { +// SaveAA(); +// Save(); +// // Kick(); +// } +} + +void Client::IncrementAA(int aa_id) { + //SendAA_Struct* aa2 = zone->FindAA(aa_id); + // + //if(aa2 == nullptr) + // return; + // + //if(GetAA(aa_id) == aa2->max_level) + // return; + // + //SetAA(aa_id, GetAA(aa_id) + 1); + // + //SaveAA(); + // + //SendAA(aa_id); + //SendAATable(); + //SendAAStats(); + //CalcBonuses(); +} + AA_SwarmPetInfo::AA_SwarmPetInfo() { target = 0; @@ -2119,14 +1763,14 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) { aai->total_prereqs = rank->prereqs.size(); outapp->SetWritePosition(sizeof(AARankInfo_Struct)); - for(auto effect : rank->effects) { + for(auto &effect : rank->effects) { outapp->WriteSInt32(effect.effect_id); outapp->WriteSInt32(effect.base1); outapp->WriteSInt32(effect.base2); outapp->WriteSInt32(effect.slot); } - for(auto prereq : rank->prereqs) { + for(auto &prereq : rank->prereqs) { outapp->WriteSInt32(prereq.aa_id); outapp->WriteSInt32(prereq.points); } @@ -2135,6 +1779,72 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) { safe_delete(outapp); } +void Client::SendAlternateAdvancementStats() { + EQApplicationPacket* outapp = new EQApplicationPacket(OP_AAExpUpdate, sizeof(AltAdvStats_Struct)); + AltAdvStats_Struct *aps = (AltAdvStats_Struct *)outapp->pBuffer; + aps->experience = m_pp.expAA; + aps->experience = (uint32)(((float)330.0f * (float)m_pp.expAA) / (float)max_AAXP); + aps->unspent = m_pp.aapoints; + aps->percentage = m_epp.perAA; + QueuePacket(outapp); + safe_delete(outapp); +} + +void Client::SendAlternateAdvancementPoints() { + EQApplicationPacket* outapp = new EQApplicationPacket(OP_RespondAA, sizeof(AATable_Struct)); + AATable_Struct* aa2 = (AATable_Struct *)outapp->pBuffer; + + int i = 0; + for(auto &aa : zone->aa_abilities) { + auto ranks = GetAA(aa.second->first_rank_id); + if(ranks) { + AA::Rank *rank = aa.second->GetRankByPointsSpent(ranks); + if(rank) { + aa2->aa_list[i].AA = rank->id; + aa2->aa_list[i].value = ranks; + aa2->aa_list[i].charges = 0; // todo send charges + i++; + } + } + } + + + aa2->aa_spent = GetAAPointsSpent(); + QueuePacket(outapp); + safe_delete(outapp); +} + +void Client::PurchaseAlternateAdvancementRank(int rank_id) { +} + +bool ZoneDatabase::LoadAlternateAdvancement(Client *c) { + c->ClearAAs(); + std::string query = StringFormat( + "SELECT " + "aa_id, " + "aa_value, " + "charges " + "FROM " + "`character_alternate_abilities` " + "WHERE `id` = %u ORDER BY `slot`", c->CharacterID()); + MySQLRequestResult results = database.QueryDatabase(query); + + int i = 0; + for(auto row = results.begin(); row != results.end(); ++row) { + uint32 aa = atoi(row[0]); + uint32 value = atoi(row[1]); + uint32 charges = atoi(row[2]); + + c->GetPP().aa_array[i].AA = aa; + c->GetPP().aa_array[i].value = value; + c->GetPP().aa_array[i].charges = charges; + c->SetAA(aa, value, charges); + i++; + } + + return true; +} + AA::Ability *Zone::GetAlternateAdvancementAbility(int id) { auto iter = aa_abilities.find(id); if(iter != aa_abilities.end()) { @@ -2170,13 +1880,13 @@ uint32 Mob::GetAA(uint32 rank_id) const { auto iter = aa_ranks.find(ability->id); if(iter != aa_ranks.end()) { - return iter->second; + return iter->second.first; } } return 0; } -bool Mob::SetAA(uint32 rank_id, uint32 new_value) { +bool Mob::SetAA(uint32 rank_id, uint32 new_value, uint32 charges) { if(zone) { AA::Ability *ability = zone->GetAlternateAdvancementAbilityByRank(rank_id); @@ -2188,10 +1898,10 @@ bool Mob::SetAA(uint32 rank_id, uint32 new_value) { return false; } - aa_ranks[ability->id] = new_value; + aa_ranks[ability->id] = std::make_pair(new_value, charges); } - return false; + return true; } @@ -2201,6 +1911,14 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) { if(!ability) return false; + if(!ability->classes & (1 << GetClass())) { + return false; + } + + if(!(RuleI(World, ExpansionSettings) & (1 << rank->expansion))) { + return false; + } + // Passive and Active Shroud AAs // For now we skip them if(ability->category == 3 || ability->category == 4) { @@ -2247,7 +1965,15 @@ bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank) { return false; } - //check other stuff like price later + //check that we have previous rank already + if(rank->prev) { + //rank->prev-> + } + + //check prereqs + + //check price + return true; } @@ -2268,10 +1994,12 @@ void Zone::LoadAlternateAdvancement() { //process these ranks AA::Rank *current = ability.second->first; + int i = 1; while(current) { current->prev = GetAlternateAdvancementRank(current->prev_id); current->next = GetAlternateAdvancementRank(current->next_id); current->base_ability = ability.second.get(); + current->current_value = i; if(current->prev) { current->total_cost = current->cost + current->prev->total_cost; @@ -2280,6 +2008,7 @@ void Zone::LoadAlternateAdvancement() { current->total_cost = current->cost; } + i++; current = current->next; } @@ -2366,7 +2095,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map 12) + if(effect.slot < 1) continue; if(ranks.count(rank_id) > 0) { @@ -2389,7 +2118,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map 0) { AA::Rank *rank = ranks[rank_id].get(); diff --git a/zone/aa.h b/zone/aa.h index ad41fc3ae..54d495e6e 100644 --- a/zone/aa.h +++ b/zone/aa.h @@ -2137,17 +2137,6 @@ struct AALevelCost_Struct uint32 Cost; }; -//assumes that no activatable aa.has more than 5 ranks -#define MAX_AA_ACTION_RANKS 20 -extern AA_DBAction AA_Actions[aaHighestID][MAX_AA_ACTION_RANKS]; //[aaid][rank] -extern std::map AA_SwarmPets; //key=spell_id - -#define AA_Choose3(val, v1, v2, v3) (val==1?v1:(val==2?v2:v3)) - -extern std::mapaas_send; -extern std::map > aa_effects; -extern std::map AARequiredLevelAndCost; - enum { //values of AA_Action.action aaActionActivate = 0, aaActionSetEXP = 1, diff --git a/zone/aa_rank.h b/zone/aa_rank.h index 20628a506..a824f2c82 100644 --- a/zone/aa_rank.h +++ b/zone/aa_rank.h @@ -43,6 +43,7 @@ public: Rank *prev; int next_id; Rank *next; + int current_value; int expansion; uint32 account_time_required; int total_cost; diff --git a/zone/attack.cpp b/zone/attack.cpp index a229f197e..74cb33272 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4659,38 +4659,39 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui proc_spell_id = 0; ProcMod = 0; - std::map >::const_iterator find_iter = aa_effects.find(aaid); - if(find_iter == aa_effects.end()) - break; + //old AA + //std::map >::const_iterator find_iter = aa_effects.find(aaid); + //if(find_iter == aa_effects.end()) + // break; - for (std::map::const_iterator iter = aa_effects[aaid].begin(); iter != aa_effects[aaid].end(); ++iter) { - effect = iter->second.skill_id; - base1 = iter->second.base1; - base2 = iter->second.base2; - slot = iter->second.slot; - - if (effect == SE_SkillProc || effect == SE_SkillProcSuccess) { - proc_spell_id = base1; - ProcMod = static_cast(base2); - } - - else if (effect == SE_LimitToSkill && base1 <= HIGHEST_SKILL) { - - if (CanProc && base1 == skill && IsValidSpell(proc_spell_id)) { - float final_chance = chance * (ProcMod / 100.0f); - - if (zone->random.Roll(final_chance)) { - ExecWeaponProc(nullptr, proc_spell_id, on); - CanProc = false; - break; - } - } - } - else { - proc_spell_id = 0; - ProcMod = 0; - } - } + //for (std::map::const_iterator iter = aa_effects[aaid].begin(); iter != aa_effects[aaid].end(); ++iter) { + // effect = iter->second.skill_id; + // base1 = iter->second.base1; + // base2 = iter->second.base2; + // slot = iter->second.slot; + // + // if (effect == SE_SkillProc || effect == SE_SkillProcSuccess) { + // proc_spell_id = base1; + // ProcMod = static_cast(base2); + // } + // + // else if (effect == SE_LimitToSkill && base1 <= HIGHEST_SKILL) { + // + // if (CanProc && base1 == skill && IsValidSpell(proc_spell_id)) { + // float final_chance = chance * (ProcMod / 100.0f); + // + // if (zone->random.Roll(final_chance)) { + // ExecWeaponProc(nullptr, proc_spell_id, on); + // CanProc = false; + // break; + // } + // } + // } + // else { + // proc_spell_id = 0; + // ProcMod = 0; + // } + //} } } } diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index a2a180cef..437befe11 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -671,772 +671,773 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) int32 base2 = 0; //only really used for SE_RaiseStatCap & SE_ReduceSkillTimer in aa_effects table uint32 slot = 0; - std::map >::const_iterator find_iter = aa_effects.find(aaid); - if(find_iter == aa_effects.end()) - { - return; - } - - for (std::map::const_iterator iter = aa_effects[aaid].begin(); iter != aa_effects[aaid].end(); ++iter) { - effect = iter->second.skill_id; - base1 = iter->second.base1; - base2 = iter->second.base2; - slot = iter->second.slot; - - //we default to 0 (SE_CurrentHP) for the effect, so if there aren't any base1/2 values, we'll just skip it - if (effect == 0 && base1 == 0 && base2 == 0) - continue; - - //IsBlankSpellEffect() - if (effect == SE_Blank || (effect == SE_CHA && base1 == 0) || effect == SE_StackingCommand_Block || effect == SE_StackingCommand_Overwrite) - continue; - - Log.Out(Logs::Detail, Logs::AA, "Applying Effect %d from AA %u in slot %d (base1: %d, base2: %d) on %s", effect, aaid, slot, base1, base2, this->GetCleanName()); - - uint8 focus = IsFocusEffect(0, 0, true,effect); - if (focus) - { - newbon->FocusEffects[focus] = static_cast(effect); - continue; - } - - switch (effect) - { - //Note: AA effects that use accuracy are skill limited, while spell effect is not. - case SE_Accuracy: - if ((base2 == ALL_SKILLS) && (newbon->Accuracy[HIGHEST_SKILL+1] < base1)) - newbon->Accuracy[HIGHEST_SKILL+1] = base1; - else if (newbon->Accuracy[base2] < base1) - newbon->Accuracy[base2] += base1; - break; - case SE_CurrentHP: //regens - newbon->HPRegen += base1; - break; - case SE_CurrentEndurance: - newbon->EnduranceRegen += base1; - break; - case SE_MovementSpeed: - newbon->movementspeed += base1; //should we let these stack? - /*if (base1 > newbon->movementspeed) //or should we use a total value? - newbon->movementspeed = base1;*/ - break; - case SE_STR: - newbon->STR += base1; - break; - case SE_DEX: - newbon->DEX += base1; - break; - case SE_AGI: - newbon->AGI += base1; - break; - case SE_STA: - newbon->STA += base1; - break; - case SE_INT: - newbon->INT += base1; - break; - case SE_WIS: - newbon->WIS += base1; - break; - case SE_CHA: - newbon->CHA += base1; - break; - case SE_WaterBreathing: - //handled by client - break; - case SE_CurrentMana: - newbon->ManaRegen += base1; - break; - case SE_ItemManaRegenCapIncrease: - newbon->ItemManaRegenCap += base1; - break; - case SE_ResistFire: - newbon->FR += base1; - break; - case SE_ResistCold: - newbon->CR += base1; - break; - case SE_ResistPoison: - newbon->PR += base1; - break; - case SE_ResistDisease: - newbon->DR += base1; - break; - case SE_ResistMagic: - newbon->MR += base1; - break; - case SE_ResistCorruption: - newbon->Corrup += base1; - break; - case SE_IncreaseSpellHaste: - break; - case SE_IncreaseRange: - break; - case SE_MaxHPChange: - newbon->MaxHP += base1; - break; - case SE_Packrat: - newbon->Packrat += base1; - break; - case SE_TwoHandBash: - break; - case SE_SetBreathLevel: - break; - case SE_RaiseStatCap: - switch(base2) - { - //are these #define'd somewhere? - case 0: //str - newbon->STRCapMod += base1; - break; - case 1: //sta - newbon->STACapMod += base1; - break; - case 2: //agi - newbon->AGICapMod += base1; - break; - case 3: //dex - newbon->DEXCapMod += base1; - break; - case 4: //wis - newbon->WISCapMod += base1; - break; - case 5: //int - newbon->INTCapMod += base1; - break; - case 6: //cha - newbon->CHACapMod += base1; - break; - case 7: //mr - newbon->MRCapMod += base1; - break; - case 8: //cr - newbon->CRCapMod += base1; - break; - case 9: //fr - newbon->FRCapMod += base1; - break; - case 10: //pr - newbon->PRCapMod += base1; - break; - case 11: //dr - newbon->DRCapMod += base1; - break; - case 12: //corruption - newbon->CorrupCapMod += base1; - break; - } - break; - case SE_PetDiscipline2: - break; - case SE_SpellSlotIncrease: - break; - case SE_MysticalAttune: - newbon->BuffSlotIncrease += base1; - break; - case SE_TotalHP: - newbon->HP += base1; - break; - case SE_StunResist: - newbon->StunResist += base1; - break; - case SE_SpellCritChance: - newbon->CriticalSpellChance += base1; - break; - case SE_SpellCritDmgIncrease: - newbon->SpellCritDmgIncrease += base1; - break; - case SE_DotCritDmgIncrease: - newbon->DotCritDmgIncrease += base1; - break; - case SE_ResistSpellChance: - newbon->ResistSpellChance += base1; - break; - case SE_CriticalHealChance: - newbon->CriticalHealChance += base1; - break; - case SE_CriticalHealOverTime: - newbon->CriticalHealOverTime += base1; - break; - case SE_CriticalDoTChance: - newbon->CriticalDoTChance += base1; - break; - case SE_ReduceSkillTimer: - newbon->SkillReuseTime[base2] += base1; - break; - case SE_Fearless: - newbon->Fearless = true; - break; - case SE_PersistantCasting: - newbon->PersistantCasting += base1; - break; - case SE_DelayDeath: - newbon->DelayDeath += base1; - break; - case SE_FrontalStunResist: - newbon->FrontalStunResist += base1; - break; - case SE_ImprovedBindWound: - newbon->BindWound += base1; - break; - case SE_MaxBindWound: - newbon->MaxBindWound += base1; - break; - case SE_ExtraAttackChance: - newbon->ExtraAttackChance += base1; - break; - case SE_SeeInvis: - newbon->SeeInvis = base1; - break; - case SE_BaseMovementSpeed: - newbon->BaseMovementSpeed += base1; - break; - case SE_IncreaseRunSpeedCap: - newbon->IncreaseRunSpeedCap += base1; - break; - case SE_ConsumeProjectile: - newbon->ConsumeProjectile += base1; - break; - case SE_ForageAdditionalItems: - newbon->ForageAdditionalItems += base1; - break; - case SE_Salvage: - newbon->SalvageChance += base1; - break; - case SE_ArcheryDamageModifier: - newbon->ArcheryDamageModifier += base1; - break; - case SE_DoubleRangedAttack: - newbon->DoubleRangedAttack += base1; - break; - case SE_DamageShield: - newbon->DamageShield += base1; - break; - case SE_CharmBreakChance: - newbon->CharmBreakChance += base1; - break; - case SE_OffhandRiposteFail: - newbon->OffhandRiposteFail += base1; - break; - case SE_ItemAttackCapIncrease: - newbon->ItemATKCap += base1; - break; - case SE_GivePetGroupTarget: - newbon->GivePetGroupTarget = true; - break; - case SE_ItemHPRegenCapIncrease: - newbon->ItemHPRegenCap = +base1; - break; - case SE_Ambidexterity: - newbon->Ambidexterity += base1; - break; - case SE_PetMaxHP: - newbon->PetMaxHP += base1; - break; - case SE_AvoidMeleeChance: - newbon->AvoidMeleeChanceEffect += base1; - break; - case SE_CombatStability: - newbon->CombatStability += base1; - break; - case SE_AddSingingMod: - switch (base2) - { - case ItemTypeWindInstrument: - newbon->windMod += base1; - break; - case ItemTypeStringedInstrument: - newbon->stringedMod += base1; - break; - case ItemTypeBrassInstrument: - newbon->brassMod += base1; - break; - case ItemTypePercussionInstrument: - newbon->percussionMod += base1; - break; - case ItemTypeSinging: - newbon->singingMod += base1; - break; - } - break; - case SE_SongModCap: - newbon->songModCap += base1; - break; - case SE_PetCriticalHit: - newbon->PetCriticalHit += base1; - break; - case SE_PetAvoidance: - newbon->PetAvoidance += base1; - break; - case SE_ShieldBlock: - newbon->ShieldBlock += base1; - break; - case SE_ShieldEquipHateMod: - newbon->ShieldEquipHateMod += base1; - break; - case SE_ShieldEquipDmgMod: - newbon->ShieldEquipDmgMod[0] += base1; - newbon->ShieldEquipDmgMod[1] += base2; - break; - case SE_SecondaryDmgInc: - newbon->SecondaryDmgInc = true; - break; - case SE_ChangeAggro: - newbon->hatemod += base1; - break; - case SE_EndurancePool: - newbon->Endurance += base1; - break; - case SE_ChannelChanceItems: - newbon->ChannelChanceItems += base1; - break; - case SE_ChannelChanceSpells: - newbon->ChannelChanceSpells += base1; - break; - case SE_DoubleSpecialAttack: - newbon->DoubleSpecialAttack += base1; - break; - case SE_TripleBackstab: - newbon->TripleBackstab += base1; - break; - case SE_FrontalBackstabMinDmg: - newbon->FrontalBackstabMinDmg = true; - break; - case SE_FrontalBackstabChance: - newbon->FrontalBackstabChance += base1; - break; - case SE_BlockBehind: - newbon->BlockBehind += base1; - break; - - case SE_StrikeThrough: - case SE_StrikeThrough2: - newbon->StrikeThrough += base1; - break; - case SE_DoubleAttackChance: - newbon->DoubleAttackChance += base1; - break; - case SE_GiveDoubleAttack: - newbon->GiveDoubleAttack += base1; - break; - case SE_ProcChance: - newbon->ProcChanceSPA += base1; - break; - case SE_RiposteChance: - newbon->RiposteChance += base1; - break; - case SE_Flurry: - newbon->FlurryChance += base1; - break; - case SE_PetFlurry: - newbon->PetFlurry += base1; - break; - case SE_BardSongRange: - newbon->SongRange += base1; - break; - case SE_RootBreakChance: - newbon->RootBreakChance += base1; - break; - case SE_UnfailingDivinity: - newbon->UnfailingDivinity += base1; - break; - case SE_CrippBlowChance: - newbon->CrippBlowChance += base1; - break; - - case SE_HitChance: - { - if(base2 == ALL_SKILLS) - newbon->HitChanceEffect[HIGHEST_SKILL+1] += base1; - else - newbon->HitChanceEffect[base2] += base1; - } - - case SE_ProcOnKillShot: - for(int i = 0; i < MAX_SPELL_TRIGGER*3; i+=3) - { - if(!newbon->SpellOnKill[i] || ((newbon->SpellOnKill[i] == base2) && (newbon->SpellOnKill[i+1] < base1))) - { - //base1 = chance, base2 = SpellID to be triggered, base3 = min npc level - newbon->SpellOnKill[i] = base2; - newbon->SpellOnKill[i+1] = base1; - - if (GetLevel() > 15) - newbon->SpellOnKill[i+2] = GetLevel() - 15; //AA specifiy "non-trivial" - else - newbon->SpellOnKill[i+2] = 0; - - break; - } - } - break; - - case SE_SpellOnDeath: - for(int i = 0; i < MAX_SPELL_TRIGGER*2; i+=2) - { - if(!newbon->SpellOnDeath[i]) - { - // base1 = SpellID to be triggered, base2 = chance to fire - newbon->SpellOnDeath[i] = base1; - newbon->SpellOnDeath[i+1] = base2; - break; - } - } - break; - - case SE_TriggerOnCast: - - for(int i = 0; i < MAX_SPELL_TRIGGER; i++) - { - if (newbon->SpellTriggers[i] == aaid) - break; - - if(!newbon->SpellTriggers[i]) - { - //Save the 'aaid' of each triggerable effect to an array - newbon->SpellTriggers[i] = aaid; - break; - } - } - break; - - case SE_CriticalHitChance: - { - if(base2 == ALL_SKILLS) - newbon->CriticalHitChance[HIGHEST_SKILL+1] += base1; - else - newbon->CriticalHitChance[base2] += base1; - } - break; - - case SE_CriticalDamageMob: - { - // base1 = effect value, base2 = skill restrictions(-1 for all) - if(base2 == ALL_SKILLS) - newbon->CritDmgMob[HIGHEST_SKILL+1] += base1; - else - newbon->CritDmgMob[base2] += base1; - break; - } - - case SE_CriticalSpellChance: - { - newbon->CriticalSpellChance += base1; - - if (base2 > newbon->SpellCritDmgIncNoStack) - newbon->SpellCritDmgIncNoStack = base2; - - break; - } - - case SE_ResistFearChance: - { - if(base1 == 100) // If we reach 100% in a single spell/item then we should be immune to negative fear resist effects until our immunity is over - newbon->Fearless = true; - - newbon->ResistFearChance += base1; // these should stack - break; - } - - case SE_SkillDamageAmount: - { - if(base2 == ALL_SKILLS) - newbon->SkillDamageAmount[HIGHEST_SKILL+1] += base1; - else - newbon->SkillDamageAmount[base2] += base1; - break; - } - - case SE_SpecialAttackKBProc: - { - //You can only have one of these per client. [AA Dragon Punch] - newbon->SpecialAttackKBProc[0] = base1; //Chance base 100 = 25% proc rate - newbon->SpecialAttackKBProc[1] = base2; //Skill to KB Proc Off - break; - } - - case SE_DamageModifier: - { - if(base2 == ALL_SKILLS) - newbon->DamageModifier[HIGHEST_SKILL+1] += base1; - else - newbon->DamageModifier[base2] += base1; - break; - } - - case SE_DamageModifier2: - { - if(base2 == ALL_SKILLS) - newbon->DamageModifier2[HIGHEST_SKILL+1] += base1; - else - newbon->DamageModifier2[base2] += base1; - break; - } - - case SE_SlayUndead: - { - if(newbon->SlayUndead[1] < base1) - newbon->SlayUndead[0] = base1; // Rate - newbon->SlayUndead[1] = base2; // Damage Modifier - break; - } - - case SE_DoubleRiposte: - { - newbon->DoubleRiposte += base1; - } - - case SE_GiveDoubleRiposte: - { - //0=Regular Riposte 1=Skill Attack Riposte 2=Skill - if(base2 == 0){ - if(newbon->GiveDoubleRiposte[0] < base1) - newbon->GiveDoubleRiposte[0] = base1; - } - //Only for special attacks. - else if(base2 > 0 && (newbon->GiveDoubleRiposte[1] < base1)){ - newbon->GiveDoubleRiposte[1] = base1; - newbon->GiveDoubleRiposte[2] = base2; - } - - break; - } - - //Kayen: Not sure best way to implement this yet. - //Physically raises skill cap ie if 55/55 it will raise to 55/60 - case SE_RaiseSkillCap: - { - if(newbon->RaiseSkillCap[0] < base1){ - newbon->RaiseSkillCap[0] = base1; //value - newbon->RaiseSkillCap[1] = base2; //skill - } - break; - } - - case SE_MasteryofPast: - { - if(newbon->MasteryofPast < base1) - newbon->MasteryofPast = base1; - break; - } - - case SE_CastingLevel2: - case SE_CastingLevel: - { - newbon->effective_casting_level += base1; - break; - } - - case SE_DivineSave: - { - if(newbon->DivineSaveChance[0] < base1) - { - newbon->DivineSaveChance[0] = base1; - newbon->DivineSaveChance[1] = base2; - } - break; - } - - - case SE_SpellEffectResistChance: - { - for(int e = 0; e < MAX_RESISTABLE_EFFECTS*2; e+=2) - { - if(newbon->SEResist[e+1] && (newbon->SEResist[e] == base2) && (newbon->SEResist[e+1] < base1)){ - newbon->SEResist[e] = base2; //Spell Effect ID - newbon->SEResist[e+1] = base1; //Resist Chance - break; - } - else if (!newbon->SEResist[e+1]){ - newbon->SEResist[e] = base2; //Spell Effect ID - newbon->SEResist[e+1] = base1; //Resist Chance - break; - } - } - break; - } - - case SE_MitigateDamageShield: - { - if (base1 < 0) - base1 = base1*(-1); - - newbon->DSMitigationOffHand += base1; - break; - } - - case SE_FinishingBlow: - { - //base1 = chance, base2 = damage - if (newbon->FinishingBlow[1] < base2){ - newbon->FinishingBlow[0] = base1; - newbon->FinishingBlow[1] = base2; - } - break; - } - - case SE_FinishingBlowLvl: - { - //base1 = level, base2 = ??? (Set to 200 in AA data, possible proc rate mod?) - if (newbon->FinishingBlowLvl[0] < base1){ - newbon->FinishingBlowLvl[0] = base1; - newbon->FinishingBlowLvl[1] = base2; - } - break; - } - - case SE_StunBashChance: - newbon->StunBashChance += base1; - break; - - case SE_IncreaseChanceMemwipe: - newbon->IncreaseChanceMemwipe += base1; - break; - - case SE_CriticalMend: - newbon->CriticalMend += base1; - break; - - case SE_HealRate: - newbon->HealRate += base1; - break; - - case SE_MeleeLifetap: - { - - if((base1 < 0) && (newbon->MeleeLifetap > base1)) - newbon->MeleeLifetap = base1; - - else if(newbon->MeleeLifetap < base1) - newbon->MeleeLifetap = base1; - break; - } - - case SE_Vampirism: - newbon->Vampirism += base1; - break; - - case SE_FrenziedDevastation: - newbon->FrenziedDevastation += base2; - break; - - case SE_SpellProcChance: - newbon->SpellProcChance += base1; - break; - - case SE_Berserk: - newbon->BerserkSPA = true; - break; - - case SE_Metabolism: - newbon->Metabolism += base1; - break; - - case SE_ImprovedReclaimEnergy: - { - if((base1 < 0) && (newbon->ImprovedReclaimEnergy > base1)) - newbon->ImprovedReclaimEnergy = base1; - - else if(newbon->ImprovedReclaimEnergy < base1) - newbon->ImprovedReclaimEnergy = base1; - break; - } - - case SE_HeadShot: - { - if(newbon->HeadShot[1] < base2){ - newbon->HeadShot[0] = base1; - newbon->HeadShot[1] = base2; - } - break; - } - - case SE_HeadShotLevel: - { - if(newbon->HSLevel < base1) - newbon->HSLevel = base1; - break; - } - - case SE_Assassinate: - { - if(newbon->Assassinate[1] < base2){ - newbon->Assassinate[0] = base1; - newbon->Assassinate[1] = base2; - } - break; - } - - case SE_AssassinateLevel: - { - if(newbon->AssassinateLevel < base1) - newbon->AssassinateLevel = base1; - break; - } - - case SE_PetMeleeMitigation: - newbon->PetMeleeMitigation += base1; - break; - - case SE_MeleeVulnerability: - newbon->MeleeVulnerability += base1; - break; - - case SE_FactionModPct: - { - if((base1 < 0) && (newbon->FactionModPct > base1)) - newbon->FactionModPct = base1; - - else if(newbon->FactionModPct < base1) - newbon->FactionModPct = base1; - break; - } - - case SE_IllusionPersistence: - newbon->IllusionPersistence = true; - break; - - case SE_LimitToSkill:{ - if (base1 <= HIGHEST_SKILL) - newbon->LimitToSkill[base1] = true; - break; - } - - case SE_SkillProc:{ - for(int e = 0; e < MAX_SKILL_PROCS; e++) - { - if(newbon->SkillProc[e] && newbon->SkillProc[e] == aaid) - break; //Do not use the same aa id more than once. - - else if(!newbon->SkillProc[e]){ - newbon->SkillProc[e] = aaid; - break; - } - } - break; - } - - case SE_SkillProcSuccess:{ - - for(int e = 0; e < MAX_SKILL_PROCS; e++) - { - if(newbon->SkillProcSuccess[e] && newbon->SkillProcSuccess[e] == aaid) - break; //Do not use the same spell id more than once. - - else if(!newbon->SkillProcSuccess[e]){ - newbon->SkillProcSuccess[e] = aaid; - break; - } - } - break; - } - - case SE_MeleeMitigation: - newbon->MeleeMitigationEffect -= base1; - break; - - } - } + //AA old + //std::map >::const_iterator find_iter = aa_effects.find(aaid); + //if(find_iter == aa_effects.end()) + //{ + // return; + //} + // + //for (std::map::const_iterator iter = aa_effects[aaid].begin(); iter != aa_effects[aaid].end(); ++iter) { + // effect = iter->second.skill_id; + // base1 = iter->second.base1; + // base2 = iter->second.base2; + // slot = iter->second.slot; + // + // //we default to 0 (SE_CurrentHP) for the effect, so if there aren't any base1/2 values, we'll just skip it + // if (effect == 0 && base1 == 0 && base2 == 0) + // continue; + // + // //IsBlankSpellEffect() + // if (effect == SE_Blank || (effect == SE_CHA && base1 == 0) || effect == SE_StackingCommand_Block || effect == SE_StackingCommand_Overwrite) + // continue; + // + // Log.Out(Logs::Detail, Logs::AA, "Applying Effect %d from AA %u in slot %d (base1: %d, base2: %d) on %s", effect, aaid, slot, base1, base2, this->GetCleanName()); + // + // uint8 focus = IsFocusEffect(0, 0, true,effect); + // if (focus) + // { + // newbon->FocusEffects[focus] = static_cast(effect); + // continue; + // } + // + // switch (effect) + // { + // //Note: AA effects that use accuracy are skill limited, while spell effect is not. + // case SE_Accuracy: + // if ((base2 == ALL_SKILLS) && (newbon->Accuracy[HIGHEST_SKILL+1] < base1)) + // newbon->Accuracy[HIGHEST_SKILL+1] = base1; + // else if (newbon->Accuracy[base2] < base1) + // newbon->Accuracy[base2] += base1; + // break; + // case SE_CurrentHP: //regens + // newbon->HPRegen += base1; + // break; + // case SE_CurrentEndurance: + // newbon->EnduranceRegen += base1; + // break; + // case SE_MovementSpeed: + // newbon->movementspeed += base1; //should we let these stack? + // /*if (base1 > newbon->movementspeed) //or should we use a total value? + // newbon->movementspeed = base1;*/ + // break; + // case SE_STR: + // newbon->STR += base1; + // break; + // case SE_DEX: + // newbon->DEX += base1; + // break; + // case SE_AGI: + // newbon->AGI += base1; + // break; + // case SE_STA: + // newbon->STA += base1; + // break; + // case SE_INT: + // newbon->INT += base1; + // break; + // case SE_WIS: + // newbon->WIS += base1; + // break; + // case SE_CHA: + // newbon->CHA += base1; + // break; + // case SE_WaterBreathing: + // //handled by client + // break; + // case SE_CurrentMana: + // newbon->ManaRegen += base1; + // break; + // case SE_ItemManaRegenCapIncrease: + // newbon->ItemManaRegenCap += base1; + // break; + // case SE_ResistFire: + // newbon->FR += base1; + // break; + // case SE_ResistCold: + // newbon->CR += base1; + // break; + // case SE_ResistPoison: + // newbon->PR += base1; + // break; + // case SE_ResistDisease: + // newbon->DR += base1; + // break; + // case SE_ResistMagic: + // newbon->MR += base1; + // break; + // case SE_ResistCorruption: + // newbon->Corrup += base1; + // break; + // case SE_IncreaseSpellHaste: + // break; + // case SE_IncreaseRange: + // break; + // case SE_MaxHPChange: + // newbon->MaxHP += base1; + // break; + // case SE_Packrat: + // newbon->Packrat += base1; + // break; + // case SE_TwoHandBash: + // break; + // case SE_SetBreathLevel: + // break; + // case SE_RaiseStatCap: + // switch(base2) + // { + // //are these #define'd somewhere? + // case 0: //str + // newbon->STRCapMod += base1; + // break; + // case 1: //sta + // newbon->STACapMod += base1; + // break; + // case 2: //agi + // newbon->AGICapMod += base1; + // break; + // case 3: //dex + // newbon->DEXCapMod += base1; + // break; + // case 4: //wis + // newbon->WISCapMod += base1; + // break; + // case 5: //int + // newbon->INTCapMod += base1; + // break; + // case 6: //cha + // newbon->CHACapMod += base1; + // break; + // case 7: //mr + // newbon->MRCapMod += base1; + // break; + // case 8: //cr + // newbon->CRCapMod += base1; + // break; + // case 9: //fr + // newbon->FRCapMod += base1; + // break; + // case 10: //pr + // newbon->PRCapMod += base1; + // break; + // case 11: //dr + // newbon->DRCapMod += base1; + // break; + // case 12: //corruption + // newbon->CorrupCapMod += base1; + // break; + // } + // break; + // case SE_PetDiscipline2: + // break; + // case SE_SpellSlotIncrease: + // break; + // case SE_MysticalAttune: + // newbon->BuffSlotIncrease += base1; + // break; + // case SE_TotalHP: + // newbon->HP += base1; + // break; + // case SE_StunResist: + // newbon->StunResist += base1; + // break; + // case SE_SpellCritChance: + // newbon->CriticalSpellChance += base1; + // break; + // case SE_SpellCritDmgIncrease: + // newbon->SpellCritDmgIncrease += base1; + // break; + // case SE_DotCritDmgIncrease: + // newbon->DotCritDmgIncrease += base1; + // break; + // case SE_ResistSpellChance: + // newbon->ResistSpellChance += base1; + // break; + // case SE_CriticalHealChance: + // newbon->CriticalHealChance += base1; + // break; + // case SE_CriticalHealOverTime: + // newbon->CriticalHealOverTime += base1; + // break; + // case SE_CriticalDoTChance: + // newbon->CriticalDoTChance += base1; + // break; + // case SE_ReduceSkillTimer: + // newbon->SkillReuseTime[base2] += base1; + // break; + // case SE_Fearless: + // newbon->Fearless = true; + // break; + // case SE_PersistantCasting: + // newbon->PersistantCasting += base1; + // break; + // case SE_DelayDeath: + // newbon->DelayDeath += base1; + // break; + // case SE_FrontalStunResist: + // newbon->FrontalStunResist += base1; + // break; + // case SE_ImprovedBindWound: + // newbon->BindWound += base1; + // break; + // case SE_MaxBindWound: + // newbon->MaxBindWound += base1; + // break; + // case SE_ExtraAttackChance: + // newbon->ExtraAttackChance += base1; + // break; + // case SE_SeeInvis: + // newbon->SeeInvis = base1; + // break; + // case SE_BaseMovementSpeed: + // newbon->BaseMovementSpeed += base1; + // break; + // case SE_IncreaseRunSpeedCap: + // newbon->IncreaseRunSpeedCap += base1; + // break; + // case SE_ConsumeProjectile: + // newbon->ConsumeProjectile += base1; + // break; + // case SE_ForageAdditionalItems: + // newbon->ForageAdditionalItems += base1; + // break; + // case SE_Salvage: + // newbon->SalvageChance += base1; + // break; + // case SE_ArcheryDamageModifier: + // newbon->ArcheryDamageModifier += base1; + // break; + // case SE_DoubleRangedAttack: + // newbon->DoubleRangedAttack += base1; + // break; + // case SE_DamageShield: + // newbon->DamageShield += base1; + // break; + // case SE_CharmBreakChance: + // newbon->CharmBreakChance += base1; + // break; + // case SE_OffhandRiposteFail: + // newbon->OffhandRiposteFail += base1; + // break; + // case SE_ItemAttackCapIncrease: + // newbon->ItemATKCap += base1; + // break; + // case SE_GivePetGroupTarget: + // newbon->GivePetGroupTarget = true; + // break; + // case SE_ItemHPRegenCapIncrease: + // newbon->ItemHPRegenCap = +base1; + // break; + // case SE_Ambidexterity: + // newbon->Ambidexterity += base1; + // break; + // case SE_PetMaxHP: + // newbon->PetMaxHP += base1; + // break; + // case SE_AvoidMeleeChance: + // newbon->AvoidMeleeChanceEffect += base1; + // break; + // case SE_CombatStability: + // newbon->CombatStability += base1; + // break; + // case SE_AddSingingMod: + // switch (base2) + // { + // case ItemTypeWindInstrument: + // newbon->windMod += base1; + // break; + // case ItemTypeStringedInstrument: + // newbon->stringedMod += base1; + // break; + // case ItemTypeBrassInstrument: + // newbon->brassMod += base1; + // break; + // case ItemTypePercussionInstrument: + // newbon->percussionMod += base1; + // break; + // case ItemTypeSinging: + // newbon->singingMod += base1; + // break; + // } + // break; + // case SE_SongModCap: + // newbon->songModCap += base1; + // break; + // case SE_PetCriticalHit: + // newbon->PetCriticalHit += base1; + // break; + // case SE_PetAvoidance: + // newbon->PetAvoidance += base1; + // break; + // case SE_ShieldBlock: + // newbon->ShieldBlock += base1; + // break; + // case SE_ShieldEquipHateMod: + // newbon->ShieldEquipHateMod += base1; + // break; + // case SE_ShieldEquipDmgMod: + // newbon->ShieldEquipDmgMod[0] += base1; + // newbon->ShieldEquipDmgMod[1] += base2; + // break; + // case SE_SecondaryDmgInc: + // newbon->SecondaryDmgInc = true; + // break; + // case SE_ChangeAggro: + // newbon->hatemod += base1; + // break; + // case SE_EndurancePool: + // newbon->Endurance += base1; + // break; + // case SE_ChannelChanceItems: + // newbon->ChannelChanceItems += base1; + // break; + // case SE_ChannelChanceSpells: + // newbon->ChannelChanceSpells += base1; + // break; + // case SE_DoubleSpecialAttack: + // newbon->DoubleSpecialAttack += base1; + // break; + // case SE_TripleBackstab: + // newbon->TripleBackstab += base1; + // break; + // case SE_FrontalBackstabMinDmg: + // newbon->FrontalBackstabMinDmg = true; + // break; + // case SE_FrontalBackstabChance: + // newbon->FrontalBackstabChance += base1; + // break; + // case SE_BlockBehind: + // newbon->BlockBehind += base1; + // break; + // + // case SE_StrikeThrough: + // case SE_StrikeThrough2: + // newbon->StrikeThrough += base1; + // break; + // case SE_DoubleAttackChance: + // newbon->DoubleAttackChance += base1; + // break; + // case SE_GiveDoubleAttack: + // newbon->GiveDoubleAttack += base1; + // break; + // case SE_ProcChance: + // newbon->ProcChanceSPA += base1; + // break; + // case SE_RiposteChance: + // newbon->RiposteChance += base1; + // break; + // case SE_Flurry: + // newbon->FlurryChance += base1; + // break; + // case SE_PetFlurry: + // newbon->PetFlurry += base1; + // break; + // case SE_BardSongRange: + // newbon->SongRange += base1; + // break; + // case SE_RootBreakChance: + // newbon->RootBreakChance += base1; + // break; + // case SE_UnfailingDivinity: + // newbon->UnfailingDivinity += base1; + // break; + // case SE_CrippBlowChance: + // newbon->CrippBlowChance += base1; + // break; + // + // case SE_HitChance: + // { + // if(base2 == ALL_SKILLS) + // newbon->HitChanceEffect[HIGHEST_SKILL+1] += base1; + // else + // newbon->HitChanceEffect[base2] += base1; + // } + // + // case SE_ProcOnKillShot: + // for(int i = 0; i < MAX_SPELL_TRIGGER*3; i+=3) + // { + // if(!newbon->SpellOnKill[i] || ((newbon->SpellOnKill[i] == base2) && (newbon->SpellOnKill[i+1] < base1))) + // { + // //base1 = chance, base2 = SpellID to be triggered, base3 = min npc level + // newbon->SpellOnKill[i] = base2; + // newbon->SpellOnKill[i+1] = base1; + // + // if (GetLevel() > 15) + // newbon->SpellOnKill[i+2] = GetLevel() - 15; //AA specifiy "non-trivial" + // else + // newbon->SpellOnKill[i+2] = 0; + // + // break; + // } + // } + // break; + // + // case SE_SpellOnDeath: + // for(int i = 0; i < MAX_SPELL_TRIGGER*2; i+=2) + // { + // if(!newbon->SpellOnDeath[i]) + // { + // // base1 = SpellID to be triggered, base2 = chance to fire + // newbon->SpellOnDeath[i] = base1; + // newbon->SpellOnDeath[i+1] = base2; + // break; + // } + // } + // break; + // + // case SE_TriggerOnCast: + // + // for(int i = 0; i < MAX_SPELL_TRIGGER; i++) + // { + // if (newbon->SpellTriggers[i] == aaid) + // break; + // + // if(!newbon->SpellTriggers[i]) + // { + // //Save the 'aaid' of each triggerable effect to an array + // newbon->SpellTriggers[i] = aaid; + // break; + // } + // } + // break; + // + // case SE_CriticalHitChance: + // { + // if(base2 == ALL_SKILLS) + // newbon->CriticalHitChance[HIGHEST_SKILL+1] += base1; + // else + // newbon->CriticalHitChance[base2] += base1; + // } + // break; + // + // case SE_CriticalDamageMob: + // { + // // base1 = effect value, base2 = skill restrictions(-1 for all) + // if(base2 == ALL_SKILLS) + // newbon->CritDmgMob[HIGHEST_SKILL+1] += base1; + // else + // newbon->CritDmgMob[base2] += base1; + // break; + // } + // + // case SE_CriticalSpellChance: + // { + // newbon->CriticalSpellChance += base1; + // + // if (base2 > newbon->SpellCritDmgIncNoStack) + // newbon->SpellCritDmgIncNoStack = base2; + // + // break; + // } + // + // case SE_ResistFearChance: + // { + // if(base1 == 100) // If we reach 100% in a single spell/item then we should be immune to negative fear resist effects until our immunity is over + // newbon->Fearless = true; + // + // newbon->ResistFearChance += base1; // these should stack + // break; + // } + // + // case SE_SkillDamageAmount: + // { + // if(base2 == ALL_SKILLS) + // newbon->SkillDamageAmount[HIGHEST_SKILL+1] += base1; + // else + // newbon->SkillDamageAmount[base2] += base1; + // break; + // } + // + // case SE_SpecialAttackKBProc: + // { + // //You can only have one of these per client. [AA Dragon Punch] + // newbon->SpecialAttackKBProc[0] = base1; //Chance base 100 = 25% proc rate + // newbon->SpecialAttackKBProc[1] = base2; //Skill to KB Proc Off + // break; + // } + // + // case SE_DamageModifier: + // { + // if(base2 == ALL_SKILLS) + // newbon->DamageModifier[HIGHEST_SKILL+1] += base1; + // else + // newbon->DamageModifier[base2] += base1; + // break; + // } + // + // case SE_DamageModifier2: + // { + // if(base2 == ALL_SKILLS) + // newbon->DamageModifier2[HIGHEST_SKILL+1] += base1; + // else + // newbon->DamageModifier2[base2] += base1; + // break; + // } + // + // case SE_SlayUndead: + // { + // if(newbon->SlayUndead[1] < base1) + // newbon->SlayUndead[0] = base1; // Rate + // newbon->SlayUndead[1] = base2; // Damage Modifier + // break; + // } + // + // case SE_DoubleRiposte: + // { + // newbon->DoubleRiposte += base1; + // } + // + // case SE_GiveDoubleRiposte: + // { + // //0=Regular Riposte 1=Skill Attack Riposte 2=Skill + // if(base2 == 0){ + // if(newbon->GiveDoubleRiposte[0] < base1) + // newbon->GiveDoubleRiposte[0] = base1; + // } + // //Only for special attacks. + // else if(base2 > 0 && (newbon->GiveDoubleRiposte[1] < base1)){ + // newbon->GiveDoubleRiposte[1] = base1; + // newbon->GiveDoubleRiposte[2] = base2; + // } + // + // break; + // } + // + // //Kayen: Not sure best way to implement this yet. + // //Physically raises skill cap ie if 55/55 it will raise to 55/60 + // case SE_RaiseSkillCap: + // { + // if(newbon->RaiseSkillCap[0] < base1){ + // newbon->RaiseSkillCap[0] = base1; //value + // newbon->RaiseSkillCap[1] = base2; //skill + // } + // break; + // } + // + // case SE_MasteryofPast: + // { + // if(newbon->MasteryofPast < base1) + // newbon->MasteryofPast = base1; + // break; + // } + // + // case SE_CastingLevel2: + // case SE_CastingLevel: + // { + // newbon->effective_casting_level += base1; + // break; + // } + // + // case SE_DivineSave: + // { + // if(newbon->DivineSaveChance[0] < base1) + // { + // newbon->DivineSaveChance[0] = base1; + // newbon->DivineSaveChance[1] = base2; + // } + // break; + // } + // + // + // case SE_SpellEffectResistChance: + // { + // for(int e = 0; e < MAX_RESISTABLE_EFFECTS*2; e+=2) + // { + // if(newbon->SEResist[e+1] && (newbon->SEResist[e] == base2) && (newbon->SEResist[e+1] < base1)){ + // newbon->SEResist[e] = base2; //Spell Effect ID + // newbon->SEResist[e+1] = base1; //Resist Chance + // break; + // } + // else if (!newbon->SEResist[e+1]){ + // newbon->SEResist[e] = base2; //Spell Effect ID + // newbon->SEResist[e+1] = base1; //Resist Chance + // break; + // } + // } + // break; + // } + // + // case SE_MitigateDamageShield: + // { + // if (base1 < 0) + // base1 = base1*(-1); + // + // newbon->DSMitigationOffHand += base1; + // break; + // } + // + // case SE_FinishingBlow: + // { + // //base1 = chance, base2 = damage + // if (newbon->FinishingBlow[1] < base2){ + // newbon->FinishingBlow[0] = base1; + // newbon->FinishingBlow[1] = base2; + // } + // break; + // } + // + // case SE_FinishingBlowLvl: + // { + // //base1 = level, base2 = ??? (Set to 200 in AA data, possible proc rate mod?) + // if (newbon->FinishingBlowLvl[0] < base1){ + // newbon->FinishingBlowLvl[0] = base1; + // newbon->FinishingBlowLvl[1] = base2; + // } + // break; + // } + // + // case SE_StunBashChance: + // newbon->StunBashChance += base1; + // break; + // + // case SE_IncreaseChanceMemwipe: + // newbon->IncreaseChanceMemwipe += base1; + // break; + // + // case SE_CriticalMend: + // newbon->CriticalMend += base1; + // break; + // + // case SE_HealRate: + // newbon->HealRate += base1; + // break; + // + // case SE_MeleeLifetap: + // { + // + // if((base1 < 0) && (newbon->MeleeLifetap > base1)) + // newbon->MeleeLifetap = base1; + // + // else if(newbon->MeleeLifetap < base1) + // newbon->MeleeLifetap = base1; + // break; + // } + // + // case SE_Vampirism: + // newbon->Vampirism += base1; + // break; + // + // case SE_FrenziedDevastation: + // newbon->FrenziedDevastation += base2; + // break; + // + // case SE_SpellProcChance: + // newbon->SpellProcChance += base1; + // break; + // + // case SE_Berserk: + // newbon->BerserkSPA = true; + // break; + // + // case SE_Metabolism: + // newbon->Metabolism += base1; + // break; + // + // case SE_ImprovedReclaimEnergy: + // { + // if((base1 < 0) && (newbon->ImprovedReclaimEnergy > base1)) + // newbon->ImprovedReclaimEnergy = base1; + // + // else if(newbon->ImprovedReclaimEnergy < base1) + // newbon->ImprovedReclaimEnergy = base1; + // break; + // } + // + // case SE_HeadShot: + // { + // if(newbon->HeadShot[1] < base2){ + // newbon->HeadShot[0] = base1; + // newbon->HeadShot[1] = base2; + // } + // break; + // } + // + // case SE_HeadShotLevel: + // { + // if(newbon->HSLevel < base1) + // newbon->HSLevel = base1; + // break; + // } + // + // case SE_Assassinate: + // { + // if(newbon->Assassinate[1] < base2){ + // newbon->Assassinate[0] = base1; + // newbon->Assassinate[1] = base2; + // } + // break; + // } + // + // case SE_AssassinateLevel: + // { + // if(newbon->AssassinateLevel < base1) + // newbon->AssassinateLevel = base1; + // break; + // } + // + // case SE_PetMeleeMitigation: + // newbon->PetMeleeMitigation += base1; + // break; + // + // case SE_MeleeVulnerability: + // newbon->MeleeVulnerability += base1; + // break; + // + // case SE_FactionModPct: + // { + // if((base1 < 0) && (newbon->FactionModPct > base1)) + // newbon->FactionModPct = base1; + // + // else if(newbon->FactionModPct < base1) + // newbon->FactionModPct = base1; + // break; + // } + // + // case SE_IllusionPersistence: + // newbon->IllusionPersistence = true; + // break; + // + // case SE_LimitToSkill:{ + // if (base1 <= HIGHEST_SKILL) + // newbon->LimitToSkill[base1] = true; + // break; + // } + // + // case SE_SkillProc:{ + // for(int e = 0; e < MAX_SKILL_PROCS; e++) + // { + // if(newbon->SkillProc[e] && newbon->SkillProc[e] == aaid) + // break; //Do not use the same aa id more than once. + // + // else if(!newbon->SkillProc[e]){ + // newbon->SkillProc[e] = aaid; + // break; + // } + // } + // break; + // } + // + // case SE_SkillProcSuccess:{ + // + // for(int e = 0; e < MAX_SKILL_PROCS; e++) + // { + // if(newbon->SkillProcSuccess[e] && newbon->SkillProcSuccess[e] == aaid) + // break; //Do not use the same spell id more than once. + // + // else if(!newbon->SkillProcSuccess[e]){ + // newbon->SkillProcSuccess[e] = aaid; + // break; + // } + // } + // break; + // } + // + // case SE_MeleeMitigation: + // newbon->MeleeMitigationEffect -= base1; + // break; + // + // } + //} } void Mob::CalcSpellBonuses(StatBonuses* newbon) diff --git a/zone/bot.cpp b/zone/bot.cpp index 8b3741443..c6c0f6e7f 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -193,7 +193,7 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to GenerateBaseStats(); LoadTimers(); - LoadAAs(); + //LoadAAs(); old aa, replace this LoadBuffs(); CalcBotStats(false); @@ -1430,114 +1430,103 @@ void Bot::GenerateAABonuses(StatBonuses* newbon) { uint8 botLevel = GetLevel(); memset(newbon, 0, sizeof(StatBonuses)); //start fresh - - if(botLevel >= 51) { - //level 51 = 1 AA level - - int i; - int totalAAs = database.CountAAs(); - uint32 slots = 0; - uint32 aa_AA = 0; - uint32 aa_value = 0; - for (i = 0; i < totalAAs; i++) { //iterate through all of the client's AAs - std::map::iterator aa = botAAs.find(i); - if(aa != botAAs.end()) { // make sure aa exists or we'll crash zone - aa_AA = aa->second.aa_id; //same as aaid from the aa_effects table - aa_value = aa->second.total_levels; //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 + aa_value -1, slots, newbon); //add the bonuses - } - } - } - } + //old aa + //if(botLevel >= 51) { + // //level 51 = 1 AA level + // + // int i; + // int totalAAs = database.CountAAs(); + // uint32 slots = 0; + // uint32 aa_AA = 0; + // uint32 aa_value = 0; + // for (i = 0; i < totalAAs; i++) { //iterate through all of the client's AAs + // std::map::iterator aa = botAAs.find(i); + // if(aa != botAAs.end()) { // make sure aa exists or we'll crash zone + // aa_AA = aa->second.aa_id; //same as aaid from the aa_effects table + // aa_value = aa->second.total_levels; //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 + aa_value -1, slots, newbon); //add the bonuses + // } + // } + // } + //} } -void Bot::LoadAAs() { - int maxAAExpansion = RuleI(Bots, BotAAExpansion); //get expansion to get AAs up to - botAAs.clear(); //start fresh - - std::string query; - - if(GetClass() == BERSERKER) - query = StringFormat("SELECT skill_id FROM altadv_vars WHERE berserker = 1 AND class_type > 1 AND class_type <= %i AND aa_expansion <= %i ORDER BY skill_id;", GetLevel(), maxAAExpansion); - else - query = StringFormat("SELECT skill_id FROM altadv_vars WHERE ((classes & ( 1 << %i )) >> %i) = 1 AND class_type > 1 AND class_type <= %i AND aa_expansion <= %i ORDER BY skill_id;", GetClass(), GetClass(), GetLevel(), maxAAExpansion); - - auto results = database.QueryDatabase(query); - - if(!results.Success()) { - Log.Out(Logs::General, Logs::Error, "Error in Bot::LoadAAs()"); - return; - } - - int totalAAs = database.CountAAs(); - - for (auto row = results.begin(); row != results.end(); ++row) { - uint32 skill_id = 0; - skill_id = atoi(row[0]); - - if(skill_id <= 0 || skill_id >= totalAAs) - continue; - - SendAA_Struct *sendAA = zone->FindAA(skill_id); - - if(!sendAA) - continue; - - for(int i=0; imax_level; i++) { - //Get AA info & add to list - uint32 aaid = sendAA->id + i; - uint8 total_levels = 0; - uint8 req_level; - std::map::iterator RequiredLevel = AARequiredLevelAndCost.find(aaid); - - //Get level required for AA - if(RequiredLevel != AARequiredLevelAndCost.end()) - req_level = RequiredLevel->second.Level; - else - req_level = (sendAA->class_type + i * sendAA->level_inc); - - if(req_level > GetLevel()) - break; - - //Bot is high enough level for AA - std::map::iterator foundAA = botAAs.find(aaid); - - // AA is already in list - if(foundAA != botAAs.end()) - continue; - - if(sendAA->id == aaid) { - BotAA newAA; - - newAA.total_levels = 0; - newAA.aa_id = aaid; - newAA.req_level = req_level; - newAA.total_levels += 1; - - botAAs[aaid] = newAA; //add to list - } - else //update master AA record with number of levels a bot has in AA, based on level. - botAAs[sendAA->id].total_levels+=1; - } - } - -} - -uint32 Bot::GetAA(uint32 aa_id) { - - std::map::const_iterator find_iter = botAAs.find(aa_id); - int aaLevel = 0; - - if(find_iter != botAAs.end()) { - aaLevel = find_iter->second.total_levels; - } - - return aaLevel; -} +//old AA +//void Bot::LoadAAs() { +// int maxAAExpansion = RuleI(Bots, BotAAExpansion); //get expansion to get AAs up to +// botAAs.clear(); //start fresh +// +// std::string query; +// +// if(GetClass() == BERSERKER) +// query = StringFormat("SELECT skill_id FROM altadv_vars WHERE berserker = 1 AND class_type > 1 AND class_type <= %i AND aa_expansion <= %i ORDER BY skill_id;", GetLevel(), maxAAExpansion); +// else +// query = StringFormat("SELECT skill_id FROM altadv_vars WHERE ((classes & ( 1 << %i )) >> %i) = 1 AND class_type > 1 AND class_type <= %i AND aa_expansion <= %i ORDER BY skill_id;", GetClass(), GetClass(), GetLevel(), maxAAExpansion); +// +// auto results = database.QueryDatabase(query); +// +// if(!results.Success()) { +// Log.Out(Logs::General, Logs::Error, "Error in Bot::LoadAAs()"); +// return; +// } +// +// int totalAAs = database.CountAAs(); +// +// for (auto row = results.begin(); row != results.end(); ++row) { +// uint32 skill_id = 0; +// skill_id = atoi(row[0]); +// +// if(skill_id <= 0 || skill_id >= totalAAs) +// continue; +// +// SendAA_Struct *sendAA = zone->FindAA(skill_id); +// +// if(!sendAA) +// continue; +// +// for(int i=0; imax_level; i++) { +// //Get AA info & add to list +// uint32 aaid = sendAA->id + i; +// uint8 total_levels = 0; +// uint8 req_level; +// std::map::iterator RequiredLevel = AARequiredLevelAndCost.find(aaid); +// +// //Get level required for AA +// if(RequiredLevel != AARequiredLevelAndCost.end()) +// req_level = RequiredLevel->second.Level; +// else +// req_level = (sendAA->class_type + i * sendAA->level_inc); +// +// if(req_level > GetLevel()) +// break; +// +// //Bot is high enough level for AA +// std::map::iterator foundAA = botAAs.find(aaid); +// +// // AA is already in list +// if(foundAA != botAAs.end()) +// continue; +// +// if(sendAA->id == aaid) { +// BotAA newAA; +// +// newAA.total_levels = 0; +// newAA.aa_id = aaid; +// newAA.req_level = req_level; +// newAA.total_levels += 1; +// +// botAAs[aaid] = newAA; //add to list +// } +// else //update master AA record with number of levels a bot has in AA, based on level. +// botAAs[sendAA->id].total_levels+=1; +// } +// } +// +//} //current with Client::ApplyAABonuses 9/26/12 void Bot::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) @@ -1551,551 +1540,552 @@ void Bot::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) int32 base2 = 0; //only really used for SE_RaiseStatCap & SE_ReduceSkillTimer in aa_effects table uint32 slot = 0; - std::map >::const_iterator find_iter = aa_effects.find(aaid); - if(find_iter == aa_effects.end()) - { - return; - } - - for (std::map::const_iterator iter = aa_effects[aaid].begin(); iter != aa_effects[aaid].end(); ++iter) { - effect = iter->second.skill_id; - base1 = iter->second.base1; - base2 = iter->second.base2; - slot = iter->second.slot; - - //we default to 0 (SE_CurrentHP) for the effect, so if there aren't any base1/2 values, we'll just skip it - if (effect == 0 && base1 == 0 && base2 == 0) - continue; - - //IsBlankSpellEffect() - if (effect == SE_Blank || (effect == SE_CHA && base1 == 0) || effect == SE_StackingCommand_Block || effect == SE_StackingCommand_Overwrite) - continue; - - Log.Out(Logs::Detail, Logs::AA, "Applying Effect %d from AA %u in slot %d (base1: %d, base2: %d) on %s", effect, aaid, slot, base1, base2, this->GetCleanName()); - - uint8 focus = IsFocusEffect(0, 0, true,effect); - if (focus) - { - newbon->FocusEffects[focus] = effect; - continue; - } - - switch (effect) - { - //Note: AA effects that use accuracy are skill limited, while spell effect is not. - case SE_Accuracy: - if ((base2 == -1) && (newbon->Accuracy[HIGHEST_SKILL+1] < base1)) - newbon->Accuracy[HIGHEST_SKILL+1] = base1; - else if (newbon->Accuracy[base2] < base1) - newbon->Accuracy[base2] += base1; - break; - case SE_CurrentHP: //regens - newbon->HPRegen += base1; - break; - case SE_CurrentEndurance: - newbon->EnduranceRegen += base1; - break; - case SE_MovementSpeed: - newbon->movementspeed += base1; //should we let these stack? - /*if (base1 > newbon->movementspeed) //or should we use a total value? - newbon->movementspeed = base1;*/ - break; - case SE_STR: - newbon->STR += base1; - break; - case SE_DEX: - newbon->DEX += base1; - break; - case SE_AGI: - newbon->AGI += base1; - break; - case SE_STA: - newbon->STA += base1; - break; - case SE_INT: - newbon->INT += base1; - break; - case SE_WIS: - newbon->WIS += base1; - break; - case SE_CHA: - newbon->CHA += base1; - break; - case SE_WaterBreathing: - //handled by client - break; - case SE_CurrentMana: - newbon->ManaRegen += base1; - break; - case SE_ItemManaRegenCapIncrease: - newbon->ItemManaRegenCap += base1; - break; - case SE_ResistFire: - newbon->FR += base1; - break; - case SE_ResistCold: - newbon->CR += base1; - break; - case SE_ResistPoison: - newbon->PR += base1; - break; - case SE_ResistDisease: - newbon->DR += base1; - break; - case SE_ResistMagic: - newbon->MR += base1; - break; - case SE_ResistCorruption: - newbon->Corrup += base1; - break; - case SE_IncreaseSpellHaste: - break; - case SE_IncreaseRange: - break; - case SE_MaxHPChange: - newbon->MaxHP += base1; - break; - case SE_Packrat: - newbon->Packrat += base1; - break; - case SE_TwoHandBash: - break; - case SE_SetBreathLevel: - break; - case SE_RaiseStatCap: - switch(base2) - { - //are these #define'd somewhere? - case 0: //str - newbon->STRCapMod += base1; - break; - case 1: //sta - newbon->STACapMod += base1; - break; - case 2: //agi - newbon->AGICapMod += base1; - break; - case 3: //dex - newbon->DEXCapMod += base1; - break; - case 4: //wis - newbon->WISCapMod += base1; - break; - case 5: //int - newbon->INTCapMod += base1; - break; - case 6: //cha - newbon->CHACapMod += base1; - break; - case 7: //mr - newbon->MRCapMod += base1; - break; - case 8: //cr - newbon->CRCapMod += base1; - break; - case 9: //fr - newbon->FRCapMod += base1; - break; - case 10: //pr - newbon->PRCapMod += base1; - break; - case 11: //dr - newbon->DRCapMod += base1; - break; - case 12: //corruption - newbon->CorrupCapMod += base1; - break; - } - break; - case SE_PetDiscipline2: - break; - case SE_SpellSlotIncrease: - break; - case SE_MysticalAttune: - newbon->BuffSlotIncrease += base1; - break; - case SE_TotalHP: - newbon->HP += base1; - break; - case SE_StunResist: - newbon->StunResist += base1; - break; - case SE_SpellCritChance: - newbon->CriticalSpellChance += base1; - break; - case SE_SpellCritDmgIncrease: - newbon->SpellCritDmgIncrease += base1; - break; - case SE_DotCritDmgIncrease: - newbon->DotCritDmgIncrease += base1; - break; - case SE_ResistSpellChance: - newbon->ResistSpellChance += base1; - break; - case SE_CriticalHealChance: - newbon->CriticalHealChance += base1; - break; - case SE_CriticalHealOverTime: - newbon->CriticalHealOverTime += base1; - break; - case SE_CriticalDoTChance: - newbon->CriticalDoTChance += base1; - break; - case SE_ReduceSkillTimer: - newbon->SkillReuseTime[base2] += base1; - break; - case SE_Fearless: - newbon->Fearless = true; - break; - case SE_PersistantCasting: - newbon->PersistantCasting += base1; - break; - case SE_DelayDeath: - newbon->DelayDeath += base1; - break; - case SE_FrontalStunResist: - newbon->FrontalStunResist += base1; - break; - case SE_ImprovedBindWound: - newbon->BindWound += base1; - break; - case SE_MaxBindWound: - newbon->MaxBindWound += base1; - break; - case SE_ExtraAttackChance: - newbon->ExtraAttackChance += base1; - break; - case SE_SeeInvis: - newbon->SeeInvis = base1; - break; - case SE_BaseMovementSpeed: - newbon->BaseMovementSpeed += base1; - break; - case SE_IncreaseRunSpeedCap: - newbon->IncreaseRunSpeedCap += base1; - break; - case SE_ConsumeProjectile: - newbon->ConsumeProjectile += base1; - break; - case SE_ArcheryDamageModifier: - newbon->ArcheryDamageModifier += base1; - break; - case SE_DamageShield: - newbon->DamageShield += base1; - break; - case SE_CharmBreakChance: - newbon->CharmBreakChance += base1; - break; - case SE_OffhandRiposteFail: - newbon->OffhandRiposteFail += base1; - break; - case SE_ItemAttackCapIncrease: - newbon->ItemATKCap += base1; - break; - case SE_GivePetGroupTarget: - newbon->GivePetGroupTarget = true; - break; - case SE_ItemHPRegenCapIncrease: - newbon->ItemHPRegenCap = +base1; - break; - case SE_Ambidexterity: - newbon->Ambidexterity += base1; - break; - case SE_PetMaxHP: - newbon->PetMaxHP += base1; - break; - case SE_AvoidMeleeChance: - newbon->AvoidMeleeChance += base1; - break; - case SE_CombatStability: - newbon->CombatStability += base1; - break; - case SE_PetCriticalHit: - newbon->PetCriticalHit += base1; - break; - case SE_PetAvoidance: - newbon->PetAvoidance += base1; - break; - case SE_ShieldBlock: - newbon->ShieldBlock += base1; - break; - case SE_SecondaryDmgInc: - newbon->SecondaryDmgInc = true; - break; - case SE_ChangeAggro: - newbon->hatemod += base1; - break; - case SE_EndurancePool: - newbon->Endurance += base1; - break; - case SE_ChannelChanceItems: - newbon->ChannelChanceItems += base1; - break; - case SE_ChannelChanceSpells: - newbon->ChannelChanceSpells += base1; - break; - case SE_DoubleSpecialAttack: - newbon->DoubleSpecialAttack += base1; - break; - case SE_TripleBackstab: - newbon->TripleBackstab += base1; - break; - case SE_FrontalBackstabMinDmg: - newbon->FrontalBackstabMinDmg = true; - break; - case SE_FrontalBackstabChance: - newbon->FrontalBackstabChance += base1; - break; - case SE_BlockBehind: - newbon->BlockBehind += base1; - break; - case SE_StrikeThrough2: - newbon->StrikeThrough += base1; - break; - case SE_DoubleAttackChance: - newbon->DoubleAttackChance += base1; - break; - case SE_GiveDoubleAttack: - newbon->GiveDoubleAttack += base1; - break; - case SE_ProcChance: - newbon->ProcChance += base1; - break; - case SE_RiposteChance: - newbon->RiposteChance += base1; - break; - case SE_Flurry: - newbon->FlurryChance += base1; - break; - case SE_PetFlurry: - newbon->PetFlurry = base1; - break; - case SE_BardSongRange: - newbon->SongRange += base1; - break; - case SE_RootBreakChance: - newbon->RootBreakChance += base1; - break; - case SE_UnfailingDivinity: - newbon->UnfailingDivinity += base1; - break; - - case SE_ProcOnKillShot: - for(int i = 0; i < MAX_SPELL_TRIGGER*3; i+=3) - { - if(!newbon->SpellOnKill[i] || ((newbon->SpellOnKill[i] == base2) && (newbon->SpellOnKill[i+1] < base1))) - { - //base1 = chance, base2 = SpellID to be triggered, base3 = min npc level - newbon->SpellOnKill[i] = base2; - newbon->SpellOnKill[i+1] = base1; - - if (GetLevel() > 15) - newbon->SpellOnKill[i+2] = GetLevel() - 15; //AA specifiy "non-trivial" - else - newbon->SpellOnKill[i+2] = 0; - - break; - } - } - break; - - case SE_SpellOnDeath: - for(int i = 0; i < MAX_SPELL_TRIGGER*2; i+=2) - { - if(!newbon->SpellOnDeath[i]) - { - // base1 = SpellID to be triggered, base2 = chance to fire - newbon->SpellOnDeath[i] = base1; - newbon->SpellOnDeath[i+1] = base2; - break; - } - } - break; - - case SE_TriggerOnCast: - - for(int i = 0; i < MAX_SPELL_TRIGGER; i++) - { - if (newbon->SpellTriggers[i] == aaid) - break; - - if(!newbon->SpellTriggers[i]) - { - //Save the 'aaid' of each triggerable effect to an array - newbon->SpellTriggers[i] = aaid; - break; - } - } - break; - - case SE_CriticalHitChance: - { - if(base2 == -1) - newbon->CriticalHitChance[HIGHEST_SKILL+1] += base1; - else - newbon->CriticalHitChance[base2] += base1; - } - break; - - case SE_CriticalDamageMob: - { - // base1 = effect value, base2 = skill restrictions(-1 for all) - if(base2 == -1) - newbon->CritDmgMob[HIGHEST_SKILL+1] += base1; - else - newbon->CritDmgMob[base2] += base1; - break; - } - - case SE_CriticalSpellChance: - { - newbon->CriticalSpellChance += base1; - - if (base2 > newbon->SpellCritDmgIncrease) - newbon->SpellCritDmgIncrease = base2; - - break; - } - - case SE_ResistFearChance: - { - if(base1 == 100) // If we reach 100% in a single spell/item then we should be immune to negative fear resist effects until our immunity is over - newbon->Fearless = true; - - newbon->ResistFearChance += base1; // these should stack - break; - } - - case SE_SkillDamageAmount: - { - if(base2 == -1) - newbon->SkillDamageAmount[HIGHEST_SKILL+1] += base1; - else - newbon->SkillDamageAmount[base2] += base1; - break; - } - - case SE_SpecialAttackKBProc: - { - //You can only have one of these per client. [AA Dragon Punch] - newbon->SpecialAttackKBProc[0] = base1; //Chance base 100 = 25% proc rate - newbon->SpecialAttackKBProc[1] = base2; //Skill to KB Proc Off - break; - } - - case SE_DamageModifier: - { - if(base2 == -1) - newbon->DamageModifier[HIGHEST_SKILL+1] += base1; - else - newbon->DamageModifier[base2] += base1; - break; - } - - case SE_SlayUndead: - { - if(newbon->SlayUndead[1] < base1) - newbon->SlayUndead[0] = base1; // Rate - newbon->SlayUndead[1] = base2; // Damage Modifier - break; - } - - case SE_GiveDoubleRiposte: - { - //0=Regular Riposte 1=Skill Attack Riposte 2=Skill - if(base2 == 0){ - if(newbon->GiveDoubleRiposte[0] < base1) - newbon->GiveDoubleRiposte[0] = base1; - } - //Only for special attacks. - else if(base2 > 0 && (newbon->GiveDoubleRiposte[1] < base1)){ - newbon->GiveDoubleRiposte[1] = base1; - newbon->GiveDoubleRiposte[2] = base2; - } - - break; - } - - //Kayen: Not sure best way to implement this yet. - //Physically raises skill cap ie if 55/55 it will raise to 55/60 - case SE_RaiseSkillCap: - { - if(newbon->RaiseSkillCap[0] < base1){ - newbon->RaiseSkillCap[0] = base1; //value - newbon->RaiseSkillCap[1] = base2; //skill - } - break; - } - - case SE_MasteryofPast: - { - if(newbon->MasteryofPast < base1) - newbon->MasteryofPast = base1; - break; - } - - case SE_CastingLevel2: - case SE_CastingLevel: - { - newbon->effective_casting_level += base1; - break; - } - - - case SE_DivineSave: - { - if(newbon->DivineSaveChance[0] < base1) - { - newbon->DivineSaveChance[0] = base1; - newbon->DivineSaveChance[1] = base2; - } - break; - } - - case SE_SpellEffectResistChance: - { - for(int e = 0; e < MAX_RESISTABLE_EFFECTS*2; e+=2) - { - if(!newbon->SEResist[e] || ((newbon->SEResist[e] = base2) && (newbon->SEResist[e+1] < base1)) ){ - newbon->SEResist[e] = base2; - newbon->SEResist[e+1] = base1; - break; - } - } - break; - } - - case SE_MitigateDamageShield: - { - if (base1 < 0) - base1 = base1*(-1); - - newbon->DSMitigationOffHand += base1; - break; - } - - case SE_FinishingBlow: - { - - //base1 = chance, base2 = damage - if (newbon->FinishingBlow[1] < base2){ - newbon->FinishingBlow[0] = base1; - newbon->FinishingBlow[1] = base2; - } - break; - } - - case SE_FinishingBlowLvl: - { - //base1 = level, base2 = ??? (Set to 200 in AA data, possible proc rate mod?) - if (newbon->FinishingBlowLvl[0] < base1){ - newbon->FinishingBlowLvl[0] = base1; - newbon->FinishingBlowLvl[1] = base2; - } - break; - } - } - } + //old AA + //std::map >::const_iterator find_iter = aa_effects.find(aaid); + //if(find_iter == aa_effects.end()) + //{ + // return; + //} + // + //for (std::map::const_iterator iter = aa_effects[aaid].begin(); iter != aa_effects[aaid].end(); ++iter) { + // effect = iter->second.skill_id; + // base1 = iter->second.base1; + // base2 = iter->second.base2; + // slot = iter->second.slot; + // + // //we default to 0 (SE_CurrentHP) for the effect, so if there aren't any base1/2 values, we'll just skip it + // if (effect == 0 && base1 == 0 && base2 == 0) + // continue; + // + // //IsBlankSpellEffect() + // if (effect == SE_Blank || (effect == SE_CHA && base1 == 0) || effect == SE_StackingCommand_Block || effect == SE_StackingCommand_Overwrite) + // continue; + // + // Log.Out(Logs::Detail, Logs::AA, "Applying Effect %d from AA %u in slot %d (base1: %d, base2: %d) on %s", effect, aaid, slot, base1, base2, this->GetCleanName()); + // + // uint8 focus = IsFocusEffect(0, 0, true,effect); + // if (focus) + // { + // newbon->FocusEffects[focus] = effect; + // continue; + // } + // + // switch (effect) + // { + // //Note: AA effects that use accuracy are skill limited, while spell effect is not. + // case SE_Accuracy: + // if ((base2 == -1) && (newbon->Accuracy[HIGHEST_SKILL+1] < base1)) + // newbon->Accuracy[HIGHEST_SKILL+1] = base1; + // else if (newbon->Accuracy[base2] < base1) + // newbon->Accuracy[base2] += base1; + // break; + // case SE_CurrentHP: //regens + // newbon->HPRegen += base1; + // break; + // case SE_CurrentEndurance: + // newbon->EnduranceRegen += base1; + // break; + // case SE_MovementSpeed: + // newbon->movementspeed += base1; //should we let these stack? + // /*if (base1 > newbon->movementspeed) //or should we use a total value? + // newbon->movementspeed = base1;*/ + // break; + // case SE_STR: + // newbon->STR += base1; + // break; + // case SE_DEX: + // newbon->DEX += base1; + // break; + // case SE_AGI: + // newbon->AGI += base1; + // break; + // case SE_STA: + // newbon->STA += base1; + // break; + // case SE_INT: + // newbon->INT += base1; + // break; + // case SE_WIS: + // newbon->WIS += base1; + // break; + // case SE_CHA: + // newbon->CHA += base1; + // break; + // case SE_WaterBreathing: + // //handled by client + // break; + // case SE_CurrentMana: + // newbon->ManaRegen += base1; + // break; + // case SE_ItemManaRegenCapIncrease: + // newbon->ItemManaRegenCap += base1; + // break; + // case SE_ResistFire: + // newbon->FR += base1; + // break; + // case SE_ResistCold: + // newbon->CR += base1; + // break; + // case SE_ResistPoison: + // newbon->PR += base1; + // break; + // case SE_ResistDisease: + // newbon->DR += base1; + // break; + // case SE_ResistMagic: + // newbon->MR += base1; + // break; + // case SE_ResistCorruption: + // newbon->Corrup += base1; + // break; + // case SE_IncreaseSpellHaste: + // break; + // case SE_IncreaseRange: + // break; + // case SE_MaxHPChange: + // newbon->MaxHP += base1; + // break; + // case SE_Packrat: + // newbon->Packrat += base1; + // break; + // case SE_TwoHandBash: + // break; + // case SE_SetBreathLevel: + // break; + // case SE_RaiseStatCap: + // switch(base2) + // { + // //are these #define'd somewhere? + // case 0: //str + // newbon->STRCapMod += base1; + // break; + // case 1: //sta + // newbon->STACapMod += base1; + // break; + // case 2: //agi + // newbon->AGICapMod += base1; + // break; + // case 3: //dex + // newbon->DEXCapMod += base1; + // break; + // case 4: //wis + // newbon->WISCapMod += base1; + // break; + // case 5: //int + // newbon->INTCapMod += base1; + // break; + // case 6: //cha + // newbon->CHACapMod += base1; + // break; + // case 7: //mr + // newbon->MRCapMod += base1; + // break; + // case 8: //cr + // newbon->CRCapMod += base1; + // break; + // case 9: //fr + // newbon->FRCapMod += base1; + // break; + // case 10: //pr + // newbon->PRCapMod += base1; + // break; + // case 11: //dr + // newbon->DRCapMod += base1; + // break; + // case 12: //corruption + // newbon->CorrupCapMod += base1; + // break; + // } + // break; + // case SE_PetDiscipline2: + // break; + // case SE_SpellSlotIncrease: + // break; + // case SE_MysticalAttune: + // newbon->BuffSlotIncrease += base1; + // break; + // case SE_TotalHP: + // newbon->HP += base1; + // break; + // case SE_StunResist: + // newbon->StunResist += base1; + // break; + // case SE_SpellCritChance: + // newbon->CriticalSpellChance += base1; + // break; + // case SE_SpellCritDmgIncrease: + // newbon->SpellCritDmgIncrease += base1; + // break; + // case SE_DotCritDmgIncrease: + // newbon->DotCritDmgIncrease += base1; + // break; + // case SE_ResistSpellChance: + // newbon->ResistSpellChance += base1; + // break; + // case SE_CriticalHealChance: + // newbon->CriticalHealChance += base1; + // break; + // case SE_CriticalHealOverTime: + // newbon->CriticalHealOverTime += base1; + // break; + // case SE_CriticalDoTChance: + // newbon->CriticalDoTChance += base1; + // break; + // case SE_ReduceSkillTimer: + // newbon->SkillReuseTime[base2] += base1; + // break; + // case SE_Fearless: + // newbon->Fearless = true; + // break; + // case SE_PersistantCasting: + // newbon->PersistantCasting += base1; + // break; + // case SE_DelayDeath: + // newbon->DelayDeath += base1; + // break; + // case SE_FrontalStunResist: + // newbon->FrontalStunResist += base1; + // break; + // case SE_ImprovedBindWound: + // newbon->BindWound += base1; + // break; + // case SE_MaxBindWound: + // newbon->MaxBindWound += base1; + // break; + // case SE_ExtraAttackChance: + // newbon->ExtraAttackChance += base1; + // break; + // case SE_SeeInvis: + // newbon->SeeInvis = base1; + // break; + // case SE_BaseMovementSpeed: + // newbon->BaseMovementSpeed += base1; + // break; + // case SE_IncreaseRunSpeedCap: + // newbon->IncreaseRunSpeedCap += base1; + // break; + // case SE_ConsumeProjectile: + // newbon->ConsumeProjectile += base1; + // break; + // case SE_ArcheryDamageModifier: + // newbon->ArcheryDamageModifier += base1; + // break; + // case SE_DamageShield: + // newbon->DamageShield += base1; + // break; + // case SE_CharmBreakChance: + // newbon->CharmBreakChance += base1; + // break; + // case SE_OffhandRiposteFail: + // newbon->OffhandRiposteFail += base1; + // break; + // case SE_ItemAttackCapIncrease: + // newbon->ItemATKCap += base1; + // break; + // case SE_GivePetGroupTarget: + // newbon->GivePetGroupTarget = true; + // break; + // case SE_ItemHPRegenCapIncrease: + // newbon->ItemHPRegenCap = +base1; + // break; + // case SE_Ambidexterity: + // newbon->Ambidexterity += base1; + // break; + // case SE_PetMaxHP: + // newbon->PetMaxHP += base1; + // break; + // case SE_AvoidMeleeChance: + // newbon->AvoidMeleeChance += base1; + // break; + // case SE_CombatStability: + // newbon->CombatStability += base1; + // break; + // case SE_PetCriticalHit: + // newbon->PetCriticalHit += base1; + // break; + // case SE_PetAvoidance: + // newbon->PetAvoidance += base1; + // break; + // case SE_ShieldBlock: + // newbon->ShieldBlock += base1; + // break; + // case SE_SecondaryDmgInc: + // newbon->SecondaryDmgInc = true; + // break; + // case SE_ChangeAggro: + // newbon->hatemod += base1; + // break; + // case SE_EndurancePool: + // newbon->Endurance += base1; + // break; + // case SE_ChannelChanceItems: + // newbon->ChannelChanceItems += base1; + // break; + // case SE_ChannelChanceSpells: + // newbon->ChannelChanceSpells += base1; + // break; + // case SE_DoubleSpecialAttack: + // newbon->DoubleSpecialAttack += base1; + // break; + // case SE_TripleBackstab: + // newbon->TripleBackstab += base1; + // break; + // case SE_FrontalBackstabMinDmg: + // newbon->FrontalBackstabMinDmg = true; + // break; + // case SE_FrontalBackstabChance: + // newbon->FrontalBackstabChance += base1; + // break; + // case SE_BlockBehind: + // newbon->BlockBehind += base1; + // break; + // case SE_StrikeThrough2: + // newbon->StrikeThrough += base1; + // break; + // case SE_DoubleAttackChance: + // newbon->DoubleAttackChance += base1; + // break; + // case SE_GiveDoubleAttack: + // newbon->GiveDoubleAttack += base1; + // break; + // case SE_ProcChance: + // newbon->ProcChance += base1; + // break; + // case SE_RiposteChance: + // newbon->RiposteChance += base1; + // break; + // case SE_Flurry: + // newbon->FlurryChance += base1; + // break; + // case SE_PetFlurry: + // newbon->PetFlurry = base1; + // break; + // case SE_BardSongRange: + // newbon->SongRange += base1; + // break; + // case SE_RootBreakChance: + // newbon->RootBreakChance += base1; + // break; + // case SE_UnfailingDivinity: + // newbon->UnfailingDivinity += base1; + // break; + // + // case SE_ProcOnKillShot: + // for(int i = 0; i < MAX_SPELL_TRIGGER*3; i+=3) + // { + // if(!newbon->SpellOnKill[i] || ((newbon->SpellOnKill[i] == base2) && (newbon->SpellOnKill[i+1] < base1))) + // { + // //base1 = chance, base2 = SpellID to be triggered, base3 = min npc level + // newbon->SpellOnKill[i] = base2; + // newbon->SpellOnKill[i+1] = base1; + // + // if (GetLevel() > 15) + // newbon->SpellOnKill[i+2] = GetLevel() - 15; //AA specifiy "non-trivial" + // else + // newbon->SpellOnKill[i+2] = 0; + // + // break; + // } + // } + // break; + // + // case SE_SpellOnDeath: + // for(int i = 0; i < MAX_SPELL_TRIGGER*2; i+=2) + // { + // if(!newbon->SpellOnDeath[i]) + // { + // // base1 = SpellID to be triggered, base2 = chance to fire + // newbon->SpellOnDeath[i] = base1; + // newbon->SpellOnDeath[i+1] = base2; + // break; + // } + // } + // break; + // + // case SE_TriggerOnCast: + // + // for(int i = 0; i < MAX_SPELL_TRIGGER; i++) + // { + // if (newbon->SpellTriggers[i] == aaid) + // break; + // + // if(!newbon->SpellTriggers[i]) + // { + // //Save the 'aaid' of each triggerable effect to an array + // newbon->SpellTriggers[i] = aaid; + // break; + // } + // } + // break; + // + // case SE_CriticalHitChance: + // { + // if(base2 == -1) + // newbon->CriticalHitChance[HIGHEST_SKILL+1] += base1; + // else + // newbon->CriticalHitChance[base2] += base1; + // } + // break; + // + // case SE_CriticalDamageMob: + // { + // // base1 = effect value, base2 = skill restrictions(-1 for all) + // if(base2 == -1) + // newbon->CritDmgMob[HIGHEST_SKILL+1] += base1; + // else + // newbon->CritDmgMob[base2] += base1; + // break; + // } + // + // case SE_CriticalSpellChance: + // { + // newbon->CriticalSpellChance += base1; + // + // if (base2 > newbon->SpellCritDmgIncrease) + // newbon->SpellCritDmgIncrease = base2; + // + // break; + // } + // + // case SE_ResistFearChance: + // { + // if(base1 == 100) // If we reach 100% in a single spell/item then we should be immune to negative fear resist effects until our immunity is over + // newbon->Fearless = true; + // + // newbon->ResistFearChance += base1; // these should stack + // break; + // } + // + // case SE_SkillDamageAmount: + // { + // if(base2 == -1) + // newbon->SkillDamageAmount[HIGHEST_SKILL+1] += base1; + // else + // newbon->SkillDamageAmount[base2] += base1; + // break; + // } + // + // case SE_SpecialAttackKBProc: + // { + // //You can only have one of these per client. [AA Dragon Punch] + // newbon->SpecialAttackKBProc[0] = base1; //Chance base 100 = 25% proc rate + // newbon->SpecialAttackKBProc[1] = base2; //Skill to KB Proc Off + // break; + // } + // + // case SE_DamageModifier: + // { + // if(base2 == -1) + // newbon->DamageModifier[HIGHEST_SKILL+1] += base1; + // else + // newbon->DamageModifier[base2] += base1; + // break; + // } + // + // case SE_SlayUndead: + // { + // if(newbon->SlayUndead[1] < base1) + // newbon->SlayUndead[0] = base1; // Rate + // newbon->SlayUndead[1] = base2; // Damage Modifier + // break; + // } + // + // case SE_GiveDoubleRiposte: + // { + // //0=Regular Riposte 1=Skill Attack Riposte 2=Skill + // if(base2 == 0){ + // if(newbon->GiveDoubleRiposte[0] < base1) + // newbon->GiveDoubleRiposte[0] = base1; + // } + // //Only for special attacks. + // else if(base2 > 0 && (newbon->GiveDoubleRiposte[1] < base1)){ + // newbon->GiveDoubleRiposte[1] = base1; + // newbon->GiveDoubleRiposte[2] = base2; + // } + // + // break; + // } + // + // //Kayen: Not sure best way to implement this yet. + // //Physically raises skill cap ie if 55/55 it will raise to 55/60 + // case SE_RaiseSkillCap: + // { + // if(newbon->RaiseSkillCap[0] < base1){ + // newbon->RaiseSkillCap[0] = base1; //value + // newbon->RaiseSkillCap[1] = base2; //skill + // } + // break; + // } + // + // case SE_MasteryofPast: + // { + // if(newbon->MasteryofPast < base1) + // newbon->MasteryofPast = base1; + // break; + // } + // + // case SE_CastingLevel2: + // case SE_CastingLevel: + // { + // newbon->effective_casting_level += base1; + // break; + // } + // + // + // case SE_DivineSave: + // { + // if(newbon->DivineSaveChance[0] < base1) + // { + // newbon->DivineSaveChance[0] = base1; + // newbon->DivineSaveChance[1] = base2; + // } + // break; + // } + // + // case SE_SpellEffectResistChance: + // { + // for(int e = 0; e < MAX_RESISTABLE_EFFECTS*2; e+=2) + // { + // if(!newbon->SEResist[e] || ((newbon->SEResist[e] = base2) && (newbon->SEResist[e+1] < base1)) ){ + // newbon->SEResist[e] = base2; + // newbon->SEResist[e+1] = base1; + // break; + // } + // } + // break; + // } + // + // case SE_MitigateDamageShield: + // { + // if (base1 < 0) + // base1 = base1*(-1); + // + // newbon->DSMitigationOffHand += base1; + // break; + // } + // + // case SE_FinishingBlow: + // { + // + // //base1 = chance, base2 = damage + // if (newbon->FinishingBlow[1] < base2){ + // newbon->FinishingBlow[0] = base1; + // newbon->FinishingBlow[1] = base2; + // } + // break; + // } + // + // case SE_FinishingBlowLvl: + // { + // //base1 = level, base2 = ??? (Set to 200 in AA data, possible proc rate mod?) + // if (newbon->FinishingBlowLvl[0] < base1){ + // newbon->FinishingBlowLvl[0] = base1; + // newbon->FinishingBlowLvl[1] = base2; + // } + // break; + // } + // } + //} } bool Bot::IsValidRaceClassCombo() { @@ -6326,398 +6316,399 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id) bool LimitFound = false; int FocusCount = 0; - std::map >::const_iterator find_iter = aa_effects.find(aa_ID); - if(find_iter == aa_effects.end()) - { - return 0; - } + //old AA + //std::map >::const_iterator find_iter = aa_effects.find(aa_ID); + //if(find_iter == aa_effects.end()) + //{ + // return 0; + //} + // + //for (std::map::const_iterator iter = aa_effects[aa_ID].begin(); iter != aa_effects[aa_ID].end(); ++iter) + //{ + // effect = iter->second.skill_id; + // base1 = iter->second.base1; + // base2 = iter->second.base2; + // slot = iter->second.slot; + // + // //AA Foci's can contain multiple focus effects within the same AA. + // //To handle this we will not automatically return zero if a limit is found. + // //Instead if limit is found and multiple effects, we will reset the limit check + // //when the next valid focus effect is found. + // if (IsFocusEffect(0, 0, true,effect) || (effect == SE_TriggerOnCast)){ + // FocusCount++; + // //If limit found on prior check next, else end loop. + // if (FocusCount > 1){ + // if (LimitFound){ + // value = 0; + // LimitFound = false; + // } + // + // else{ + // break; + // } + // } + // } + // + // + // switch (effect) + // { + // case SE_Blank: + // break; + // + // //Handle Focus Limits + // case SE_LimitResist: + // if(base1) + // { + // if(spell.resisttype != base1) + // LimitFound = true; + // } + // break; + // case SE_LimitInstant: + // if(spell.buffduration) + // LimitFound = true; + // break; + // case SE_LimitMaxLevel: + // spell_level = spell.classes[(GetClass()%16) - 1]; + // lvldiff = spell_level - base1; + // //every level over cap reduces the effect by base2 percent unless from a clicky when ItemCastsUseFocus is true + // if(lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || RuleB(Character, ItemCastsUseFocus) == false)) + // { + // if(base2 > 0) + // { + // lvlModifier -= base2*lvldiff; + // if(lvlModifier < 1) + // LimitFound = true; + // } + // else { + // LimitFound = true; + // } + // } + // break; + // case SE_LimitMinLevel: + // if((spell.classes[(GetClass()%16) - 1]) < base1) + // LimitFound = true; + // break; + // case SE_LimitCastTimeMin: + // if (spell.cast_time < base1) + // LimitFound = true; + // break; + // case SE_LimitSpell: + // // Exclude spell(any but this) + // if(base1 < 0) { + // if (spell_id == (base1*-1)) + // LimitFound = true; + // } + // else { + // // Include Spell(only this) + // if (spell_id != base1) + // LimitFound = true; + // } + // break; + // case SE_LimitMinDur: + // if (base1 > CalcBuffDuration_formula(GetLevel(), spell.buffdurationformula, spell.buffduration)) + // LimitFound = true; + // break; + // case SE_LimitEffect: + // // Exclude effect(any but this) + // if(base1 < 0) { + // if(IsEffectInSpell(spell_id,(base1*-1))) + // LimitFound = true; + // } + // else { + // // Include effect(only this) + // if(!IsEffectInSpell(spell_id,base1)) + // LimitFound = true; + // } + // break; + // case SE_LimitSpellType: + // switch(base1) + // { + // case 0: + // if (!IsDetrimentalSpell(spell_id)) + // LimitFound = true; + // break; + // case 1: + // if (!IsBeneficialSpell(spell_id)) + // LimitFound = true; + // break; + // } + // break; + // + // case SE_LimitManaMin: + // if(spell.mana < base1) + // LimitFound = true; + // break; + // + // case SE_LimitTarget: + // // Exclude + // if(base1 < 0){ + // if(-base1 == spell.targettype) + // LimitFound = true; + // } + // // Include + // else { + // if(base1 != spell.targettype) + // LimitFound = true; + // } + // break; + // + // case SE_LimitCombatSkills: + // // 1 is for disciplines only + // if(base1 == 1 && !IsDiscipline(spell_id)) + // LimitFound = true; + // // 0 is spells only + // else if(base1 == 0 && IsDiscipline(spell_id)) + // LimitFound = true; + // break; + // + // case SE_LimitSpellGroup: + // if(base1 > 0 && base1 != spell.spellgroup) + // LimitFound = true; + // else if(base1 < 0 && base1 == spell.spellgroup) + // LimitFound = true; + // break; + // + // + // case SE_LimitCastingSkill: + // LimitSpellSkill = true; + // if(base1 == spell.skill) + // SpellSkill_Found = true; + // break; + // + // case SE_LimitClass: + // //Do not use this limit more then once per spell. If multiple class, treat value like items would. + // if (!PassLimitClass(base1, GetClass())) + // LimitFound = true; + // break; + // + // + // //Handle Focus Effects + // case SE_ImprovedDamage: + // if (type == focusImprovedDamage && base1 > value) + // value = base1; + // break; + // + // case SE_ImprovedHeal: + // if (type == focusImprovedHeal && base1 > value) + // value = base1; + // break; + // + // case SE_ReduceManaCost: + // if (type == focusManaCost ) + // value = base1; + // break; + // + // case SE_IncreaseSpellHaste: + // if (type == focusSpellHaste && base1 > value) + // value = base1; + // break; + // + // case SE_IncreaseSpellDuration: + // if (type == focusSpellDuration && base1 > value) + // value = base1; + // break; + // + // case SE_SpellDurationIncByTic: + // if (type == focusSpellDurByTic && base1 > value) + // value = base1; + // break; + // + // case SE_SwarmPetDuration: + // if (type == focusSwarmPetDuration && base1 > value) + // value = base1; + // break; + // + // case SE_IncreaseRange: + // if (type == focusRange && base1 > value) + // value = base1; + // break; + // + // case SE_ReduceReagentCost: + // if (type == focusReagentCost && base1 > value) + // value = base1; + // break; + // + // case SE_PetPowerIncrease: + // if (type == focusPetPower && base1 > value) + // value = base1; + // break; + // + // case SE_SpellResistReduction: + // if (type == focusResistRate && base1 > value) + // value = base1; + // break; + // + // case SE_SpellHateMod: + // if (type == focusSpellHateMod) + // { + // if(value != 0) + // { + // if(value > 0) + // { + // if(base1 > value) + // { + // value = base1; + // } + // } + // else + // { + // if(base1 < value) + // { + // value = base1; + // } + // } + // } + // else + // value = base1; + // } + // break; + // + // case SE_ReduceReuseTimer: + // { + // if(type == focusReduceRecastTime) + // value = base1 / 1000; + // + // break; + // } + // + // case SE_TriggerOnCast: + // { + // if(type == focusTriggerOnCast) + // { + // if(zone->random.Int(0, 100) <= base1){ + // value = base2; + // } + // + // else{ + // value = 0; + // LimitFound = true; + // } + // } + // break; + // } + // case SE_FcSpellVulnerability: + // { + // if(type == focusSpellVulnerability) + // { + // value = base1; + // } + // break; + // } + // case SE_BlockNextSpellFocus: + // { + // if(type == focusBlockNextSpell) + // { + // if(zone->random.Int(1, 100) <= base1) + // value = 1; + // } + // break; + // } + // case SE_FcTwincast: + // { + // if(type == focusTwincast) + // { + // value = base1; + // } + // break; + // } + // + // /* + // case SE_SympatheticProc: + // { + // if(type == focusSympatheticProc) + // { + // float ProcChance, ProcBonus; + // int16 ProcRateMod = base1; //Baseline is 100 for most Sympathetic foci + // int32 cast_time = GetActSpellCasttime(spell_id, spells[spell_id].cast_time); + // GetSympatheticProcChances(ProcBonus, ProcChance, cast_time, ProcRateMod); + // + // if(zone->random.Real(0, 1) <= ProcChance) + // value = focus_id; + // + // else + // value = 0; + // } + // break; + // } + // */ + // case SE_FcDamageAmt: + // { + // if(type == focusFcDamageAmt) + // value = base1; + // + // break; + // } + // + // case SE_FcDamageAmtCrit: + // { + // if(type == focusFcDamageAmtCrit) + // value = base1; + // + // break; + // } + // + // case SE_FcDamageAmtIncoming: + // { + // if(type == focusFcDamageAmtIncoming) + // value = base1; + // + // break; + // } + // + // case SE_FcHealAmtIncoming: + // if(type == focusFcHealAmtIncoming) + // value = base1; + // break; + // + // case SE_FcHealPctCritIncoming: + // if (type == focusFcHealPctCritIncoming) + // value = base1; + // break; + // + // case SE_FcHealAmtCrit: + // if(type == focusFcHealAmtCrit) + // value = base1; + // break; + // + // case SE_FcHealAmt: + // if(type == focusFcHealAmt) + // value = base1; + // break; + // + // case SE_FcHealPctIncoming: + // if(type == focusFcHealPctIncoming) + // value = base1; + // break; + // + // case SE_FcBaseEffects: + // { + // if (type == focusFcBaseEffects) + // value = base1; + // + // break; + // } + // case SE_FcDamagePctCrit: + // { + // if(type == focusFcDamagePctCrit) + // value = base1; + // + // break; + // } + // + // case SE_FcIncreaseNumHits: + // { + // if(type == focusIncreaseNumHits) + // value = base1; + // + // break; + // } - for (std::map::const_iterator iter = aa_effects[aa_ID].begin(); iter != aa_effects[aa_ID].end(); ++iter) - { - effect = iter->second.skill_id; - base1 = iter->second.base1; - base2 = iter->second.base2; - slot = iter->second.slot; - - //AA Foci's can contain multiple focus effects within the same AA. - //To handle this we will not automatically return zero if a limit is found. - //Instead if limit is found and multiple effects, we will reset the limit check - //when the next valid focus effect is found. - if (IsFocusEffect(0, 0, true,effect) || (effect == SE_TriggerOnCast)){ - FocusCount++; - //If limit found on prior check next, else end loop. - if (FocusCount > 1){ - if (LimitFound){ - value = 0; - LimitFound = false; - } - - else{ - break; - } - } - } - - - switch (effect) - { - case SE_Blank: - break; - - //Handle Focus Limits - case SE_LimitResist: - if(base1) - { - if(spell.resisttype != base1) - LimitFound = true; - } - break; - case SE_LimitInstant: - if(spell.buffduration) - LimitFound = true; - break; - case SE_LimitMaxLevel: - spell_level = spell.classes[(GetClass()%16) - 1]; - lvldiff = spell_level - base1; - //every level over cap reduces the effect by base2 percent unless from a clicky when ItemCastsUseFocus is true - if(lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || RuleB(Character, ItemCastsUseFocus) == false)) - { - if(base2 > 0) - { - lvlModifier -= base2*lvldiff; - if(lvlModifier < 1) - LimitFound = true; - } - else { - LimitFound = true; - } - } - break; - case SE_LimitMinLevel: - if((spell.classes[(GetClass()%16) - 1]) < base1) - LimitFound = true; - break; - case SE_LimitCastTimeMin: - if (spell.cast_time < base1) - LimitFound = true; - break; - case SE_LimitSpell: - // Exclude spell(any but this) - if(base1 < 0) { - if (spell_id == (base1*-1)) - LimitFound = true; - } - else { - // Include Spell(only this) - if (spell_id != base1) - LimitFound = true; - } - break; - case SE_LimitMinDur: - if (base1 > CalcBuffDuration_formula(GetLevel(), spell.buffdurationformula, spell.buffduration)) - LimitFound = true; - break; - case SE_LimitEffect: - // Exclude effect(any but this) - if(base1 < 0) { - if(IsEffectInSpell(spell_id,(base1*-1))) - LimitFound = true; - } - else { - // Include effect(only this) - if(!IsEffectInSpell(spell_id,base1)) - LimitFound = true; - } - break; - case SE_LimitSpellType: - switch(base1) - { - case 0: - if (!IsDetrimentalSpell(spell_id)) - LimitFound = true; - break; - case 1: - if (!IsBeneficialSpell(spell_id)) - LimitFound = true; - break; - } - break; - - case SE_LimitManaMin: - if(spell.mana < base1) - LimitFound = true; - break; - - case SE_LimitTarget: - // Exclude - if(base1 < 0){ - if(-base1 == spell.targettype) - LimitFound = true; - } - // Include - else { - if(base1 != spell.targettype) - LimitFound = true; - } - break; - - case SE_LimitCombatSkills: - // 1 is for disciplines only - if(base1 == 1 && !IsDiscipline(spell_id)) - LimitFound = true; - // 0 is spells only - else if(base1 == 0 && IsDiscipline(spell_id)) - LimitFound = true; - break; - - case SE_LimitSpellGroup: - if(base1 > 0 && base1 != spell.spellgroup) - LimitFound = true; - else if(base1 < 0 && base1 == spell.spellgroup) - LimitFound = true; - break; - - - case SE_LimitCastingSkill: - LimitSpellSkill = true; - if(base1 == spell.skill) - SpellSkill_Found = true; - break; - - case SE_LimitClass: - //Do not use this limit more then once per spell. If multiple class, treat value like items would. - if (!PassLimitClass(base1, GetClass())) - LimitFound = true; - break; - - - //Handle Focus Effects - case SE_ImprovedDamage: - if (type == focusImprovedDamage && base1 > value) - value = base1; - break; - - case SE_ImprovedHeal: - if (type == focusImprovedHeal && base1 > value) - value = base1; - break; - - case SE_ReduceManaCost: - if (type == focusManaCost ) - value = base1; - break; - - case SE_IncreaseSpellHaste: - if (type == focusSpellHaste && base1 > value) - value = base1; - break; - - case SE_IncreaseSpellDuration: - if (type == focusSpellDuration && base1 > value) - value = base1; - break; - - case SE_SpellDurationIncByTic: - if (type == focusSpellDurByTic && base1 > value) - value = base1; - break; - - case SE_SwarmPetDuration: - if (type == focusSwarmPetDuration && base1 > value) - value = base1; - break; - - case SE_IncreaseRange: - if (type == focusRange && base1 > value) - value = base1; - break; - - case SE_ReduceReagentCost: - if (type == focusReagentCost && base1 > value) - value = base1; - break; - - case SE_PetPowerIncrease: - if (type == focusPetPower && base1 > value) - value = base1; - break; - - case SE_SpellResistReduction: - if (type == focusResistRate && base1 > value) - value = base1; - break; - - case SE_SpellHateMod: - if (type == focusSpellHateMod) - { - if(value != 0) - { - if(value > 0) - { - if(base1 > value) - { - value = base1; - } - } - else - { - if(base1 < value) - { - value = base1; - } - } - } - else - value = base1; - } - break; - - case SE_ReduceReuseTimer: - { - if(type == focusReduceRecastTime) - value = base1 / 1000; - - break; - } - - case SE_TriggerOnCast: - { - if(type == focusTriggerOnCast) - { - if(zone->random.Int(0, 100) <= base1){ - value = base2; - } - - else{ - value = 0; - LimitFound = true; - } - } - break; - } - case SE_FcSpellVulnerability: - { - if(type == focusSpellVulnerability) - { - value = base1; - } - break; - } - case SE_BlockNextSpellFocus: - { - if(type == focusBlockNextSpell) - { - if(zone->random.Int(1, 100) <= base1) - value = 1; - } - break; - } - case SE_FcTwincast: - { - if(type == focusTwincast) - { - value = base1; - } - break; - } - - /* - case SE_SympatheticProc: - { - if(type == focusSympatheticProc) - { - float ProcChance, ProcBonus; - int16 ProcRateMod = base1; //Baseline is 100 for most Sympathetic foci - int32 cast_time = GetActSpellCasttime(spell_id, spells[spell_id].cast_time); - GetSympatheticProcChances(ProcBonus, ProcChance, cast_time, ProcRateMod); - - if(zone->random.Real(0, 1) <= ProcChance) - value = focus_id; - - else - value = 0; - } - break; - } - */ - case SE_FcDamageAmt: - { - if(type == focusFcDamageAmt) - value = base1; - - break; - } - - case SE_FcDamageAmtCrit: - { - if(type == focusFcDamageAmtCrit) - value = base1; - - break; - } - - case SE_FcDamageAmtIncoming: - { - if(type == focusFcDamageAmtIncoming) - value = base1; - - break; - } - - case SE_FcHealAmtIncoming: - if(type == focusFcHealAmtIncoming) - value = base1; - break; - - case SE_FcHealPctCritIncoming: - if (type == focusFcHealPctCritIncoming) - value = base1; - break; - - case SE_FcHealAmtCrit: - if(type == focusFcHealAmtCrit) - value = base1; - break; - - case SE_FcHealAmt: - if(type == focusFcHealAmt) - value = base1; - break; - - case SE_FcHealPctIncoming: - if(type == focusFcHealPctIncoming) - value = base1; - break; - - case SE_FcBaseEffects: - { - if (type == focusFcBaseEffects) - value = base1; - - break; - } - case SE_FcDamagePctCrit: - { - if(type == focusFcDamagePctCrit) - value = base1; - - break; - } - - case SE_FcIncreaseNumHits: - { - if(type == focusIncreaseNumHits) - value = base1; - - break; - } - - //Check for spell skill limits. - if ((LimitSpellSkill) && (!SpellSkill_Found)) - return 0; - - } - } + ////Check for spell skill limits. + //if ((LimitSpellSkill) && (!SpellSkill_Found)) + // return 0; + // + // } + //} if (LimitFound){ return 0; @@ -6885,30 +6876,30 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) { // AA Focus if (aabonuses.FocusEffects[bottype]){ - - int totalAAs = database.CountAAs(); - int32 Total3 = 0; - uint32 slots = 0; - uint32 aa_AA = 0; - uint32 aa_value = 0; - - for (int i = 0; i < totalAAs; i++) { //iterate through all of the client's AAs - std::map::iterator aa = botAAs.find(i); - if(aa != botAAs.end()) { // make sure aa exists or we'll crash zone - aa_AA = aa->second.aa_id; //same as aaid from the aa_effects table - aa_value = aa->second.total_levels; //how many points in it - if (aa_AA < 1 || aa_value < 1) - continue; - - Total3 = CalcBotAAFocus(bottype, aa_AA, spell_id); - if (Total3 > 0 && realTotal3 >= 0 && Total3 > realTotal3) { - realTotal3 = Total3; - } - else if (Total3 < 0 && Total3 < realTotal3) { - realTotal3 = Total3; - } - } - } + //old aa + //int totalAAs = database.CountAAs(); + //int32 Total3 = 0; + //uint32 slots = 0; + //uint32 aa_AA = 0; + //uint32 aa_value = 0; + // + //for (int i = 0; i < totalAAs; i++) { //iterate through all of the client's AAs + // std::map::iterator aa = botAAs.find(i); + // if(aa != botAAs.end()) { // make sure aa exists or we'll crash zone + // aa_AA = aa->second.aa_id; //same as aaid from the aa_effects table + // aa_value = aa->second.total_levels; //how many points in it + // if (aa_AA < 1 || aa_value < 1) + // continue; + // + // Total3 = CalcBotAAFocus(bottype, aa_AA, spell_id); + // if (Total3 > 0 && realTotal3 >= 0 && Total3 > realTotal3) { + // realTotal3 = Total3; + // } + // else if (Total3 < 0 && Total3 < realTotal3) { + // realTotal3 = Total3; + // } + // } + //} } if(bottype == BotfocusReagentCost && IsSummonPetSpell(spell_id) && GetAA(aaElementalPact)) @@ -8940,6 +8931,7 @@ int32 Bot::GetActSpellCost(uint16 spell_id, int32 cost) { break; } + //aa old bonus += 0.05 * GetAA(aaAdvancedSpellCastingMastery); if(SuccessChance <= (SpecializeSkill * 0.3 * bonus)) diff --git a/zone/bot.h b/zone/bot.h index 25e0d1c52..1f1262ffc 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -448,8 +448,6 @@ public: bool IsBotWISCaster() { return (GetClass() == CLERIC || GetClass() == DRUID || GetClass() == SHAMAN); } bool CanHeal(); int GetRawACNoShield(int &shield_ac); - void LoadAAs(); - uint32 GetAA(uint32 aa_id); void ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon); bool GetHasBeenSummoned() { return _hasBeenSummoned; } const glm::vec3 GetPreSummonLocation() const { return m_PreSummonLocation; } diff --git a/zone/client.cpp b/zone/client.cpp index f7510f855..24968f005 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -439,7 +439,7 @@ void Client::SendZoneInPackets() //Send AA Exp packet: if (GetLevel() >= 51) - SendAAStats(); + SendAlternateAdvancementStats(); // Send exp packets outapp = new EQApplicationPacket(OP_ExpUpdate, sizeof(ExpUpdate_Struct)); @@ -8040,56 +8040,6 @@ void Client::TryItemTimer(int slot) } } -void Client::RefundAA() { - int cur = 0; - bool refunded = false; - - for(int x = 0; x < aaHighestID; x++) { - cur = GetAA(x); - if(cur > 0){ - SendAA_Struct* curaa = zone->FindAA(x); - if(cur){ - SetAA(x, 0); - for(int j = 0; j < cur; j++) { - m_pp.aapoints += curaa->cost + (curaa->cost_inc * j); - refunded = true; - } - } - else - { - m_pp.aapoints += cur; - SetAA(x, 0); - refunded = true; - } - } - } - - if(refunded) { - SaveAA(); - Save(); - // Kick(); - } -} - -void Client::IncrementAA(int aa_id) { - SendAA_Struct* aa2 = zone->FindAA(aa_id); - - if(aa2 == nullptr) - return; - - if(GetAA(aa_id) == aa2->max_level) - return; - - SetAA(aa_id, GetAA(aa_id) + 1); - - SaveAA(); - - SendAA(aa_id); - SendAATable(); - SendAAStats(); - CalcBonuses(); -} - void Client::SendItemScale(ItemInst *inst) { int slot = m_inv.GetSlotByItemInst(inst); if(slot != -1) { diff --git a/zone/client.h b/zone/client.h index 0b105c3ef..bd2c5371d 100644 --- a/zone/client.h +++ b/zone/client.h @@ -762,9 +762,16 @@ public: //New AA Methods void SendAlternateAdvancementRank(int aa_id, int level); void SendAlternateAdvancementTable(); + void SendAlternateAdvancementStats(); + void PurchaseAlternateAdvancementRank(int rank_id); + void SendAlternateAdvancementPoints(); + + void SetAAPoints(uint32 points) { m_pp.aapoints = points; SendAlternateAdvancementStats(); } + void AddAAPoints(uint32 points) { m_pp.aapoints += points; SendAlternateAdvancementStats(); } + int GetAAPoints() { return m_pp.aapoints; } + int GetSpentAA() { return m_pp.aapoints_spent; } //old AA Methods - void SendAAList(); void ResetAA(); void SendClearAA(); void SendAA(uint32 id, int seq=1); @@ -776,7 +783,6 @@ public: void SetTitleSuffix(const char *txt); inline uint32 GetMaxAAXP(void) const { return max_AAXP; } inline uint32 GetAAXP() const { return m_pp.expAA; } - void SendAAStats(); void SendAATable(); void SendAATimers(); int GetAATimerID(aaID activate); @@ -790,10 +796,6 @@ public: 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); - void SetAAPoints(uint32 points) { m_pp.aapoints = points; SendAAStats(); } - void AddAAPoints(uint32 points) { m_pp.aapoints += points; SendAAStats(); } - int GetAAPoints() { return m_pp.aapoints; } - int GetSpentAA() { return m_pp.aapoints_spent; } void RefundAA(); void IncrementAA(int aa_id); int32 GetAAEffectDataBySlot(uint32 aa_ID, uint32 slot_id, bool GetEffect, bool GetBase1, bool GetBase2); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index f97873db3..e7d3b61a7 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1152,7 +1152,7 @@ void Client::Handle_Connect_OP_TGB(const EQApplicationPacket *app) void Client::Handle_Connect_OP_UpdateAA(const EQApplicationPacket *app) { - SendAATable(); + SendAlternateAdvancementPoints(); } void Client::Handle_Connect_OP_WearChange(const EQApplicationPacket *app) @@ -1439,61 +1439,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if (m_pp.ldon_points_tak < 0 || m_pp.ldon_points_tak > 2000000000){ m_pp.ldon_points_tak = 0; } 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 */ - //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(!database.LoadAlternateAdvancement(this)) { + Log.Out(Logs::General, Logs::Error, "Error loading AA points for %s", GetName()); + } if (SPDAT_RECORDS > 0) { for (uint32 z = 0; zsize != sizeof(AA_Action)){ - printf("Error! OP_AAAction size didnt match!\n"); + Log.Out(Logs::General, Logs::AA, "Error! OP_AAAction size didnt match!"); return; } AA_Action* action = (AA_Action*)app->pBuffer; if (action->action == aaActionActivate) {//AA Hotkey Log.Out(Logs::Detail, Logs::AA, "Activating AA %d", action->ability); - ActivateAA((aaID)action->ability); + //ActivateAlternateAdvancementAbility(action->ability); } else if (action->action == aaActionBuy) { - BuyAA(action); + PurchaseAlternateAdvancementRank(action->ability); } else if (action->action == aaActionDisableEXP){ //Turn Off AA Exp if (m_epp.perAA > 0) Message_StringID(0, AA_OFF); + m_epp.perAA = 0; - SendAAStats(); + SendAlternateAdvancementStats(); } else if (action->action == aaActionSetEXP) { if (m_epp.perAA == 0) Message_StringID(0, AA_ON); m_epp.perAA = action->exp_value; - if (m_epp.perAA<0 || m_epp.perAA>100) m_epp.perAA = 0; // stop exploit with sanity check + if (m_epp.perAA < 0 || m_epp.perAA > 100) + m_epp.perAA = 0; // stop exploit with sanity check + // send an update - SendAAStats(); - SendAATable(); + SendAlternateAdvancementStats(); + SendAlternateAdvancementTable(); } else { - printf("Unknown AA action: %u %u 0x%x %d\n", action->action, action->ability, action->unknown08, action->exp_value); + Log.Out(Logs::General, Logs::AA, "Unknown AA action : %u %u 0x%x %d", action->action, action->ability, action->unknown08, action->exp_value); } - - return; } void Client::Handle_OP_AcceptNewTask(const EQApplicationPacket *app) diff --git a/zone/command.cpp b/zone/command.cpp index f2a84baaa..298022dc9 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -5600,8 +5600,8 @@ void command_setaapts(Client *c, const Seperator *sep) t->SetLeadershipEXP(t->GetGroupEXP(), atoi(sep->arg[2])*RAID_EXP_PER_POINT); } else { t->SetEXP(t->GetEXP(),t->GetMaxAAXP()*atoi(sep->arg[2]),false); - t->SendAAStats(); - t->SendAATable(); + t->SendAlternateAdvancementStats(); + t->SendAlternateAdvancementTable(); } } @@ -7684,54 +7684,55 @@ void command_reloadtitles(Client *c, const Seperator *sep) } +//old aa, probably to be removed void command_altactivate(Client *c, const Seperator *sep){ - if(sep->arg[1][0] == '\0'){ - c->Message(10, "Invalid argument, usage:"); - c->Message(10, "#altactivate list - lists the AA ID numbers that are available to you"); - c->Message(10, "#altactivate time [argument] - returns the time left until you can use the AA with the ID that matches the argument."); - c->Message(10, "#altactivate [argument] - activates the AA with the ID that matches the argument."); - return; - } - if(!strcasecmp(sep->arg[1], "help")){ - c->Message(10, "Usage:"); - c->Message(10, "#altactivate list - lists the AA ID numbers that are available to you"); - c->Message(10, "#altactivate time [argument] - returns the time left until you can use the AA with the ID that matches the argument."); - c->Message(10, "#altactivate [argument] - activates the AA with the ID that matches the argument."); - return; - } - if(!strcasecmp(sep->arg[1], "list")){ - c->Message(10, "You have access to the following AA Abilities:"); - int x, val; - SendAA_Struct* saa = nullptr; - for(x = 0; x < aaHighestID; x++){ - if(AA_Actions[x][0].spell_id || AA_Actions[x][0].action){ //if there's an action or spell associated we assume it's a valid - val = 0; //and assume if they don't have a value for the first rank then it isn't valid for any rank - saa = nullptr; - val = c->GetAA(x); - if(val){ - saa = zone->FindAA(x); - c->Message(10, "%d: %s %d", x, saa->name, val); - } - } - } - } - else if(!strcasecmp(sep->arg[1], "time")){ - int ability = atoi(sep->arg[2]); - if(c->GetAA(ability)){ - int remain = c->GetPTimers().GetRemainingTime(pTimerAAStart + ability); - if(remain) - c->Message(10, "You may use that ability in %d minutes and %d seconds.", (remain/60), (remain%60)); - else - c->Message(10, "You may use that ability now."); - } - else{ - c->Message(10, "You do not have access to that ability."); - } - } - else - { - c->ActivateAA((aaID) atoi(sep->arg[1])); - } +// if(sep->arg[1][0] == '\0'){ +// c->Message(10, "Invalid argument, usage:"); +// c->Message(10, "#altactivate list - lists the AA ID numbers that are available to you"); +// c->Message(10, "#altactivate time [argument] - returns the time left until you can use the AA with the ID that matches the argument."); +// c->Message(10, "#altactivate [argument] - activates the AA with the ID that matches the argument."); +// return; +// } +// if(!strcasecmp(sep->arg[1], "help")){ +// c->Message(10, "Usage:"); +// c->Message(10, "#altactivate list - lists the AA ID numbers that are available to you"); +// c->Message(10, "#altactivate time [argument] - returns the time left until you can use the AA with the ID that matches the argument."); +// c->Message(10, "#altactivate [argument] - activates the AA with the ID that matches the argument."); +// return; +// } +// if(!strcasecmp(sep->arg[1], "list")){ +// c->Message(10, "You have access to the following AA Abilities:"); +// int x, val; +// SendAA_Struct* saa = nullptr; +// for(x = 0; x < aaHighestID; x++){ +// if(AA_Actions[x][0].spell_id || AA_Actions[x][0].action){ //if there's an action or spell associated we assume it's a valid +// val = 0; //and assume if they don't have a value for the first rank then it isn't valid for any rank +// saa = nullptr; +// val = c->GetAA(x); +// if(val){ +// saa = zone->FindAA(x); +// c->Message(10, "%d: %s %d", x, saa->name, val); +// } +// } +// } +// } +// else if(!strcasecmp(sep->arg[1], "time")){ +// int ability = atoi(sep->arg[2]); +// if(c->GetAA(ability)){ +// int remain = c->GetPTimers().GetRemainingTime(pTimerAAStart + ability); +// if(remain) +// c->Message(10, "You may use that ability in %d minutes and %d seconds.", (remain/60), (remain%60)); +// else +// c->Message(10, "You may use that ability now."); +// } +// else{ +// c->Message(10, "You do not have access to that ability."); +// } +// } +// else +// { +// c->ActivateAA((aaID) atoi(sep->arg[1])); +// } } void command_traindisc(Client *c, const Seperator *sep) diff --git a/zone/exp.cpp b/zone/exp.cpp index 826b12e67..0172263e7 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -515,7 +515,7 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { if (GetLevel() < 51) { m_epp.perAA = 0; // turn off aa exp if they drop below 51 } else - SendAAStats(); //otherwise, send them an AA update + SendAlternateAdvancementStats(); //otherwise, send them an AA update //send the expdata in any case so the xp bar isnt stuck after leveling uint32 tmpxp1 = GetEXPForLevel(GetLevel()+1); diff --git a/zone/mob.h b/zone/mob.h index b074782b3..bbc841f48 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -958,7 +958,8 @@ public: //aa new uint32 GetAA(uint32 rank_id) const; - bool SetAA(uint32 rank_id, uint32 new_value); + bool SetAA(uint32 rank_id, uint32 new_value, uint32 charges = 0); + void ClearAAs() { aa_ranks.clear(); } bool CanUseAlternateAdvancementRank(AA::Rank *rank); bool CanPurchaseAlternateAdvancementRank(AA::Rank *ran); @@ -1316,7 +1317,7 @@ protected: bool bEnraged; bool destructibleobject; - std::unordered_map aa_ranks; + std::unordered_map> aa_ranks; private: void _StopSong(); //this is not what you think it is diff --git a/zone/net.cpp b/zone/net.cpp index 0178eff21..1bca0571b 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -248,9 +248,6 @@ int main(int argc, char** argv) { Log.Out(Logs::General, Logs::Zone_Server, "Loading titles"); title_manager.LoadTitles(); - Log.Out(Logs::General, Logs::Zone_Server, "Loading AA effects"); - database.LoadAAEffects(); - Log.Out(Logs::General, Logs::Zone_Server, "Loading tributes"); database.LoadTributes(); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index eed8305f4..d564a341e 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -4077,33 +4077,34 @@ XS(XS_Client_RefundAA) { if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - int curpt = 0; - bool refunded = false; - - for(int x1=0;x1GetAA(x1); - if(curpt > 0){ - SendAA_Struct* curaa = zone->FindAA(x1); - if(curaa){ - THIS->SetAA(x1, 0); - for(int x2=0;x2GetPP().aapoints += curaa->cost + (curaa->cost_inc * x2); - refunded = true; - } - } - else //aa doesn't exist.. but if they bought it then it had at least a cost of 1 point each - { //so give back what we can - THIS->GetPP().aapoints += curpt; - THIS->SetAA(x1, 0); - refunded = true; - } - } - } - - if(refunded){ - THIS->Save(); //save of course - THIS->Kick(); //client gets all buggy if we don't immediatly relog so just force it on them - } + //old aa + //int curpt = 0; + //bool refunded = false; + // + //for(int x1=0;x1GetAA(x1); + // if(curpt > 0){ + // SendAA_Struct* curaa = zone->FindAA(x1); + // if(curaa){ + // THIS->SetAA(x1, 0); + // for(int x2=0;x2GetPP().aapoints += curaa->cost + (curaa->cost_inc * x2); + // refunded = true; + // } + // } + // else //aa doesn't exist.. but if they bought it then it had at least a cost of 1 point each + // { //so give back what we can + // THIS->GetPP().aapoints += curpt; + // THIS->SetAA(x1, 0); + // refunded = true; + // } + // } + //} + // + //if(refunded){ + // THIS->Save(); //save of course + // THIS->Kick(); //client gets all buggy if we don't immediatly relog so just force it on them + //} } XSRETURN_EMPTY; } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 7e91550c5..8ac60c125 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -4157,30 +4157,30 @@ int32 Client::GetAAEffectDataBySlot(uint32 aa_ID, uint32 slot_id, bool GetEffect int32 base2 = 0; uint32 slot = 0; - - std::map >::const_iterator find_iter = aa_effects.find(aa_ID); - if(find_iter == aa_effects.end()) - return 0; - - for (std::map::const_iterator iter = aa_effects[aa_ID].begin(); iter != aa_effects[aa_ID].end(); ++iter) - { - effect = iter->second.skill_id; - base1 = iter->second.base1; - base2 = iter->second.base2; - slot = iter->second.slot; - - if (slot && slot == slot_id) { - - if (GetEffect) - return effect; - - if (GetBase1) - return base1; - - if (GetBase2) - return base2; - } - } + //old aa + //std::map >::const_iterator find_iter = aa_effects.find(aa_ID); + //if(find_iter == aa_effects.end()) + // return 0; + // + //for (std::map::const_iterator iter = aa_effects[aa_ID].begin(); iter != aa_effects[aa_ID].end(); ++iter) + //{ + // effect = iter->second.skill_id; + // base1 = iter->second.base1; + // base2 = iter->second.base2; + // slot = iter->second.slot; + // + // if (slot && slot == slot_id) { + // + // if (GetEffect) + // return effect; + // + // if (GetBase1) + // return base1; + // + // if (GetBase2) + // return base2; + // } + //} return 0; } @@ -4214,431 +4214,432 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) */ int FocusCount = 0; - std::map >::const_iterator find_iter = aa_effects.find(aa_ID); - if(find_iter == aa_effects.end()) - { - return 0; - } - - for (std::map::const_iterator iter = aa_effects[aa_ID].begin(); iter != aa_effects[aa_ID].end(); ++iter) - { - effect = iter->second.skill_id; - base1 = iter->second.base1; - base2 = iter->second.base2; - slot = iter->second.slot; - - /* - AA Foci's can contain multiple focus effects within the same AA. - To handle this we will not automatically return zero if a limit is found. - Instead if limit is found and multiple focus effects, we will reset the limit check - when the next valid focus effect is found. - */ - - if (IsFocusEffect(0, 0, true,effect) || (effect == SE_TriggerOnCast)){ - FocusCount++; - //If limit found on prior check next, else end loop. - if (FocusCount > 1){ - - for(int e = 0; e < MaxLimitInclude; e+=2) { - if (LimitInclude[e] && !LimitInclude[e+1]) - LimitFailure = true; - } - - if (LimitFailure){ - value = 0; - LimitFailure = false; - - for(int e = 0; e < MaxLimitInclude; e++) { - LimitInclude[e] = false; //Reset array - } - } - - else{ - break; - } - } - } - - - switch (effect) - { - case SE_Blank: - break; - - //Handle Focus Limits - - case SE_LimitResist: - if(base1 < 0){ - if(spell.resisttype == -base1) //Exclude - LimitFailure = true; - } - else { - LimitInclude[0] = true; - if (spell.resisttype == base1) //Include - LimitInclude[1] = true; - } - break; - - case SE_LimitInstant: - if(base1 == 1 && spell.buffduration) //Fail if not instant - LimitFailure = true; - if(base1 == 0 && (spell.buffduration == 0)) //Fail if instant - LimitFailure = true; - - break; - - case SE_LimitMaxLevel: - spell_level = spell.classes[(GetClass()%16) - 1]; - lvldiff = spell_level - base1; - //every level over cap reduces the effect by base2 percent unless from a clicky when ItemCastsUseFocus is true - if(lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || RuleB(Character, ItemCastsUseFocus) == false)) { - if(base2 > 0){ - lvlModifier -= base2*lvldiff; - if(lvlModifier < 1) - LimitFailure = true; - } - else - LimitFailure = true; - } - break; - - case SE_LimitMinLevel: - if((spell.classes[(GetClass()%16) - 1]) < base1) - LimitFailure = true; - break; - - case SE_LimitCastTimeMin: - if (static_cast(spell.cast_time) < base1) - LimitFailure = true; - break; - - case SE_LimitCastTimeMax: - if (static_cast(spell.cast_time) > base1) - LimitFailure = true; - break; - - case SE_LimitSpell: - if(base1 < 0) { //Exclude - if (spell_id == -base1) - LimitFailure = true; - } - else { - LimitInclude[2] = true; - if (spell_id == base1) //Include - LimitInclude[3] = true; - } - break; - - case SE_LimitMinDur: - if (base1 > CalcBuffDuration_formula(GetLevel(), spell.buffdurationformula, spell.buffduration)) - LimitFailure = true; - - break; - - case SE_LimitEffect: - if(base1 < 0){ - if(IsEffectInSpell(spell_id,-base1)) //Exclude - LimitFailure = true; - } - else{ - LimitInclude[4] = true; - if(IsEffectInSpell(spell_id,base1)) //Include - LimitInclude[5] = true; - } - break; - - case SE_LimitSpellType: - switch(base1) - { - case 0: - if (!IsDetrimentalSpell(spell_id)) - LimitFailure = true; - break; - case 1: - if (!IsBeneficialSpell(spell_id)) - LimitFailure = true; - break; - } - break; - - case SE_LimitManaMin: - if(spell.mana < base1) - LimitFailure = true; - break; - - case SE_LimitTarget: - if (base1 < 0) { - if (-base1 == spell.targettype) //Exclude - LimitFailure = true; - } - else { - LimitInclude[6] = true; - if (base1 == spell.targettype) //Include - LimitInclude[7] = true; - } - break; - - case SE_LimitCombatSkills: - if (base1 == 0 && (IsCombatSkill(spell_id) || IsCombatProc(spell_id))) //Exclude Discs / Procs - LimitFailure = true; - else if (base1 == 1 && (!IsCombatSkill(spell_id) || !IsCombatProc(spell_id))) //Exclude Spells - LimitFailure = true; - - break; - - case SE_LimitSpellGroup: - if(base1 < 0) { - if (-base1 == spell.spellgroup) //Exclude - LimitFailure = true; - } - else { - LimitInclude[8] = true; - if (base1 == spell.spellgroup) //Include - LimitInclude[9] = true; - } - break; - - case SE_LimitCastingSkill: - if(base1 < 0) { - if(-base1 == spell.skill) - LimitFailure = true; - } - else { - LimitInclude[10] = true; - if(base1 == spell.skill) - LimitInclude[11] = true; - } - break; - - case SE_LimitSpellClass: - if(base1 < 0) { //Exclude - if (CheckSpellCategory(spell_id, base1, SE_LimitSpellClass)) - return(0); - } - else { - LimitInclude[12] = true; - if (CheckSpellCategory(spell_id, base1, SE_LimitSpellClass)) //Include - LimitInclude[13] = true; - } - break; - - case SE_LimitSpellSubclass: - if(base1 < 0) { //Exclude - if (CheckSpellCategory(spell_id, base1, SE_LimitSpellSubclass)) - return(0); - } - else { - LimitInclude[14] = true; - if (CheckSpellCategory(spell_id, base1, SE_LimitSpellSubclass)) //Include - LimitInclude[15] = true; - } - break; - - case SE_LimitClass: - //Do not use this limit more then once per spell. If multiple class, treat value like items would. - if (!PassLimitClass(base1, GetClass())) - LimitFailure = true; - break; - - case SE_LimitRace: - if (base1 != GetRace()) - LimitFailure = true; - break; - - case SE_LimitUseMin: - if (base1 > spell.numhits) - LimitFailure = true; - break; - - case SE_LimitUseType: - if (base1 != spell.numhitstype) - LimitFailure = true; - break; - - //Handle Focus Effects - case SE_ImprovedDamage: - if (type == focusImprovedDamage && base1 > value) - value = base1; - break; - - case SE_ImprovedHeal: - if (type == focusImprovedHeal && base1 > value) - value = base1; - break; - - case SE_ReduceManaCost: - if (type == focusManaCost) - value = base1; - break; - - case SE_IncreaseSpellHaste: - if (type == focusSpellHaste && base1 > value) - value = base1; - break; - - case SE_IncreaseSpellDuration: - if (type == focusSpellDuration && base1 > value) - value = base1; - break; - - case SE_SpellDurationIncByTic: - if (type == focusSpellDurByTic && base1 > value) - value = base1; - break; - - case SE_SwarmPetDuration: - if (type == focusSwarmPetDuration && base1 > value) - value = base1; - break; - - case SE_IncreaseRange: - if (type == focusRange && base1 > value) - value = base1; - break; - - case SE_ReduceReagentCost: - if (type == focusReagentCost && base1 > value) - value = base1; - break; - - case SE_PetPowerIncrease: - if (type == focusPetPower && base1 > value) - value = base1; - break; - - case SE_SpellResistReduction: - if (type == focusResistRate && base1 > value) - value = base1; - break; - - case SE_SpellHateMod: - if (type == focusSpellHateMod ) { - if(value != 0) { - if(value > 0){ - if(base1 > value) - value = base1; - } - else{ - if(base1 < value) - value = base1; - } - } - else - value = base1; - } - break; - - case SE_ReduceReuseTimer: - if(type == focusReduceRecastTime) - value = base1 / 1000; - break; - - case SE_TriggerOnCast: - if(type == focusTriggerOnCast){ - if(zone->random.Roll(base1)) { - value = base2; - } else { - value = 0; - LimitFailure = true; - } - break; - } - - case SE_FcSpellVulnerability: - if(type == focusSpellVulnerability) - value = base1; - break; - - case SE_BlockNextSpellFocus: - if(type == focusBlockNextSpell){ - if(zone->random.Roll(base1)) - value = 1; - } - break; - - case SE_FcTwincast: - if(type == focusTwincast) - value = base1; - break; - - //Note if using these as AA, make sure this is first focus used. - case SE_SympatheticProc: - if(type == focusSympatheticProc) - value = base2; - break; - - case SE_FcDamageAmt: - if(type == focusFcDamageAmt) - value = base1; - break; - - case SE_FcDamageAmtCrit: - if(type == focusFcDamageAmtCrit) - value = base1; - break; - - case SE_FcDamageAmtIncoming: - if(type == focusFcDamageAmtIncoming) - value = base1; - break; - - case SE_FcHealAmtIncoming: - if(type == focusFcHealAmtIncoming) - value = base1; - break; - - case SE_FcHealPctCritIncoming: - if (type == focusFcHealPctCritIncoming) - value = base1; - break; - - case SE_FcHealAmtCrit: - if(type == focusFcHealAmtCrit) - value = base1; - break; - - case SE_FcHealAmt: - if(type == focusFcHealAmt) - value = base1; - break; - - case SE_FcHealPctIncoming: - if(type == focusFcHealPctIncoming) - value = base1; - break; - - case SE_FcBaseEffects: - if (type == focusFcBaseEffects) - value = base1; - break; - - case SE_FcDamagePctCrit: - if(type == focusFcDamagePctCrit) - value = base1; - break; - - case SE_FcIncreaseNumHits: - if(type == focusIncreaseNumHits) - value = base1; - break; - - case SE_FcLimitUse: - if(type == focusFcLimitUse) - value = base1; - break; - - case SE_FcMute: - if(type == focusFcMute) - value = base1; - break; - - case SE_FcStunTimeMod: - if(type == focusFcStunTimeMod) - value = base1; - break; - - } - } + //old AA + //std::map >::const_iterator find_iter = aa_effects.find(aa_ID); + //if(find_iter == aa_effects.end()) + //{ + // return 0; + //} + // + //for (std::map::const_iterator iter = aa_effects[aa_ID].begin(); iter != aa_effects[aa_ID].end(); ++iter) + //{ + // effect = iter->second.skill_id; + // base1 = iter->second.base1; + // base2 = iter->second.base2; + // slot = iter->second.slot; + // + // /* + // AA Foci's can contain multiple focus effects within the same AA. + // To handle this we will not automatically return zero if a limit is found. + // Instead if limit is found and multiple focus effects, we will reset the limit check + // when the next valid focus effect is found. + // */ + // + // if (IsFocusEffect(0, 0, true,effect) || (effect == SE_TriggerOnCast)){ + // FocusCount++; + // //If limit found on prior check next, else end loop. + // if (FocusCount > 1){ + // + // for(int e = 0; e < MaxLimitInclude; e+=2) { + // if (LimitInclude[e] && !LimitInclude[e+1]) + // LimitFailure = true; + // } + // + // if (LimitFailure){ + // value = 0; + // LimitFailure = false; + // + // for(int e = 0; e < MaxLimitInclude; e++) { + // LimitInclude[e] = false; //Reset array + // } + // } + // + // else{ + // break; + // } + // } + // } + // + // + // switch (effect) + // { + // case SE_Blank: + // break; + // + // //Handle Focus Limits + // + // case SE_LimitResist: + // if(base1 < 0){ + // if(spell.resisttype == -base1) //Exclude + // LimitFailure = true; + // } + // else { + // LimitInclude[0] = true; + // if (spell.resisttype == base1) //Include + // LimitInclude[1] = true; + // } + // break; + // + // case SE_LimitInstant: + // if(base1 == 1 && spell.buffduration) //Fail if not instant + // LimitFailure = true; + // if(base1 == 0 && (spell.buffduration == 0)) //Fail if instant + // LimitFailure = true; + // + // break; + // + // case SE_LimitMaxLevel: + // spell_level = spell.classes[(GetClass()%16) - 1]; + // lvldiff = spell_level - base1; + // //every level over cap reduces the effect by base2 percent unless from a clicky when ItemCastsUseFocus is true + // if(lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || RuleB(Character, ItemCastsUseFocus) == false)) { + // if(base2 > 0){ + // lvlModifier -= base2*lvldiff; + // if(lvlModifier < 1) + // LimitFailure = true; + // } + // else + // LimitFailure = true; + // } + // break; + // + // case SE_LimitMinLevel: + // if((spell.classes[(GetClass()%16) - 1]) < base1) + // LimitFailure = true; + // break; + // + // case SE_LimitCastTimeMin: + // if (static_cast(spell.cast_time) < base1) + // LimitFailure = true; + // break; + // + // case SE_LimitCastTimeMax: + // if (static_cast(spell.cast_time) > base1) + // LimitFailure = true; + // break; + // + // case SE_LimitSpell: + // if(base1 < 0) { //Exclude + // if (spell_id == -base1) + // LimitFailure = true; + // } + // else { + // LimitInclude[2] = true; + // if (spell_id == base1) //Include + // LimitInclude[3] = true; + // } + // break; + // + // case SE_LimitMinDur: + // if (base1 > CalcBuffDuration_formula(GetLevel(), spell.buffdurationformula, spell.buffduration)) + // LimitFailure = true; + // + // break; + // + // case SE_LimitEffect: + // if(base1 < 0){ + // if(IsEffectInSpell(spell_id,-base1)) //Exclude + // LimitFailure = true; + // } + // else{ + // LimitInclude[4] = true; + // if(IsEffectInSpell(spell_id,base1)) //Include + // LimitInclude[5] = true; + // } + // break; + // + // case SE_LimitSpellType: + // switch(base1) + // { + // case 0: + // if (!IsDetrimentalSpell(spell_id)) + // LimitFailure = true; + // break; + // case 1: + // if (!IsBeneficialSpell(spell_id)) + // LimitFailure = true; + // break; + // } + // break; + // + // case SE_LimitManaMin: + // if(spell.mana < base1) + // LimitFailure = true; + // break; + // + // case SE_LimitTarget: + // if (base1 < 0) { + // if (-base1 == spell.targettype) //Exclude + // LimitFailure = true; + // } + // else { + // LimitInclude[6] = true; + // if (base1 == spell.targettype) //Include + // LimitInclude[7] = true; + // } + // break; + // + // case SE_LimitCombatSkills: + // if (base1 == 0 && (IsCombatSkill(spell_id) || IsCombatProc(spell_id))) //Exclude Discs / Procs + // LimitFailure = true; + // else if (base1 == 1 && (!IsCombatSkill(spell_id) || !IsCombatProc(spell_id))) //Exclude Spells + // LimitFailure = true; + // + // break; + // + // case SE_LimitSpellGroup: + // if(base1 < 0) { + // if (-base1 == spell.spellgroup) //Exclude + // LimitFailure = true; + // } + // else { + // LimitInclude[8] = true; + // if (base1 == spell.spellgroup) //Include + // LimitInclude[9] = true; + // } + // break; + // + // case SE_LimitCastingSkill: + // if(base1 < 0) { + // if(-base1 == spell.skill) + // LimitFailure = true; + // } + // else { + // LimitInclude[10] = true; + // if(base1 == spell.skill) + // LimitInclude[11] = true; + // } + // break; + // + // case SE_LimitSpellClass: + // if(base1 < 0) { //Exclude + // if (CheckSpellCategory(spell_id, base1, SE_LimitSpellClass)) + // return(0); + // } + // else { + // LimitInclude[12] = true; + // if (CheckSpellCategory(spell_id, base1, SE_LimitSpellClass)) //Include + // LimitInclude[13] = true; + // } + // break; + // + // case SE_LimitSpellSubclass: + // if(base1 < 0) { //Exclude + // if (CheckSpellCategory(spell_id, base1, SE_LimitSpellSubclass)) + // return(0); + // } + // else { + // LimitInclude[14] = true; + // if (CheckSpellCategory(spell_id, base1, SE_LimitSpellSubclass)) //Include + // LimitInclude[15] = true; + // } + // break; + // + // case SE_LimitClass: + // //Do not use this limit more then once per spell. If multiple class, treat value like items would. + // if (!PassLimitClass(base1, GetClass())) + // LimitFailure = true; + // break; + // + // case SE_LimitRace: + // if (base1 != GetRace()) + // LimitFailure = true; + // break; + // + // case SE_LimitUseMin: + // if (base1 > spell.numhits) + // LimitFailure = true; + // break; + // + // case SE_LimitUseType: + // if (base1 != spell.numhitstype) + // LimitFailure = true; + // break; + // + // //Handle Focus Effects + // case SE_ImprovedDamage: + // if (type == focusImprovedDamage && base1 > value) + // value = base1; + // break; + // + // case SE_ImprovedHeal: + // if (type == focusImprovedHeal && base1 > value) + // value = base1; + // break; + // + // case SE_ReduceManaCost: + // if (type == focusManaCost) + // value = base1; + // break; + // + // case SE_IncreaseSpellHaste: + // if (type == focusSpellHaste && base1 > value) + // value = base1; + // break; + // + // case SE_IncreaseSpellDuration: + // if (type == focusSpellDuration && base1 > value) + // value = base1; + // break; + // + // case SE_SpellDurationIncByTic: + // if (type == focusSpellDurByTic && base1 > value) + // value = base1; + // break; + // + // case SE_SwarmPetDuration: + // if (type == focusSwarmPetDuration && base1 > value) + // value = base1; + // break; + // + // case SE_IncreaseRange: + // if (type == focusRange && base1 > value) + // value = base1; + // break; + // + // case SE_ReduceReagentCost: + // if (type == focusReagentCost && base1 > value) + // value = base1; + // break; + // + // case SE_PetPowerIncrease: + // if (type == focusPetPower && base1 > value) + // value = base1; + // break; + // + // case SE_SpellResistReduction: + // if (type == focusResistRate && base1 > value) + // value = base1; + // break; + // + // case SE_SpellHateMod: + // if (type == focusSpellHateMod ) { + // if(value != 0) { + // if(value > 0){ + // if(base1 > value) + // value = base1; + // } + // else{ + // if(base1 < value) + // value = base1; + // } + // } + // else + // value = base1; + // } + // break; + // + // case SE_ReduceReuseTimer: + // if(type == focusReduceRecastTime) + // value = base1 / 1000; + // break; + // + // case SE_TriggerOnCast: + // if(type == focusTriggerOnCast){ + // if(zone->random.Roll(base1)) { + // value = base2; + // } else { + // value = 0; + // LimitFailure = true; + // } + // break; + // } + // + // case SE_FcSpellVulnerability: + // if(type == focusSpellVulnerability) + // value = base1; + // break; + // + // case SE_BlockNextSpellFocus: + // if(type == focusBlockNextSpell){ + // if(zone->random.Roll(base1)) + // value = 1; + // } + // break; + // + // case SE_FcTwincast: + // if(type == focusTwincast) + // value = base1; + // break; + // + // //Note if using these as AA, make sure this is first focus used. + // case SE_SympatheticProc: + // if(type == focusSympatheticProc) + // value = base2; + // break; + // + // case SE_FcDamageAmt: + // if(type == focusFcDamageAmt) + // value = base1; + // break; + // + // case SE_FcDamageAmtCrit: + // if(type == focusFcDamageAmtCrit) + // value = base1; + // break; + // + // case SE_FcDamageAmtIncoming: + // if(type == focusFcDamageAmtIncoming) + // value = base1; + // break; + // + // case SE_FcHealAmtIncoming: + // if(type == focusFcHealAmtIncoming) + // value = base1; + // break; + // + // case SE_FcHealPctCritIncoming: + // if (type == focusFcHealPctCritIncoming) + // value = base1; + // break; + // + // case SE_FcHealAmtCrit: + // if(type == focusFcHealAmtCrit) + // value = base1; + // break; + // + // case SE_FcHealAmt: + // if(type == focusFcHealAmt) + // value = base1; + // break; + // + // case SE_FcHealPctIncoming: + // if(type == focusFcHealPctIncoming) + // value = base1; + // break; + // + // case SE_FcBaseEffects: + // if (type == focusFcBaseEffects) + // value = base1; + // break; + // + // case SE_FcDamagePctCrit: + // if(type == focusFcDamagePctCrit) + // value = base1; + // break; + // + // case SE_FcIncreaseNumHits: + // if(type == focusIncreaseNumHits) + // value = base1; + // break; + // + // case SE_FcLimitUse: + // if(type == focusFcLimitUse) + // value = base1; + // break; + // + // case SE_FcMute: + // if(type == focusFcMute) + // value = base1; + // break; + // + // case SE_FcStunTimeMod: + // if(type == focusFcStunTimeMod) + // value = base1; + // break; + // + // } + //} for(int e = 0; e < MaxLimitInclude; e+=2) { if (LimitInclude[e] && !LimitInclude[e+1]) diff --git a/zone/zone.cpp b/zone/zone.cpp index 31bc27b41..e5e30f01a 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -804,8 +804,6 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name) weather_intensity = 0; blocked_spells = nullptr; totalBS = 0; - aas = nullptr; - totalAAs = 0; zone_has_current_time = false; Instance_Shutdown_Timer = nullptr; @@ -864,16 +862,6 @@ Zone::~Zone() { safe_delete(qGlobals); safe_delete_array(adv_data); safe_delete_array(map_name); - - if(aas != nullptr) { - int r; - for(r = 0; r < totalAAs; r++) { - uchar *data = (uchar *) aas[r]; - safe_delete_array(data); - } - safe_delete_array(aas); - } - safe_delete(GuildBanks); } @@ -952,9 +940,6 @@ bool Zone::Init(bool iStaticZone) { zone->LoadAlternateCurrencies(); zone->LoadNPCEmotes(&NPCEmoteList); - //Load AA information - LoadAAs(); - LoadAlternateAdvancement(); //Load merchant data diff --git a/zone/zone.h b/zone/zone.h index 536ff048c..a4a49b8b2 100644 --- a/zone/zone.h +++ b/zone/zone.h @@ -120,14 +120,7 @@ public: AA::Ability *GetAlternateAdvancementAbilityByRank(int rank_id); AA::Rank *GetAlternateAdvancementRank(int rank_id); - //old AA - void LoadAAs(); - int GetTotalAAs() { return totalAAs; } - SendAA_Struct* GetAABySequence(uint32 seq) { return aas[seq]; } - SendAA_Struct* FindAA(uint32 id); - uint8 GetTotalAALevels(uint32 skill_id); - - void LoadZoneDoors(const char* zone, int16 version); + void LoadZoneDoors(const char* zone, int16 version); bool LoadZoneObjects(); bool LoadGroundSpawns(); void ReloadStaticData(); @@ -202,6 +195,10 @@ public: char *adv_data; bool did_adventure_actions; + //new AA + std::unordered_map> aa_abilities; + std::unordered_map> aa_ranks; + void DoAdventureCountIncrease(); void DoAdventureAssassinationCountIncrease(); void DoAdventureActions(); @@ -322,17 +319,6 @@ private: int totalBS; ZoneSpellsBlocked *blocked_spells; -public: - //new AA - std::unordered_map> aa_abilities; - std::unordered_map> aa_ranks; - -private: - - //old AA - int totalAAs; - SendAA_Struct **aas; //array of AA structs - /* Spawn related things */ diff --git a/zone/zonedb.h b/zone/zonedb.h index ddd9450d2..35275b654 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -343,18 +343,7 @@ public: /* AAs New */ bool LoadAlternateAdvancementAbilities(std::unordered_map> &abilities, std::unordered_map> &ranks); - - /* AAs Old */ - bool LoadAAEffects(); - bool LoadAAEffects2(); - bool LoadSwarmSpells(); - SendAA_Struct*GetAASkillVars(uint32 skill_id); - uint8 GetTotalAALevels(uint32 skill_id); - uint32 GetSizeAA(); - uint32 CountAAs(); - void LoadAAs(SendAA_Struct **load); - uint32 CountAAEffects(); - void FillAAEffects(SendAA_Struct* aa_struct); + bool LoadAlternateAdvancement(Client *c); /* Zone related */ bool GetZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct *data, bool &can_bind, bool &can_combat, bool &can_levitate, bool &can_castoutdoor, bool &is_city, bool &is_hotzone, bool &allow_mercs, uint8 &zone_type, int &ruleset, char **map_filename);