More work, looks a lot better than before, tomorrow i hope to get actual client implementation done

This commit is contained in:
KimLS 2015-06-09 22:12:31 -07:00
parent 33c1c7c3e4
commit d5e697c061
9 changed files with 363 additions and 342 deletions

View File

@ -1254,37 +1254,37 @@ void Client::SendAA(uint32 id, int seq) {
if (RuleB(AA, Stacking) && (GetClientVersionBit() >= 4) && (saa2->hotkey_sid == 4294967295u))
aa_stack = true;
if (aa_stack){
uint32 aa_AA = 0;
uint32 aa_value = 0;
for (int i = 0; i < MAX_PP_AA_ARRAY; i++) {
if (aa[i]) {
aa_AA = aa[i]->AA;
aa_value = aa[i]->value;
if (aa_AA){
if (aa_value > 0)
aa_AA -= aa_value-1;
saa_pp = zone->FindAA(aa_AA);
if (saa_pp){
if (saa_pp->sof_next_skill == saa2->sof_next_skill){
if (saa_pp->id == saa2->id)
break; //You already have this in the player profile.
else if ((saa_pp->sof_current_level < saa2->sof_current_level) && (aa_value < saa_pp->max_level))
return; //DISABLE DISPLAY HIGHER - You have not reached max level yet of your current AA.
else if ((saa_pp->sof_current_level < saa2->sof_current_level) && (aa_value == saa_pp->max_level) && (saa_pp->sof_next_id == saa2->id))
IsBaseLevel = false; //ALLOW DISPLAY HIGHER
}
}
}
}
}
}
//if (aa_stack){
// uint32 aa_AA = 0;
// uint32 aa_value = 0;
// for (int i = 0; i < MAX_PP_AA_ARRAY; i++) {
// if (aa[i]) {
// aa_AA = aa[i]->AA;
// aa_value = aa[i]->value;
//
// if (aa_AA){
//
// if (aa_value > 0)
// aa_AA -= aa_value-1;
//
// saa_pp = zone->FindAA(aa_AA);
//
// if (saa_pp){
//
// if (saa_pp->sof_next_skill == saa2->sof_next_skill){
//
// if (saa_pp->id == saa2->id)
// break; //You already have this in the player profile.
// else if ((saa_pp->sof_current_level < saa2->sof_current_level) && (aa_value < saa_pp->max_level))
// return; //DISABLE DISPLAY HIGHER - You have not reached max level yet of your current AA.
// else if ((saa_pp->sof_current_level < saa2->sof_current_level) && (aa_value == saa_pp->max_level) && (saa_pp->sof_next_id == saa2->id))
// IsBaseLevel = false; //ALLOW DISPLAY HIGHER
// }
// }
// }
// }
// }
//}
//Hide higher tiers of multi tiered AA's if the base level is not fully purchased.
if (aa_stack && IsBaseLevel && saa2->sof_current_level > 0)
@ -1399,51 +1399,6 @@ void Client::SendAAList(){
}
}
uint32 Client::GetAA(uint32 aa_id) const {
std::map<uint32,uint8>::const_iterator res;
res = aa_points.find(aa_id);
if(res != aa_points.end()) {
return(res->second);
}
return(0);
}
bool Client::SetAA(uint32 aa_id, uint32 new_value) {
aa_points[aa_id] = new_value;
uint32 cur;
auto sendaa = zone->FindAA(aa_id); // this is a bit hacky
uint32 charges = sendaa->special_category == 7 && new_value ? 1 : 0;
for(cur=0;cur < MAX_PP_AA_ARRAY;cur++){
if((aa[cur]->value > 1) && ((aa[cur]->AA - aa[cur]->value + 1)== aa_id)){
aa[cur]->value = new_value;
if(new_value > 0)
aa[cur]->AA++;
aa[cur]->charges = charges;
return true;
}
else if((aa[cur]->value == 1) && (aa[cur]->AA == aa_id)){
aa[cur]->value = new_value;
if(new_value > 0)
aa[cur]->AA++;
aa[cur]->charges = charges;
return true;
}
// hack to prevent expendable exploit, we should probably be reshuffling the array to fix the hole
else if(aa[cur]->value == 0 && new_value == 1 && aa[cur]->AA == aa_id) {
aa[cur]->value = new_value;
aa[cur]->charges = charges;
return true;
}
else if(aa[cur]->AA==0){ //end of list
aa[cur]->AA = aa_id;
aa[cur]->value = new_value;
aa[cur]->charges = charges;
return true;
}
}
return false;
}
SendAA_Struct* Zone::FindAA(uint32 id) {
return aas_send[id];
}
@ -1503,39 +1458,39 @@ bool ZoneDatabase::LoadAAEffects2() {
}
void Client::ResetAA(){
RefundAA();
uint32 i;
for (i=0; i < MAX_PP_AA_ARRAY; i++) {
aa[i]->AA = 0;
aa[i]->value = 0;
aa[i]->charges = 0;
m_pp.aa_array[i].AA = 0;
m_pp.aa_array[i].value = 0;
m_pp.aa_array[i].charges= 0;
}
std::map<uint32,uint8>::iterator itr;
for(itr = aa_points.begin(); itr != aa_points.end(); ++itr)
aa_points[itr->first] = 0;
for(int i = 0; i < _maxLeaderAA; ++i)
m_pp.leader_abilities.ranks[i] = 0;
m_pp.group_leadership_points = 0;
m_pp.raid_leadership_points = 0;
m_pp.group_leadership_exp = 0;
m_pp.raid_leadership_exp = 0;
database.DeleteCharacterAAs(this->CharacterID());
SaveAA();
SendClearAA();
SendAAList();
SendAATable();
SendAAStats();
database.DeleteCharacterLeadershipAAs(this->CharacterID());
// undefined for these clients
if (GetClientVersionBit() & BIT_TitaniumAndEarlier)
Kick();
// RefundAA();
// uint32 i;
// for (i=0; i < MAX_PP_AA_ARRAY; i++) {
// aa[i]->AA = 0;
// aa[i]->value = 0;
// aa[i]->charges = 0;
// m_pp.aa_array[i].AA = 0;
// m_pp.aa_array[i].value = 0;
// m_pp.aa_array[i].charges= 0;
// }
//
// std::map<uint32,uint8>::iterator itr;
// for(itr = aa_points.begin(); itr != aa_points.end(); ++itr)
// aa_points[itr->first] = 0;
//
// for(int i = 0; i < _maxLeaderAA; ++i)
// m_pp.leader_abilities.ranks[i] = 0;
//
// m_pp.group_leadership_points = 0;
// m_pp.raid_leadership_points = 0;
// m_pp.group_leadership_exp = 0;
// m_pp.raid_leadership_exp = 0;
//
// database.DeleteCharacterAAs(this->CharacterID());
// SaveAA();
// SendClearAA();
// SendAAList();
// SendAATable();
// SendAAStats();
// database.DeleteCharacterLeadershipAAs(this->CharacterID());
// // undefined for these clients
// if (GetClientVersionBit() & BIT_TitaniumAndEarlier)
// Kick();
}
void Client::SendClearAA()
@ -2096,19 +2051,23 @@ Mob *AA_SwarmPetInfo::GetOwner()
return entity_list.GetMobID(owner_id);
}
void Client::SendAlternateAdvancementList() {
//for(auto &aa : zone->aa_abilities) {
// SendAlternateAdvancement(aa.first, 5);
//}
SendAlternateAdvancementRank(1, 5);
SendAlternateAdvancementRank(1, 6);
SendAlternateAdvancementRank(2, 1);
//SendAlternateAdvancement(1, 5);
//SendAlternateAdvancement(2, 5);
//New AA
void Client::SendAlternateAdvancementTable() {
for(auto &aa : zone->aa_abilities) {
auto ranks = GetAA(aa.second->first_rank_id);
if(ranks) {
if(aa.second->GetMaxLevel() == ranks) {
SendAlternateAdvancementRank(aa.first, ranks);
} else {
SendAlternateAdvancementRank(aa.first, ranks);
SendAlternateAdvancementRank(aa.first, ranks + 1);
}
} else {
SendAlternateAdvancementRank(aa.first, 1);
}
}
}
//New AA
void Client::SendAlternateAdvancementRank(int aa_id, int level) {
if(!zone)
return;
@ -2126,53 +2085,9 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) {
if(!rank)
return;
if(rank->account_time_required) {
if((Timer::GetTimeSeconds() - account_creation) < rank->account_time_required)
{
return;
}
}
// Hide Quest/Progression AAs unless player has been granted the first level using $client->IncrementAA(skill_id).
if(ability->category == 1 || ability->category == 2) {
//if(GetAA(saa2->id) == 0)
// return;
if(rank->expansion > 0) {
AA::Ability *qaa = zone->GetAlternateAdvancementAbility(aa_id + 1);
//if(qaa && qaa->expansion == rank->expansion && GetAA(aa_id) > 0) {
// return;
//}
}
}
// Passive and Active Shroud AAs
// For now we skip them
if(ability->category == 3 || ability->category == 4) {
if(!CanUseAlternateAdvancementRank(rank)) {
return;
}
// Check for racial/Drakkin blood line AAs
if(ability->category == 8)
{
uint32 client_race = GetBaseRace();
// Drakkin Bloodlines
if(rank->expansion > 522)
{
if(client_race != 522)
return;
int heritage = this->GetDrakkinHeritage() + 523; // 523 = Drakkin Race(522) + Bloodline
if(heritage != rank->expansion)
return;
}
else if(client_race != rank->expansion)
{
return;
}
}
int size = sizeof(AARankInfo_Struct) + (sizeof(AARankEffect_Struct) * rank->effects.size()) + (sizeof(AARankPrereq_Struct) * rank->prereqs.size());
EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, size);
@ -2220,10 +2135,126 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) {
safe_delete(outapp);
}
AA::Ability *Zone::GetAlternateAdvancementAbility(int id) {
auto iter = aa_abilities.find(id);
if(iter != aa_abilities.end()) {
return iter->second.get();
}
return nullptr;
}
AA::Ability *Zone::GetAlternateAdvancementAbilityByRank(int rank_id) {
AA::Rank *rank = GetAlternateAdvancementRank(rank_id);
if(!rank)
return nullptr;
return rank->base_ability;
}
AA::Rank *Zone::GetAlternateAdvancementRank(int rank_id) {
auto iter = aa_ranks.find(rank_id);
if(iter != aa_ranks.end()) {
return iter->second.get();
}
return nullptr;
}
uint32 Mob::GetAA(uint32 rank_id) const {
if(zone) {
AA::Ability *ability = zone->GetAlternateAdvancementAbilityByRank(rank_id);
if(!ability)
return 0;
auto iter = aa_ranks.find(ability->id);
if(iter != aa_ranks.end()) {
return iter->second;
}
}
return 0;
}
bool Mob::SetAA(uint32 rank_id, uint32 new_value) {
if(zone) {
AA::Ability *ability = zone->GetAlternateAdvancementAbilityByRank(rank_id);
if(!ability) {
return false;
}
if(new_value > ability->GetMaxLevel()) {
return false;
}
aa_ranks[ability->id] = new_value;
}
return false;
}
bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) {
AA::Ability *ability = rank->base_ability;
if(!ability)
return false;
// Passive and Active Shroud AAs
// For now we skip them
if(ability->category == 3 || ability->category == 4) {
return false;
}
// Check for racial/Drakkin blood line AAs
if(ability->category == 8)
{
uint32 client_race = GetBaseRace();
// Drakkin Bloodlines
if(rank->expansion > 522)
{
if(client_race != 522)
return false;
int heritage = this->GetDrakkinHeritage() + 523; // 523 = Drakkin Race(522) + Bloodline
if(heritage != rank->expansion)
return false;
}
else if(client_race != rank->expansion)
{
return false;
}
}
return true;
}
bool Mob::CanPurchaseAlternateAdvancementRank(AA::Rank *rank) {
AA::Ability *ability = rank->base_ability;
if(!ability)
return false;
if(!CanUseAlternateAdvancementRank(rank)) {
return false;
}
//You can't purchase grant only AAs they can only be assigned
if(ability->grant_only) {
return false;
}
//check other stuff like price later
return true;
}
void Zone::LoadAlternateAdvancement() {
Log.Out(Logs::General, Logs::Status, "Loading Alternate Advancement Data...");
if(!database.LoadAlternateAdvancementAbilities(aa_abilities,
aa_ranks))
if(!database.LoadAlternateAdvancementAbilities(aa_abilities,
aa_ranks))
{
aa_abilities.clear();
aa_ranks.clear();
@ -2244,7 +2275,8 @@ void Zone::LoadAlternateAdvancement() {
if(current->prev) {
current->total_cost = current->cost + current->prev->total_cost;
} else {
}
else {
current->total_cost = current->cost;
}
@ -2257,24 +2289,6 @@ void Zone::LoadAlternateAdvancement() {
Log.Out(Logs::General, Logs::Status, "Loaded Alternate Advancement Data");
}
AA::Ability *Zone::GetAlternateAdvancementAbility(int id) {
auto iter = aa_abilities.find(id);
if(iter != aa_abilities.end()) {
return iter->second.get();
}
return nullptr;
}
AA::Rank *Zone::GetAlternateAdvancementRank(int rank_id) {
auto iter = aa_ranks.find(rank_id);
if(iter != aa_ranks.end()) {
return iter->second.get();
}
return nullptr;
}
bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map<int, std::unique_ptr<AA::Ability>> &abilities,
std::unordered_map<int, std::unique_ptr<AA::Rank>> &ranks)
{
@ -2285,7 +2299,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map<int, std
if(results.Success()) {
for(auto row = results.begin(); row != results.end(); ++row) {
AA::Ability *ability = new AA::Ability;
int id = atoi(row[0]);
ability->id = atoi(row[0]);
ability->name = row[1];
ability->category = atoi(row[2]);
ability->classes = atoi(row[3]);
@ -2295,7 +2309,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map<int, std
ability->first_rank_id = atoi(row[7]);
ability->first = nullptr;
abilities[id] = std::unique_ptr<AA::Ability>(ability);
abilities[ability->id] = std::unique_ptr<AA::Ability>(ability);
}
} else {
Log.Out(Logs::General, Logs::Error, "Failed to load Alternate Advancement Abilities");
@ -2312,8 +2326,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map<int, std
if(results.Success()) {
for(auto row = results.begin(); row != results.end(); ++row) {
AA::Rank *rank = new AA::Rank;
int id = atoi(row[0]);
rank->id = id;
rank->id = atoi(row[0]);
rank->upper_hotkey_sid = atoi(row[1]);
rank->lower_hotkey_sid = atoi(row[2]);
rank->title_sid = atoi(row[3]);
@ -2332,7 +2345,7 @@ bool ZoneDatabase::LoadAlternateAdvancementAbilities(std::unordered_map<int, std
rank->next = nullptr;
rank->prev = nullptr;
ranks[id] = std::unique_ptr<AA::Rank>(rank);
ranks[rank->id] = std::unique_ptr<AA::Rank>(rank);
}
} else {
Log.Out(Logs::General, Logs::Error, "Failed to load Alternate Advancement Ability Ranks");

View File

@ -41,6 +41,7 @@ public:
Rank *GetRankByPointsSpent(int current_level);
int GetMaxLevel(bool force_calc = false);
int id;
std::string name;
int category;
int classes;

View File

@ -639,20 +639,21 @@ void Client::CalcAABonuses(StatBonuses* newbon) {
uint32 slots = 0;
uint32 aa_AA = 0;
uint32 aa_value = 0;
if(this->aa) {
for (i = 0; i < MAX_PP_AA_ARRAY; i++) { //iterate through all of the client's AAs
if (this->aa[i]) { // make sure aa exists or we'll crash zone
aa_AA = this->aa[i]->AA; //same as aaid from the aa_effects table
aa_value = this->aa[i]->value; //how many points in it
if (aa_AA > 0 || aa_value > 0) { //do we have the AA? if 1 of the 2 is set, we can assume we do
//slots = database.GetTotalAALevels(aa_AA); //find out how many effects from aa_effects table
slots = zone->GetTotalAALevels(aa_AA); //find out how many effects from aa_effects, which is loaded into memory
if (slots > 0) //and does it have any effects? may be able to put this above, not sure if it runs on each iteration
ApplyAABonuses(aa_AA, slots, newbon); //add the bonuses
}
}
}
}
//aa old
//if(this->aa) {
// for (i = 0; i < MAX_PP_AA_ARRAY; i++) { //iterate through all of the client's AAs
// if (this->aa[i]) { // make sure aa exists or we'll crash zone
// aa_AA = this->aa[i]->AA; //same as aaid from the aa_effects table
// aa_value = this->aa[i]->value; //how many points in it
// if (aa_AA > 0 || aa_value > 0) { //do we have the AA? if 1 of the 2 is set, we can assume we do
// //slots = database.GetTotalAALevels(aa_AA); //find out how many effects from aa_effects table
// slots = zone->GetTotalAALevels(aa_AA); //find out how many effects from aa_effects, which is loaded into memory
// if (slots > 0) //and does it have any effects? may be able to put this above, not sure if it runs on each iteration
// ApplyAABonuses(aa_AA, slots, newbon); //add the bonuses
// }
// }
// }
//}
}

View File

@ -176,7 +176,6 @@ Client::Client(EQStreamInterface* ieqs)
admin = 0;
lsaccountid = 0;
shield_target = nullptr;
SQL_log = nullptr;
guild_id = GUILD_NONE;
guildrank = 0;
GuildBanker = false;
@ -524,47 +523,48 @@ void Client::ReportConnectingState() {
}
bool Client::SaveAA(){
int first_entry = 0;
std::string rquery;
/* Save Player AA */
int spentpoints = 0;
for (int a = 0; a < MAX_PP_AA_ARRAY; a++) {
uint32 points = aa[a]->value;
if (points > HIGHEST_AA_VALUE) {
aa[a]->value = HIGHEST_AA_VALUE;
points = HIGHEST_AA_VALUE;
}
if (points > 0) {
SendAA_Struct* curAA = zone->FindAA(aa[a]->AA - aa[a]->value + 1);
if (curAA) {
for (int rank = 0; rank<points; rank++) {
std::map<uint32, AALevelCost_Struct>::iterator RequiredLevel = AARequiredLevelAndCost.find(aa[a]->AA - aa[a]->value + 1 + rank);
if (RequiredLevel != AARequiredLevelAndCost.end()) {
spentpoints += RequiredLevel->second.Cost;
}
else
spentpoints += (curAA->cost + (curAA->cost_inc * rank));
}
}
}
}
m_pp.aapoints_spent = spentpoints + m_epp.expended_aa;
int highest = 0;
for (int a = 0; a < MAX_PP_AA_ARRAY; a++) {
if (aa[a]->AA > 0) { // those with value 0 will be cleaned up on next load
if (first_entry != 1){
rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value, charges)"
" VALUES (%u, %u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value, aa[a]->charges);
first_entry = 1;
} else {
rquery = rquery + StringFormat(", (%u, %u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value, aa[a]->charges);
}
highest = a;
}
}
auto results = database.QueryDatabase(rquery);
/* This is another part of the hack to clean up holes left by expendable AAs */
rquery = StringFormat("DELETE FROM `character_alternate_abilities` WHERE `id` = %u AND `slot` > %d", character_id, highest);
//aa old
//int first_entry = 0;
//std::string rquery;
///* Save Player AA */
//int spentpoints = 0;
//for (int a = 0; a < MAX_PP_AA_ARRAY; a++) {
// uint32 points = aa[a]->value;
// if (points > HIGHEST_AA_VALUE) {
// aa[a]->value = HIGHEST_AA_VALUE;
// points = HIGHEST_AA_VALUE;
// }
// if (points > 0) {
// SendAA_Struct* curAA = zone->FindAA(aa[a]->AA - aa[a]->value + 1);
// if (curAA) {
// for (int rank = 0; rank<points; rank++) {
// std::map<uint32, AALevelCost_Struct>::iterator RequiredLevel = AARequiredLevelAndCost.find(aa[a]->AA - aa[a]->value + 1 + rank);
// if (RequiredLevel != AARequiredLevelAndCost.end()) {
// spentpoints += RequiredLevel->second.Cost;
// }
// else
// spentpoints += (curAA->cost + (curAA->cost_inc * rank));
// }
// }
// }
//}
//m_pp.aapoints_spent = spentpoints + m_epp.expended_aa;
//int highest = 0;
//for (int a = 0; a < MAX_PP_AA_ARRAY; a++) {
// if (aa[a]->AA > 0) { // those with value 0 will be cleaned up on next load
// if (first_entry != 1){
// rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value, charges)"
// " VALUES (%u, %u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value, aa[a]->charges);
// first_entry = 1;
// } else {
// rquery = rquery + StringFormat(", (%u, %u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value, aa[a]->charges);
// }
// highest = a;
// }
//}
//auto results = database.QueryDatabase(rquery);
///* This is another part of the hack to clean up holes left by expendable AAs */
//rquery = StringFormat("DELETE FROM `character_alternate_abilities` WHERE `id` = %u AND `slot` > %d", character_id, highest);
return true;
}

View File

@ -761,7 +761,7 @@ public:
//New AA Methods
void SendAlternateAdvancementRank(int aa_id, int level);
void SendAlternateAdvancementList();
void SendAlternateAdvancementTable();
//old AA Methods
void SendAAList();
@ -787,8 +787,6 @@ public:
void DisableAAEffect(aaEffectType type);
bool CheckAAEffect(aaEffectType type);
void HandleAAAction(aaID activate);
uint32 GetAA(uint32 aa_id) const;
bool SetAA(uint32 aa_id, uint32 new_value);
inline uint32 GetAAPointsSpent() { return m_pp.aapoints_spent; }
int16 CalcAAFocusEffect(focusType type, uint16 focus_spell, uint16 spell_id);
int16 CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id);
@ -1493,11 +1491,7 @@ private:
uint32 tribute_master_id;
FILE *SQL_log;
uint32 max_AAXP;
uint32 staminacount;
AA_Array* aa[MAX_PP_AA_ARRAY]; //this list contains pointers into our player profile
std::map<uint32,uint8> aa_points;
bool npcflag;
uint8 npclevel;
bool feigned;

View File

@ -1091,7 +1091,7 @@ void Client::Handle_Connect_OP_SendAAStats(const EQApplicationPacket *app)
void Client::Handle_Connect_OP_SendAATable(const EQApplicationPacket *app)
{
SendAlternateAdvancementList();
SendAlternateAdvancementTable();
return;
}
@ -1440,58 +1440,60 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
if (m_pp.ldon_points_available < 0 || m_pp.ldon_points_available > 2000000000){ m_pp.ldon_points_available = 0; }
/* Initialize AA's : Move to function eventually */
for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++)
aa[a] = &m_pp.aa_array[a];
query = StringFormat(
"SELECT "
"slot, "
"aa_id, "
"aa_value, "
"charges "
"FROM "
"`character_alternate_abilities` "
"WHERE `id` = %u ORDER BY `slot`", this->CharacterID());
results = database.QueryDatabase(query); i = 0;
int offset = 0; // offset to fix the hole from expendables
for (auto row = results.begin(); row != results.end(); ++row) {
i = atoi(row[0]) - offset;
m_pp.aa_array[i].AA = atoi(row[1]);
m_pp.aa_array[i].value = atoi(row[2]);
m_pp.aa_array[i].charges = atoi(row[3]);
/* A used expendable could cause there to be a "hole" in the array, this is very bad. Bad things like keeping your expendable after use.
We could do a few things, one of them being reshuffling when the hole is created or defer the fixing until a later point, like during load!
Or just never making a hole in the array and just have hacks every where. Fixing the hole at load really just keeps 1 hack in Client::SendAATable
and keeping this offset that will cause the next AA to be pushed back over the hole. We also need to clean up on save so we don't have multiple
entries for a single AA.
*/
if (m_pp.aa_array[i].value == 0)
offset++;
}
for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++){
uint32 id = aa[a]->AA;
//watch for invalid AA IDs
if (id == aaNone)
continue;
if (id >= aaHighestID) {
aa[a]->AA = aaNone;
aa[a]->value = 0;
continue;
}
if (aa[a]->value == 0) {
aa[a]->AA = aaNone;
continue;
}
if (aa[a]->value > HIGHEST_AA_VALUE) {
aa[a]->AA = aaNone;
aa[a]->value = 0;
continue;
}
if (aa[a]->value > 1) /* hack in some stuff for sony's new AA method (where each level of each aa.has a seperate ID) */
aa_points[(id - aa[a]->value + 1)] = aa[a]->value;
else
aa_points[id] = aa[a]->value;
}
//aa old
//for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++)
// aa[a] = &m_pp.aa_array[a];
//query = StringFormat(
// "SELECT "
// "slot, "
// "aa_id, "
// "aa_value, "
// "charges "
// "FROM "
// "`character_alternate_abilities` "
// "WHERE `id` = %u ORDER BY `slot`", this->CharacterID());
//results = database.QueryDatabase(query); i = 0;
//int offset = 0; // offset to fix the hole from expendables
//for (auto row = results.begin(); row != results.end(); ++row) {
// i = atoi(row[0]) - offset;
// m_pp.aa_array[i].AA = atoi(row[1]);
// m_pp.aa_array[i].value = atoi(row[2]);
// m_pp.aa_array[i].charges = atoi(row[3]);
// /* A used expendable could cause there to be a "hole" in the array, this is very bad. Bad things like keeping your expendable after use.
// We could do a few things, one of them being reshuffling when the hole is created or defer the fixing until a later point, like during load!
// Or just never making a hole in the array and just have hacks every where. Fixing the hole at load really just keeps 1 hack in Client::SendAATable
// and keeping this offset that will cause the next AA to be pushed back over the hole. We also need to clean up on save so we don't have multiple
// entries for a single AA.
// */
// if (m_pp.aa_array[i].value == 0)
// offset++;
//}
//for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++){
// uint32 id = aa[a]->AA;
// //watch for invalid AA IDs
// if (id == aaNone)
// continue;
// if (id >= aaHighestID) {
// aa[a]->AA = aaNone;
// aa[a]->value = 0;
// continue;
// }
// if (aa[a]->value == 0) {
// aa[a]->AA = aaNone;
// continue;
// }
// if (aa[a]->value > HIGHEST_AA_VALUE) {
// aa[a]->AA = aaNone;
// aa[a]->value = 0;
// continue;
// }
//
// //aa old
// // if (aa[a]->value > 1) /* hack in some stuff for sony's new AA method (where each level of each aa.has a seperate ID) */
// // aa_points[(id - aa[a]->value + 1)] = aa[a]->value;
// // else
// // aa_points[id] = aa[a]->value;
//}
if (SPDAT_RECORDS > 0) {
for (uint32 z = 0; z<MAX_PP_MEMSPELL; z++) {

View File

@ -23,6 +23,7 @@
#include "hate_list.h"
#include "pathing.h"
#include "position.h"
#include "aa_ability.h"
#include <set>
#include <vector>
#include <memory>
@ -860,7 +861,6 @@ public:
uint32 GetZoneID() const; //for perl
virtual int32 CheckAggroAmount(uint16 spell_id, bool isproc = false);
virtual int32 CheckHealAggroAmount(uint16 spell_id, uint32 heal_possible = 0);
virtual uint32 GetAA(uint32 aa_id) const { return(0); }
uint32 GetInstrumentMod(uint16 spell_id) const;
int CalcSpellEffectValue(uint16 spell_id, int effect_id, int caster_level = 1, uint32 instrument_mod = 10, Mob *caster = nullptr, int ticsremaining = 0);
@ -956,6 +956,12 @@ public:
void Tune_FindAccuaryByHitChance(Mob* defender, Mob *attacker, float hit_chance, int interval, int max_loop, int avoid_override, int Msg = 0);
void Tune_FindAvoidanceByHitChance(Mob* defender, Mob *attacker, float hit_chance, int interval, int max_loop, int acc_override, int Msg = 0);
//aa new
uint32 GetAA(uint32 rank_id) const;
bool SetAA(uint32 rank_id, uint32 new_value);
bool CanUseAlternateAdvancementRank(AA::Rank *rank);
bool CanPurchaseAlternateAdvancementRank(AA::Rank *ran);
protected:
void CommonDamage(Mob* other, int32 &damage, const uint16 spell_id, const SkillUseTypes attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic);
static uint16 GetProcID(uint16 spell_id, uint8 effect_index);
@ -969,7 +975,6 @@ protected:
virtual bool AI_PursueCastCheck() { return(false); }
virtual bool AI_IdleCastCheck() { return(false); }
bool IsFullHP;
bool moved;
@ -1311,6 +1316,8 @@ protected:
bool bEnraged;
bool destructibleobject;
std::unordered_map<uint32, uint32> aa_ranks;
private:
void _StopSong(); //this is not what you think it is
Mob* target;

View File

@ -5231,24 +5231,25 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) {
uint32 aa_AA = 0;
uint32 aa_value = 0;
for (int i = 0; i < MAX_PP_AA_ARRAY; i++)
{
aa_AA = this->aa[i]->AA;
aa_value = this->aa[i]->value;
if (aa_AA < 1 || aa_value < 1)
continue;
if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS)
continue;
proc_spellid = CalcAAFocus(type, aa_AA, spell_id);
if (IsValidSpell(proc_spellid)){
ProcChance = GetSympatheticProcChances(spell_id, GetAABase1(aa_AA, 1));
if(zone->random.Roll(ProcChance))
SympatheticProcList.push_back(proc_spellid);
}
}
//aa old
//for (int i = 0; i < MAX_PP_AA_ARRAY; i++)
//{
// aa_AA = this->aa[i]->AA;
// aa_value = this->aa[i]->value;
// if (aa_AA < 1 || aa_value < 1)
// continue;
//
// if (SympatheticProcList.size() > MAX_SYMPATHETIC_PROCS)
// continue;
//
// proc_spellid = CalcAAFocus(type, aa_AA, spell_id);
//
// if (IsValidSpell(proc_spellid)){
// ProcChance = GetSympatheticProcChances(spell_id, GetAABase1(aa_AA, 1));
// if(zone->random.Roll(ProcChance))
// SympatheticProcList.push_back(proc_spellid);
// }
//}
}
if (SympatheticProcList.size() > 0)
@ -5503,21 +5504,22 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) {
uint32 aa_AA = 0;
uint32 aa_value = 0;
for (int i = 0; i < MAX_PP_AA_ARRAY; i++)
{
aa_AA = this->aa[i]->AA;
aa_value = this->aa[i]->value;
if (aa_AA < 1 || aa_value < 1)
continue;
Total3 = CalcAAFocus(type, aa_AA, spell_id);
if (Total3 > 0 && realTotal3 >= 0 && Total3 > realTotal3) {
realTotal3 = Total3;
}
else if (Total3 < 0 && Total3 < realTotal3) {
realTotal3 = Total3;
}
}
//aa old
//for (int i = 0; i < MAX_PP_AA_ARRAY; i++)
//{
// aa_AA = this->aa[i]->AA;
// aa_value = this->aa[i]->value;
// if (aa_AA < 1 || aa_value < 1)
// continue;
//
// Total3 = CalcAAFocus(type, aa_AA, spell_id);
// if (Total3 > 0 && realTotal3 >= 0 && Total3 > realTotal3) {
// realTotal3 = Total3;
// }
// else if (Total3 < 0 && Total3 < realTotal3) {
// realTotal3 = Total3;
// }
//}
}
if(type == focusReagentCost && IsSummonPetSpell(spell_id) && GetAA(aaElementalPact))

View File

@ -117,6 +117,7 @@ public:
//new AA
void LoadAlternateAdvancement();
AA::Ability *GetAlternateAdvancementAbility(int id);
AA::Ability *GetAlternateAdvancementAbilityByRank(int rank_id);
AA::Rank *GetAlternateAdvancementRank(int rank_id);
//old AA