mirror of
https://github.com/EQEmu/Server.git
synced 2026-04-13 19:12:26 +00:00
Fix exploit with expendable AAs
This commit is contained in:
parent
db307d865b
commit
6229b90451
@ -3,6 +3,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
|||||||
== 06/07/2015 ==
|
== 06/07/2015 ==
|
||||||
Uleat: Implemented optional rule for using disenchanted bags. Action triggers at the same point that temporary items are removed.
|
Uleat: Implemented optional rule for using disenchanted bags. Action triggers at the same point that temporary items are removed.
|
||||||
Optional SQL: utils/sql/git/optional/2015_06_07_TransformSummonedBagsRule.sql
|
Optional SQL: utils/sql/git/optional/2015_06_07_TransformSummonedBagsRule.sql
|
||||||
|
mackal: changes to AA packets since more fields have been identified
|
||||||
|
mackal: fix exploit with expendable AAs punching holes in the aa_array and staying around longer than they are welcomed
|
||||||
|
|
||||||
== 05/25/2015 ==
|
== 05/25/2015 ==
|
||||||
Akkadius: Implemented disjointed zone based time, this can be triggered via quest methods
|
Akkadius: Implemented disjointed zone based time, this can be triggered via quest methods
|
||||||
|
|||||||
12
zone/aa.cpp
12
zone/aa.cpp
@ -1104,7 +1104,7 @@ void Client::SendAATable() {
|
|||||||
|
|
||||||
uint32 i;
|
uint32 i;
|
||||||
for(i=0;i < MAX_PP_AA_ARRAY;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].value = aa[i]->value;
|
||||||
aa2->aa_list[i].charges = aa[i]->charges;
|
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;
|
aa[cur]->value = new_value;
|
||||||
if(new_value > 0)
|
if(new_value > 0)
|
||||||
aa[cur]->AA++;
|
aa[cur]->AA++;
|
||||||
else
|
|
||||||
aa[cur]->AA = 0;
|
|
||||||
aa[cur]->charges = charges;
|
aa[cur]->charges = charges;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1411,8 +1409,12 @@ bool Client::SetAA(uint32 aa_id, uint32 new_value) {
|
|||||||
aa[cur]->value = new_value;
|
aa[cur]->value = new_value;
|
||||||
if(new_value > 0)
|
if(new_value > 0)
|
||||||
aa[cur]->AA++;
|
aa[cur]->AA++;
|
||||||
else
|
aa[cur]->charges = charges;
|
||||||
aa[cur]->AA = 0;
|
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;
|
aa[cur]->charges = charges;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -549,17 +549,22 @@ bool Client::SaveAA(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_pp.aapoints_spent = spentpoints + m_epp.expended_aa;
|
m_pp.aapoints_spent = spentpoints + m_epp.expended_aa;
|
||||||
|
int highest = 0;
|
||||||
for (int a = 0; a < MAX_PP_AA_ARRAY; a++) {
|
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 (aa[a]->AA > 0) { // those with value 0 will be cleaned up on next load
|
||||||
if (first_entry != 1){
|
if (first_entry != 1){
|
||||||
rquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, slot, aa_id, aa_value, charges)"
|
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);
|
" VALUES (%u, %u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value, aa[a]->charges);
|
||||||
first_entry = 1;
|
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);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1452,11 +1452,20 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
|||||||
"`character_alternate_abilities` "
|
"`character_alternate_abilities` "
|
||||||
"WHERE `id` = %u ORDER BY `slot`", this->CharacterID());
|
"WHERE `id` = %u ORDER BY `slot`", this->CharacterID());
|
||||||
results = database.QueryDatabase(query); i = 0;
|
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) {
|
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].AA = atoi(row[1]);
|
||||||
m_pp.aa_array[i].value = atoi(row[2]);
|
m_pp.aa_array[i].value = atoi(row[2]);
|
||||||
m_pp.aa_array[i].charges = atoi(row[3]);
|
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++){
|
for (uint32 a = 0; a < MAX_PP_AA_ARRAY; a++){
|
||||||
uint32 id = aa[a]->AA;
|
uint32 id = aa[a]->AA;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user