From c2e6dd20dda42686164c190eb7ebcc673a21802e Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 26 Apr 2009 07:14:46 +0400 Subject: [PATCH] [7715] Provided way for scripts set alternative gameobject state for client show. Also use enum for gsmeobject states. --- src/game/BattleGround.cpp | 4 ++-- src/game/GameObject.cpp | 48 ++++++++++++++++++++++----------------- src/game/GameObject.h | 41 +++++++++++++++++++++------------ src/game/Level2.cpp | 2 +- src/game/ObjectMgr.cpp | 10 +++++++- src/game/SpellAuras.cpp | 2 +- src/game/SpellEffects.cpp | 14 ++++++------ src/game/Transports.cpp | 2 +- src/game/World.cpp | 8 +++---- src/shared/revision_nr.h | 2 +- 10 files changed, 80 insertions(+), 53 deletions(-) diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 6ea83c0f4..ee972d2d4 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -1324,7 +1324,7 @@ bool BattleGround::AddObject(uint32 type, uint32 entry, float x, float y, float // so we must create it specific for this instance GameObject * go = new GameObject; if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),entry, map, - PHASEMASK_NORMAL, x,y,z,o,rotation0,rotation1,rotation2,rotation3,100,1)) + PHASEMASK_NORMAL, x,y,z,o,rotation0,rotation1,rotation2,rotation3,100,GO_STATE_READY)) { sLog.outErrorDb("Gameobject template %u not found in database! BattleGround not created!", entry); sLog.outError("Cannot create gameobject template %u! BattleGround not created!", entry); @@ -1367,7 +1367,7 @@ void BattleGround::DoorClose(uint32 type) if (obj) { //if doors are open, close it - if (obj->getLootState() == GO_ACTIVATED && !obj->GetGoState()) + if (obj->getLootState() == GO_ACTIVATED && obj->GetGoState() != GO_STATE_READY) { //change state to allow door to be closed obj->SetLootState(GO_READY); diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index 7531c01b9..600d74b66 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -88,7 +88,7 @@ void GameObject::RemoveFromWorld() Object::RemoveFromWorld(); } -bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, uint32 phaseMask, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, uint32 go_state) +bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, uint32 phaseMask, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, GOState go_state) { Relocate(x,y,z,ang); SetMapId(map->GetId()); @@ -188,7 +188,7 @@ void GameObject::Update(uint32 /*p_time*/) Unit* caster = GetOwner(); if(caster && caster->GetTypeId()==TYPEID_PLAYER) { - SetGoState(0); + SetGoState(GO_STATE_ACTIVE); SetUInt32Value(GAMEOBJECT_FLAGS, GO_FLAG_NODESPAWN); UpdateData udata; @@ -246,11 +246,11 @@ void GameObject::Update(uint32 /*p_time*/) case GAMEOBJECT_TYPE_DOOR: case GAMEOBJECT_TYPE_BUTTON: //we need to open doors if they are closed (add there another condition if this code breaks some usage, but it need to be here for battlegrounds) - if( !GetGoState() ) - SwitchDoorOrButton(false); + if (GetGoState() != GO_STATE_READY) + ResetDoorOrButton(); //flags in AB are type_button and we need to add them here so no break! default: - if(!m_spawnedByDefault) // despawn timer + if (!m_spawnedByDefault) // despawn timer { // can be despawned or destroyed SetLootState(GO_JUST_DEACTIVATED); @@ -368,11 +368,8 @@ void GameObject::Update(uint32 /*p_time*/) { case GAMEOBJECT_TYPE_DOOR: case GAMEOBJECT_TYPE_BUTTON: - if(GetAutoCloseTime() && (m_cooldownTime < time(NULL))) - { - SwitchDoorOrButton(false); - SetLootState(GO_JUST_DEACTIVATED); - } + if (GetAutoCloseTime() && (m_cooldownTime < time(NULL))) + ResetDoorOrButton(); break; } break; @@ -460,7 +457,7 @@ void GameObject::Delete() { SendObjectDeSpawnAnim(GetGUID()); - SetGoState(1); + SetGoState(GO_STATE_READY); SetUInt32Value(GAMEOBJECT_FLAGS, GetGOInfo()->flags); uint16 poolid = poolhandler.IsPartOfAPool(GetGUIDLow(), TYPEID_GAMEOBJECT); @@ -545,8 +542,8 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask) << GetFloatValue(GAMEOBJECT_PARENTROTATION+2) << ", " << GetFloatValue(GAMEOBJECT_PARENTROTATION+3) << ", " << m_respawnDelayTime << ", " - << (uint32)GetGoAnimProgress() << ", " - << (uint32)GetGoState() << ")"; + << uint32(GetGoAnimProgress()) << ", " + << uint32(GetGoState()) << ")"; WorldDatabase.BeginTransaction(); WorldDatabase.PExecuteLog("DELETE FROM gameobject WHERE guid = '%u'", m_DBTableGuid); @@ -578,7 +575,7 @@ bool GameObject::LoadFromDB(uint32 guid, Map *map) float rotation3 = data->rotation3; uint32 animprogress = data->animprogress; - uint32 go_state = data->go_state; + GOState go_state = data->go_state; m_DBTableGuid = guid; if (map->GetInstanceId() != 0) guid = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT); @@ -813,7 +810,17 @@ GameObject* GameObject::LookupFishingHoleAround(float range) return ok; } -void GameObject::UseDoorOrButton(uint32 time_to_restore) +void GameObject::ResetDoorOrButton() +{ + if (m_lootState == GO_READY || m_lootState == GO_JUST_DEACTIVATED) + return; + + SwitchDoorOrButton(false); + SetLootState(GO_JUST_DEACTIVATED); + m_cooldownTime = 0; +} + +void GameObject::UseDoorOrButton(uint32 time_to_restore, bool alternative /* = false */) { if(m_lootState != GO_READY) return; @@ -821,24 +828,23 @@ void GameObject::UseDoorOrButton(uint32 time_to_restore) if(!time_to_restore) time_to_restore = GetAutoCloseTime(); - SwitchDoorOrButton(true); + SwitchDoorOrButton(true,alternative); SetLootState(GO_ACTIVATED); m_cooldownTime = time(NULL) + time_to_restore; - } -void GameObject::SwitchDoorOrButton(bool activate) +void GameObject::SwitchDoorOrButton(bool activate, bool alternative /* = false */) { if(activate) SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE); else RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE); - if(GetGoState()) //if closed -> open - SetGoState(0); + if(GetGoState() == GO_STATE_READY) //if closed -> open + SetGoState(alternative ? GO_STATE_ACTIVE_ALTERNATIVE : GO_STATE_ACTIVE); else //if open -> close - SetGoState(1); + SetGoState(GO_STATE_READY); } void GameObject::Use(Unit* user) diff --git a/src/game/GameObject.h b/src/game/GameObject.h index f06dbe79e..5b88a6b23 100644 --- a/src/game/GameObject.h +++ b/src/game/GameObject.h @@ -366,12 +366,29 @@ struct GameObjectInfo uint32 ScriptId; }; +// 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 + struct GameObjectLocale { std::vector Name; std::vector CastBarCaption; }; +// client side GO show states +enum GOState +{ + GO_STATE_ACTIVE = 0, // show in world as used and not reset (closed door open) + GO_STATE_READY = 1, // show in world as ready (closed door close) + GO_STATE_ACTIVE_ALTERNATIVE = 2 // show in world as used in alt way and not reset (closed door open by cannon fire) +}; + +#define MAX_GO_STATE 3 + // from `gameobject` struct GameObjectData { @@ -388,17 +405,10 @@ struct GameObjectData float rotation3; int32 spawntimesecs; uint32 animprogress; - uint32 go_state; + GOState go_state; uint8 spawnMask; }; -// 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) -> ... @@ -425,7 +435,7 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject void AddToWorld(); void RemoveFromWorld(); - bool Create(uint32 guidlow, uint32 name_id, Map *map, uint32 phaseMask, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, uint32 go_state); + bool Create(uint32 guidlow, uint32 name_id, Map *map, uint32 phaseMask, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, GOState go_state); void Update(uint32 p_time); GameObjectInfo const* GetGOInfo() const; @@ -456,7 +466,6 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject void SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask); 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 @@ -523,8 +532,8 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject void getFishLoot(Loot *loot, Player* loot_owner); GameobjectTypes GetGoType() const { return GameobjectTypes(GetByteValue(GAMEOBJECT_BYTES_1, 1)); } void SetGoType(GameobjectTypes type) { SetByteValue(GAMEOBJECT_BYTES_1, 1, type); } - uint8 GetGoState() const { return GetByteValue(GAMEOBJECT_BYTES_1, 0); } - void SetGoState(uint8 state) { SetByteValue(GAMEOBJECT_BYTES_1, 0, state); } + GOState GetGoState() const { return GOState(GetByteValue(GAMEOBJECT_BYTES_1, 0)); } + void SetGoState(GOState state) { SetByteValue(GAMEOBJECT_BYTES_1, 0, state); } uint8 GetGoArtKit() const { return GetByteValue(GAMEOBJECT_BYTES_1, 2); } void SetGoArtKit(uint8 artkit) { SetByteValue(GAMEOBJECT_BYTES_1, 2, artkit); } uint8 GetGoAnimProgress() const { return GetByteValue(GAMEOBJECT_BYTES_1, 3); } @@ -533,6 +542,7 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject void Use(Unit* user); LootState getLootState() const { return m_lootState; } + void SetLootState(LootState s) { m_lootState = s; } void AddToSkillupList(uint32 PlayerGuidLow) { m_SkillupList.push_back(PlayerGuidLow); } bool IsInSkillupList(uint32 PlayerGuidLow) const @@ -556,7 +566,10 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject 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` + void UseDoorOrButton(uint32 time_to_restore = 0, bool alternative = false); + // 0 = use `gameobject`.`spawntimesecs` + void ResetDoorOrButton(); + // 0 = use `gameobject`.`spawntimesecs` uint32 GetLinkedGameObjectEntry() const { @@ -611,7 +624,7 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject uint32 m_DBTableGuid; ///< For new or temporary gameobjects is 0 for saved it is lowguid GameObjectInfo const* m_goInfo; private: - void SwitchDoorOrButton(bool activate); + void SwitchDoorOrButton(bool activate, bool alternative = false); GridReference m_gridRef; }; diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index fc757bb98..1237ef026 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -740,7 +740,7 @@ bool ChatHandler::HandleGameObjectAddCommand(const char* args) GameObject* pGameObj = new GameObject; uint32 db_lowGUID = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT); - if(!pGameObj->Create(db_lowGUID, goI->id, map, chr->GetPhaseMaskForSpawn(), x, y, z, o, 0.0f, 0.0f, 0.0f, 0.0f, 0, 1)) + if(!pGameObj->Create(db_lowGUID, goI->id, map, chr->GetPhaseMaskForSpawn(), x, y, z, o, 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY)) { delete pGameObj; return false; diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index d87ef4150..af0767a8f 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -1081,7 +1081,15 @@ void ObjectMgr::LoadGameobjects() data.rotation3 = fields[10].GetFloat(); data.spawntimesecs = fields[11].GetInt32(); data.animprogress = fields[12].GetUInt32(); - data.go_state = fields[13].GetUInt32(); + + uint32 go_state = fields[13].GetUInt32(); + if (go_state >= MAX_GO_STATE) + { + sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with invalid `state` (%u) value, skip",guid,data.id,go_state); + continue; + } + data.go_state = GOState(go_state); + data.spawnMask = fields[14].GetUInt8(); data.phaseMask = fields[15].GetUInt16(); int16 gameEvent = fields[16].GetInt16(); diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 65c0a69d9..939dbcbcb 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -3406,7 +3406,7 @@ void Aura::HandleAuraModStun(bool apply, bool Real) { GameObject* pObj = new GameObject; if(pObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 185584, m_target->GetMap(), m_target->GetPhaseMask(), - m_target->GetPositionX(), m_target->GetPositionY(), m_target->GetPositionZ(), m_target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, 1)) + m_target->GetPositionX(), m_target->GetPositionY(), m_target->GetPositionZ(), m_target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY)) { pObj->SetRespawnTime(GetAuraDuration()/IN_MILISECONDS); pObj->SetSpellId(GetId()); diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 5d56514df..f68cb4b1a 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -793,7 +793,7 @@ void Spell::EffectDummy(uint32 i) // create before death for get proper coordinates if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 179644, map, m_caster->GetPhaseMask(), creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(), - creatureTarget->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, 1) ) + creatureTarget->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY) ) { delete pGameObj; return; @@ -4558,7 +4558,7 @@ void Spell::EffectSummonObjectWild(uint32 i) Map *map = target->GetMap(); if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map, - m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, 1)) + m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY)) { delete pGameObj; return; @@ -4606,7 +4606,7 @@ void Spell::EffectSummonObjectWild(uint32 i) { GameObject* linkedGO = new GameObject; if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map, - m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, 1)) + m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY)) { linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0); linkedGO->SetSpellId(m_spellInfo->Id); @@ -5260,7 +5260,7 @@ void Spell::EffectDuel(uint32 i) m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 , m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 , m_caster->GetPositionZ(), - m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, 1)) + m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY)) { delete pGameObj; return; @@ -5649,7 +5649,7 @@ void Spell::EffectSummonObject(uint32 i) Map *map = m_caster->GetMap(); if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map, - m_caster->GetPhaseMask(), x, y, z, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, 1)) + m_caster->GetPhaseMask(), x, y, z, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY)) { delete pGameObj; return; @@ -6239,7 +6239,7 @@ void Spell::EffectTransmitted(uint32 effIndex) GameObject* pGameObj = new GameObject; if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap, - m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, 1)) + m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY)) { delete pGameObj; return; @@ -6306,7 +6306,7 @@ void Spell::EffectTransmitted(uint32 effIndex) { GameObject* linkedGO = new GameObject; if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap, - m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, 1)) + m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY)) { linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0); linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() ); diff --git a/src/game/Transports.cpp b/src/game/Transports.cpp index 95e0dbcdd..860bdfd40 100644 --- a/src/game/Transports.cpp +++ b/src/game/Transports.cpp @@ -172,7 +172,7 @@ bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z, SetUInt32Value(GAMEOBJECT_DISPLAYID, goinfo->displayId); - SetGoState(1); + SetGoState(GO_STATE_READY); SetGoType(GameobjectTypes(goinfo->type)); SetGoAnimProgress(animprogress); diff --git a/src/game/World.cpp b/src/game/World.cpp index 5ed2c327e..45c5c093c 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -2000,18 +2000,18 @@ void World::ScriptsProcess() CellLock cell_lock(cell, p); cell_lock->Visit(cell_lock, object_checker, *caster->GetMap()); - if ( !door ) + if (!door) { sLog.outError("SCRIPT_COMMAND_OPEN_DOOR failed for gameobject(guid: %u).", step.script->datalong); break; } - if ( door->GetGoType() != GAMEOBJECT_TYPE_DOOR ) + if (door->GetGoType() != GAMEOBJECT_TYPE_DOOR) { sLog.outError("SCRIPT_COMMAND_OPEN_DOOR failed for non-door(GoType: %u).", door->GetGoType()); break; } - if( !door->GetGoState() ) + if (door->GetGoState() != GO_STATE_READY) break; //door already open door->UseDoorOrButton(time_to_close); @@ -2067,7 +2067,7 @@ void World::ScriptsProcess() break; } - if( door->GetGoState() ) + if( door->GetGoState() == GO_STATE_READY ) break; //door already closed door->UseDoorOrButton(time_to_open); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index cd277961d..3be8dae7c 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7714" + #define REVISION_NR "7715" #endif // __REVISION_NR_H__