[Quest API] Add Client Spell Methods to Perl/Lua. (#2550)

* [Quest API] Add Client Spell Methods to Perl/Lua.

# Perl
- Add `$client->ApplySpell(spell_id)`.
- Add `$client->ApplySpell(spell_id, duration)`.
- Add `$client->ApplySpell(spell_id, duration, allow_pets)`.
- Add `$client->ApplySpell(spell_id, duration, allow_pets, is_raid_group_only)`.
- Add `$client->ApplySpell(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`.
- Add `$client->ApplySpellGroup(spell_id)`.
- Add `$client->ApplySpellGroup(spell_id, duration)`.
- Add `$client->ApplySpellGroup(spell_id, duration, allow_pets)`.
- Add `$client->ApplySpellGroup(spell_id, duration, allow_pets, is_raid_group_only)`.
- Add `$client->ApplySpellGroup(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`.
- Add `$client->ApplySpellRaid(spell_id)`.
- Add `$client->ApplySpellRaid(spell_id, duration)`.
- Add `$client->ApplySpellRaid(spell_id, duration, allow_pets)`.
- Add `$client->ApplySpellRaid(spell_id, duration, allow_pets, is_raid_group_only)`.
- Add `$client->ApplySpellRaid(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`.
- Add `$client->SetSpellDuration(spell_id)`.
- Add `$client->SetSpellDuration(spell_id, duration)`.
- Add `$client->SetSpellDuration(spell_id, duration, allow_pets)`.
- Add `$client->SetSpellDuration(spell_id, duration, allow_pets, is_raid_group_only)`.
- Add `$client->SetSpellDuration(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`.
- Add `$client->SetSpellDurationGroup(spell_id)`.
- Add `$client->SetSpellDurationGroup(spell_id, duration)`.
- Add `$client->SetSpellDurationGroup(spell_id, duration, allow_pets)`.
- Add `$client->SetSpellDurationGroup(spell_id, duration, allow_pets, is_raid_group_only)`.
- Add `$client->SetSpellDurationGroup(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`.
- Add `$client->SetSpellDurationRaid(spell_id)`.
- Add `$client->SetSpellDurationRaid(spell_id, duration)`.
- Add `$client->SetSpellDurationRaid(spell_id, duration, allow_pets)`.
- Add `$client->SetSpellDurationRaid(spell_id, duration, allow_pets, is_raid_group_only)`.
- Add `$client->SetSpellDurationRaid(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`.

# Lua
- Add `client:ApplySpell(spell_id)`.
- Add `client:ApplySpell(spell_id, duration)`.
- Add `client:ApplySpell(spell_id, duration, allow_pets)`.
- Add `client:ApplySpell(spell_id, duration, allow_pets, is_raid_group_only)`.
- Add `client:ApplySpell(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`.
- Add `client:ApplySpellGroup(spell_id)`.
- Add `client:ApplySpellGroup(spell_id, duration)`.
- Add `client:ApplySpellGroup(spell_id, duration, allow_pets)`.
- Add `client:ApplySpellGroup(spell_id, duration, allow_pets, is_raid_group_only)`.
- Add `client:ApplySpellGroup(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`.
- Add `client:ApplySpellRaid(spell_id)`.
- Add `client:ApplySpellRaid(spell_id, duration)`.
- Add `client:ApplySpellRaid(spell_id, duration, allow_pets)`.
- Add `client:ApplySpellRaid(spell_id, duration, allow_pets, is_raid_group_only)`.
- Add `client:ApplySpellRaid(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`.
- Add `client:SetSpellDuration(spell_id)`.
- Add `client:SetSpellDuration(spell_id, duration)`.
- Add `client:SetSpellDuration(spell_id, duration, allow_pets)`.
- Add `client:SetSpellDuration(spell_id, duration, allow_pets, is_raid_group_only)`.
- Add `client:SetSpellDuration(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`.
- Add `client:SetSpellDurationGroup(spell_id)`.
- Add `client:SetSpellDurationGroup(spell_id, duration)`.
- Add `client:SetSpellDurationGroup(spell_id, duration, allow_pets)`.
- Add `client:SetSpellDurationGroup(spell_id, duration, allow_pets, is_raid_group_only)`.
- Add `client:SetSpellDurationGroup(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`.
- Add `client:SetSpellDurationRaid(spell_id)`.
- Add `client:SetSpellDurationRaid(spell_id, duration)`.
- Add `client:SetSpellDurationRaid(spell_id, duration, allow_pets)`.
- Add `client:SetSpellDurationRaid(spell_id, duration, allow_pets, is_raid_group_only)`.
- Add `client:SetSpellDurationRaid(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`.

# Notes
- Allows operators extremely easy shorthands to cast on entire groups and raid groups and optionally include their bots and pets.
- Default functionality for Raid is that it only casts on your group, set `is_raid_group_only` to `false` to cast on the entire Raid.

* Cleanup.

* Remove Raid parameter from Solo/Group methods.
This commit is contained in:
Kinglykrab 2022-11-22 09:11:36 -05:00 committed by GitHub
parent 37af643b61
commit 0c56586f3b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 1018 additions and 289 deletions

View File

@ -580,11 +580,17 @@ enum BucketComparison : uint8 {
BucketIsNotBetween
};
enum EntityFilterTypes : uint8 {
enum class EntityFilterType {
All,
Bots,
Clients,
NPCs
};
enum class ApplySpellType {
Solo,
Group,
Raid
};
#endif /*COMMON_EMU_CONSTANTS_H*/

View File

@ -1518,7 +1518,7 @@ bool Mob::PassCharismaCheck(Mob* caster, uint16 spell_id) {
void Mob::RogueEvade(Mob *other)
{
int64 amount = other->GetHateAmount(this) * zone->random.Int(40, 70) / 100;
other->SetHateAmountOnEnt(this, std::max((int64)100, amount));
other->SetHateAmountOnEnt(this, std::max(static_cast<int64>(100), amount));
return;
}

View File

@ -11810,3 +11810,108 @@ void Client::AddAAPoints(uint32 points)
bool Client::SendGMCommand(std::string message, bool ignore_status) {
return command_dispatch(this, message, ignore_status) >= 0 ? true : false;
}
std::vector<Mob*> Client::GetApplySpellList(
ApplySpellType apply_type,
bool allow_pets,
bool is_raid_group_only,
bool allow_bots
) {
std::vector<Mob*> l;
if (apply_type == ApplySpellType::Raid && IsRaidGrouped()) {
auto* r = GetRaid();
auto group_id = r->GetGroup(this);
if (r && EQ::ValueWithin(group_id, 0, (MAX_RAID_GROUPS - 1))) {
for (auto i = 0; i < MAX_RAID_MEMBERS; i++) {
auto* m = r->members[i].member;
if (m && m->IsClient() && (!is_raid_group_only || r->GetGroup(m) == group_id)) {
l.push_back(m);
if (allow_pets && m->HasPet()) {
l.push_back(m->GetPet());
}
#ifdef BOTS
if (allow_bots) {
const auto& sbl = entity_list.GetBotListByCharacterID(m->CharacterID());
for (const auto& b : sbl) {
l.push_back(b);
}
}
#endif
}
}
}
} else if (apply_type == ApplySpellType::Group && IsGrouped()) {
auto* g = GetGroup();
if (g) {
for (auto i = 0; i < MAX_GROUP_MEMBERS; i++) {
auto* m = g->members[i];
if (m && m->IsClient()) {
l.push_back(m->CastToClient());
if (allow_pets && m->HasPet()) {
l.push_back(m->GetPet());
}
#ifdef BOTS
if (allow_bots) {
const auto& sbl = entity_list.GetBotListByCharacterID(m->CastToClient()->CharacterID());
for (const auto& b : sbl) {
l.push_back(b);
}
}
#endif
}
}
}
} else {
l.push_back(this);
if (allow_pets && HasPet()) {
l.push_back(GetPet());
}
#ifdef BOTS
if (allow_bots) {
const auto& sbl = entity_list.GetBotListByCharacterID(CharacterID());
for (const auto& b : sbl) {
l.push_back(b);
}
}
#endif
}
return l;
}
void Client::ApplySpell(
int spell_id,
int duration,
ApplySpellType apply_type,
bool allow_pets,
bool is_raid_group_only,
bool allow_bots
) {
const auto& l = GetApplySpellList(apply_type, allow_pets, is_raid_group_only, allow_bots);
for (const auto& m : l) {
m->ApplySpellBuff(spell_id, duration);
}
}
void Client::SetSpellDuration(
int spell_id,
int duration,
ApplySpellType apply_type,
bool allow_pets,
bool is_raid_group_only,
bool allow_bots
) {
const auto& l = GetApplySpellList(apply_type, allow_pets, is_raid_group_only, allow_bots);
for (const auto& m : l) {
m->SetBuffDuration(spell_id, duration);
}
}

View File

@ -910,6 +910,31 @@ public:
bool SendGMCommand(std::string message, bool ignore_status = false);
std::vector<Mob*> GetApplySpellList(
ApplySpellType apply_type,
bool allow_pets,
bool is_raid_group_only,
bool allow_bots
);
void ApplySpell(
int spell_id,
int duration = 0,
ApplySpellType apply_type = ApplySpellType::Solo,
bool allow_pets = false,
bool is_raid_group_only = true,
bool allow_bots = false
);
void SetSpellDuration(
int spell_id,
int duration = 0,
ApplySpellType apply_type = ApplySpellType::Solo,
bool allow_pets = false,
bool is_raid_group_only = true,
bool allow_bots = false
);
//old AA methods that we still use
void ResetAA();
void RefundAA();

View File

@ -5858,9 +5858,9 @@ void EntityList::Marquee(
}
}
std::vector<Mob*> EntityList::GetFilteredEntityList(Mob* sender, uint32 distance, uint8 filter_type)
std::vector<Mob*> EntityList::GetFilteredEntityList(Mob* sender, uint32 distance, EntityFilterType filter_type)
{
std::vector<Mob *> l;
std::vector<Mob*> l;
if (!sender) {
return l;
}
@ -5887,9 +5887,9 @@ std::vector<Mob*> EntityList::GetFilteredEntityList(Mob* sender, uint32 distance
}
if (
(filter_type == EntityFilterTypes::Bots && !m.second->IsBot()) ||
(filter_type == EntityFilterTypes::Clients && !m.second->IsClient()) ||
(filter_type == EntityFilterTypes::NPCs && !m.second->IsNPC())
(filter_type == EntityFilterType::Bots && !m.second->IsBot()) ||
(filter_type == EntityFilterType::Clients && !m.second->IsClient()) ||
(filter_type == EntityFilterType::NPCs && !m.second->IsNPC())
) {
continue;
}
@ -5900,8 +5900,13 @@ std::vector<Mob*> EntityList::GetFilteredEntityList(Mob* sender, uint32 distance
return l;
}
void EntityList::DamageArea(Mob* sender, int64 damage, uint32 distance, uint8 filter_type, bool is_percentage)
{
void EntityList::DamageArea(
Mob* sender,
int64 damage,
uint32 distance,
EntityFilterType filter_type,
bool is_percentage
) {
if (!sender) {
return;
}

View File

@ -340,8 +340,19 @@ public:
void DescribeAggro(Client *to_who, NPC *from_who, float dist, bool verbose);
std::vector<Mob*> GetFilteredEntityList(Mob* sender, uint32 distance = 0, uint8 filter_type = EntityFilterTypes::All);
void DamageArea(Mob* sender, int64 damage, uint32 distance = 0, uint8 filter_type = EntityFilterTypes::All, bool is_percentage = false);
std::vector<Mob*> GetFilteredEntityList(
Mob* sender,
uint32 distance = 0,
EntityFilterType filter_type = EntityFilterType::All
);
void DamageArea(
Mob* sender,
int64 damage,
uint32 distance = 0,
EntityFilterType filter_type = EntityFilterType::All,
bool is_percentage = false
);
void Marquee(uint32 type, std::string message, uint32 duration = 3000);
void Marquee(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string message);

View File

@ -999,13 +999,13 @@ NPC* HateList::GetRandomNPCOnHateList(bool skip_mezzed)
return nullptr;
}
void HateList::DamageHateList(int64 damage, uint32 distance, uint8 filter_type, bool is_percentage)
void HateList::DamageHateList(int64 damage, uint32 distance, EntityFilterType filter_type, bool is_percentage)
{
if (damage <= 0) {
return;
}
const auto& l = GetFilteredHateList(distance, filter_type);
const auto& l = GetFilteredHateList(filter_type, distance);
for (const auto& h : l) {
auto e = h->entity_on_hatelist;
if (is_percentage) {
@ -1018,7 +1018,7 @@ void HateList::DamageHateList(int64 damage, uint32 distance, uint8 filter_type,
}
}
std::list<struct_HateList*> HateList::GetFilteredHateList(uint32 distance, uint8 filter_type)
std::list<struct_HateList*> HateList::GetFilteredHateList(EntityFilterType filter_type, uint32 distance)
{
std::list<struct_HateList*> l;
const auto squared_distance = (distance * distance);
@ -1039,9 +1039,9 @@ std::list<struct_HateList*> HateList::GetFilteredHateList(uint32 distance, uint8
}
if (
(filter_type == EntityFilterTypes::Bots && !e->IsBot()) ||
(filter_type == EntityFilterTypes::Clients && !e->IsClient()) ||
(filter_type == EntityFilterTypes::NPCs && !e->IsNPC())
(filter_type == EntityFilterType::Bots && !e->IsBot()) ||
(filter_type == EntityFilterType::Clients && !e->IsClient()) ||
(filter_type == EntityFilterType::NPCs && !e->IsNPC())
) {
continue;
}

View File

@ -66,15 +66,16 @@ public:
int64 GetEntHateAmount(Mob *ent, bool in_damage = false);
std::list<struct_HateList *> &GetHateList() { return list; }
std::list<struct_HateList *> GetFilteredHateList(
uint32 distance = 0,
uint8 filter_type = EntityFilterTypes::All
EntityFilterType filter_type = EntityFilterType::All,
uint32 distance = 0
);
void DamageHateList(
int64 damage,
uint32 distance = 0,
uint8 filter_type = EntityFilterTypes::All,
EntityFilterType filter_type = EntityFilterType::All,
bool is_percentage = false
);

View File

@ -2613,6 +2613,148 @@ void Lua_Client::SendMarqueeMessage(uint32 type, uint32 priority, uint32 fade_in
self->SendMarqueeMessage(type, priority, fade_in, fade_out, duration, message);
}
void Lua_Client::ApplySpell(int spell_id) {
Lua_Safe_Call_Void();
self->ApplySpell(spell_id);
}
void Lua_Client::ApplySpell(int spell_id, int duration) {
Lua_Safe_Call_Void();
self->ApplySpell(spell_id, duration);
}
void Lua_Client::ApplySpell(int spell_id, int duration, bool allow_pets) {
Lua_Safe_Call_Void();
self->ApplySpell(spell_id, duration, ApplySpellType::Solo, allow_pets);
}
#ifdef BOTS
void Lua_Client::ApplySpell(int spell_id, int duration, bool allow_pets, bool allow_bots) {
Lua_Safe_Call_Void();
self->ApplySpell(spell_id, duration, ApplySpellType::Solo, allow_pets, true, allow_bots);
}
#endif
void Lua_Client::ApplySpellGroup(int spell_id) {
Lua_Safe_Call_Void();
self->ApplySpell(spell_id, 0, ApplySpellType::Group);
}
void Lua_Client::ApplySpellGroup(int spell_id, int duration) {
Lua_Safe_Call_Void();
self->ApplySpell(spell_id, duration, ApplySpellType::Group);
}
void Lua_Client::ApplySpellGroup(int spell_id, int duration, bool allow_pets) {
Lua_Safe_Call_Void();
self->ApplySpell(spell_id, duration, ApplySpellType::Group, allow_pets);
}
#ifdef BOTS
void Lua_Client::ApplySpellGroup(int spell_id, int duration, bool allow_pets, bool allow_bots) {
Lua_Safe_Call_Void();
self->ApplySpell(spell_id, duration, ApplySpellType::Group, allow_pets, true, allow_bots);
}
#endif
void Lua_Client::ApplySpellRaid(int spell_id) {
Lua_Safe_Call_Void();
self->ApplySpell(spell_id, 0, ApplySpellType::Raid);
}
void Lua_Client::ApplySpellRaid(int spell_id, int duration) {
Lua_Safe_Call_Void();
self->ApplySpell(spell_id, duration, ApplySpellType::Raid);
}
void Lua_Client::ApplySpellRaid(int spell_id, int duration, bool allow_pets) {
Lua_Safe_Call_Void();
self->ApplySpell(spell_id, duration, ApplySpellType::Raid, allow_pets);
}
void Lua_Client::ApplySpellRaid(int spell_id, int duration, bool allow_pets, bool is_raid_group_only) {
Lua_Safe_Call_Void();
self->ApplySpell(spell_id, duration, ApplySpellType::Raid, allow_pets, is_raid_group_only);
}
#ifdef BOTS
void Lua_Client::ApplySpellRaid(int spell_id, int duration, bool allow_pets, bool is_raid_group_only, bool allow_bots) {
Lua_Safe_Call_Void();
self->ApplySpell(spell_id, duration, ApplySpellType::Raid, allow_pets, is_raid_group_only, allow_bots);
}
#endif
void Lua_Client::SetSpellDuration(int spell_id) {
Lua_Safe_Call_Void();
self->SetSpellDuration(spell_id);
}
void Lua_Client::SetSpellDuration(int spell_id, int duration) {
Lua_Safe_Call_Void();
self->SetSpellDuration(spell_id, duration);
}
void Lua_Client::SetSpellDuration(int spell_id, int duration, bool allow_pets) {
Lua_Safe_Call_Void();
self->SetSpellDuration(spell_id, duration, ApplySpellType::Solo, allow_pets);
}
#ifdef BOTS
void Lua_Client::SetSpellDuration(int spell_id, int duration, bool allow_pets, bool allow_bots) {
Lua_Safe_Call_Void();
self->SetSpellDuration(spell_id, duration, ApplySpellType::Solo, allow_pets, true, allow_bots);
}
#endif
void Lua_Client::SetSpellDurationGroup(int spell_id) {
Lua_Safe_Call_Void();
self->SetSpellDuration(spell_id, 0, ApplySpellType::Group);
}
void Lua_Client::SetSpellDurationGroup(int spell_id, int duration) {
Lua_Safe_Call_Void();
self->SetSpellDuration(spell_id, duration, ApplySpellType::Group);
}
void Lua_Client::SetSpellDurationGroup(int spell_id, int duration, bool allow_pets) {
Lua_Safe_Call_Void();
self->SetSpellDuration(spell_id, duration, ApplySpellType::Group, allow_pets);
}
#ifdef BOTS
void Lua_Client::SetSpellDurationGroup(int spell_id, int duration, bool allow_pets, bool allow_bots) {
Lua_Safe_Call_Void();
self->SetSpellDuration(spell_id, duration, ApplySpellType::Group, allow_pets, true, allow_bots);
}
#endif
void Lua_Client::SetSpellDurationRaid(int spell_id) {
Lua_Safe_Call_Void();
self->SetSpellDuration(spell_id, 0, ApplySpellType::Raid);
}
void Lua_Client::SetSpellDurationRaid(int spell_id, int duration) {
Lua_Safe_Call_Void();
self->SetSpellDuration(spell_id, duration, ApplySpellType::Raid);
}
void Lua_Client::SetSpellDurationRaid(int spell_id, int duration, bool allow_pets) {
Lua_Safe_Call_Void();
self->SetSpellDuration(spell_id, duration, ApplySpellType::Raid, allow_pets);
}
void Lua_Client::SetSpellDurationRaid(int spell_id, int duration, bool allow_pets, bool is_raid_group_only) {
Lua_Safe_Call_Void();
self->SetSpellDuration(spell_id, duration, ApplySpellType::Raid, allow_pets, is_raid_group_only);
}
#ifdef BOTS
void Lua_Client::SetSpellDurationRaid(int spell_id, int duration, bool allow_pets, bool is_raid_group_only, bool allow_bots) {
Lua_Safe_Call_Void();
self->SetSpellDuration(spell_id, duration, ApplySpellType::Group, allow_pets, is_raid_group_only, allow_bots);
}
#endif
void Lua_Client::UpdateAdmin() {
Lua_Safe_Call_Void();
self->UpdateAdmin();
@ -2727,6 +2869,25 @@ luabind::scope lua_register_client() {
.def("AddPVPPoints", (void(Lua_Client::*)(uint32))&Lua_Client::AddPVPPoints)
.def("AddSkill", (void(Lua_Client::*)(int,int))&Lua_Client::AddSkill)
.def("Admin", (int16(Lua_Client::*)(void))&Lua_Client::Admin)
.def("ApplySpell", (void(Lua_Client::*)(int))&Lua_Client::ApplySpell)
.def("ApplySpell", (void(Lua_Client::*)(int,int))&Lua_Client::ApplySpell)
.def("ApplySpell", (void(Lua_Client::*)(int,int,bool))&Lua_Client::ApplySpell)
#ifdef BOTS
.def("ApplySpell", (void(Lua_Client::*)(int,int,bool,bool))&Lua_Client::ApplySpell)
#endif
.def("ApplySpellGroup", (void(Lua_Client::*)(int))&Lua_Client::ApplySpellGroup)
.def("ApplySpellGroup", (void(Lua_Client::*)(int,int))&Lua_Client::ApplySpellGroup)
.def("ApplySpellGroup", (void(Lua_Client::*)(int,int,bool))&Lua_Client::ApplySpellGroup)
#ifdef BOTS
.def("ApplySpellGroup", (void(Lua_Client::*)(int,int,bool,bool))&Lua_Client::ApplySpellGroup)
#endif
.def("ApplySpellRaid", (void(Lua_Client::*)(int))&Lua_Client::ApplySpellRaid)
.def("ApplySpellRaid", (void(Lua_Client::*)(int,int))&Lua_Client::ApplySpellRaid)
.def("ApplySpellRaid", (void(Lua_Client::*)(int,int,bool))&Lua_Client::ApplySpellRaid)
.def("ApplySpellRaid", (void(Lua_Client::*)(int,int,bool,bool))&Lua_Client::ApplySpellRaid)
#ifdef BOTS
.def("ApplySpellRaid", (void(Lua_Client::*)(int,int,bool,bool,bool))&Lua_Client::ApplySpellRaid)
#endif
.def("AssignTask", (void(Lua_Client::*)(int))&Lua_Client::AssignTask)
.def("AssignTask", (void(Lua_Client::*)(int,int))&Lua_Client::AssignTask)
.def("AssignTask", (void(Lua_Client::*)(int,int,bool))&Lua_Client::AssignTask)
@ -3109,6 +3270,25 @@ luabind::scope lua_register_client() {
.def("SetSecondaryWeaponOrnamentation", (void(Lua_Client::*)(uint32))&Lua_Client::SetSecondaryWeaponOrnamentation)
.def("SetSkill", (void(Lua_Client::*)(int,int))&Lua_Client::SetSkill)
.def("SetSkillPoints", (void(Lua_Client::*)(int))&Lua_Client::SetSkillPoints)
.def("SetSpellDuration", (void(Lua_Client::*)(int))&Lua_Client::SetSpellDuration)
.def("SetSpellDuration", (void(Lua_Client::*)(int,int))&Lua_Client::SetSpellDuration)
.def("SetSpellDuration", (void(Lua_Client::*)(int,int,bool))&Lua_Client::SetSpellDuration)
#ifdef BOTS
.def("SetSpellDuration", (void(Lua_Client::*)(int,int,bool,bool))&Lua_Client::SetSpellDuration)
#endif
.def("SetSpellDurationGroup", (void(Lua_Client::*)(int))&Lua_Client::SetSpellDurationGroup)
.def("SetSpellDurationGroup", (void(Lua_Client::*)(int,int))&Lua_Client::SetSpellDurationGroup)
.def("SetSpellDurationGroup", (void(Lua_Client::*)(int,int,bool))&Lua_Client::SetSpellDurationGroup)
#ifdef BOTS
.def("SetSpellDurationGroup", (void(Lua_Client::*)(int,int,bool,bool))&Lua_Client::SetSpellDurationGroup)
#endif
.def("SetSpellDurationRaid", (void(Lua_Client::*)(int))&Lua_Client::SetSpellDurationRaid)
.def("SetSpellDurationRaid", (void(Lua_Client::*)(int,int))&Lua_Client::SetSpellDurationRaid)
.def("SetSpellDurationRaid", (void(Lua_Client::*)(int,int,bool))&Lua_Client::SetSpellDurationRaid)
.def("SetSpellDurationRaid", (void(Lua_Client::*)(int,int,bool,bool))&Lua_Client::SetSpellDurationRaid)
#ifdef BOTS
.def("SetSpellDurationRaid", (void(Lua_Client::*)(int,int,bool,bool,bool))&Lua_Client::SetSpellDurationRaid)
#endif
.def("SetStartZone", (void(Lua_Client::*)(int))&Lua_Client::SetStartZone)
.def("SetStartZone", (void(Lua_Client::*)(int,float))&Lua_Client::SetStartZone)
.def("SetStartZone", (void(Lua_Client::*)(int,float,float))&Lua_Client::SetStartZone)
@ -3118,7 +3298,7 @@ luabind::scope lua_register_client() {
.def("SetTint", (void(Lua_Client::*)(int,uint32))&Lua_Client::SetTint)
.def("SetTitleSuffix", (void(Lua_Client::*)(const char *))&Lua_Client::SetTitleSuffix)
.def("SetZoneFlag", (void(Lua_Client::*)(uint32))&Lua_Client::SetZoneFlag)
.def("Signal", (void(Lua_Client::*)(int))&Lua_Client::Signal)
.def("Signal", (void(Lua_Client::*)(uint32))&Lua_Client::Signal)
.def("Sit", (void(Lua_Client::*)(void))&Lua_Client::Sit)
.def("Stand", (void(Lua_Client::*)(void))&Lua_Client::Stand)
.def("SummonBaggedItems", (void(Lua_Client::*)(uint32,luabind::adl::object))&Lua_Client::SummonBaggedItems)

View File

@ -437,6 +437,51 @@ public:
void UpdateAdmin();
void UpdateAdmin(bool from_database);
void ApplySpell(int spell_id);
void ApplySpell(int spell_id, int duration);
void ApplySpell(int spell_id, int duration, bool allow_pets);
#ifdef BOTS
void ApplySpell(int spell_id, int duration, bool allow_pets, bool allow_bots);
#endif
void ApplySpellGroup(int spell_id);
void ApplySpellGroup(int spell_id, int duration);
void ApplySpellGroup(int spell_id, int duration, bool allow_pets);
#ifdef BOTS
void ApplySpellGroup(int spell_id, int duration, bool allow_pets, bool allow_bots);
#endif
void ApplySpellRaid(int spell_id);
void ApplySpellRaid(int spell_id, int duration);
void ApplySpellRaid(int spell_id, int duration, bool allow_pets);
void ApplySpellRaid(int spell_id, int duration, bool allow_pets, bool is_raid_group_only);
#ifdef BOTS
void ApplySpellRaid(int spell_id, int duration, bool allow_pets, bool is_raid_group_only, bool allow_bots);
#endif
void SetSpellDuration(int spell_id);
void SetSpellDuration(int spell_id, int duration);
void SetSpellDuration(int spell_id, int duration, bool allow_pets);
#ifdef BOTS
void SetSpellDuration(int spell_id, int duration, bool allow_pets, bool allow_bots);
#endif
void SetSpellDurationGroup(int spell_id);
void SetSpellDurationGroup(int spell_id, int duration);
void SetSpellDurationGroup(int spell_id, int duration, bool allow_pets);
#ifdef BOTS
void SetSpellDurationGroup(int spell_id, int duration, bool allow_pets, bool allow_bots);
#endif
void SetSpellDurationRaid(int spell_id);
void SetSpellDurationRaid(int spell_id, int duration);
void SetSpellDurationRaid(int spell_id, int duration, bool allow_pets);
void SetSpellDurationRaid(int spell_id, int duration, bool allow_pets, bool is_raid_group_only);
#ifdef BOTS
void SetSpellDurationRaid(int spell_id, int duration, bool allow_pets, bool is_raid_group_only, bool allow_bots);
#endif
int GetEnvironmentDamageModifier();
void SetEnvironmentDamageModifier(int value);
bool GetInvulnerableEnvironmentDamage();

View File

@ -1382,7 +1382,7 @@ void Lua_Mob::Signal(int signal_id) {
#ifdef BOTS
} else if (self->IsBot()) {
self->CastToBot()->SignalBot(signal_id);
#endif
#endif
}
}
@ -2376,7 +2376,7 @@ Lua_HateList Lua_Mob::GetHateListByDistance(uint32 distance) {
Lua_Safe_Call_Class(Lua_HateList);
Lua_HateList ret;
auto h_list = self->GetFilteredHateList(distance);
auto h_list = self->GetFilteredHateList(EntityFilterType::All, distance);
for (auto h : h_list) {
Lua_HateEntry e(h);
ret.entries.push_back(e);
@ -2524,59 +2524,59 @@ void Lua_Mob::DamageHateList(int64 damage, uint32 distance) {
void Lua_Mob::DamageHateListClients(int64 damage) {
Lua_Safe_Call_Void();
self->DamageHateList(damage, 0, EntityFilterTypes::Clients);
self->DamageHateList(damage, 0, EntityFilterType::Clients);
}
void Lua_Mob::DamageHateListClients(int64 damage, uint32 distance) {
Lua_Safe_Call_Void();
self->DamageHateList(damage, distance, EntityFilterTypes::Clients);
self->DamageHateList(damage, distance, EntityFilterType::Clients);
}
void Lua_Mob::DamageHateListNPCs(int64 damage) {
Lua_Safe_Call_Void();
self->DamageHateList(damage, 0, EntityFilterTypes::NPCs);
self->DamageHateList(damage, 0, EntityFilterType::NPCs);
}
void Lua_Mob::DamageHateListNPCs(int64 damage, uint32 distance) {
Lua_Safe_Call_Void();
self->DamageHateList(damage, distance, EntityFilterTypes::NPCs);
self->DamageHateList(damage, distance, EntityFilterType::NPCs);
}
void Lua_Mob::DamageHateListPercentage(int64 damage) {
Lua_Safe_Call_Void();
self->DamageHateList(damage, 0, EntityFilterTypes::All, true);
self->DamageHateList(damage, 0, EntityFilterType::All, true);
}
void Lua_Mob::DamageHateListPercentage(int64 damage, uint32 distance) {
Lua_Safe_Call_Void();
self->DamageHateList(damage, distance, EntityFilterTypes::All, true);
self->DamageHateList(damage, distance, EntityFilterType::All, true);
}
void Lua_Mob::DamageHateListClientsPercentage(int64 damage) {
Lua_Safe_Call_Void();
self->DamageHateList(damage, 0, EntityFilterTypes::Clients, true);
self->DamageHateList(damage, 0, EntityFilterType::Clients, true);
}
void Lua_Mob::DamageHateListClientsPercentage(int64 damage, uint32 distance) {
Lua_Safe_Call_Void();
self->DamageHateList(damage, distance, EntityFilterTypes::Clients, true);
self->DamageHateList(damage, distance, EntityFilterType::Clients, true);
}
void Lua_Mob::DamageHateListNPCsPercentage(int64 damage) {
Lua_Safe_Call_Void();
self->DamageHateList(damage, 0, EntityFilterTypes::NPCs, true);
self->DamageHateList(damage, 0, EntityFilterType::NPCs, true);
}
void Lua_Mob::DamageHateListNPCsPercentage(int64 damage, uint32 distance) {
Lua_Safe_Call_Void();
self->DamageHateList(damage, distance, EntityFilterTypes::NPCs, true);
self->DamageHateList(damage, distance, EntityFilterType::NPCs, true);
}
Lua_HateList Lua_Mob::GetHateListClients() {
Lua_Safe_Call_Class(Lua_HateList);
Lua_HateList ret;
auto h_list = self->GetFilteredHateList(EntityFilterTypes::Clients);
auto h_list = self->GetFilteredHateList(EntityFilterType::Clients);
for (auto h : h_list) {
Lua_HateEntry e(h);
ret.entries.push_back(e);
@ -2589,7 +2589,7 @@ Lua_HateList Lua_Mob::GetHateListClients(uint32 distance) {
Lua_Safe_Call_Class(Lua_HateList);
Lua_HateList ret;
auto h_list = self->GetFilteredHateList(EntityFilterTypes::Clients, distance);
auto h_list = self->GetFilteredHateList(EntityFilterType::Clients, distance);
for (auto h : h_list) {
Lua_HateEntry e(h);
ret.entries.push_back(e);
@ -2602,7 +2602,7 @@ Lua_HateList Lua_Mob::GetHateListNPCs() {
Lua_Safe_Call_Class(Lua_HateList);
Lua_HateList ret;
auto h_list = self->GetFilteredHateList(EntityFilterTypes::NPCs);
auto h_list = self->GetFilteredHateList(EntityFilterType::NPCs);
for (auto h : h_list) {
Lua_HateEntry e(h);
ret.entries.push_back(e);
@ -2615,7 +2615,7 @@ Lua_HateList Lua_Mob::GetHateListNPCs(uint32 distance) {
Lua_Safe_Call_Class(Lua_HateList);
Lua_HateList ret;
auto h_list = self->GetFilteredHateList(EntityFilterTypes::NPCs, distance);
auto h_list = self->GetFilteredHateList(EntityFilterType::NPCs, distance);
for (auto h : h_list) {
Lua_HateEntry e(h);
ret.entries.push_back(e);
@ -2636,100 +2636,100 @@ void Lua_Mob::DamageArea(int64 damage, uint32 distance) {
void Lua_Mob::DamageAreaPercentage(int64 damage) {
Lua_Safe_Call_Void();
self->DamageArea(damage, 0, EntityFilterTypes::All, true);
self->DamageArea(damage, 0, EntityFilterType::All, true);
}
void Lua_Mob::DamageAreaPercentage(int64 damage, uint32 distance) {
Lua_Safe_Call_Void();
self->DamageArea(damage, distance, EntityFilterTypes::All, true);
self->DamageArea(damage, distance, EntityFilterType::All, true);
}
void Lua_Mob::DamageAreaClients(int64 damage) {
Lua_Safe_Call_Void();
self->DamageArea(damage, 0, EntityFilterTypes::Clients);
self->DamageArea(damage, 0, EntityFilterType::Clients);
}
void Lua_Mob::DamageAreaClients(int64 damage, uint32 distance) {
Lua_Safe_Call_Void();
self->DamageArea(damage, distance, EntityFilterTypes::Clients);
self->DamageArea(damage, distance, EntityFilterType::Clients);
}
void Lua_Mob::DamageAreaClientsPercentage(int64 damage) {
Lua_Safe_Call_Void();
self->DamageArea(damage, 0, EntityFilterTypes::Clients, true);
self->DamageArea(damage, 0, EntityFilterType::Clients, true);
}
void Lua_Mob::DamageAreaClientsPercentage(int64 damage, uint32 distance) {
Lua_Safe_Call_Void();
self->DamageArea(damage, distance, EntityFilterTypes::Clients, true);
self->DamageArea(damage, distance, EntityFilterType::Clients, true);
}
void Lua_Mob::DamageAreaNPCs(int64 damage) {
Lua_Safe_Call_Void();
self->DamageArea(damage, 0, EntityFilterTypes::NPCs);
self->DamageArea(damage, 0, EntityFilterType::NPCs);
}
void Lua_Mob::DamageAreaNPCs(int64 damage, uint32 distance) {
Lua_Safe_Call_Void();
self->DamageArea(damage, distance, EntityFilterTypes::NPCs);
self->DamageArea(damage, distance, EntityFilterType::NPCs);
}
void Lua_Mob::DamageAreaNPCsPercentage(int64 damage) {
Lua_Safe_Call_Void();
self->DamageArea(damage, 0, EntityFilterTypes::NPCs, true);
self->DamageArea(damage, 0, EntityFilterType::NPCs, true);
}
void Lua_Mob::DamageAreaNPCsPercentage(int64 damage, uint32 distance) {
Lua_Safe_Call_Void();
self->DamageArea(damage, distance, EntityFilterTypes::NPCs, true);
self->DamageArea(damage, distance, EntityFilterType::NPCs, true);
}
#ifdef BOTS
void Lua_Mob::DamageAreaBots(int64 damage) {
Lua_Safe_Call_Void();
self->DamageArea(damage, 0, EntityFilterTypes::Bots);
self->DamageArea(damage, 0, EntityFilterType::Bots);
}
void Lua_Mob::DamageAreaBots(int64 damage, uint32 distance) {
Lua_Safe_Call_Void();
self->DamageArea(damage, distance, EntityFilterTypes::Bots);
self->DamageArea(damage, distance, EntityFilterType::Bots);
}
void Lua_Mob::DamageAreaBotsPercentage(int64 damage) {
Lua_Safe_Call_Void();
self->DamageArea(damage, 0, EntityFilterTypes::Bots, true);
self->DamageArea(damage, 0, EntityFilterType::Bots, true);
}
void Lua_Mob::DamageAreaBotsPercentage(int64 damage, uint32 distance) {
Lua_Safe_Call_Void();
self->DamageArea(damage, distance, EntityFilterTypes::Bots, true);
self->DamageArea(damage, distance, EntityFilterType::Bots, true);
}
void Lua_Mob::DamageHateListBots(int64 damage) {
Lua_Safe_Call_Void();
self->DamageHateList(damage, 0, EntityFilterTypes::Bots);
self->DamageHateList(damage, 0, EntityFilterType::Bots);
}
void Lua_Mob::DamageHateListBots(int64 damage, uint32 distance) {
Lua_Safe_Call_Void();
self->DamageHateList(damage, distance, EntityFilterTypes::Bots);
self->DamageHateList(damage, distance, EntityFilterType::Bots);
}
void Lua_Mob::DamageHateListBotsPercentage(int64 damage) {
Lua_Safe_Call_Void();
self->DamageHateList(damage, 0, EntityFilterTypes::Bots, true);
self->DamageHateList(damage, 0, EntityFilterType::Bots, true);
}
void Lua_Mob::DamageHateListBotsPercentage(int64 damage, uint32 distance) {
Lua_Safe_Call_Void();
self->DamageHateList(damage, distance, EntityFilterTypes::Bots, true);
self->DamageHateList(damage, distance, EntityFilterType::Bots, true);
}
Lua_HateList Lua_Mob::GetHateListBots() {
Lua_Safe_Call_Class(Lua_HateList);
Lua_HateList ret;
auto h_list = self->GetFilteredHateList(EntityFilterTypes::Bots);
auto h_list = self->GetFilteredHateList(EntityFilterType::Bots);
for (auto h : h_list) {
Lua_HateEntry e(h);
ret.entries.push_back(e);
@ -2742,7 +2742,7 @@ Lua_HateList Lua_Mob::GetHateListBots(uint32 distance) {
Lua_Safe_Call_Class(Lua_HateList);
Lua_HateList ret;
auto h_list = self->GetFilteredHateList(EntityFilterTypes::Bots, distance);
auto h_list = self->GetFilteredHateList(EntityFilterType::Bots, distance);
for (auto h : h_list) {
Lua_HateEntry e(h);
ret.entries.push_back(e);

View File

@ -351,9 +351,18 @@ public:
bool SpellFinished(uint16 spell_id, Mob *target, EQ::spells::CastingSlot slot = EQ::spells::CastingSlot::Item, int mana_used = 0,
uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0, bool isproc = false, int level_override = -1, uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, bool from_casted_spell = false, uint32 aa_id = 0);
void SendBeginCast(uint16 spell_id, uint32 casttime);
virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar, int reflect_effectiveness = 0,
bool use_resist_adjust = false, int16 resist_adjust = 0, bool isproc = false, int level_override = -1, int32 duration_override = 0, bool disable_buff_overrwrite = false);
virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100, int level_override = -1, int reflect_effectiveness = 0, int32 duration_override = 0, bool disable_buff_overrwrite = false);
virtual bool SpellOnTarget(
uint16 spell_id,
Mob* spelltar,
int reflect_effectiveness = 0,
bool use_resist_adjust = false,
int16 resist_adjust = 0,
bool isproc = false,
int level_override = -1,
int duration_override = 0,
bool disable_buff_overwrite = false
);
virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100, int level_override = -1, int reflect_effectiveness = 0, int32 duration_override = 0, bool disable_buff_overwrite = false);
virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center,
CastAction_type &CastAction, EQ::spells::CastingSlot slot, bool isproc = false);
bool DoCastingChecksOnCaster(int32 spell_id, EQ::spells::CastingSlot slot);
@ -409,7 +418,7 @@ public:
bool IsAffectedByBuff(uint16 spell_id);
bool IsAffectedByBuffByGlobalGroup(GlobalGroup group);
void BuffModifyDurationBySpellID(uint16 spell_id, int32 newDuration);
int AddBuff(Mob *caster, const uint16 spell_id, int duration = 0, int32 level_override = -1, bool disable_buff_overrwrite = false);
int AddBuff(Mob *caster, const uint16 spell_id, int duration = 0, int32 level_override = -1, bool disable_buff_overwrite = false);
int CanBuffStack(uint16 spellid, uint8 caster_level, bool iFailIfOverwrite = false);
int CalcBuffDuration(Mob *caster, Mob *target, uint16 spell_id, int32 caster_level_override = -1);
void SendPetBuffsToClient();
@ -464,8 +473,8 @@ public:
void GetAppearenceEffects();
void ClearAppearenceEffects();
void SendSavedAppearenceEffects(Client *receiver);
void SetBuffDuration(int32 spell_id, int32 duration = 0);
void ApplySpellBuff(int32 spell_id, int32 duration = 0);
void SetBuffDuration(int spell_id, int duration = 0);
void ApplySpellBuff(int spell_id, int duration = 0);
int GetBuffStatValueBySpell(int32 spell_id, const char* stat_identifier);
int GetBuffStatValueBySlot(uint8 slot, const char* stat_identifier);
@ -727,9 +736,6 @@ public:
bool IsOnFeignMemory(Mob *attacker) const;
void PrintHateListToClient(Client *who) { hate_list.PrintHateListToClient(who); }
std::list<struct_HateList*>& GetHateList() { return hate_list.GetHateList(); }
std::list<struct_HateList*> GetFilteredHateList(uint8 filter_type = EntityFilterTypes::All, uint32 distance = 0) { return hate_list.GetFilteredHateList(distance, filter_type); }
void DamageHateList(int64 damage, uint32 distance = 0, uint8 filter_type = EntityFilterTypes::All, bool is_percentage = false) { hate_list.DamageHateList(damage, distance, filter_type, is_percentage); }
void DamageArea(int64 damage, uint32 distance = 0, uint8 filter_type = EntityFilterTypes::All, bool is_percentage = false) { entity_list.DamageArea(this, damage, distance, filter_type, is_percentage); }
bool CheckLosFN(Mob* other);
bool CheckLosFN(float posX, float posY, float posZ, float mobSize);
static bool CheckLosFN(glm::vec3 posWatcher, float sizeWatcher, glm::vec3 posTarget, float sizeTarget);
@ -737,6 +743,31 @@ public:
inline bool CheckLastLosState() const { return last_los_check; }
std::string GetMobDescription();
std::list<struct_HateList*> GetFilteredHateList(
EntityFilterType filter_type = EntityFilterType::All,
uint32 distance = 0
) {
return hate_list.GetFilteredHateList(filter_type, distance);
}
void DamageHateList(
int64 damage,
uint32 distance = 0,
EntityFilterType filter_type = EntityFilterType::All,
bool is_percentage = false
) {
hate_list.DamageHateList(damage, distance, filter_type, is_percentage);
}
void DamageArea(
int64 damage,
uint32 distance = 0,
EntityFilterType filter_type = EntityFilterType::All,
bool is_percentage = false
) {
entity_list.DamageArea(this, damage, distance, filter_type, is_percentage);
}
//Quest
void CameraEffect(uint32 duration, float intensity, Client *c = nullptr, bool global = false);
inline bool GetQglobal() const { return qglobal; }

View File

@ -2506,6 +2506,148 @@ void Perl_Client_SendMarqueeMessage(Client* self, uint32 type, uint32 priority,
self->SendMarqueeMessage(type, priority, fade_in, fade_out, duration, message);
}
void Perl_Client_ApplySpell(Client* self, int spell_id)
{
self->ApplySpell(spell_id);
}
void Perl_Client_ApplySpell(Client* self, int spell_id, int duration)
{
self->ApplySpell(spell_id, duration);
}
void Perl_Client_ApplySpell(Client* self, int spell_id, int duration, bool allow_pets)
{
self->ApplySpell(spell_id, duration, ApplySpellType::Solo, allow_pets);
}
#ifdef BOTS
void Perl_Client_ApplySpell(Client* self, int spell_id, int duration, bool allow_pets, bool allow_bots)
{
self->ApplySpell(spell_id, duration, ApplySpellType::Solo, allow_pets, true, allow_bots);
}
#endif
void Perl_Client_ApplySpellGroup(Client* self, int spell_id)
{
self->ApplySpell(spell_id, 0, ApplySpellType::Group);
}
void Perl_Client_ApplySpellGroup(Client* self, int spell_id, int duration)
{
self->ApplySpell(spell_id, duration, ApplySpellType::Group);
}
void Perl_Client_ApplySpellGroup(Client* self, int spell_id, int duration, bool allow_pets)
{
self->ApplySpell(spell_id, duration, ApplySpellType::Group, allow_pets);
}
#ifdef BOTS
void Perl_Client_ApplySpellGroup(Client* self, int spell_id, int duration, bool allow_pets, bool allow_bots)
{
self->ApplySpell(spell_id, duration, ApplySpellType::Group, allow_pets, true, allow_bots);
}
#endif
void Perl_Client_ApplySpellRaid(Client* self, int spell_id)
{
self->ApplySpell(spell_id, 0, ApplySpellType::Raid);
}
void Perl_Client_ApplySpellRaid(Client* self, int spell_id, int duration)
{
self->ApplySpell(spell_id, duration, ApplySpellType::Raid);
}
void Perl_Client_ApplySpellRaid(Client* self, int spell_id, int duration, bool allow_pets)
{
self->ApplySpell(spell_id, duration, ApplySpellType::Raid, allow_pets);
}
void Perl_Client_ApplySpellRaid(Client* self, int spell_id, int duration, bool allow_pets, bool is_raid_group_only)
{
self->ApplySpell(spell_id, duration, ApplySpellType::Raid, allow_pets, is_raid_group_only);
}
#ifdef BOTS
void Perl_Client_ApplySpellRaid(Client* self, int spell_id, int duration, bool allow_pets, bool is_raid_group_only, bool allow_bots)
{
self->ApplySpell(spell_id, duration, ApplySpellType::Raid, allow_pets, is_raid_group_only, allow_bots);
}
#endif
void Perl_Client_SetSpellDuration(Client* self, int spell_id)
{
self->SetSpellDuration(spell_id);
}
void Perl_Client_SetSpellDuration(Client* self, int spell_id, int duration)
{
self->SetSpellDuration(spell_id, duration);
}
void Perl_Client_SetSpellDuration(Client* self, int spell_id, int duration, bool allow_pets)
{
self->SetSpellDuration(spell_id, duration, ApplySpellType::Solo, allow_pets);
}
#ifdef BOTS
void Perl_Client_SetSpellDuration(Client* self, int spell_id, int duration, bool allow_pets, bool allow_bots)
{
self->SetSpellDuration(spell_id, duration, ApplySpellType::Solo, allow_pets, true, allow_bots);
}
#endif
void Perl_Client_SetSpellDurationGroup(Client* self, int spell_id)
{
self->SetSpellDuration(spell_id, 0, ApplySpellType::Group);
}
void Perl_Client_SetSpellDurationGroup(Client* self, int spell_id, int duration)
{
self->SetSpellDuration(spell_id, duration, ApplySpellType::Group);
}
void Perl_Client_SetSpellDurationGroup(Client* self, int spell_id, int duration, bool allow_pets)
{
self->SetSpellDuration(spell_id, duration, ApplySpellType::Group, allow_pets);
}
#ifdef BOTS
void Perl_Client_SetSpellDurationGroup(Client* self, int spell_id, int duration, bool allow_pets, bool allow_bots)
{
self->SetSpellDuration(spell_id, duration, ApplySpellType::Group, allow_pets, true, allow_bots);
}
#endif
void Perl_Client_SetSpellDurationRaid(Client* self, int spell_id)
{
self->ApplySpell(spell_id, 0, ApplySpellType::Raid);
}
void Perl_Client_SetSpellDurationRaid(Client* self, int spell_id, int duration)
{
self->ApplySpell(spell_id, duration, ApplySpellType::Raid);
}
void Perl_Client_SetSpellDurationRaid(Client* self, int spell_id, int duration, bool allow_pets)
{
self->SetSpellDuration(spell_id, duration, ApplySpellType::Raid, allow_pets);
}
void Perl_Client_SetSpellDurationRaid(Client* self, int spell_id, int duration, bool allow_pets, bool is_raid_group_only)
{
self->SetSpellDuration(spell_id, duration, ApplySpellType::Raid, allow_pets, is_raid_group_only);
}
#ifdef BOTS
void Perl_Client_SetSpellDurationRaid(Client* self, int spell_id, int duration, bool allow_pets, bool is_raid_group_only, bool allow_bots)
{
self->SetSpellDuration(spell_id, duration, ApplySpellType::Raid, allow_pets, is_raid_group_only, allow_bots);
}
#endif
#ifdef BOTS
int Perl_Client_GetBotRequiredLevel(Client* self)
@ -2601,6 +2743,25 @@ void perl_register_client()
package.add("AddPVPPoints", &Perl_Client_AddPVPPoints);
package.add("AddSkill", &Perl_Client_AddSkill);
package.add("Admin", &Perl_Client_Admin);
package.add("ApplySpell", (void(*)(Client*, int))&Perl_Client_ApplySpell);
package.add("ApplySpell", (void(*)(Client*, int, int))&Perl_Client_ApplySpell);
package.add("ApplySpell", (void(*)(Client*, int, int, bool))&Perl_Client_ApplySpell);
#ifdef BOTS
package.add("ApplySpell", (void(*)(Client*, int, int, bool, bool))&Perl_Client_ApplySpell);
#endif
package.add("ApplySpellGroup", (void(*)(Client*, int))&Perl_Client_ApplySpellGroup);
package.add("ApplySpellGroup", (void(*)(Client*, int, int))&Perl_Client_ApplySpellGroup);
package.add("ApplySpellGroup", (void(*)(Client*, int, int, bool))&Perl_Client_ApplySpellGroup);
#ifdef BOTS
package.add("ApplySpellGroup", (void(*)(Client*, int, int, bool, bool))&Perl_Client_ApplySpellGroup);
#endif
package.add("ApplySpellRaid", (void(*)(Client*, int))&Perl_Client_ApplySpellRaid);
package.add("ApplySpellRaid", (void(*)(Client*, int, int))&Perl_Client_ApplySpellRaid);
package.add("ApplySpellRaid", (void(*)(Client*, int, int, bool))&Perl_Client_ApplySpellRaid);
package.add("ApplySpellRaid", (void(*)(Client*, int, int, bool, bool))&Perl_Client_ApplySpellRaid);
#ifdef BOTS
package.add("ApplySpellRaid", (void(*)(Client*, int, int, bool, bool, bool))&Perl_Client_ApplySpellRaid);
#endif
package.add("AssignTask", (void(*)(Client*, int))&Perl_Client_AssignTask);
package.add("AssignTask", (void(*)(Client*, int, int))&Perl_Client_AssignTask);
package.add("AssignTask", (void(*)(Client*, int, int, bool))&Perl_Client_AssignTask);
@ -2983,6 +3144,25 @@ void perl_register_client()
package.add("SetSecondaryWeaponOrnamentation", &Perl_Client_SetSecondaryWeaponOrnamentation);
package.add("SetSkill", &Perl_Client_SetSkill);
package.add("SetSkillPoints", &Perl_Client_SetSkillPoints);
package.add("SetSpellDuration", (void(*)(Client*, int))&Perl_Client_SetSpellDuration);
package.add("SetSpellDuration", (void(*)(Client*, int, int))&Perl_Client_SetSpellDuration);
package.add("SetSpellDuration", (void(*)(Client*, int, int, bool))&Perl_Client_SetSpellDuration);
#ifdef BOTS
package.add("SetSpellDuration", (void(*)(Client*, int, int, bool, bool))&Perl_Client_SetSpellDuration);
#endif
package.add("SetSpellDurationGroup", (void(*)(Client*, int))&Perl_Client_SetSpellDurationGroup);
package.add("SetSpellDurationGroup", (void(*)(Client*, int, int))&Perl_Client_SetSpellDurationGroup);
package.add("SetSpellDurationGroup", (void(*)(Client*, int, int, bool))&Perl_Client_SetSpellDurationGroup);
#ifdef BOTS
package.add("SetSpellDurationGroup", (void(*)(Client*, int, int, bool, bool))&Perl_Client_SetSpellDurationGroup);
#endif
package.add("SetSpellDurationRaid", (void(*)(Client*, int))&Perl_Client_SetSpellDurationRaid);
package.add("SetSpellDurationRaid", (void(*)(Client*, int, int))&Perl_Client_SetSpellDurationRaid);
package.add("SetSpellDurationRaid", (void(*)(Client*, int, int, bool))&Perl_Client_SetSpellDurationRaid);
package.add("SetSpellDurationRaid", (void(*)(Client*, int, int, bool, bool))&Perl_Client_SetSpellDurationRaid);
#ifdef BOTS
package.add("SetSpellDurationRaid", (void(*)(Client*, int, int, bool, bool, bool))&Perl_Client_SetSpellDurationRaid);
#endif
package.add("SetStartZone", (void(*)(Client*, uint32))&Perl_Client_SetStartZone);
package.add("SetStartZone", (void(*)(Client*, uint32, float, float, float))&Perl_Client_SetStartZone);
package.add("SetStartZone", (void(*)(Client*, uint32, float, float, float, float))&Perl_Client_SetStartZone);

View File

@ -2346,7 +2346,7 @@ perl::array Perl_Mob_GetHateListByDistance(Mob* self, uint32 distance) // @categ
{
perl::array result;
auto h_list = self->GetFilteredHateList(distance, EntityFilterTypes::All);
auto h_list = self->GetFilteredHateList(EntityFilterType::All, distance);
for (auto h : h_list) {
result.push_back(h);
}
@ -2491,57 +2491,57 @@ void Perl_Mob_DamageArea(Mob* self, int64 damage) // @categories Hate and Aggro
void Perl_Mob_DamageArea(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro
{
self->DamageArea(damage, distance, EntityFilterTypes::All);
self->DamageArea(damage, distance, EntityFilterType::All);
}
void Perl_Mob_DamageAreaPercentage(Mob* self, int64 damage) // @categories Hate and Aggro
{
self->DamageArea(damage, 0, EntityFilterTypes::All, true);
self->DamageArea(damage, 0, EntityFilterType::All, true);
}
void Perl_Mob_DamageAreaPercentage(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro
{
self->DamageArea(damage, distance, EntityFilterTypes::All, true);
self->DamageArea(damage, distance, EntityFilterType::All, true);
}
void Perl_Mob_DamageAreaClients(Mob* self, int64 damage) // @categories Hate and Aggro
{
self->DamageArea(damage, 0, EntityFilterTypes::Clients);
self->DamageArea(damage, 0, EntityFilterType::Clients);
}
void Perl_Mob_DamageAreaClients(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro
{
self->DamageArea(damage, distance, EntityFilterTypes::Clients);
self->DamageArea(damage, distance, EntityFilterType::Clients);
}
void Perl_Mob_DamageAreaClientsPercentage(Mob* self, int64 damage) // @categories Hate and Aggro
{
self->DamageArea(damage, 0, EntityFilterTypes::Clients, true);
self->DamageArea(damage, 0, EntityFilterType::Clients, true);
}
void Perl_Mob_DamageAreaClientsPercentage(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro
{
self->DamageArea(damage, distance, EntityFilterTypes::Clients, true);
self->DamageArea(damage, distance, EntityFilterType::Clients, true);
}
void Perl_Mob_DamageAreaNPCs(Mob* self, int64 damage) // @categories Hate and Aggro
{
self->DamageArea(damage, 0, EntityFilterTypes::NPCs);
self->DamageArea(damage, 0, EntityFilterType::NPCs);
}
void Perl_Mob_DamageAreaNPCs(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro
{
self->DamageArea(damage, distance, EntityFilterTypes::NPCs);
self->DamageArea(damage, distance, EntityFilterType::NPCs);
}
void Perl_Mob_DamageAreaNPCsPercentage(Mob* self, int64 damage) // @categories Hate and Aggro
{
self->DamageArea(damage, 0, EntityFilterTypes::NPCs, true);
self->DamageArea(damage, 0, EntityFilterType::NPCs, true);
}
void Perl_Mob_DamageAreaNPCsPercentage(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro
{
self->DamageArea(damage, distance, EntityFilterTypes::NPCs, true);
self->DamageArea(damage, distance, EntityFilterType::NPCs, true);
}
void Perl_Mob_DamageHateList(Mob* self, int64 damage) // @categories Hate and Aggro
@ -2551,64 +2551,64 @@ void Perl_Mob_DamageHateList(Mob* self, int64 damage) // @categories Hate and Ag
void Perl_Mob_DamageHateList(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro
{
self->DamageHateList(damage, distance, EntityFilterTypes::All);
self->DamageHateList(damage, distance, EntityFilterType::All);
}
void Perl_Mob_DamageHateListPercentage(Mob* self, int64 damage) // @categories Hate and Aggro
{
self->DamageHateList(damage, 0, EntityFilterTypes::All, true);
self->DamageHateList(damage, 0, EntityFilterType::All, true);
}
void Perl_Mob_DamageHateListPercentage(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro
{
self->DamageHateList(damage, distance, EntityFilterTypes::All, true);
self->DamageHateList(damage, distance, EntityFilterType::All, true);
}
void Perl_Mob_DamageHateListClients(Mob* self, int64 damage) // @categories Hate and Aggro
{
self->DamageHateList(damage, 0, EntityFilterTypes::Clients);
self->DamageHateList(damage, 0, EntityFilterType::Clients);
}
void Perl_Mob_DamageHateListClients(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro
{
self->DamageHateList(damage, distance, EntityFilterTypes::Clients);
self->DamageHateList(damage, distance, EntityFilterType::Clients);
}
void Perl_Mob_DamageHateListClientsPercentage(Mob* self, int64 damage) // @categories Hate and Aggro
{
self->DamageHateList(damage, 0, EntityFilterTypes::Clients, true);
self->DamageHateList(damage, 0, EntityFilterType::Clients, true);
}
void Perl_Mob_DamageHateListClientsPercentage(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro
{
self->DamageHateList(damage, distance, EntityFilterTypes::Clients, true);
self->DamageHateList(damage, distance, EntityFilterType::Clients, true);
}
void Perl_Mob_DamageHateListNPCs(Mob* self, int64 damage) // @categories Hate and Aggro
{
self->DamageHateList(damage, 0, EntityFilterTypes::NPCs);
self->DamageHateList(damage, 0, EntityFilterType::NPCs);
}
void Perl_Mob_DamageHateListNPCs(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro
{
self->DamageHateList(damage, distance, EntityFilterTypes::NPCs);
self->DamageHateList(damage, distance, EntityFilterType::NPCs);
}
void Perl_Mob_DamageHateListNPCsPercentage(Mob* self, int64 damage) // @categories Hate and Aggro
{
self->DamageHateList(damage, 0, EntityFilterTypes::NPCs, true);
self->DamageHateList(damage, 0, EntityFilterType::NPCs, true);
}
void Perl_Mob_DamageHateListNPCsPercentage(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro
{
self->DamageHateList(damage, distance, EntityFilterTypes::NPCs, true);
self->DamageHateList(damage, distance, EntityFilterType::NPCs, true);
}
perl::array Perl_Mob_GetHateListClients(Mob* self)
{
perl::array result;
auto h_list = self->GetFilteredHateList(EntityFilterTypes::Clients);
auto h_list = self->GetFilteredHateList(EntityFilterType::Clients);
for (auto h : h_list) {
result.push_back(h);
}
@ -2620,7 +2620,7 @@ perl::array Perl_Mob_GetHateListClients(Mob* self, uint32 distance)
{
perl::array result;
auto h_list = self->GetFilteredHateList(distance, EntityFilterTypes::Clients);
auto h_list = self->GetFilteredHateList(EntityFilterType::Clients, distance);
for (auto h : h_list) {
result.push_back(h);
}
@ -2632,7 +2632,7 @@ perl::array Perl_Mob_GetHateListNPCs(Mob* self)
{
perl::array result;
auto h_list = self->GetFilteredHateList(EntityFilterTypes::NPCs);
auto h_list = self->GetFilteredHateList(EntityFilterType::NPCs);
for (auto h : h_list) {
result.push_back(h);
}
@ -2644,7 +2644,7 @@ perl::array Perl_Mob_GetHateListNPCs(Mob* self, uint32 distance)
{
perl::array result;
auto h_list = self->GetFilteredHateList(distance, EntityFilterTypes::NPCs);
auto h_list = self->GetFilteredHateList(EntityFilterType::NPCs, distance);
for (auto h : h_list) {
result.push_back(h);
}
@ -2655,49 +2655,49 @@ perl::array Perl_Mob_GetHateListNPCs(Mob* self, uint32 distance)
#ifdef BOTS
void Perl_Mob_DamageAreaBots(Mob* self, int64 damage) // @categories Hate and Aggro
{
self->DamageArea(damage, 0, EntityFilterTypes::Bots);
self->DamageArea(damage, 0, EntityFilterType::Bots);
}
void Perl_Mob_DamageAreaBots(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro
{
self->DamageArea(damage, distance, EntityFilterTypes::Bots);
self->DamageArea(damage, distance, EntityFilterType::Bots);
}
void Perl_Mob_DamageAreaBotsPercentage(Mob* self, int64 damage) // @categories Hate and Aggro
{
self->DamageArea(damage, 0, EntityFilterTypes::Bots, true);
self->DamageArea(damage, 0, EntityFilterType::Bots, true);
}
void Perl_Mob_DamageAreaBotsPercentage(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro
{
self->DamageArea(damage, distance, EntityFilterTypes::Bots, true);
self->DamageArea(damage, distance, EntityFilterType::Bots, true);
}
void Perl_Mob_DamageHateListBots(Mob* self, int64 damage) // @categories Hate and Aggro
{
self->DamageHateList(damage, 0, EntityFilterTypes::Bots);
self->DamageHateList(damage, 0, EntityFilterType::Bots);
}
void Perl_Mob_DamageHateListBots(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro
{
self->DamageHateList(damage, distance, EntityFilterTypes::Bots);
self->DamageHateList(damage, distance, EntityFilterType::Bots);
}
void Perl_Mob_DamageHateListBotsPercentage(Mob* self, int64 damage) // @categories Hate and Aggro
{
self->DamageHateList(damage, 0, EntityFilterTypes::Bots, true);
self->DamageHateList(damage, 0, EntityFilterType::Bots, true);
}
void Perl_Mob_DamageHateListBotsPercentage(Mob* self, int64 damage, uint32 distance) // @categories Hate and Aggro
{
self->DamageHateList(damage, distance, EntityFilterTypes::Bots, true);
self->DamageHateList(damage, distance, EntityFilterType::Bots, true);
}
perl::array Perl_Mob_GetHateListBots(Mob* self)
{
perl::array result;
auto h_list = self->GetFilteredHateList(EntityFilterTypes::Bots);
auto h_list = self->GetFilteredHateList(EntityFilterType::Bots);
for (auto h : h_list) {
result.push_back(h);
}
@ -2709,7 +2709,7 @@ perl::array Perl_Mob_GetHateListBots(Mob* self, uint32 distance)
{
perl::array result;
auto h_list = self->GetFilteredHateList(distance, EntityFilterTypes::Bots);
auto h_list = self->GetFilteredHateList(EntityFilterType::Bots, distance);
for (auto h : h_list)
{
result.push_back(h);

View File

@ -46,7 +46,7 @@ extern WorldServer worldserver;
// the spell can still fail here, if the buff can't stack
// in this case false will be returned, true otherwise
bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_override, int reflect_effectiveness, int32 duration_override, bool disable_buff_overrwrite)
bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_override, int reflect_effectiveness, int32 duration_override, bool disable_buff_overwrite)
{
int caster_level, buffslot, effect, effect_value, i;
EQ::ItemInstance *SummonedItem=nullptr;
@ -119,7 +119,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
}
else
{
buffslot = AddBuff(caster, spell_id, duration_override, -1, disable_buff_overrwrite);
buffslot = AddBuff(caster, spell_id, duration_override, -1, disable_buff_overwrite);
}
if(buffslot == -1) // stacking failure
return false;
@ -186,7 +186,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
return true;
}
#endif
}
}
if(IsVirusSpell(spell_id)) {
@ -8091,7 +8091,7 @@ bool Mob::PassCastRestriction(int value)
}
else if (!IsNonSpellFighterClass(GetClass()) && GetManaRatio() <= 10) {
return true;
}
}
else if (IsHybridClass(GetClass()) && CastToClient()->GetEndurancePercent() <= 10) {
return true;
}
@ -10292,7 +10292,7 @@ bool Mob::HasPersistDeathIllusion(int32 spell_id) {
return false;
}
void Mob::SetBuffDuration(int32 spell_id, int32 duration) {
void Mob::SetBuffDuration(int spell_id, int duration) {
/*
Will refresh the buff with specified spell_id to the specified duration
@ -10331,7 +10331,7 @@ void Mob::SetBuffDuration(int32 spell_id, int32 duration) {
}
}
void Mob::ApplySpellBuff(int32 spell_id, int32 duration)
void Mob::ApplySpellBuff(int spell_id, int duration)
{
/*
Used for quest command to apply a new buff with custom duration.
@ -10340,11 +10340,12 @@ void Mob::ApplySpellBuff(int32 spell_id, int32 duration)
if (!IsValidSpell(spell_id)) {
return;
}
if (!spells[spell_id].buff_duration) {
return;
}
if (duration < -1) {
if (duration <= -1) {
duration = PERMANENT_BUFF_DURATION;
}

View File

@ -3274,7 +3274,7 @@ bool Mob::HasDiscBuff()
// stacking problems, and -2 if this is not a buff
// if caster is null, the buff will be added with the caster level being
// the level of the mob
int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_override, bool disable_buff_overrwrite)
int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_override, bool disable_buff_overwrite)
{
int buffslot, ret, caster_level, emptyslot = -1;
bool will_overwrite = false;
@ -3370,7 +3370,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid
// at this point we know that this buff will stick, but we have
// to remove some other buffs already worn if will_overwrite is true
if (will_overwrite && !disable_buff_overrwrite) {
if (will_overwrite && !disable_buff_overwrite) {
std::vector<int>::iterator cur, end;
cur = overwrite_slots.begin();
end = overwrite_slots.end();
@ -3515,14 +3515,21 @@ int Mob::CanBuffStack(uint16 spellid, uint8 caster_level, bool iFailIfOverwrite)
// and if you don't want effects just return false. interrupting here will
// break stuff
//
bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectiveness, bool use_resist_adjust, int16 resist_adjust,
bool isproc, int level_override, int32 duration_override, bool disable_buff_overrwrite)
{
bool Mob::SpellOnTarget(
uint16 spell_id,
Mob *spelltar,
int reflect_effectiveness,
bool use_resist_adjust,
int16 resist_adjust,
bool isproc,
int level_override,
int duration_override,
bool disable_buff_overwrite
) {
auto spellOwner = GetOwnerOrSelf();
// well we can't cast a spell on target without a target
if(!spelltar)
{
if (!spelltar) {
LogSpells("Unable to apply spell [{}] without a target", spell_id);
Message(Chat::Red, "SOT: You must have a target for this spell.");
return false;
@ -3532,11 +3539,17 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
return false;
}
if (!IsValidSpell(spell_id))
if (!IsValidSpell(spell_id)) {
return false;
}
if(IsDetrimentalSpell(spell_id) && !IsAttackAllowed(spelltar, true) && !IsResurrectionEffects(spell_id) && !IsEffectInSpell(spell_id, SE_BindSight)) {
if(!IsClient() || !CastToClient()->GetGM()) {
if (
IsDetrimentalSpell(spell_id) &&
!IsAttackAllowed(spelltar, true) &&
!IsResurrectionEffects(spell_id) &&
!IsEffectInSpell(spell_id, SE_BindSight)
) {
if (!IsClient() || !CastToClient()->GetGM()) {
MessageString(Chat::SpellFailure, SPELL_NO_HOLD);
return false;
}
@ -3548,12 +3561,28 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
// these target types skip pcnpc only check (according to dev quotes)
// other AE spells this is redundant, oh well
// 1 = PCs, 2 = NPCs
if (spells[spell_id].pcnpc_only_flag && spells[spell_id].target_type != ST_AETargetHateList &&
spells[spell_id].target_type != ST_HateList) {
if (spells[spell_id].pcnpc_only_flag == 1 && !spelltar->IsClient() && !spelltar->IsMerc() && !spelltar->IsBot())
if (
spells[spell_id].pcnpc_only_flag &&
spells[spell_id].target_type != ST_AETargetHateList &&
spells[spell_id].target_type != ST_HateList
) {
if (
spells[spell_id].pcnpc_only_flag == 1 &&
!spelltar->IsClient() &&
!spelltar->IsMerc() &&
!spelltar->IsBot()
) {
return false;
else if (spells[spell_id].pcnpc_only_flag == 2 && (spelltar->IsClient() || spelltar->IsMerc() || spelltar->IsBot()))
} else if (
spells[spell_id].pcnpc_only_flag == 2 &&
(
spelltar->IsClient() ||
spelltar->IsMerc() ||
spelltar->IsBot()
)
) {
return false;
}
}
uint16 caster_level = level_override > 0 ? level_override : GetCasterLevel(spell_id);
@ -3570,12 +3599,9 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
Action_Struct* action = (Action_Struct*) action_packet->pBuffer;
// select source
if(IsClient() && CastToClient()->GMHideMe())
{
if (IsClient() && CastToClient()->GMHideMe()) {
action->source = spelltar->GetID();
}
else
{
} else {
action->source = GetID();
// this is a hack that makes detrimental buffs work client to client
// TODO figure out how to do this right
@ -3591,12 +3617,9 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
}
// select target
if (IsEffectInSpell(spell_id, SE_BindSight))
{
if (IsEffectInSpell(spell_id, SE_BindSight)) {
action->target = GetID();
}
else
{
} else {
action->target = spelltar->GetID();
}
@ -3609,10 +3632,13 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
action->instrument_mod = GetInstrumentMod(spell_id);
action->effect_flag = 0;
if(spelltar != this && spelltar->IsClient()) // send to target
if (spelltar != this && spelltar->IsClient()) { // send to target
spelltar->CastToClient()->QueuePacket(action_packet);
if(IsClient()) // send to caster
}
if (IsClient()) { // send to caster
CastToClient()->QueuePacket(action_packet);
}
// send to people in the area, ignoring caster and target
entity_list.QueueCloseClients(
@ -3626,12 +3652,13 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
);
/* Send the EVENT_CAST_ON event */
std::string export_string = fmt::format(
const auto export_string = fmt::format(
"{} {} {}",
spell_id,
GetID(),
caster_level
);
if (spelltar->IsNPC()) {
parse->EventNPC(EVENT_CAST_ON, spelltar->CastToNPC(), this, export_string, 0);
} else if (spelltar->IsClient()) {
@ -3642,7 +3669,6 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
#endif
}
mod_spell_cast(spell_id, spelltar, reflect_effectiveness, use_resist_adjust, resist_adjust, isproc);
if (!DoCastingChecksOnTarget(false, spell_id, spelltar)) {
@ -3654,25 +3680,37 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
if (RuleB(Spells, EnableBlockedBuffs)) {
// We return true here since the caster's client should act like normal
if (spelltar->IsBlockedBuff(spell_id)) {
LogSpells("Spell [{}] not applied to [{}] as it is a Blocked Buff",
spell_id, spelltar->GetName());
LogSpells(
"Spell [{}] not applied to [{}] as it is a Blocked Buff",
spell_id,
spelltar->GetName()
);
safe_delete(action_packet);
return true;
}
if (spelltar->IsPet() && spelltar->GetOwner() &&
spelltar->GetOwner()->IsBlockedPetBuff(spell_id)) {
LogSpells("Spell [{}] not applied to [{}] ([{}]'s pet) as it is a Pet Blocked Buff",
spell_id, spelltar->GetName(), spelltar->GetOwner()->GetName());
if (
spelltar->IsPet() &&
spelltar->GetOwner() &&
spelltar->GetOwner()->IsBlockedPetBuff(spell_id)
) {
LogSpells(
"Spell [{}] not applied to [{}] ([{}]'s pet) as it is a Pet Blocked Buff",
spell_id,
spelltar->GetName(),
spelltar->GetOwner()->GetName()
);
safe_delete(action_packet);
return true;
}
}
// invuln mobs can't be affected by any spells, good or bad, except if caster is casting a spell with 'cast_not_standing' on self.
if ((spelltar->GetInvul() && !spelltar->DivineAura()) ||
if (
(spelltar->GetInvul() && !spelltar->DivineAura()) ||
(spelltar != this && spelltar->DivineAura()) ||
(spelltar == this && spelltar->DivineAura() && !IgnoreCastingRestriction(spell_id))) {
(spelltar == this && spelltar->DivineAura() && !IgnoreCastingRestriction(spell_id))
) {
LogSpells("Casting spell [{}] on [{}] aborted: they are invulnerable", spell_id, spelltar->GetName());
safe_delete(action_packet);
return false;
@ -3680,7 +3718,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
//cannot hurt untargetable mobs
bodyType bt = spelltar->GetBodyType();
if(bt == BT_NoTarget || bt == BT_NoTarget2) {
if (bt == BT_NoTarget || bt == BT_NoTarget2) {
if (RuleB(Pets, UnTargetableSwarmPet)) {
if (spelltar->IsNPC()) {
if (!spelltar->CastToNPC()->GetSwarmOwner()) {
@ -3704,30 +3742,24 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
// Not sure if all 3 should be stacking
//This is not live like behavior (~Kayen confirmed 2/2/22)
if (!RuleB(Spells, AllowDoubleInvis)) {
if (IsEffectInSpell(spell_id, SE_Invisibility))
{
if (spelltar->invisible)
{
if (IsEffectInSpell(spell_id, SE_Invisibility)) {
if (spelltar->invisible) {
spelltar->MessageString(Chat::SpellFailure, ALREADY_INVIS, GetCleanName());
safe_delete(action_packet);
return false;
}
}
if (IsEffectInSpell(spell_id, SE_InvisVsUndead))
{
if (spelltar->invisible_undead)
{
if (IsEffectInSpell(spell_id, SE_InvisVsUndead)) {
if (spelltar->invisible_undead) {
spelltar->MessageString(Chat::SpellFailure, ALREADY_INVIS, GetCleanName());
safe_delete(action_packet);
return false;
}
}
if (IsEffectInSpell(spell_id, SE_InvisVsAnimals))
{
if (spelltar->invisible_animals)
{
if (IsEffectInSpell(spell_id, SE_InvisVsAnimals)) {
if (spelltar->invisible_animals) {
spelltar->MessageString(Chat::SpellFailure, ALREADY_INVIS, GetCleanName());
safe_delete(action_packet);
return false;
@ -3735,15 +3767,10 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
}
}
if(!(IsClient() && CastToClient()->GetGM()) && !IsHarmonySpell(spell_id)) // GMs can cast on anything
{
if (!(IsClient() && CastToClient()->GetGM()) && !IsHarmonySpell(spell_id)) {// GMs can cast on anything
// Beneficial spells check
if(IsBeneficialSpell(spell_id))
{
if(IsClient() && //let NPCs do beneficial spells on anybody if they want, should be the job of the AI, not the spell code to prevent this from going wrong
spelltar != this)
{
if (IsBeneficialSpell(spell_id)) {
if (IsClient() && spelltar != this) {//let NPCs do beneficial spells on anybody if they want, should be the job of the AI, not the spell code to prevent this from going wrong
Client* pClient = nullptr;
Raid* pRaid = nullptr;
Group* pBasicGroup = nullptr;
@ -3765,60 +3792,89 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
pClient = CastToClient();
pRaid = entity_list.GetRaidByClient(pClient);
pBasicGroup = entity_list.GetGroupByMob(this);
if(pRaid)
if (pRaid) {
nGroup = pRaid->GetGroup(pClient) + 1;
}
//Target client pointers
if(spelltar->IsClient())
{
if (spelltar->IsClient()) {
pClientTarget = spelltar->CastToClient();
pRaidTarget = entity_list.GetRaidByClient(pClientTarget);
pBasicGroupTarget = entity_list.GetGroupByMob(spelltar);
if(pRaidTarget)
if (pRaidTarget) {
nGroupTarget = pRaidTarget->GetGroup(pClientTarget) + 1;
}
}
if(spelltar->IsPet())
{
if (spelltar->IsPet()) {
Mob *owner = spelltar->GetOwner();
if(owner->IsClient())
{
if (owner->IsClient()) {
pClientTargetPet = owner->CastToClient();
pRaidTargetPet = entity_list.GetRaidByClient(pClientTargetPet);
pBasicGroupTargetPet = entity_list.GetGroupByMob(owner);
if(pRaidTargetPet)
if (pRaidTargetPet) {
nGroupTargetPet = pRaidTargetPet->GetGroup(pClientTargetPet) + 1;
}
}
}
if((!IsAllianceSpellLine(spell_id) && !IsBeneficialAllowed(spelltar)) ||
if (
(!IsAllianceSpellLine(spell_id) && !IsBeneficialAllowed(spelltar)) ||
(IsGroupOnlySpell(spell_id) &&
!(
(pBasicGroup && ((pBasicGroup == pBasicGroupTarget) || (pBasicGroup == pBasicGroupTargetPet))) || //Basic Group
((nGroup != cnWTF) && ((nGroup == nGroupTarget) || (nGroup == nGroupTargetPet))) || //Raid group
(spelltar == GetPet()) //should be able to cast grp spells on self and pet despite grped status.
(
pBasicGroup &&
(
pBasicGroup == pBasicGroupTarget ||
pBasicGroup == pBasicGroupTargetPet
)
) || //Basic Group
(
nGroup != cnWTF &&
(
nGroup == nGroupTarget ||
nGroup == nGroupTargetPet
)
) || //Raid group
spelltar == GetPet() //should be able to cast grp spells on self and pet despite grped status.
)
)
)
{
if(spells[spell_id].target_type == ST_AEBard) {
) {
if (spells[spell_id].target_type == ST_AEBard) {
//if it was a beneficial AE bard song don't spam the window that it would not hold
LogSpells("Beneficial ae bard song [{}] can't take hold [{}] -> [{}], IBA? [{}]", spell_id, GetName(), spelltar->GetName(), IsBeneficialAllowed(spelltar));
LogSpells(
"Beneficial ae bard song [{}] can't take hold [{}] -> [{}], IBA? [{}]",
spell_id,
GetName(),
spelltar->GetName(),
IsBeneficialAllowed(spelltar)
);
} else {
LogSpells("Beneficial spell [{}] can't take hold [{}] -> [{}], IBA? [{}]", spell_id, GetName(), spelltar->GetName(), IsBeneficialAllowed(spelltar));
LogSpells(
"Beneficial spell [{}] can't take hold [{}] -> [{}], IBA? [{}]",
spell_id,
GetName(),
spelltar->GetName(),
IsBeneficialAllowed(spelltar)
);
MessageString(Chat::SpellFailure, SPELL_NO_HOLD);
}
safe_delete(action_packet);
return false;
}
}
}
else if ( !IsAttackAllowed(spelltar, true) && !IsResurrectionEffects(spell_id) && !IsEffectInSpell(spell_id, SE_BindSight)) // Detrimental spells - PVP check
{
LogSpells("Detrimental spell [{}] can't take hold [{}] -> [{}]", spell_id, GetName(), spelltar->GetName());
} else if (
!IsAttackAllowed(spelltar, true) &&
!IsResurrectionEffects(spell_id) &&
!IsEffectInSpell(spell_id, SE_BindSight)
) { // Detrimental spells - PVP check
LogSpells(
"Detrimental spell [{}] can't take hold [{}] -> [{}]",
spell_id,
GetName(),
spelltar->GetName()
);
spelltar->MessageString(Chat::SpellFailure, YOU_ARE_PROTECTED, GetCleanName());
safe_delete(action_packet);
return false;
@ -3829,8 +3885,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
// but we need to check special cases and resists
// check immunities
if(spelltar->IsImmuneToSpell(spell_id, this))
{
if (spelltar->IsImmuneToSpell(spell_id, this)) {
//the above call does the message to the client if needed
LogSpells("Spell [{}] can't take hold due to immunity [{}] -> [{}]", spell_id, GetName(), spelltar->GetName());
safe_delete(action_packet);
@ -3838,30 +3893,36 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
}
//check for AE_Undead
if(spells[spell_id].target_type == ST_UndeadAE){
if(spelltar->GetBodyType() != BT_SummonedUndead &&
if (spells[spell_id].target_type == ST_UndeadAE){
if (
spelltar->GetBodyType() != BT_SummonedUndead &&
spelltar->GetBodyType() != BT_Undead &&
spelltar->GetBodyType() != BT_Vampire)
{
spelltar->GetBodyType() != BT_Vampire
) {
safe_delete(action_packet);
return false;
}
}
//Need this to account for special AOE cases.
if (IsClient() && IsHarmonySpell(spell_id) && !HarmonySpellLevelCheck(spell_id, spelltar)) {
if (
IsClient() &&
IsHarmonySpell(spell_id) &&
!HarmonySpellLevelCheck(spell_id, spelltar)
) {
MessageString(Chat::SpellFailure, SPELL_NO_EFFECT);
safe_delete(action_packet);
return false;
}
// Block next spell effect should be used up first(since its blocking the next spell)
if(CanBlockSpell()) {
if (CanBlockSpell()) {
int buff_count = GetMaxTotalSlots();
int focus = 0;
for (int b=0; b < buff_count; b++) {
if(IsEffectInSpell(buffs[b].spellid, SE_BlockNextSpellFocus)) {
for (int b = 0; b < buff_count; b++) {
if (IsEffectInSpell(buffs[b].spellid, SE_BlockNextSpellFocus)) {
focus = CalcFocusEffect(focusBlockNextSpell, buffs[b].spellid, spell_id);
if(focus) {
if (focus) {
CheckNumHitsRemaining(NumHit::MatchingSpells, b);
MessageString(Chat::SpellFailure, SPELL_WOULDNT_HOLD);
safe_delete(action_packet);
@ -3883,67 +3944,83 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
There are a few spells in database that are not detrimental that have Reflectable field set, however from testing, they do not actually reflect.
*/
if(spells[spell_id].reflectable && !reflect_effectiveness && spelltar && this != spelltar && IsDetrimentalSpell(spell_id) &&
(spelltar->spellbonuses.reflect[SBIndex::REFLECT_CHANCE] || spelltar->aabonuses.reflect[SBIndex::REFLECT_CHANCE] || spelltar->itembonuses.reflect[SBIndex::REFLECT_CHANCE])) {
if (
spells[spell_id].reflectable &&
!reflect_effectiveness &&
spelltar &&
this != spelltar &&
IsDetrimentalSpell(spell_id) &&
(
spelltar->spellbonuses.reflect[SBIndex::REFLECT_CHANCE] ||
spelltar->aabonuses.reflect[SBIndex::REFLECT_CHANCE] ||
spelltar->itembonuses.reflect[SBIndex::REFLECT_CHANCE]
)
) {
bool can_spell_reflect = false;
switch(RuleI(Spells, ReflectType))
{
case REFLECT_DISABLED:
break;
case REFLECT_SINGLE_TARGET_SPELLS_ONLY:
{
if(spells[spell_id].target_type == ST_Target) {
for(int y = 0; y < 16; y++) {
switch (RuleI(Spells, ReflectType)) {
case REFLECT_SINGLE_TARGET_SPELLS_ONLY: {
if (spells[spell_id].target_type == ST_Target) {
for (int y = 0; y < 16; y++) {
if (spells[spell_id].classes[y] < 255) {
can_spell_reflect = true;
}
}
}
break;
}
case REFLECT_ALL_PLAYER_SPELLS:
{
for(int y = 0; y < 16; y++) {
case REFLECT_ALL_PLAYER_SPELLS: {
for (int y = 0; y < 16; y++) {
if (spells[spell_id].classes[y] < 255) {
can_spell_reflect = true;
}
}
break;
}
case RELFECT_ALL_SINGLE_TARGET_SPELLS:
{
case RELFECT_ALL_SINGLE_TARGET_SPELLS: {
if (spells[spell_id].target_type == ST_Target) {
can_spell_reflect = true;
}
break;
}
case REFLECT_ALL_SPELLS: //This is live like behavior
case REFLECT_ALL_SPELLS: {//This is live like behavior
can_spell_reflect = true;
default:
}
case REFLECT_DISABLED:
default: {
break;
}
}
if (can_spell_reflect) {
if (can_spell_reflect) {
int reflect_resist_adjust = 0;
int reflect_effectiveness_mod = 0; //Need value of 100 to do baseline unmodified damage.
if (spelltar->spellbonuses.reflect[SBIndex::REFLECT_CHANCE] && zone->random.Roll(spelltar->spellbonuses.reflect[SBIndex::REFLECT_CHANCE])) {
reflect_resist_adjust = spelltar->spellbonuses.reflect[SBIndex::REFLECT_RESISTANCE_MOD];
reflect_effectiveness_mod = spelltar->spellbonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS] ? spelltar->spellbonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS] : 100;
}
else if (spelltar->aabonuses.reflect[SBIndex::REFLECT_CHANCE] && zone->random.Roll(spelltar->aabonuses.reflect[SBIndex::REFLECT_CHANCE])) {
if (
spelltar->spellbonuses.reflect[SBIndex::REFLECT_CHANCE] &&
zone->random.Roll(spelltar->spellbonuses.reflect[SBIndex::REFLECT_CHANCE])
) {
reflect_resist_adjust = spelltar->spellbonuses.reflect[SBIndex::REFLECT_RESISTANCE_MOD];
reflect_effectiveness_mod = spelltar->spellbonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS]
? spelltar->spellbonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS] : 100;
} else if (
spelltar->aabonuses.reflect[SBIndex::REFLECT_CHANCE] &&
zone->random.Roll(spelltar->aabonuses.reflect[SBIndex::REFLECT_CHANCE])
) {
reflect_effectiveness_mod = 100;
reflect_resist_adjust = spelltar->aabonuses.reflect[SBIndex::REFLECT_RESISTANCE_MOD];
}
else if (spelltar->itembonuses.reflect[SBIndex::REFLECT_CHANCE] && zone->random.Roll(spelltar->itembonuses.reflect[SBIndex::REFLECT_CHANCE])) {
reflect_resist_adjust = spelltar->itembonuses.reflect[SBIndex::REFLECT_RESISTANCE_MOD];
reflect_effectiveness_mod = spelltar->itembonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS] ? spelltar->itembonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS] : 100;
} else if (
spelltar->itembonuses.reflect[SBIndex::REFLECT_CHANCE] &&
zone->random.Roll(spelltar->itembonuses.reflect[SBIndex::REFLECT_CHANCE])
) {
reflect_resist_adjust = spelltar->itembonuses.reflect[SBIndex::REFLECT_RESISTANCE_MOD];
reflect_effectiveness_mod = spelltar->itembonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS]
? spelltar->itembonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS] : 100;
}
if (reflect_effectiveness_mod) {
if (RuleB(Spells, ReflectMessagesClose)) {
entity_list.MessageCloseString(
this, /* Sender */
@ -3954,8 +4031,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
GetCleanName(), /* Message 1 */
spelltar->GetCleanName() /* Message 2 */
);
}
else {
} else {
MessageString(Chat::Spells, SPELL_REFLECT, GetCleanName(), spelltar->GetCleanName());
}
@ -3971,40 +4047,62 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
// resist check - every spell can be resisted, beneficial or not
// add: ok this isn't true, eqlive's spell data is fucked up, buffs are
// not all unresistable, so changing this to only check certain spells
if(IsResistableSpell(spell_id))
{
if (IsResistableSpell(spell_id)) {
spelltar->BreakInvisibleSpells(); //Any detrimental spell cast on you will drop invisible (can be AOE, non damage ect).
if (IsCharmSpell(spell_id) || IsMezSpell(spell_id) || IsFearSpell(spell_id))
spell_effectiveness = spelltar->ResistSpell(spells[spell_id].resist_type, spell_id, this, use_resist_adjust, resist_adjust, true, false, false, level_override);
else
spell_effectiveness = spelltar->ResistSpell(spells[spell_id].resist_type, spell_id, this, use_resist_adjust, resist_adjust, false, false, false, level_override);
if (
IsCharmSpell(spell_id) ||
IsMezSpell(spell_id) ||
IsFearSpell(spell_id)
) {
spell_effectiveness = spelltar->ResistSpell(
spells[spell_id].resist_type,
spell_id,
this,
use_resist_adjust,
resist_adjust,
true,
false,
false,
level_override
);
} else {
spell_effectiveness = spelltar->ResistSpell(
spells[spell_id].resist_type,
spell_id,
this,
use_resist_adjust,
resist_adjust,
false,
false,
false,
level_override
);
}
if(spell_effectiveness < 100)
{
if(spell_effectiveness == 0 || !IsPartialCapableSpell(spell_id) )
{
if (spell_effectiveness < 100) {
if (spell_effectiveness == 0 || !IsPartialCapableSpell(spell_id)) {
LogSpells("Spell [{}] was completely resisted by [{}]", spell_id, spelltar->GetName());
if (spells[spell_id].resist_type == RESIST_PHYSICAL){
MessageString(Chat::SpellFailure, PHYSICAL_RESIST_FAIL,spells[spell_id].name);
spelltar->MessageString(Chat::SpellFailure, YOU_RESIST, spells[spell_id].name);
}
else {
} else {
MessageString(Chat::SpellFailure, TARGET_RESISTED, spells[spell_id].name);
spelltar->MessageString(Chat::SpellFailure, YOU_RESIST, spells[spell_id].name);
}
if (spelltar->IsAIControlled()) {
int32 aggro = CheckAggroAmount(spell_id, spelltar);
auto aggro = CheckAggroAmount(spell_id, spelltar);
if (aggro > 0) {
if (!IsHarmonySpell(spell_id))
if (!IsHarmonySpell(spell_id)) {
spelltar->AddToHateList(this, aggro);
else if (!spelltar->PassCharismaCheck(this, spell_id))
} else if (!spelltar->PassCharismaCheck(this, spell_id)) {
spelltar->AddToHateList(this, aggro);
}
} else {
int newhate = spelltar->GetHateAmount(this) + aggro;
spelltar->SetHateAmountOnEnt(this, std::max(1, newhate));
int64 newhate = spelltar->GetHateAmount(this) + aggro;
spelltar->SetHateAmountOnEnt(this, std::max(static_cast<int64>(1), newhate));
}
}
@ -4025,33 +4123,41 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
spelltar->CastToClient()->BreakSneakWhenCastOn(this, false);
spelltar->CastToClient()->BreakFeignDeathWhenCastOn(false);
}
}
else
{
} else {
spell_effectiveness = 100;
}
if (spells[spell_id].feedbackable && (spelltar->spellbonuses.SpellDamageShield || spelltar->itembonuses.SpellDamageShield || spelltar->aabonuses.SpellDamageShield)) {
if (
spells[spell_id].feedbackable &&
(
spelltar->spellbonuses.SpellDamageShield ||
spelltar->itembonuses.SpellDamageShield ||
spelltar->aabonuses.SpellDamageShield
)
) {
spelltar->DamageShield(this, true);
}
if (spelltar->IsAIControlled() && IsDetrimentalSpell(spell_id) && !IsHarmonySpell(spell_id)) {
int32 aggro_amount = CheckAggroAmount(spell_id, spelltar, isproc);
if (
spelltar->IsAIControlled() &&
IsDetrimentalSpell(spell_id) &&
!IsHarmonySpell(spell_id)
) {
auto aggro_amount = CheckAggroAmount(spell_id, spelltar, isproc);
LogSpells("Spell [{}] cast on [{}] generated [{}] hate", spell_id,
spelltar->GetName(), aggro_amount);
if (aggro_amount > 0) {
spelltar->AddToHateList(this, aggro_amount);
} else {
int32 newhate = spelltar->GetHateAmount(this) + aggro_amount;
spelltar->SetHateAmountOnEnt(this, std::max(newhate, 1));
int64 newhate = spelltar->GetHateAmount(this) + aggro_amount;
spelltar->SetHateAmountOnEnt(this, std::max(newhate, static_cast<int64>(1)));
}
} else if (IsBeneficialSpell(spell_id) && !IsSummonPCSpell(spell_id)) {
if (this != spelltar && IsClient()){
if (spelltar->IsClient()) {
CastToClient()->UpdateRestTimer(spelltar->CastToClient()->GetRestTimer());
}
else if (spelltar->IsPet()) {
Mob *owner = spelltar->GetOwner();
} else if (spelltar->IsPet()) {
auto* owner = spelltar->GetOwner();
if (owner && owner != this && owner->IsClient()) {
CastToClient()->UpdateRestTimer(owner->CastToClient()->GetRestTimer());
}
@ -4059,23 +4165,39 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
}
entity_list.AddHealAggro(
spelltar, this,
CheckHealAggroAmount(spell_id, spelltar, (spelltar->GetMaxHP() - spelltar->GetHP())));
spelltar,
this,
CheckHealAggroAmount(
spell_id,
spelltar,
(spelltar->GetMaxHP() - spelltar->GetHP())
)
);
}
// make sure spelltar is high enough level for the buff
if(RuleB(Spells, BuffLevelRestrictions) && !spelltar->CheckSpellLevelRestriction(spell_id))
{
if (RuleB(Spells, BuffLevelRestrictions) && !spelltar->CheckSpellLevelRestriction(spell_id)) {
LogSpells("Spell [{}] failed: recipient did not meet the level restrictions", spell_id);
if(!IsBardSong(spell_id))
if (!IsBardSong(spell_id)) {
MessageString(Chat::SpellFailure, SPELL_TOO_POWERFUL);
}
safe_delete(action_packet);
return false;
}
// cause the effects to the target
if(!spelltar->SpellEffect(this, spell_id, spell_effectiveness, level_override, reflect_effectiveness, duration_override, disable_buff_overrwrite))
{
if (
!spelltar->SpellEffect(
this,
spell_id,
spell_effectiveness,
level_override,
reflect_effectiveness,
duration_override,
disable_buff_overwrite
)
) {
// if SpellEffect returned false there's a problem applying the
// spell. It's most likely a buff that can't stack.
LogSpells("Spell [{}] could not apply its effects [{}] -> [{}]\n", spell_id, GetName(), spelltar->GetName());
@ -4087,18 +4209,27 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
}
//Check SE_Fc_Cast_Spell_On_Land SPA 481 on target, if hit by this spell and Conditions are Met then target will cast the specified spell.
if (spelltar)
if (spelltar) {
spelltar->CastSpellOnLand(this, spell_id);
}
if (IsValidSpell(spells[spell_id].recourse_link) && spells[spell_id].recourse_link != spell_id)
SpellFinished(spells[spell_id].recourse_link, this, CastingSlot::Item, 0, -1, spells[spells[spell_id].recourse_link].resist_difficulty);
if (IsValidSpell(spells[spell_id].recourse_link) && spells[spell_id].recourse_link != spell_id) {
SpellFinished(
spells[spell_id].recourse_link,
this,
CastingSlot::Item,
0,
-1,
spells[spells[spell_id].recourse_link].resist_difficulty
);
}
if (IsDetrimentalSpell(spell_id)) {
CheckNumHitsRemaining(NumHit::OutgoingSpells);
if (spelltar)
if (spelltar) {
spelltar->CheckNumHitsRemaining(NumHit::IncomingSpells);
}
}
// send the action packet again now that the spell is successful
@ -4107,16 +4238,17 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
// the complete sequence is 2 actions and 1 damage message
action->effect_flag = 0x04; // this is a success flag
if(spells[spell_id].push_back != 0.0f || spells[spell_id].push_up != 0.0f)
{
if (spelltar->IsClient())
{
if (!IsBuffSpell(spell_id))
{
if (spells[spell_id].push_back != 0.0f || spells[spell_id].push_up != 0.0f) {
if (spelltar->IsClient()) {
if (!IsBuffSpell(spell_id)) {
spelltar->CastToClient()->cheat_manager.SetExemptStatus(KnockBack, true);
}
}
else if (RuleB(Spells, NPCSpellPush) && !spelltar->IsPermaRooted() && !spelltar->IsPseudoRooted() && spelltar->ForcedMovement == 0) {
} else if (
RuleB(Spells, NPCSpellPush) &&
!spelltar->IsPermaRooted() &&
!spelltar->IsPseudoRooted() &&
!spelltar->ForcedMovement
) {
spelltar->m_Delta.x += action->force * g_Math.FastSin(action->hit_heading);
spelltar->m_Delta.y += action->force * g_Math.FastCos(action->hit_heading);
spelltar->m_Delta.z += action->hit_pitch;
@ -4124,17 +4256,18 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
}
}
if (spelltar->IsClient() && IsEffectInSpell(spell_id, SE_ShadowStep))
{
if (spelltar->IsClient() && IsEffectInSpell(spell_id, SE_ShadowStep)) {
spelltar->CastToClient()->cheat_manager.SetExemptStatus(ShadowStep, true);
}
if(!IsEffectInSpell(spell_id, SE_BindAffinity))
{
if(spelltar != this && spelltar->IsClient()) // send to target
if (!IsEffectInSpell(spell_id, SE_BindAffinity)) {
if (spelltar != this && spelltar->IsClient()) {// send to target
spelltar->CastToClient()->QueuePacket(action_packet);
if(IsClient()) // send to caster
}
if(IsClient()) {// send to caster
CastToClient()->QueuePacket(action_packet);
}
}
message_packet = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct));
@ -4148,7 +4281,12 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
cd->hit_pitch = action->hit_pitch;
cd->damage = 0;
if (!IsLifetapSpell(spell_id) && !IsEffectInSpell(spell_id, SE_BindAffinity) && !IsAENukeSpell(spell_id) && !IsDamageSpell(spell_id)) {
if (
!IsLifetapSpell(spell_id) &&
!IsEffectInSpell(spell_id, SE_BindAffinity) &&
!IsAENukeSpell(spell_id) &&
!IsDamageSpell(spell_id)
) {
entity_list.QueueCloseClients(
spelltar, /* Sender */
message_packet, /* Packet */
@ -4159,6 +4297,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
(spellOwner->IsClient() ? FilterPCSpells : FilterNPCSpells) /* Message Filter Type: (8 or 9) */
);
}
safe_delete(action_packet);
safe_delete(message_packet);