diff --git a/zone/aa.cpp b/zone/aa.cpp index 20009d281..fc1923506 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -23,7 +23,7 @@ Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) #include "../common/races.h" #include "../common/spdat.h" #include "../common/string_util.h" - +#include "../common/deity.h" #include "aa.h" #include "client.h" #include "corpse.h" @@ -1279,7 +1279,7 @@ void Client::SendAlternateAdvancementTable() { uint32 charges = 0; auto ranks = GetAA(aa.second->first_rank_id, &charges); if(ranks) { - if(aa.second->GetMaxLevel() == ranks) { + if(aa.second->GetMaxLevel(this) == ranks) { SendAlternateAdvancementRank(aa.first, ranks); } else { SendAlternateAdvancementRank(aa.first, ranks); @@ -1330,7 +1330,7 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) { aai->classes = ability->classes; aai->level_req = rank->level_req; aai->current_level = level; - aai->max_level = ability->GetMaxLevel(); + aai->max_level = ability->GetMaxLevel(this); aai->prev_id = rank->prev_id; if(rank->next && !CanUseAlternateAdvancementRank(rank->next)) { @@ -1450,9 +1450,11 @@ void Client::PurchaseAlternateAdvancementRank(int rank_id) { uint32 charges = 0; GetAA(rank_id, &charges); - if(charges == 0) { - SetAA(rank_id, rank->current_value, rank->base_ability->charges); + if(charges > 0) { + return; } + + SetAA(rank_id, rank->current_value, rank->base_ability->charges); } else { SetAA(rank_id, rank->current_value, 0); @@ -1781,7 +1783,7 @@ bool Mob::SetAA(uint32 rank_id, uint32 new_value, uint32 charges) { return false; } - if(new_value > ability->GetMaxLevel()) { + if(new_value > ability->GetMaxLevel(this)) { return false; } @@ -1817,29 +1819,44 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) { } } - //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) - { - uint32 client_race = GetBaseRace(); - - // Drakkin Bloodlines - if(rank->expansion > 522) - { - if(client_race != 522) - return false; - - int heritage = this->GetDrakkinHeritage() + 523; // 523 = Drakkin Race(522) + Bloodline - - if(heritage != rank->expansion) - return false; - } - else if(client_race != rank->expansion) - { - return false; - } + if(!(RuleI(World, ExpansionSettings) & (1 << rank->expansion))) { + return false; } + auto race = GetArrayRace(GetBaseRace()); + race = race > 16 ? 1 : race; + if(!(ability->races & (1 << (race - 1)))) { + return false; + } + + auto deity = ConvertDeityToBitDeity((DeityTypes)GetDeity()); + if(!(ability->deities & deity)) { + return false; + } + + // Check for racial/Drakkin blood line AAs + //Commented this out for now, will add a drakkin heritage field later + //if(ability->category == 8) + //{ + // uint32 client_race = GetBaseRace(); + // + // // Drakkin Bloodlines + // if(rank->expansion > 522) + // { + // if(client_race != 522) + // return false; + // + // int heritage = this->GetDrakkinHeritage() + 523; // 523 = Drakkin Race(522) + Bloodline + // + // if(heritage != rank->expansion) + // return false; + // } + // else if(client_race != rank->expansion) + // { + // return false; + // } + //} + return true; } @@ -1858,10 +1875,6 @@ bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price) return false; } - if(!(RuleI(World, ExpansionSettings) & (1 << rank->expansion))) { - return false; - } - //check level req if(rank->level_req > GetLevel()) { return false; @@ -1940,8 +1953,6 @@ void Zone::LoadAlternateAdvancement() { i++; current = current->next; } - - ability.second->GetMaxLevel(true); } Log.Out(Logs::General, Logs::Status, "Loaded Alternate Advancement Data"); @@ -1952,7 +1963,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_mapid = atoi(row[0]); ability->name = row[1]; ability->category = atoi(row[2]); - ability->classes = atoi(row[3]); - ability->type = atoi(row[4]); - ability->charges = atoi(row[5]); - ability->grant_only = atoi(row[6]) != 0 ? true : false; - ability->first_rank_id = atoi(row[7]); + //EQ client has classes left shifted by one bit for some odd reason + ability->classes = atoi(row[3]) << 1; + ability->races = atoi(row[4]); + ability->deities = atoi(row[5]); + ability->type = atoi(row[6]); + ability->charges = atoi(row[7]); + ability->grant_only = atoi(row[8]) != 0 ? true : false; + ability->first_rank_id = atoi(row[9]); ability->first = nullptr; abilities[ability->id] = std::unique_ptr(ability); diff --git a/zone/aa_ability.cpp b/zone/aa_ability.cpp index 8f9cb8da4..3612b00c7 100644 --- a/zone/aa_ability.cpp +++ b/zone/aa_ability.cpp @@ -18,6 +18,7 @@ #include "../common/global_define.h" #include "../common/types.h" +#include "masterentity.h" #include "aa_ability.h" AA::Rank *AA::Ability::GetMaxRank() { @@ -53,16 +54,17 @@ AA::Rank *AA::Ability::GetRankByPointsSpent(int current_level) { return current; } -int AA::Ability::GetMaxLevel(bool force_calc) { - if(!force_calc) - return max_level; - - max_level = 0; +int AA::Ability::GetMaxLevel(Mob *who) { + int max_level = 0; Rank *current = first; while(current) { + if(!who->CanUseAlternateAdvancementRank(current)) { + return max_level; + } + max_level++; current = current->next; } - + return max_level; } \ No newline at end of file diff --git a/zone/aa_ability.h b/zone/aa_ability.h index a31bc06e3..bd2b9e306 100644 --- a/zone/aa_ability.h +++ b/zone/aa_ability.h @@ -27,6 +27,8 @@ #include "aa_rank_prereqs.h" #include "aa_rank.h" +class Mob; + namespace AA { @@ -39,17 +41,18 @@ public: Rank *GetMaxRank(); Rank *GetRankByLevel(int level); Rank *GetRankByPointsSpent(int current_level); - int GetMaxLevel(bool force_calc = false); + int GetMaxLevel(Mob *who); int id; std::string name; int category; int classes; + int races; + int deities; bool grant_only; int type; int charges; int first_rank_id; - int max_level; Rank *first; }; diff --git a/zone/mob.cpp b/zone/mob.cpp index 645b42325..965007fcf 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1143,6 +1143,10 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) else ns->spawn.flymode = flymode; + if(IsBoat()) { + ns->spawn.flymode = 1; + } + ns->spawn.lastName[0] = '\0'; strn0cpy(ns->spawn.lastName, lastname, sizeof(ns->spawn.lastName)); diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 7570165a3..834109dd1 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -212,7 +212,7 @@ void NPC::UpdateWaypoint(int wp_index) Log.Out(Logs::Detail, Logs::AI, "Next waypoint %d: (%.3f, %.3f, %.3f, %.3f)", wp_index, m_CurrentWayPoint.x, m_CurrentWayPoint.y, m_CurrentWayPoint.z, m_CurrentWayPoint.w); //fix up pathing Z - if(zone->HasMap() && RuleB(Map, FixPathingZAtWaypoints)) + if(zone->HasMap() && RuleB(Map, FixPathingZAtWaypoints) && !IsBoat()) { if(!RuleB(Watermap, CheckForWaterAtWaypoints) || !zone->HasWaterMap() || @@ -521,7 +521,7 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo } bool send_update = false; - int compare_steps = IsBoat() ? 1 : 20; + int compare_steps = 20; if(tar_ndx < compare_steps && m_TargetLocation.x==x && m_TargetLocation.y==y) { float new_x = m_Position.x + m_TargetV.x*tar_vector;