/* * Ascent MMORPG Server * Copyright (C) 2005-2007 Ascent Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #ifndef __EVENTMGR_H #define __EVENTMGR_H enum EventTypes { EVENT_UNK = 0, EVENT_MAPMGR_UPDATEOBJECTS, EVENT_MAPCELL_UNLOAD, EVENT_WORLD_UPDATEAUCTIONS, EVENT_WORLD_UPDATESESSIONS, EVENT_CREATURE_UPDATE, EVENT_PLAYER_UPDATE, EVENT_PLAYER_UPDATEEXPLORATION, EVENT_GAMEOBJECT_UPDATE, EVENT_DYNAMICOBJECT_UPDATE, EVENT_GAMEOBJECT_ENV_DAMAGE, EVENT_PLAYER_STOPPVP, EVENT_CREATURE_JUSTDIED, EVENT_CREATURE_REMOVE_CORPSE, EVENT_CREATURE_RESPAWN, EVENT_MAPMGR_UNLOAD_CELL, EVENT_PLAYER_REST, EVENT_PLAYER_SEND_PACKET, EVENT_UNIT_EMOTE, EVENT_WORLD_UPDATEQUEUES, EVENT_PET_UPDATE, EVENT_PLAYER_REDUCEDRUNK, EVENT_WEATHER_UPDATE, EVENT_TOTEM_EXPIRE, EVENT_TOTEM_SEEK_TARGET, EVENT_TOTEM_SEEK_TARGET_AREA_AURA, EVENT_ENSLAVE_EXPIRE, EVENT_PLAYER_TAXI_DISMOUNT, EVENT_GAMEOBJECT_DOOR_CLOSE, EVENT_PLAYER_ALLOW_TRIGGERPORT, EVENT_SPELL_DAMAGE_HIT, EVENT_PET_SPELL_COOLDOWN, EVENT_GAMEOBJECT_UNHOOK, EVENT_GAMEOBJECT_FISH_HOOKED, EVENT_GAMEOBJECT_FISH_NOT_HOOKED, EVENT_GAMEOBJECT_END_FISHING, EVENT_PLAYER_REPEAT_SHOT, EVENT_PLAYER_ACTIVATE_GAMEOBJECT, EVENT_UNIT_REPEAT_MSG, EVENT_UNIT_CHAT_MSG, EVENT_PLAYER_MOTD, EVENT_TIMED_QUEST_EXPIRE, EVENT_UNIT_MANUAL_REPEAT_MSG, EVENT_PLAYER_TAXI_POSITION_UPDATE, EVENT_PLAYER_TAXI_INTERPOLATE, EVENT_PLAYER_CHECKFORCHEATS, EVENT_AREAAURA_UPDATE, EVENT_AURA_REMOVE, EVENT_AURA_PERIODIC_DAMAGE, EVENT_AURA_PERIODIC_DAMAGE_PERCENT, EVENT_AURA_PERIODIC_HEAL, EVENT_AURA_PERIODIC_TRIGGERSPELL, EVENT_AURA_PERIODIC_ENERGIZE, EVENT_AURA_PERIODIC_LEECH, EVENT_AURA_PERIODIC_BURN, EVENT_AURA_PERIOCIC_MANA, EVENT_AURA_PERIODIC_HEALTH_FUNNEL, EVENT_AURA_MANA_FUNNEL, EVENT_CANNIBALIZE, EVENT_GROUP_POSITION_UPDATE, EVNET_RAID_POSITION_UPDATE, EVENT_DELETE_TIMER, EVENT_UNIT_SENDMOVE, EVENT_GAMEOBJECT_ITEM_SPAWN, EVENT_GAMEOBJECT_ITEM_DESPAWN, EVENT_GAMEOBJECT_EXPIRE, EVENT_CREATURE_SAFE_DELETE, EVENT_PET_DELAYED_REMOVE, EVENT_REMOVE_ENCHANTMENT, EVENT_REMOVE_ENCHANTMENT1, EVENT_REMOVE_ENCHANTMENT2, EVENT_REMOVE_ENCHANTMENT3, EVENT_REMOVE_ENCHANTMENT4, EVENT_REMOVE_ENCHANTMENT5, EVENT_REMOVE_ENCHANTMENT6, EVENT_REMOVE_ENCHANTMENT7, EVENT_REMOVE_ENCHANTMENT8, EVENT_REMOVE_ENCHANTMENT9, EVENT_REMOVE_ENCHANTMENT10, EVENT_REMOVE_ENCHANTMENT11, EVENT_REMOVE_ENCHANTMENT12, EVENT_REMOVE_ENCHANTMENT13, EVENT_REMOVE_ENCHANTMENT14, EVENT_REMOVE_ENCHANTMENT15, EVENT_REMOVE_ENCHANTMENT16, EVENT_REMOVE_ENCHANTMENT17, EVENT_REMOVE_ENCHANTMENT18, EVENT_REMOVE_ENCHANTMENT19, EVENT_REMOVE_ENCHANTMENT20, EVENT_REMOVE_ENCHANTMENT21, EVENT_PLAYER_CHARM_ATTACK, EVENT_PLAYER_KICK, EVENT_TRANSPORTER_NEXT_WAYPOINT, EVENT_LOOT_ROLL_FINALIZE, EVENT_FIELD_UPDATE_EXPIRE, EVENT_SUMMON_PET_EXPIRE, EVENT_CORPSE_DESPAWN, EVENT_SCRIPT_UPDATE_EVENT, EVENT_INSTANCE_SOFT_RESET, EVENT_INSTANCE_HARD_RESET, EVENT_INSTANCE_LIMIT_COUNTER, EVENT_MAP_SPAWN_EVENTS, EVENT_PLAYER_DUEL_COUNTDOWN, EVENT_PLAYER_DUEL_BOUNDARY_CHECK, EVENT_GAMEOBJECT_TRAP_SEARCH_TARGET, EVENT_PLAYER_TELEPORT, EVENT_UNIT_DIMINISHING_RETURN, EVENT_UNIT_UNROOT, EVENT_MAILSYSTEM_RELOAD, EVENT_CREATURE_FORMATION_LINKUP, EVENT_AURA_REGEN_MANA_STAT_PCT, EVENT_AURA_PERIODIC_HEALINCOMB, EVENT_AURA_REGEN, EVENT_AURA_PERIODIC_REGEN, EVENT_AURA_PERIODIC_HEALPERC, EVENT_ATTACK_TIMEOUT, //Zack 2007 05 05: if no action is taken then combat should be exited after 5 seconds. EVENT_SUMMON_EXPIRE, //Zack 2007 05 28: similar to pet expire but we can have multiple guardians EVENT_MUTE_PLAYER, //Zack 2007 06 05: player gains his voice back EVENT_PLAYER_FORECED_RESURECT, //Zack 2007 06 08: After player not pushing release spirit for 6 minutes while dead EVENT_PLAYER_SOFT_DISCONNECT, //Zack 2007 06 12: Kick AFK players to not eat resources EVENT_BATTLEGROND_WSG_AUTO_RETURN_FLAG, EVENT_CORPSE_SPAWN_BONES, EVENT_DODGE_BLOCK_FLAG_EXPIRE, //yeah, there are more then 1 flags EVENT_PARRY_FLAG_EXPIRE, EVENT_CRIT_FLAG_EXPIRE, EVENT_GMSCRIPT_EVENT, EVENT_RELOCATE, EVENT_BATTLEGROUND_QUEUE_UPDATE, EVENT_BATTLEGROUND_SPAWN_BUFF, EVENT_BATTLEGROUND_COUNTDOWN, EVENT_BATTLEGROUND_CLOSE, }; enum EventFlags { EVENT_FLAG_DO_NOT_EXECUTE_IN_WORLD_CONTEXT = 0x1, }; struct SERVER_DECL TimedEvent { TimedEvent(void* object, CallbackBase* callback, uint32 type, time_t time, uint32 repeat, uint32 flags) : obj(object), cb(callback), eventType(type), msTime(time), currTime(time), repeats(repeat), deleted(false), eventFlag(flags),ref(0) {} void *obj; CallbackBase *cb; uint32 eventType; uint16 eventFlag; time_t msTime; time_t currTime; uint16 repeats; bool deleted; int instanceId; volatile long ref; static TimedEvent * Allocate(void* object, CallbackBase* callback, uint32 flags, time_t time, uint32 repeat); #ifdef WIN32 inline void DecRef() { InterlockedDecrement(&ref); if(ref <= 0) { delete cb; delete this; } } inline void IncRef() { InterlockedIncrement(&ref); } #else /* espire: if anyone knows how to do the equivilent of InterlockedIncrement/Decrement on linux feel free to change this, I couldn't find the atomic functions anymore though :*( */ inline void IncRef() { ++ref; } inline void DecRef() { --ref; if(ref <= 0) { delete cb; delete this; } } #endif }; class EventMgr; class EventableObjectHolder; typedef map HolderMap; class SERVER_DECL EventMgr : public Singleton < EventMgr > { friend class MiniEventMgr; public: template void AddEvent(Class *obj, void (Class::*method)(), uint32 type, uint32 time, uint32 repeats, uint32 flags) { // create a timed event TimedEvent * event = new TimedEvent(obj, new CallbackP0(obj, method), type, time, repeats, flags); // add this to the object's list, updating will all be done later on... obj->event_AddEvent(event); } template void AddEvent(Class *obj, void (Class::*method)(P1), P1 p1, uint32 type, uint32 time, uint32 repeats, uint32 flags) { // create a timed event TimedEvent * event = new TimedEvent(obj, new CallbackP1(obj, method, p1), type, time, repeats, flags); // add this to the object's list, updating will all be done later on... obj->event_AddEvent(event); } template void AddEvent(Class *obj, void (Class::*method)(P1,P2), P1 p1, P2 p2, uint32 type, uint32 time, uint32 repeats, uint32 flags) { // create a timed event TimedEvent * event = new TimedEvent(obj, new CallbackP2(obj, method, p1, p2), type, time, repeats, flags); // add this to the object's list, updating will all be done later on... obj->event_AddEvent(event); } template void AddEvent(Class *obj,void (Class::*method)(P1,P2,P3), P1 p1, P2 p2, P3 p3, uint32 type, uint32 time, uint32 repeats, uint32 flags) { // create a timed event TimedEvent * event = new TimedEvent(obj, new CallbackP3(obj, method, p1, p2, p3), type, time, repeats, flags); // add this to the object's list, updating will all be done later on... obj->event_AddEvent(event); } template void AddEvent(Class *obj, void (Class::*method)(P1,P2,P3,P4), P1 p1, P2 p2, P3 p3, P4 p4, uint32 type, uint32 time, uint32 repeats, uint32 flags) { // create a timed event TimedEvent * event = new TimedEvent(obj, new CallbackP4(obj, method, p1, p2, p3, p4), type, time, repeats, flags); // add this to the object's list, updating will all be done later on... obj->event_AddEvent(event); } template inline void RemoveEvents(Class *obj) { RemoveEvents(obj, -1); } template void RemoveEvents(Class *obj, int32 type) { obj->event_RemoveEvents(type); } template void ModifyEventTimeLeft(Class *obj, uint32 type, uint32 time,bool unconditioned=true) { obj->event_ModifyTimeLeft(type, time,unconditioned); } template void ModifyEventTime(Class *obj, uint32 type, uint32 time) { obj->event_ModifyTime(type, time); } template bool HasEvent(Class *obj, uint32 type) { return obj->event_HasEvent(type); } EventableObjectHolder * GetEventHolder(int32 InstanceId) { HolderMap::iterator itr = mHolders.find(InstanceId); if(itr == mHolders.end()) return 0; return itr->second; } inline void AddEventHolder(EventableObjectHolder * holder, int32 InstanceId) { holderLock.Acquire(); mHolders.insert( HolderMap::value_type( InstanceId, holder) ); holderLock.Release(); } inline void RemoveEventHolder(int32 InstanceId) { holderLock.Acquire(); mHolders.erase(InstanceId); holderLock.Release(); } inline void RemoveEventHolder(EventableObjectHolder * holder) { holderLock.Acquire(); HolderMap::iterator itr = mHolders.begin(); for(; itr != mHolders.end(); ++itr) { if(itr->second == holder) { mHolders.erase(itr); holderLock.Release(); return; } } holderLock.Release(); } protected: HolderMap mHolders; Mutex holderLock; }; #define sEventMgr EventMgr::getSingleton() #endif