diff options
| author | Shauren <shauren.trinity@gmail.com> | 2014-09-29 20:10:08 +0200 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2014-09-29 20:10:08 +0200 |
| commit | 83668e8f8fcfc7a1e4c0904d29818e6f9a976389 (patch) | |
| tree | d19f9ec408e7acaa11a323d85c3fb303c91e36c8 /src/server/game/Entities/GameObject | |
| parent | 977b5f41e9bce2a6e3b8ae182b43ebc312b0f78f (diff) | |
Core/GameObjects: Implemented new gameobject type 11 (transport) states, fixes elevators in orgrimmar as well as all stoppable elevators
Closes #10019
Closes #12747
Closes #13194
Diffstat (limited to 'src/server/game/Entities/GameObject')
| -rw-r--r-- | src/server/game/Entities/GameObject/GameObject.cpp | 109 | ||||
| -rw-r--r-- | src/server/game/Entities/GameObject/GameObject.h | 17 |
2 files changed, 116 insertions, 10 deletions
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index d134740d1cd..864524373f7 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -69,6 +69,8 @@ GameObject::~GameObject() { delete m_AI; delete m_model; + if (m_goInfo->type == GAMEOBJECT_TYPE_TRANSPORT) + delete m_goValue.Transport.StopFrames; //if (m_uint32Values) // field array can be not exist if GameOBject not loaded // CleanupsBeforeDelete(); } @@ -239,13 +241,29 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 /*phase SetUInt32Value(GAMEOBJECT_PARENTROTATION, m_goInfo->building.destructibleData); break; case GAMEOBJECT_TYPE_TRANSPORT: - SetUInt32Value(GAMEOBJECT_LEVEL, goinfo->transport.pause); - SetGoState(goinfo->transport.startOpen ? GO_STATE_ACTIVE : GO_STATE_READY); - SetGoAnimProgress(animprogress); - m_goValue.Transport.PathProgress = 0; + { m_goValue.Transport.AnimationInfo = sTransportMgr->GetTransportAnimInfo(goinfo->entry); + m_goValue.Transport.PathProgress = (getMSTime() / GetTransportPeriod()); + m_goValue.Transport.PathProgress *= GetTransportPeriod(); m_goValue.Transport.CurrentSeg = 0; + m_goValue.Transport.StateUpdateTimer = 0; + m_goValue.Transport.StopFrames = new std::vector<uint32>(); + if (goinfo->transport.stopFrame1 > 0) + m_goValue.Transport.StopFrames->push_back(goinfo->transport.stopFrame1); + if (goinfo->transport.stopFrame2 > 0) + m_goValue.Transport.StopFrames->push_back(goinfo->transport.stopFrame3); + if (goinfo->transport.stopFrame3 > 0) + m_goValue.Transport.StopFrames->push_back(goinfo->transport.stopFrame3); + if (goinfo->transport.stopFrame4 > 0) + m_goValue.Transport.StopFrames->push_back(goinfo->transport.stopFrame4); + if (goinfo->transport.startOpen) + SetTransportState(GO_STATE_TRANSPORT_STOPPED, goinfo->transport.startOpen - 1); + else + SetTransportState(GO_STATE_TRANSPORT_ACTIVE); + + SetGoAnimProgress(animprogress); break; + } case GAMEOBJECT_TYPE_FISHINGNODE: SetGoAnimProgress(0); break; @@ -309,11 +327,11 @@ void GameObject::Update(uint32 diff) if (!m_goValue.Transport.AnimationInfo) break; - if (GetGoState() == GO_STATE_READY) + if (GetGoState() == GO_STATE_TRANSPORT_ACTIVE) { m_goValue.Transport.PathProgress += diff; /* TODO: Fix movement in unloaded grid - currently GO will just disappear - uint32 timer = m_goValue.Transport.PathProgress % m_goValue.Transport.AnimationInfo->TotalTime; + uint32 timer = m_goValue.Transport.PathProgress % GetTransportPeriod(); TransportAnimationEntry const* node = m_goValue.Transport.AnimationInfo->GetAnimNode(timer); if (node && m_goValue.Transport.CurrentSeg != node->TimeSeg) { @@ -333,6 +351,18 @@ void GameObject::Update(uint32 diff) GetMap()->GameObjectRelocation(this, pos.x, pos.y, pos.z, GetOrientation()); } */ + + if (!m_goValue.Transport.StopFrames->empty()) + { + uint32 visualStateBefore = (m_goValue.Transport.StateUpdateTimer / 20000) & 1; + m_goValue.Transport.StateUpdateTimer += diff; + uint32 visualStateAfter = (m_goValue.Transport.StateUpdateTimer / 20000) & 1; + if (visualStateBefore != visualStateAfter) + { + ForceValuesUpdateAtIndex(GAMEOBJECT_LEVEL); + ForceValuesUpdateAtIndex(GAMEOBJECT_BYTES_1); + } + } } break; } @@ -934,7 +964,7 @@ bool GameObject::IsDynTransport() const if (!gInfo) return false; - return gInfo->type == GAMEOBJECT_TYPE_MO_TRANSPORT || (gInfo->type == GAMEOBJECT_TYPE_TRANSPORT && !gInfo->transport.pause); + return gInfo->type == GAMEOBJECT_TYPE_MO_TRANSPORT || (gInfo->type == GAMEOBJECT_TYPE_TRANSPORT && m_goValue.Transport.StopFrames->empty()); } bool GameObject::IsDestructibleBuilding() const @@ -2079,6 +2109,38 @@ void GameObject::SetGoState(GOState state) } } +uint32 GameObject::GetTransportPeriod() const +{ + ASSERT(GetGOInfo()->type == GAMEOBJECT_TYPE_TRANSPORT); + if (m_goValue.Transport.AnimationInfo) + return m_goValue.Transport.AnimationInfo->TotalTime; + + // return something that will nicely divide for GAMEOBJECT_DYNAMIC value calculation + return m_goValue.Transport.PathProgress; +} + +void GameObject::SetTransportState(GOState state, uint32 stopFrame /*= 0*/) +{ + if (GetGoState() == state) + return; + + ASSERT(GetGOInfo()->type == GAMEOBJECT_TYPE_TRANSPORT); + ASSERT(state >= GO_STATE_TRANSPORT_ACTIVE); + if (state == GO_STATE_TRANSPORT_ACTIVE) + { + m_goValue.Transport.StateUpdateTimer = 0; + m_goValue.Transport.PathProgress = getMSTime() + m_goValue.Transport.StopFrames->at(GetGoState() - GO_STATE_TRANSPORT_STOPPED); + SetGoState(GO_STATE_TRANSPORT_ACTIVE); + } + else + { + ASSERT(state < GO_STATE_TRANSPORT_STOPPED + MAX_GO_STATE_TRANSPORT_STOP_FRAMES); + ASSERT(stopFrame < m_goValue.Transport.StopFrames->size()); + m_goValue.Transport.PathProgress = getMSTime() + m_goValue.Transport.StopFrames->at(stopFrame); + SetGoState(GOState(GO_STATE_TRANSPORT_STOPPED + stopFrame)); + } +} + void GameObject::SetDisplayId(uint32 displayid) { SetUInt32Value(GAMEOBJECT_DISPLAYID, displayid); @@ -2175,6 +2237,7 @@ void GameObject::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* t if (!target) return; + bool isStoppableTransport = GetGoType() == GAMEOBJECT_TYPE_TRANSPORT && !m_goValue.Transport.StopFrames->empty(); bool forcedFlags = GetGoType() == GAMEOBJECT_TYPE_CHEST && GetGOInfo()->chest.groupLootRules && HasLootRecipient(); bool targetIsGM = target->IsGameMaster(); @@ -2217,9 +2280,18 @@ void GameObject::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* t if (ActivateToQuest(target)) dynFlags |= GO_DYNFLAG_LO_SPARKLE; break; + case GAMEOBJECT_TYPE_TRANSPORT: + { + float timer = float(m_goValue.Transport.PathProgress % GetTransportPeriod()); + pathProgress = int16(timer / float(GetTransportPeriod()) * 65535.0f); + break; + } case GAMEOBJECT_TYPE_MO_TRANSPORT: - pathProgress = int16(float(m_goValue.Transport.PathProgress) / float(GetUInt32Value(GAMEOBJECT_LEVEL)) * 65535.0f); + { + float timer = float(m_goValue.Transport.PathProgress % GetUInt32Value(GAMEOBJECT_LEVEL)); + pathProgress = int16(timer / float(GetUInt32Value(GAMEOBJECT_LEVEL)) * 65535.0f); break; + } default: break; } @@ -2236,6 +2308,27 @@ void GameObject::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* t fieldBuffer << flags; } + else if (index == GAMEOBJECT_LEVEL) + { + if (isStoppableTransport) + fieldBuffer << uint32(m_goValue.Transport.PathProgress); + else + fieldBuffer << m_uint32Values[index]; + } + else if (index == GAMEOBJECT_BYTES_1) + { + uint32 bytes1 = m_uint32Values[index]; + if (isStoppableTransport && GetGoState() == GO_STATE_TRANSPORT_ACTIVE) + { + if ((m_goValue.Transport.StateUpdateTimer / 20000) & 1) + { + bytes1 &= 0xFFFFFF00; + bytes1 |= GO_STATE_TRANSPORT_STOPPED; + } + } + + fieldBuffer << bytes1; + } else fieldBuffer << m_uint32Values[index]; // other cases } diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index 4d945b54e6b..bb6a862ad4a 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -193,11 +193,17 @@ struct GameObjectTemplate //11 GAMEOBJECT_TYPE_TRANSPORT struct { - uint32 pause; //0 + int32 stopFrame1; //0 uint32 startOpen; //1 uint32 autoCloseTime; //2 secs till autoclose = autoCloseTime / 0x10000 uint32 pause1EventID; //3 uint32 pause2EventID; //4 + uint32 mapId; //5 + int32 stopFrame2; //6 + uint32 unknown; + int32 stopFrame3; //8 + uint32 unknown2; + int32 stopFrame4; //10 } transport; //12 GAMEOBJECT_TYPE_AREADAMAGE struct @@ -552,6 +558,8 @@ union GameObjectValue uint32 PathProgress; TransportAnimation const* AnimationInfo; uint32 CurrentSeg; + std::vector<uint32>* StopFrames; + uint32 StateUpdateTimer; } Transport; //25 GAMEOBJECT_TYPE_FISHINGHOLE struct @@ -582,10 +590,13 @@ 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) + GO_STATE_ACTIVE_ALTERNATIVE = 2, // show in world as used in alt way and not reset (closed door open by cannon fire) + GO_STATE_TRANSPORT_ACTIVE = 24, + GO_STATE_TRANSPORT_STOPPED = 25 }; #define MAX_GO_STATE 3 +#define MAX_GO_STATE_TRANSPORT_STOP_FRAMES 9 // from `gameobject` struct GameObjectData @@ -720,6 +731,8 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map void SetGoType(GameobjectTypes type) { SetByteValue(GAMEOBJECT_BYTES_1, 1, type); } GOState GetGoState() const { return GOState(GetByteValue(GAMEOBJECT_BYTES_1, 0)); } void SetGoState(GOState state); + uint32 GetTransportPeriod() const; + void SetTransportState(GOState state, uint32 stopFrame = 0); uint8 GetGoArtKit() const { return GetByteValue(GAMEOBJECT_BYTES_1, 2); } void SetGoArtKit(uint8 artkit); uint8 GetGoAnimProgress() const { return GetByteValue(GAMEOBJECT_BYTES_1, 3); } |
