virtual void JumpTo(entity_pos_t x, entity_pos_t z) { m_LastX = m_PrevX = m_X = x; m_LastZ = m_PrevZ = m_Z = z; m_InWorld = true; UpdateXZRotation(); m_LastInterpolatedRotX = m_InterpolatedRotX; m_LastInterpolatedRotZ = m_InterpolatedRotZ; AdvertisePositionChanges(); }
virtual void SetXZRotation(entity_angle_t x, entity_angle_t z) { m_RotX = x; m_RotZ = z; if (m_InWorld) { UpdateXZRotation(); m_LastInterpolatedRotX = m_InterpolatedRotX; m_LastInterpolatedRotZ = m_InterpolatedRotZ; } }
virtual void SetYRotation(entity_angle_t y) { m_RotY = y; m_InterpolatedRotY = m_RotY.ToFloat(); if (m_InWorld) { UpdateXZRotation(); m_LastInterpolatedRotX = m_InterpolatedRotX; m_LastInterpolatedRotZ = m_InterpolatedRotZ; } AdvertisePositionChanges(); }
virtual void SetYRotation(entity_angle_t y) { if (m_TurretParent != INVALID_ENTITY) { CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), m_TurretParent); if (cmpPosition) y -= cmpPosition->GetRotation().Y; } m_RotY = y; m_InterpolatedRotY = m_RotY.ToFloat(); if (m_InWorld) { UpdateXZRotation(); m_LastInterpolatedRotX = m_InterpolatedRotX; m_LastInterpolatedRotZ = m_InterpolatedRotZ; } AdvertisePositionChanges(); UpdateMessageSubscriptions(); }
virtual void Deserialize(const CParamNode& paramNode, IDeserializer& deserialize) { Init(paramNode); deserialize.Bool("in world", m_InWorld); if (m_InWorld) { deserialize.NumberFixed_Unbounded("x", m_X); deserialize.NumberFixed_Unbounded("y", m_Y); deserialize.NumberFixed_Unbounded("z", m_Z); deserialize.NumberFixed_Unbounded("last x", m_LastX); deserialize.NumberFixed_Unbounded("last y diff", m_LastYDifference); deserialize.NumberFixed_Unbounded("last z", m_LastZ); } deserialize.NumberI32_Unbounded("territory", m_Territory); deserialize.NumberFixed_Unbounded("rot x", m_RotX); deserialize.NumberFixed_Unbounded("rot y", m_RotY); deserialize.NumberFixed_Unbounded("rot z", m_RotZ); deserialize.NumberFixed_Unbounded("altitude", m_Y); deserialize.Bool("relative", m_RelativeToGround); deserialize.Bool("floating", m_Floating); deserialize.NumberFixed_Unbounded("constructionprogress", m_ConstructionProgress); // TODO: should there be range checks on all these values? m_InterpolatedRotY = m_RotY.ToFloat(); deserialize.NumberU32_Unbounded("turret parent", m_TurretParent); if (m_TurretParent != INVALID_ENTITY) { deserialize.NumberFixed_Unbounded("x", m_TurretPosition.X); deserialize.NumberFixed_Unbounded("y", m_TurretPosition.Y); deserialize.NumberFixed_Unbounded("z", m_TurretPosition.Z); } if (m_InWorld) UpdateXZRotation(); UpdateMessageSubscriptions(); }
virtual void Deserialize(const CParamNode& paramNode, IDeserializer& deserialize) { Init(paramNode); deserialize.Bool("in world", m_InWorld); if (m_InWorld) { deserialize.NumberFixed_Unbounded("x", m_X); deserialize.NumberFixed_Unbounded("z", m_Z); deserialize.NumberFixed_Unbounded("last x", m_LastX); deserialize.NumberFixed_Unbounded("last z", m_LastZ); } deserialize.NumberFixed_Unbounded("rot x", m_RotX); deserialize.NumberFixed_Unbounded("rot y", m_RotY); deserialize.NumberFixed_Unbounded("rot z", m_RotZ); deserialize.NumberFixed_Unbounded("altitude", m_YOffset); deserialize.Bool("relative", m_RelativeToGround); // TODO: should there be range checks on all these values? m_InterpolatedRotY = m_RotY.ToFloat(); if (m_InWorld) UpdateXZRotation(); }
virtual void HandleMessage(const CMessage& msg, bool UNUSED(global)) { switch (msg.GetType()) { case MT_Interpolate: { PROFILE("Position::Interpolate"); const CMessageInterpolate& msgData = static_cast<const CMessageInterpolate&> (msg); float rotY = m_RotY.ToFloat(); if (rotY != m_InterpolatedRotY) { float delta = rotY - m_InterpolatedRotY; // Wrap delta to -M_PI..M_PI delta = fmodf(delta + (float)M_PI, 2*(float)M_PI); // range -2PI..2PI if (delta < 0) delta += 2*(float)M_PI; // range 0..2PI delta -= (float)M_PI; // range -M_PI..M_PI // Clamp to max rate float deltaClamped = clamp(delta, -m_RotYSpeed*msgData.deltaSimTime, +m_RotYSpeed*msgData.deltaSimTime); // Calculate new orientation, in a peculiar way in order to make sure the // result gets close to m_orientation (rather than being n*2*M_PI out) m_InterpolatedRotY = rotY + deltaClamped - delta; // update the visual XZ rotation if (m_InWorld) { m_LastInterpolatedRotX = m_InterpolatedRotX; m_LastInterpolatedRotZ = m_InterpolatedRotZ; UpdateXZRotation(); } UpdateMessageSubscriptions(); } break; } case MT_TurnStart: { m_LastInterpolatedRotX = m_InterpolatedRotX; m_LastInterpolatedRotZ = m_InterpolatedRotZ; if (m_InWorld && (m_LastX != m_X || m_LastZ != m_Z)) UpdateXZRotation(); // Store the positions from the turn before m_PrevX = m_LastX; m_PrevZ = m_LastZ; m_LastX = m_X; m_LastZ = m_Z; m_LastYDifference = entity_pos_t::Zero(); // warn when a position change also causes a territory change under the entity if (m_InWorld) { player_id_t newTerritory; CmpPtr<ICmpTerritoryManager> cmpTerritoryManager(GetSystemEntity()); if (cmpTerritoryManager) newTerritory = cmpTerritoryManager->GetOwner(m_X, m_Z); else newTerritory = INVALID_PLAYER; if (newTerritory != m_Territory) { m_Territory = newTerritory; CMessageTerritoryPositionChanged msg(GetEntityId(), m_Territory); GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); } } else if (m_Territory != INVALID_PLAYER) { m_Territory = INVALID_PLAYER; CMessageTerritoryPositionChanged msg(GetEntityId(), m_Territory); GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); } break; } case MT_TerrainChanged: case MT_WaterChanged: { AdvertiseInterpolatedPositionChanges(); break; } case MT_Deserialized: { Deserialized(); break; } } }
virtual void HandleMessage(const CMessage& msg, bool UNUSED(global)) { switch (msg.GetType()) { case MT_Interpolate: { const CMessageInterpolate& msgData = static_cast<const CMessageInterpolate&> (msg); float rotY = m_RotY.ToFloat(); if (rotY != m_InterpolatedRotY) { float delta = rotY - m_InterpolatedRotY; // Wrap delta to -M_PI..M_PI delta = fmodf(delta + (float)M_PI, 2*(float)M_PI); // range -2PI..2PI if (delta < 0) delta += 2*(float)M_PI; // range 0..2PI delta -= (float)M_PI; // range -M_PI..M_PI // Clamp to max rate float deltaClamped = clamp(delta, -m_RotYSpeed*msgData.deltaSimTime, +m_RotYSpeed*msgData.deltaSimTime); // Calculate new orientation, in a peculiar way in order to make sure the // result gets close to m_orientation (rather than being n*2*M_PI out) m_InterpolatedRotY = rotY + deltaClamped - delta; // update the visual XZ rotation if (m_InWorld) { m_LastInterpolatedRotX = m_InterpolatedRotX; m_LastInterpolatedRotZ = m_InterpolatedRotZ; UpdateXZRotation(); } } if (m_InWorld && m_NeedInitialXZRotation) { // the terrain probably wasn't loaded last time we tried, so update the XZ rotation without interpolation UpdateXZRotation(); m_LastInterpolatedRotX = m_InterpolatedRotX; m_LastInterpolatedRotZ = m_InterpolatedRotZ; } break; } case MT_TurnStart: { m_LastInterpolatedRotX = m_InterpolatedRotX; m_LastInterpolatedRotZ = m_InterpolatedRotZ; if (m_InWorld && (m_LastX != m_X || m_LastZ != m_Z)) UpdateXZRotation(); // Store the positions from the turn before m_PrevX = m_LastX; m_PrevZ = m_LastZ; m_LastX = m_X; m_LastZ = m_Z; break; } } };