Merge conflicts abound and now are fixed

This commit is contained in:
KimLS 2015-07-02 20:12:51 -07:00
commit 214873c139
67 changed files with 24488 additions and 5020 deletions

View File

@ -150,4 +150,26 @@ static ClientVersion ClientVersionFromBit(uint32 clientVersionBit)
}
}
static uint32 ExpansionFromClientVersion(ClientVersion clientVersion)
{
switch(clientVersion)
{
case ClientVersion::Unknown:
case ClientVersion::Client62:
case ClientVersion::Titanium:
return 0x000007FFU;
case ClientVersion::SoF:
return 0x00007FFFU;
case ClientVersion::SoD:
return 0x0000FFFFU;
case ClientVersion::UF:
return 0x0001FFFFU;
case ClientVersion::RoF:
case ClientVersion::RoF2:
return 0x000FFFFFU;
default:
return 0;
}
}
#endif /* CLIENTVERSIONS_H */

View File

@ -548,4 +548,5 @@ N(OP_ZoneServerInfo),
N(OP_ZoneServerReady),
N(OP_ZoneSpawns),
N(OP_ZoneUnavail),
N(OP_ResetAA),
// mail and chat opcodes located in ../mail_oplist.h

View File

@ -4219,6 +4219,52 @@ struct UseAA_Struct {
uint32 end;
};
//new AA stuff
//reference only
struct AARankInfo_Struct
{
uint32 id;
int32 upper_hotkey_sid;
int32 lower_hotkey_sid;
int32 title_sid;
int32 desc_sid;
int32 level_req;
int32 cost;
uint32 seq;
uint32 current_level;
uint32 type;
int32 spell;
int32 spell_type;
int32 spell_refresh;
int32 classes;
int32 max_level;
int32 prev_id;
int32 next_id;
int32 total_cost;
int32 expansion;
int32 category;
uint32 charges;
uint8 grant_only;
uint32 total_effects;
uint32 total_prereqs;
};
struct AARankPrereq_Struct
{
int32 aa_id;
int32 points;
};
struct AARankEffect_Struct
{
int32 effect_id;
int32 base1;
int32 base2;
int32 slot;
};
//old AA stuff
struct AA_Ability {
/*00*/ uint32 skill_id;
/*04*/ uint32 base1;
@ -4273,7 +4319,7 @@ struct SendAA_Struct {
struct AA_Action {
/*00*/ uint32 action;
/*04*/ uint32 ability;
/*08*/ uint32 unknown08;
/*08*/ uint32 target_id;
/*12*/ uint32 exp_value;
};

View File

@ -2810,7 +2810,7 @@ namespace RoF
eq->aa_spent = emu->aa_spent;
// These fields may need to be correctly populated at some point
eq->aapoints_assigned = emu->aa_spent + 1;
eq->aapoints_assigned = emu->aa_spent;
eq->aa_spent_general = 0;
eq->aa_spent_archetype = 0;
eq->aa_spent_class = 0;
@ -2846,58 +2846,81 @@ namespace RoF
ENCODE(OP_SendAATable)
{
ENCODE_LENGTH_ATLEAST(SendAA_Struct);
SETUP_VAR_ENCODE(SendAA_Struct);
ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability));
EQApplicationPacket *inapp = *p;
*p = nullptr;
AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer;
// Check clientver field to verify this AA should be sent for SoF
// clientver 1 is for all clients and 5 is for Live
if (emu->clientver <= 7)
{
OUT(id);
eq->unknown004 = 1;
//eq->hotkey_sid = (emu->hotkey_sid==4294967295UL)?0:(emu->id - emu->current_level + 1);
//eq->hotkey_sid2 = (emu->hotkey_sid2==4294967295UL)?0:(emu->id - emu->current_level + 1);
//eq->title_sid = emu->id - emu->current_level + 1;
//eq->desc_sid = emu->id - emu->current_level + 1;
eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? -1 : (emu->sof_next_skill);
eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? -1 : (emu->sof_next_skill);
eq->title_sid = emu->sof_next_skill;
eq->desc_sid = emu->sof_next_skill;
OUT(class_type);
OUT(cost);
OUT(seq);
OUT(current_level);
eq->prereq_skill_count = 1; // min 1
OUT(prereq_skill);
eq->prereq_minpoints_count = 1; // min 1
OUT(prereq_minpoints);
eq->type = emu->sof_type;
OUT(spellid);
eq->unknown057 = 1; // Introduced during HoT
OUT(spell_type);
OUT(spell_refresh);
OUT(classes);
OUT(berserker);
//eq->max_level = emu->sof_max_level;
OUT(max_level);
OUT(last_id);
OUT(next_id);
OUT(cost2);
eq->aa_expansion = emu->aa_expansion;
eq->special_category = emu->special_category;
eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number
OUT(total_abilities);
unsigned int r;
for (r = 0; r < emu->total_abilities; r++) {
OUT(abilities[r].skill_id);
OUT(abilities[r].base1);
OUT(abilities[r].base2);
OUT(abilities[r].slot);
}
// the structs::SendAA_Struct includes enough space for 1 prereq which is the min even if it has no prereqs
auto prereq_size = emu->total_prereqs > 1 ? (emu->total_prereqs - 1) * 8 : 0;
auto outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability) + prereq_size);
inapp->SetReadPosition(sizeof(AARankInfo_Struct)+emu->total_effects * sizeof(AARankEffect_Struct));
std::vector<int32> skill;
std::vector<int32> points;
for(auto i = 0; i < emu->total_prereqs; ++i) {
skill.push_back(inapp->ReadUInt32());
points.push_back(inapp->ReadUInt32());
}
FINISH_ENCODE();
outapp->WriteUInt32(emu->id);
outapp->WriteUInt8(1);
outapp->WriteSInt32(emu->upper_hotkey_sid);
outapp->WriteSInt32(emu->lower_hotkey_sid);
outapp->WriteSInt32(emu->title_sid);
outapp->WriteSInt32(emu->desc_sid);
outapp->WriteSInt32(emu->level_req);
outapp->WriteSInt32(emu->cost);
outapp->WriteUInt32(emu->seq);
outapp->WriteUInt32(emu->current_level);
if(emu->total_prereqs) {
outapp->WriteUInt32(emu->total_prereqs);
for(auto &e : skill)
outapp->WriteSInt32(e);
outapp->WriteUInt32(emu->total_prereqs);
for(auto &e : points)
outapp->WriteSInt32(e);
}
else {
outapp->WriteUInt32(1);
outapp->WriteUInt32(0);
outapp->WriteUInt32(1);
outapp->WriteUInt32(0);
}
outapp->WriteSInt32(emu->type);
outapp->WriteSInt32(emu->spell);
outapp->WriteSInt32(1);
outapp->WriteSInt32(emu->spell_type);
outapp->WriteSInt32(emu->spell_refresh);
outapp->WriteSInt32(emu->classes);
outapp->WriteSInt32(emu->max_level);
outapp->WriteSInt32(emu->prev_id);
outapp->WriteSInt32(emu->next_id);
outapp->WriteSInt32(emu->total_cost);
outapp->WriteUInt8(0);
outapp->WriteUInt8(emu->grant_only);
outapp->WriteUInt8(0);
outapp->WriteUInt32(emu->charges);
outapp->WriteSInt32(emu->expansion);
outapp->WriteSInt32(emu->category);
outapp->WriteUInt8(0); // shroud
outapp->WriteUInt8(0); // unknown109
outapp->WriteUInt8(0); // loh
outapp->WriteUInt8(0); // unknown111
outapp->WriteUInt32(emu->total_effects);
inapp->SetReadPosition(sizeof(AARankInfo_Struct));
for(auto i = 0; i < emu->total_effects; ++i) {
outapp->WriteUInt32(inapp->ReadUInt32()); // skill_id
outapp->WriteUInt32(inapp->ReadUInt32()); // base1
outapp->WriteUInt32(inapp->ReadUInt32()); // base2
outapp->WriteUInt32(inapp->ReadUInt32()); // slot
}
dest->FastQueuePacket(&outapp);
delete inapp;
}
ENCODE(OP_SendCharInfo)

View File

@ -2466,7 +2466,8 @@ namespace RoF2
outapp->WriteUInt32(emu->lastlogin);
outapp->WriteUInt32(emu->timePlayedMin);
outapp->WriteUInt32(emu->timeentitledonaccount);
outapp->WriteUInt32(0x0007ffff); // Expansion bitmask
outapp->WriteUInt32(emu->expansions);
//outapp->WriteUInt32(0x0007ffff); // Expansion bitmask
outapp->WriteUInt32(structs::MAX_PP_LANGUAGE);
@ -2899,7 +2900,7 @@ namespace RoF2
eq->aa_spent = emu->aa_spent;
// These fields may need to be correctly populated at some point
eq->aapoints_assigned = emu->aa_spent + 1;
eq->aapoints_assigned = emu->aa_spent;
eq->aa_spent_general = 0;
eq->aa_spent_archetype = 0;
eq->aa_spent_class = 0;
@ -2935,58 +2936,80 @@ namespace RoF2
ENCODE(OP_SendAATable)
{
ENCODE_LENGTH_ATLEAST(SendAA_Struct);
SETUP_VAR_ENCODE(SendAA_Struct);
ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability));
EQApplicationPacket *inapp = *p;
*p = nullptr;
AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer;
// the structs::SendAA_Struct includes enough space for 1 prereq which is the min even if it has no prereqs
auto prereq_size = emu->total_prereqs > 1 ? (emu->total_prereqs - 1) * 8 : 0;
auto outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability) + prereq_size);
inapp->SetReadPosition(sizeof(AARankInfo_Struct)+emu->total_effects * sizeof(AARankEffect_Struct));
// Check clientver field to verify this AA should be sent for SoF
// clientver 1 is for all clients and 5 is for Live
if (emu->clientver <= 8)
{
OUT(id);
eq->unknown004 = 1;
//eq->hotkey_sid = (emu->hotkey_sid==4294967295UL)?0:(emu->id - emu->current_level + 1);
//eq->hotkey_sid2 = (emu->hotkey_sid2==4294967295UL)?0:(emu->id - emu->current_level + 1);
//eq->title_sid = emu->id - emu->current_level + 1;
//eq->desc_sid = emu->id - emu->current_level + 1;
eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? -1 : (emu->sof_next_skill);
eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? -1 : (emu->sof_next_skill);
eq->title_sid = emu->sof_next_skill;
eq->desc_sid = emu->sof_next_skill;
OUT(class_type);
OUT(cost);
OUT(seq);
OUT(current_level);
eq->prereq_skill_count = 1; // min 1
OUT(prereq_skill);
eq->prereq_minpoints_count = 1; // min 1
OUT(prereq_minpoints);
eq->type = emu->sof_type;
OUT(spellid);
eq->unknown057 = 1; // Introduced during HoT
OUT(spell_type);
OUT(spell_refresh);
OUT(classes);
OUT(berserker);
//eq->max_level = emu->sof_max_level;
OUT(max_level);
OUT(last_id);
OUT(next_id);
OUT(cost2);
eq->aa_expansion = emu->aa_expansion;
eq->special_category = emu->special_category;
OUT(total_abilities);
eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number
unsigned int r;
for (r = 0; r < emu->total_abilities; r++) {
OUT(abilities[r].skill_id);
OUT(abilities[r].base1);
OUT(abilities[r].base2);
OUT(abilities[r].slot);
}
std::vector<int32> skill;
std::vector<int32> points;
for(auto i = 0; i < emu->total_prereqs; ++i) {
skill.push_back(inapp->ReadUInt32());
points.push_back(inapp->ReadUInt32());
}
FINISH_ENCODE();
outapp->WriteUInt32(emu->id);
outapp->WriteUInt8(1);
outapp->WriteSInt32(emu->upper_hotkey_sid);
outapp->WriteSInt32(emu->lower_hotkey_sid);
outapp->WriteSInt32(emu->title_sid);
outapp->WriteSInt32(emu->desc_sid);
outapp->WriteSInt32(emu->level_req);
outapp->WriteSInt32(emu->cost);
outapp->WriteUInt32(emu->seq);
outapp->WriteUInt32(emu->current_level);
if (emu->total_prereqs) {
outapp->WriteUInt32(emu->total_prereqs);
for (auto &e : skill)
outapp->WriteSInt32(e);
outapp->WriteUInt32(emu->total_prereqs);
for (auto &e : points)
outapp->WriteSInt32(e);
} else {
outapp->WriteUInt32(1);
outapp->WriteUInt32(0);
outapp->WriteUInt32(1);
outapp->WriteUInt32(0);
}
outapp->WriteSInt32(emu->type);
outapp->WriteSInt32(emu->spell);
outapp->WriteSInt32(1);
outapp->WriteSInt32(emu->spell_type);
outapp->WriteSInt32(emu->spell_refresh);
outapp->WriteSInt32(emu->classes);
outapp->WriteSInt32(emu->max_level);
outapp->WriteSInt32(emu->prev_id);
outapp->WriteSInt32(emu->next_id);
outapp->WriteSInt32(emu->total_cost);
outapp->WriteUInt8(0);
outapp->WriteUInt8(emu->grant_only);
outapp->WriteUInt8(0);
outapp->WriteUInt32(emu->charges);
outapp->WriteSInt32(emu->expansion);
outapp->WriteSInt32(emu->category);
outapp->WriteUInt8(0); // shroud
outapp->WriteUInt8(0); // unknown109
outapp->WriteUInt8(0); // loh
outapp->WriteUInt8(0); // unknown111
outapp->WriteUInt32(emu->total_effects);
inapp->SetReadPosition(sizeof(AARankInfo_Struct));
for(auto i = 0; i < emu->total_effects; ++i) {
outapp->WriteUInt32(inapp->ReadUInt32()); // skill_id
outapp->WriteUInt32(inapp->ReadUInt32()); // base1
outapp->WriteUInt32(inapp->ReadUInt32()); // base2
outapp->WriteUInt32(inapp->ReadUInt32()); // slot
}
dest->FastQueuePacket(&outapp);
delete inapp;
}
ENCODE(OP_SendCharInfo)

View File

@ -4289,7 +4289,7 @@ struct AA_List {
struct AA_Action {
/*00*/ uint32 action;
/*04*/ uint32 ability;
/*08*/ uint32 unknown08;
/*08*/ uint32 target_id;
/*12*/ uint32 exp_value;
/*16*/
};

View File

@ -4288,7 +4288,7 @@ struct AA_List {
struct AA_Action {
/*00*/ uint32 action;
/*04*/ uint32 ability;
/*08*/ uint32 unknown08;
/*08*/ uint32 target_id;
/*12*/ uint32 exp_value;
/*16*/
};

View File

@ -1677,8 +1677,8 @@ namespace SoD
OUT(copper_bank);
OUT(platinum_shared);
// OUT(unknown13156[84]);
//OUT(expansions);
eq->expansions = 16383;
OUT(expansions);
//eq->expansions = 16383;
// OUT(unknown13244[12]);
OUT(autosplit);
// OUT(unknown13260[16]);
@ -1862,55 +1862,56 @@ namespace SoD
ENCODE(OP_SendAATable)
{
ENCODE_LENGTH_ATLEAST(SendAA_Struct);
SETUP_VAR_ENCODE(SendAA_Struct);
ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability));
EQApplicationPacket *inapp = *p;
*p = nullptr;
AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer;
// Check clientver field to verify this AA should be sent for SoF
// clientver 1 is for all clients and 5 is for SoD
if (emu->clientver <= 5)
{
OUT(id);
eq->unknown004 = 1;
//eq->hotkey_sid = (emu->hotkey_sid==4294967295UL)?0:(emu->id - emu->current_level + 1);
//eq->hotkey_sid2 = (emu->hotkey_sid2==4294967295UL)?0:(emu->id - emu->current_level + 1);
//eq->title_sid = emu->id - emu->current_level + 1;
//eq->desc_sid = emu->id - emu->current_level + 1;
eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? 0 : (emu->sof_next_skill);
eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? 0 : (emu->sof_next_skill);
eq->title_sid = emu->sof_next_skill;
eq->desc_sid = emu->sof_next_skill;
OUT(class_type);
OUT(cost);
OUT(seq);
OUT(current_level);
OUT(prereq_skill);
OUT(prereq_minpoints);
eq->type = emu->sof_type;
OUT(spellid);
OUT(spell_type);
OUT(spell_refresh);
OUT(classes);
OUT(berserker);
//eq->max_level = emu->sof_max_level;
OUT(max_level);
OUT(last_id);
OUT(next_id);
OUT(cost2);
eq->aa_expansion = emu->aa_expansion;
eq->special_category = emu->special_category;
eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number
OUT(total_abilities);
unsigned int r;
for (r = 0; r < emu->total_abilities; r++) {
OUT(abilities[r].skill_id);
OUT(abilities[r].base1);
OUT(abilities[r].base2);
OUT(abilities[r].slot);
}
EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability));
structs::SendAA_Struct *eq = (structs::SendAA_Struct*)outapp->pBuffer;
inapp->SetReadPosition(sizeof(AARankInfo_Struct));
outapp->SetWritePosition(sizeof(structs::SendAA_Struct));
eq->id = emu->id;
eq->unknown004 = 1;
eq->id = emu->id;
eq->hotkey_sid = emu->upper_hotkey_sid;
eq->hotkey_sid2 = emu->lower_hotkey_sid;
eq->desc_sid = emu->desc_sid;
eq->title_sid = emu->title_sid;
eq->class_type = emu->level_req;
eq->cost = emu->cost;
eq->seq = emu->seq;
eq->current_level = emu->current_level;
eq->type = emu->type;
eq->spellid = emu->spell;
eq->spell_type = emu->spell_type;
eq->spell_refresh = emu->spell_refresh;
eq->classes = emu->classes;
eq->max_level = emu->max_level;
eq->last_id = emu->prev_id;
eq->next_id = emu->next_id;
eq->cost2 = emu->total_cost;
eq->grant_only = emu->grant_only;
eq->expendable_charges = emu->charges;
eq->aa_expansion = emu->expansion;
eq->special_category = emu->category;
eq->total_abilities = emu->total_effects;
for(auto i = 0; i < eq->total_abilities; ++i) {
eq->abilities[i].skill_id = inapp->ReadUInt32();
eq->abilities[i].base1 = inapp->ReadUInt32();
eq->abilities[i].base2 = inapp->ReadUInt32();
eq->abilities[i].slot = inapp->ReadUInt32();
}
FINISH_ENCODE();
if(emu->total_prereqs > 0) {
eq->prereq_skill = inapp->ReadUInt32();
eq->prereq_minpoints = inapp->ReadUInt32();
}
dest->FastQueuePacket(&outapp);
delete inapp;
}
ENCODE(OP_SendCharInfo)

View File

@ -3813,8 +3813,7 @@ struct SendAA_Struct {
/*0049*/ uint32 spellid;
/*0053*/ uint32 spell_type;
/*0057*/ uint32 spell_refresh;
/*0061*/ uint16 classes;
/*0063*/ uint16 berserker; //seems to be 1 if its a berserker ability
/*0061*/ uint32 classes;
/*0065*/ uint32 max_level;
/*0069*/ uint32 last_id;
/*0073*/ uint32 next_id;
@ -3840,7 +3839,7 @@ struct AA_List {
struct AA_Action {
/*00*/ uint32 action;
/*04*/ uint32 ability;
/*08*/ uint32 unknown08;
/*08*/ uint32 target_id;
/*12*/ uint32 exp_value;
};

View File

@ -1335,8 +1335,8 @@ namespace SoF
OUT(copper_bank);
OUT(platinum_shared);
// OUT(unknown13156[84]);
//OUT(expansions);
eq->expansions = 16383;
OUT(expansions);
//eq->expansions = 16383;
// OUT(unknown13244[12]);
OUT(autosplit);
// OUT(unknown13260[16]);
@ -1520,56 +1520,56 @@ namespace SoF
ENCODE(OP_SendAATable)
{
ENCODE_LENGTH_ATLEAST(SendAA_Struct);
EQApplicationPacket *inapp = *p;
*p = nullptr;
AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer;
SETUP_VAR_ENCODE(SendAA_Struct);
ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability));
EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability));
structs::SendAA_Struct *eq = (structs::SendAA_Struct*)outapp->pBuffer;
// Check clientver field to verify this AA should be sent for SoF
// clientver 1 is for all clients and 4 is for SoF
if (emu->clientver <= 4)
{
OUT(id);
eq->unknown004 = 1;
//eq->hotkey_sid = (emu->hotkey_sid==4294967295UL)?0:(emu->id - emu->current_level + 1);
//eq->hotkey_sid2 = (emu->hotkey_sid2==4294967295UL)?0:(emu->id - emu->current_level + 1);
//eq->title_sid = emu->id - emu->current_level + 1;
//eq->desc_sid = emu->id - emu->current_level + 1;
eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? 0 : (emu->sof_next_skill);
eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? 0 : (emu->sof_next_skill);
eq->title_sid = emu->sof_next_skill;
eq->desc_sid = emu->sof_next_skill;
OUT(class_type);
OUT(cost);
OUT(seq);
OUT(current_level);
OUT(prereq_skill);
OUT(prereq_minpoints);
eq->type = emu->sof_type;
OUT(spellid);
OUT(spell_type);
OUT(spell_refresh);
OUT(classes);
OUT(berserker);
//eq->max_level = emu->sof_max_level;
OUT(max_level);
OUT(last_id);
OUT(next_id);
OUT(cost2);
eq->aa_expansion = emu->aa_expansion;
eq->special_category = emu->special_category;
eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number
OUT(total_abilities);
unsigned int r;
for (r = 0; r < emu->total_abilities; r++) {
OUT(abilities[r].skill_id);
OUT(abilities[r].base1);
OUT(abilities[r].base2);
OUT(abilities[r].slot);
}
inapp->SetReadPosition(sizeof(AARankInfo_Struct));
outapp->SetWritePosition(sizeof(structs::SendAA_Struct));
eq->id = emu->id;
eq->unknown004 = 1;
eq->id = emu->id;
eq->hotkey_sid = emu->upper_hotkey_sid;
eq->hotkey_sid2 = emu->lower_hotkey_sid;
eq->desc_sid = emu->desc_sid;
eq->title_sid = emu->title_sid;
eq->class_type = emu->level_req;
eq->cost = emu->cost;
eq->seq = emu->seq;
eq->current_level = emu->current_level;
eq->type = emu->type;
eq->spellid = emu->spell;
eq->spell_type = emu->spell_type;
eq->spell_refresh = emu->spell_refresh;
eq->classes = emu->classes;
eq->max_level = emu->max_level;
eq->last_id = emu->prev_id;
eq->next_id = emu->next_id;
eq->cost2 = emu->total_cost;
eq->grant_only = emu->grant_only;
eq->expendable_charges = emu->charges;
eq->aa_expansion = emu->expansion;
eq->special_category = emu->category;
eq->total_abilities = emu->total_effects;
for(auto i = 0; i < eq->total_abilities; ++i) {
eq->abilities[i].skill_id = inapp->ReadUInt32();
eq->abilities[i].base1 = inapp->ReadUInt32();
eq->abilities[i].base2 = inapp->ReadUInt32();
eq->abilities[i].slot = inapp->ReadUInt32();
}
FINISH_ENCODE();
if(emu->total_prereqs > 0) {
eq->prereq_skill = inapp->ReadUInt32();
eq->prereq_minpoints = inapp->ReadUInt32();
}
dest->FastQueuePacket(&outapp);
delete inapp;
}
ENCODE(OP_SendCharInfo)
@ -1665,8 +1665,6 @@ namespace SoF
emu_ptr += sizeof(CharacterSelectEntry_Struct);
eq_ptr += sizeof(structs::CharacterSelectEntry_Struct);
}
FINISH_ENCODE();
}
//hack hack hack

View File

@ -3677,8 +3677,7 @@ struct SendAA_Struct {
/*0049*/ uint32 spellid;
/*0053*/ uint32 spell_type;
/*0057*/ uint32 spell_refresh;
/*0061*/ uint16 classes;
/*0063*/ uint16 berserker; //seems to be 1 if its a berserker ability
/*0061*/ uint32 classes;
/*0065*/ uint32 max_level;
/*0069*/ uint32 last_id;
/*0073*/ uint32 next_id;
@ -3702,7 +3701,7 @@ struct AA_List {
struct AA_Action {
/*00*/ uint32 action;
/*04*/ uint32 ability;
/*08*/ uint32 unknown08;
/*08*/ uint32 target_id;
/*12*/ uint32 exp_value;
};

View File

@ -1107,50 +1107,52 @@ namespace Titanium
ENCODE(OP_SendAATable)
{
ENCODE_LENGTH_ATLEAST(SendAA_Struct);
EQApplicationPacket *inapp = *p;
*p = nullptr;
AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer;
SETUP_VAR_ENCODE(SendAA_Struct);
ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability));
EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability));
structs::SendAA_Struct *eq = (structs::SendAA_Struct*)outapp->pBuffer;
// Check clientver field to verify this AA should be sent for Titanium
// clientver 1 is for all clients and 3 is for Titanium
if (emu->clientver <= 3)
{
OUT(id);
eq->unknown004 = 1;
eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? 0 : (emu->id - emu->current_level + 1);
eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? 0 : (emu->id - emu->current_level + 1);
eq->title_sid = emu->id - emu->current_level + 1;
eq->desc_sid = emu->id - emu->current_level + 1;
OUT(class_type);
OUT(cost);
OUT(seq);
OUT(current_level);
OUT(prereq_skill);
OUT(prereq_minpoints);
OUT(type);
OUT(spellid);
OUT(spell_type);
OUT(spell_refresh);
OUT(classes);
OUT(berserker);
OUT(max_level);
OUT(last_id);
OUT(next_id);
OUT(cost2);
OUT(unknown80[0]);
OUT(unknown80[1]);
OUT(total_abilities);
unsigned int r;
for (r = 0; r < emu->total_abilities; r++) {
OUT(abilities[r].skill_id);
OUT(abilities[r].base1);
OUT(abilities[r].base2);
OUT(abilities[r].slot);
}
inapp->SetReadPosition(sizeof(AARankInfo_Struct));
outapp->SetWritePosition(sizeof(structs::SendAA_Struct));
eq->id = emu->id;
eq->unknown004 = 1;
eq->id = emu->id;
eq->hotkey_sid = emu->upper_hotkey_sid;
eq->hotkey_sid2 = emu->lower_hotkey_sid;
eq->desc_sid = emu->desc_sid;
eq->title_sid = emu->title_sid;
eq->class_type = emu->level_req;
eq->cost = emu->cost;
eq->seq = emu->seq;
eq->current_level = emu->current_level;
eq->type = emu->type;
eq->spellid = emu->spell;
eq->spell_type = emu->spell_type;
eq->spell_refresh = emu->spell_refresh;
eq->classes = emu->classes;
eq->max_level = emu->max_level;
eq->last_id = emu->prev_id;
eq->next_id = emu->next_id;
eq->cost2 = emu->total_cost;
eq->total_abilities = emu->total_effects;
for(auto i = 0; i < eq->total_abilities; ++i) {
eq->abilities[i].skill_id = inapp->ReadUInt32();
eq->abilities[i].base1 = inapp->ReadUInt32();
eq->abilities[i].base2 = inapp->ReadUInt32();
eq->abilities[i].slot = inapp->ReadUInt32();
}
FINISH_ENCODE();
if(emu->total_prereqs > 0) {
eq->prereq_skill = inapp->ReadUInt32();
eq->prereq_minpoints = inapp->ReadUInt32();
}
dest->FastQueuePacket(&outapp);
delete inapp;
}
ENCODE(OP_SendCharInfo)

View File

@ -3157,8 +3157,7 @@ struct SendAA_Struct {
/*0052*/ uint32 spellid;
/*0056*/ uint32 spell_type;
/*0060*/ uint32 spell_refresh;
/*0064*/ uint16 classes;
/*0066*/ uint16 berserker; //seems to be 1 if its a berserker ability
/*0064*/ uint32 classes;
/*0068*/ uint32 max_level;
/*0072*/ uint32 last_id;
/*0076*/ uint32 next_id;
@ -3175,7 +3174,7 @@ struct AA_List {
struct AA_Action {
/*00*/ uint32 action;
/*04*/ uint32 ability;
/*08*/ uint32 unknown08;
/*08*/ uint32 target_id;
/*12*/ uint32 exp_value;
};

View File

@ -1805,11 +1805,13 @@ namespace UF
//NOTE: new client supports 300 AAs, our internal rep/PP
//only supports 240..
for (r = 0; r < MAX_PP_AA_ARRAY; r++) {
OUT(aa_array[r].AA);
OUT(aa_array[r].value);
OUT(aa_array[r].charges);
eq->aa_array[r].AA = emu->aa_array[r].AA;
eq->aa_array[r].value = emu->aa_array[r].value;
eq->aa_array[r].charges = emu->aa_array[r].charges;
}
// OUT(unknown02220[4]);
OUT(mana);
OUT(cur_hp);
OUT(STR);
@ -1939,8 +1941,8 @@ namespace UF
OUT(copper_bank);
OUT(platinum_shared);
// OUT(unknown13156[84]);
//OUT(expansions);
eq->expansions = 0xffff;
OUT(expansions);
//eq->expansions = 0x1ffff;
// OUT(unknown13244[12]);
OUT(autosplit);
// OUT(unknown13260[16]);
@ -2128,7 +2130,7 @@ namespace UF
eq->aa_spent = emu->aa_spent;
eq->aa_assigned = emu->aa_spent;
eq->aa_spent3 = emu->aa_spent;
eq->aa_spent3 = 0;
eq->unknown012 = 0;
eq->unknown016 = 0;
eq->unknown020 = 0;
@ -2145,55 +2147,56 @@ namespace UF
ENCODE(OP_SendAATable)
{
ENCODE_LENGTH_ATLEAST(SendAA_Struct);
SETUP_VAR_ENCODE(SendAA_Struct);
ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability));
EQApplicationPacket *inapp = *p;
*p = nullptr;
AARankInfo_Struct *emu = (AARankInfo_Struct*)inapp->pBuffer;
// Check clientver field to verify this AA should be sent for SoF
// clientver 1 is for all clients and 6 is for Underfoot
if (emu->clientver <= 6)
{
OUT(id);
eq->unknown004 = 1;
//eq->hotkey_sid = (emu->hotkey_sid==4294967295UL)?0:(emu->id - emu->current_level + 1);
//eq->hotkey_sid2 = (emu->hotkey_sid2==4294967295UL)?0:(emu->id - emu->current_level + 1);
//eq->title_sid = emu->id - emu->current_level + 1;
//eq->desc_sid = emu->id - emu->current_level + 1;
eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? 0 : (emu->sof_next_skill);
eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? 0 : (emu->sof_next_skill);
eq->title_sid = emu->sof_next_skill;
eq->desc_sid = emu->sof_next_skill;
OUT(class_type);
OUT(cost);
OUT(seq);
OUT(current_level);
OUT(prereq_skill);
OUT(prereq_minpoints);
eq->type = emu->sof_type;
OUT(spellid);
OUT(spell_type);
OUT(spell_refresh);
OUT(classes);
OUT(berserker);
//eq->max_level = emu->sof_max_level;
OUT(max_level);
OUT(last_id);
OUT(next_id);
OUT(cost2);
eq->aa_expansion = emu->aa_expansion;
eq->special_category = emu->special_category;
eq->expendable_charges = emu->special_category == 7 ? 1 : 0; // temp hack, this can actually be any number
OUT(total_abilities);
unsigned int r;
for (r = 0; r < emu->total_abilities; r++) {
OUT(abilities[r].skill_id);
OUT(abilities[r].base1);
OUT(abilities[r].base2);
OUT(abilities[r].slot);
}
EQApplicationPacket *outapp = new EQApplicationPacket(OP_SendAATable, sizeof(structs::SendAA_Struct) + emu->total_effects * sizeof(structs::AA_Ability));
structs::SendAA_Struct *eq = (structs::SendAA_Struct*)outapp->pBuffer;
inapp->SetReadPosition(sizeof(AARankInfo_Struct));
outapp->SetWritePosition(sizeof(structs::SendAA_Struct));
eq->id = emu->id;
eq->unknown004 = 1;
eq->id = emu->id;
eq->hotkey_sid = emu->upper_hotkey_sid;
eq->hotkey_sid2 = emu->lower_hotkey_sid;
eq->desc_sid = emu->desc_sid;
eq->title_sid = emu->title_sid;
eq->class_type = emu->level_req;
eq->cost = emu->cost;
eq->seq = emu->seq;
eq->current_level = emu->current_level;
eq->type = emu->type;
eq->spellid = emu->spell;
eq->spell_type = emu->spell_type;
eq->spell_refresh = emu->spell_refresh;
eq->classes = emu->classes;
eq->max_level = emu->max_level;
eq->last_id = emu->prev_id;
eq->next_id = emu->next_id;
eq->cost2 = emu->total_cost;
eq->grant_only = emu->grant_only;
eq->expendable_charges = emu->charges;
eq->aa_expansion = emu->expansion;
eq->special_category = emu->category;
eq->total_abilities = emu->total_effects;
for(auto i = 0; i < eq->total_abilities; ++i) {
eq->abilities[i].skill_id = inapp->ReadUInt32();
eq->abilities[i].base1 = inapp->ReadUInt32();
eq->abilities[i].base2 = inapp->ReadUInt32();
eq->abilities[i].slot = inapp->ReadUInt32();
}
FINISH_ENCODE();
if(emu->total_prereqs > 0) {
eq->prereq_skill = inapp->ReadUInt32();
eq->prereq_minpoints = inapp->ReadUInt32();
}
dest->FastQueuePacket(&outapp);
delete inapp;
}
ENCODE(OP_SendCharInfo)

View File

@ -3886,8 +3886,7 @@ struct SendAA_Struct {
/*0049*/ uint32 spellid;
/*0053*/ uint32 spell_type;
/*0057*/ uint32 spell_refresh;
/*0061*/ uint16 classes;
/*0063*/ uint16 berserker; //seems to be 1 if its a berserker ability
/*0061*/ uint32 classes;
/*0065*/ uint32 max_level;
/*0069*/ uint32 last_id;
/*0073*/ uint32 next_id;
@ -3913,7 +3912,7 @@ struct AA_List {
struct AA_Action {
/*00*/ uint32 action;
/*04*/ uint32 ability;
/*08*/ uint32 unknown08;
/*08*/ uint32 target_id;
/*12*/ uint32 exp_value;
};

View File

@ -139,8 +139,4 @@ protected:
std::map<pTimerType, PersistentTimer *> _list;
};
//code prettying macros
#define AA_Choose3(val, v1, v2, v3) (val==1?v1:(val==2?v2:v3))
#define AA_Choose5(val, v1, v2, v3, v4, v5) (val==1?v1:(val==2?v2:(val==3?v3:(val==4?v4:v5))))
#endif

View File

@ -99,6 +99,7 @@ RULE_BOOL(Character, EnableXTargetting, true) // Enable Extended Targetting Wind
RULE_BOOL(Character, KeepLevelOverMax, false) // Don't delevel a character that has somehow gone over the level cap
RULE_INT(Character, FoodLossPerUpdate, 35) // How much food/water you lose per stamina update
RULE_INT(Character, BaseInstrumentSoftCap, 36) // Softcap for instrument mods, 36 commonly referred to as "3.6" as well.
RULE_BOOL(Character, UseSpellFileSongCap, true) // When they removed the AA that increased the cap they removed the above and just use the spell field
RULE_INT(Character, BaseRunSpeedCap, 158) // Base Run Speed Cap, on live it's 158% which will give you a runspeed of 1.580 hard capped to 225.
RULE_INT(Character, OrnamentationAugmentType, 20) //Ornamentation Augment Type
RULE_REAL(Character, EnvironmentDamageMulipliter, 1)
@ -185,6 +186,7 @@ RULE_INT(World, MinGMAntiHackStatus, 1) //Minimum GM status to check against Ant
RULE_INT(World, SoFStartZoneID, -1) //Sets the Starting Zone for SoF Clients separate from Titanium Clients (-1 is disabled)
RULE_INT(World, TitaniumStartZoneID, -1) //Sets the Starting Zone for Titanium Clients (-1 is disabled). Replaces the old method.
RULE_INT(World, ExpansionSettings, 16383) // Sets the expansion settings for the server, This is sent on login to world and affects client expansion settings. Defaults to all expansions enabled up to TSS.
RULE_BOOL(World, UseClientBasedExpansionSettings, true) // if true it will overrule World, ExpansionSettings and set someone's expansion based on the client they're using
RULE_INT(World, PVPSettings, 0) // Sets the PVP settings for the server, 1 = Rallos Zek RuleSet, 2 = Tallon/Vallon Zek Ruleset, 4 = Sullon Zek Ruleset, 6 = Discord Ruleset, anything above 6 is the Discord Ruleset without the no-drop restrictions removed. TODO: Edit IsAttackAllowed in Zone to accomodate for these rules.
RULE_BOOL (World, IsGMPetitionWindowEnabled, false)
RULE_INT (World, FVNoDropFlag, 0) // Sets the Firiona Vie settings on the client. If set to 2, the flag will be set for GMs only, allowing trading of no-drop items.

View File

@ -1682,6 +1682,7 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) {
sp[tempid].not_extendable = atoi(row[197]) != 0;
sp[tempid].suspendable = atoi(row[200]) != 0;
sp[tempid].viral_range = atoi(row[201]);
sp[tempid].songcap = atoi(row[202]);
sp[tempid].no_block = atoi(row[205]);
sp[tempid].spellgroup=atoi(row[207]);
sp[tempid].rank = atoi(row[208]);
@ -2021,7 +2022,7 @@ const LootDrop_Struct* SharedDatabase::GetLootDrop(uint32 lootdrop_id) {
void SharedDatabase::LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct* message) {
std::string query = StringFormat("SELECT `inspect_message` FROM `character_inspect_messages` WHERE `id` = %u LIMIT 1", character_id);
auto results = QueryDatabase(query);
auto results = QueryDatabase(query);
auto row = results.begin();
memset(message, '\0', sizeof(InspectMessage_Struct));
for (auto row = results.begin(); row != results.end(); ++row) {
@ -2031,7 +2032,7 @@ void SharedDatabase::LoadCharacterInspectMessage(uint32 character_id, InspectMes
void SharedDatabase::SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct* message) {
std::string query = StringFormat("REPLACE INTO `character_inspect_messages` (id, inspect_message) VALUES (%u, '%s')", character_id, EscapeString(message->text).c_str());
auto results = QueryDatabase(query);
auto results = QueryDatabase(query);
}
void SharedDatabase::GetBotInspectMessage(uint32 botid, InspectMessage_Struct* message) {

View File

@ -381,47 +381,47 @@ typedef enum {
#define SE_GiveDoubleAttack 225 // implemented[AA] - Allow any class to double attack with set chance.
#define SE_TwoHandBash 226 // *not implemented as bonus
#define SE_ReduceSkillTimer 227 // implemented
//#define SE_ReduceFallDamage 228 // not implented as bonus - reduce the damage that you take from falling
#define SE_ReduceFallDamage 228 // not implented as bonus - reduce the damage that you take from falling
#define SE_PersistantCasting 229 // implemented
//#define SE_ExtendedShielding 230 // not used as bonus - increase range of /shield ability
#define SE_ExtendedShielding 230 // not used as bonus - increase range of /shield ability
#define SE_StunBashChance 231 // implemented - increase chance to stun from bash.
#define SE_DivineSave 232 // implemented (base1 == % chance on death to insta-res) (base2 == spell cast on save)
#define SE_Metabolism 233 // implemented - Modifies food/drink consumption rates.
//#define SE_ReduceApplyPoisonTime 234 // not implemented as bonus - reduces the time to apply poison
#define SE_ReduceApplyPoisonTime 234 // not implemented as bonus - reduces the time to apply poison
#define SE_ChannelChanceSpells 235 // implemented[AA] - chance to channel from SPELLS *No longer used on live.
//#define SE_FreePet 236 // not used
#define SE_GivePetGroupTarget 237 // implemented[AA] - (Pet Affinity)
#define SE_IllusionPersistence 238 // implemented - lends persistence to your illusionary disguises, causing them to last until you die or the illusion is forcibly removed.
//#define SE_FeignedCastOnChance 239 // *not implemented as bonus - ability gives you an increasing chance for your feigned deaths to not be revealed by spells cast upon you.
#define SE_FeignedCastOnChance 239 // *not implemented as bonus - ability gives you an increasing chance for your feigned deaths to not be revealed by spells cast upon you.
//#define SE_StringUnbreakable 240 // not used [Likely related to above - you become immune to feign breaking on a resisted spell and have a good chance of feigning through a spell that successfully lands upon you.]
#define SE_ImprovedReclaimEnergy 241 // implemented - increase the amount of mana returned to you when reclaiming your pet.
#define SE_IncreaseChanceMemwipe 242 // implemented - increases the chance to wipe hate with memory blurr
#define SE_CharmBreakChance 243 // implemented - Total Domination
#define SE_RootBreakChance 244 // implemented[AA] reduce the chance that your root will break.
//#define SE_TrapCircumvention 245 // *not implemented[AA] - decreases the chance that you will set off a trap when opening a chest
#define SE_TrapCircumvention 245 // *not implemented[AA] - decreases the chance that you will set off a trap when opening a chest
#define SE_SetBreathLevel 246 // *not implemented as bonus
#define SE_RaiseSkillCap 247 // *not implemented[AA] - adds skill over the skill cap.
//#define SE_SecondaryForte 248 // not implemented as bonus(gives you a 2nd specialize skill that can go past 50 to 100)
#define SE_SecondaryForte 248 // not implemented as bonus(gives you a 2nd specialize skill that can go past 50 to 100)
#define SE_SecondaryDmgInc 249 // implemented[AA] Allows off hand weapon to recieve a damage bonus (Sinister Strikes)
#define SE_SpellProcChance 250 // implemented - Increase chance to proc from melee proc spells (ie Spirit of Panther)
#define SE_ConsumeProjectile 251 // implemented[AA] - chance to not consume an arrow (ConsumeProjectile = 100)
#define SE_FrontalBackstabChance 252 // implemented[AA] - chance to perform a full damage backstab from front.
#define SE_FrontalBackstabMinDmg 253 // implemented[AA] - allow a frontal backstab for mininum damage.
#define SE_Blank 254 // implemented
//#define SE_ShieldDuration 255 // not implemented as bonus - increases duration of /shield
//#define SE_ShroudofStealth 256 // not implemented as bonus - rogue improved invs
//#define SE_PetDiscipline 257 // not implemented as bonus - /pet hold
#define SE_ShieldDuration 255 // not implemented as bonus - increases duration of /shield
#define SE_ShroudofStealth 256 // not implemented as bonus - rogue improved invs
#define SE_PetDiscipline 257 // not implemented as bonus - /pet hold
#define SE_TripleBackstab 258 // implemented[AA] - chance to perform a triple backstab
#define SE_CombatStability 259 // implemented[AA] - damage mitigation
#define SE_AddSingingMod 260 // implemented[AA] - Instrument/Singing Mastery, base1 is the mod, base2 is the ItemType
#define SE_SongModCap 261 // implemented[AA] - Song Mod cap increase (no longer used on live)
#define SE_RaiseStatCap 262 // implemented
//#define SE_TradeSkillMastery 263 // not implemented - lets you raise more than one tradeskill above master.
//#define SE_HastenedAASkill 264 // not implemented as bonus - Use redux field in aa_actions table for this effect
#define SE_TradeSkillMastery 263 // not implemented - lets you raise more than one tradeskill above master.
#define SE_HastenedAASkill 264 // implemented
#define SE_MasteryofPast 265 // implemented[AA] - Spells less than effect values level can not be fizzled
#define SE_ExtraAttackChance 266 // implemented - increase chance to score an extra attack with a 2-Handed Weapon.
#define SE_PetDiscipline2 267 // *not implemented - /pet focus, /pet no cast
//#define SE_ReduceTradeskillFail 268 // *not implemented? - reduces chance to fail with given tradeskill by a percent chance
#define SE_ReduceTradeskillFail 268 // *not implemented? - reduces chance to fail with given tradeskill by a percent chance
#define SE_MaxBindWound 269 // implemented[AA] - Increase max HP you can bind wound.
#define SE_BardSongRange 270 // implemented[AA] - increase range of beneficial bard songs (Sionachie's Crescendo)
#define SE_BaseMovementSpeed 271 // implemented[AA] - mods basemove speed, doesn't stack with other move mods
@ -434,14 +434,14 @@ typedef enum {
#define SE_FinishingBlow 278 // implemented[AA] - chance to do massive damage under 10% HP (base1 = chance, base2 = damage)
#define SE_Flurry 279 // implemented
#define SE_PetFlurry 280 // implemented[AA]
//#define SE_FeignedMinion 281 // *not implemented[AA] ability allows you to instruct your pet to feign death via the '/pet feign' command. value = succeed chance
#define SE_FeignedMinion 281 // *not implemented[AA] ability allows you to instruct your pet to feign death via the '/pet feign' command. value = succeed chance
#define SE_ImprovedBindWound 282 // implemented[AA] - increase bind wound amount by percent.
#define SE_DoubleSpecialAttack 283 // implemented[AA] - Chance to perform second special attack as monk
//#define SE_LoHSetHeal 284 // not used
//#define SE_NimbleEvasion 285 // *not implemented - base1 = 100 for max
#define SE_NimbleEvasion 285 // *not implemented - base1 = 100 for max
#define SE_FcDamageAmt 286 // implemented - adds direct spell damage
#define SE_SpellDurationIncByTic 287 // implemented
#define SE_SpecialAttackKBProc 288 // implemented[AA] - Chance to to do a knockback from special attacks [AA Dragon Punch].
#define SE_SkillAttackProc 288 // implemented[AA] - Chance to proc spell on skill attack usage (ex. Dragon Punch)
#define SE_CastOnFadeEffect 289 // implemented - Triggers only if fades after natural duration.
#define SE_IncreaseRunSpeedCap 290 // implemented[AA] - increases run speed over the hard cap
#define SE_Purify 291 // implemented - Removes determental effects
@ -515,8 +515,8 @@ typedef enum {
//#define SE_PassiveSenseTrap 359 // *not implemented - Invulnerability (Brell's Blessing)
#define SE_ProcOnKillShot 360 // implemented - a buff that has a base1 % to cast spell base2 when you kill a "challenging foe" base3 min level
#define SE_SpellOnDeath 361 // implemented - casts spell on death of buffed
//#define SE_PotionBeltSlots 362 // *not implemented[AA] 'Quick Draw' expands the potion belt by one additional available item slot per rank.
//#define SE_BandolierSlots 363 // *not implemented[AA] 'Battle Ready' expands the bandolier by one additional save slot per rank.
#define SE_PotionBeltSlots 362 // *not implemented[AA] 'Quick Draw' expands the potion belt by one additional available item slot per rank.
#define SE_BandolierSlots 363 // *not implemented[AA] 'Battle Ready' expands the bandolier by one additional save slot per rank.
#define SE_TripleAttackChance 364 // implemented
#define SE_ProcOnSpellKillShot 365 // implemented - chance to trigger a spell on kill when the kill is caused by a specific spell with this effect in it (10470 Venin)
#define SE_ShieldEquipDmgMod 366 // implemented[AA] Damage modifier to melee if shield equiped. (base1 = dmg mod , base2 = ?) ie Shield Specialist AA
@ -525,7 +525,7 @@ typedef enum {
#define SE_CorruptionCounter 369 // implemented
#define SE_ResistCorruption 370 // implemented
#define SE_AttackSpeed4 371 // implemented - stackable slow effect 'Inhibit Melee'
//#define SE_ForageSkill 372 // *not implemented[AA] Will increase the skill cap for those that have the Forage skill and grant the skill and raise the cap to those that do not.
#define SE_ForageSkill 372 // *not implemented[AA] Will increase the skill cap for those that have the Forage skill and grant the skill and raise the cap to those that do not.
#define SE_CastOnFadeEffectAlways 373 // implemented - Triggers if fades after natural duration OR from rune/numhits fades.
#define SE_ApplyEffect 374 // implemented
#define SE_DotCritDmgIncrease 375 // implemented - Increase damage of DoT critical amount
@ -544,7 +544,7 @@ typedef enum {
//#define SE_SummonCorpseZone 388 // *not implemented - summons a corpse from any zone(nec AA)
#define SE_FcTimerRefresh 389 // implemented - Refresh spell icons
//#define SE_FcTimerLockout 390 // *not implemented - Sets recast timers to specific value, focus limited.
#define SE_MeleeVulnerability 391 // implemented [Live SPA has this as LimitManaMax however that is clearly not the effect used]
#define SE_LimitManaMax 391 // implemented
#define SE_FcHealAmt 392 // implemented - Adds or removes healing from spells
#define SE_FcHealPctIncoming 393 // implemented - HealRate with focus restrictions.
#define SE_FcHealAmtIncoming 394 // implemented - Adds/Removes amount of healing on target by X value with foucs restrictions.
@ -579,7 +579,7 @@ typedef enum {
#define SE_LimitUseType 423 // implemented - limit a focus to require a certain numhits type
#define SE_GravityEffect 424 // implemented - Pulls/pushes you toward/away the mob at a set pace
//#define SE_Display 425 // *not implemented - Illusion: Flying Dragon(21626)
//#define SE_IncreaseExtTargetWindow 426 // *not implmented[AA] - increases the capacity of your extended target window
#define SE_IncreaseExtTargetWindow 426 // *not implmented[AA] - increases the capacity of your extended target window
#define SE_SkillProc 427 // implemented - chance to proc when using a skill(ie taunt)
#define SE_LimitToSkill 428 // implemented - limits what skills will effect a skill proc
#define SE_SkillProcSuccess 429 // implemented - chance to proc when tje skill in use successfully fires.
@ -735,8 +735,8 @@ struct SPDat_Spell_Struct
/* 198- 199 */
/* 200 */ bool suspendable; // buff is suspended in suspended buff zones
/* 201 */ int viral_range;
/* 202 */
/* 203 */ //int songcap; // individual song cap (how live currently does it, not implemented)
/* 202 */ int songcap; // individual song cap
/* 203 */
/* 204 */
/* 205 */ bool no_block;
/* 206 */

View File

@ -30,7 +30,7 @@
Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9085
#define CURRENT_BINARY_DATABASE_VERSION 9086
#define COMPILE_DATE __DATE__
#define COMPILE_TIME __TIME__
#ifndef WIN32

View File

@ -353,6 +353,7 @@ OP_OpenContainer=0x0000
OP_Marquee=0x502e
OP_ItemRecastDelay=0x15a9
#OP_OpenInventory=0x0000 # Likely does not exist in RoF -U
OP_ResetAA=0x1669
# Expeditions
OP_DzAddPlayer=0x4701

View File

@ -339,7 +339,7 @@
9083|2015_06_07_aa_update.sql|SHOW COLUMNS FROM `character_alternate_abilities` LIKE 'charges'|empty|
9084|2015_06_30_runspeed_adjustments.sql|SELECT `runspeed` FROM `npc_types` WHERE `runspeed` > 3|not_empty|
9085|2015_7_1_Marquee_Rule.sql|SELECT * FROM `rule_values` WHERE `rule_name` LIKE '%Character:MarqueeHPUpdates%'|empty|
9086|2015_07_02_aa_rework.sql|SHOW TABLES LIKE 'aa_ranks'|empty|
# Upgrade conditions:
# This won't be needed after this system is implemented, but it is used database that are not

File diff suppressed because it is too large Load Diff

View File

@ -152,7 +152,13 @@ void Client::SendEnterWorld(std::string name)
void Client::SendExpansionInfo() {
auto outapp = new EQApplicationPacket(OP_ExpansionInfo, sizeof(ExpansionInfo_Struct));
ExpansionInfo_Struct *eis = (ExpansionInfo_Struct*)outapp->pBuffer;
eis->Expansions = (RuleI(World, ExpansionSettings));
if(RuleB(World, UseClientBasedExpansionSettings)) {
eis->Expansions = ExpansionFromClientVersion(eqs->GetClientVersion());
//eis->Expansions = ExpansionFromClientVersion(this->GetCLE.
} else {
eis->Expansions = (RuleI(World, ExpansionSettings));
}
QueuePacket(outapp);
safe_delete(outapp);
}

View File

@ -2,6 +2,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
SET(zone_sources
aa.cpp
aa_ability.cpp
aggro.cpp
attack.cpp
beacon.cpp
@ -126,6 +127,7 @@ SET(zone_sources
SET(zone_headers
aa.h
aa_ability.h
basic_functions.h
beacon.h
bot.h

File diff suppressed because it is too large Load Diff

638
zone/aa.h
View File

@ -1,27 +1,8 @@
#ifndef AA_H
#define AA_H
struct AA_Ability;
struct SendAA_Struct;
#define MANA_BURN 664
#include <map>
#define MAX_SWARM_PETS 12 //this can change as long as you make more coords (swarm_pet_x/swarm_pet_y)
//this might be missing some, and some might not be used...
typedef enum { //AA Targeting Constants
aaTargetUser = 1,
aaTargetCurrent = 2, //use current target
aaTargetGroup = 3, //target group of user
aaTargetCurrentGroup = 4, //target group of current target
aaTargetPet = 5 //target the user's pet
} aaTargetType;
typedef enum {
aaActionNone = 0,
aaActionAETaunt = 1,
@ -42,21 +23,6 @@ typedef enum {
aaActionFadingMemories = 16
} aaNonspellAction;
//use these for AAs which dont cast spells, yet need effects
//if this list grows beyond 32, more work is needed in *AAEffect
typedef enum { //AA Effect IDs
aaEffectMassGroupBuff = 1, //unused - Handled via spell effect.
aaEffectRampage,
aaEffectSharedHealth,
aaEffectFlamingArrows,
aaEffectFrostArrows,
aaEffectWarcry,
aaEffectLeechTouch,
aaEffectProjectIllusion, // unused - Handled via spell effect
_maxaaEffectType = 32
} aaEffectType;
enum { //leadership AA indexes
groupAAMarkNPC = 0,
groupAANPCHealth,
@ -133,571 +99,6 @@ static const uint8 LeadershipAACosts[_maxLeaderAA][MAX_LEADERSHIP_TIERS] = {
{ 0, 0, 0, 0, 0, 0 }, //raidAA15
};
/*
typedef enum { //AA IDs
aaNone = 0,
aaInnateStrength = 2, //works
aaInnateStamina = 7, //works
aaInnateAgility = 12, //works
//aaCompleteHeal = 13,/ //not implemented, but is in dbstr_us.txt
aaInnateDexterity = 17, //works
aaInnateIntelligence = 22, //works
aaInnateWisdom = 27, //works
aaInnateCharisma = 32, //works
aaInnateFireProtection = 37, //works
aaInnateColdProtection = 42, //works
aaInnateMagicProtection = 47, //works
aaInnatePoisonProtection = 52, //works
aaInnateDiseaseProtection = 57, //works
aaInnateRunSpeed = 62, //works
aaInnateRegeneration = 65, //works
aaInnateMetabolism = 68,
aaInnateLungCapacity = 71, //handled by client
aaFirstAid = 74, //untested
aaHealingAdept = 77, //untested
aaHealingGift = 80, //untested
aaSpellCastingMastery = 83, //untested
aaSpellCastingReinforcement = 86, //untested
aaMentalClarity = 89,
aaSpellCastingFury = 92, //untested
aaChanellingFocus = 95,
aaSpellCastingSubtlety = 98, //untested
aaSpellCastingExpertise = 101, //untested
aaSpellCastingDeftness = 104, //untested
aaNaturalDurability = 107, //works
aaNaturalHealing = 110, //untested
aaCombatFury = 113, //untested
aaFearResistance = 116, //untested
aaFinishingBlow = 119, //untested
aaCombatStability = 122,
aaCombatAgility = 125,
aaMassGroupBuff = 128, //untested
aaDivineResurrection = 129, //DB
aaInnateInvisToUndead = 130, //DB
aaCelestialRegeneration = 131, //untested
aaBestowDivineAura = 132, //DB
aaTurnUndead = 133, //DB
aaPurifySoul = 136, //DB
aaQuickEvacuation = 137, //untested
aaExodus = 140, //untested
aaQuickDamage = 141, //untested
aaEnhancedRoot = 144,
aaDireCharm = 145, //untested
aaCannibalization = 146, //DB
aaQuickBuff = 147, //untested
aaAlchemyMastery = 150,
aaRabidBear = 153, //DB
aaManaBurn = 154, //DB
aaImprovedFamiliar = 155, //untested, implemented?
aaNexusGate = 156, //DB
aaUnknown54 = 157,
aaPermanentIllusion = 158,
aaJewelCraftMastery = 159,
aaGatherMana = 162, //DB
aaMendCompanion = 163, //DB
aaQuickSummoning = 164, //untested
aaFrenziedBurnout = 167, //DB
aaElementalFormFire = 168, //DB
aaElementalFormWater = 171, //DB
aaElementalFormEarth = 174, //DB
aaElementalFormAir = 177, //DB
aaImprovedReclaimEnergy = 180, //untested
aaTurnSummoned = 181, //DB
aaElementalPact = 182, //DB
aaLifeBurn = 183, //DB
aaDeadMesmerization = 184, //DB
aaFearstorm = 185, //DB
aaFleshToBone = 186, //DB
aaCallToCorpse = 187, //DB
aaDivineStun = 188, //DB
aaImprovedLayOnHands = 189,
aaSlayUndead = 190,
aaActOfValor = 193, //DB
aaHolySteed = 194, //DB
aaFearless = 195,
aa2HandBash = 196, //works. handled by client?
aaInnateCamouflage = 197, //DB
aaAmbidexterity = 198, //untested
aaArcheryMastery = 199, //untested
aaFletchingMastery = 202, //removed from db?
aaEndlessQuiver = 205, //untested
aaUnholySteed = 206, //DB
aaImprovedHarmTouch = 207, //untested
aaLeechTouch = 208, //DB
aaDeathPeace = 209,
aaSoulAbrasion = 210, //untested
aaInstrumentMastery = 213, //untested
aaUnknown91 = 216, //not used
aaUnknown92 = 219, //not used
aaUnknown93 = 222, //not used
aaJamFest = 225,
aaUnknown95 = 228,
aaSonicCall = 229,
aaCriticalMend = 230, //untested
aaPurifyBody = 233, //DB
aaChainCombo = 234,
aaRapidFeign = 237, //works
aaReturnKick = 240,
aaEscape = 243, //DB
aaPoisonMastery = 244,
aaDoubleRiposte = 247, //untested
aaQuickHide = 250,
aaQuickThrow = 253, //corrected from dbstr_us.txt
aaPurgePoison = 254, //DB
aaFlurry = 255, //untested
aaRampage = 258, //untested
aaAreaTaunt = 259, //untested
aaWarcry = 260, //DB
aaBandageWound = 263, //untested
aaSpellCastingReinforcementMastery = 266, //untested
aaSpellCastingFuryMastery = 267, //untested
aaExtendedNotes = 270, //untested
aaDragonPunch = 273,
aaStrongRoot = 274, //DB
aaSingingMastery = 275, //untested
aaBodyAndMindRejuvenation = 278, //added
aaPhysicalEnhancement = 279, //untested
aaAdvTrapNegotiation = 280, //untested
aaAcrobatics = 283, //untested
aaScribbleNotes = 286,
aaChaoticStab = 287, //untested
aaPetDiscipline = 288, //added
aaHobbleofSpirits = 289, //DB
aaFrenzyofSpirit = 290, //DB
aaParagonofSpirit = 291, //DB
aaAdvancedInnateStrength = 292, //works
aaAdvancedInnateStamina = 302, //works
aaAdvancedInnateAgility = 312, //works
aaAdvancedInnateDexterity = 322, //works
aaAdvancedInnateIntelligence = 332, //works
aaAdvancedInnateWisdom = 342, //works
aaAdvancedInnateCharisma = 352, //works
aaWardingofSolusek = 362, //works
aaBlessingofEci = 372, //works
aaMarrsProtection = 382, //works
aaShroudofTheFaceless = 392, //works
aaBertoxxulousGift = 402, //works
aaNewTanaanCraftingMastery = 412,
aaPlanarPower = 418, //untested
aaPlanarDurability = 423, //added
aaInnateEnlightenment = 426, //added
aaAdvancedSpellCastingMastery = 431,//untested
aaAdvancedHealingAdept = 434, //untested
aaAdvancedHealingGift = 437, //untested
aaCoupdeGrace = 440, //added
aaFuryoftheAges = 443, //added
aaMasteryofthePast = 446, //untested
aaLightningReflexes = 449, //added
aaInnateDefense = 454, //added
aaRadiantCure = 459, //DB
aaHastenedDivinity = 462, //DB
aaHastenedTurning = 465, //DB
aaHastenedPurificationofSoul = 468, //DB
aaHastenedGathering = 471, //DB
aaHastenedRabidity = 474, //DB
aaHastenedExodus = 477, //DB
aaHastenedRoot = 480, //DB
aaHastenedMending = 483, //DB
aaHastenedBanishment = 486, //DB
aaHastenedInstigation = 489, //DB, maybe
aaFuriousRampage = 492, //DB
aaHastenedPurificationoftheBody = 495,//DB
aaHastyExit = 498, //DB
aaHastenedPurification = 501, //DB
aaFlashofSteel = 504,
aaDivineArbitration = 507, //DB
aaWrathoftheWild = 510, //DB
aaVirulentParalysis = 513, //DB
aaHarvestofDruzzil = 516, //DB
aaEldritchRune = 517, //DB
aaServantofRo = 520, //DB
aaWaketheDead = 523, //DB
aaSuspendedMinion = 526, //untested
aaSpiritCall = 528, //DB
aaCelestialRenewal = 531, //DB
aaAllegiantFamiliar = 533,
aaHandofPiety = 534, //DB
aaMithanielsBinding = 537, //untested
aaMendingoftheTranquil = 539,
aaRagingFlurry = 542,
aaGuardianoftheForest = 545, //DB
aaSpiritoftheWood = 548, //DB
aaBestialFrenzy = 551, //untested
aaHarmoniousAttack = 556, //untested
aaKnightsAdvantage = 561,
aaFerocity = 564,
aaViscidRoots = 567,
aaSionachiesCrescendo = 568, //untested
aaAyonaesTutelage = 571,
aaFeignedMinion = 574,
aaUnfailingDivinity = 577,
aaAnimationEmpathy = 580, // Implemented
aaRushtoJudgement = 583,
aaLivingShield = 586,
aaConsumptionoftheSoul = 589, //untested
aaBoastfulBellow = 592, //DB
aaFervrentBlessing = 593, //untested
aaTouchoftheWicked = 596, //untested
aaPunishingBlade = 599,
aaSpeedoftheKnight = 602,
aaShroudofStealth = 605,
aaNimbleEvasion = 606,
aaTechniqueofMasterWu = 611,
aaHostoftheElements = 616, //DB
aaCallofXuzl = 619, //DB
aaHastenedStealth = 622,
aaIngenuity = 625,
aaFleetofFoot = 628,
aaFadingMemories = 630,
aaTacticalMastery = 631,
aaTheftofLife = 634,
aaFuryofMagic = 637,
aaFuryofMagicMastery2 = 640, //whats the difference?
aaProjectIllusion = 643,
aaHeadshot = 644, //added
aaEntrap = 645, //DB
aaUnholyTouch = 646, //untested
aaTotalDomination = 649, // Implemented
aaStalwartEndurance = 652, //implemented as bonus
aaQuickSummoning2 = 655, //whats the difference?
aaMentalClarity2 = 658, //whats the difference?
aaInnateRegeneration2 = 661, //whats the difference?
aaManaBurn2 = 664, //whats the difference?
aaExtendedNotes2 = 665, //not implemented - later expansions replaced Extended Notes with this.
aaSionachiesCrescendo2 = 668, //not implemented - later expansions replaced Sionachies Crescendo with this.
aaImprovedReclaimEnergy2 = 671, //whats the difference? untetsed
aaSwiftJourney = 672, //implemented as bonus
aaConvalescence = 674, //added 9/26/08
aaLastingBreath = 676, //handled by client
aaPackrat = 678, //added 9/29/08
aaHeightenedEndurance = 683,
aaWeaponAffinity = 686, //implemented
aaSecondaryForte = 691,
aaPersistantCasting = 692,
aaTuneofPursuance = 695,
aaImprovedInstrumentMastery = 700,
aaImprovedSingingMastery =701,
aaExultantBellowing = 702,
aaEchoofTaelosia = 707,
aaInternalMetronome = 710, //In 2006 this AA was removed.
aaPiousSupplication = 715,
aaBeastialAlignment = 718, //untested
aaWrathofXuzl = 721,
aaFeralSwipe = 723, //DB?
aaWardersFury = 724,
aaWardersAlacrity = 729,
aaPetAffinity = 734, // Implemented
aaMasteryofthePast2 = 735, //whats the difference?
aaSpellCastingSubtlety2 = 738, //whats the difference?
aaTouchoftheDivine = 741,
aaDivineAvatar = 746, //DB
aaExquisiteBenediction = 749, //DB
aaQuickenedCuring = 754,
aaNaturesBoon = 757, //DB
aaAdvancedTracking = 762,
aaCriticalAffliction = 767,
aaFuryofMagicMastery = 770, //whats the difference?
aaDoppelganger = 773,
aaEnchancedForgetfulness = 776,
aaMesmerizationMastery = 781,
aaQuickMassGroupBuff = 782,
aaSharedHealth = 785,
aaElementalFury = 790,
aaElementalAlacrity = 795,
aaElementalAgility = 800,
aaElementalDurability = 803,
aaSinisterStrikes = 806,
aaStrikethrough = 807,
aaStonewall = 810,
aaRapidStrikes = 815,
aaKickMastery = 820,
aaHightenedAwareness = 823,
aaDestructiveForce = 828, //DB
aaSwarmofDecay = 831, //DB
aaDeathsFury = 834,
aaQuickeningofDeath = 839,
aaAdvancedTheftofLife = 844,
aaTripleBackstab = 846,
aaHastenedPiety = 849,
aaImmobilizingBash = 852,
aaViciousSmash = 855,
aaRadiantCure2 = 860, //whats the difference?
aaPurification = 863,
aaPrecisionofthePathfinder = 864,
aaCoatofThistles = 867,
aaFlamingArrows = 872, //untested
aaFrostArrows = 875, //untested
aaSeizedOpportunity = 878,
aaTrapCircumvention = 881,
aaImprovedHastyExit = 886,
aaVirulentVenom = 888,
aaImprovedConsumptionofSoul = 893,
aaIntenseHatred = 895,
aaAdvancedSpiritCall = 900,
aaCalloftheAncients = 902, //DB
aaSturdiness = 907,
aaWarlordsTenacity = 912, //DB
aaStrengthenedStrike = 915,
aaExtendedShielding = 918,
aaRosFlamingFamiliar = 921, //DB
aaEcisIcyFamiliar = 922, //DB
aaDruzzilsMysticalFamiliar = 923, //DB
aaAdvancedFuryofMagicMastery = 924, //added 9/29/08
aaWardofDestruction = 926, //DB
aaFrenziedDevastation = 931, //DB
aaCombatFury2 = 934, //whats the difference?
aaCombatFury3 = 937, //whats the difference?
aaCombatFury4 = 940, //whats the difference?
aaFuryoftheAges2 = 943, //whats the difference?
aaFuryoftheAges3 = 946, //whats the difference?
aaFuryoftheAges4 = 949, //whats the difference?
aaPlanarDurability2 = 952, //whats the difference?
aaInnateEnlightenment2 = 955, //whats the difference?
aaDireCharm2 = 960, //whats the difference?
aaDireCharm3 = 961, //whats the difference?
aaTouchoftheDivine2 = 962, //whats the difference?
aaTouchofDecay = 967,
aaCalloftheAncients2 = 970, //whats the difference?
aaImprovedVision = 975,
aaEternalBreath = 978, //handled by client
aaBlacksmithingMastery = 979, //added 9/29/08
aaBakingMastery = 982, //added 9/29/08
aaBrewingMastery = 985, //added 9/29/08
aaFletchingMastery2 = 988, //added 9/29/08
aaPotteryMastery = 991, //added 9/29/08
aaTailoringMastery = 994, //added 9/29/08
aaSalvage = 997,
aaOrigin = 1000, //spell
aaChaoticPotential = 1001, //added
aaDiscordantDefiance = 1006, //added 9/29/08
aaTrialsofMataMuram = 1011,
aaMysticalAttuning = 1021,
aaDelayDeath = 1026,
aaHealthyAura = 1031,
aaFitness = 1036,
aaVeteransWrath = 1041, //added 9/29/08
aaVeteransWrath2 = 1044, //whats the difference?
aaVeteransWrath3 = 1047, //whats the difference?
aaVeteransWrath4 = 1050, //whats the difference?
aaDeathblow = 1053,
aaReflexiveMastery = 1061,
aaDefensiveInstincts = 1066,
aaMnemonicRetention = 1071, //Implemented
aaExpansiveMind = 1072, //added 9/29/08
aaSleightofHand = 1077,
aaSleightofHand2 = 1080, //whats the difference?
aaHealingAdeptMastery = 1083,
aaHealingGiftMastery = 1086,
aaArcaneTongues = 1089,
aaMasterofDisguise = 1092,
aaSlipperyAttacks = 1093,
aaImprovedCriticalAffliction = 1099,
aaFortifiedBellowing = 1102,
aaFuryofMagic2 = 1107, //whats the difference?
aaDanceofBlades = 1110,
aaShieldofNotes = 1116,
aaRoarofThunder = 1119,
aaPersistentMinion = 1122,
aaPerfectionofSpirit = 1123,
aaReplentishCompanion = 1126,
aaAdvancedPetDiscipline = 1129,
aaThrowingMastery = 1131,
aaBlurofAxes = 1134,
aaHastenedWarCry = 1137,
aaDeadAim = 1140,
aaFrenziedDefense = 1143,
aaTirelessSprint = 1146,
aaDesperation = 1149,
aaUntamedRage = 1150,
aaEchoingCries = 1155,
aaViciousFrenzy = 1158,
aaCrazedOnslaught = 1163,
aaOverwhelmingAttack = 1172,
aaFuriousRage = 1175,
aaBloodPact = 1178,
aaShieldingResistance = 1181,
aaHealingBoon = 1186,
aaResplendentCure = 1189,
aaCelestialHammer = 1192,
aaDivineRetribution = 1195,
aaCelestialRejuvination = 1203,
aaFerventBenediction = 1206,
aaSanctuary = 1209,
aaDestructiveFury = 1210, //added 9/29/08
aaDestructiveFury2 = 1213, //whats the difference?
aaBoonoftheForest = 1222,
aaSpiritoftheGrove = 1225,
aaCalloftheWild = 1228,
aaSecondaryRecall = 1229,
aaNaturesBounty = 1230,
aaStasis = 1233,
aaColorShock = 1239,
aaMindOverMatter = 1242,
aaSoothingWords = 1245,
aaElementalSwarm = 1248,
aaHeartofFlames = 1251,
aaHeartofVapor = 1252,
aaHeartofIce = 1253,
aaHeartofStone = 1254,
aaImitateDeath = 1255,
aaCripplingStrike = 1256,
aaStunningKick = 1259,
aaEyeGouge = 1262,
aaIronKicks = 1265,
aaStyleoftheMimic = 1268,
aaDeathPeace2 = 1272, //whats the difference?
aaArmyoftheDead = 1274,
aaCelestialStun = 1277,
aaHandofDevotion = 1278,
aaSteadfastWill = 1284,
aaShieldBlock = 1287,
aaScoutsEfficiency = 1290,
aaGuardianoftheGlade = 1293,
aaTrackingMastery = 1296,
aaFlurryofKnives = 1301,
aaPrecision = 1304,
aaNervesofSteel = 1307,
aaTouchoftheCursed = 1313,
aaSpiritualCorrosion = 1316,
aaSoulThief = 1319,
aaSpiritualChanneling = 1323,
aaBoonoftheAncients = 1324,
aaAncestralAid = 1327,
aaResoluteDefiance = 1330,
aaPresstheAttack = 1333,
aaMindCrash = 1334,
aaProlongedDestruction = 1337,
aaRosGreaterFamiliar = 1340,
aaEcisGreaterFamiliar = 1341,
aaDruzzilsGreaterFamiliar = 1342,
aaTeleportBind = 1343,
aaDevotedFamiliar = 1344,
aaAuspiceoftheHunter = 1345,
aaSavageSpirit = 1348,
aaPresstheAttack2 = 1351, //whats the difference?
aaCripplingStrike2 = 1352, //whats the difference?
aaStunningKick2 = 1353, //whats the difference?
aaEyeGouge2 = 1358, //whats the difference?
//Dragons of Norrath
//good info here: http://www.eqthieves.com/exp-don-progression.htm and here: http://everquest.allakhazam.com/db/guides.html?guide=811
aaGiftoftheDarkReign = 1361, //from dbstr_us.txt
aaTenacityoftheDarkReign = 1362, //from dbstr_us.txt
aaEmbraceoftheDarkReign = 1363, //from dbstr_us.txt
aaPoweroftheDarkReign = 1364, //from dbstr_us.txt
aaFervoroftheDarkReign = 1365, //from dbstr_us.txt
aaGiftoftheKeepers = 1366, //from dbstr_us.txt
aaValoroftheKeepers = 1367, //from dbstr_us.txt
aaEmbraceoftheKeepers = 1368, //from dbstr_us.txt
aaPoweroftheKeepers = 1369, //from dbstr_us.txt
aaSanctityoftheKeepers = 1370, //from dbstr_us.txt
//Veteran AAs
aaLessonoftheDevoted = 1371, //from dbstr_us.txt
aaInfusionoftheFaithful = 1372, //from dbstr_us.txt
aaChaoticJester = 1373, //from dbstr_us.txt
aaExpedientRecovery = 1374, //from dbstr_us.txt
aaSteadfastServant = 1375, //from dbstr_us.txt
aaStaunchRecovery = 1376, //from dbstr_us.txt
aaIntensityoftheResolute = 1377, //from dbstr_us.txt
//Depths of Darkhollow
//the following 5 look to be used as flags for completion of the Blood Raids for access to the Demiplane of Blood
//quest info here: http://everquest.allakhazam.com/db/quest.html?quest=3582
//"You must also complete the five Blood Raids in any order: The Council of Nine, Emperor Draygun, Bloodeye, Matriarch Shyra, Sendaii, the Hive Queen"
//"The AA's you receive are: Curse of Blood (1/5), Affliction of Blood (2/5), Torment of Blood (3/5), Temptation of Blood (4/5), Invitation of Blood (5/5)."
aaCurseofBlood = 1378, //from dbstr_us.txt
aaAfflictionofBlood = 1379, //from dbstr_us.txt
aaTormentofBlood = 1380, //from dbstr_us.txt
aaTemptationofBlood = 1381, //from dbstr_us.txt
aaInvitationofBlood = 1382, //from dbstr_us.txt
aaTurnUndead2 = 1383, //from dbstr_us.txt, Class AA changed in DoD
aaWrackUndead = 1386, //from dbstr_us.txt, PoP Class AA changed in DoD
aaEradicateUndead = 1387, //from dbstr_us.txt
aaInnateSeeInvis = 1388, //from dbstr_us.txt
aaProlongedMortality = 1389, //from dbstr_us.txt
aaPrecognition = 1394, //from dbstr_us.txt
aaThickSkin = 1399, //from dbstr_us.txt
aaSilentCasting = 1404, //from dbstr_us.txt
aaSilentCasting2 = 1409, //from dbstr_us.txt
aaHastenedMindCrash = 1414, //from dbstr_us.txt
aaFieldDressing = 1417, //from dbstr_us.txt
aaBandageWounds = 1420, //from dbstr_us.txt
aaCascadingRage = 1425, //from dbstr_us.txt
aaElementalFerocity = 1430, //from dbstr_us.txt
aaGiftofMana = 1435, //from dbstr_us.txt
aaRuneofShadows = 1440, //from dbstr_us.txt
aaChannelingMastery = 1445, //from dbstr_us.txt
aaConservation = 1453, //from dbstr_us.txt
aaCryofBattle = 1458, //from dbstr_us.txt
aaWardofPurity = 1459, //from dbstr_us.txt
aaTurnSummoned2 = 1462, //from dbstr_us.txt
aaWrackSummoned = 1465, //from dbstr_us.txt
aaEradicateSummoned = 1466, //from dbstr_us.txt
aaWardersSavagery = 1467, //from dbstr_us.txt
aaShackleofSpirits = 1470, //from dbstr_us.txt
aaHastenedThunder = 1471, //from dbstr_us.txt
aaTranslocationalAnchor = 1474, //from dbstr_us.txt
aaStealthyGetaway = 1477, //from dbstr_us.txt
aaPyromancy = 1478, //from dbstr_us.txt
aaMasteryofFury = 1483, //from dbstr_us.txt
aaAbundantHealing = 1486, //from dbstr_us.txt
aaGreaterAvatar = 1491, //from dbstr_us.txt
aaSharedCamouflage = 1494, //from dbstr_us.txt
aaConvergenceofSpirits = 1495, //from dbstr_us.txt
aaNaturesGuardian = 1498, //from dbstr_us.txt
aaEdictofCommand = 1501, //from dbstr_us.txt
aaExtendedBurnout = 1504, //from dbstr_us.txt
aaGuardianofRo = 1507, //from dbstr_us.txt
aaBloodMagic = 1510, //from dbstr_us.txt
aaGraverobbing = 1511, //from dbstr_us.txt
aaAfflictionMastery = 1514, //from dbstr_us.txt
aaGreaterRabidBear = 1517, //from dbstr_us.txt
aaAncestralGuard = 1520, //from dbstr_us.txt
aaCloakofLight = 1523, //from dbstr_us.txt
aaVanquishUndead = 1524, //from dbstr_us.txt
aaCloakofShadows = 1527, //from dbstr_us.txt
aaWillfulDeath = 1528, //from dbstr_us.txt
aaSwiftBlade = 1533, //from dbstr_us.txt
aaWickedBlade = 1536, //from dbstr_us.txt
aaForcedOpening = 1539, //from dbstr_us.txt
aaAppraisal = 1542, //from dbstr_us.txt
aaPreciseStrikes = 1543, //from dbstr_us.txt
aaHastenedDeath = 1546, //from dbstr_us.txt
aaUnflinchingResolve = 1549, //from dbstr_us.txt
aaWeightlessSteps = 1552, //from dbstr_us.txt
aaHastenedBlades = 1555, //from dbstr_us.txt
aaImprovedHarmoniousAttack = 1563, //from dbstr_us.txt
aaImprovedBestialFrenzy = 1566, //from dbstr_us.txt
aaSongofStone = 1569, //from dbstr_us.txt
aaDeepSleep = 1572, //from dbstr_us.txt
aaCompanionsGift = 1577, //from dbstr_us.txt
aaHastenedDefiance = 1583, //from dbstr_us.txt
aaDauntlessPerseverance = 1586, //from dbstr_us.txt
aaConcentration = 1587, //from dbstr_us.txt
aaEnhancedAggression = 1592, //from dbstr_us.txt
aaCallofChallenge = 1597, //from dbstr_us.txt
aaCacophony = 1598, //from dbstr_us.txt
aaImprovedHeadshot = 1601, //from dbstr_us.txt
aaAnatomy = 1604, //from dbstr_us.txt
aaFetterofSpirits = 1607, //from dbstr_us.txt
aaTrickShot = 1608, //from dbstr_us.txt
aaLightningStrikes = 1616, //from dbstr_us.txt
aaRelentlessAssault = 1621, //from dbstr_us.txt
aaKnightsExpertise = 1624, //from dbstr_us.txt
aaSelosEnduringCadence = 1627, //from dbstr_us.txt
aaHarmTouch = 7800, //from dbstr_us.txt
aaLayonHands = 7850, //from dbstr_us.txt
aaLayonHandsRank16 = 7866,
aaHighestID //this should always be last, and should always
//follow the highest AA ID
} aaID;
*/
typedef enum { //AA IDs
aaNone =0,
aaInnateStrength =2,//implemented as bonus
@ -2109,21 +1510,6 @@ typedef enum { //AA IDs
//follow the highest AA ID
} aaID;
//Structure representing the database's AA actions
struct AA_DBAction {
uint32 reuse_time; //in seconds
uint16 spell_id; //spell to cast, SPELL_UNKNOWN=no spell
aaTargetType target; //from aaTargetType
aaNonspellAction action; //non-spell action to take
uint16 mana_cost; //mana the NON-SPELL action costs
uint16 duration; //duration of NON-SPELL effect, 0=N/A
aaID redux_aa; //AA which reduces reuse time
int32 redux_rate; //%/point in redux_aa reduction in reuse time
aaID redux_aa2; //AA which reduces reuse time
int32 redux_rate2; //%/point in redux_aa reduction in reuse time
};
//Structure representing the database's swarm pet configs
struct AA_SwarmPet {
uint8 count; //number to summon
@ -2131,23 +1517,6 @@ struct AA_SwarmPet {
uint16 duration; //how long they last, in seconds
};
struct AALevelCost_Struct
{
uint32 Level;
uint32 Cost;
};
//assumes that no activatable aa.has more than 5 ranks
#define MAX_AA_ACTION_RANKS 20
extern AA_DBAction AA_Actions[aaHighestID][MAX_AA_ACTION_RANKS]; //[aaid][rank]
extern std::map<uint16, AA_SwarmPet> AA_SwarmPets; //key=spell_id
#define AA_Choose3(val, v1, v2, v3) (val==1?v1:(val==2?v2:v3))
extern std::map<uint32,SendAA_Struct*>aas_send;
extern std::map<uint32, std::map<uint32, AA_Ability> > aa_effects;
extern std::map<uint32, AALevelCost_Struct> AARequiredLevelAndCost;
enum { //values of AA_Action.action
aaActionActivate = 0,
aaActionSetEXP = 1,
@ -2167,4 +1536,11 @@ public:
uint32 owner_id;
};
enum AATimers
{
aaTimerRampage,
aaTimerWarcry,
aaTimerMax
};
#endif

70
zone/aa_ability.cpp Normal file
View File

@ -0,0 +1,70 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "../common/global_define.h"
#include "../common/types.h"
#include "masterentity.h"
#include "aa_ability.h"
AA::Rank *AA::Ability::GetMaxRank() {
if(!first)
return nullptr;
Rank *current = first;
while(current->next) {
current = current->next;
}
return current;
}
AA::Rank *AA::Ability::GetRankByPointsSpent(int current_level) {
if(current_level == 0)
return nullptr;
if(!first)
return nullptr;
int i = 1;
Rank *current = first;
while(current->next) {
if(i == current_level) {
break;
}
i++;
current = current->next;
}
return current;
}
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;
}

61
zone/aa_ability.h Normal file
View File

@ -0,0 +1,61 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef EQEMU_ZONE_AA_ABILITY_H
#define EQEMU_ZONE_AA_ABILITY_H
#include "../common/global_define.h"
#include <unordered_map>
#include <vector>
#include <memory>
#include "aa_rank_effects.h"
#include "aa_rank.h"
class Mob;
namespace AA
{
class Ability
{
public:
Ability() { }
~Ability() { }
Rank *GetMaxRank();
Rank *GetRankByPointsSpent(int current_level);
int GetMaxLevel(Mob *who);
int id;
std::string name;
int category;
int classes;
int races;
int deities;
int drakkin_heritage;
int status;
bool grant_only;
int type;
int charges;
int first_rank_id;
Rank *first;
};
}
#endif

56
zone/aa_rank.h Normal file
View File

@ -0,0 +1,56 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef EQEMU_ZONE_AA_RANK_H
#define EQEMU_ZONE_AA_RANK_H
namespace AA
{
class Ability;
class Rank
{
public:
Rank() { }
~Rank() { }
int id;
int upper_hotkey_sid;
int lower_hotkey_sid;
int title_sid;
int desc_sid;
int cost;
int level_req;
int spell;
int spell_type;
int recast_time;
int prev_id;
Rank *prev;
int next_id;
Rank *next;
int current_value;
int expansion;
int total_cost;
Ability *base_ability;
std::vector<RankEffect> effects;
std::map<int, int> prereqs;
};
}
#endif

38
zone/aa_rank_effects.h Normal file
View File

@ -0,0 +1,38 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef EQEMU_ZONE_AA_RANK_EFFECTS_H
#define EQEMU_ZONE_AA_RANK_EFFECTS_H
#include "../common/global_define.h"
#include <string>
namespace AA
{
struct RankEffect
{
int slot;
int effect_id;
int base1;
int base2;
};
}
#endif

View File

@ -1372,6 +1372,13 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
///////////////////////////////////////////////////////////
////// Send Attack Damage
///////////////////////////////////////////////////////////
if (damage > 0 && aabonuses.SkillAttackProc[0] && aabonuses.SkillAttackProc[1] == skillinuse &&
IsValidSpell(aabonuses.SkillAttackProc[2])) {
float chance = aabonuses.SkillAttackProc[0] / 1000.0f;
if (zone->random.Roll(chance))
SpellFinished(aabonuses.SkillAttackProc[2], other, 10, 0, -1,
spells[aabonuses.SkillAttackProc[2]].ResistDiff);
}
other->Damage(this, damage, SPELL_UNKNOWN, skillinuse);
if (IsDead()) return false;
@ -3512,14 +3519,6 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
if(damage > 0) {
//if there is some damage being done and theres an attacker involved
if(attacker) {
if(spell_id == SPELL_HARM_TOUCH2 && attacker->IsClient() && attacker->CastToClient()->CheckAAEffect(aaEffectLeechTouch)){
int healed = damage;
healed = attacker->GetActSpellHealing(spell_id, healed);
attacker->HealDamage(healed);
entity_list.MessageClose(this, true, 300, MT_Emote, "%s beams a smile at %s", attacker->GetCleanName(), this->GetCleanName() );
attacker->CastToClient()->DisableAAEffect(aaEffectLeechTouch);
}
// if spell is lifetap add hp to the caster
if (spell_id != SPELL_UNKNOWN && IsLifetapSpell( spell_id )) {
int healed = damage;
@ -4416,42 +4415,55 @@ bool Mob::TryFinishingBlow(Mob *defender, SkillUseTypes skillinuse)
return false;
}
void Mob::DoRiposte(Mob* defender) {
void Mob::DoRiposte(Mob *defender)
{
Log.Out(Logs::Detail, Logs::Combat, "Preforming a riposte");
if (!defender)
return;
defender->Attack(this, MainPrimary, true);
if (HasDied()) return;
if (HasDied())
return;
int32 DoubleRipChance = defender->aabonuses.GiveDoubleRiposte[0] +
defender->spellbonuses.GiveDoubleRiposte[0] +
defender->itembonuses.GiveDoubleRiposte[0];
// this effect isn't used on live? See no AAs or spells
int32 DoubleRipChance = defender->aabonuses.DoubleRiposte + defender->spellbonuses.DoubleRiposte +
defender->itembonuses.DoubleRiposte;
DoubleRipChance = defender->aabonuses.DoubleRiposte +
defender->spellbonuses.DoubleRiposte +
defender->itembonuses.DoubleRiposte;
//Live AA - Double Riposte
if(DoubleRipChance && zone->random.Roll(DoubleRipChance)) {
Log.Out(Logs::Detail, Logs::Combat, "Preforming a double riposed (%d percent chance)", DoubleRipChance);
if (DoubleRipChance && zone->random.Roll(DoubleRipChance)) {
Log.Out(Logs::Detail, Logs::Combat,
"Preforming a double riposted from SE_DoubleRiposte (%d percent chance)", DoubleRipChance);
defender->Attack(this, MainPrimary, true);
if (HasDied()) return;
if (HasDied())
return;
}
//Double Riposte effect, allows for a chance to do RIPOSTE with a skill specfic special attack (ie Return Kick).
//Coded narrowly: Limit to one per client. Limit AA only. [1 = Skill Attack Chance, 2 = Skill]
DoubleRipChance = defender->aabonuses.GiveDoubleRiposte[0] + defender->spellbonuses.GiveDoubleRiposte[0] +
defender->itembonuses.GiveDoubleRiposte[0];
// Live AA - Double Riposte
if (DoubleRipChance && zone->random.Roll(DoubleRipChance)) {
Log.Out(Logs::Detail, Logs::Combat,
"Preforming a double riposted from SE_GiveDoubleRiposte base1 == 0 (%d percent chance)",
DoubleRipChance);
defender->Attack(this, MainPrimary, true);
if (HasDied())
return;
}
// Double Riposte effect, allows for a chance to do RIPOSTE with a skill specific special attack (ie Return Kick).
// Coded narrowly: Limit to one per client. Limit AA only. [1 = Skill Attack Chance, 2 = Skill]
DoubleRipChance = defender->aabonuses.GiveDoubleRiposte[1];
if(DoubleRipChance && zone->random.Roll(DoubleRipChance)) {
Log.Out(Logs::Detail, Logs::Combat, "Preforming a return SPECIAL ATTACK (%d percent chance)", DoubleRipChance);
if (DoubleRipChance && zone->random.Roll(DoubleRipChance)) {
Log.Out(Logs::Detail, Logs::Combat, "Preforming a return SPECIAL ATTACK (%d percent chance)",
DoubleRipChance);
if (defender->GetClass() == MONK)
defender->MonkSpecialAttack(this, defender->aabonuses.GiveDoubleRiposte[2]);
else if (defender->IsClient())
defender->CastToClient()->DoClassAttacks(this,defender->aabonuses.GiveDoubleRiposte[2], true);
else if (defender->IsClient() && defender->CastToClient()->HasSkill((SkillUseTypes)defender->aabonuses.GiveDoubleRiposte[2]))
defender->CastToClient()->DoClassAttacks(this, defender->aabonuses.GiveDoubleRiposte[2], true);
}
}
@ -4643,7 +4655,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
if (IsClient() && aabonuses.LimitToSkill[skill]){
CanProc = true;
uint32 effect = 0;
uint32 effect_id = 0;
int32 base1 = 0;
int32 base2 = 0;
uint32 slot = 0;
@ -4662,36 +4674,41 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, ui
proc_spell_id = 0;
ProcMod = 0;
std::map<uint32, std::map<uint32, AA_Ability> >::const_iterator find_iter = aa_effects.find(aaid);
if(find_iter == aa_effects.end())
break;
for(auto &rank_info : aa_ranks) {
auto ability_rank = zone->GetAlternateAdvancementAbilityAndRank(rank_info.first, rank_info.second.first);
auto ability = ability_rank.first;
auto rank = ability_rank.second;
for (std::map<uint32, AA_Ability>::const_iterator iter = aa_effects[aaid].begin(); iter != aa_effects[aaid].end(); ++iter) {
effect = iter->second.skill_id;
base1 = iter->second.base1;
base2 = iter->second.base2;
slot = iter->second.slot;
if (effect == SE_SkillProc || effect == SE_SkillProcSuccess) {
proc_spell_id = base1;
ProcMod = static_cast<float>(base2);
if(!ability) {
continue;
}
else if (effect == SE_LimitToSkill && base1 <= HIGHEST_SKILL) {
for(auto &effect : rank->effects) {
effect_id = effect.effect_id;
base1 = effect.base1;
base2 = effect.base2;
slot = effect.slot;
if (CanProc && base1 == skill && IsValidSpell(proc_spell_id)) {
float final_chance = chance * (ProcMod / 100.0f);
if(effect_id == SE_SkillProc || effect_id == SE_SkillProcSuccess) {
proc_spell_id = base1;
ProcMod = static_cast<float>(base2);
}
else if(effect_id == SE_LimitToSkill && base1 <= HIGHEST_SKILL) {
if (zone->random.Roll(final_chance)) {
ExecWeaponProc(nullptr, proc_spell_id, on);
CanProc = false;
break;
if (CanProc && base1 == skill && IsValidSpell(proc_spell_id)) {
float final_chance = chance * (ProcMod / 100.0f);
if (zone->random.Roll(final_chance)) {
ExecWeaponProc(nullptr, proc_spell_id, on);
CanProc = false;
break;
}
}
}
}
else {
proc_spell_id = 0;
ProcMod = 0;
else {
proc_spell_id = 0;
ProcMod = 0;
}
}
}
}
@ -5042,3 +5059,39 @@ void NPC::SetAttackTimer()
TimerToUse->SetAtTrigger(std::max(RuleI(Combat, MinHastedDelay), speed), true, true);
}
}
void Client::DoAttackRounds(Mob *target, int hand, bool IsFromSpell)
{
if (!target)
return;
Attack(target, hand, false, false, IsFromSpell);
if (CanThisClassDoubleAttack()) {
CheckIncreaseSkill(SkillDoubleAttack, target, -10);
if (CheckDoubleAttack())
Attack(target, hand, false, false, IsFromSpell);
if (hand == MainPrimary && GetLevel() >= 60 &&
(GetClass() == MONK || GetClass() == WARRIOR || GetClass() == RANGER || GetClass() == BERSERKER) &&
CheckDoubleAttack(true))
Attack(target, hand, false, false, IsFromSpell);
}
if (hand == MainPrimary) {
auto flurrychance = aabonuses.FlurryChance + spellbonuses.FlurryChance + itembonuses.FlurryChance;
if (flurrychance && zone->random.Roll(flurrychance)) {
Message_StringID(MT_NPCFlurry, YOU_FLURRY);
Attack(target, hand, false, false, IsFromSpell);
Attack(target, hand, false, false, IsFromSpell);
}
auto extraattackchance = aabonuses.ExtraAttackChance + spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance;
if (extraattackchance) {
auto wpn = GetInv().GetItem(MainPrimary);
if (wpn && (wpn->GetItem()->ItemType == ItemType2HBlunt ||
wpn->GetItem()->ItemType == ItemType2HSlash ||
wpn->GetItem()->ItemType == ItemType2HPiercing))
if (zone->random.Roll(extraattackchance))
Attack(target, hand, false, false, IsFromSpell);
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -314,11 +314,12 @@ public:
virtual float GetAOERange(uint16 spell_id);
virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100);
virtual void DoBuffTic(const Buffs_Struct &buff, int slot, Mob* caster = nullptr);
virtual bool CastSpell(uint16 spell_id, uint16 target_id, uint16 slot = USE_ITEM_SPELL_SLOT, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, int16 *resist_adjust = nullptr);
virtual bool CastSpell(uint16 spell_id, uint16 target_id, uint16 slot = USE_ITEM_SPELL_SLOT, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0,
uint32 item_slot = 0xFFFFFFFF, int16 *resist_adjust = nullptr, uint32 aa_id = 0);
virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar);
virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster);
virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction);
virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot = USE_ITEM_SPELL_SLOT, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF);
virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot = USE_ITEM_SPELL_SLOT, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, uint32 aa_id = 0);
// Bot Action Command Methods
bool MesmerizeTarget(Mob* target);
@ -448,9 +449,6 @@ public:
bool IsBotWISCaster() { return (GetClass() == CLERIC || GetClass() == DRUID || GetClass() == SHAMAN); }
bool CanHeal();
int GetRawACNoShield(int &shield_ac);
void LoadAAs();
uint32 GetAA(uint32 aa_id);
void ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon);
bool GetHasBeenSummoned() { return _hasBeenSummoned; }
const glm::vec3 GetPreSummonLocation() const { return m_PreSummonLocation; }
bool GetGroupMessagesOn() { return _groupMessagesOn; }
@ -564,7 +562,7 @@ protected:
virtual bool CheckBotDoubleAttack(bool Triple = false);
virtual int32 GetBotFocusEffect(BotfocusType bottype, uint16 spell_id);
virtual int32 CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spell_id, bool best_focus=false);
virtual int32 CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id);
virtual int32 CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16 spell_id);
virtual void PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* client);
virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0);
virtual float GetMaxMeleeRangeToTarget(Mob* target);
@ -646,12 +644,12 @@ private:
uint8 _baseGender; // Bots gender. Necessary to preserve the original value otherwise it can be changed by illusions.
// Class Methods
void LoadAAs();
int32 acmod();
void GenerateBaseStats();
void GenerateAppearance();
void GenerateArmorClass();
int32 GenerateBaseHitPoints();
void GenerateAABonuses(StatBonuses* newbon);
int32 GenerateBaseManaPoints();
void GenerateSpecialAttacks();
void SetBotID(uint32 botID);

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;
@ -441,7 +440,7 @@ void Client::SendZoneInPackets()
//Send AA Exp packet:
if (GetLevel() >= 51)
SendAAStats();
SendAlternateAdvancementStats();
// Send exp packets
outapp = new EQApplicationPacket(OP_ExpUpdate, sizeof(ExpUpdate_Struct));
@ -458,7 +457,7 @@ void Client::SendZoneInPackets()
}
safe_delete(outapp);
SendAATimers();
SendAlternateAdvancementTimers();
outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(ZoneInSendName_Struct));
ZoneInSendName_Struct* zonesendname = (ZoneInSendName_Struct*)outapp->pBuffer;
@ -525,48 +524,39 @@ void Client::ReportConnectingState() {
};
}
bool Client::SaveAA(){
int first_entry = 0;
std::string rquery;
/* Save Player AA */
bool Client::SaveAA() {
std::string iquery;
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;
int i = 0;
for(auto &rank : aa_ranks) {
AA::Ability *ability = zone->GetAlternateAdvancementAbility(rank.first);
if(!ability)
continue;
if(rank.second.first > 0) {
AA::Rank *r = ability->GetRankByPointsSpent(rank.second.first);
if(!r)
continue;
spentpoints += r->total_cost;
if(i == 0) {
iquery = StringFormat("REPLACE INTO `character_alternate_abilities` (id, aa_id, aa_value, charges)"
" VALUES (%u, %u, %u, %u)", character_id, ability->first_rank_id, rank.second.first, rank.second.second);
} else {
rquery = rquery + StringFormat(", (%u, %u, %u, %u, %u)", character_id, a, aa[a]->AA, aa[a]->value, aa[a]->charges);
iquery += StringFormat(", (%u, %u, %u, %u)", character_id, ability->first_rank_id, rank.second.first, rank.second.second);
}
highest = a;
i++;
}
}
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);
m_pp.aapoints_spent = spentpoints + m_epp.expended_aa;
if(iquery.length() > 0) {
database.QueryDatabase(iquery);
}
return true;
}
@ -8041,56 +8031,6 @@ void Client::TryItemTimer(int slot)
}
}
void Client::RefundAA() {
int cur = 0;
bool refunded = false;
for(int x = 0; x < aaHighestID; x++) {
cur = GetAA(x);
if(cur > 0){
SendAA_Struct* curaa = zone->FindAA(x);
if(cur){
SetAA(x, 0);
for(int j = 0; j < cur; j++) {
m_pp.aapoints += curaa->cost + (curaa->cost_inc * j);
refunded = true;
}
}
else
{
m_pp.aapoints += cur;
SetAA(x, 0);
refunded = true;
}
}
}
if(refunded) {
SaveAA();
Save();
// Kick();
}
}
void Client::IncrementAA(int aa_id) {
SendAA_Struct* aa2 = zone->FindAA(aa_id);
if(aa2 == nullptr)
return;
if(GetAA(aa_id) == aa2->max_level)
return;
SetAA(aa_id, GetAA(aa_id) + 1);
SaveAA();
SendAA(aa_id);
SendAATable();
SendAAStats();
CalcBonuses();
}
void Client::SendItemScale(ItemInst *inst) {
int slot = m_inv.GetSlotByItemInst(inst);
if(slot != -1) {
@ -8651,4 +8591,4 @@ void Client::SendHPUpdateMarquee(){
std::string health_update_notification = StringFormat("Health: %u%%", health_percentage);
this->SendMarqueeMessage(15, 510, 0, 3000, 3000, health_update_notification);
}
}

View File

@ -45,7 +45,6 @@ struct Item_Struct;
#include "../common/item_struct.h"
#include "../common/clientversions.h"
#include "aa.h"
#include "common.h"
#include "merc.h"
#include "mob.h"
@ -227,6 +226,7 @@ public:
virtual int32 GetMeleeMitDmg(Mob *attacker, int32 damage, int32 minhit, float mit_rating, float atk_rating);
virtual void SetAttackTimer();
float GetQuiverHaste();
void DoAttackRounds(Mob *target, int hand, bool IsFromSpell = false);
void AI_Init();
void AI_Start(uint32 iMoveDelay = 0);
@ -541,7 +541,6 @@ public:
bool Flurry();
bool Rampage();
void DurationRampage(uint32 duration);
inline uint32 GetEXP() const { return m_pp.exp; }
@ -623,6 +622,7 @@ public:
inline uint32 AccountID() const { return account_id; }
inline const char* AccountName()const { return account_name; }
inline int GetAccountCreation() const { return account_creation; }
inline int16 Admin() const { return admin; }
inline uint32 CharacterID() const { return character_id; }
void UpdateAdmin(bool iFromDB = true);
@ -759,45 +759,35 @@ public:
inline PTimerList &GetPTimers() { return(p_timers); }
//AA Methods
void SendAAList();
void ResetAA();
void SendClearAA();
void SendAA(uint32 id, int seq=1);
void SendPreviousAA(uint32 id, int seq=1);
void BuyAA(AA_Action* action);
//this function is used by some AA stuff
void MemorizeSpell(uint32 slot,uint32 spellid,uint32 scribing);
void SetAATitle(const char *Title);
void SetTitleSuffix(const char *txt);
inline uint32 GetMaxAAXP(void) const { return max_AAXP; }
inline uint32 GetAAXP() const { return m_pp.expAA; }
void SendAAStats();
void SendAATable();
void SendAATimers();
int GetAATimerID(aaID activate);
int CalcAAReuseTimer(const AA_DBAction *caa);
void ActivateAA(aaID activate);
void SendAATimer(uint32 ability, uint32 begin, uint32 end);
void EnableAAEffect(aaEffectType type, uint32 duration = 0);
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);
void SetAAPoints(uint32 points) { m_pp.aapoints = points; SendAAStats(); }
void AddAAPoints(uint32 points) { m_pp.aapoints += points; SendAAStats(); }
//New AA Methods
void SendAlternateAdvancementRank(int aa_id, int level);
void SendAlternateAdvancementTable();
void SendAlternateAdvancementStats();
void PurchaseAlternateAdvancementRank(int rank_id);
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();
void SendAlternateAdvancementTimer(int ability, int begin, int end);
void SendAlternateAdvancementTimers();
void ResetAlternateAdvancementTimer(int ability);
void ResetAlternateAdvancementTimers();
void SetAAPoints(uint32 points) { m_pp.aapoints = points; SendAlternateAdvancementStats(); }
void AddAAPoints(uint32 points) { m_pp.aapoints += points; SendAlternateAdvancementStats(); }
int GetAAPoints() { return m_pp.aapoints; }
int GetSpentAA() { return m_pp.aapoints_spent; }
//old AA methods that we still use
void ResetAA();
void RefundAA();
void IncrementAA(int aa_id);
int32 GetAAEffectDataBySlot(uint32 aa_ID, uint32 slot_id, bool GetEffect, bool GetBase1, bool GetBase2);
int32 GetAAEffectid(uint32 aa_ID, uint32 slot_id) { return GetAAEffectDataBySlot(aa_ID, slot_id, true, false,false); }
int32 GetAABase1(uint32 aa_ID, uint32 slot_id) { return GetAAEffectDataBySlot(aa_ID, slot_id, false, true,false); }
int32 GetAABase2(uint32 aa_ID, uint32 slot_id) { return GetAAEffectDataBySlot(aa_ID, slot_id, false, false,true); }
void SendClearAA();
inline uint32 GetMaxAAXP(void) const { return max_AAXP; }
inline uint32 GetAAXP() const { return m_pp.expAA; }
int16 CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id);
void SetAATitle(const char *Title);
void SetTitleSuffix(const char *txt);
void MemorizeSpell(uint32 slot, uint32 spellid, uint32 scribing);
int32 acmod();
// Item methods
@ -1271,8 +1261,6 @@ protected:
void AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug = false);
int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat);
void CalcEdibleBonuses(StatBonuses* newbon);
void CalcAABonuses(StatBonuses* newbon);
void ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon);
void ProcessItemCaps();
void MakeBuffFadePacket(uint16 spell_id, int slot_id, bool send_message = true);
bool client_data_loaded;
@ -1280,6 +1268,8 @@ protected:
int16 GetFocusEffect(focusType type, uint16 spell_id);
uint16 GetSympatheticFocusEffect(focusType type, uint16 spell_id);
void FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost);
Mob* bind_sight_target;
glm::vec4 m_AutoAttackPosition;
@ -1497,11 +1487,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

@ -1121,7 +1121,7 @@ int32 Client::CalcMaxMana()
switch (GetCasterClass()) {
case 'I':
case 'W': {
max_mana = (CalcBaseMana() + itembonuses.Mana + spellbonuses.Mana + GroupLeadershipAAManaEnhancement());
max_mana = (CalcBaseMana() + itembonuses.Mana + spellbonuses.Mana + aabonuses.Mana + GroupLeadershipAAManaEnhancement());
break;
}
case 'N': {
@ -1978,7 +1978,18 @@ uint32 Mob::GetInstrumentMod(uint16 spell_id) const
return 10;
uint32 effectmod = 10;
int effectmodcap = RuleI(Character, BaseInstrumentSoftCap);
int effectmodcap = 0;
bool nocap = false;
if (RuleB(Character, UseSpellFileSongCap)) {
effectmodcap = spells[spell_id].songcap / 10;
// this looks a bit weird, but easiest way I could think to keep both systems working
if (effectmodcap == 0)
nocap = true;
else
effectmodcap += 10;
} else {
effectmodcap = RuleI(Character, BaseInstrumentSoftCap);
}
// this should never use spell modifiers...
// if a spell grants better modifers, they are copied into the item mods
// because the spells are supposed to act just like having the intrument.
@ -2048,10 +2059,11 @@ uint32 Mob::GetInstrumentMod(uint16 spell_id) const
effectmod = 10;
return effectmod;
}
effectmodcap += aabonuses.songModCap + spellbonuses.songModCap + itembonuses.songModCap;
if (!RuleB(Character, UseSpellFileSongCap))
effectmodcap += aabonuses.songModCap + spellbonuses.songModCap + itembonuses.songModCap;
if (effectmod < 10)
effectmod = 10;
if (effectmod > effectmodcap)
if (!nocap && effectmod > effectmodcap) // if the cap is calculated to be 0 using new rules, no cap.
effectmod = effectmodcap;
Log.Out(Logs::Detail, Logs::Spells, "%s::GetInstrumentMod() spell=%d mod=%d modcap=%d\n", GetName(), spell_id,
effectmod, effectmodcap);

View File

@ -389,6 +389,7 @@ void MapOpcodes()
ConnectedOpcodes[OP_XTargetRequest] = &Client::Handle_OP_XTargetRequest;
ConnectedOpcodes[OP_YellForHelp] = &Client::Handle_OP_YellForHelp;
ConnectedOpcodes[OP_ZoneChange] = &Client::Handle_OP_ZoneChange;
ConnectedOpcodes[OP_ResetAA] = &Client::Handle_OP_ResetAA;
}
void ClearMappedOpcode(EmuOpcode op)
@ -1082,7 +1083,7 @@ void Client::Handle_Connect_OP_ReqNewZone(const EQApplicationPacket *app)
void Client::Handle_Connect_OP_SendAAStats(const EQApplicationPacket *app)
{
SendAATimers();
SendAlternateAdvancementTimers();
EQApplicationPacket* outapp = new EQApplicationPacket(OP_SendAAStats, 0);
QueuePacket(outapp);
safe_delete(outapp);
@ -1091,7 +1092,7 @@ void Client::Handle_Connect_OP_SendAAStats(const EQApplicationPacket *app)
void Client::Handle_Connect_OP_SendAATable(const EQApplicationPacket *app)
{
SendAAList();
SendAlternateAdvancementTable();
return;
}
@ -1152,7 +1153,7 @@ void Client::Handle_Connect_OP_TGB(const EQApplicationPacket *app)
void Client::Handle_Connect_OP_UpdateAA(const EQApplicationPacket *app)
{
SendAATable();
SendAlternateAdvancementPoints();
}
void Client::Handle_Connect_OP_WearChange(const EQApplicationPacket *app)
@ -1439,58 +1440,15 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
if (m_pp.ldon_points_tak < 0 || m_pp.ldon_points_tak > 2000000000){ m_pp.ldon_points_tak = 0; }
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++;
if(RuleB(World, UseClientBasedExpansionSettings)) {
m_pp.expansions = ExpansionFromClientVersion(GetClientVersion());
}
else {
m_pp.expansions = RuleI(World, ExpansionSettings);
}
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;
if(!database.LoadAlternateAdvancement(this)) {
Log.Out(Logs::General, Logs::Error, "Error loading AA points for %s", GetName());
}
if (SPDAT_RECORDS > 0) {
@ -1615,11 +1573,6 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
/* Update LFP in case any (or all) of our group disbanded while we were zoning. */
if (IsLFP()) { UpdateLFP(); }
/* Get Expansions from variables table and ship via PP */
char val[20] = { 0 };
if (database.GetVariable("Expansions", val, 20)){ m_pp.expansions = atoi(val); }
else{ m_pp.expansions = 0x3FF; }
p_timers.SetCharID(CharacterID());
if (!p_timers.Load(&database)) {
Log.Out(Logs::General, Logs::Error, "Unable to load ability timers from the database for %s (%i)!", GetCleanName(), CharacterID());
@ -1794,38 +1747,39 @@ void Client::Handle_OP_AAAction(const EQApplicationPacket *app)
Log.Out(Logs::Detail, Logs::AA, "Received OP_AAAction");
if (app->size != sizeof(AA_Action)){
printf("Error! OP_AAAction size didnt match!\n");
Log.Out(Logs::General, Logs::AA, "Error! OP_AAAction size didnt match!");
return;
}
AA_Action* action = (AA_Action*)app->pBuffer;
if (action->action == aaActionActivate) {//AA Hotkey
Log.Out(Logs::Detail, Logs::AA, "Activating AA %d", action->ability);
ActivateAA((aaID)action->ability);
ActivateAlternateAdvancementAbility(action->ability, action->target_id);
}
else if (action->action == aaActionBuy) {
BuyAA(action);
PurchaseAlternateAdvancementRank(action->ability);
}
else if (action->action == aaActionDisableEXP){ //Turn Off AA Exp
if (m_epp.perAA > 0)
Message_StringID(0, AA_OFF);
m_epp.perAA = 0;
SendAAStats();
SendAlternateAdvancementStats();
}
else if (action->action == aaActionSetEXP) {
if (m_epp.perAA == 0)
Message_StringID(0, AA_ON);
m_epp.perAA = action->exp_value;
if (m_epp.perAA<0 || m_epp.perAA>100) m_epp.perAA = 0; // stop exploit with sanity check
if (m_epp.perAA < 0 || m_epp.perAA > 100)
m_epp.perAA = 0; // stop exploit with sanity check
// send an update
SendAAStats();
SendAATable();
SendAlternateAdvancementStats();
SendAlternateAdvancementTable();
}
else {
printf("Unknown AA action: %u %u 0x%x %d\n", action->action, action->ability, action->unknown08, action->exp_value);
Log.Out(Logs::General, Logs::AA, "Unknown AA action : %u %u %u %d", action->action, action->ability, action->target_id, action->exp_value);
}
return;
}
void Client::Handle_OP_AcceptNewTask(const EQApplicationPacket *app)
@ -3898,8 +3852,6 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app)
return;
}
m_TargetRing = glm::vec3(castspell->x_pos, castspell->y_pos, castspell->z_pos);
CastSpell(spell_to_cast, castspell->target_id, castspell->slot);
}
/* Spell Slot or Potion Belt Slot */
@ -8852,7 +8804,7 @@ void Client::Handle_OP_LFGuild(const EQApplicationPacket *app)
pack->WriteUInt32(QSG_LFGuild_UpdatePlayerInfo);
pack->WriteUInt32(GetBaseClass());
pack->WriteUInt32(GetLevel());
pack->WriteUInt32(GetAAPointsSpent());
pack->WriteUInt32(GetSpentAA());
pack->WriteString(pts->Comment);
pack->WriteUInt32(pts->Toggle);
pack->WriteUInt32(pts->TimeZone);
@ -14228,9 +14180,12 @@ void Client::Handle_OP_YellForHelp(const EQApplicationPacket *app)
return;
}
/*
void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app)
void Client::Handle_OP_ResetAA(const EQApplicationPacket *app)
{
if(Admin() >= 50) {
Message(0, "Resetting AA points.");
ResetAA();
}
return;
}
*/

View File

@ -295,3 +295,4 @@
void Handle_OP_XTargetRequest(const EQApplicationPacket *app);
void Handle_OP_YellForHelp(const EQApplicationPacket *app);
void Handle_OP_ZoneChange(const EQApplicationPacket *app);
void Handle_OP_ResetAA(const EQApplicationPacket *app);

View File

@ -391,73 +391,12 @@ bool Client::Process() {
}
else if (auto_attack_target->GetHP() > -10) // -10 so we can watch people bleed in PvP
{
if(CheckAAEffect(aaEffectRampage))
{
entity_list.AEAttack(this, 30);
} else {
Attack(auto_attack_target, MainPrimary); // Kaiyodo - added attacking hand to arguments
}
ItemInst *wpn = GetInv().GetItem(MainPrimary);
TryWeaponProc(wpn, auto_attack_target, MainPrimary);
bool tripleAttackSuccess = false;
if( auto_attack_target && CanThisClassDoubleAttack() ) {
CheckIncreaseSkill(SkillDoubleAttack, auto_attack_target, -10);
if(CheckDoubleAttack()) {
//should we allow rampage on double attack?
if(CheckAAEffect(aaEffectRampage)) {
entity_list.AEAttack(this, 30);
} else {
Attack(auto_attack_target, MainPrimary, false);
}
}
//triple attack: rangers, monks, warriors, berserkers over level 60
if((((GetClass() == MONK || GetClass() == WARRIOR || GetClass() == RANGER || GetClass() == BERSERKER)
&& GetLevel() >= 60) || GetSpecialAbility(SPECATK_TRIPLE))
&& CheckDoubleAttack(true))
{
tripleAttackSuccess = true;
Attack(auto_attack_target, MainPrimary, false);
}
//quad attack, does this belong here??
if(GetSpecialAbility(SPECATK_QUAD) && CheckDoubleAttack(true))
{
Attack(auto_attack_target, MainPrimary, false);
}
}
//Live AA - Flurry, Rapid Strikes ect (Flurry does not require Triple Attack).
int16 flurrychance = aabonuses.FlurryChance + spellbonuses.FlurryChance + itembonuses.FlurryChance;
if (auto_attack_target && flurrychance)
{
if(zone->random.Int(0, 99) < flurrychance)
{
Message_StringID(MT_NPCFlurry, YOU_FLURRY);
Attack(auto_attack_target, MainPrimary, false);
Attack(auto_attack_target, MainPrimary, false);
}
}
int16 ExtraAttackChanceBonus = spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance + aabonuses.ExtraAttackChance;
if (auto_attack_target && ExtraAttackChanceBonus) {
ItemInst *wpn = GetInv().GetItem(MainPrimary);
if(wpn){
if(wpn->GetItem()->ItemType == ItemType2HSlash ||
wpn->GetItem()->ItemType == ItemType2HBlunt ||
wpn->GetItem()->ItemType == ItemType2HPiercing )
{
if(zone->random.Int(0, 99) < ExtraAttackChanceBonus)
{
Attack(auto_attack_target, MainPrimary, false);
}
}
}
}
DoAttackRounds(auto_attack_target, MainPrimary);
if (CheckAATimer(aaTimerRampage))
entity_list.AEAttack(this, 30);
}
}
@ -498,23 +437,11 @@ bool Client::Process() {
float random = zone->random.Real(0, 1);
CheckIncreaseSkill(SkillDualWield, auto_attack_target, -10);
if (random < DualWieldProbability){ // Max 78% of DW
if(CheckAAEffect(aaEffectRampage)) {
entity_list.AEAttack(this, 30, MainSecondary);
} else {
Attack(auto_attack_target, MainSecondary); // Single attack with offhand
}
if (random < DualWieldProbability) { // Max 78% of DW
ItemInst *wpn = GetInv().GetItem(MainSecondary);
TryWeaponProc(wpn, auto_attack_target, MainSecondary);
if( CanThisClassDoubleAttack() && CheckDoubleAttack()) {
if(CheckAAEffect(aaEffectRampage)) {
entity_list.AEAttack(this, 30, MainSecondary);
} else {
if(auto_attack_target && auto_attack_target->GetHP() > -10)
Attack(auto_attack_target, MainSecondary); // Single attack with offhand
}
}
DoAttackRounds(auto_attack_target, MainSecondary);
}
}
}

View File

@ -167,7 +167,6 @@ int command_init(void) {
command_add("aggro", "(range) [-v] - Display aggro information for all mobs 'range' distance from your target. -v is verbose faction info.", 80, command_aggro) ||
command_add("aggrozone", "[aggro] - Aggro every mob in the zone with X aggro. Default is 0. Not recommend if you're not invulnerable.", 100, command_aggrozone) ||
command_add("ai", "[factionid/spellslist/con/guard/roambox/stop/start] - Modify AI on NPC target", 100, command_ai) ||
command_add("altactivate", "[argument] - activates alternate advancement abilities, use altactivate help for more information", 0, command_altactivate) ||
command_add("appearance", "[type] [value] - Send an appearance packet for you or your target", 150, command_appearance) ||
command_add("attack", "[targetname] - Make your NPC target attack targetname", 150, command_attack) ||
command_add("augmentitem", "Force augments an item. Must have the augment item window open.", 250, command_augmentitem) ||
@ -273,7 +272,6 @@ int command_init(void) {
command_add("los", nullptr,0, command_checklos) ||
command_add("makepet", "[level] [class] [race] [texture] - Make a pet", 50, command_makepet) ||
command_add("mana", "- Fill your or your target's mana", 50, command_mana) ||
command_add("manaburn", "- Use AA Wizard class skill manaburn on target", 10, command_manaburn) ||
command_add("maxskills", "Maxes skills for you.", 200, command_max_all_skills) ||
command_add("memspell", "[slotid] [spellid] - Memorize spellid in the specified slot", 50, command_memspell) ||
command_add("merchant_close_shop", "Closes a merchant shop", 100, command_merchantcloseshop) ||
@ -322,6 +320,7 @@ int command_init(void) {
command_add("raidloot", "LEADER|GROUPLEADER|SELECTED|ALL - Sets your raid loot settings if you have permission to do so.", 0, command_raidloot) ||
command_add("randomfeatures", "- Temporarily randomizes the Facial Features of your target", 80, command_randomfeatures) ||
command_add("refreshgroup", "- Refreshes Group.", 0, command_refreshgroup) ||
command_add("reloadaa", "Reloads AA data", 200, command_reloadaa) ||
command_add("reloadallrules", "Executes a reload of all rules.", 80, command_reloadallrules) ||
command_add("reloademote", "Reloads NPC Emotes", 80, command_reloademote) ||
command_add("reloadlevelmods", nullptr,255, command_reloadlevelmods) ||
@ -334,7 +333,8 @@ int command_init(void) {
command_add("reloadzonepoints", "- Reload zone points from database", 150, command_reloadzps) ||
command_add("reloadzps", nullptr,0, command_reloadzps) ||
command_add("repop", "[delay] - Repop the zone with optional delay", 100, command_repop) ||
command_add("resetaa", "- Resets a Player's AA in their profile and refunds spent AA's to unspent, disconnects player.", 200, command_resetaa) ||
command_add("resetaa", "- Resets a Player's AA in their profile and refunds spent AA's to unspent, may disconnect player.", 200, command_resetaa) ||
command_add("resetaa_timer", "Command to reset AA cooldown timers.", 200, command_resetaa_timer) ||
command_add("revoke", "[charname] [1/0] - Makes charname unable to talk on OOC", 200, command_revoke) ||
command_add("rules", "(subcommand) - Manage server rules", 250, command_rules) ||
command_add("save", "- Force your player or player corpse target to be saved to the database", 50, command_save) ||
@ -673,8 +673,8 @@ void command_incstat(Client* c, const Seperator* sep){
}
}
void command_resetaa(Client* c,const Seperator *sep){
if(c->GetTarget()!=0 && c->GetTarget()->IsClient()){
void command_resetaa(Client* c,const Seperator *sep) {
if(c->GetTarget() && c->GetTarget()->IsClient()){
c->GetTarget()->CastToClient()->ResetAA();
c->Message(13,"Successfully reset %s's AAs", c->GetTarget()->GetName());
}
@ -4840,36 +4840,6 @@ void command_zonestatus(Client *c, const Seperator *sep)
}
}
void command_manaburn(Client *c, const Seperator *sep)
{
Mob* target=c->GetTarget();
if (c->GetTarget() == 0)
c->Message(0, "#Manaburn needs a target.");
else {
int cur_level=c->GetAA(MANA_BURN);//ManaBurn ID
if (DistanceSquared(c->GetPosition(), target->GetPosition()) > 200)
c->Message(0,"You are too far away from your target.");
else {
if(cur_level == 1) {
if(c->IsAttackAllowed(target))
{
c->SetMana(0);
int nukedmg=(c->GetMana())*2;
if (nukedmg>0)
{
target->Damage(c, nukedmg, 2751, SkillAbjuration/*hackish*/);
c->Message(4,"You unleash an enormous blast of magical energies.");
}
Log.Out(Logs::General, Logs::Normal, "Manaburn request from %s, damage: %d", c->GetName(), nukedmg);
}
}
else
c->Message(0, "You have not learned this skill.");
}
}
}
void command_doanim(Client *c, const Seperator *sep)
{
if (!sep->IsNumber(1))
@ -5584,16 +5554,23 @@ void command_setaapts(Client *c, const Seperator *sep)
if(sep->arg[1][0] == '\0' || sep->arg[2][0] == '\0')
c->Message(0, "Usage: #setaapts <AA|group|raid> <new AA points value>");
else if(atoi(sep->arg[2]) <= 0 || atoi(sep->arg[2]) > 200)
c->Message(0, "You must have a number greater than 0 for points and no more than 200.");
else if(atoi(sep->arg[2]) <= 0 || atoi(sep->arg[2]) > 5000)
c->Message(0, "You must have a number greater than 0 for points and no more than 5000.");
else if(!strcasecmp(sep->arg[1], "group")) {
t->SetLeadershipEXP(atoi(sep->arg[2])*GROUP_EXP_PER_POINT, t->GetRaidEXP());
t->GetPP().group_leadership_points = atoi(sep->arg[2]);
t->GetPP().group_leadership_exp = 0;
t->Message(MT_Experience, "Setting Group AA points to %u", t->GetPP().group_leadership_points);
t->SendLeadershipEXPUpdate();
} else if(!strcasecmp(sep->arg[1], "raid")) {
t->SetLeadershipEXP(t->GetGroupEXP(), atoi(sep->arg[2])*RAID_EXP_PER_POINT);
t->GetPP().raid_leadership_points = atoi(sep->arg[2]);
t->GetPP().raid_leadership_exp = 0;
t->Message(MT_Experience, "Setting Raid AA points to %u", t->GetPP().raid_leadership_points);
t->SendLeadershipEXPUpdate();
} else {
t->SetEXP(t->GetEXP(),t->GetMaxAAXP()*atoi(sep->arg[2]),false);
t->SendAAStats();
t->SendAATable();
t->GetPP().aapoints = atoi(sep->arg[2]);
t->GetPP().expAA = 0;
t->Message(MT_Experience, "Setting personal AA points to %u", t->GetPP().aapoints);
t->SendAlternateAdvancementStats();
}
}
@ -7676,56 +7653,6 @@ void command_reloadtitles(Client *c, const Seperator *sep)
}
void command_altactivate(Client *c, const Seperator *sep){
if(sep->arg[1][0] == '\0'){
c->Message(10, "Invalid argument, usage:");
c->Message(10, "#altactivate list - lists the AA ID numbers that are available to you");
c->Message(10, "#altactivate time [argument] - returns the time left until you can use the AA with the ID that matches the argument.");
c->Message(10, "#altactivate [argument] - activates the AA with the ID that matches the argument.");
return;
}
if(!strcasecmp(sep->arg[1], "help")){
c->Message(10, "Usage:");
c->Message(10, "#altactivate list - lists the AA ID numbers that are available to you");
c->Message(10, "#altactivate time [argument] - returns the time left until you can use the AA with the ID that matches the argument.");
c->Message(10, "#altactivate [argument] - activates the AA with the ID that matches the argument.");
return;
}
if(!strcasecmp(sep->arg[1], "list")){
c->Message(10, "You have access to the following AA Abilities:");
int x, val;
SendAA_Struct* saa = nullptr;
for(x = 0; x < aaHighestID; x++){
if(AA_Actions[x][0].spell_id || AA_Actions[x][0].action){ //if there's an action or spell associated we assume it's a valid
val = 0; //and assume if they don't have a value for the first rank then it isn't valid for any rank
saa = nullptr;
val = c->GetAA(x);
if(val){
saa = zone->FindAA(x);
c->Message(10, "%d: %s %d", x, saa->name, val);
}
}
}
}
else if(!strcasecmp(sep->arg[1], "time")){
int ability = atoi(sep->arg[2]);
if(c->GetAA(ability)){
int remain = c->GetPTimers().GetRemainingTime(pTimerAAStart + ability);
if(remain)
c->Message(10, "You may use that ability in %d minutes and %d seconds.", (remain/60), (remain%60));
else
c->Message(10, "You may use that ability now.");
}
else{
c->Message(10, "You do not have access to that ability.");
}
}
else
{
c->ActivateAA((aaID) atoi(sep->arg[1]));
}
}
void command_traindisc(Client *c, const Seperator *sep)
{
uint8 max_level, min_level;
@ -10655,3 +10582,35 @@ void command_mysqltest(Client *c, const Seperator *sep)
}
Log.Out(Logs::General, Logs::Debug, "MySQL Test... Took %f seconds", ((float)(std::clock() - t)) / CLOCKS_PER_SEC);
}
void command_resetaa_timer(Client *c, const Seperator *sep) {
Client *target = nullptr;
if(!c->GetTarget() || !c->GetTarget()->IsClient()) {
target = c;
} else {
target = c->GetTarget()->CastToClient();
}
if(sep->IsNumber(1))
{
int timer_id = atoi(sep->arg[1]);
c->Message(0, "Reset of timer %i for %s", timer_id, c->GetName());
c->ResetAlternateAdvancementTimer(timer_id);
}
else if(!strcasecmp(sep->arg[1], "all"))
{
c->Message(0, "Reset all timers for %s", c->GetName());
c->ResetAlternateAdvancementTimers();
}
else
{
c->Message(0, "usage: #resetaa_timer [all | timer_id]");
}
}
void command_reloadaa(Client *c, const Seperator *sep) {
c->Message(0, "Reloading Alternate Advancement Data...");
zone->LoadAlternateAdvancement();
c->Message(0, "Alternate Advancement Data Reloaded");
entity_list.SendAlternateAdvancementStats();
}

View File

@ -216,7 +216,6 @@ void command_time(Client *c, const Seperator *sep);
void command_guild(Client *c, const Seperator *sep);
bool helper_guild_edit(Client *c, uint32 dbid, uint32 eqid, uint8 rank, const char* what, const char* value);
void command_zonestatus(Client *c, const Seperator *sep);
void command_manaburn(Client *c, const Seperator *sep);
void command_doanim(Client *c, const Seperator *sep);
void command_randomfeatures(Client *c, const Seperator *sep);
void command_face(Client *c, const Seperator *sep);
@ -276,7 +275,6 @@ void command_guildlist(Client *c, const Seperator *sep);
void command_rules(Client *c, const Seperator *sep);
void command_task(Client *c, const Seperator *sep);
void command_reloadtitles(Client *c, const Seperator *sep);
void command_altactivate(Client *c, const Seperator *sep);
void command_refundaa(Client *c, const Seperator *sep);
void command_traindisc(Client *c, const Seperator *sep);
void command_deletegraveyard(Client *c, const Seperator *sep);
@ -325,7 +323,9 @@ void command_tune(Client *c, const Seperator *sep);
void command_logtest(Client *c, const Seperator *sep);
void command_mysqltest(Client *c, const Seperator *sep);
void command_logs(Client *c, const Seperator *sep);
void command_resetaa_timer(Client *c, const Seperator *sep);
void command_reloadaa(Client *c, const Seperator *sep);
#ifdef EQPROFILE
void command_profiledump(Client *c, const Seperator *sep);
void command_profilereset(Client *c, const Seperator *sep);

View File

@ -22,6 +22,7 @@
#define TARGET_RING_SPELL_SLOT 12
#define DISCIPLINE_SPELL_SLOT 10
#define ABILITY_SPELL_SLOT 9
#define ALTERNATE_ABILITY_SPELL_SLOT 0xFF
//LOS Parameters:
#define HEAD_POSITION 0.9f //ratio of GetSize() where NPCs see from
@ -400,7 +401,6 @@ struct StatBonuses {
int32 Metabolism; // Food/drink consumption rates.
bool Sanctuary; // Sanctuary effect, lowers place on hate list until cast on others.
int32 FactionModPct; // Modifies amount of faction gained.
int32 MeleeVulnerability; // Weakness/mitigation to melee damage
bool LimitToSkill[HIGHEST_SKILL+2]; // Determines if we need to search for a skill proc.
uint32 SkillProc[MAX_SKILL_PROCS]; // Max number of spells containing skill_procs.
uint32 SkillProcSuccess[MAX_SKILL_PROCS]; // Max number of spells containing skill_procs_success.
@ -412,7 +412,7 @@ struct StatBonuses {
int8 BaseMovementSpeed; // Adjust base run speed, does not stack with other movement bonuses.
uint8 IncreaseRunSpeedCap; // Increase max run speed above cap.
int32 DoubleSpecialAttack; // Chance to to perform a double special attack (ie flying kick 2x)
int32 SpecialAttackKBProc[2]; // Chance to to do a knockback from special attacks. (0 = chance 1 = Skill)
int32 SkillAttackProc[3]; // [0] chance to proc [2] spell on [1] skill usage
uint8 FrontalStunResist; // Chance to resist a frontal stun
int32 BindWound; // Increase amount of HP by percent.
int32 MaxBindWound; // Increase max amount of HP you can bind wound.
@ -461,6 +461,7 @@ struct StatBonuses {
uint8 AssassinateLevel; // Max Level Assassinate will be effective at.
int32 PetMeleeMitigation; // Add AC to owner's pet.
bool IllusionPersistence; // Causes illusions not to fade.
uint16 extra_xtargets; // extra xtarget entries
};
typedef struct

View File

@ -421,12 +421,6 @@ int32 Mob::GetActSpellDuration(uint16 spell_id, int32 duration)
int tic_inc = 0;
tic_inc = GetFocusEffect(focusSpellDurByTic, spell_id);
// unsure on the exact details, but bard songs that don't cost mana at some point get an extra tick, 60 for now
// a level 53 bard reported getting 2 tics
// bard DOTs do get this extra tick, but beneficial long bard songs don't? (invul, crescendo)
if ((IsShortDurationBuff(spell_id) || IsDetrimentalSpell(spell_id)) && IsBardSong(spell_id) &&
spells[spell_id].mana == 0 && GetClass() == BARD && GetLevel() > 60)
tic_inc++;
float focused = ((duration * increase) / 100.0f) + tic_inc;
int ifocused = static_cast<int>(focused);
@ -878,7 +872,7 @@ void EntityList::AEBardPulse(Mob *caster, Mob *center, uint16 spell_id, bool aff
caster->CastToClient()->CheckSongSkillIncrease(spell_id);
}
//Dook- Rampage and stuff for clients.
// Rampage and stuff for clients. Normal and Duration rampages
//NPCs handle it differently in Mob::Rampage
void EntityList::AEAttack(Mob *attacker, float dist, int Hand, int count, bool IsFromSpell) {
//Dook- Will need tweaking, currently no pets or players or horses
@ -896,7 +890,10 @@ void EntityList::AEAttack(Mob *attacker, float dist, int Hand, int count, bool I
&& curmob->GetRace() != 216 && curmob->GetRace() != 472 /* dont attack horses */
&& (DistanceSquared(curmob->GetPosition(), attacker->GetPosition()) <= dist2)
) {
attacker->Attack(curmob, Hand, false, false, IsFromSpell);
if (!attacker->IsClient() || attacker->GetClass() == MONK || attacker->GetClass() == RANGER)
attacker->Attack(curmob, Hand, false, false, IsFromSpell);
else
attacker->CastToClient()->DoAttackRounds(curmob, Hand, IsFromSpell);
hit++;
if (count != 0 && hit >= count)
return;

View File

@ -58,7 +58,6 @@ extern uint32 numclients;
extern PetitionList petition_list;
extern char errorname[32];
extern uint16 adverrornum;
Entity::Entity()
{
@ -4705,3 +4704,11 @@ void EntityList::StopMobAI()
mob.second->AI_ShutDown();
}
}
void EntityList::SendAlternateAdvancementStats() {
for(auto &c : client_list) {
c.second->SendAlternateAdvancementTable();
c.second->SendAlternateAdvancementStats();
c.second->SendAlternateAdvancementPoints();
}
}

View File

@ -398,7 +398,6 @@ public:
void SaveAllClientsTaskState();
void ReloadAllClientsTaskState(int TaskID=0);
uint16 CreateGroundObject(uint32 itemid, const glm::vec4& position, uint32 decay_time = 300000);
uint16 CreateGroundObjectFromModel(const char *model, const glm::vec4& position, uint8 type = 0x00, uint32 decay_time = 0);
uint16 CreateDoor(const char *model, const glm::vec4& position, uint8 type = 0, uint16 size = 100);
@ -429,6 +428,7 @@ public:
uint16 GetFreeID();
void RefreshAutoXTargets(Client *c);
void RefreshClientXTargets(Client *c);
void SendAlternateAdvancementStats();
protected:
friend class Zone;

View File

@ -515,7 +515,7 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
if (GetLevel() < 51) {
m_epp.perAA = 0; // turn off aa exp if they drop below 51
} else
SendAAStats(); //otherwise, send them an AA update
SendAlternateAdvancementStats(); //otherwise, send them an AA update
//send the expdata in any case so the xp bar isnt stuck after leveling
uint32 tmpxp1 = GetEXPForLevel(GetLevel()+1);

View File

@ -350,6 +350,11 @@ const char *Lua_Client::AccountName() {
return self->AccountName();
}
int Lua_Client::GetAccountAge() {
Lua_Safe_Call_Int();
return time(nullptr) - self->GetAccountCreation();
}
int Lua_Client::Admin() {
Lua_Safe_Call_Bool();
return self->Admin();
@ -1024,7 +1029,17 @@ void Lua_Client::AddLevelBasedExp(int exp_pct, int max_level) {
void Lua_Client::IncrementAA(int aa) {
Lua_Safe_Call_Void();
self->IncrementAA(aa);
self->IncrementAlternateAdvancementRank(aa);
}
bool Lua_Client::GrantAlternateAdvancementAbility(int aa_id, int points) {
Lua_Safe_Call_Bool();
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) {
@ -1365,6 +1380,7 @@ luabind::scope lua_register_client() {
.def("GetRawItemAC", (int(Lua_Client::*)(void))&Lua_Client::GetRawItemAC)
.def("AccountID", (uint32(Lua_Client::*)(void))&Lua_Client::AccountID)
.def("AccountName", (const char *(Lua_Client::*)(void))&Lua_Client::AccountName)
.def("GetAccountAge", (int(Lua_Client::*)(void))&Lua_Client::GetAccountAge)
.def("Admin", (int(Lua_Client::*)(void))&Lua_Client::Admin)
.def("CharacterID", (uint32(Lua_Client::*)(void))&Lua_Client::CharacterID)
.def("GuildRank", (int(Lua_Client::*)(void))&Lua_Client::GuildRank)
@ -1500,6 +1516,8 @@ luabind::scope lua_register_client() {
.def("AddLevelBasedExp", (void(Lua_Client::*)(int))&Lua_Client::AddLevelBasedExp)
.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)

View File

@ -166,9 +166,9 @@ public:
void SummonItem(uint32 item_id, int charges, uint32 aug1, uint32 aug2, uint32 aug3);
void SummonItem(uint32 item_id, int charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4);
void SummonItem(uint32 item_id, int charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5);
void SummonItem(uint32 item_id, int charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5,
void SummonItem(uint32 item_id, int charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5,
bool attuned);
void SummonItem(uint32 item_id, int charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5,
void SummonItem(uint32 item_id, int charges, uint32 aug1, uint32 aug2, uint32 aug3, uint32 aug4, uint32 aug5,
bool attuned, int to_slot);
void SetStats(int type, int value);
void IncStats(int type, int value);
@ -233,6 +233,8 @@ public:
void AddLevelBasedExp(int exp_pct);
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();
@ -260,6 +262,7 @@ public:
bool HasSpellScribed(int spell_id);
void SetAccountFlag(std::string flag, std::string val);
std::string GetAccountFlag(std::string flag);
int GetAccountAge();
Lua_Group GetGroup();
Lua_Raid GetRaid();
bool PutItemInInventory(int slot_id, Lua_ItemInst inst);

View File

@ -790,7 +790,7 @@ bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time, in
int16 res = resist_adjust;
return self->CastSpell(spell_id, target_id, slot, cast_time, mana_cost, nullptr, static_cast<uint32>(item_slot),
static_cast<uint32>(timer), static_cast<uint32>(timer_duration), 0, &res);
static_cast<uint32>(timer), static_cast<uint32>(timer_duration), &res);
}
bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target) {
@ -1195,6 +1195,21 @@ int Lua_Mob::GetAA(int id) {
return self->GetAA(id);
}
int Lua_Mob::GetAAByAAID(int id) {
Lua_Safe_Call_Int();
return self->GetAAByAAID(id);
}
bool Lua_Mob::SetAA(int rank_id, int new_value) {
Lua_Safe_Call_Bool();
return self->SetAA(rank_id, new_value);
}
bool Lua_Mob::SetAA(int rank_id, int new_value, int charges) {
Lua_Safe_Call_Bool();
return self->SetAA(rank_id, new_value, charges);
}
bool Lua_Mob::DivineAura() {
Lua_Safe_Call_Bool();
return self->DivineAura();
@ -2074,6 +2089,9 @@ luabind::scope lua_register_mob() {
.def("CheckHealAggroAmount", (int(Lua_Mob::*)(int))&Lua_Mob::CheckHealAggroAmount)
.def("CheckHealAggroAmount", (int(Lua_Mob::*)(int,uint32))&Lua_Mob::CheckHealAggroAmount)
.def("GetAA", (int(Lua_Mob::*)(int))&Lua_Mob::GetAA)
.def("GetAAByAAID", (int(Lua_Mob::*)(int))&Lua_Mob::GetAAByAAID)
.def("SetAA", (bool(Lua_Mob::*)(int,int))&Lua_Mob::SetAA)
.def("SetAA", (bool(Lua_Mob::*)(int,int,int))&Lua_Mob::SetAA)
.def("DivineAura", (bool(Lua_Mob::*)(void))&Lua_Mob::DivineAura)
.def("SetOOCRegen", (void(Lua_Mob::*)(int))&Lua_Mob::SetOOCRegen)
.def("GetEntityVariable", (const char*(Lua_Mob::*)(const char*))&Lua_Mob::GetEntityVariable)

View File

@ -249,6 +249,9 @@ public:
int CheckHealAggroAmount(int spell_id);
int CheckHealAggroAmount(int spell_id, uint32 heal_possible);
int GetAA(int id);
int GetAAByAAID(int id);
bool SetAA(int rank_id, int new_value);
bool SetAA(int rank_id, int new_value, int charges);
bool DivineAura();
void SetOOCRegen(int regen);
const char* GetEntityVariable(const char *name);

View File

@ -307,8 +307,8 @@ Mob::Mob(const char* in_name,
casting_spell_id = 0;
casting_spell_timer = 0;
casting_spell_timer_duration = 0;
casting_spell_type = 0;
casting_spell_inventory_slot = 0;
casting_spell_aa_id = 0;
target = 0;
ActiveProjectileATK = false;
@ -1142,6 +1142,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));
@ -3510,9 +3514,11 @@ void Mob::TriggerOnCast(uint32 focus_spell, uint32 spell_id, bool aa_trigger)
uint32 trigger_spell_id = 0;
if (aa_trigger && IsClient()){
//focus_spell = aaid
trigger_spell_id = CastToClient()->CalcAAFocus(focusTriggerOnCast, focus_spell, spell_id);
if (aa_trigger && IsClient()) {
// focus_spell = aaid
auto rank = zone->GetAlternateAdvancementRank(focus_spell);
if (rank)
trigger_spell_id = CastToClient()->CalcAAFocus(focusTriggerOnCast, *rank, spell_id);
if(IsValidSpell(trigger_spell_id) && GetTarget())
SpellFinished(trigger_spell_id, GetTarget(), 10, 0, -1, spells[trigger_spell_id].ResistDiff);
@ -3768,11 +3774,8 @@ int16 Mob::GetSkillDmgTaken(const SkillUseTypes skill_used)
skilldmg_mod += itembonuses.SkillDmgTaken[HIGHEST_SKILL+1] + spellbonuses.SkillDmgTaken[HIGHEST_SKILL+1] +
itembonuses.SkillDmgTaken[skill_used] + spellbonuses.SkillDmgTaken[skill_used];
skilldmg_mod += SkillDmgTaken_Mod[skill_used] + SkillDmgTaken_Mod[HIGHEST_SKILL+1];
skilldmg_mod += spellbonuses.MeleeVulnerability + itembonuses.MeleeVulnerability + aabonuses.MeleeVulnerability;
if(skilldmg_mod < -100)
skilldmg_mod = -100;

View File

@ -23,6 +23,8 @@
#include "hate_list.h"
#include "pathing.h"
#include "position.h"
#include "aa_ability.h"
#include "aa.h"
#include <set>
#include <vector>
#include <memory>
@ -221,10 +223,12 @@ public:
virtual void SpellProcess();
virtual bool CastSpell(uint16 spell_id, uint16 target_id, uint16 slot = USE_ITEM_SPELL_SLOT, int32 casttime = -1,
int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF,
uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, uint32 type = 0, int16 *resist_adjust = nullptr);
uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, int16 *resist_adjust = nullptr,
uint32 aa_id = 0);
virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot = 10, int32 casttime = -1,
int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF,
uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, uint32 type = 0, int16 resist_adjust = 0);
uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, int16 resist_adjust = 0,
uint32 aa_id = 0);
void CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot, uint16 mana_used,
uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0);
bool SpellFinished(uint16 spell_id, Mob *target, uint16 slot = 10, uint16 mana_used = 0,
@ -860,7 +864,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 +959,19 @@ 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, uint32 *charges = nullptr) const;
uint32 GetAAByAAID(uint32 aa_id, uint32 *charges = nullptr) const;
bool SetAA(uint32 rank_id, uint32 new_value, uint32 charges = 0);
void ClearAAs() { aa_ranks.clear(); }
bool CanUseAlternateAdvancementRank(AA::Rank *rank);
bool CanPurchaseAlternateAdvancementRank(AA::Rank *rank, bool check_price, bool check_grant);
int GetAlternateAdvancementCooldownReduction(AA::Rank *rank_in);
void ExpendAlternateAdvancementCharge(uint32 aa_id);
void CalcAABonuses(StatBonuses* newbon);
void ApplyAABonuses(const AA::Rank &rank, StatBonuses* newbon);
bool CheckAATimer(int timer);
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 +985,6 @@ protected:
virtual bool AI_PursueCastCheck() { return(false); }
virtual bool AI_IdleCastCheck() { return(false); }
bool IsFullHP;
bool moved;
@ -1145,6 +1160,7 @@ protected:
uint32 casting_spell_timer_duration;
uint32 casting_spell_type;
int16 casting_spell_resist_adjust;
uint32 casting_spell_aa_id;
bool casting_spell_checks;
uint16 bardsong;
uint8 bardsong_slot;
@ -1311,6 +1327,9 @@ protected:
bool bEnraged;
bool destructibleobject;
std::unordered_map<uint32, std::pair<uint32, uint32>> aa_ranks;
Timer aa_timers[aaTimerMax];
private:
void _StopSong(); //this is not what you think it is
Mob* target;

View File

@ -342,7 +342,7 @@ bool NPC::AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgain
SetCurrentSpeed(0);
}
return CastSpell(AIspells[i].spellid, tar->GetID(), 1, AIspells[i].manacost == -2 ? 0 : -1, mana_cost, oDontDoAgainBefore, -1, -1, 0, 0, &(AIspells[i].resist_adjust));
return CastSpell(AIspells[i].spellid, tar->GetID(), 1, AIspells[i].manacost == -2 ? 0 : -1, mana_cost, oDontDoAgainBefore, -1, -1, 0, &(AIspells[i].resist_adjust));
}
bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float iRange, uint16 iSpellTypes) {

View File

@ -96,7 +96,6 @@ EntityList entity_list;
WorldServer worldserver;
uint32 numclients = 0;
char errorname[32];
uint16 adverrornum = 0;
extern Zone* zone;
EQStreamFactory eqsf(ZoneStream);
npcDecayTimes_Struct npcCorpseDecayTimes[100];
@ -249,9 +248,6 @@ int main(int argc, char** argv) {
Log.Out(Logs::General, Logs::Zone_Server, "Loading titles");
title_manager.LoadTitles();
Log.Out(Logs::General, Logs::Zone_Server, "Loading AA effects");
database.LoadAAEffects();
Log.Out(Logs::General, Logs::Zone_Server, "Loading tributes");
database.LoadTributes();

View File

@ -31,7 +31,6 @@
#include "../common/linked_list.h"
#include "../common/servertalk.h"
#include "aa.h"
#include "client.h"
#include "entity.h"
#include "npc.h"

View File

@ -4077,33 +4077,7 @@ XS(XS_Client_RefundAA) {
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
int curpt = 0;
bool refunded = false;
for(int x1=0;x1<aaHighestID;x1++){
curpt = THIS->GetAA(x1);
if(curpt > 0){
SendAA_Struct* curaa = zone->FindAA(x1);
if(curaa){
THIS->SetAA(x1, 0);
for(int x2=0;x2<curpt;x2++){ //add up all the AA points pt by pt to get the correct cost
THIS->GetPP().aapoints += curaa->cost + (curaa->cost_inc * x2);
refunded = true;
}
}
else //aa doesn't exist.. but if they bought it then it had at least a cost of 1 point each
{ //so give back what we can
THIS->GetPP().aapoints += curpt;
THIS->SetAA(x1, 0);
refunded = true;
}
}
}
if(refunded){
THIS->Save(); //save of course
THIS->Kick(); //client gets all buggy if we don't immediatly relog so just force it on them
}
THIS->RefundAA();
}
XSRETURN_EMPTY;
}
@ -4915,11 +4889,44 @@ XS(XS_Client_IncrementAA)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
THIS->IncrementAA(aaskillid);
THIS->IncrementAlternateAdvancementRank(aaskillid);
}
XSRETURN_EMPTY;
}
XS(XS_Client_GrantAlternateAdvancementAbility); /* prototype to pass -Wmissing-prototypes */
XS(XS_Client_GrantAlternateAdvancementAbility)
{
dXSARGS;
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)));
THIS = INT2PTR(Client *, tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type Client");
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
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));
}
XSRETURN(1);
}
XS(XS_Client_GetAALevel);
XS(XS_Client_GetAALevel)
{
@ -6463,6 +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, "GetAALevel"), XS_Client_GetAALevel, file, "$$");
newXSproto(strcpy(buf, "MarkCompassLoc"), XS_Client_MarkCompassLoc, file, "$$$$");
newXSproto(strcpy(buf, "ClearCompassMark"), XS_Client_ClearCompassMark, file, "$");

View File

@ -3998,9 +3998,9 @@ XS(XS_Mob_CastSpell)
}
if (resist_adjust == 0)//If you do not pass resist adjust as nullptr it will ignore the spells default resist adjust
THIS->CastSpell(spell_id, target_id, slot, casttime, mana_cost, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0);
THIS->CastSpell(spell_id, target_id, slot, casttime, mana_cost, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0);
else
THIS->CastSpell(spell_id, target_id, slot, casttime, mana_cost, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0, 0, &resist_adjust);
THIS->CastSpell(spell_id, target_id, slot, casttime, mana_cost, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0, &resist_adjust);
}
XSRETURN_EMPTY;
}
@ -6360,12 +6360,12 @@ XS(XS_Mob_GetAA)
{
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: Mob::GetAA(THIS, aa_id)");
Perl_croak(aTHX_ "Usage: Mob::GetAA(THIS, rank_id)");
{
Mob * THIS;
uint32 RETVAL;
dXSTARG;
uint32 aa_id = (uint32)SvUV(ST(1));
uint32 rank_id = (uint32)SvUV(ST(1));
if (sv_derived_from(ST(0), "Mob")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
@ -6376,12 +6376,68 @@ XS(XS_Mob_GetAA)
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetAA(aa_id);
RETVAL = THIS->GetAA(rank_id);
XSprePUSH; PUSHu((UV)RETVAL);
}
XSRETURN(1);
}
XS(XS_Mob_GetAAByAAID); /* prototype to pass -Wmissing-prototypes */
XS(XS_Mob_GetAAByAAID)
{
dXSARGS;
if(items != 2)
Perl_croak(aTHX_ "Usage: Mob::GetAAByAAID(THIS, aa_id)");
{
Mob * THIS;
uint32 RETVAL;
dXSTARG;
uint32 aa_id = (uint32)SvUV(ST(1));
if(sv_derived_from(ST(0), "Mob")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(Mob *, tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type Mob");
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetAAByAAID(aa_id);
XSprePUSH; PUSHu((UV)RETVAL);
}
XSRETURN(1);
}
XS(XS_Mob_SetAA); /* prototype to pass -Wmissing-prototypes */
XS(XS_Mob_SetAA)
{
dXSARGS;
if(items < 3 || items > 4)
Perl_croak(aTHX_ "Usage: Mob::SetAA(THIS, aa_id, points, [charges])");
{
Mob * THIS;
bool RETVAL;
int aa_id = (int)SvIV(ST(1));
int points = (int)SvIV(ST(2));
int charges = (items == 4) ? (int)SvIV(ST(3)) : 0;
if(sv_derived_from(ST(0), "Mob")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(Mob *, tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type Mob");
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->SetAA(aa_id, points, charges);
ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0));
}
XSRETURN(1);
}
XS(XS_Mob_DivineAura); /* prototype to pass -Wmissing-prototypes */
XS(XS_Mob_DivineAura)
{
@ -8625,6 +8681,8 @@ XS(boot_Mob)
newXSproto(strcpy(buf, "CheckAggroAmount"), XS_Mob_CheckAggroAmount, file, "$$");
newXSproto(strcpy(buf, "CheckHealAggroAmount"), XS_Mob_CheckHealAggroAmount, file, "$$");
newXSproto(strcpy(buf, "GetAA"), XS_Mob_GetAA, file, "$$");
newXSproto(strcpy(buf, "GetAAByAAID"), XS_Mob_GetAAByAAID, file, "$$");
newXSproto(strcpy(buf, "SetAA"), XS_Mob_SetAA, file, "$$$;$");
newXSproto(strcpy(buf, "DivineAura"), XS_Mob_DivineAura, file, "$");
newXSproto(strcpy(buf, "AddFeignMemory"), XS_Mob_AddFeignMemory, file, "$$");
newXSproto(strcpy(buf, "RemoveFromFeignMemory"), XS_Mob_RemoveFromFeignMemory, file, "$$");

View File

@ -149,22 +149,19 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage,
}
who->AddToHateList(this, hate, 0, false);
if (max_damage > 0 && aabonuses.SkillAttackProc[0] && aabonuses.SkillAttackProc[1] == skill &&
IsValidSpell(aabonuses.SkillAttackProc[2])) {
float chance = aabonuses.SkillAttackProc[0] / 1000.0f;
if (zone->random.Roll(chance))
SpellFinished(aabonuses.SkillAttackProc[2], who, 10, 0, -1,
spells[aabonuses.SkillAttackProc[2]].ResistDiff);
}
who->Damage(this, max_damage, SPELL_UNKNOWN, skill, false);
//Make sure 'this' has not killed the target and 'this' is not dead (Damage shield ect).
if(!GetTarget())return;
if (HasDied()) return;
//[AA Dragon Punch] value[0] = 100 for 25%, chance value[1] = skill
if(aabonuses.SpecialAttackKBProc[0] && aabonuses.SpecialAttackKBProc[1] == skill){
int kb_chance = 25;
kb_chance += kb_chance*(100-aabonuses.SpecialAttackKBProc[0])/100;
if (zone->random.Roll(kb_chance))
SpellFinished(904, who, 10, 0, -1, spells[904].ResistDiff);
//who->Stun(100); Kayen: This effect does not stun on live, it only moves the NPC.
}
if (HasSkillProcs())
TrySkillProc(who, skill, ReuseTime*1000);
@ -2442,19 +2439,18 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
}
other->AddToHateList(this, hate, 0, false);
if (damage > 0 && aabonuses.SkillAttackProc[0] && aabonuses.SkillAttackProc[1] == skillinuse &&
IsValidSpell(aabonuses.SkillAttackProc[2])) {
float chance = aabonuses.SkillAttackProc[0] / 1000.0f;
if (zone->random.Roll(chance))
SpellFinished(aabonuses.SkillAttackProc[2], other, 10, 0, -1,
spells[aabonuses.SkillAttackProc[2]].ResistDiff);
}
other->Damage(this, damage, SPELL_UNKNOWN, skillinuse);
if (HasDied())
return;
if(aabonuses.SpecialAttackKBProc[0] && aabonuses.SpecialAttackKBProc[1] == skillinuse){
int kb_chance = 25;
kb_chance += kb_chance*(100-aabonuses.SpecialAttackKBProc[0])/100;
if (zone->random.Roll(kb_chance))
SpellFinished(904, other, 10, 0, -1, spells[904].ResistDiff);
}
if (CanSkillProc && HasSkillProcs())
TrySkillProc(other, skillinuse, ReuseTime);

File diff suppressed because it is too large Load Diff

View File

@ -146,7 +146,8 @@ void NPC::SpellProcess()
// to allow procs to work
bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot,
int32 cast_time, int32 mana_cost, uint32* oSpellWillFinish, uint32 item_slot,
uint32 timer, uint32 timer_duration, uint32 type, int16 *resist_adjust)
uint32 timer, uint32 timer_duration, int16 *resist_adjust,
uint32 aa_id)
{
Log.Out(Logs::Detail, Logs::Spells, "CastSpell called for spell %s (%d) on entity %d, slot %d, time %d, mana %d, from item slot %d",
(IsValidSpell(spell_id))?spells[spell_id].name:"UNKNOWN SPELL", spell_id, target_id, slot, cast_time, mana_cost, (item_slot==0xFFFFFFFF)?999:item_slot);
@ -318,11 +319,11 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot,
if(resist_adjust)
{
return(DoCastSpell(spell_id, target_id, slot, cast_time, mana_cost, oSpellWillFinish, item_slot, timer, timer_duration, type, *resist_adjust));
return(DoCastSpell(spell_id, target_id, slot, cast_time, mana_cost, oSpellWillFinish, item_slot, timer, timer_duration, *resist_adjust, aa_id));
}
else
{
return(DoCastSpell(spell_id, target_id, slot, cast_time, mana_cost, oSpellWillFinish, item_slot, timer, timer_duration, type, spells[spell_id].ResistDiff));
return(DoCastSpell(spell_id, target_id, slot, cast_time, mana_cost, oSpellWillFinish, item_slot, timer, timer_duration, spells[spell_id].ResistDiff, aa_id));
}
}
@ -336,8 +337,8 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot,
//
bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot,
int32 cast_time, int32 mana_cost, uint32* oSpellWillFinish,
uint32 item_slot, uint32 timer, uint32 timer_duration, uint32 type,
int16 resist_adjust)
uint32 item_slot, uint32 timer, uint32 timer_duration,
int16 resist_adjust, uint32 aa_id)
{
Mob* pMob = nullptr;
int32 orgcasttime;
@ -361,7 +362,7 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot,
casting_spell_timer = timer;
casting_spell_timer_duration = timer_duration;
}
casting_spell_type = type;
casting_spell_aa_id = aa_id;
SaveSpellLoc();
Log.Out(Logs::Detail, Logs::Spells, "Casting %d Started at (%.3f,%.3f,%.3f)", spell_id, m_SpellLocation.x, m_SpellLocation.y, m_SpellLocation.z);
@ -408,24 +409,19 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot,
// ok now we know the target
casting_spell_targetid = target_id;
if (mana_cost == -1) {
// We don't get actual mana cost here, that's done when we consume the mana
if (mana_cost == -1)
mana_cost = spell.mana;
mana_cost = GetActSpellCost(spell_id, mana_cost);
}
if(HasMGB() && spells[spell_id].can_mgb)
mana_cost *= 2;
// mana is checked for clients on the frontend. we need to recheck it for NPCs though
// fix: items dont need mana :-/
// If you're at full mana, let it cast even if you dont have enough mana
// we calculated this above, now enforce it
if(mana_cost > 0 && slot != 10)
if(mana_cost > 0 && slot != USE_ITEM_SPELL_SLOT)
{
int my_curmana = GetMana();
int my_maxmana = GetMaxMana();
if(my_curmana < spell.mana) // not enough mana
if(my_curmana < mana_cost) // not enough mana
{
//this is a special case for NPCs with no mana...
if(IsNPC() && my_curmana == my_maxmana)
@ -783,9 +779,9 @@ void Mob::ZeroCastingVars()
casting_spell_inventory_slot = 0;
casting_spell_timer = 0;
casting_spell_timer_duration = 0;
casting_spell_type = 0;
casting_spell_resist_adjust = 0;
casting_spell_checks = false;
casting_spell_aa_id = 0;
delaytimer = false;
}
@ -816,10 +812,9 @@ void Mob::InterruptSpell(uint16 message, uint16 color, uint16 spellid)
CastToNPC()->AI_Event_SpellCastFinished(false, casting_spell_slot);
}
if(casting_spell_type == 1 && IsClient()) { //Rest AA Timer on failed cast
CastToClient()->SendAATimer(casting_spell_timer - pTimerAAStart, 0, 0xFFFFFF);
CastToClient()->Message_StringID(15,ABILITY_FAILED);
CastToClient()->GetPTimers().Clear(&database, casting_spell_timer);
if(casting_spell_aa_id && IsClient()) { //Rest AA Timer on failed cast
CastToClient()->Message_StringID(MT_SpellFailure, ABILITY_FAILED);
CastToClient()->ResetAlternateAdvancementTimer(casting_spell_aa_id);
}
ZeroCastingVars(); // resets all the state keeping stuff
@ -2078,7 +2073,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16
else if(!SpellOnTarget(spell_id, spell_target, false, true, resist_adjust, false, level_override)) {
if(IsBuffSpell(spell_id) && IsBeneficialSpell(spell_id)) {
// Prevent mana usage/timers being set for beneficial buffs
if(casting_spell_type == 1)
if(casting_spell_aa_id)
InterruptSpell();
return false;
}
@ -2157,11 +2152,11 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16
}
#endif //BOTS
// We hold off turning MBG off so we can still use it to calc the mana cost
if(spells[spell_id].can_mgb && HasMGB())
{
SpellOnTarget(spell_id, this);
entity_list.MassGroupBuff(this, this, spell_id, true);
SetMGB(false);
}
else
{
@ -2262,20 +2257,36 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16
}
// if this was a spell slot or an ability use up the mana for it
// CastSpell already reduced the cost for it if we're a client with focus
if(slot != USE_ITEM_SPELL_SLOT && slot != POTION_BELT_SPELL_SLOT && slot != TARGET_RING_SPELL_SLOT && mana_used > 0)
{
mana_used = GetActSpellCost(spell_id, mana_used);
if (HasMGB() && spells[spell_id].can_mgb) {
mana_used *= 2;
SetMGB(false);
}
// clamp if we some how got focused above our current mana
if (GetMana() < mana_used)
mana_used = GetMana();
Log.Out(Logs::Detail, Logs::Spells, "Spell %d: consuming %d mana", spell_id, mana_used);
if (!DoHPToManaCovert(mana_used))
if (!DoHPToManaCovert(mana_used)) {
SetMana(GetMana() - mana_used);
TryTriggerOnValueAmount(false, true);
}
}
//set our reuse timer on long ass reuse_time spells...
if(IsClient() && !isproc)
{
if(spell_id == casting_spell_id && casting_spell_timer != 0xFFFFFFFF)
if(casting_spell_aa_id) {
AA::Rank *rank = zone->GetAlternateAdvancementRank(casting_spell_aa_id);
if(rank && rank->base_ability) {
ExpendAlternateAdvancementCharge(rank->base_ability->id);
}
}
else if(spell_id == casting_spell_id && casting_spell_timer != 0xFFFFFFFF)
{
//aa new todo: aa expendable charges here
CastToClient()->GetPTimers().Start(casting_spell_timer, casting_spell_timer_duration);
Log.Out(Logs::Detail, Logs::Spells, "Spell %d: Setting custom reuse timer %d to %d", spell_id, casting_spell_timer, casting_spell_timer_duration);
}
@ -3753,7 +3764,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
// if SpellEffect returned false there's a problem applying the
// spell. It's most likely a buff that can't stack.
Log.Out(Logs::Detail, Logs::Spells, "Spell %d could not apply its effects %s -> %s\n", spell_id, GetName(), spelltar->GetName());
if(casting_spell_type != 1) // AA is handled differently
if(casting_spell_aa_id)
Message_StringID(MT_SpellFailure, SPELL_NO_HOLD);
safe_delete(action_packet);
return false;
@ -4116,8 +4127,7 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster)
}
return true;
}
else if (IsClient() && CastToClient()->CheckAAEffect(aaEffectWarcry))
else if (CheckAATimer(aaTimerWarcry))
{
Message(13, "Your are immune to fear.");
Log.Out(Logs::Detail, Logs::Spells, "Clients has WarCry effect, immune to fear!");

View File

@ -179,10 +179,10 @@ bool TitleManager::IsClientEligibleForTitle(Client *c, std::vector<TitleEntry>::
if((Title->Class >= 0) && (c->GetBaseClass() != Title->Class))
return false;
if((Title->MinAAPoints >= 0) && (c->GetAAPointsSpent() < static_cast<uint32>(Title->MinAAPoints)))
if((Title->MinAAPoints >= 0) && (c->GetSpentAA() < static_cast<uint32>(Title->MinAAPoints)))
return false;
if((Title->MaxAAPoints >= 0) && (c->GetAAPointsSpent() > static_cast<uint32>(Title->MaxAAPoints)))
if((Title->MaxAAPoints >= 0) && (c->GetSpentAA() > static_cast<uint32>(Title->MaxAAPoints)))
return false;
if(Title->SkillID >= 0)

View File

@ -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;

View File

@ -68,7 +68,6 @@ extern bool staticzone;
extern NetConnection net;
extern PetitionList petition_list;
extern QuestParserCollection* parse;
extern uint16 adverrornum;
extern uint32 numclients;
extern WorldServer worldserver;
extern Zone* zone;
@ -805,8 +804,6 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name)
weather_intensity = 0;
blocked_spells = nullptr;
totalBS = 0;
aas = nullptr;
totalAAs = 0;
zone_has_current_time = false;
Instance_Shutdown_Timer = nullptr;
@ -865,16 +862,6 @@ Zone::~Zone() {
safe_delete(qGlobals);
safe_delete_array(adv_data);
safe_delete_array(map_name);
if(aas != nullptr) {
int r;
for(r = 0; r < totalAAs; r++) {
uchar *data = (uchar *) aas[r];
safe_delete_array(data);
}
safe_delete_array(aas);
}
safe_delete(GuildBanks);
}
@ -953,16 +940,12 @@ bool Zone::Init(bool iStaticZone) {
zone->LoadAlternateCurrencies();
zone->LoadNPCEmotes(&NPCEmoteList);
//Load AA information
adverrornum = 500;
LoadAAs();
LoadAlternateAdvancement();
//Load merchant data
adverrornum = 501;
zone->GetMerchantDataForZoneLoad();
//Load temporary merchant data
adverrornum = 502;
zone->LoadTempMerchantData();
// Merc data
@ -974,7 +957,6 @@ bool Zone::Init(bool iStaticZone) {
if (RuleB(Zone, LevelBasedEXPMods))
zone->LoadLevelEXPMods();
adverrornum = 503;
petition_list.ClearPetitions();
petition_list.ReadDatabase();

View File

@ -27,6 +27,7 @@
#include "qglobals.h"
#include "spawn2.h"
#include "spawngroup.h"
#include "aa_ability.h"
struct ZonePoint
{
@ -113,11 +114,13 @@ public:
inline const uint32& GetMaxClients() { return pMaxClients; }
void LoadAAs();
int GetTotalAAs() { return totalAAs; }
SendAA_Struct* GetAABySequence(uint32 seq) { return aas[seq]; }
SendAA_Struct* FindAA(uint32 id);
uint8 GetTotalAALevels(uint32 skill_id);
//new AA
void LoadAlternateAdvancement();
AA::Ability *GetAlternateAdvancementAbility(int id);
AA::Ability *GetAlternateAdvancementAbilityByRank(int rank_id);
AA::Rank *GetAlternateAdvancementRank(int rank_id);
std::pair<AA::Ability*, AA::Rank*> GetAlternateAdvancementAbilityAndRank(int id, int points_spent);
void LoadZoneDoors(const char* zone, int16 version);
bool LoadZoneObjects();
bool LoadGroundSpawns();
@ -193,6 +196,10 @@ public:
char *adv_data;
bool did_adventure_actions;
//new AA
std::unordered_map<int, std::unique_ptr<AA::Ability>> aa_abilities;
std::unordered_map<int, std::unique_ptr<AA::Rank>> aa_ranks;
void DoAdventureCountIncrease();
void DoAdventureAssassinationCountIncrease();
void DoAdventureActions();
@ -313,9 +320,6 @@ private:
int totalBS;
ZoneSpellsBlocked *blocked_spells;
int totalAAs;
SendAA_Struct **aas; //array of AA structs
/*
Spawn related things
*/

View File

@ -6,6 +6,7 @@
#include "position.h"
#include "../common/faction.h"
#include "../common/eqemu_logsys.h"
#include "aa_ability.h"
class Client;
class Corpse;
@ -339,17 +340,10 @@ public:
bool SetCharacterFactionLevel(uint32 char_id, int32 faction_id, int32 value, uint8 temp, faction_map &val_list); // needed for factions Dec, 16 2001
bool LoadFactionData();
/* AAs */
bool LoadAAEffects();
bool LoadAAEffects2();
bool LoadSwarmSpells();
SendAA_Struct*GetAASkillVars(uint32 skill_id);
uint8 GetTotalAALevels(uint32 skill_id);
uint32 GetSizeAA();
uint32 CountAAs();
void LoadAAs(SendAA_Struct **load);
uint32 CountAAEffects();
void FillAAEffects(SendAA_Struct* aa_struct);
/* AAs New */
bool LoadAlternateAdvancementAbilities(std::unordered_map<int, std::unique_ptr<AA::Ability>> &abilities,
std::unordered_map<int, std::unique_ptr<AA::Rank>> &ranks);
bool LoadAlternateAdvancement(Client *c);
/* Zone related */
bool GetZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct *data, bool &can_bind, bool &can_combat, bool &can_levitate, bool &can_castoutdoor, bool &is_city, bool &is_hotzone, bool &allow_mercs, uint8 &zone_type, int &ruleset, char **map_filename);