mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 02:11:30 +00:00
[Spells] Allow item click effects to have cast time and recast time modified by focus effects. (#1695)
* prelim * Spell Focus implemented * AA implemented * Update spdat.h * Update spdat.h * working * Update spells.cpp * prelim excludes * enum limit expansion * overhaul * v2 testing * updates * working * Fin * Update spell_effects.cpp * Update spell_effects.cpp * update * Update spells.cpp * fix * fix * Update spell_effects.cpp * remove debugs * Update spells.cpp
This commit is contained in:
parent
990729fe21
commit
d9c8e80bca
@ -4539,13 +4539,21 @@ int32 Client::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id)
|
||||
int spell_level = 0;
|
||||
int lvldiff = 0;
|
||||
uint32 effect = 0;
|
||||
int32 base_value = 0;
|
||||
int32 limit_value = 0;
|
||||
int32 base_value = 0;
|
||||
int32 limit_value = 0;
|
||||
uint32 slot = 0;
|
||||
|
||||
int index_id = -1;
|
||||
uint32 focus_reuse_time = 0;
|
||||
|
||||
bool is_from_item_click = false;
|
||||
bool try_apply_to_item_click = false;
|
||||
bool has_item_limit_check = false;
|
||||
|
||||
if (casting_spell_inventory_slot && casting_spell_inventory_slot != -1) {
|
||||
is_from_item_click = true;
|
||||
}
|
||||
|
||||
bool LimitFailure = false;
|
||||
bool LimitInclude[MaxLimitInclude] = {false};
|
||||
/* Certain limits require only one of several Include conditions to be true. Ie. Add damage to fire OR ice
|
||||
@ -4903,6 +4911,7 @@ int32 Client::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id)
|
||||
break;
|
||||
|
||||
case SE_FFItemClass:
|
||||
has_item_limit_check = true;
|
||||
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);
|
||||
@ -4995,18 +5004,21 @@ int32 Client::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id)
|
||||
case SE_IncreaseSpellHaste:
|
||||
if (type == focusSpellHaste && base_value > value) {
|
||||
value = base_value;
|
||||
try_apply_to_item_click = is_from_item_click ? true : false;
|
||||
}
|
||||
break;
|
||||
|
||||
case SE_Fc_CastTimeMod2:
|
||||
if (type == focusFcCastTimeMod2 && base_value > value) {
|
||||
value = base_value;
|
||||
try_apply_to_item_click = is_from_item_click ? true : false;
|
||||
}
|
||||
break;
|
||||
|
||||
case SE_Fc_CastTimeAmt:
|
||||
if (type == focusFcCastTimeAmt && base_value > value) {
|
||||
value = base_value;
|
||||
try_apply_to_item_click = is_from_item_click ? true : false;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -5081,6 +5093,7 @@ int32 Client::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id)
|
||||
case SE_ReduceReuseTimer:
|
||||
if (type == focusReduceRecastTime) {
|
||||
value = base_value / 1000;
|
||||
try_apply_to_item_click = is_from_item_click ? true : false;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -5247,6 +5260,10 @@ int32 Client::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id)
|
||||
}
|
||||
}
|
||||
|
||||
if (try_apply_to_item_click && !has_item_limit_check) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (LimitFailure) {
|
||||
return 0;
|
||||
}
|
||||
@ -5290,6 +5307,14 @@ int32 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
|
||||
uint32 Caston_spell_id = 0;
|
||||
int index_id = -1;
|
||||
uint32 focus_reuse_time = 0; //If this is set and all limits pass, start timer at end of script.
|
||||
|
||||
bool is_from_item_click = false;
|
||||
bool try_apply_to_item_click = false;
|
||||
bool has_item_limit_check = false;
|
||||
|
||||
if (casting_spell_inventory_slot && casting_spell_inventory_slot != -1) {
|
||||
is_from_item_click = true;
|
||||
}
|
||||
|
||||
bool LimitInclude[MaxLimitInclude] = {false};
|
||||
/* Certain limits require only one of several Include conditions to be true. Determined by limits being negative or positive
|
||||
@ -5638,14 +5663,14 @@ int32 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
|
||||
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.
|
||||
|
||||
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]
|
||||
@ -5653,9 +5678,9 @@ int32 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
|
||||
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.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
has_item_limit_check = true;
|
||||
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);
|
||||
@ -5756,18 +5781,21 @@ int32 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
|
||||
case SE_IncreaseSpellHaste:
|
||||
if (type == focusSpellHaste && focus_spell.base_value[i] > value) {
|
||||
value = focus_spell.base_value[i];
|
||||
try_apply_to_item_click = is_from_item_click ? true : false;
|
||||
}
|
||||
break;
|
||||
|
||||
case SE_Fc_CastTimeMod2:
|
||||
if (type == focusFcCastTimeMod2 && focus_spell.base_value[i] > value) {
|
||||
value = focus_spell.base_value[i];
|
||||
try_apply_to_item_click = is_from_item_click ? true : false;
|
||||
}
|
||||
break;
|
||||
|
||||
case SE_Fc_CastTimeAmt:
|
||||
if (type == focusFcCastTimeAmt && focus_spell.base_value[i] > value) {
|
||||
value = focus_spell.base_value[i];
|
||||
try_apply_to_item_click = is_from_item_click ? true : false;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -5828,6 +5856,7 @@ int32 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
|
||||
case SE_ReduceReuseTimer:
|
||||
if (type == focusReduceRecastTime) {
|
||||
value = focus_spell.base_value[i] / 1000;
|
||||
try_apply_to_item_click = is_from_item_click ? true : false;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -6011,6 +6040,15 @@ int32 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
For item click cast/recast focus modifiers. Only use if SPA 415 exists.
|
||||
This is an item click but does not have SPA 415 limiter. Fail here.
|
||||
*/
|
||||
|
||||
if (try_apply_to_item_click && !has_item_limit_check) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Caston_spell_id) {
|
||||
if (IsValidSpell(Caston_spell_id) && (Caston_spell_id != spell_id)) {
|
||||
|
||||
@ -417,14 +417,21 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
|
||||
target_id = GetID();
|
||||
}
|
||||
|
||||
if(cast_time <= -1) {
|
||||
if (cast_time <= -1) {
|
||||
// save the non-reduced cast time to use in the packet
|
||||
cast_time = orgcasttime = spell.cast_time;
|
||||
// if there's a cast time, check if they have a modifier for it
|
||||
if(cast_time) {
|
||||
if (cast_time) {
|
||||
cast_time = GetActSpellCasttime(spell_id, cast_time);
|
||||
}
|
||||
}
|
||||
//must use SPA 415 with focus (SPA 127/500/501) to reduce item recast
|
||||
else if (cast_time && IsClient() && slot == CastingSlot::Item && item_slot != 0xFFFFFFFF) {
|
||||
orgcasttime = cast_time;
|
||||
if (cast_time) {
|
||||
cast_time = GetActSpellCasttime(spell_id, cast_time);
|
||||
}
|
||||
}
|
||||
else
|
||||
orgcasttime = cast_time;
|
||||
|
||||
@ -2543,6 +2550,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, ui
|
||||
recast -= GetAA(aaTouchoftheWicked) * 420;
|
||||
}
|
||||
int reduction = CastToClient()->GetFocusEffect(focusReduceRecastTime, spell_id);//Client only
|
||||
|
||||
if(reduction)
|
||||
recast -= reduction;
|
||||
|
||||
@ -2556,20 +2564,32 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, ui
|
||||
EQ::ItemInstance *itm = CastToClient()->GetInv().GetItem(inventory_slot);
|
||||
if(itm && itm->GetItem()->RecastDelay > 0){
|
||||
auto recast_type = itm->GetItem()->RecastType;
|
||||
CastToClient()->GetPTimers().Start((pTimerItemStart + recast_type), itm->GetItem()->RecastDelay);
|
||||
if (recast_type != -1) {
|
||||
database.UpdateItemRecastTimestamps(
|
||||
CastToClient()->CharacterID(),
|
||||
recast_type,
|
||||
CastToClient()->GetPTimers().Get(pTimerItemStart + recast_type)->GetReadyTimestamp()
|
||||
);
|
||||
int recast_delay = itm->GetItem()->RecastDelay;
|
||||
//must use SPA 415 with focus (SPA 310) to reduce item recast
|
||||
int reduction = CastToClient()->GetFocusEffect(focusReduceRecastTime, spell_id);
|
||||
if (reduction) {
|
||||
recast_delay -= reduction;
|
||||
}
|
||||
recast_delay = std::max(recast_delay, 0);
|
||||
|
||||
if (recast_delay > 0) {
|
||||
|
||||
CastToClient()->GetPTimers().Start((pTimerItemStart + recast_type), recast_delay);
|
||||
if (recast_type != -1) {
|
||||
database.UpdateItemRecastTimestamps(
|
||||
CastToClient()->CharacterID(),
|
||||
recast_type,
|
||||
CastToClient()->GetPTimers().Get(pTimerItemStart + recast_type)->GetReadyTimestamp()
|
||||
);
|
||||
}
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_ItemRecastDelay, sizeof(ItemRecastDelay_Struct));
|
||||
ItemRecastDelay_Struct *ird = (ItemRecastDelay_Struct *)outapp->pBuffer;
|
||||
ird->recast_delay = static_cast<uint32>(recast_delay);
|
||||
ird->recast_type = recast_type;
|
||||
CastToClient()->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
auto outapp = new EQApplicationPacket(OP_ItemRecastDelay, sizeof(ItemRecastDelay_Struct));
|
||||
ItemRecastDelay_Struct *ird = (ItemRecastDelay_Struct *)outapp->pBuffer;
|
||||
ird->recast_delay = itm->GetItem()->RecastDelay;
|
||||
ird->recast_type = recast_type;
|
||||
CastToClient()->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user