Fix exploit with expendable AAs

This commit is contained in:
Michael Cook (mackal) 2015-06-08 02:00:44 -04:00
parent db307d865b
commit 6229b90451
4 changed files with 233 additions and 215 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1104,7 +1104,7 @@ void Client::SendAATable() {
uint32 i;
for(i=0;i < MAX_PP_AA_ARRAY;i++){
aa2->aa_list[i].AA = aa[i]->AA;
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;
}
@ -1402,8 +1402,6 @@ bool Client::SetAA(uint32 aa_id, uint32 new_value) {
aa[cur]->value = new_value;
if(new_value > 0)
aa[cur]->AA++;
else
aa[cur]->AA = 0;
aa[cur]->charges = charges;
return true;
}
@ -1411,8 +1409,12 @@ bool Client::SetAA(uint32 aa_id, uint32 new_value) {
aa[cur]->value = new_value;
if(new_value > 0)
aa[cur]->AA++;
else
aa[cur]->AA = 0;
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;
}

View File

@ -549,17 +549,22 @@ bool Client::SaveAA(){
}
}
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);
}
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

@ -1452,11 +1452,20 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
"`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]);
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;