mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-19 17:38:26 +00:00
[Feature] Implemented /shield ability and related affects (#1494)
* shield ability initial work
* updates
* update
* updates
* Update client_process.cpp
* major updates
optimized
pet support
perl support
* updates
* minor update
* fix merge error
* requested changes
* variable fix
* optimization
* minor update
* Revert "optimization"
This reverts commit 27e11e758b.
* fix
reset variables on shield_target if shielder dies or zones during shielding.
* edge case fix
Catch and fix situations where shield target doesn't have shielder variable cleared. Can occur if shielder . uses ability when target is not in combat then zones.
* combined packet and mob function
Shield now uses a common pathway through ShieldAbility, added parameters to perl function
* Addressing formatting for Kayen
* Fix function typo
Co-authored-by: Akkadius <akkadius1@gmail.com>
This commit is contained in:
+126
-9
@@ -261,7 +261,6 @@ Mob::Mob(
|
||||
MR = CR = FR = DR = PR = Corrup = PhR = 0;
|
||||
ExtraHaste = 0;
|
||||
bEnraged = false;
|
||||
shield_target = nullptr;
|
||||
current_mana = 0;
|
||||
max_mana = 0;
|
||||
hp_regen = in_hp_regen;
|
||||
@@ -376,11 +375,13 @@ Mob::Mob(
|
||||
silenced = false;
|
||||
amnesiad = false;
|
||||
inWater = false;
|
||||
int m;
|
||||
for (m = 0; m < MAX_SHIELDERS; m++) {
|
||||
shielder[m].shielder_id = 0;
|
||||
shielder[m].shielder_bonus = 0;
|
||||
}
|
||||
|
||||
shield_timer.Disable();
|
||||
m_shield_target_id = 0;
|
||||
m_shielder_id = 0;
|
||||
m_shield_target_mitigation = 0;
|
||||
m_shielder_mitigation = 0;
|
||||
m_shielder_max_distance = 0;
|
||||
|
||||
destructibleobject = false;
|
||||
wandertype = 0;
|
||||
@@ -3144,7 +3145,7 @@ int32 Mob::GetActSpellCasttime(uint16 spell_id, int32 casttime)
|
||||
cast_reducer += cast_reducer_no_limit;
|
||||
casttime = casttime * (100 - cast_reducer) / 100;
|
||||
casttime -= cast_reducer_amt;
|
||||
|
||||
|
||||
return std::max(casttime, 0);
|
||||
|
||||
}
|
||||
@@ -4944,11 +4945,11 @@ int16 Mob::GetPositionalDmgAmt(Mob* defender)
|
||||
|
||||
if (back_arc_dmg_amt || front_arc_dmg_amt) {
|
||||
if (BehindMob(defender, GetX(), GetY()))
|
||||
total_amt = back_arc_dmg_amt;
|
||||
total_amt = back_arc_dmg_amt;
|
||||
else
|
||||
total_amt = front_arc_dmg_amt;
|
||||
}
|
||||
|
||||
|
||||
return total_amt;
|
||||
}
|
||||
|
||||
@@ -6196,6 +6197,122 @@ float Mob::GetDefaultRaceSize() const {
|
||||
return GetRaceGenderDefaultHeight(race, gender);
|
||||
}
|
||||
|
||||
bool Mob::ShieldAbility(uint32 target_id, int shielder_max_distance, int shield_duration, int shield_target_mitigation, int shielder_mitigation, bool use_aa, bool can_shield_npc)
|
||||
{
|
||||
Mob* shield_target = entity_list.GetMob(target_id);
|
||||
if (!shield_target) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!can_shield_npc && shield_target->IsNPC()) {
|
||||
if (IsClient()) {
|
||||
MessageString(Chat::White, SHIELD_TARGET_NPC);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (shield_target->GetID() == GetID()) { //Client will give message "You can not shield yourself"
|
||||
return false;
|
||||
}
|
||||
|
||||
//Edge case situations. If 'Shield Target' still has Shielder set but Shielder is not in zone. Catch and fix here.
|
||||
if (shield_target->GetShielderID() && !entity_list.GetMob(shield_target->GetShielderID())) {
|
||||
shield_target->SetShielderID(0);
|
||||
}
|
||||
|
||||
if (GetShielderID() && !entity_list.GetMob(GetShielderID())) {
|
||||
SetShielderID(0);
|
||||
}
|
||||
|
||||
//You have a shielder, or your 'Shield Target' already has a 'Shielder'
|
||||
if (GetShielderID() || shield_target->GetShielderID()) {
|
||||
if (IsClient()) {
|
||||
MessageString(Chat::White, ALREADY_SHIELDED);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//You are being shielded or already have a 'Shield Target'
|
||||
if (GetShieldTargetID() || shield_target->GetShieldTargetID()) {
|
||||
if (IsClient()) {
|
||||
MessageString(Chat::White, ALREADY_SHIELDING);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//AA to increase SPA 230 extended shielding (default live is 15 distance units)
|
||||
if (use_aa) {
|
||||
shielder_max_distance += aabonuses.ExtendedShielding + itembonuses.ExtendedShielding + spellbonuses.ExtendedShielding;
|
||||
shielder_max_distance = std::max(shielder_max_distance, 0);
|
||||
}
|
||||
|
||||
if (shield_target->CalculateDistance(GetX(), GetY(), GetZ()) > static_cast<float>(shielder_max_distance)) {
|
||||
return false; //Live does not give a message when out of range.
|
||||
}
|
||||
|
||||
entity_list.MessageCloseString(this, false, 100, 0, START_SHIELDING, GetCleanName(), shield_target->GetCleanName());
|
||||
|
||||
SetShieldTargetID(shield_target->GetID());
|
||||
SetShielderMitigation(shield_target_mitigation);
|
||||
SetShielderMaxDistance(shielder_max_distance);
|
||||
|
||||
shield_target->SetShielderID(GetID());
|
||||
shield_target->SetShieldTargetMitigation(shield_target_mitigation);
|
||||
|
||||
//Calculate AA for adding time SPA 255 extend shield duration (Baseline ability is 12 seconds)
|
||||
if (use_aa) {
|
||||
shield_duration += (aabonuses.ShieldDuration + itembonuses.ShieldDuration + spellbonuses.ShieldDuration) * 1000;
|
||||
shield_duration = std::max(shield_duration, 1); //Incase of negative modifiers lets just make min duration 1 ms.
|
||||
}
|
||||
|
||||
shield_timer.Start(static_cast<uint32>(shield_duration));
|
||||
return true;
|
||||
}
|
||||
|
||||
void Mob::ShieldAbilityFinish()
|
||||
{
|
||||
Mob* shield_target = entity_list.GetMob(GetShieldTargetID());
|
||||
|
||||
if (shield_target) {
|
||||
entity_list.MessageCloseString(this, false, 100, 0, END_SHIELDING, GetCleanName(), shield_target->GetCleanName());
|
||||
shield_target->SetShielderID(0);
|
||||
shield_target->SetShieldTargetMitigation(0);
|
||||
}
|
||||
SetShieldTargetID(0);
|
||||
SetShielderMitigation(0);
|
||||
SetShielderMaxDistance(0);
|
||||
shield_timer.Disable();
|
||||
}
|
||||
|
||||
void Mob::ShieldAbilityClearVariables()
|
||||
{
|
||||
//If 'shield target' dies
|
||||
if (GetShielderID()){
|
||||
Mob* shielder = entity_list.GetMob(GetShielderID());
|
||||
if (shielder) {
|
||||
shielder->SetShieldTargetID(0);
|
||||
shielder->SetShielderMitigation(0);
|
||||
shielder->SetShielderMaxDistance(0);
|
||||
shielder->shield_timer.Disable();
|
||||
}
|
||||
SetShielderID(0);
|
||||
SetShieldTargetMitigation(0);
|
||||
}
|
||||
|
||||
//If 'shielder' dies
|
||||
if (GetShieldTargetID()) {
|
||||
Mob* shield_target = entity_list.GetMob(GetShieldTargetID());
|
||||
if (shield_target) {
|
||||
shield_target->SetShielderID(0);
|
||||
shield_target->SetShieldTargetMitigation(0);
|
||||
}
|
||||
SetShieldTargetID(0);
|
||||
SetShielderMitigation(0);
|
||||
SetShielderMaxDistance(0);
|
||||
shield_timer.Disable();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BOTS
|
||||
bool Mob::JoinHealRotationTargetPool(std::shared_ptr<HealRotation>* heal_rotation)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user