diff --git a/zone/aa.cpp b/zone/aa.cpp index 8a4df6293..c97ff7af4 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -762,6 +762,10 @@ void Client::RefundAA() { continue; } + if(ability->grant_only) { + continue; + } + refunded += rank->total_cost; } @@ -997,31 +1001,36 @@ void Client::PurchaseAlternateAdvancementRank(int rank_id) { return; } - FinishAlternateAdvancementPurchase(rank); + FinishAlternateAdvancementPurchase(rank, false); } -bool Client::GrantAlternateAdvancementAbility(int aa_id, int points) { - auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(aa_id, points); - auto ability = ability_rank.first; - auto rank = ability_rank.second; +bool Client::GrantAlternateAdvancementAbility(int aa_id, int points, bool ignore_cost) { + bool ret = false; + for(int i = 1; i <= points; ++i) { + auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(aa_id, i); + auto ability = ability_rank.first; + auto rank = ability_rank.second; - if(!rank) { - return false; + if(!rank) { + continue; + } + + if(!rank->base_ability) { + continue; + } + + if(!CanPurchaseAlternateAdvancementRank(rank, !ignore_cost, false)) { + continue; + } + + ret = true; + FinishAlternateAdvancementPurchase(rank, ignore_cost); } - if(!rank->base_ability) { - return false; - } - - if(!CanPurchaseAlternateAdvancementRank(rank, true, false)) { - return false; - } - - FinishAlternateAdvancementPurchase(rank); - return true; + return ret; } -void Client::FinishAlternateAdvancementPurchase(AA::Rank *rank) { +void Client::FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost) { int rank_id = rank->base_ability->first_rank_id; if(rank->base_ability->charges > 0) { @@ -1043,7 +1052,9 @@ void Client::FinishAlternateAdvancementPurchase(AA::Rank *rank) { } } - m_pp.aapoints -= rank->cost; + int cost = !ignore_cost ? rank->cost : 0; + + m_pp.aapoints -= cost ; SaveAA(); SendAlternateAdvancementPoints(); @@ -1053,30 +1064,33 @@ void Client::FinishAlternateAdvancementPurchase(AA::Rank *rank) { 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()); + std::to_string(cost).c_str(), + cost == 1 ? std::to_string(AA_POINT).c_str() : std::to_string(AA_POINTS).c_str()); /* QS: Player_Log_AA_Purchases */ - if(RuleB(QueryServ, PlayerLogAAPurchases)){ - std::string event_desc = StringFormat("Ranked AA Purchase :: aa_id:%i at cost:%i in zoneid:%i instid:%i", rank->id, rank->cost, GetZoneID(), GetInstanceID()); + if(RuleB(QueryServ, PlayerLogAAPurchases)) { + std::string event_desc = StringFormat("Ranked AA Purchase :: aa_id:%i at cost:%i in zoneid:%i instid:%i", rank->id, cost, GetZoneID(), GetInstanceID()); QServ->PlayerLogEvent(Player_Log_AA_Purchases, 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()); + std::to_string(cost).c_str(), + cost == 1 ? std::to_string(AA_POINT).c_str() : std::to_string(AA_POINTS).c_str()); /* QS: Player_Log_AA_Purchases */ - if(RuleB(QueryServ, PlayerLogAAPurchases)){ - std::string event_desc = StringFormat("Initial AA Purchase :: aa_id:%i at cost:%i in zoneid:%i instid:%i", rank->id, rank->cost, GetZoneID(), GetInstanceID()); + if(RuleB(QueryServ, PlayerLogAAPurchases)) { + std::string event_desc = StringFormat("Initial AA Purchase :: aa_id:%i at cost:%i in zoneid:%i instid:%i", rank->id, cost, GetZoneID(), GetInstanceID()); QServ->PlayerLogEvent(Player_Log_AA_Purchases, CharacterID(), event_desc); } } CalcBonuses(); - if(title_manager.IsNewAATitleAvailable(m_pp.aapoints_spent, GetBaseClass())) - NotifyNewTitlesAvailable(); + + if(cost > 0) { + if(title_manager.IsNewAATitleAvailable(m_pp.aapoints_spent, GetBaseClass())) + NotifyNewTitlesAvailable(); + } } //need to rewrite this @@ -1090,54 +1104,8 @@ void Client::IncrementAlternateAdvancementRank(int rank_id) { return; } - if(!CanPurchaseAlternateAdvancementRank(rank, false, true)) { - 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: Player_Log_AA_Purchases */ - if (RuleB(QueryServ, PlayerLogAAPurchases)){ - std::string event_desc = StringFormat("Ranked AA Purchase :: aa_id:%i at cost:%i in zoneid:%i instid:%i", rank->id, rank->cost, GetZoneID(), GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_AA_Purchases, 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: Player_Log_AA_Purchases */ - if (RuleB(QueryServ, PlayerLogAAPurchases)){ - std::string event_desc = StringFormat("Initial AA Purchase :: aa_id:%i at cost:%i in zoneid:%i instid:%i", rank->id, rank->cost, GetZoneID(), GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_AA_Purchases, this->CharacterID(), event_desc); - } - } - - CalcBonuses(); + int points = GetAA(rank_id); + GrantAlternateAdvancementAbility(rank->base_ability->id, points + 1, true); } void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) { @@ -1496,12 +1464,18 @@ bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price, auto points = GetAA(rank->id, ¤t_charges); //check that we are on previous rank already (if exists) - if(rank->prev) { + //grant ignores the req to own the previous rank. + if(check_grant && rank->prev) { if(points != rank->prev->current_value) { return false; } } + //check that we aren't already on this rank or one ahead of us + if(points >= rank->current_value) { + return false; + } + //if expendable only let us purchase if we have no charges already //not quite sure on how this functions client side atm //I intend to look into it later to make sure the behavior is right diff --git a/zone/client.h b/zone/client.h index 8b0522162..7ab3749e1 100644 --- a/zone/client.h +++ b/zone/client.h @@ -763,7 +763,7 @@ public: void SendAlternateAdvancementTable(); void SendAlternateAdvancementStats(); void PurchaseAlternateAdvancementRank(int rank_id); - bool GrantAlternateAdvancementAbility(int aa_id, int points); + bool GrantAlternateAdvancementAbility(int aa_id, int points, bool ignore_cost = false); void IncrementAlternateAdvancementRank(int rank_id); void ActivateAlternateAdvancementAbility(int rank_id, int target_id); void SendAlternateAdvancementPoints(); @@ -1263,7 +1263,7 @@ protected: int16 GetFocusEffect(focusType type, uint16 spell_id); uint16 GetSympatheticFocusEffect(focusType type, uint16 spell_id); - void FinishAlternateAdvancementPurchase(AA::Rank *rank); + void FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost); Mob* bind_sight_target; diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 8f2106b04..0c5bf8cc1 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -1032,6 +1032,11 @@ bool Lua_Client::GrantAlternateAdvancementAbility(int aa_id, int points) { self->GrantAlternateAdvancementAbility(aa_id, points); } +bool Lua_Client::GrantAlternateAdvancementAbility(int aa_id, int points, bool ignore_cost) { + Lua_Safe_Call_Bool(); + self->GrantAlternateAdvancementAbility(aa_id, points, ignore_cost); +} + void Lua_Client::MarkSingleCompassLoc(float in_x, float in_y, float in_z) { Lua_Safe_Call_Void(); self->MarkSingleCompassLoc(in_x, in_y, in_z); @@ -1506,6 +1511,7 @@ luabind::scope lua_register_client() { .def("AddLevelBasedExp", (void(Lua_Client::*)(int,int))&Lua_Client::AddLevelBasedExp) .def("IncrementAA", (void(Lua_Client::*)(int))&Lua_Client::IncrementAA) .def("GrantAlternateAdvancementAbility", (bool(Lua_Client::*)(int, int))&Lua_Client::GrantAlternateAdvancementAbility) + .def("GrantAlternateAdvancementAbility", (bool(Lua_Client::*)(int, int, bool))&Lua_Client::GrantAlternateAdvancementAbility) .def("MarkSingleCompassLoc", (void(Lua_Client::*)(float,float,float))&Lua_Client::MarkSingleCompassLoc) .def("MarkSingleCompassLoc", (void(Lua_Client::*)(float,float,float,int))&Lua_Client::MarkSingleCompassLoc) .def("GetNextAvailableSpellBookSlot", (int(Lua_Client::*)(void))&Lua_Client::GetNextAvailableSpellBookSlot) diff --git a/zone/lua_client.h b/zone/lua_client.h index a20f4fb57..0639cd6da 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -234,6 +234,7 @@ public: void AddLevelBasedExp(int exp_pct, int max_level); void IncrementAA(int aa); bool GrantAlternateAdvancementAbility(int aa_id, int points); + bool GrantAlternateAdvancementAbility(int aa_id, int points, bool ignore_cost); void MarkSingleCompassLoc(float in_x, float in_y, float in_z); void MarkSingleCompassLoc(float in_x, float in_y, float in_z, int count); int GetNextAvailableSpellBookSlot(); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index c836e378e..ee4ee943d 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -4898,13 +4898,14 @@ XS(XS_Client_GrantAlternateAdvancementAbility); /* prototype to pass -Wmissing-p XS(XS_Client_GrantAlternateAdvancementAbility) { dXSARGS; - if(items != 3) - Perl_croak(aTHX_ "Usage: Client::GrantAlternateAdvancementAbility(THIS, aa_id, points)"); + if(items < 3 || items > 4) + Perl_croak(aTHX_ "Usage: Client::GrantAlternateAdvancementAbility(THIS, aa_id, points, [ignore_cost])"); { Client * THIS; bool RETVAL; int aa_id = (int)SvIV(ST(1)); int points = (int)SvIV(ST(2)); + bool ignore_cost = false; if(sv_derived_from(ST(0), "Client")) { IV tmp = SvIV((SV*)SvRV(ST(0))); @@ -4915,7 +4916,11 @@ XS(XS_Client_GrantAlternateAdvancementAbility) if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - RETVAL = THIS->GrantAlternateAdvancementAbility(aa_id, points); + if(items > 3) { + ignore_cost = (bool)SvTRUE(ST(3)); + } + + RETVAL = THIS->GrantAlternateAdvancementAbility(aa_id, points, ignore_cost); ST(0) = boolSV(RETVAL); sv_2mortal(ST(0)); } @@ -6465,7 +6470,7 @@ XS(boot_Client) newXSproto(strcpy(buf, "GetIP"), XS_Client_GetIP, file, "$"); newXSproto(strcpy(buf, "AddLevelBasedExp"), XS_Client_AddLevelBasedExp, file, "$$;$"); newXSproto(strcpy(buf, "IncrementAA"), XS_Client_IncrementAA, file, "$$"); - newXSproto(strcpy(buf, "GrantAlternateAdvancementAbility"), XS_Client_GrantAlternateAdvancementAbility, file, "$$$"); + newXSproto(strcpy(buf, "GrantAlternateAdvancementAbility"), XS_Client_GrantAlternateAdvancementAbility, file, "$$$;$"); newXSproto(strcpy(buf, "GetAALevel"), XS_Client_GetAALevel, file, "$$"); newXSproto(strcpy(buf, "MarkCompassLoc"), XS_Client_MarkCompassLoc, file, "$$$$"); newXSproto(strcpy(buf, "ClearCompassMark"), XS_Client_ClearCompassMark, file, "$");