[Quest API] Add Area-Based Quest Methods to Perl/Lua (#4447)

* [Quest API] Add Area-Based Quest Methods to Perl/Lua

* Convert some to mob

* Fix
This commit is contained in:
Alex King 2024-08-26 21:29:07 -04:00 committed by GitHub
parent 080865faa2
commit 40738b29e3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 492 additions and 135 deletions

View File

@ -751,4 +751,9 @@ static std::map<uint32, std::string> stance_names = {
{ Stance::AEBurn, "AE Burn" }
};
namespace PCNPCOnlyFlagType {
constexpr int PC = 1;
constexpr int NPC = 2;
}
#endif /*COMMON_EMU_CONSTANTS_H*/

View File

@ -1028,24 +1028,15 @@ void Client::SendDisciplineTimer(uint32 timer_id, uint32 duration)
}
}
/**
* @param taunter
* @param range
* @param bonus_hate
*/
void EntityList::AETaunt(Client *taunter, float range, int32 bonus_hate)
void EntityList::AETaunt(Client* taunter, float range, int bonus_hate)
{
/**
* Live AE taunt range - Hardcoded.
*/
if (range == 0) {
range = 40;
}
float range_squared = range * range;
for (auto &it : entity_list.GetCloseMobList(taunter, range)) {
for (auto& it: entity_list.GetCloseMobList(taunter, range)) {
Mob *them = it.second;
if (!them) {
continue;
@ -1060,9 +1051,11 @@ void EntityList::AETaunt(Client *taunter, float range, int32 bonus_hate)
z_difference *= -1;
}
if (z_difference < 10
&& taunter->IsAttackAllowed(them)
&& DistanceSquaredNoZ(taunter->GetPosition(), them->GetPosition()) <= range_squared) {
if (
z_difference < 10 &&
taunter->IsAttackAllowed(them) &&
DistanceSquaredNoZ(taunter->GetPosition(), them->GetPosition()) <= range_squared
) {
if (taunter->CheckLosFN(them)) {
taunter->Taunt(them->CastToNPC(), true, 0, true, bonus_hate);
}
@ -1070,38 +1063,31 @@ void EntityList::AETaunt(Client *taunter, float range, int32 bonus_hate)
}
}
/**
* Causes caster to hit every mob within dist range of center with spell_id
*
* @param caster_mob
* @param center_mob
* @param spell_id
* @param affect_caster
* @param resist_adjust
* @param max_targets
*/
void EntityList::AESpell(
Mob *caster_mob,
Mob *center_mob,
Mob* caster_mob,
Mob* center_mob,
uint16 spell_id,
bool affect_caster,
int16 resist_adjust,
int *max_targets
int* max_targets,
bool is_scripted
)
{
const auto &cast_target_position =
spells[spell_id].target_type == ST_Ring ?
caster_mob->GetTargetRingLocation() :
static_cast<glm::vec3>(center_mob->GetPosition());
const auto& cast_target_position = (
(!is_scripted && spells[spell_id].target_type == ST_Ring) ?
caster_mob->GetTargetRingLocation() :
static_cast<glm::vec3>(center_mob->GetPosition())
);
Mob* current_mob = nullptr;
Mob *current_mob = nullptr;
bool is_detrimental_spell = IsDetrimentalSpell(spell_id);
bool is_npc = caster_mob->IsNPC();
float distance = caster_mob->GetAOERange(spell_id);
float distance_squared = distance * distance;
float min_range2 = spells[spell_id].min_range * spells[spell_id].min_range;
glm::vec2 min = {cast_target_position.x - distance, cast_target_position.y - distance};
glm::vec2 max = {cast_target_position.x + distance, cast_target_position.y + distance};
float min_range_squared = spells[spell_id].min_range * spells[spell_id].min_range;
glm::vec2 min = { cast_target_position.x - distance, cast_target_position.y - distance };
glm::vec2 max = { cast_target_position.x + distance, cast_target_position.y + distance };
/**
* If using Old Rain Targets - there is no max target limitation
@ -1110,17 +1096,18 @@ void EntityList::AESpell(
max_targets = nullptr;
}
/**
* Max AOE targets
*/
int max_targets_allowed = RuleI(Range, AOEMaxTargets); // unlimited
if (max_targets) { // rains pass this in since they need to preserve the count through waves
max_targets_allowed = *max_targets;
}
else if (spells[spell_id].aoe_max_targets) {
} else if (spells[spell_id].aoe_max_targets) {
max_targets_allowed = spells[spell_id].aoe_max_targets;
}
else if (IsTargetableAESpell(spell_id) && is_detrimental_spell && !is_npc && !IsEffectInSpell(spell_id, SE_Lull) && !IsEffectInSpell(spell_id, SE_Mez)) {
} else if (
IsTargetableAESpell(spell_id) &&
is_detrimental_spell &&
!is_npc &&
!IsEffectInSpell(spell_id, SE_Lull) &&
!IsEffectInSpell(spell_id, SE_Mez)
) {
max_targets_allowed = 4;
}
@ -1133,7 +1120,7 @@ void EntityList::AESpell(
distance
);
for (auto &it : entity_list.GetCloseMobList(caster_mob, distance)) {
for (auto& it: entity_list.GetCloseMobList(caster_mob, distance)) {
current_mob = it.second;
if (!current_mob) {
continue;
@ -1161,16 +1148,11 @@ void EntityList::AESpell(
continue;
}
/**
* Check PC / NPC
* 1 = PC
* 2 = NPC
*/
if (spells[spell_id].pcnpc_only_flag == 1 && !current_mob->IsOfClientBotMerc()) {
if (spells[spell_id].pcnpc_only_flag == PCNPCOnlyFlagType::PC && !current_mob->IsOfClientBotMerc()) {
continue;
}
if (spells[spell_id].pcnpc_only_flag == 2 && current_mob->IsOfClientBotMerc()) {
if (spells[spell_id].pcnpc_only_flag == PCNPCOnlyFlagType::NPC && current_mob->IsOfClientBotMerc()) {
continue;
}
@ -1184,41 +1166,40 @@ void EntityList::AESpell(
continue;
}
if (distance_to_target < min_range2) {
if (distance_to_target < min_range_squared) {
continue;
}
if (is_npc && current_mob->IsNPC() &&
spells[spell_id].target_type != ST_AreaNPCOnly) { //check npc->npc casting
FACTION_VALUE faction_value = current_mob->GetReverseFactionCon(caster_mob);
if (
is_npc &&
current_mob->IsNPC() &&
spells[spell_id].target_type != ST_AreaNPCOnly
) {
const auto faction_value = current_mob->GetReverseFactionCon(caster_mob);
if (is_detrimental_spell) {
//affect mobs that are on our hate list, or
//which have bad faction with us
if (
!(caster_mob->CheckAggro(current_mob) ||
faction_value == FACTION_THREATENINGLY ||
faction_value == FACTION_SCOWLS)) {
faction_value == FACTION_THREATENINGLY ||
faction_value == FACTION_SCOWLS)
) {
continue;
}
}
else {
//only affect mobs we would assist.
} else {
if (!(faction_value <= FACTION_AMIABLY)) {
continue;
}
}
}
/**
* Finally, make sure they are within range
*/
if (is_detrimental_spell) {
if (!caster_mob->IsAttackAllowed(current_mob, true)) {
continue;
}
if (center_mob && !spells[spell_id].npc_no_los && !center_mob->CheckLosFN(current_mob)) {
continue;
}
if (!center_mob && !spells[spell_id].npc_no_los && !caster_mob->CheckLosFN(
caster_mob->GetTargetRingX(),
caster_mob->GetTargetRingY(),
@ -1226,9 +1207,7 @@ void EntityList::AESpell(
current_mob->GetSize())) {
continue;
}
}
else {
} else {
/**
* Check to stop casting beneficial ae buffs (to wit: bard songs) on enemies...
* This does not check faction for beneficial AE buffs... only agro and attackable.
@ -1238,6 +1217,7 @@ void EntityList::AESpell(
if (caster_mob->IsAttackAllowed(current_mob, true)) {
continue;
}
if (caster_mob->CheckAggro(current_mob)) {
continue;
}
@ -1264,40 +1244,29 @@ void EntityList::AESpell(
}
}
/**
* @param caster
* @param center
* @param spell_id
* @param affect_caster
*/
void EntityList::MassGroupBuff(
Mob *caster,
Mob *center,
Mob* caster,
Mob* center,
uint16 spell_id,
bool affect_caster)
bool affect_caster
)
{
Mob *current_mob = nullptr;
Mob* current_mob = nullptr;
float distance = caster->GetAOERange(spell_id);
float distance_squared = distance * distance;
bool is_detrimental_spell = IsDetrimentalSpell(spell_id);
for (auto &it : entity_list.GetCloseMobList(caster, distance)) {
for (auto& it: entity_list.GetCloseMobList(caster, distance)) {
current_mob = it.second;
if (!current_mob) {
continue;
}
/**
* Skip center
*/
if (current_mob == center) {
if (current_mob == center) { // Skip Center
continue;
}
/**
* Skip self
*/
if (current_mob == caster && !affect_caster) {
if (current_mob == caster && !affect_caster) { // Skip Caster
continue;
}
@ -1305,17 +1274,13 @@ void EntityList::MassGroupBuff(
continue;
}
/**
* Pets
*/
if (current_mob->IsNPC()) {
Mob *owner = current_mob->GetOwner();
Mob* owner = current_mob->GetOwner();
if (owner) {
if (!owner->IsOfClientBot()) {
continue;
}
}
else {
} else {
continue;
}
}
@ -1328,55 +1293,48 @@ void EntityList::MassGroupBuff(
}
}
/**
* Rampage - Normal and Duration rampages
* NPCs handle it differently in Mob::Rampage
*
* @param attacker
* @param distance
* @param Hand
* @param count
* @param is_from_spell
*/
void EntityList::AEAttack(
Mob *attacker,
Mob* attacker,
float distance,
int Hand,
int count,
int16 slot_id,
int hit_count,
bool is_from_spell,
int attack_rounds)
int attack_rounds
)
{
Mob *current_mob = nullptr;
Mob* current_mob = nullptr;
float distance_squared = distance * distance;
int hit_count = 0;
int current_hits = 0;
for (auto &it : entity_list.GetCloseMobList(attacker, distance)) {
for (auto& it: entity_list.GetCloseMobList(attacker, distance)) {
current_mob = it.second;
if (!current_mob) {
continue;
}
if (current_mob->IsNPC()
&& current_mob != attacker //this is not needed unless NPCs can use this
&& (attacker->IsAttackAllowed(current_mob))
&& !current_mob->IsHorse() /* dont attack mounts */
&& (DistanceSquared(current_mob->GetPosition(), attacker->GetPosition()) <= distance_squared)
) {
if (
current_mob->IsNPC() &&
current_mob != attacker &&
attacker->IsAttackAllowed(current_mob) &&
!current_mob->IsHorse() &&
DistanceSquared(current_mob->GetPosition(), attacker->GetPosition()) <= distance_squared
) {
for (int i = 0; i < attack_rounds; i++) {
if (!attacker->IsClient() || attacker->GetClass() == Class::Monk || attacker->GetClass() == Class::Ranger) {
attacker->Attack(current_mob, Hand, false, false, is_from_spell);
if (
!attacker->IsClient() ||
attacker->GetClass() == Class::Monk ||
attacker->GetClass() == Class::Ranger
) {
attacker->Attack(current_mob, slot_id, false, false, is_from_spell);
} else {
attacker->CastToClient()->DoAttackRounds(current_mob, Hand, is_from_spell);
attacker->CastToClient()->DoAttackRounds(current_mob, slot_id, is_from_spell);
}
}
hit_count++;
if (count != 0 && hit_count >= count) {
current_hits++;
if (hit_count != 0 && current_hits >= hit_count) {
return;
}
}
}
}

View File

@ -436,23 +436,24 @@ public:
void QueueToGroupsForNPCHealthAA(Mob* sender, const EQApplicationPacket* app);
void AEAttack(
Mob *attacker,
Mob* attacker,
float distance,
int Hand = EQ::invslot::slotPrimary,
int count = 0,
int16 slot_id = EQ::invslot::slotPrimary,
int hit_count = 0,
bool is_from_spell = false,
int attack_rounds = 1
);
void AETaunt(Client *caster, float range = 0, int32 bonus_hate = 0);
void AETaunt(Client* caster, float range = 0, int bonus_hate = 0);
void AESpell(
Mob *caster,
Mob *center,
Mob* caster,
Mob* center,
uint16 spell_id,
bool affect_caster = true,
int16 resist_adjust = 0,
int *max_targets = nullptr
int* max_targets = nullptr,
bool is_scripted = false
);
void MassGroupBuff(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster = true);
void MassGroupBuff(Mob* caster, Mob* center, uint16 spell_id, bool affect_caster = true);
//trap stuff
Mob* GetTrapTrigger(Trap* trap);

View File

@ -3412,6 +3412,24 @@ bool Lua_Client::AreTasksCompleted(luabind::object task_ids)
return self->AreTasksCompleted(v);
}
void Lua_Client::AreaTaunt()
{
Lua_Safe_Call_Void();
entity_list.AETaunt(self);
}
void Lua_Client::AreaTaunt(float range)
{
Lua_Safe_Call_Void();
entity_list.AETaunt(self, range);
}
void Lua_Client::AreaTaunt(float range, int bonus_hate)
{
Lua_Safe_Call_Void();
entity_list.AETaunt(self, range, bonus_hate);
}
luabind::scope lua_register_client() {
return luabind::class_<Lua_Client, Lua_Mob>("Client")
.def(luabind::constructor<>())
@ -3459,6 +3477,9 @@ luabind::scope lua_register_client() {
.def("ApplySpellRaid", (void(Lua_Client::*)(int,int,int,bool,bool))&Lua_Client::ApplySpellRaid)
.def("ApplySpellRaid", (void(Lua_Client::*)(int,int,int,bool,bool,bool))&Lua_Client::ApplySpellRaid)
.def("AreTasksCompleted", (bool(Lua_Client::*)(luabind::object))&Lua_Client::AreTasksCompleted)
.def("AreaTaunt", (void(Lua_Client::*)(void))&Lua_Client::AreaTaunt)
.def("AreaTaunt", (void(Lua_Client::*)(float))&Lua_Client::AreaTaunt)
.def("AreaTaunt", (void(Lua_Client::*)(float, int))&Lua_Client::AreaTaunt)
.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)

View File

@ -505,6 +505,9 @@ public:
void DescribeSpecialAbilities(Lua_NPC n);
void ResetLeadershipAA();
uint8 GetSkillTrainLevel(int skill_id);
void AreaTaunt();
void AreaTaunt(float range);
void AreaTaunt(float range, int bonus_hate);
void ApplySpell(int spell_id);
void ApplySpell(int spell_id, int duration);

View File

@ -680,11 +680,107 @@ Lua_Mob_List Lua_EntityList::GetCloseMobList(Lua_Mob mob, float distance, bool i
return ret;
}
void Lua_EntityList::AreaAttack(Lua_Mob attacker, float distance)
{
Lua_Safe_Call_Void();
self->AEAttack(attacker, distance);
}
void Lua_EntityList::AreaAttack(Lua_Mob attacker, float distance, int16 slot_id)
{
Lua_Safe_Call_Void();
self->AEAttack(attacker, distance, slot_id);
}
void Lua_EntityList::AreaAttack(Lua_Mob attacker, float distance, int16 slot_id, int count)
{
Lua_Safe_Call_Void();
self->AEAttack(attacker, distance, slot_id, count);
}
void Lua_EntityList::AreaAttack(Lua_Mob attacker, float distance, int16 slot_id, int count, bool is_from_spell)
{
Lua_Safe_Call_Void();
self->AEAttack(attacker, distance, slot_id, count, is_from_spell);
}
void Lua_EntityList::AreaAttack(Lua_Mob attacker, float distance, int16 slot_id, int count, bool is_from_spell, int attack_rounds)
{
Lua_Safe_Call_Void();
self->AEAttack(attacker, distance, slot_id, count, is_from_spell, attack_rounds);
}
void Lua_EntityList::AreaSpell(Lua_Mob caster, Lua_Mob center, uint16 spell_id)
{
Lua_Safe_Call_Void();
self->AESpell(caster, center, spell_id);
}
void Lua_EntityList::AreaSpell(Lua_Mob caster, Lua_Mob center, uint16 spell_id, bool affect_caster)
{
Lua_Safe_Call_Void();
self->AESpell(caster, center, spell_id, affect_caster);
}
void Lua_EntityList::AreaSpell(Lua_Mob caster, Lua_Mob center, uint16 spell_id, bool affect_caster, int16 resist_adjust)
{
Lua_Safe_Call_Void();
self->AESpell(caster, center, spell_id, affect_caster, resist_adjust);
}
void Lua_EntityList::AreaSpell(Lua_Mob caster, Lua_Mob center, uint16 spell_id, bool affect_caster, int16 resist_adjust, int max_targets)
{
Lua_Safe_Call_Void();
self->AESpell(caster, center, spell_id, affect_caster, resist_adjust, &max_targets);
}
void Lua_EntityList::AreaTaunt(Lua_Client caster)
{
Lua_Safe_Call_Void();
self->AETaunt(caster);
}
void Lua_EntityList::AreaTaunt(Lua_Client caster, float range)
{
Lua_Safe_Call_Void();
self->AETaunt(caster, range);
}
void Lua_EntityList::AreaTaunt(Lua_Client caster, float range, int bonus_hate)
{
Lua_Safe_Call_Void();
self->AETaunt(caster, range, bonus_hate);
}
void Lua_EntityList::MassGroupBuff(Lua_Mob caster, Lua_Mob center, uint16 spell_id)
{
Lua_Safe_Call_Void();
self->MassGroupBuff(caster, center, spell_id);
}
void Lua_EntityList::MassGroupBuff(Lua_Mob caster, Lua_Mob center, uint16 spell_id, bool affect_caster)
{
Lua_Safe_Call_Void();
self->MassGroupBuff(caster, center, spell_id, affect_caster);
}
luabind::scope lua_register_entity_list() {
return luabind::class_<Lua_EntityList>("EntityList")
.def(luabind::constructor<>())
.property("null", &Lua_EntityList::Null)
.property("valid", &Lua_EntityList::Valid)
.def("AreaAttack", (void(Lua_EntityList::*)(Lua_Mob, float))&Lua_EntityList::AreaAttack)
.def("AreaAttack", (void(Lua_EntityList::*)(Lua_Mob, float, int16))&Lua_EntityList::AreaAttack)
.def("AreaAttack", (void(Lua_EntityList::*)(Lua_Mob, float, int16, int))&Lua_EntityList::AreaAttack)
.def("AreaAttack", (void(Lua_EntityList::*)(Lua_Mob, float, int16, int, bool))&Lua_EntityList::AreaAttack)
.def("AreaAttack", (void(Lua_EntityList::*)(Lua_Mob, float, int16, int, bool, int))&Lua_EntityList::AreaAttack)
.def("AreaSpell", (void(Lua_EntityList::*)(Lua_Mob, Lua_Mob, uint16))&Lua_EntityList::AreaSpell)
.def("AreaSpell", (void(Lua_EntityList::*)(Lua_Mob, Lua_Mob, uint16, bool))&Lua_EntityList::AreaSpell)
.def("AreaSpell", (void(Lua_EntityList::*)(Lua_Mob, Lua_Mob, uint16, bool, int16))&Lua_EntityList::AreaSpell)
.def("AreaSpell", (void(Lua_EntityList::*)(Lua_Mob, Lua_Mob, uint16, bool, int16, int))&Lua_EntityList::AreaSpell)
.def("AreaTaunt", (void(Lua_EntityList::*)(Lua_Client))&Lua_EntityList::AreaTaunt)
.def("AreaTaunt", (void(Lua_EntityList::*)(Lua_Client, float))&Lua_EntityList::AreaTaunt)
.def("AreaTaunt", (void(Lua_EntityList::*)(Lua_Client, float, int))&Lua_EntityList::AreaTaunt)
.def("CanAddHateForMob", (bool(Lua_EntityList::*)(Lua_Mob))&Lua_EntityList::CanAddHateForMob)
.def("ChannelMessage", (void(Lua_EntityList::*)(Lua_Mob, int, uint8, const char*))&Lua_EntityList::ChannelMessage)
.def("ClearClientPetitionQueue", (void(Lua_EntityList::*)(void))&Lua_EntityList::ClearClientPetitionQueue)
@ -759,6 +855,8 @@ luabind::scope lua_register_entity_list() {
.def("Marquee", (void(Lua_EntityList::*)(uint32, std::string))&Lua_EntityList::Marquee)
.def("Marquee", (void(Lua_EntityList::*)(uint32, std::string, uint32))&Lua_EntityList::Marquee)
.def("Marquee", (void(Lua_EntityList::*)(uint32, uint32, uint32, uint32, uint32, std::string))&Lua_EntityList::Marquee)
.def("MassGroupBuff", (void(Lua_EntityList::*)(Lua_Mob, Lua_Mob, uint16))&Lua_EntityList::MassGroupBuff)
.def("MassGroupBuff", (void(Lua_EntityList::*)(Lua_Mob, Lua_Mob, uint16, bool))&Lua_EntityList::MassGroupBuff)
.def("Message", (void(Lua_EntityList::*)(uint32, uint32, const char*))&Lua_EntityList::Message)
.def("MessageClose", (void(Lua_EntityList::*)(Lua_Mob, bool, float, uint32, const char*))&Lua_EntityList::MessageClose)
.def("MessageGroup", (void(Lua_EntityList::*)(Lua_Mob, bool, uint32, const char*))&Lua_EntityList::MessageGroup)

View File

@ -142,6 +142,21 @@ public:
Lua_Mob_List GetCloseMobList(Lua_Mob mob);
Lua_Mob_List GetCloseMobList(Lua_Mob mob, float distance);
Lua_Mob_List GetCloseMobList(Lua_Mob mob, float distance, bool ignore_self);
void AreaAttack(Lua_Mob attacker, float distance);
void AreaAttack(Lua_Mob attacker, float distance, int16 slot_id);
void AreaAttack(Lua_Mob attacker, float distance, int16 slot_id, int count);
void AreaAttack(Lua_Mob attacker, float distance, int16 slot_id, int count, bool is_from_spell);
void AreaAttack(Lua_Mob attacker, float distance, int16 slot_id, int count, bool is_from_spell, int attack_rounds);
void AreaSpell(Lua_Mob caster, Lua_Mob center, uint16 spell_id);
void AreaSpell(Lua_Mob caster, Lua_Mob center, uint16 spell_id, bool affect_caster);
void AreaSpell(Lua_Mob caster, Lua_Mob center, uint16 spell_id, bool affect_caster, int16 resist_adjust);
void AreaSpell(Lua_Mob caster, Lua_Mob center, uint16 spell_id, bool affect_caster, int16 resist_adjust, int max_targets);
void AreaTaunt(Lua_Client caster);
void AreaTaunt(Lua_Client caster, float range);
void AreaTaunt(Lua_Client caster, float range, int bonus_hate);
void MassGroupBuff(Lua_Mob caster, Lua_Mob center, uint16 spell_id);
void MassGroupBuff(Lua_Mob caster, Lua_Mob center, uint16 spell_id, bool affect_caster);
};
#endif

View File

@ -3380,6 +3380,72 @@ int Lua_Mob::GetExtraHaste()
return self->GetExtraHaste();
}
void Lua_Mob::AreaAttack(float distance)
{
Lua_Safe_Call_Void();
entity_list.AEAttack(self, distance);
}
void Lua_Mob::AreaAttack(float distance, int16 slot_id)
{
Lua_Safe_Call_Void();
entity_list.AEAttack(self, distance, slot_id);
}
void Lua_Mob::AreaAttack(float distance, int16 slot_id, int count)
{
Lua_Safe_Call_Void();
entity_list.AEAttack(self, distance, slot_id, count);
}
void Lua_Mob::AreaAttack(float distance, int16 slot_id, int count, bool is_from_spell)
{
Lua_Safe_Call_Void();
entity_list.AEAttack(self, distance, slot_id, count, is_from_spell);
}
void Lua_Mob::AreaAttack(float distance, int16 slot_id, int count, bool is_from_spell, int attack_rounds)
{
Lua_Safe_Call_Void();
entity_list.AEAttack(self, distance, slot_id, count, is_from_spell, attack_rounds);
}
void Lua_Mob::AreaSpell(Lua_Mob center, uint16 spell_id)
{
Lua_Safe_Call_Void();
entity_list.AESpell(self, center, spell_id);
}
void Lua_Mob::AreaSpell(Lua_Mob center, uint16 spell_id, bool affect_caster)
{
Lua_Safe_Call_Void();
entity_list.AESpell(self, center, spell_id, affect_caster);
}
void Lua_Mob::AreaSpell(Lua_Mob center, uint16 spell_id, bool affect_caster, int16 resist_adjust)
{
Lua_Safe_Call_Void();
entity_list.AESpell(self, center, spell_id, affect_caster, resist_adjust);
}
void Lua_Mob::AreaSpell(Lua_Mob center, uint16 spell_id, bool affect_caster, int16 resist_adjust, int max_targets)
{
Lua_Safe_Call_Void();
entity_list.AESpell(self, center, spell_id, affect_caster, resist_adjust, &max_targets);
}
void Lua_Mob::MassGroupBuff(Lua_Mob center, uint16 spell_id)
{
Lua_Safe_Call_Void();
entity_list.MassGroupBuff(self, center, spell_id);
}
void Lua_Mob::MassGroupBuff(Lua_Mob center, uint16 spell_id, bool affect_caster)
{
Lua_Safe_Call_Void();
entity_list.MassGroupBuff(self, center, spell_id, affect_caster);
}
luabind::scope lua_register_mob() {
return luabind::class_<Lua_Mob, Lua_Entity>("Mob")
.def(luabind::constructor<>())
@ -3393,6 +3459,15 @@ luabind::scope lua_register_mob() {
.def("ApplySpellBuff", (void(Lua_Mob::*)(int))&Lua_Mob::ApplySpellBuff)
.def("ApplySpellBuff", (void(Lua_Mob::*)(int,int))&Lua_Mob::ApplySpellBuff)
.def("ApplySpellBuff", (void(Lua_Mob::*)(int,int,int))&Lua_Mob::ApplySpellBuff)
.def("AreaAttack", (void(Lua_Mob::*)(float))&Lua_Mob::AreaAttack)
.def("AreaAttack", (void(Lua_Mob::*)(float, int16))&Lua_Mob::AreaAttack)
.def("AreaAttack", (void(Lua_Mob::*)(float, int16, int))&Lua_Mob::AreaAttack)
.def("AreaAttack", (void(Lua_Mob::*)(float, int16, int, bool))&Lua_Mob::AreaAttack)
.def("AreaAttack", (void(Lua_Mob::*)(float, int16, int, bool, int))&Lua_Mob::AreaAttack)
.def("AreaSpell", (void(Lua_Mob::*)(Lua_Mob, uint16))&Lua_Mob::AreaSpell)
.def("AreaSpell", (void(Lua_Mob::*)(Lua_Mob, uint16, bool))&Lua_Mob::AreaSpell)
.def("AreaSpell", (void(Lua_Mob::*)(Lua_Mob, uint16, bool, int16))&Lua_Mob::AreaSpell)
.def("AreaSpell", (void(Lua_Mob::*)(Lua_Mob, uint16, bool, int16, int))&Lua_Mob::AreaSpell)
.def("Attack", (bool(Lua_Mob::*)(Lua_Mob))&Lua_Mob::Attack)
.def("Attack", (bool(Lua_Mob::*)(Lua_Mob,int))&Lua_Mob::Attack)
.def("Attack", (bool(Lua_Mob::*)(Lua_Mob,int,bool))&Lua_Mob::Attack)
@ -3808,6 +3883,8 @@ luabind::scope lua_register_mob() {
.def("IsWarriorClass", &Lua_Mob::IsWarriorClass)
.def("IsWisdomCasterClass", &Lua_Mob::IsWisdomCasterClass)
.def("Kill", (void(Lua_Mob::*)(void))&Lua_Mob::Kill)
.def("MassGroupBuff", (void(Lua_Mob::*)(Lua_Mob, uint16))&Lua_Mob::MassGroupBuff)
.def("MassGroupBuff", (void(Lua_Mob::*)(Lua_Mob, uint16, bool))&Lua_Mob::MassGroupBuff)
.def("Mesmerize", (void(Lua_Mob::*)(void))&Lua_Mob::Mesmerize)
.def("Message", &Lua_Mob::Message)
.def("MessageString", &Lua_Mob::MessageString)

View File

@ -594,6 +594,17 @@ public:
int GetExtraHaste();
void SetExtraHaste(int haste);
void SetExtraHaste(int haste, bool need_to_save);
void AreaAttack(float distance);
void AreaAttack(float distance, int16 slot_id);
void AreaAttack(float distance, int16 slot_id, int count);
void AreaAttack(float distance, int16 slot_id, int count, bool is_from_spell);
void AreaAttack(float distance, int16 slot_id, int count, bool is_from_spell, int attack_rounds);
void AreaSpell(Lua_Mob center, uint16 spell_id);
void AreaSpell(Lua_Mob center, uint16 spell_id, bool affect_caster);
void AreaSpell(Lua_Mob center, uint16 spell_id, bool affect_caster, int16 resist_adjust);
void AreaSpell(Lua_Mob center, uint16 spell_id, bool affect_caster, int16 resist_adjust, int max_targets);
void MassGroupBuff(Lua_Mob center, uint16 spell_id);
void MassGroupBuff(Lua_Mob center, uint16 spell_id, bool affect_caster);
};
#endif

View File

@ -3187,6 +3187,21 @@ bool Perl_Client_AreTasksCompleted(Client* self, perl::array task_ids)
return self->AreTasksCompleted(v);
}
void Perl_Client_AreaTaunt(Client* self)
{
entity_list.AETaunt(self);
}
void Perl_Client_AreaTaunt(Client* self, float range)
{
entity_list.AETaunt(self, range);
}
void Perl_Client_AreaTaunt(Client* self, float range, int bonus_hate)
{
entity_list.AETaunt(self, range, bonus_hate);
}
void perl_register_client()
{
perl::interpreter perl(PERL_GET_THX);
@ -3237,6 +3252,9 @@ void perl_register_client()
package.add("ApplySpellRaid", (void(*)(Client*, int, int, int, bool, bool))&Perl_Client_ApplySpellRaid);
package.add("ApplySpellRaid", (void(*)(Client*, int, int, int, bool, bool, bool))&Perl_Client_ApplySpellRaid);
package.add("AreTasksCompleted", (bool(*)(Client*, perl::array))&Perl_Client_AreTasksCompleted);
package.add("AreaTaunt", (void(*)(Client*))&Perl_Client_AreaTaunt);
package.add("AreaTaunt", (void(*)(Client*, float))&Perl_Client_AreaTaunt);
package.add("AreaTaunt", (void(*)(Client*, float, int))&Perl_Client_AreaTaunt);
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);

View File

@ -669,11 +669,93 @@ perl::array Perl_EntityList_GetSpawnList(EntityList* self) {
return ret;
}
void Perl_EntityList_AreaAttack(EntityList* self, Mob* attacker, float distance)
{
self->AEAttack(attacker, distance);
}
void Perl_EntityList_AreaAttack(EntityList* self, Mob* attacker, float distance, int16 slot_id)
{
self->AEAttack(attacker, distance, slot_id);
}
void Perl_EntityList_AreaAttack(EntityList* self, Mob* attacker, float distance, int16 slot_id, int count)
{
self->AEAttack(attacker, distance, slot_id, count);
}
void Perl_EntityList_AreaAttack(EntityList* self, Mob* attacker, float distance, int16 slot_id, int count, bool is_from_spell)
{
self->AEAttack(attacker, distance, slot_id, count, is_from_spell);
}
void Perl_EntityList_AreaAttack(EntityList* self, Mob* attacker, float distance, int16 slot_id, int count, bool is_from_spell, int attack_rounds)
{
self->AEAttack(attacker, distance, slot_id, count, is_from_spell, attack_rounds);
}
void Perl_EntityList_AreaSpell(EntityList* self, Mob* caster, Mob* center, uint16 spell_id)
{
self->AESpell(caster, center, spell_id);
}
void Perl_EntityList_AreaSpell(EntityList* self, Mob* caster, Mob* center, uint16 spell_id, bool affect_caster)
{
self->AESpell(caster, center, spell_id, affect_caster);
}
void Perl_EntityList_AreaSpell(EntityList* self, Mob* caster, Mob* center, uint16 spell_id, bool affect_caster, int16 resist_adjust)
{
self->AESpell(caster, center, spell_id, affect_caster, resist_adjust);
}
void Perl_EntityList_AreaSpell(EntityList* self, Mob* caster, Mob* center, uint16 spell_id, bool affect_caster, int16 resist_adjust, int max_targets)
{
self->AESpell(caster, center, spell_id, affect_caster, resist_adjust, &max_targets);
}
void Perl_EntityList_AreaTaunt(EntityList* self, Client* caster)
{
self->AETaunt(caster);
}
void Perl_EntityList_AreaTaunt(EntityList* self, Client* caster, float range)
{
self->AETaunt(caster, range);
}
void Perl_EntityList_AreaTaunt(EntityList* self, Client* caster, float range, int bonus_hate)
{
self->AETaunt(caster, range, bonus_hate);
}
void Perl_EntityList_MassGroupBuff(EntityList* self, Mob* caster, Mob* center, uint16 spell_id)
{
self->MassGroupBuff(caster, center, spell_id);
}
void Perl_EntityList_MassGroupBuff(EntityList* self, Mob* caster, Mob* center, uint16 spell_id, bool affect_caster)
{
self->MassGroupBuff(caster, center, spell_id, affect_caster);
}
void perl_register_entitylist()
{
perl::interpreter perl(PERL_GET_THX);
auto package = perl.new_class<EntityList>("EntityList");
package.add("AreaAttack", (void(*)(EntityList*, Mob*, float))&Perl_EntityList_AreaAttack);
package.add("AreaAttack", (void(*)(EntityList*, Mob*, float, int16))&Perl_EntityList_AreaAttack);
package.add("AreaAttack", (void(*)(EntityList*, Mob*, float, int16, int))&Perl_EntityList_AreaAttack);
package.add("AreaAttack", (void(*)(EntityList*, Mob*, float, int16, int, bool))&Perl_EntityList_AreaAttack);
package.add("AreaAttack", (void(*)(EntityList*, Mob*, float, int16, int, bool, int))&Perl_EntityList_AreaAttack);
package.add("AreaSpell", (void(*)(EntityList*, Mob*, Mob*, uint16))&Perl_EntityList_AreaSpell);
package.add("AreaSpell", (void(*)(EntityList*, Mob*, Mob*, uint16, bool))&Perl_EntityList_AreaSpell);
package.add("AreaSpell", (void(*)(EntityList*, Mob*, Mob*, uint16, bool, int16))&Perl_EntityList_AreaSpell);
package.add("AreaSpell", (void(*)(EntityList*, Mob*, Mob*, uint16, bool, int16, int))&Perl_EntityList_AreaSpell);
package.add("AreaTaunt", (void(*)(EntityList*, Client*))&Perl_EntityList_AreaTaunt);
package.add("AreaTaunt", (void(*)(EntityList*, Client*, float))&Perl_EntityList_AreaTaunt);
package.add("AreaTaunt", (void(*)(EntityList*, Client*, float, int))&Perl_EntityList_AreaTaunt);
package.add("CanAddHateForMob", &Perl_EntityList_CanAddHateForMob);
package.add("Clear", &Perl_EntityList_Clear);
package.add("ClearClientPetitionQueue", &Perl_EntityList_ClearClientPetitionQueue);
@ -747,6 +829,8 @@ void perl_register_entitylist()
package.add("Marquee", (void(*)(EntityList*, uint32, std::string))&Perl_EntityList_Marquee);
package.add("Marquee", (void(*)(EntityList*, uint32, std::string, uint32))&Perl_EntityList_Marquee);
package.add("Marquee", (void(*)(EntityList*, uint32, uint32, uint32, uint32, uint32, std::string))&Perl_EntityList_Marquee);
package.add("MassGroupBuff", (void(*)(EntityList*, Mob*, Mob*, uint16))&Perl_EntityList_MassGroupBuff);
package.add("MassGroupBuff", (void(*)(EntityList*, Mob*, Mob*, uint16, bool))&Perl_EntityList_MassGroupBuff);
package.add("Message", &Perl_EntityList_Message);
package.add("MessageClose", &Perl_EntityList_MessageClose);
package.add("MessageGroup", &Perl_EntityList_MessageGroup);

View File

@ -3488,6 +3488,61 @@ std::string Perl_Mob_GetConsiderColor(Mob* self, uint8 other_level)
return EQ::constants::GetConsiderColorName(self->GetLevelCon(other_level));
}
void Perl_Mob_AreaAttack(Mob* self, float distance)
{
entity_list.AEAttack(self, distance);
}
void Perl_Mob_AreaAttack(Mob* self, float distance, int16 slot_id)
{
entity_list.AEAttack(self, distance, slot_id);
}
void Perl_Mob_AreaAttack(Mob* self, float distance, int16 slot_id, int count)
{
entity_list.AEAttack(self, distance, slot_id, count);
}
void Perl_Mob_AreaAttack(Mob* self, float distance, int16 slot_id, int count, bool is_from_spell)
{
entity_list.AEAttack(self, distance, slot_id, count, is_from_spell);
}
void Perl_Mob_AreaAttack(Mob* self, float distance, int16 slot_id, int count, bool is_from_spell, int attack_rounds)
{
entity_list.AEAttack(self, distance, slot_id, count, is_from_spell, attack_rounds);
}
void Perl_Mob_AreaSpell(Mob* self, Mob* center, uint16 spell_id)
{
entity_list.AESpell(self, center, spell_id, true, 0, nullptr, true);
}
void Perl_Mob_AreaSpell(Mob* self, Mob* center, uint16 spell_id, bool affect_caster)
{
entity_list.AESpell(self, center, spell_id, affect_caster, 0, nullptr, true);
}
void Perl_Mob_AreaSpell(Mob* self, Mob* center, uint16 spell_id, bool affect_caster, int16 resist_adjust)
{
entity_list.AESpell(self, center, spell_id, affect_caster, resist_adjust, nullptr, true);
}
void Perl_Mob_AreaSpell(Mob* self, Mob* center, uint16 spell_id, bool affect_caster, int16 resist_adjust, int max_targets)
{
entity_list.AESpell(self, center, spell_id, affect_caster, resist_adjust, &max_targets, true);
}
void Perl_Mob_MassGroupBuff(Mob* self, Mob* center, uint16 spell_id)
{
entity_list.MassGroupBuff(self, center, spell_id);
}
void Perl_Mob_MassGroupBuff(Mob* self, Mob* center, uint16 spell_id, bool affect_caster)
{
entity_list.MassGroupBuff(self, center, spell_id, affect_caster);
}
void perl_register_mob()
{
perl::interpreter perl(PERL_GET_THX);
@ -3504,6 +3559,15 @@ void perl_register_mob()
package.add("ApplySpellBuff", (void(*)(Mob*, int))&Perl_Mob_ApplySpellBuff);
package.add("ApplySpellBuff", (void(*)(Mob*, int, int))&Perl_Mob_ApplySpellBuff);
package.add("ApplySpellBuff", (void(*)(Mob*, int, int, int))&Perl_Mob_ApplySpellBuff);
package.add("AreaAttack", (void(*)(Mob*, float))&Perl_Mob_AreaAttack);
package.add("AreaAttack", (void(*)(Mob*, float, int16))&Perl_Mob_AreaAttack);
package.add("AreaAttack", (void(*)(Mob*, float, int16, int))&Perl_Mob_AreaAttack);
package.add("AreaAttack", (void(*)(Mob*, float, int16, int, bool))&Perl_Mob_AreaAttack);
package.add("AreaAttack", (void(*)(Mob*, float, int16, int, bool, int))&Perl_Mob_AreaAttack);
package.add("AreaSpell", (void(*)(Mob*, Mob*, uint16))&Perl_Mob_AreaSpell);
package.add("AreaSpell", (void(*)(Mob*, Mob*, uint16, bool))&Perl_Mob_AreaSpell);
package.add("AreaSpell", (void(*)(Mob*, Mob*, uint16, bool, int16))&Perl_Mob_AreaSpell);
package.add("AreaSpell", (void(*)(Mob*, Mob*, uint16, bool, int16, int))&Perl_Mob_AreaSpell);
package.add("Attack", (bool(*)(Mob*, Mob*))&Perl_Mob_Attack);
package.add("Attack", (bool(*)(Mob*, Mob*, int))&Perl_Mob_Attack);
package.add("Attack", (bool(*)(Mob*, Mob*, int, bool))&Perl_Mob_Attack);
@ -3928,6 +3992,8 @@ void perl_register_mob()
package.add("MakeTempPet", (void(*)(Mob*, uint16, const char*, uint32))&Perl_Mob_MakeTempPet);
package.add("MakeTempPet", (void(*)(Mob*, uint16, const char*, uint32, Mob*))&Perl_Mob_MakeTempPet);
package.add("MakeTempPet", (void(*)(Mob*, uint16, const char*, uint32, Mob*, bool))&Perl_Mob_MakeTempPet);
package.add("MassGroupBuff", (void(*)(Mob*, Mob*, uint16))&Perl_Mob_MassGroupBuff);
package.add("MassGroupBuff", (void(*)(Mob*, Mob*, uint16, bool))&Perl_Mob_MassGroupBuff);
package.add("Mesmerize", &Perl_Mob_Mesmerize);
package.add("Message", &Perl_Mob_Message);
package.add("Message_StringID", (void(*)(Mob*, uint32, uint32))&Perl_Mob_Message_StringID);

View File

@ -886,13 +886,13 @@ bool Mob::DoCastingChecksOnTarget(bool check_on_casting, int32 spell_id, Mob *sp
*/
if (!ignore_on_casting) {
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 && !spell_target->IsClient() && !spell_target->IsMerc() && !spell_target->IsBot()) {
if (spells[spell_id].pcnpc_only_flag == PCNPCOnlyFlagType::PC && !spell_target->IsClient() && !spell_target->IsMerc() && !spell_target->IsBot()) {
if (check_on_casting) {
Message(Chat::SpellFailure, "This spell only works on other PCs");
}
return false;
}
else if (spells[spell_id].pcnpc_only_flag == 2 && (spell_target->IsClient() || spell_target->IsMerc() || spell_target->IsBot())) {
else if (spells[spell_id].pcnpc_only_flag == PCNPCOnlyFlagType::NPC && (spell_target->IsClient() || spell_target->IsMerc() || spell_target->IsBot())) {
if (check_on_casting) {
Message(Chat::SpellFailure, "This spell only works on NPCs.");
}
@ -3947,12 +3947,12 @@ bool Mob::SpellOnTarget(
spells[spell_id].target_type != ST_HateList
) {
if (
spells[spell_id].pcnpc_only_flag == 1 &&
spells[spell_id].pcnpc_only_flag == PCNPCOnlyFlagType::PC &&
!spelltar->IsOfClientBotMerc()
) {
return false;
} else if (
spells[spell_id].pcnpc_only_flag == 2 &&
spells[spell_id].pcnpc_only_flag == PCNPCOnlyFlagType::NPC &&
(
spelltar->IsOfClientBotMerc()
)