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
This commit is contained in:
Shauren
2014-09-29 20:10:08 +02:00
parent 977b5f41e9
commit 83668e8f8f
6 changed files with 137 additions and 26 deletions
@@ -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_MO_TRANSPORT:
pathProgress = int16(float(m_goValue.Transport.PathProgress) / float(GetUInt32Value(GAMEOBJECT_LEVEL)) * 65535.0f);
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:
{
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
}