Ticket #1921: ShipSinking.patch

File ShipSinking.patch, 3.2 KB (added by wraitii, 11 years ago)
  • binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship.xml

     
    1212  </Cost>
    1313  <Decay>
    1414    <Inactive/>
     15    <SinkingAnim/>
    1516    <DelayTime>0.0</DelayTime>
    1617    <SinkRate>0.5</SinkRate>
    1718    <SinkAccel>7.0</SinkAccel>
  • source/simulation2/components/CCmpDecay.cpp

     
    5353    DEFAULT_COMPONENT_ALLOCATOR(Decay)
    5454
    5555    bool m_Active;
     56    bool m_ShipSink;
    5657    float m_DelayTime;
    5758    float m_SinkRate;
    5859    float m_SinkAccel;
    5960
     61    entity_pos_t m_InitialXRotation;
     62    entity_pos_t m_InitialZRotation;
     63
    6064    float m_CurrentTime;
    6165    float m_TotalSinkDepth; // distance we need to sink (derived from bounding box), or -1 if undetermined
    6266
     
    7680                "<element name='Inactive' a:help='If this element is present, the entity will not do any decaying'>"
    7781                    "<empty/>"
    7882                "</element>"
     83            "</optional>"
     84            "<optional>"
     85                "<element name='SinkingAnim' a:help='If this element is present, the entity will decay in a ship-like manner'>"
     86                    "<empty/>"
     87                "</element>"
    7988            "</optional>";
    8089    }
    8190
    8291    virtual void Init(const CParamNode& paramNode)
    8392    {
    8493        m_Active = !paramNode.GetChild("Inactive").IsOk();
     94        m_ShipSink = paramNode.GetChild("SinkingAnim").IsOk();
    8595        m_DelayTime = paramNode.GetChild("DelayTime").ToFixed().ToFloat();
    8696        m_SinkRate = paramNode.GetChild("SinkRate").ToFixed().ToFloat();
    8797        m_SinkAccel = paramNode.GetChild("SinkAccel").ToFixed().ToFloat();
     
    155165                    fixed ground = cmpTerrain->GetGroundLevel(pos.X, pos.Z);
    156166                    m_TotalSinkDepth += std::max(0.f, (pos.Y - ground).ToFloat());
    157167                }
     168
     169                // Sink it further down if it sinks like a ship, as it will rotate.
     170                if (m_ShipSink)
     171                    m_TotalSinkDepth += 10.0f;
     172
     173                // probably 0 in both cases but we'll remember it anyway.
     174                m_InitialXRotation = cmpPosition->GetRotation().X;
     175                m_InitialZRotation = cmpPosition->GetRotation().Z;
    158176            }
    159177
    160178            m_CurrentTime += msgData.deltaSimTime;
    161179
    162             if (m_CurrentTime > m_DelayTime)
     180            if (m_CurrentTime >= m_DelayTime)
    163181            {
    164182                float t = m_CurrentTime - m_DelayTime;
    165183                float depth = (m_SinkRate * t) + (m_SinkAccel * t * t);
    166184
     185                if (m_ShipSink)
     186                {
     187                    // exponential sinking with tilting.
     188                    float tilt_time = t > 5 ? 5 : t;
     189                    float tiltSink = (tilt_time/5)*(tilt_time/5)*5;
     190                    entity_pos_t RotX = entity_pos_t::FromFloat(((m_InitialXRotation.ToFloat() * (5 - tiltSink)) + (1.5 * tiltSink))/5);
     191                    entity_pos_t RotZ = entity_pos_t::FromFloat(((m_InitialZRotation.ToFloat() * (3 - tilt_time)) + (-0.3 * tilt_time))/3);
     192                    cmpPosition->SetXZRotation(RotX,RotZ);
     193                   
     194                    depth = m_SinkRate * (exp(t-1)-exp(-0.6)) + (m_SinkAccel * exp(t-4)-exp(-4));
     195                    if (depth < 0)
     196                        depth = 0;
     197                }
     198               
    167199                cmpPosition->SetHeightOffset(entity_pos_t::FromFloat(-depth));
    168200
    169201                if (depth > m_TotalSinkDepth)