/*
* Copyright (C) 2008 Trinity
*
* Thanks to the original authors: MaNGOS
*
* 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 2 of the License, or
* (at your option) 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef TRINITYCORE_GAMEOBJECT_H
#define TRINITYCORE_GAMEOBJECT_H
#include "Common.h"
#include "SharedDefines.h"
#include "Object.h"
#include "LootMgr.h"
#include "Database/DatabaseEnv.h"
// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform
#if defined( __GNUC__ )
#pragma pack(1)
#else
#pragma pack(push,1)
#endif
// from `gameobject_template`
struct GameObjectInfo
{
uint32 id;
uint32 type;
uint32 displayId;
char *name;
char *castBarCaption;
uint32 faction;
uint32 flags;
float size;
union // different GO types have different data field
{
//0 GAMEOBJECT_TYPE_DOOR
struct
{
uint32 startOpen; //0 used client side to determine GO_ACTIVATED means open/closed
uint32 lockId; //1 -> Lock.dbc
uint32 autoCloseTime; //2 secs till autoclose = autoCloseTime / 0x10000
uint32 noDamageImmune; //3 break opening whenever you recieve damage?
uint32 openTextID; //4 can be used to replace castBarCaption?
uint32 closeTextID; //5
} door;
//1 GAMEOBJECT_TYPE_BUTTON
struct
{
uint32 startOpen; //0
uint32 lockId; //1 -> Lock.dbc
uint32 autoCloseTime; //2 secs till autoclose = autoCloseTime / 0x10000
uint32 linkedTrap; //3
uint32 noDamageImmune; //4 isBattlegroundObject
uint32 large; //5
uint32 openTextID; //6 can be used to replace castBarCaption?
uint32 closeTextID; //7
uint32 losOK; //8
} button;
//2 GAMEOBJECT_TYPE_QUESTGIVER
struct
{
uint32 lockId; //0 -> Lock.dbc
uint32 questList; //1
uint32 pageMaterial; //2
uint32 gossipID; //3
uint32 customAnim; //4
uint32 noDamageImmune; //5
uint32 openTextID; //6 can be used to replace castBarCaption?
uint32 losOK; //7
uint32 allowMounted; //8
uint32 large; //9
} questgiver;
//3 GAMEOBJECT_TYPE_CHEST
struct
{
uint32 lockId; //0 -> Lock.dbc
uint32 lootId; //1
uint32 chestRestockTime; //2
uint32 consumable; //3
uint32 minSuccessOpens; //4
uint32 maxSuccessOpens; //5
uint32 eventId; //6 lootedEvent
uint32 linkedTrapId; //7
uint32 questId; //8 not used currently but store quest required for GO activation for player
uint32 level; //9
uint32 losOK; //10
uint32 leaveLoot; //11
uint32 notInCombat; //12
uint32 logLoot; //13
uint32 openTextID; //14 can be used to replace castBarCaption?
uint32 groupLootRules; //15
} chest;
//5 GAMEOBJECT_TYPE_GENERIC
struct
{
uint32 floatingTooltip; //0
uint32 highlight; //1
uint32 serverOnly; //2
uint32 large; //3
uint32 floatOnWater; //4
uint32 questID; //5
} _generic;
//6 GAMEOBJECT_TYPE_TRAP
struct
{
uint32 lockId; //0 -> Lock.dbc
uint32 level; //1
uint32 radius; //2 radius for trap activation
uint32 spellId; //3
uint32 charges; //4 need respawn (if > 0)
uint32 cooldown; //5 time in secs
uint32 autoCloseTime; //6
uint32 startDelay; //7
uint32 serverOnly; //8
uint32 stealthed; //9
uint32 large; //10
uint32 stealthAffected; //11
uint32 openTextID; //12 can be used to replace castBarCaption?
uint32 closeTextID; //13
} trap;
//7 GAMEOBJECT_TYPE_CHAIR
struct
{
uint32 slots; //0
uint32 height; //1
uint32 onlyCreatorUse; //2
} chair;
//8 GAMEOBJECT_TYPE_SPELL_FOCUS
struct
{
uint32 focusId; //0
uint32 dist; //1
uint32 linkedTrapId; //2
uint32 serverOnly; //3
uint32 questID; //4
uint32 large; //5
} spellFocus;
//9 GAMEOBJECT_TYPE_TEXT
struct
{
uint32 pageID; //0
uint32 language; //1
uint32 pageMaterial; //2
uint32 allowMounted; //3
} text;
//10 GAMEOBJECT_TYPE_GOOBER
struct
{
uint32 lockId; //0 -> Lock.dbc
uint32 questId; //1
uint32 eventId; //2
uint32 autoCloseTime; //3
uint32 customAnim; //4
uint32 consumable; //5
uint32 cooldown; //6
uint32 pageId; //7
uint32 language; //8
uint32 pageMaterial; //9
uint32 spellId; //10
uint32 noDamageImmune; //11
uint32 linkedTrapId; //12
uint32 large; //13
uint32 openTextID; //14 can be used to replace castBarCaption?
uint32 closeTextID; //15
uint32 losOK; //16 isBattlegroundObject
uint32 allowMounted; //17
} goober;
//11 GAMEOBJECT_TYPE_TRANSPORT
struct
{
uint32 pause; //0
uint32 startOpen; //1
uint32 autoCloseTime; //2 secs till autoclose = autoCloseTime / 0x10000
} transport;
//12 GAMEOBJECT_TYPE_AREADAMAGE
struct
{
uint32 lockId; //0
uint32 radius; //1
uint32 damageMin; //2
uint32 damageMax; //3
uint32 damageSchool; //4
uint32 autoCloseTime; //5 secs till autoclose = autoCloseTime / 0x10000
uint32 openTextID; //6
uint32 closeTextID; //7
} areadamage;
//13 GAMEOBJECT_TYPE_CAMERA
struct
{
uint32 lockId; //0 -> Lock.dbc
uint32 cinematicId; //1
uint32 eventID; //2
uint32 openTextID; //3 can be used to replace castBarCaption?
} camera;
//15 GAMEOBJECT_TYPE_MO_TRANSPORT
struct
{
uint32 taxiPathId; //0
uint32 moveSpeed; //1
uint32 accelRate; //2
uint32 startEventID; //3
uint32 stopEventID; //4
uint32 transportPhysics; //5
uint32 mapID; //6
} moTransport;
//17 GAMEOBJECT_TYPE_FISHINGNODE
struct
{
uint32 _data0; //0
uint32 lootId; //1
} fishnode;
//18 GAMEOBJECT_TYPE_SUMMONING_RITUAL
struct
{
uint32 reqParticipants; //0
uint32 spellId; //1
uint32 animSpell; //2
uint32 ritualPersistent; //3
uint32 casterTargetSpell; //4
uint32 casterTargetSpellTargets; //5
uint32 castersGrouped; //6
uint32 ritualNoTargetCheck; //7
} summoningRitual;
//20 GAMEOBJECT_TYPE_AUCTIONHOUSE
struct
{
uint32 actionHouseID; //0
} auctionhouse;
//21 GAMEOBJECT_TYPE_GUARDPOST
struct
{
uint32 creatureID; //0
uint32 charges; //1
} guardpost;
//22 GAMEOBJECT_TYPE_SPELLCASTER
struct
{
uint32 spellId; //0
uint32 charges; //1
uint32 partyOnly; //2
} spellcaster;
//23 GAMEOBJECT_TYPE_MEETINGSTONE
struct
{
uint32 minLevel; //0
uint32 maxLevel; //1
uint32 areaID; //2
} meetingstone;
//24 GAMEOBJECT_TYPE_FLAGSTAND
struct
{
uint32 lockId; //0
uint32 pickupSpell; //1
uint32 radius; //2
uint32 returnAura; //3
uint32 returnSpell; //4
uint32 noDamageImmune; //5
uint32 openTextID; //6
uint32 losOK; //7
} flagstand;
//25 GAMEOBJECT_TYPE_FISHINGHOLE // not implemented yet
struct
{
uint32 radius; //0 how close bobber must land for sending loot
uint32 lootId; //1
uint32 minSuccessOpens; //2
uint32 maxSuccessOpens; //3
uint32 lockId; //4 -> Lock.dbc; possibly 1628 for all?
} fishinghole;
//26 GAMEOBJECT_TYPE_FLAGDROP
struct
{
uint32 lockId; //0
uint32 eventID; //1
uint32 pickupSpell; //2
uint32 noDamageImmune; //3
uint32 openTextID; //4
} flagdrop;
//27 GAMEOBJECT_TYPE_MINI_GAME
struct
{
uint32 gameType; //0
} miniGame;
//29 GAMEOBJECT_TYPE_CAPTURE_POINT
struct
{
uint32 radius; //0
uint32 spell; //1
uint32 worldState1; //2
uint32 worldstate2; //3
uint32 winEventID1; //4
uint32 winEventID2; //5
uint32 contestedEventID1; //6
uint32 contestedEventID2; //7
uint32 progressEventID1; //8
uint32 progressEventID2; //9
uint32 neutralEventID1; //10
uint32 neutralEventID2; //11
uint32 neutralPercent; //12
uint32 worldstate3; //13
uint32 minSuperiority; //14
uint32 maxSuperiority; //15
uint32 minTime; //16
uint32 maxTime; //17
uint32 large; //18
uint32 highlight; //19
} capturePoint;
//30 GAMEOBJECT_TYPE_AURA_GENERATOR
struct
{
uint32 startOpen; //0
uint32 radius; //1
uint32 auraID1; //2
uint32 conditionID1; //3
uint32 auraID2; //4
uint32 conditionID2; //5
uint32 serverOnly; //6
} auraGenerator;
//31 GAMEOBJECT_TYPE_DUNGEON_DIFFICULTY
struct
{
uint32 mapID; //0
uint32 difficulty; //1
} dungeonDifficulty;
//32 GAMEOBJECT_TYPE_DO_NOT_USE_YET
struct
{
uint32 mapID; //0
uint32 difficulty; //1
} doNotUseYet;
//33 GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING
struct
{
uint32 dmgPctState1; //0
uint32 dmgPctState2; //1
uint32 state1Name; //2
uint32 state2Name; //3
} destructibleBuilding;
// not use for specific field access (only for output with loop by all filed), also this determinate max union size
struct // GAMEOBJECT_TYPE_SPELLCASTER
{
uint32 data[24];
} raw;
};
char *ScriptName;
};
struct GameObjectLocale
{
std::vector Name;
std::vector CastBarCaption;
};
// from `gameobject`
struct GameObjectData
{
uint32 id; // entry in gamobject_template
uint32 mapid;
float posX;
float posY;
float posZ;
float orientation;
float rotation0;
float rotation1;
float rotation2;
float rotation3;
int32 spawntimesecs;
uint32 animprogress;
uint32 go_state;
uint8 spawnMask;
uint32 ArtKit;
};
// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform
#if defined( __GNUC__ )
#pragma pack()
#else
#pragma pack(pop)
#endif
// For containers: [GO_NOT_READY]->GO_READY (close)->GO_ACTIVATED (open) ->GO_JUST_DEACTIVATED->GO_READY -> ...
// For bobber: GO_NOT_READY ->GO_READY (close)->GO_ACTIVATED (open) ->GO_JUST_DEACTIVATED->
// For door(closed):[GO_NOT_READY]->GO_READY (close)->GO_ACTIVATED (open) ->GO_JUST_DEACTIVATED->GO_READY(close) -> ...
// For door(open): [GO_NOT_READY]->GO_READY (open) ->GO_ACTIVATED (close)->GO_JUST_DEACTIVATED->GO_READY(open) -> ...
enum LootState
{
GO_NOT_READY = 0,
GO_READY, // can be ready but despawned, and then not possible activate until spawn
GO_ACTIVATED,
GO_JUST_DEACTIVATED
};
class Unit;
// 5 sec for bobber catch
#define FISHING_BOBBER_READY_TIME 5
class TRINITY_DLL_SPEC GameObject : public WorldObject
{
public:
explicit GameObject();
~GameObject();
void AddToWorld();
void RemoveFromWorld();
bool Create(uint32 guidlow, uint32 name_id, Map *map, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, uint32 go_state, uint32 ArtKit = 0);
void Update(uint32 p_time);
static GameObject* GetGameObject(WorldObject& object, uint64 guid);
GameObjectInfo const* GetGOInfo() const;
bool IsTransport() const;
void SetOwnerGUID(uint64 owner)
{
m_spawnedByDefault = false; // all object with owner is despawned after delay
SetUInt64Value(OBJECT_FIELD_CREATED_BY, owner);
}
uint64 GetOwnerGUID() const { return GetUInt64Value(OBJECT_FIELD_CREATED_BY); }
Unit* GetOwner() const;
uint32 GetDBTableGUIDLow() const { return m_DBTableGuid; }
void Say(const char* text, uint32 language, uint64 TargetGuid) { MonsterSay(text,language,TargetGuid); }
void Yell(const char* text, uint32 language, uint64 TargetGuid) { MonsterYell(text,language,TargetGuid); }
void TextEmote(const char* text, uint64 TargetGuid) { MonsterTextEmote(text,TargetGuid); }
void Whisper(const char* text,uint64 receiver) { MonsterWhisper(text,receiver); }
void Say(int32 textId, uint32 language, uint64 TargetGuid) { MonsterSay(textId,language,TargetGuid); }
void Yell(int32 textId, uint32 language, uint64 TargetGuid) { MonsterYell(textId,language,TargetGuid); }
void TextEmote(int32 textId, uint64 TargetGuid) { MonsterTextEmote(textId,TargetGuid); }
void Whisper(int32 textId, uint64 receiver) { MonsterWhisper(textId,receiver); }
void SaveToDB();
void SaveToDB(uint32 mapid, uint8 spawnMask);
bool LoadFromDB(uint32 guid, Map *map);
void DeleteFromDB();
void SetLootState(LootState s) { m_lootState = s; }
static uint32 GetLootId(GameObjectInfo const* info);
uint32 GetLootId() const { return GetLootId(GetGOInfo()); }
uint32 GetLockId() const
{
switch(GetGoType())
{
case GAMEOBJECT_TYPE_DOOR: return GetGOInfo()->door.lockId;
case GAMEOBJECT_TYPE_BUTTON: return GetGOInfo()->button.lockId;
case GAMEOBJECT_TYPE_QUESTGIVER: return GetGOInfo()->questgiver.lockId;
case GAMEOBJECT_TYPE_CHEST: return GetGOInfo()->chest.lockId;
case GAMEOBJECT_TYPE_TRAP: return GetGOInfo()->trap.lockId;
case GAMEOBJECT_TYPE_GOOBER: return GetGOInfo()->goober.lockId;
case GAMEOBJECT_TYPE_AREADAMAGE: return GetGOInfo()->areadamage.lockId;
case GAMEOBJECT_TYPE_CAMERA: return GetGOInfo()->camera.lockId;
case GAMEOBJECT_TYPE_FLAGSTAND: return GetGOInfo()->flagstand.lockId;
case GAMEOBJECT_TYPE_FISHINGHOLE:return GetGOInfo()->fishinghole.lockId;
case GAMEOBJECT_TYPE_FLAGDROP: return GetGOInfo()->flagdrop.lockId;
default: return 0;
}
}
time_t GetRespawnTime() const { return m_respawnTime; }
time_t GetRespawnTimeEx() const
{
time_t now = time(NULL);
if(m_respawnTime > now)
return m_respawnTime;
else
return now;
}
void SetRespawnTime(int32 respawn)
{
m_respawnTime = respawn > 0 ? time(NULL) + respawn : 0;
m_respawnDelayTime = respawn > 0 ? respawn : 0;
}
void Respawn();
bool isSpawned() const
{
return m_respawnDelayTime == 0 ||
(m_respawnTime > 0 && !m_spawnedByDefault) ||
(m_respawnTime == 0 && m_spawnedByDefault);
}
bool isSpawnedByDefault() const { return m_spawnedByDefault; }
void SetSpawnedByDefault(bool b) { m_spawnedByDefault = b; }
uint32 GetRespawnDelay() const { return m_respawnDelayTime; }
void Refresh();
void Delete();
void SetSpellId(uint32 id) { m_spellId = id;}
uint32 GetSpellId() const { return m_spellId;}
void getFishLoot(Loot *loot);
GameobjectTypes GetGoType() const { return GameobjectTypes(GetUInt32Value(GAMEOBJECT_TYPE_ID)); }
void SetGoType(GameobjectTypes type) { SetUInt32Value(GAMEOBJECT_TYPE_ID, type); }
uint32 GetGoState() const { return GetUInt32Value(GAMEOBJECT_STATE); }
void SetGoState(uint32 state) { SetUInt32Value(GAMEOBJECT_STATE, state); }
uint32 GetGoArtKit() const { return GetUInt32Value(GAMEOBJECT_ARTKIT); }
void SetGoArtKit(uint32 artkit);
uint32 GetGoAnimProgress() const { return GetUInt32Value(GAMEOBJECT_ANIMPROGRESS); }
void SetGoAnimProgress(uint32 animprogress) { SetUInt32Value(GAMEOBJECT_ANIMPROGRESS, animprogress); }
void Use(Unit* user);
LootState getLootState() const { return m_lootState; }
void AddToSkillupList(uint32 PlayerGuidLow) { m_SkillupList.push_back(PlayerGuidLow); }
bool IsInSkillupList(uint32 PlayerGuidLow) const
{
for (std::list::const_iterator i = m_SkillupList.begin(); i != m_SkillupList.end(); ++i)
if (*i == PlayerGuidLow) return true;
return false;
}
void ClearSkillupList() { m_SkillupList.clear(); }
void AddUniqueUse(Player* player);
void AddUse() { ++m_usetimes; }
uint32 GetUseCount() const { return m_usetimes; }
uint32 GetUniqueUseCount() const { return m_unique_users.size(); }
void SaveRespawnTime();
Loot loot;
bool hasQuest(uint32 quest_id) const;
bool hasInvolvedQuest(uint32 quest_id) const;
bool ActivateToQuest(Player *pTarget) const;
void UseDoorOrButton(uint32 time_to_restore = 0); // 0 = use `gameobject`.`spawntimesecs`
uint32 GetLinkedGameObjectEntry() const
{
switch(GetGoType())
{
case GAMEOBJECT_TYPE_CHEST: return GetGOInfo()->chest.linkedTrapId;
case GAMEOBJECT_TYPE_SPELL_FOCUS: return GetGOInfo()->spellFocus.linkedTrapId;
case GAMEOBJECT_TYPE_GOOBER: return GetGOInfo()->goober.linkedTrapId;
default: return 0;
}
}
uint32 GetAutoCloseTime() const
{
uint32 autoCloseTime = 0;
switch(GetGoType())
{
case GAMEOBJECT_TYPE_DOOR: autoCloseTime = GetGOInfo()->door.autoCloseTime; break;
case GAMEOBJECT_TYPE_BUTTON: autoCloseTime = GetGOInfo()->button.autoCloseTime; break;
case GAMEOBJECT_TYPE_TRAP: autoCloseTime = GetGOInfo()->trap.autoCloseTime; break;
case GAMEOBJECT_TYPE_GOOBER: autoCloseTime = GetGOInfo()->goober.autoCloseTime; break;
case GAMEOBJECT_TYPE_TRANSPORT: autoCloseTime = GetGOInfo()->transport.autoCloseTime; break;
case GAMEOBJECT_TYPE_AREADAMAGE: autoCloseTime = GetGOInfo()->areadamage.autoCloseTime; break;
default: break;
}
return autoCloseTime / 0x10000;
}
void TriggeringLinkedGameObject( uint32 trapEntry, Unit* target);
bool isVisibleForInState(Player const* u, bool inVisibleList) const;
GameObject* LookupFishingHoleAround(float range);
GridReference &GetGridRef() { return m_gridRef; }
protected:
uint32 m_charges; // Spell charges for GAMEOBJECT_TYPE_SPELLCASTER (22)
uint32 m_spellId;
time_t m_respawnTime; // (secs) time of next respawn (or despawn if GO have owner()),
uint32 m_respawnDelayTime; // (secs) if 0 then current GO state no dependent from timer
LootState m_lootState;
bool m_spawnedByDefault;
time_t m_cooldownTime; // used as internal reaction delay time store (not state change reaction).
// For traps this: spell casting cooldown, for doors/buttons: reset time.
std::list m_SkillupList;
std::set m_unique_users;
uint32 m_usetimes;
uint32 m_DBTableGuid; ///< For new or temporary gameobjects is 0 for saved it is lowguid
GameObjectInfo const* m_goInfo;
private:
void SwitchDoorOrButton(bool activate);
GridReference m_gridRef;
};
#endif