Added direct inventory access, and event_loot for items and event_weapon_proc for items

This commit is contained in:
KimLS 2013-06-20 14:03:22 -07:00
parent d8a1d84a49
commit 7b894a7c61
21 changed files with 483 additions and 88 deletions

View File

@ -250,7 +250,7 @@ void ClientListEntry::Camp(ZoneServer* iZS) {
bool ClientListEntry::CheckStale() {
stale++;
if (stale >= 3) {
if (stale > 20) {
if (pOnline > CLE_Status_Offline)
SetOnline(CLE_Status_Offline);
else
@ -260,7 +260,6 @@ bool ClientListEntry::CheckStale() {
}
bool ClientListEntry::CheckAuth(uint32 iLSID, const char* iKey) {
// if (LSID() == iLSID && strncmp(plskey, iKey,10) == 0) {
if (strncmp(plskey, iKey,10) == 0) {
if (paccountid == 0 && LSID()>0) {
int16 tmpStatus = WorldConfig::get()->DefaultStatus;

View File

@ -40,6 +40,7 @@ SET(zone_sources
lua_general.cpp
lua_group.cpp
lua_hate_list.cpp
lua_inventory.cpp
lua_item.cpp
lua_iteminst.cpp
lua_mob.cpp
@ -147,6 +148,7 @@ SET(zone_headers
lua_general.h
lua_group.h
lua_hate_list.h
lua_inventory.h
lua_item.h
lua_iteminst.h
lua_mob.h

View File

@ -1953,8 +1953,8 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
if (!GetTarget())
return true; //We killed them
if( !bRiposte && other->GetHP() > 0 ) {
TryWeaponProc(weapon, other, Hand); //no weapon
if(!bRiposte && other->GetHP() > 0 ) {
TryWeaponProc(nullptr, weapon, other, Hand); //no weapon
}
TriggerDefensiveProcs(nullptr, other, Hand, damage);
@ -3780,7 +3780,7 @@ void Mob::TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand, int dam
if (DefensiveProcs[i].spellID != SPELL_UNKNOWN) {
int chance = ProcChance * (DefensiveProcs[i].chance);
if ((MakeRandomInt(0, 100) < chance)) {
ExecWeaponProc(DefensiveProcs[i].spellID, on);
ExecWeaponProc(nullptr, DefensiveProcs[i].spellID, on);
CheckHitsRemaining(0, false, false, 0, DefensiveProcs[i].base_spellID);
}
}
@ -3812,17 +3812,17 @@ void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) {
}
if(!weapon_g) {
TryWeaponProc((const Item_Struct*) nullptr, on, hand);
TryWeaponProc(nullptr, (const Item_Struct*)nullptr, on, hand);
return;
}
if(!weapon_g->IsType(ItemClassCommon)) {
TryWeaponProc((const Item_Struct*) nullptr, on, hand);
TryWeaponProc(nullptr, (const Item_Struct*) nullptr, on, hand);
return;
}
//do main procs
TryWeaponProc(weapon_g->GetItem(), on, hand);
TryWeaponProc(weapon_g, weapon_g->GetItem(), on, hand);
//we have to calculate these again, oh well
@ -3855,14 +3855,14 @@ void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) {
Message_StringID(13,PROC_TOOLOW);
}
} else {
ExecWeaponProc(aug->Proc.Effect, on);
ExecWeaponProc(aug_i, aug->Proc.Effect, on);
}
}
}
}
}
void Mob::TryWeaponProc(const Item_Struct* weapon, Mob *on, uint16 hand) {
void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct* weapon, Mob *on, uint16 hand) {
_ZP(Mob_TryWeaponProcB);
uint16 skillinuse = 28;
int ourlevel = GetLevel();
@ -3891,7 +3891,7 @@ void Mob::TryWeaponProc(const Item_Struct* weapon, Mob *on, uint16 hand) {
}
} else {
mlog(COMBAT__PROCS, "Attacking weapon (%s) successfully procing spell %d (%.2f percent chance)", weapon->Name, weapon->Proc.Effect, ProcChance*100);
ExecWeaponProc(weapon->Proc.Effect, on);
ExecWeaponProc(inst, weapon->Proc.Effect, on);
}
} else {
mlog(COMBAT__PROCS, "Attacking weapon (%s) did no proc (%.2f percent chance).", weapon->Name, ProcChance*100);
@ -3928,7 +3928,7 @@ void Mob::TryWeaponProc(const Item_Struct* weapon, Mob *on, uint16 hand) {
if (PermaProcs[i].spellID != SPELL_UNKNOWN) {
if(MakeRandomInt(0, 100) < PermaProcs[i].chance) {
mlog(COMBAT__PROCS, "Permanent proc %d procing spell %d (%d percent chance)", i, PermaProcs[i].spellID, PermaProcs[i].chance);
ExecWeaponProc(PermaProcs[i].spellID, on);
ExecWeaponProc(nullptr, PermaProcs[i].spellID, on);
} else {
mlog(COMBAT__PROCS, "Permanent proc %d failed to proc %d (%d percent chance)", i, PermaProcs[i].spellID, PermaProcs[i].chance);
}
@ -3945,7 +3945,7 @@ void Mob::TryWeaponProc(const Item_Struct* weapon, Mob *on, uint16 hand) {
int chance = ProcChance * (SpellProcs[i].chance);
if(MakeRandomInt(0, 100) < chance) {
mlog(COMBAT__PROCS, "Spell proc %d procing spell %d (%d percent chance)", i, SpellProcs[i].spellID, chance);
ExecWeaponProc(SpellProcs[i].spellID, on);
ExecWeaponProc(nullptr, SpellProcs[i].spellID, on);
} else {
mlog(COMBAT__PROCS, "Spell proc %d failed to proc %d (%d percent chance)", i, SpellProcs[i].spellID, chance);
}
@ -3955,7 +3955,7 @@ void Mob::TryWeaponProc(const Item_Struct* weapon, Mob *on, uint16 hand) {
int chance = ProcChance * RangedProcs[i].chance;
if(MakeRandomInt(0, 100) < chance) {
mlog(COMBAT__PROCS, "Ranged proc %d procing spell %d", i, RangedProcs[i].spellID, RangedProcs[i].chance);
ExecWeaponProc(RangedProcs[i].spellID, on);
ExecWeaponProc(nullptr, RangedProcs[i].spellID, on);
CheckHitsRemaining(0, false, false, 0, RangedProcs[i].base_spellID);
} else {
mlog(COMBAT__PROCS, "Ranged proc %d failed to proc %d", i, RangedProcs[i].spellID, RangedProcs[i].chance);
@ -4295,7 +4295,7 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, float chance)
if (PassLimitToSkill(SkillProcs[i].base_spellID,skill)){
int ProcChance = chance * (float)SkillProcs[i].chance;
if ((MakeRandomInt(0, 100) < ProcChance)) {
ExecWeaponProc(SkillProcs[i].spellID, on);
ExecWeaponProc(nullptr, SkillProcs[i].spellID, on);
CheckHitsRemaining(0, false, false, 0, SkillProcs[i].base_spellID);
}
}

View File

@ -9896,8 +9896,8 @@ bool Bot::SpellEffect(Mob* caster, uint16 spell_id, float partial) {
return Result;
}
void Bot::DoBuffTic(uint16 spell_id, uint32 ticsremaining, uint8 caster_level, Mob* caster) {
Mob::DoBuffTic(spell_id, ticsremaining, caster_level, caster);
void Bot::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caster_level, Mob* caster) {
Mob::DoBuffTic(spell_id, slot, ticsremaining, caster_level, caster);
}
bool Bot::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot, int32 cast_time, int32 mana_cost, uint32* oSpellWillFinish, uint32 item_slot, int16 *resist_adjust) {

View File

@ -312,7 +312,7 @@ public:
virtual int32 GetActSpellDuration(uint16 spell_id, int32 duration);
virtual float GetAOERange(uint16 spell_id);
virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100);
virtual void DoBuffTic(uint16 spell_id, uint32 ticsremaining, uint8 caster_level, Mob* caster = 0);
virtual void DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caster_level, Mob* caster = 0);
virtual bool CastSpell(uint16 spell_id, uint16 target_id, uint16 slot = 10, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, int16 *resist_adjust = nullptr);
virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar);
virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster);

View File

@ -1218,7 +1218,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app)
if(proximity_timer.Check()) {
entity_list.ProcessMove(this, ppu->x_pos, ppu->y_pos, ppu->z_pos);
if(RuleB(TaskSystem, EnableTaskSystem) && RuleB(TaskSystem,EnableTaskProximity))
if(RuleB(TaskSystem, EnableTaskSystem) && RuleB(TaskSystem,EnableTaskProximity))
ProcessTaskProximities(ppu->x_pos, ppu->y_pos, ppu->z_pos);
proximity_x = ppu->x_pos;
proximity_y = ppu->y_pos;

View File

@ -1171,6 +1171,7 @@ void Corpse::LootItem(Client* client, const EQApplicationPacket* app)
args.push_back(inst);
args.push_back(this);
parse->EventPlayer(EVENT_LOOT, client, buf, 0, &args);
parse->EventItem(EVENT_LOOT, client, inst, this, buf, 0);
if ((RuleB(Character, EnableDiscoveredItems)))
{

View File

@ -100,7 +100,8 @@ const char *QuestEventSubroutines[_LargestEventID] = {
"EVENT_SAY",
"EVENT_DROP_ITEM",
"EVENT_DESTROY_ITEM",
"EVENT_FEIGN_DEATH"
"EVENT_FEIGN_DEATH",
"EVENT_WEAPON_PROC"
};
PerlembParser::PerlembParser() : perl(nullptr), event_queue_in_use_(false) {

View File

@ -69,6 +69,7 @@ typedef enum {
EVENT_DROP_ITEM,
EVENT_DESTROY_ITEM,
EVENT_FEIGN_DEATH,
EVENT_WEAPON_PROC,
_LargestEventID
} QuestEventID;

View File

@ -8,6 +8,7 @@
#include "lua_npc.h"
#include "lua_item.h"
#include "lua_iteminst.h"
#include "lua_inventory.h"
#include "lua_group.h"
#include "lua_raid.h"
@ -880,11 +881,6 @@ int Lua_Client::GetLDoNLossesTheme(int theme) {
return self->GetLDoNLossesTheme(theme);
}
Lua_ItemInst Lua_Client::GetItemAt(int slot) {
Lua_Safe_Call_Class(Lua_ItemInst);
return Lua_ItemInst(self->GetInv().GetItem(slot));
}
int Lua_Client::GetStartZone() {
Lua_Safe_Call_Int();
return self->GetStartZone();
@ -1152,12 +1148,12 @@ std::string Lua_Client::GetAccountFlag(std::string flag) {
Lua_Group Lua_Client::GetGroup() {
Lua_Safe_Call_Class(Lua_Group);
return Lua_Group(self->GetGroup());
return self->GetGroup();
}
Lua_Raid Lua_Client::GetRaid() {
Lua_Safe_Call_Class(Lua_Raid);
return Lua_Raid(self->GetRaid());
return self->GetRaid();
}
bool Lua_Client::PutItemInInventory(int slot_id, Lua_ItemInst inst) {
@ -1172,6 +1168,11 @@ bool Lua_Client::PushItemOnCursor(Lua_ItemInst inst) {
return self->PushItemOnCursor(*rinst, true);
}
Lua_Inventory Lua_Client::GetInventory() {
Lua_Safe_Call_Class(Lua_Inventory);
return &self->GetInv();
}
luabind::scope lua_register_client() {
return luabind::class_<Lua_Client, Lua_Mob>("Client")
.def(luabind::constructor<>())
@ -1348,7 +1349,6 @@ luabind::scope lua_register_client() {
.def("GetLDoNLosses", (int(Lua_Client::*)(void))&Lua_Client::GetLDoNLosses)
.def("GetLDoNWinsTheme", (int(Lua_Client::*)(int))&Lua_Client::GetLDoNWinsTheme)
.def("GetLDoNLossesTheme", (int(Lua_Client::*)(int))&Lua_Client::GetLDoNLossesTheme)
.def("GetItemAt", (Lua_ItemInst(Lua_Client::*)(int))&Lua_Client::GetItemAt)
.def("GetStartZone", (int(Lua_Client::*)(void))&Lua_Client::GetStartZone)
.def("SetStartZone", (void(Lua_Client::*)(int))&Lua_Client::SetStartZone)
.def("SetStartZone", (void(Lua_Client::*)(int,float))&Lua_Client::SetStartZone)
@ -1405,7 +1405,8 @@ luabind::scope lua_register_client() {
.def("GetGroup", (Lua_Group(Lua_Client::*)(void))&Lua_Client::GetGroup)
.def("GetRaid", (Lua_Raid(Lua_Client::*)(void))&Lua_Client::GetRaid)
.def("PutItemInInventory", (bool(Lua_Client::*)(int,Lua_ItemInst))&Lua_Client::PutItemInInventory)
.def("PushItemOnCursor", (bool(Lua_Client::*)(Lua_ItemInst))&Lua_Client::PushItemOnCursor);
.def("PushItemOnCursor", (bool(Lua_Client::*)(Lua_ItemInst))&Lua_Client::PushItemOnCursor)
.def("GetInventory", (Lua_Inventory(Lua_Client::*)(void))&Lua_Client::GetInventory);
}
luabind::scope lua_register_inventory_where() {

View File

@ -7,6 +7,7 @@
class Client;
class Lua_Group;
class Lua_Raid;
class Lua_Inventory;
namespace luabind {
struct scope;
@ -202,7 +203,6 @@ public:
int GetLDoNLosses();
int GetLDoNWinsTheme(int theme);
int GetLDoNLossesTheme(int theme);
Lua_ItemInst GetItemAt(int slot);
int GetStartZone();
void SetStartZone(int zone_id);
void SetStartZone(int zone_id, float x);
@ -260,6 +260,7 @@ public:
Lua_Raid GetRaid();
bool PutItemInInventory(int slot_id, Lua_ItemInst inst);
bool PushItemOnCursor(Lua_ItemInst inst);
Lua_Inventory GetInventory();
};
#endif

View File

@ -965,6 +965,7 @@ luabind::scope lua_register_events() {
luabind::value("popup_response", static_cast<int>(EVENT_POPUP_RESPONSE)),
luabind::value("proximity_say", static_cast<int>(EVENT_PROXIMITY_SAY)),
luabind::value("cast", static_cast<int>(EVENT_CAST)),
luabind::value("cast_begin", static_cast<int>(EVENT_CAST_BEGIN)),
luabind::value("scale_calc", static_cast<int>(EVENT_SCALE_CALC)),
luabind::value("item_enter_zone", static_cast<int>(EVENT_ITEM_ENTER_ZONE)),
luabind::value("target_change", static_cast<int>(EVENT_TARGET_CHANGE)),
@ -992,7 +993,11 @@ luabind::scope lua_register_events() {
luabind::value("duel_lose", static_cast<int>(EVENT_DUEL_LOSE)),
luabind::value("encounter_load", static_cast<int>(EVENT_ENCOUNTER_LOAD)),
luabind::value("encounter_unload", static_cast<int>(EVENT_ENCOUNTER_UNLOAD)),
luabind::value("command", static_cast<int>(EVENT_COMMAND))
luabind::value("command", static_cast<int>(EVENT_COMMAND)),
luabind::value("drop_item", static_cast<int>(EVENT_DROP_ITEM)),
luabind::value("destroy_item", static_cast<int>(EVENT_DESTROY_ITEM)),
luabind::value("feign_death", static_cast<int>(EVENT_FEIGN_DEATH)),
luabind::value("weapon_proc", static_cast<int>(EVENT_WEAPON_PROC))
];
}

195
zone/lua_inventory.cpp Normal file
View File

@ -0,0 +1,195 @@
#ifdef LUA_EQEMU
#include "lua.hpp"
#include <luabind/luabind.hpp>
#include "masterentity.h"
#include "lua_inventory.h"
#include "lua_iteminst.h"
#include "lua_item.h"
Lua_ItemInst Lua_Inventory::GetItem(int slot_id) {
Lua_Safe_Call_Class(Lua_ItemInst);
return self->GetItem(slot_id);
}
Lua_ItemInst Lua_Inventory::GetItem(int slot_id, int bag_slot) {
Lua_Safe_Call_Class(Lua_ItemInst);
return self->GetItem(slot_id, bag_slot);
}
int Lua_Inventory::PutItem(int slot_id, Lua_ItemInst item) {
Lua_Safe_Call_Int();
ItemInst *inst = item;
if(!inst) {
return 0;
}
return self->PutItem(slot_id, *inst);
}
int Lua_Inventory::PushCursor(Lua_ItemInst item) {
Lua_Safe_Call_Int();
ItemInst *inst = item;
if(!inst) {
return 0;
}
return self->PushCursor(*inst);
}
bool Lua_Inventory::SwapItem(int slot_a, int slot_b) {
Lua_Safe_Call_Bool();
return self->SwapItem(slot_a, slot_b);
}
bool Lua_Inventory::DeleteItem(int slot_id) {
Lua_Safe_Call_Bool();
return self->DeleteItem(slot_id);
}
bool Lua_Inventory::DeleteItem(int slot_id, int quantity) {
Lua_Safe_Call_Bool();
return self->DeleteItem(slot_id, quantity);
}
bool Lua_Inventory::CheckNoDrop(int slot_id) {
Lua_Safe_Call_Bool();
return self->CheckNoDrop(slot_id);
}
Lua_ItemInst Lua_Inventory::PopItem(int slot_id) {
Lua_Safe_Call_Class(Lua_ItemInst);
return Lua_ItemInst(self->PopItem(slot_id), true);
}
int Lua_Inventory::HasItem(int item_id) {
Lua_Safe_Call_Int();
return self->HasItem(item_id);
}
int Lua_Inventory::HasItem(int item_id, int quantity) {
Lua_Safe_Call_Int();
return self->HasItem(item_id, quantity);
}
int Lua_Inventory::HasItem(int item_id, int quantity, int where) {
Lua_Safe_Call_Int();
return self->HasItem(item_id, quantity, where);
}
bool Lua_Inventory::HasSpaceForItem(Lua_Item item, int quantity) {
Lua_Safe_Call_Bool();
return self->HasSpaceForItem(item, quantity);
}
int Lua_Inventory::HasItemByUse(int use) {
Lua_Safe_Call_Int();
return self->HasItemByUse(use);
}
int Lua_Inventory::HasItemByUse(int use, uint8 quantity) {
Lua_Safe_Call_Int();
return self->HasItemByUse(use, quantity);
}
int Lua_Inventory::HasItemByUse(int use, uint8 quantity, uint8 where) {
Lua_Safe_Call_Int();
return self->HasItemByUse(use, quantity, where);
}
int Lua_Inventory::HasItemByLoreGroup(uint32 loregroup) {
Lua_Safe_Call_Int();
return self->HasItemByLoreGroup(loregroup);
}
int Lua_Inventory::HasItemByLoreGroup(uint32 loregroup, int where) {
Lua_Safe_Call_Int();
return self->HasItemByLoreGroup(loregroup, where);
}
int Lua_Inventory::FindFreeSlot(bool for_bag, bool try_cursor) {
Lua_Safe_Call_Int();
return self->FindFreeSlot(for_bag, try_cursor);
}
int Lua_Inventory::FindFreeSlot(bool for_bag, bool try_cursor, int min_size) {
Lua_Safe_Call_Int();
return self->FindFreeSlot(for_bag, try_cursor, min_size);
}
int Lua_Inventory::FindFreeSlot(bool for_bag, bool try_cursor, int min_size, bool is_arrow) {
Lua_Safe_Call_Int();
return self->FindFreeSlot(for_bag, try_cursor, min_size, is_arrow);
}
int Lua_Inventory::CalcSlotId(int slot_id) {
Lua_Safe_Call_Int();
return self->CalcSlotId(slot_id);
}
int Lua_Inventory::CalcSlotId(int slot_id, int bag_slot) {
Lua_Safe_Call_Int();
return self->CalcSlotId(slot_id, bag_slot);
}
int Lua_Inventory::CalcBagIdx(int slot_id) {
Lua_Safe_Call_Int();
return self->CalcBagIdx(slot_id);
}
int Lua_Inventory::CalcSlotFromMaterial(int material) {
Lua_Safe_Call_Int();
return self->CalcSlotFromMaterial(material);
}
int Lua_Inventory::CalcMaterialFromSlot(int equipslot) {
Lua_Safe_Call_Int();
return self->CalcMaterialFromSlot(equipslot);
}
bool Lua_Inventory::CanItemFitInContainer(Lua_Item item, Lua_Item container) {
Lua_Safe_Call_Bool();
return self->CanItemFitInContainer(item, container);
}
bool Lua_Inventory::SupportsContainers(int slot_id) {
Lua_Safe_Call_Bool();
return self->SupportsContainers(slot_id);
}
luabind::scope lua_register_inventory() {
return luabind::class_<Lua_Inventory>("Inventory")
.def(luabind::constructor<>())
.def("GetItem", (Lua_ItemInst(Lua_Inventory::*)(int))&Lua_Inventory::GetItem)
.def("GetItem", (Lua_ItemInst(Lua_Inventory::*)(int,int))&Lua_Inventory::GetItem)
.def("PutItem", (int(Lua_Inventory::*)(int,Lua_ItemInst))&Lua_Inventory::PutItem)
.def("PushCursor", (int(Lua_Inventory::*)(Lua_ItemInst))&Lua_Inventory::PushCursor)
.def("SwapItem", (bool(Lua_Inventory::*)(int,int))&Lua_Inventory::SwapItem)
.def("DeleteItem", (bool(Lua_Inventory::*)(int))&Lua_Inventory::DeleteItem)
.def("DeleteItem", (bool(Lua_Inventory::*)(int,int))&Lua_Inventory::DeleteItem)
.def("CheckNoDrop", (bool(Lua_Inventory::*)(int))&Lua_Inventory::CheckNoDrop)
.def("PopItem", (Lua_ItemInst(Lua_Inventory::*)(int))&Lua_Inventory::PopItem)
.def("HasItem", (int(Lua_Inventory::*)(int))&Lua_Inventory::HasItem)
.def("HasItem", (int(Lua_Inventory::*)(int,int))&Lua_Inventory::HasItem)
.def("HasItem", (int(Lua_Inventory::*)(int,int,int))&Lua_Inventory::HasItem)
.def("HasSpaceForItem", (bool(Lua_Inventory::*)(Lua_Item,int))&Lua_Inventory::HasSpaceForItem)
.def("HasItemByUse", (int(Lua_Inventory::*)(int))&Lua_Inventory::HasItemByUse)
.def("HasItemByUse", (int(Lua_Inventory::*)(int,uint8))&Lua_Inventory::HasItemByUse)
.def("HasItemByUse", (int(Lua_Inventory::*)(int,uint8,uint8))&Lua_Inventory::HasItemByUse)
.def("HasItemByLoreGroup", (int(Lua_Inventory::*)(uint32))&Lua_Inventory::HasItemByLoreGroup)
.def("HasItemByLoreGroup", (int(Lua_Inventory::*)(uint32,int))&Lua_Inventory::HasItemByLoreGroup)
.def("FindFreeSlot", (int(Lua_Inventory::*)(bool,bool))&Lua_Inventory::FindFreeSlot)
.def("FindFreeSlot", (int(Lua_Inventory::*)(bool,bool,int))&Lua_Inventory::FindFreeSlot)
.def("FindFreeSlot", (int(Lua_Inventory::*)(bool,bool,int,bool))&Lua_Inventory::FindFreeSlot)
.def("CalcSlotId", (int(Lua_Inventory::*)(int))&Lua_Inventory::CalcSlotId)
.def("CalcSlotId", (int(Lua_Inventory::*)(int,int))&Lua_Inventory::CalcSlotId)
.def("CalcBagIdx", (int(Lua_Inventory::*)(int))&Lua_Inventory::CalcBagIdx)
.def("CalcSlotFromMaterial", (int(Lua_Inventory::*)(int))&Lua_Inventory::CalcSlotFromMaterial)
.def("CalcMaterialFromSlot", (int(Lua_Inventory::*)(int))&Lua_Inventory::CalcMaterialFromSlot)
.def("CanItemFitInContainer", (bool(Lua_Inventory::*)(Lua_Item,Lua_Item))&Lua_Inventory::CanItemFitInContainer)
.def("SupportsContainers", (bool(Lua_Inventory::*)(int))&Lua_Inventory::SupportsContainers);
}
#endif

60
zone/lua_inventory.h Normal file
View File

@ -0,0 +1,60 @@
#ifndef EQEMU_LUA_INVENTORY_H
#define EQEMU_LUA_INVENTORY_H
#ifdef LUA_EQEMU
#include "lua_ptr.h"
class Inventory;
class Lua_ItemInst;
class Lua_Item;
namespace luabind {
struct scope;
}
luabind::scope lua_register_inventory();
class Lua_Inventory : public Lua_Ptr<void>
{
typedef Inventory NativeType;
public:
Lua_Inventory() : Lua_Ptr(nullptr) { }
Lua_Inventory(Inventory *d) : Lua_Ptr(d) { }
virtual ~Lua_Inventory() { }
operator Inventory*() {
return reinterpret_cast<Inventory*>(GetLuaPtrData());
}
Lua_ItemInst GetItem(int slot_id);
Lua_ItemInst GetItem(int slot_id, int bag_slot);
int PutItem(int slot_id, Lua_ItemInst item);
int PushCursor(Lua_ItemInst item);
bool SwapItem(int slot_a, int slot_b);
bool DeleteItem(int slot_id);
bool DeleteItem(int slot_id, int quantity);
bool CheckNoDrop(int slot_id);
Lua_ItemInst PopItem(int slot_id);
int HasItem(int item_id);
int HasItem(int item_id, int quantity);
int HasItem(int item_id, int quantity, int where);
bool HasSpaceForItem(Lua_Item item, int quantity);
int HasItemByUse(int use);
int HasItemByUse(int use, uint8 quantity);
int HasItemByUse(int use, uint8 quantity, uint8 where);
int HasItemByLoreGroup(uint32 loregroup);
int HasItemByLoreGroup(uint32 loregroup, int where);
int FindFreeSlot(bool for_bag, bool try_cursor);
int FindFreeSlot(bool for_bag, bool try_cursor, int min_size);
int FindFreeSlot(bool for_bag, bool try_cursor, int min_size, bool is_arrow);
int CalcSlotId(int slot_id);
int CalcSlotId(int slot_id, int bag_slot);
int CalcBagIdx(int slot_id);
int CalcSlotFromMaterial(int material);
int CalcMaterialFromSlot(int equipslot);
bool CanItemFitInContainer(Lua_Item item, Lua_Item container);
bool SupportsContainers(int slot_id);
};
#endif
#endif

View File

@ -18,6 +18,7 @@
#include "lua_mob.h"
#include "lua_hate_list.h"
#include "lua_client.h"
#include "lua_inventory.h"
#include "lua_npc.h"
#include "lua_spell.h"
#include "lua_entity_list.h"
@ -98,7 +99,8 @@ const char *LuaEvents[_LargestEventID] = {
"event_command",
"event_drop_item",
"event_destroy_item",
"event_feign_death"
"event_feign_death",
"event_weapon_proc"
};
extern Zone *zone;
@ -172,10 +174,13 @@ LuaParser::LuaParser() {
ItemArgumentDispatch[EVENT_ITEM_CLICK] = handle_item_click;
ItemArgumentDispatch[EVENT_ITEM_CLICK_CAST] = handle_item_click;
ItemArgumentDispatch[EVENT_TIMER] = handle_item_timer;
ItemArgumentDispatch[EVENT_WEAPON_PROC] = handle_item_proc;
ItemArgumentDispatch[EVENT_LOOT] = handle_item_loot;
SpellArgumentDispatch[EVENT_SPELL_EFFECT_CLIENT] = handle_spell_effect;
SpellArgumentDispatch[EVENT_SPELL_BUFF_TIC_CLIENT] = handle_spell_effect;
SpellArgumentDispatch[EVENT_SPELL_BUFF_TIC_CLIENT] = handle_spell_tic;
SpellArgumentDispatch[EVENT_SPELL_FADE] = handle_spell_fade;
SpellArgumentDispatch[EVENT_SPELL_EFFECT_TRANSLOCATE_COMPLETE] = handle_translocate_finish;
L = nullptr;
}
@ -424,7 +429,7 @@ int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *cl
//redo this arg function
auto arg_function = ItemArgumentDispatch[evt];
arg_function(this, L, client, item, data, extra_data, extra_pointers);
arg_function(this, L, client, item, mob, data, extra_data, extra_pointers);
quest_manager.StartQuest(client, client, item);
if(lua_pcall(L, 1, 1, 0)) {
@ -867,6 +872,7 @@ void LuaParser::MapFunctions(lua_State *L) {
lua_register_mob(),
lua_register_npc(),
lua_register_client(),
lua_register_inventory(),
lua_register_inventory_where(),
lua_register_iteminst(),
lua_register_item(),

View File

@ -445,19 +445,55 @@ void handle_player_null(QuestInterface *parse, lua_State* L, Client* client, std
}
//Item
void handle_item_click(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, std::string data, uint32 extra_data,
void handle_item_click(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
lua_pushinteger(L, extra_data);
lua_setfield(L, -2, "slot_id");
}
void handle_item_timer(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, std::string data, uint32 extra_data,
void handle_item_timer(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
lua_pushstring(L, data.c_str());
lua_setfield(L, -2, "timer");
}
void handle_item_null(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, std::string data, uint32 extra_data,
void handle_item_proc(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
Lua_Mob l_mob(mob);
luabind::object l_mob_o = luabind::object(L, l_mob);
l_mob_o.push(L);
lua_setfield(L, -2, "target");
if(IsValidSpell(extra_data)) {
Lua_Spell l_spell(&spells[extra_data]);
luabind::object l_spell_o = luabind::object(L, l_spell);
l_spell_o.push(L);
lua_setfield(L, -2, "spell");
} else {
Lua_Spell l_spell(nullptr);
luabind::object l_spell_o = luabind::object(L, l_spell);
l_spell_o.push(L);
lua_setfield(L, -2, "spell");
}
}
void handle_item_loot(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
if(mob && mob->IsCorpse()) {
Lua_Corpse l_corpse(mob->CastToCorpse());
luabind::object l_corpse_o = luabind::object(L, l_corpse);
l_corpse_o.push(L);
lua_setfield(L, -2, "corpse");
} else {
Lua_Corpse l_corpse(nullptr);
luabind::object l_corpse_o = luabind::object(L, l_corpse);
l_corpse_o.push(L);
lua_setfield(L, -2, "corpse");
}
}
void handle_item_null(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers) {
}
@ -465,11 +501,11 @@ void handle_item_null(QuestInterface *parse, lua_State* L, Client* client, ItemI
void handle_spell_effect(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers) {
if(npc) {
Lua_NPC l_npc(npc);
Lua_Mob l_npc(npc);
luabind::object l_npc_o = luabind::object(L, l_npc);
l_npc_o.push(L);
} else if(client) {
Lua_Client l_client(client);
Lua_Mob l_client(client);
luabind::object l_client_o = luabind::object(L, l_client);
l_client_o.push(L);
} else {
@ -477,8 +513,43 @@ void handle_spell_effect(QuestInterface *parse, lua_State* L, NPC* npc, Client*
luabind::object l_mob_o = luabind::object(L, l_mob);
l_mob_o.push(L);
}
lua_setfield(L, -2, "target");
lua_pushinteger(L, *reinterpret_cast<int*>(extra_pointers->at(0)));
lua_setfield(L, -2, "buff_slot");
lua_pushinteger(L, extra_data);
lua_setfield(L, -2, "caster_id");
}
void handle_spell_tic(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers) {
if(npc) {
Lua_Mob l_npc(npc);
luabind::object l_npc_o = luabind::object(L, l_npc);
l_npc_o.push(L);
} else if(client) {
Lua_Mob l_client(client);
luabind::object l_client_o = luabind::object(L, l_client);
l_client_o.push(L);
} else {
Lua_Mob l_mob(nullptr);
luabind::object l_mob_o = luabind::object(L, l_mob);
l_mob_o.push(L);
}
lua_setfield(L, -2, "target");
lua_pushinteger(L, *reinterpret_cast<int*>(extra_pointers->at(0)));
lua_setfield(L, -2, "tics_remaining");
lua_pushinteger(L, *reinterpret_cast<uint8*>(extra_pointers->at(1)));
lua_setfield(L, -2, "caster_level");
lua_pushinteger(L, *reinterpret_cast<int*>(extra_pointers->at(2)));
lua_setfield(L, -2, "buff_slot");
lua_pushinteger(L, extra_data);
lua_setfield(L, -2, "caster_id");
}
@ -486,11 +557,11 @@ void handle_spell_effect(QuestInterface *parse, lua_State* L, NPC* npc, Client*
void handle_spell_fade(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers) {
if(npc) {
Lua_NPC l_npc(npc);
Lua_Mob l_npc(npc);
luabind::object l_npc_o = luabind::object(L, l_npc);
l_npc_o.push(L);
} else if(client) {
Lua_Client l_client(client);
Lua_Mob l_client(client);
luabind::object l_client_o = luabind::object(L, l_client);
l_client_o.push(L);
} else {
@ -498,10 +569,33 @@ void handle_spell_fade(QuestInterface *parse, lua_State* L, NPC* npc, Client* cl
luabind::object l_mob_o = luabind::object(L, l_mob);
l_mob_o.push(L);
}
lua_setfield(L, -2, "target");
lua_pushinteger(L, extra_data);
lua_setfield(L, -2, "buff_slot");
lua_pushinteger(L, *reinterpret_cast<uint16*>(extra_pointers->at(0)));
lua_setfield(L, -2, "caster_id");
}
void handle_translocate_finish(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers) {
if(npc) {
Lua_Mob l_npc(npc);
luabind::object l_npc_o = luabind::object(L, l_npc);
l_npc_o.push(L);
} else if(client) {
Lua_Mob l_client(client);
luabind::object l_client_o = luabind::object(L, l_client);
l_client_o.push(L);
} else {
Lua_Mob l_mob(nullptr);
luabind::object l_mob_o = luabind::object(L, l_mob);
l_mob_o.push(L);
}
lua_setfield(L, -2, "target");
}
void handle_spell_null(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, uint32 extra_data,

View File

@ -4,7 +4,7 @@
typedef void(*NPCArgumentHandler)(QuestInterface*, lua_State*, NPC*, Mob*, std::string, uint32, std::vector<void*>*);
typedef void(*PlayerArgumentHandler)(QuestInterface*, lua_State*, Client*, std::string, uint32, std::vector<void*>*);
typedef void(*ItemArgumentHandler)(QuestInterface*, lua_State*, Client*, ItemInst*, std::string, uint32, std::vector<void*>*);
typedef void(*ItemArgumentHandler)(QuestInterface*, lua_State*, Client*, ItemInst*, Mob*, std::string, uint32, std::vector<void*>*);
typedef void(*SpellArgumentHandler)(QuestInterface*, lua_State*, NPC*, Client*, uint32, uint32, std::vector<void*>*);
//NPC
@ -86,18 +86,26 @@ void handle_player_null(QuestInterface *parse, lua_State* L, Client* client, std
std::vector<void*> *extra_pointers);
//Item
void handle_item_click(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, std::string data, uint32 extra_data,
void handle_item_click(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
void handle_item_timer(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, std::string data, uint32 extra_data,
void handle_item_timer(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
void handle_item_null(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, std::string data, uint32 extra_data,
void handle_item_proc(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
void handle_item_loot(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
void handle_item_null(QuestInterface *parse, lua_State* L, Client* client, ItemInst* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<void*> *extra_pointers);
//Spell
void handle_spell_effect(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers);
void handle_spell_tic(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers);
void handle_spell_fade(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers);
void handle_translocate_finish(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers);
void handle_spell_null(QuestInterface *parse, lua_State* L, NPC* npc, Client* client, uint32 spell_id, uint32 extra_data,
std::vector<void*> *extra_pointers);

View File

@ -2816,48 +2816,54 @@ int32 Mob::GetActSpellCasttime(uint16 spell_id, int32 casttime) {
return(casttime);
}
void Mob::ExecWeaponProc(uint16 spell_id, Mob *on) {
void Mob::ExecWeaponProc(const ItemInst *inst, uint16 spell_id, Mob *on) {
// Changed proc targets to look up based on the spells goodEffect flag.
// This should work for the majority of weapons.
if(spell_id == SPELL_UNKNOWN || on->SpecAttacks[NO_HARM_FROM_CLIENT]){ //This is so 65535 doesn't get passed to the client message and to logs because it is not relavant information for debugging.
return;
if(spell_id == SPELL_UNKNOWN || on->SpecAttacks[NO_HARM_FROM_CLIENT]) {
//This is so 65535 doesn't get passed to the client message and to logs because it is not relavant information for debugging.
return;
}
if (IsNoCast())
return;
if(!IsValidSpell(spell_id)){ // Check for a valid spell otherwise it will crash through the function
if(this->IsClient()){
this->Message(0, "Invalid spell proc %u", spell_id);
if(!IsValidSpell(spell_id)) { // Check for a valid spell otherwise it will crash through the function
if(IsClient()){
Message(0, "Invalid spell proc %u", spell_id);
mlog(CLIENT__SPELLS, "Player %s, Weapon Procced invalid spell %u", this->GetName(), spell_id);
}
return;
}
/*
int twinproc_chance = itembonuses.TwinProc + spellbonuses.TwinProc;
if(IsClient())
twinproc_chance += aabonuses.TwinProc;
*/
bool twinproc = false;
int32 twinproc_chance = 0;
if(IsClient())
twinproc_chance = CastToClient()->GetFocusEffect(focusTwincast, spell_id);
if(twinproc_chance && (MakeRandomInt(0,99) < twinproc_chance))
twinproc = true;
if (IsBeneficialSpell(spell_id)) {
SpellFinished(spell_id, this, 10, 0, -1, spells[spell_id].ResistDiff, true);
if(twinproc)
SpellOnTarget(spell_id, this, false, false, 0, true);
}
else if(!(on->IsClient() && on->CastToClient()->dead)) { //dont proc on dead clients
SpellFinished(spell_id, on, 10, 0, -1, spells[spell_id].ResistDiff, true);
if(twinproc)
SpellOnTarget(spell_id, on, false, false, 0, true);
if(inst && IsClient()) {
//const cast is dirty but it would require redoing a ton of interfaces at this point
//It should be safe as we don't have any truly const ItemInst floating around anywhere.
//So we'll live with it for now
int i = parse->EventItem(EVENT_WEAPON_PROC, CastToClient(), const_cast<ItemInst*>(inst), on, "", spell_id);
if(i != 0) {
return;
}
}
bool twinproc = false;
int32 twinproc_chance = 0;
if(IsClient())
twinproc_chance = CastToClient()->GetFocusEffect(focusTwincast, spell_id);
if(twinproc_chance && (MakeRandomInt(0,99) < twinproc_chance))
twinproc = true;
if (IsBeneficialSpell(spell_id)) {
SpellFinished(spell_id, this, 10, 0, -1, spells[spell_id].ResistDiff, true);
if(twinproc)
SpellOnTarget(spell_id, this, false, false, 0, true);
}
else if(!(on->IsClient() && on->CastToClient()->dead)) { //dont proc on dead clients
SpellFinished(spell_id, on, 10, 0, -1, spells[spell_id].ResistDiff, true);
if(twinproc)
SpellOnTarget(spell_id, on, false, false, 0, true);
}
return;
}

View File

@ -192,7 +192,7 @@ public:
//Buff
void BuffProcess();
virtual void DoBuffTic(uint16 spell_id, uint32 ticsremaining, uint8 caster_level, Mob* caster = 0);
virtual void DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caster_level, Mob* caster = 0);
void BuffFadeBySpellID(uint16 spell_id);
void BuffFadeByEffect(int effectid, int skipslot = -1);
void BuffFadeAll();
@ -878,7 +878,6 @@ protected:
uint32 scalerate;
Buffs_Struct *buffs;
uint32 current_buff_count;
Timer *buff_tic_timer;
StatBonuses itembonuses;
StatBonuses spellbonuses;
StatBonuses aabonuses;
@ -917,9 +916,9 @@ protected:
bool PassLimitToSkill(uint16 spell_id, uint16 skill);
bool PassLimitClass(uint32 Classes_, uint16 Class_);
void TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand = 13, int damage=0);
void TryWeaponProc(const Item_Struct* weapon, Mob *on, uint16 hand = 13);
void TryWeaponProc(const ItemInst* inst, const Item_Struct* weapon, Mob *on, uint16 hand = 13);
void TryWeaponProc(const ItemInst* weapon, Mob *on, uint16 hand = 13);
void ExecWeaponProc(uint16 spell_id, Mob *on);
void ExecWeaponProc(const ItemInst* weapon, uint16 spell_id, Mob *on);
virtual float GetProcChances(float &ProcBonus, float &ProcChance, uint16 weapon_speed = 30, uint16 hand = 13);
virtual float GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 weapon_speed = 30, uint16 hand = 13);
int GetWeaponDamage(Mob *against, const Item_Struct *weapon_item);

View File

@ -141,7 +141,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
if(IsNPC())
{
int i = parse->EventSpell(EVENT_SPELL_EFFECT_NPC, CastToNPC(), nullptr, spell_id, caster ? caster->GetID() : 0);
std::vector<void*> args;
args.push_back(&buffslot);
int i = parse->EventSpell(EVENT_SPELL_EFFECT_NPC, CastToNPC(), nullptr, spell_id, caster ? caster->GetID() : 0, &args);
if(i != 0){
CalcBonuses();
return true;
@ -149,7 +151,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
}
else if(IsClient())
{
int i = parse->EventSpell(EVENT_SPELL_EFFECT_CLIENT, nullptr, CastToClient(), spell_id, caster ? caster->GetID() : 0);
std::vector<void*> args;
args.push_back(&buffslot);
int i = parse->EventSpell(EVENT_SPELL_EFFECT_CLIENT, nullptr, CastToClient(), spell_id, caster ? caster->GetID() : 0, &args);
if(i != 0){
CalcBonuses();
return true;
@ -3001,7 +3005,7 @@ void Mob::BuffProcess()
{
if (buffs[buffs_i].spellid != SPELL_UNKNOWN)
{
DoBuffTic(buffs[buffs_i].spellid, buffs[buffs_i].ticsremaining, buffs[buffs_i].casterlevel, entity_list.GetMob(buffs[buffs_i].casterid));
DoBuffTic(buffs[buffs_i].spellid, buffs_i, buffs[buffs_i].ticsremaining, buffs[buffs_i].casterlevel, entity_list.GetMob(buffs[buffs_i].casterid));
// If the Mob died during DoBuffTic, then the buff we are currently processing will have been removed
if(buffs[buffs_i].spellid == SPELL_UNKNOWN)
continue;
@ -3051,7 +3055,7 @@ void Mob::BuffProcess()
}
}
void Mob::DoBuffTic(uint16 spell_id, uint32 ticsremaining, uint8 caster_level, Mob* caster) {
void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caster_level, Mob* caster) {
_ZP(Mob_DoBuffTic);
int effect, effect_value;
@ -3066,14 +3070,22 @@ void Mob::DoBuffTic(uint16 spell_id, uint32 ticsremaining, uint8 caster_level, M
if(IsNPC())
{
int i = parse->EventSpell(EVENT_SPELL_BUFF_TIC_NPC, CastToNPC(), nullptr, spell_id, caster ? caster->GetID() : 0);
std::vector<void*> args;
args.push_back(&ticsremaining);
args.push_back(&caster_level);
args.push_back(&slot);
int i = parse->EventSpell(EVENT_SPELL_BUFF_TIC_NPC, CastToNPC(), nullptr, spell_id, caster ? caster->GetID() : 0, &args);
if(i != 0) {
return;
}
}
else
{
int i = parse->EventSpell(EVENT_SPELL_BUFF_TIC_CLIENT, nullptr, CastToClient(), spell_id, caster ? caster->GetID() : 0);
std::vector<void*> args;
args.push_back(&ticsremaining);
args.push_back(&caster_level);
args.push_back(&slot);
int i = parse->EventSpell(EVENT_SPELL_BUFF_TIC_CLIENT, nullptr, CastToClient(), spell_id, caster ? caster->GetID() : 0, &args);
if(i != 0) {
return;
}
@ -3334,9 +3346,15 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
}
if(IsClient()) {
parse->EventSpell(EVENT_SPELL_FADE, nullptr, CastToClient(), buffs[slot].spellid, slot);
std::vector<void*> args;
args.push_back(&buffs[slot].casterid);
parse->EventSpell(EVENT_SPELL_FADE, nullptr, CastToClient(), buffs[slot].spellid, slot, &args);
} else if(IsNPC()) {
parse->EventSpell(EVENT_SPELL_FADE, CastToNPC(), nullptr, buffs[slot].spellid, slot);
std::vector<void*> args;
args.push_back(&buffs[slot].casterid);
parse->EventSpell(EVENT_SPELL_FADE, CastToNPC(), nullptr, buffs[slot].spellid, slot, &args);
}
for (int i=0; i < EFFECT_COUNT; i++)

View File

@ -5099,7 +5099,6 @@ void Client::InitializeBuffSlots()
buffs[x].spellid = SPELL_UNKNOWN;
}
current_buff_count = 0;
buff_tic_timer = nullptr;
}
void Client::UninitializeBuffSlots()
@ -5116,7 +5115,6 @@ void NPC::InitializeBuffSlots()
buffs[x].spellid = SPELL_UNKNOWN;
}
current_buff_count = 0;
buff_tic_timer = nullptr;
}
void NPC::UninitializeBuffSlots()