Wards support is now fully extended to allow divine aura / stoneskin / intercept as possible solutions
Addresses issue #115 - minus fervor needs its own work implemented. AddWard(dmg,keepward,wardtype,damagetype,dmgabsorptionpct,damageabsorptionmaxhealthpct,redirectdmgpct,maxhitcount)
This commit is contained in:
parent
f4cf365345
commit
07c14f1d92
4 changed files with 96 additions and 9 deletions
|
@ -908,6 +908,8 @@ bool Entity::DamageSpawn(Entity* victim, int8 type, int8 damage_type, int32 low_
|
|||
|
||||
LogWrite(MISC__TODO, 3, "TODO", "Take players armor into account\nfile: %s, func: %s, line: %i)", __FILE__, __FUNCTION__, __LINE__);
|
||||
|
||||
bool useWards = false;
|
||||
|
||||
if(damage <= 0){
|
||||
hit_result = DAMAGE_PACKET_RESULT_NO_DAMAGE;
|
||||
damage = 0;
|
||||
|
@ -915,7 +917,12 @@ bool Entity::DamageSpawn(Entity* victim, int8 type, int8 damage_type, int32 low_
|
|||
else{
|
||||
hit_result = DAMAGE_PACKET_RESULT_SUCCESSFUL;
|
||||
GetZone()->CallSpawnScript(victim, SPAWN_SCRIPT_HEALTHCHANGED, this);
|
||||
damage = victim->CheckWards(damage, damage_type);
|
||||
int32 prevDmg = damage;
|
||||
damage = victim->CheckWards(this, damage, damage_type);
|
||||
|
||||
if (damage < prevDmg)
|
||||
useWards = true;
|
||||
|
||||
victim->TakeDamage(damage);
|
||||
victim->CheckProcs(PROC_TYPE_DAMAGED, this);
|
||||
|
||||
|
@ -953,6 +960,10 @@ bool Entity::DamageSpawn(Entity* victim, int8 type, int8 damage_type, int32 low_
|
|||
if (victim->IsEntity())
|
||||
((Entity*)victim)->CheckInterruptSpell(this);
|
||||
}
|
||||
else if (useWards)
|
||||
{
|
||||
GetZone()->SendDamagePacket(this, victim, DAMAGE_PACKET_TYPE_SIMPLE_DAMAGE, DAMAGE_PACKET_RESULT_NO_DAMAGE, damage_type, 0, spell_name);
|
||||
}
|
||||
|
||||
if (victim->GetHP() <= 0)
|
||||
KillSpawn(victim, damage_type, blow_type);
|
||||
|
|
|
@ -1263,7 +1263,7 @@ void Entity::RemoveWard(int32 spellID) {
|
|||
}
|
||||
}
|
||||
|
||||
int32 Entity::CheckWards(int32 damage, int8 damage_type) {
|
||||
int32 Entity::CheckWards(Entity* attacker, int32 damage, int8 damage_type) {
|
||||
map<int32, WardInfo*>::iterator itr;
|
||||
WardInfo* ward = 0;
|
||||
LuaSpell* spell = 0;
|
||||
|
@ -1272,7 +1272,7 @@ int32 Entity::CheckWards(int32 damage, int8 damage_type) {
|
|||
// Get the ward with the lowest base damage
|
||||
for (itr = m_wardList.begin(); itr != m_wardList.end(); itr++) {
|
||||
if (!ward || itr->second->BaseDamage < ward->BaseDamage) {
|
||||
if (itr->second->DamageLeft > 0 &&
|
||||
if ((itr->second->AbsorbAllDamage || itr->second->DamageLeft > 0) &&
|
||||
(itr->second->WardType == WARD_TYPE_ALL ||
|
||||
(itr->second->WardType == WARD_TYPE_PHYSICAL && damage_type >= DAMAGE_PACKET_DAMAGE_TYPE_SLASH && damage_type <= DAMAGE_PACKET_DAMAGE_TYPE_PIERCE) ||
|
||||
(itr->second->WardType == WARD_TYPE_MAGICAL && ((itr->second->DamageType == 0 && damage_type >= DAMAGE_PACKET_DAMAGE_TYPE_PIERCE) || (damage_type >= DAMAGE_PACKET_DAMAGE_TYPE_PIERCE && itr->second->DamageType == damage_type)))))
|
||||
|
@ -1285,6 +1285,12 @@ int32 Entity::CheckWards(int32 damage, int8 damage_type) {
|
|||
|
||||
spell = ward->Spell;
|
||||
|
||||
// damage to redirect at the source (like intercept)
|
||||
int32 redirectDamage = 0;
|
||||
if (ward->RedirectDamagePercent)
|
||||
redirectDamage = (int32)(double)damage * ((double)ward->RedirectDamagePercent / 100.0);
|
||||
|
||||
// percentage the spell absorbs of all possible damage
|
||||
int32 damageToAbsorb = 0;
|
||||
if (ward->DamageAbsorptionPercentage > 0)
|
||||
damageToAbsorb = (int32)(double)damage * ((double)ward->DamageAbsorptionPercentage/100.0);
|
||||
|
@ -1302,9 +1308,17 @@ int32 Entity::CheckWards(int32 damage, int8 damage_type) {
|
|||
|
||||
int32 baseDamageRemaining = damage - damageToAbsorb;
|
||||
|
||||
if (damageToAbsorb >= ward->DamageLeft) {
|
||||
bool hasSpellBeenRemoved = false;
|
||||
if (ward->AbsorbAllDamage)
|
||||
{
|
||||
ward->LastAbsorbedDamage = ward->DamageLeft;
|
||||
GetZone()->SendHealPacket(ward->Spell->caster, this, HEAL_PACKET_TYPE_ABSORB, damage, spell->spell->GetName());
|
||||
damage = 0;
|
||||
}
|
||||
else if (damageToAbsorb >= ward->DamageLeft) {
|
||||
// Damage is greater than or equal to the amount left on the ward
|
||||
|
||||
ward->LastAbsorbedDamage = ward->DamageLeft;
|
||||
// remove what damage we can absorb
|
||||
damageToAbsorb -= ward->DamageLeft;
|
||||
|
||||
|
@ -1315,13 +1329,16 @@ int32 Entity::CheckWards(int32 damage, int8 damage_type) {
|
|||
spell->damage_remaining = 0;
|
||||
GetZone()->SendHealPacket(spell->caster, this, HEAL_PACKET_TYPE_ABSORB, ward->DamageLeft, spell->spell->GetName());
|
||||
if (!ward->keepWard) {
|
||||
hasSpellBeenRemoved = true;
|
||||
RemoveWard(spell->spell->GetSpellID());
|
||||
GetZone()->GetSpellProcess()->DeleteCasterSpell(spell);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ward->LastAbsorbedDamage = damageToAbsorb;
|
||||
// Damage is less then the amount left on the ward
|
||||
ward->DamageLeft -= damageToAbsorb;
|
||||
|
||||
spell->damage_remaining = ward->DamageLeft;
|
||||
if (spell->caster->IsPlayer())
|
||||
ClientPacketFunctions::SendMaintainedExamineUpdate(GetZone()->GetClientBySpawn(spell->caster), spell->slot_pos, ward->DamageLeft, 1);
|
||||
|
@ -1331,6 +1348,31 @@ int32 Entity::CheckWards(int32 damage, int8 damage_type) {
|
|||
damage = baseDamageRemaining;
|
||||
}
|
||||
|
||||
if (redirectDamage)
|
||||
{
|
||||
ward->LastRedirectDamage = redirectDamage;
|
||||
if (attacker && spell->caster)
|
||||
attacker->DamageSpawn(spell->caster, DAMAGE_PACKET_TYPE_SPELL_DAMAGE, damage_type, redirectDamage, redirectDamage, 0);
|
||||
}
|
||||
|
||||
bool shouldRemoveSpell = false;
|
||||
ward->HitCount++; // increment hit count
|
||||
|
||||
if (ward->MaxHitCount && spell->num_triggers)
|
||||
{
|
||||
spell->num_triggers--;
|
||||
ClientPacketFunctions::SendMaintainedExamineUpdate(spell->caster->GetZone()->GetClientBySpawn(spell->caster), spell->slot_pos, spell->num_triggers, 0);
|
||||
}
|
||||
|
||||
if (ward->HitCount >= ward->MaxHitCount) // there isn't a max hit requirement with the hit count, so just go based on hit count
|
||||
shouldRemoveSpell = true;
|
||||
|
||||
if (shouldRemoveSpell && !hasSpellBeenRemoved)
|
||||
{
|
||||
RemoveWard(spell->spell->GetSpellID());
|
||||
GetZone()->GetSpellProcess()->DeleteCasterSpell(spell);
|
||||
}
|
||||
|
||||
// Reset ward pointer
|
||||
ward = 0;
|
||||
}
|
||||
|
|
|
@ -255,8 +255,17 @@ struct WardInfo {
|
|||
int8 WardType;
|
||||
int8 DamageType;
|
||||
bool keepWard;
|
||||
int8 DamageAbsorptionPercentage;
|
||||
int8 DamageAbsorptionMaxHealthPercent;
|
||||
int32 DamageAbsorptionPercentage;
|
||||
int32 DamageAbsorptionMaxHealthPercent;
|
||||
int32 RedirectDamagePercent;
|
||||
|
||||
int32 LastRedirectDamage;
|
||||
int32 LastAbsorbedDamage;
|
||||
|
||||
int32 HitCount;
|
||||
int32 MaxHitCount;
|
||||
|
||||
bool AbsorbAllDamage; // damage is always absorbed, usually spells based on hits, when we pass damage in AddWard as 0 this will be set to true
|
||||
};
|
||||
|
||||
#define WARD_TYPE_ALL 0
|
||||
|
@ -720,7 +729,7 @@ public:
|
|||
/// <summary>Subtracts the given damage from the wards</summary>
|
||||
/// <param name='damage'>The damage to subtract from the wards</param>
|
||||
/// <returns>The amount of damage left after wards</returns>
|
||||
int32 CheckWards(int32 damage, int8 damage_type);
|
||||
int32 CheckWards(Entity* attacker, int32 damage, int8 damage_type);
|
||||
|
||||
map<int16, float> stats;
|
||||
|
||||
|
|
|
@ -4934,8 +4934,10 @@ int EQ2Emu_lua_AddWard(lua_State* state) {
|
|||
bool keepWard = (lua_interface->GetInt8Value(state, 2) == 1);
|
||||
int8 wardType = lua_interface->GetInt8Value(state, 3);
|
||||
int8 damageTypes = lua_interface->GetInt8Value(state, 4);
|
||||
int8 damageAbsorptionPercent = lua_interface->GetInt8Value(state, 5);
|
||||
int8 damageAbsorptionMaxHealthPercent = lua_interface->GetInt8Value(state, 6);
|
||||
int32 damageAbsorptionPercent = lua_interface->GetInt32Value(state, 5);
|
||||
int32 damageAbsorptionMaxHealthPercent = lua_interface->GetInt32Value(state, 6);
|
||||
int32 redirectDamagePercent = lua_interface->GetInt32Value(state, 7);
|
||||
int32 maxHitCount = lua_interface->GetInt32Value(state, 8);
|
||||
|
||||
LuaSpell* spell = lua_interface->GetCurrentSpell(state);
|
||||
|
||||
|
@ -4957,6 +4959,8 @@ int EQ2Emu_lua_AddWard(lua_State* state) {
|
|||
ward->Spell = spell;
|
||||
ward->BaseDamage = damage;
|
||||
ward->DamageLeft = damage;
|
||||
ward->AbsorbAllDamage = (damage == 0) ? true : false;
|
||||
|
||||
ward->keepWard = keepWard;
|
||||
ward->WardType = wardType;
|
||||
if (damageAbsorptionPercent > 100)
|
||||
|
@ -4969,6 +4973,17 @@ int EQ2Emu_lua_AddWard(lua_State* state) {
|
|||
|
||||
ward->DamageAbsorptionMaxHealthPercent = damageAbsorptionMaxHealthPercent;
|
||||
|
||||
ward->RedirectDamagePercent = redirectDamagePercent;
|
||||
|
||||
ward->LastRedirectDamage = 0;
|
||||
ward->LastAbsorbedDamage = 0;
|
||||
ward->HitCount = 0;
|
||||
|
||||
spell->num_triggers = maxHitCount;
|
||||
spell->had_triggers = true;
|
||||
spell->cancel_after_all_triggers = false;
|
||||
ward->MaxHitCount = maxHitCount;
|
||||
|
||||
if (wardType == WARD_TYPE_MAGICAL)
|
||||
ward->DamageType = damageTypes;
|
||||
|
||||
|
@ -5069,6 +5084,16 @@ int EQ2Emu_lua_GetWardValue(lua_State* state) {
|
|||
lua_interface->SetInt32Value(state, ward->DamageAbsorptionPercentage);
|
||||
else if (boost::iequals(type, "dmgabsorptionmaxhealthpct"))
|
||||
lua_interface->SetInt32Value(state, ward->DamageAbsorptionMaxHealthPercent);
|
||||
else if (boost::iequals(type, "redirectdamagepercent"))
|
||||
lua_interface->SetInt32Value(state, ward->RedirectDamagePercent);
|
||||
else if (boost::iequals(type, "lastredirectdamage"))
|
||||
lua_interface->SetInt32Value(state, ward->LastRedirectDamage);
|
||||
else if (boost::iequals(type, "lastabsorbeddamage"))
|
||||
lua_interface->SetInt32Value(state, ward->LastAbsorbedDamage);
|
||||
else if (boost::iequals(type, "hitcount"))
|
||||
lua_interface->SetInt32Value(state, ward->HitCount);
|
||||
else if (boost::iequals(type, "maxhitcount"))
|
||||
lua_interface->SetInt32Value(state, ward->MaxHitCount);
|
||||
else
|
||||
lua_interface->LogError("%s: LUA GetWardValue command argument type '%s' did not match any options", lua_interface->GetScriptName(state), type);
|
||||
return 1;
|
||||
|
|
Loading…
Add table
Reference in a new issue