[Spells] Implemented SPA 415 SE_FFItemClass (#1688)

* prelim

* Spell Focus implemented

* AA implemented

* Update spdat.h

* Update spdat.h

* prelim excludes

* enum limit expansion

* overhaul

* v2 testing

* updates

* working

* Fin

* Update spell_effects.cpp

* Update spell_effects.cpp

* var fix

* Update spell_effects.cpp

make it not apply to casted spells... oops

* Update spell_effects.cpp

* Update spell_effects.cpp
This commit is contained in:
KayenEQ
2021-11-07 16:35:30 -05:00
committed by GitHub
parent 1cdb1816a2
commit 7f497f9d32
3 changed files with 154 additions and 5 deletions
+147 -1
View File
@@ -3266,6 +3266,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
case SE_Buy_AA_Rank:
case SE_Ff_FocusTimerMin:
case SE_Proc_Timer_Modifier:
case SE_FFItemClass:
{
break;
}
@@ -4548,6 +4549,7 @@ int32 Client::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id)
10/11 SE_LimitCastingSkill:
12/13 SE_LimitSpellClass:
14/15 SE_LimitSpellSubClass:
16/17 SE_FFItemCLass:
Remember: Update MaxLimitInclude in spdat.h if adding new limits that require Includes
*/
@@ -4891,6 +4893,59 @@ int32 Client::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id)
}
break;
case SE_FFItemClass:
if (casting_spell_inventory_slot && casting_spell_inventory_slot != -1) {
if (IsClient() && casting_spell_slot == EQ::spells::CastingSlot::Item && casting_spell_inventory_slot != 0xFFFFFFFF) {
auto item = CastToClient()->GetInv().GetItem(casting_spell_inventory_slot);
if (item && item->GetItem()) {
//If ItemType set to < -1, then we will exclude either all Subtypes (-1000), or specific items by ItemType, SubType or Slot. See above for rules.
if (base_value < -1) { //Excludes
bool exclude_this_item = true;
int tmp_itemtype = (item->GetItem()->ItemType + 100) * -1;
//ItemType (if set to -1000, ignore and exclude any ItemType)
if (base_value < -1 && base_value != -1000) {
if (base_value != tmp_itemtype) {
exclude_this_item = false;
}
}
//SubType (if set to -1, ignore and exclude all SubTypes)
if (limit_value >= 0) {
if (limit_value != item->GetItem()->SubType) {
exclude_this_item = false;
}
}
if (exclude_this_item) {
LimitFailure = true;
}
}
else {//Includes
LimitInclude[IncludeExistsSEFFItemClass] = true;
bool include_this_item = true;
//ItemType (if set to -1, ignore and include any ItemType)
if (base_value >= 0) {
if (base_value != item->GetItem()->ItemType) {
include_this_item = false;
}
}
//SubType (if set to -1, ignore and include any SubType)
if (limit_value >= 0) {
if (limit_value != item->GetItem()->SubType) {
include_this_item = false;
}
}
if (include_this_item) {
LimitInclude[IncludeFoundSEFFItemClass] = true;
}
}
}
}
}
//If this is checking that focus can only be cast from an item, then if its not cast from item fail.
else if (base_value >= -1) {
LimitFailure = true;
}
//If we are checking to exclude items from a focus then do not fail unless the above check fails.
break;
/* These are not applicable to AA's because there is never a 'caster' of the 'buff' with the focus effect.
case SE_Ff_Same_Caster:
@@ -5239,13 +5294,14 @@ int32 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
10/11 SE_LimitCastingSkill:
12/13 SE_LimitSpellClass:
14/15 SE_LimitSpellSubClass:
16/17 SE_FFItemCLass:
Remember: Update MaxLimitInclude in spdat.h if adding new limits that require Includes
*/
for (int i = 0; i < EFFECT_COUNT; i++) {
switch (focus_spell.effect_id[i]) {
case SE_Blank:
break;
@@ -5567,6 +5623,96 @@ int32 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
}
break;
case SE_FFItemClass:
/*
Limits focuses to check if cast from item clicks. Can be used to INCLUDE or EXCLUDE items by ItemType and/or SubType and/or Slots
Not used on live, going on information we have plus implemented as broadly as possible to allow all possible options.
base = item table field 'ItemType' Limit = item table field 'SubType' Max = item table field 'Slots' (this is slot bitmask)
When including: Setting base, limit, max respectively to -1 will cause it to ignore that check, letting any type or slot ect be used.
Special rules for excluding. base value needs to be negative < -1, if excluding all ItemTypes set to -1000.
For SubType and Slots set using same rules above as for includes. Ie. -1 for all, positive for specifics
To exclude a specific ItemType we have to do some math. The exclude value will be the negative value of (ItemType + 100).
If ItemType = 10, then SET ItemType= -110 to exclude. If its ItemType 0, then SET ItemType= -100 to exclude ect. Not ideal but it works.
Usage example: [INCLUDE] Only focus spell if from click cast and is a 'defense armor' item type=10 [base= 10, limit= -1, max= -1]
Usage example: [INCLUDE] Only focus spell if from click cast and is from helmet slot' slots= 4 [base= -1, limit= -1, max= 4]
Usage example: [EXCLUDE] Do not focus spell if it is from an item click. [base= -1000, limit= -1, max= -1]
Usage example: [EXCLUDE] Do not focus spell if it is from an item click from a helmet slot. [base= -1000, limit= -1, max= 4]
Usage example: [EXCLUDE] Do not focus spell if it is from an item click and is a 'defense armor' item type=10. [base= -110, limit= -1, max= -1]
Note: You can apply multiple includes or excludes to a single focus spell, using multiple SPA 415 limits in the spell. Ie. Check for clicks from ItemType 10 or 11.
*/
if (casting_spell_inventory_slot && casting_spell_inventory_slot != -1) {
if (IsClient() && casting_spell_slot == EQ::spells::CastingSlot::Item && casting_spell_inventory_slot != 0xFFFFFFFF) {
auto item = CastToClient()->GetInv().GetItem(casting_spell_inventory_slot);
if (item && item->GetItem()) {
//If ItemType set to < -1, then we will exclude either all Subtypes (-1000), or specific items by ItemType, SubType or Slot. See above for rules.
if (focus_spell.base_value[i] < -1) { //Excludes
bool exclude_this_item = true;
int tmp_itemtype = (item->GetItem()->ItemType + 100) * -1;
//ItemType (if set to -1000, ignore and exclude any ItemType)
if (focus_spell.base_value[i] < -1 && focus_spell.base_value[i] != -1000) {
if (focus_spell.base_value[i] != tmp_itemtype) {
exclude_this_item = false;
}
}
//SubType (if set to -1, ignore and exclude all SubTypes)
if (focus_spell.limit_value[i] >= 0) {
if (focus_spell.limit_value[i] != item->GetItem()->SubType) {
exclude_this_item = false;
}
}
//item slot bitmask (if set to -1, ignore and exclude all SubTypes)
if (focus_spell.max_value[i] >= 0) {
if (focus_spell.max_value[i] != item->GetItem()->Slots) {
exclude_this_item = false;
}
}
if (exclude_this_item) {
return 0;
}
}
else {//Includes
LimitInclude[IncludeExistsSEFFItemClass] = true;
bool include_this_item = true;
//ItemType (if set to -1, ignore and include any ItemType)
if (focus_spell.base_value[i] >= 0) {
if (focus_spell.base_value[i] != item->GetItem()->ItemType) {
include_this_item = false;
}
}
//SubType (if set to -1, ignore and include any SubType)
if (focus_spell.limit_value[i] >= 0) {
if (focus_spell.limit_value[i] != item->GetItem()->SubType) {
include_this_item = false;
}
}
//item slot bitmask (if set to -1, ignore and include any slot)
if (focus_spell.max_value[i] >= 0) {
if (focus_spell.max_value[i] != item->GetItem()->Slots) {
include_this_item = false;
}
}
if (include_this_item) {
LimitInclude[IncludeFoundSEFFItemClass] = true;
}
}
}
}
}
//If this is checking that focus can only be cast from an item, then if its not cast from item fail.
else if (focus_spell.base_value[i] >= -1) {
return 0;
}
//If we are checking to exclude items from a focus then do not fail unless the above check fails.
break;
// handle effects
case SE_ImprovedDamage:
if (type == focusImprovedDamage) {