diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index f4f01e300..0596ee95b 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -2810,7 +2810,7 @@ namespace RoF eq->aa_spent = emu->aa_spent; // These fields may need to be correctly populated at some point - eq->aapoints_assigned = emu->aa_spent + 1; + eq->aapoints_assigned = 0; eq->aa_spent_general = 0; eq->aa_spent_archetype = 0; eq->aa_spent_class = 0; @@ -2846,58 +2846,81 @@ namespace RoF ENCODE(OP_SendAATable) { - 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)); + EQApplicationPacket *inapp = *p; + *p = nullptr; + AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer; - // Check clientver field to verify this AA should be sent for SoF - // clientver 1 is for all clients and 5 is for Live - if (emu->clientver <= 7) - { - 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) ? -1 : (emu->sof_next_skill); - eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? -1 : (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); - eq->prereq_skill_count = 1; // min 1 - OUT(prereq_skill); - eq->prereq_minpoints_count = 1; // min 1 - OUT(prereq_minpoints); - eq->type = emu->sof_type; - OUT(spellid); - eq->unknown057 = 1; // Introduced during HoT - 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); - } + // the structs::SendAA_Struct includes enough space for 1 prereq which is the min even if it has no prereqs + auto prereq_size = emu->total_prereqs > 1 ? (emu->total_prereqs - 1) * 8 : 0; + auto outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability) + prereq_size); + inapp->SetReadPosition(sizeof(AARankInfo_Struct)+emu->total_effects * sizeof(AARankEffect_Struct)); + + + std::vector skill; + std::vector points; + for(auto i = 0; i < emu->total_prereqs; ++i) { + skill.push_back(inapp->ReadUInt32()); + points.push_back(inapp->ReadUInt32()); } - FINISH_ENCODE(); + outapp->WriteUInt32(emu->id); + outapp->WriteUInt8(1); + outapp->WriteSInt32(emu->upper_hotkey_sid); + outapp->WriteSInt32(emu->lower_hotkey_sid); + outapp->WriteSInt32(emu->title_sid); + outapp->WriteSInt32(emu->desc_sid); + outapp->WriteSInt32(emu->level_req); + outapp->WriteSInt32(emu->cost); + outapp->WriteUInt32(emu->seq); + outapp->WriteUInt32(emu->current_level); + + if(emu->total_prereqs) { + outapp->WriteUInt32(emu->total_prereqs); + for(auto &e : skill) + outapp->WriteSInt32(e); + outapp->WriteUInt32(emu->total_prereqs); + for(auto &e : points) + outapp->WriteSInt32(e); + } + else { + outapp->WriteUInt32(1); + outapp->WriteUInt32(0); + outapp->WriteUInt32(1); + outapp->WriteUInt32(0); + } + + outapp->WriteSInt32(emu->type); + outapp->WriteSInt32(emu->spell); + outapp->WriteSInt32(1); + outapp->WriteSInt32(emu->spell_type); + outapp->WriteSInt32(emu->spell_refresh); + outapp->WriteSInt32(emu->classes); + outapp->WriteSInt32(emu->max_level); + outapp->WriteSInt32(emu->prev_id); + outapp->WriteSInt32(emu->next_id); + outapp->WriteSInt32(emu->total_cost); + outapp->WriteUInt8(0); + outapp->WriteUInt8(emu->grant_only); + outapp->WriteUInt8(0); + outapp->WriteUInt32(emu->charges); + outapp->WriteSInt32(emu->expansion); + outapp->WriteSInt32(emu->category); + outapp->WriteUInt8(0); // shroud + outapp->WriteUInt8(0); // unknown109 + outapp->WriteUInt8(0); // loh + outapp->WriteUInt8(0); // unknown111 + outapp->WriteUInt32(emu->total_effects); + + inapp->SetReadPosition(sizeof(AARankInfo_Struct)); + for(auto i = 0; i < emu->total_effects; ++i) { + outapp->WriteUInt32(inapp->ReadUInt32()); // skill_id + outapp->WriteUInt32(inapp->ReadUInt32()); // base1 + outapp->WriteUInt32(inapp->ReadUInt32()); // base2 + outapp->WriteUInt32(inapp->ReadUInt32()); // slot + } + + dest->FastQueuePacket(&outapp); + delete inapp; } ENCODE(OP_SendCharInfo) diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 3d96ae182..ba2099710 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -2900,7 +2900,7 @@ namespace RoF2 eq->aa_spent = emu->aa_spent; // These fields may need to be correctly populated at some point - eq->aapoints_assigned = emu->aa_spent + 1; + eq->aapoints_assigned = 0; eq->aa_spent_general = 0; eq->aa_spent_archetype = 0; eq->aa_spent_class = 0; diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 69bb7f4c1..1910a96e4 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1862,55 +1862,56 @@ namespace SoD ENCODE(OP_SendAATable) { - 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)); + EQApplicationPacket *inapp = *p; + *p = nullptr; + AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer; - // Check clientver field to verify this AA should be sent for SoF - // clientver 1 is for all clients and 5 is for SoD - if (emu->clientver <= 5) - { - 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); - } + EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability)); + structs::SendAA_Struct *eq = (structs::SendAA_Struct*)outapp->pBuffer; + + inapp->SetReadPosition(sizeof(AARankInfo_Struct)); + outapp->SetWritePosition(sizeof(structs::SendAA_Struct)); + + eq->id = emu->id; + eq->unknown004 = 1; + eq->id = emu->id; + eq->hotkey_sid = emu->upper_hotkey_sid; + eq->hotkey_sid2 = emu->lower_hotkey_sid; + eq->desc_sid = emu->desc_sid; + eq->title_sid = emu->title_sid; + eq->class_type = emu->level_req; + eq->cost = emu->cost; + eq->seq = emu->seq; + eq->current_level = emu->current_level; + eq->type = emu->type; + eq->spellid = emu->spell; + eq->spell_type = emu->spell_type; + eq->spell_refresh = emu->spell_refresh; + eq->classes = emu->classes; + eq->max_level = emu->max_level; + eq->last_id = emu->prev_id; + eq->next_id = emu->next_id; + eq->cost2 = emu->total_cost; + 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; + + for(auto i = 0; i < eq->total_abilities; ++i) { + eq->abilities[i].skill_id = inapp->ReadUInt32(); + eq->abilities[i].base1 = inapp->ReadUInt32(); + eq->abilities[i].base2 = inapp->ReadUInt32(); + eq->abilities[i].slot = inapp->ReadUInt32(); } - FINISH_ENCODE(); + if(emu->total_prereqs > 0) { + eq->prereq_skill = inapp->ReadUInt32(); + eq->prereq_minpoints = inapp->ReadUInt32(); + } + + dest->FastQueuePacket(&outapp); + delete inapp; } ENCODE(OP_SendCharInfo) diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 2d8ec8d3a..421903970 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1520,56 +1520,56 @@ namespace SoF ENCODE(OP_SendAATable) { - ENCODE_LENGTH_ATLEAST(SendAA_Struct); + EQApplicationPacket *inapp = *p; + *p = nullptr; + AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer; - SETUP_VAR_ENCODE(SendAA_Struct); - ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability)); + EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability)); + structs::SendAA_Struct *eq = (structs::SendAA_Struct*)outapp->pBuffer; - // Check clientver field to verify this AA should be sent for SoF - // clientver 1 is for all clients and 4 is for SoF - if (emu->clientver <= 4) - { - 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); - } + inapp->SetReadPosition(sizeof(AARankInfo_Struct)); + outapp->SetWritePosition(sizeof(structs::SendAA_Struct)); + + eq->id = emu->id; + eq->unknown004 = 1; + eq->id = emu->id; + eq->hotkey_sid = emu->upper_hotkey_sid; + eq->hotkey_sid2 = emu->lower_hotkey_sid; + eq->desc_sid = emu->desc_sid; + eq->title_sid = emu->title_sid; + eq->class_type = emu->level_req; + eq->cost = emu->cost; + eq->seq = emu->seq; + eq->current_level = emu->current_level; + eq->type = emu->type; + eq->spellid = emu->spell; + eq->spell_type = emu->spell_type; + eq->spell_refresh = emu->spell_refresh; + eq->classes = emu->classes; + eq->max_level = emu->max_level; + eq->last_id = emu->prev_id; + eq->next_id = emu->next_id; + eq->cost2 = emu->total_cost; + 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; + + for(auto i = 0; i < eq->total_abilities; ++i) { + eq->abilities[i].skill_id = inapp->ReadUInt32(); + eq->abilities[i].base1 = inapp->ReadUInt32(); + eq->abilities[i].base2 = inapp->ReadUInt32(); + eq->abilities[i].slot = inapp->ReadUInt32(); } - FINISH_ENCODE(); + if(emu->total_prereqs > 0) { + eq->prereq_skill = inapp->ReadUInt32(); + eq->prereq_minpoints = inapp->ReadUInt32(); + } + + dest->FastQueuePacket(&outapp); + delete inapp; } ENCODE(OP_SendCharInfo) @@ -1665,8 +1665,6 @@ namespace SoF emu_ptr += sizeof(CharacterSelectEntry_Struct); eq_ptr += sizeof(structs::CharacterSelectEntry_Struct); } - - FINISH_ENCODE(); } //hack hack hack diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 2fda4038a..ec25aba61 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -1107,50 +1107,52 @@ namespace Titanium ENCODE(OP_SendAATable) { - ENCODE_LENGTH_ATLEAST(SendAA_Struct); + EQApplicationPacket *inapp = *p; + *p = nullptr; + AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer; - SETUP_VAR_ENCODE(SendAA_Struct); - ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability)); + EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability)); + structs::SendAA_Struct *eq = (structs::SendAA_Struct*)outapp->pBuffer; - // Check clientver field to verify this AA should be sent for Titanium - // clientver 1 is for all clients and 3 is for Titanium - if (emu->clientver <= 3) - { - 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; - OUT(class_type); - OUT(cost); - OUT(seq); - OUT(current_level); - OUT(prereq_skill); - OUT(prereq_minpoints); - OUT(type); - OUT(spellid); - OUT(spell_type); - OUT(spell_refresh); - OUT(classes); - OUT(berserker); - OUT(max_level); - OUT(last_id); - OUT(next_id); - OUT(cost2); - OUT(unknown80[0]); - OUT(unknown80[1]); - 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); - } + inapp->SetReadPosition(sizeof(AARankInfo_Struct)); + outapp->SetWritePosition(sizeof(structs::SendAA_Struct)); + + eq->id = emu->id; + eq->unknown004 = 1; + eq->id = emu->id; + eq->hotkey_sid = emu->upper_hotkey_sid; + eq->hotkey_sid2 = emu->lower_hotkey_sid; + eq->desc_sid = emu->desc_sid; + eq->title_sid = emu->title_sid; + eq->class_type = emu->level_req; + eq->cost = emu->cost; + eq->seq = emu->seq; + eq->current_level = emu->current_level; + eq->type = emu->type; + eq->spellid = emu->spell; + eq->spell_type = emu->spell_type; + eq->spell_refresh = emu->spell_refresh; + eq->classes = emu->classes; + eq->max_level = emu->max_level; + eq->last_id = emu->prev_id; + eq->next_id = emu->next_id; + eq->cost2 = emu->total_cost; + eq->total_abilities = emu->total_effects; + + for(auto i = 0; i < eq->total_abilities; ++i) { + eq->abilities[i].skill_id = inapp->ReadUInt32(); + eq->abilities[i].base1 = inapp->ReadUInt32(); + eq->abilities[i].base2 = inapp->ReadUInt32(); + eq->abilities[i].slot = inapp->ReadUInt32(); } - FINISH_ENCODE(); + if(emu->total_prereqs > 0) { + eq->prereq_skill = inapp->ReadUInt32(); + eq->prereq_minpoints = inapp->ReadUInt32(); + } + + dest->FastQueuePacket(&outapp); + delete inapp; } ENCODE(OP_SendCharInfo) diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 5b879af9d..df6fa9615 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -2129,8 +2129,8 @@ namespace UF SETUP_DIRECT_ENCODE(AATable_Struct, structs::AATable_Struct); eq->aa_spent = emu->aa_spent; - eq->aa_assigned = emu->aa_spent; - eq->aa_spent3 = emu->aa_spent; + eq->aa_assigned = 0; + eq->aa_spent3 = 0; eq->unknown012 = 0; eq->unknown016 = 0; eq->unknown020 = 0; @@ -2195,7 +2195,6 @@ namespace UF eq->prereq_minpoints = inapp->ReadUInt32(); } - //Log.Out(Logs::General, Logs::Status, "%s", DumpPacketToString(outapp).c_str()); dest->FastQueuePacket(&outapp); delete inapp; } diff --git a/zone/aa.cpp b/zone/aa.cpp index 868c1f62c..d6be92fe7 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -930,121 +930,6 @@ bool Client::CheckAAEffect(aaEffectType type) { return(false); } -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(); - //} -} - void Client::SendAATimer(uint32 ability, uint32 begin, uint32 end) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_AAAction,sizeof(UseAA_Struct)); UseAA_Struct* uaaout = (UseAA_Struct*)outapp->pBuffer; @@ -1078,235 +963,6 @@ void Client::SendAATimers() { safe_delete(outapp); } -void Client::SendPreviousAA(uint32 id, int seq){ -} - -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; - // } - //} - -/* 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 - if (saa2->special_category == 3 || saa2->special_category == 4) - 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 (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(){ // RefundAA(); // uint32 i; @@ -1657,25 +1313,6 @@ void Client::RefundAA() { // } } -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; @@ -1753,7 +1390,12 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) { aai->current_level = level; aai->max_level = ability->GetMaxLevel(); aai->prev_id = rank->prev_id; - aai->next_id = rank->next_id; + + if(rank->next && !CanUseAlternateAdvancementRank(rank->next)) { + aai->next_id = -1; + } else { + aai->next_id = rank->next_id; + } aai->total_cost = rank->total_cost; aai->expansion = rank->expansion; aai->category = ability->category; @@ -1810,7 +1452,7 @@ void Client::SendAlternateAdvancementPoints() { } - aa2->aa_spent = GetAAPointsSpent(); + aa2->aa_spent = GetSpentAA(); QueuePacket(outapp); safe_delete(outapp); } @@ -1825,7 +1467,7 @@ void Client::PurchaseAlternateAdvancementRank(int rank_id) { return; } - if(!CanPurchaseAlternateAdvancementRank(rank)) { + if(!CanPurchaseAlternateAdvancementRank(rank, true)) { return; } @@ -1877,6 +1519,67 @@ void Client::PurchaseAlternateAdvancementRank(int rank_id) { NotifyNewTitlesAvailable(); } +void Client::IncrementAlternateAdvancementRank(int rank_id) { + AA::Rank *rank = zone->GetAlternateAdvancementRank(rank_id); + if(!rank) { + return; + } + + if(!rank->base_ability) { + return; + } + + if(!CanPurchaseAlternateAdvancementRank(rank, false)) { + return; + } + + if(rank->base_ability->charges > 0) { + SetAA(rank_id, rank->current_value, rank->base_ability->charges); + } + else { + SetAA(rank_id, rank->current_value, 0); + + //if not max then send next aa + if(rank->next) { + SendAlternateAdvancementRank(rank->base_ability->id, rank->next->current_value); + } + } + + SaveAA(); + + SendAlternateAdvancementPoints(); + SendAlternateAdvancementStats(); + + if(rank->prev) { + Message_StringID(15, AA_IMPROVE, + std::to_string(rank->title_sid).c_str(), + std::to_string(rank->prev->current_value).c_str(), + std::to_string(rank->cost).c_str(), + std::to_string(AA_POINTS).c_str()); + + //QS stuff broke with new aa, todo: fix later + /* 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); + // } + } + else { + Message_StringID(15, AA_GAIN_ABILITY, + std::to_string(rank->title_sid).c_str(), + std::to_string(rank->cost).c_str(), + std::to_string(AA_POINTS).c_str()); + //QS stuff broke with new aa, todo: fix later + /* 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); + // } + } + + CalcBonuses(); +} + bool ZoneDatabase::LoadAlternateAdvancement(Client *c) { c->ClearAAs(); std::string query = StringFormat( @@ -1984,6 +1687,16 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) { return false; } + //the one titanium hack i will allow + //just to make sure we dont crash the client with newer aas + //we'll exclude any expendable ones + if(IsClient() && CastToClient()->GetClientVersionBit() & BIT_TitaniumAndEarlier) { + if(ability->charges > 0) { + return false; + } + } + + //I might add a races behind the scenes field to take care of this // Check for racial/Drakkin blood line AAs if(ability->category == 8) { @@ -2009,7 +1722,7 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) { return true; } -bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank) { +bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price) { AA::Ability *ability = rank->base_ability; if(!ability) @@ -2063,7 +1776,7 @@ bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank) { } //check price, if client - if(IsClient()) { + if(check_price && IsClient()) { if(rank->cost > CastToClient()->GetAAPoints()) { return false; } diff --git a/zone/client.h b/zone/client.h index bd2c5371d..082d86fdc 100644 --- a/zone/client.h +++ b/zone/client.h @@ -764,6 +764,7 @@ public: void SendAlternateAdvancementTable(); void SendAlternateAdvancementStats(); void PurchaseAlternateAdvancementRank(int rank_id); + void IncrementAlternateAdvancementRank(int rank_id); void SendAlternateAdvancementPoints(); void SetAAPoints(uint32 points) { m_pp.aapoints = points; SendAlternateAdvancementStats(); } @@ -774,9 +775,6 @@ public: //old AA Methods void ResetAA(); void SendClearAA(); - void SendAA(uint32 id, int seq=1); - void SendPreviousAA(uint32 id, int seq=1); - void BuyAA(AA_Action* action); //this function is used by some AA stuff void MemorizeSpell(uint32 slot,uint32 spellid,uint32 scribing); void SetAATitle(const char *Title); @@ -793,11 +791,9 @@ public: void DisableAAEffect(aaEffectType type); bool CheckAAEffect(aaEffectType type); void HandleAAAction(aaID activate); - 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 RefundAA(); - void IncrementAA(int aa_id); int32 GetAAEffectDataBySlot(uint32 aa_ID, uint32 slot_id, bool GetEffect, bool GetBase1, bool GetBase2); int32 GetAAEffectid(uint32 aa_ID, uint32 slot_id) { return GetAAEffectDataBySlot(aa_ID, slot_id, true, false,false); } int32 GetAABase1(uint32 aa_ID, uint32 slot_id) { return GetAAEffectDataBySlot(aa_ID, slot_id, false, true,false); } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index e7d3b61a7..2068a815c 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -8801,7 +8801,7 @@ void Client::Handle_OP_LFGuild(const EQApplicationPacket *app) pack->WriteUInt32(QSG_LFGuild_UpdatePlayerInfo); pack->WriteUInt32(GetBaseClass()); pack->WriteUInt32(GetLevel()); - pack->WriteUInt32(GetAAPointsSpent()); + pack->WriteUInt32(GetSpentAA()); pack->WriteString(pts->Comment); pack->WriteUInt32(pts->Toggle); pack->WriteUInt32(pts->TimeZone); diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 47607b705..37f379a06 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -1024,7 +1024,7 @@ void Lua_Client::AddLevelBasedExp(int exp_pct, int max_level) { void Lua_Client::IncrementAA(int aa) { Lua_Safe_Call_Void(); - self->IncrementAA(aa); + self->IncrementAlternateAdvancementRank(aa); } void Lua_Client::MarkSingleCompassLoc(float in_x, float in_y, float in_z) { diff --git a/zone/mob.h b/zone/mob.h index ce9fe3634..db3879257 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -961,7 +961,7 @@ public: 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); + bool CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price); protected: void CommonDamage(Mob* other, int32 &damage, const uint16 spell_id, const SkillUseTypes attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index d564a341e..95fc146ae 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -4916,7 +4916,7 @@ XS(XS_Client_IncrementAA) if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - THIS->IncrementAA(aaskillid); + THIS->IncrementAlternateAdvancementRank(aaskillid); } XSRETURN_EMPTY; } diff --git a/zone/titles.cpp b/zone/titles.cpp index 3a4162060..8e6115aee 100644 --- a/zone/titles.cpp +++ b/zone/titles.cpp @@ -179,10 +179,10 @@ bool TitleManager::IsClientEligibleForTitle(Client *c, std::vector:: if((Title->Class >= 0) && (c->GetBaseClass() != Title->Class)) return false; - if((Title->MinAAPoints >= 0) && (c->GetAAPointsSpent() < static_cast(Title->MinAAPoints))) + if((Title->MinAAPoints >= 0) && (c->GetSpentAA() < static_cast(Title->MinAAPoints))) return false; - if((Title->MaxAAPoints >= 0) && (c->GetAAPointsSpent() > static_cast(Title->MaxAAPoints))) + if((Title->MaxAAPoints >= 0) && (c->GetSpentAA() > static_cast(Title->MaxAAPoints))) return false; if(Title->SkillID >= 0)