mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 21:01:29 +00:00
[Feature] NPCs with bows and arrows do ranged attacks (#2322)
* NPCs with bows and arrows do ranged attacks Who knew!! * PR comments Co-authored-by: Akkadius <akkadius1@gmail.com>
This commit is contained in:
parent
0f9427098d
commit
dd71420a0e
@ -400,6 +400,16 @@ void NPC::AddLootDrop(
|
|||||||
item->trivial_max_level = loot_drop.trivial_max_level;
|
item->trivial_max_level = loot_drop.trivial_max_level;
|
||||||
item->equip_slot = EQ::invslot::SLOT_INVALID;
|
item->equip_slot = EQ::invslot::SLOT_INVALID;
|
||||||
|
|
||||||
|
|
||||||
|
// unsure if required to equip, YOLO for now
|
||||||
|
if (item2->ItemType == EQ::item::ItemTypeBow) {
|
||||||
|
SetBowEquipped(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item2->ItemType == EQ::item::ItemTypeArrow) {
|
||||||
|
SetArrowEquipped(true);
|
||||||
|
}
|
||||||
|
|
||||||
if (loot_drop.equip_item > 0) {
|
if (loot_drop.equip_item > 0) {
|
||||||
uint8 eslot = 0xFF;
|
uint8 eslot = 0xFF;
|
||||||
char newid[20];
|
char newid[20];
|
||||||
|
|||||||
@ -480,6 +480,11 @@ public:
|
|||||||
bool HasTwoHanderEquipped() { return has_twohanderequipped; }
|
bool HasTwoHanderEquipped() { return has_twohanderequipped; }
|
||||||
void SetTwoHanderEquipped(bool val) { has_twohanderequipped = val; }
|
void SetTwoHanderEquipped(bool val) { has_twohanderequipped = val; }
|
||||||
bool HasDualWeaponsEquiped() const { return has_duelweaponsequiped; }
|
bool HasDualWeaponsEquiped() const { return has_duelweaponsequiped; }
|
||||||
|
bool HasBowEquipped() const { return has_bowequipped; }
|
||||||
|
void SetBowEquipped(bool val) { has_bowequipped = val; }
|
||||||
|
bool HasArrowEquipped() const { return has_arrowequipped; }
|
||||||
|
void SetArrowEquipped(bool val) { has_arrowequipped = val; }
|
||||||
|
bool HasBowAndArrowEquipped() const { return HasBowEquipped() && HasArrowEquipped(); }
|
||||||
inline void SetDuelWeaponsEquiped(bool val) { has_duelweaponsequiped = val; }
|
inline void SetDuelWeaponsEquiped(bool val) { has_duelweaponsequiped = val; }
|
||||||
bool CanFacestab() { return can_facestab; }
|
bool CanFacestab() { return can_facestab; }
|
||||||
void SetFacestab(bool val) { can_facestab = val; }
|
void SetFacestab(bool val) { can_facestab = val; }
|
||||||
@ -1655,6 +1660,8 @@ protected:
|
|||||||
bool has_twohandbluntequiped;
|
bool has_twohandbluntequiped;
|
||||||
bool has_twohanderequipped;
|
bool has_twohanderequipped;
|
||||||
bool has_duelweaponsequiped;
|
bool has_duelweaponsequiped;
|
||||||
|
bool has_bowequipped = false;
|
||||||
|
bool has_arrowequipped = false;
|
||||||
bool use_double_melee_round_dmg_bonus;
|
bool use_double_melee_round_dmg_bonus;
|
||||||
bool can_facestab;
|
bool can_facestab;
|
||||||
bool has_numhits;
|
bool has_numhits;
|
||||||
|
|||||||
@ -1336,9 +1336,11 @@ void Mob::AI_Process() {
|
|||||||
|
|
||||||
// See if we can summon the mob to us
|
// See if we can summon the mob to us
|
||||||
if (!HateSummon()) {
|
if (!HateSummon()) {
|
||||||
|
|
||||||
//could not summon them, check ranged...
|
//could not summon them, check ranged...
|
||||||
if (GetSpecialAbility(SPECATK_RANGED_ATK))
|
if (GetSpecialAbility(SPECATK_RANGED_ATK) || HasBowAndArrowEquipped()) {
|
||||||
doranged = true;
|
doranged = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Now pursue
|
// Now pursue
|
||||||
// TODO: Check here for another person on hate list with close hate value
|
// TODO: Check here for another person on hate list with close hate value
|
||||||
|
|||||||
@ -1153,52 +1153,52 @@ float Mob::GetRangeDistTargetSizeMod(Mob* other)
|
|||||||
return (mod + 2.0f); //Add 2.0f as buffer to prevent any chance of failures, client enforce range check regardless.
|
return (mod + 2.0f); //Add 2.0f as buffer to prevent any chance of failures, client enforce range check regardless.
|
||||||
}
|
}
|
||||||
|
|
||||||
void NPC::RangedAttack(Mob* other)
|
void NPC::RangedAttack(Mob *other)
|
||||||
{
|
{
|
||||||
if (!other)
|
if (!other)
|
||||||
return;
|
return;
|
||||||
//make sure the attack and ranged timers are up
|
// make sure the attack and ranged timers are up
|
||||||
//if the ranged timer is disabled, then they have no ranged weapon and shouldent be attacking anyhow
|
// if the ranged timer is disabled, then they have no ranged weapon and shouldent be attacking anyhow
|
||||||
if((attack_timer.Enabled() && !attack_timer.Check(false)) || (ranged_timer.Enabled() && !ranged_timer.Check())){
|
if ((attack_timer.Enabled() && !attack_timer.Check(false)) ||
|
||||||
LogCombat("Archery canceled. Timer not up. Attack [{}], ranged [{}]", attack_timer.GetRemainingTime(), ranged_timer.GetRemainingTime());
|
(ranged_timer.Enabled() && !ranged_timer.Check())) {
|
||||||
|
LogCombat("Archery canceled. Timer not up. Attack [{}], ranged [{}]", attack_timer.GetRemainingTime(),
|
||||||
|
ranged_timer.GetRemainingTime());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!CheckLosFN(other))
|
if (!HasBowAndArrowEquipped() && !GetSpecialAbility(SPECATK_RANGED_ATK))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int attacks = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 0);
|
if (!CheckLosFN(other))
|
||||||
attacks = attacks > 0 ? attacks : 1;
|
|
||||||
for(int i = 0; i < attacks; ++i) {
|
|
||||||
|
|
||||||
if(!GetSpecialAbility(SPECATK_RANGED_ATK))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int sa_min_range = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 4); //Min Range of NPC attack
|
int attacks = 1;
|
||||||
int sa_max_range = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 1); //Max Range of NPC attack
|
|
||||||
|
|
||||||
float min_range = static_cast<float>(RuleI(Combat, MinRangedAttackDist));
|
float min_range = static_cast<float>(RuleI(Combat, MinRangedAttackDist));
|
||||||
float max_range = 250; // needs to be longer than 200(most spells)
|
float max_range = 250.0f; // needs to be longer than 200(most spells)
|
||||||
|
|
||||||
if (sa_max_range)
|
if (GetSpecialAbility(SPECATK_RANGED_ATK)) {
|
||||||
max_range = static_cast<float>(sa_max_range);
|
int temp_attacks = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 0);
|
||||||
|
attacks = temp_attacks > 0 ? temp_attacks : 1;
|
||||||
|
|
||||||
if (sa_min_range)
|
int temp_min_range = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 4); // Min Range of NPC attack
|
||||||
min_range = static_cast<float>(sa_min_range);
|
int temp_max_range = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 1); // Max Range of NPC attack
|
||||||
|
if (temp_max_range)
|
||||||
|
max_range = static_cast<float>(temp_max_range);
|
||||||
|
if (temp_min_range)
|
||||||
|
min_range = static_cast<float>(temp_min_range);
|
||||||
|
}
|
||||||
|
|
||||||
max_range *= max_range;
|
max_range *= max_range;
|
||||||
if(DistanceSquared(m_Position, other->GetPosition()) > max_range)
|
min_range *= min_range;
|
||||||
|
|
||||||
|
for (int i = 0; i < attacks; ++i) {
|
||||||
|
if (DistanceSquared(m_Position, other->GetPosition()) > max_range)
|
||||||
return;
|
return;
|
||||||
else if(DistanceSquared(m_Position, other->GetPosition()) < (min_range * min_range))
|
else if (DistanceSquared(m_Position, other->GetPosition()) < min_range)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(!other || !IsAttackAllowed(other) ||
|
if (!other || !IsAttackAllowed(other) || IsCasting() || DivineAura() || IsStunned() || IsFeared() ||
|
||||||
IsCasting() ||
|
IsMezzed() || (GetAppearance() == eaDead)) {
|
||||||
DivineAura() ||
|
|
||||||
IsStunned() ||
|
|
||||||
IsFeared() ||
|
|
||||||
IsMezzed() ||
|
|
||||||
(GetAppearance() == eaDead)){
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user