Ticket #2461: ShipSinkingRefinements.patch

File ShipSinkingRefinements.patch, 5.0 KB (added by Demiguise, 10 years ago)
  • binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship.xml

     
    1717  </Cost>
    1818  <Decay>
    1919    <Inactive/>
    20     <SinkingAnim/>
     20    <SinkingAnim>
     21    <ShipSlowRate>0.01</ShipSlowRate>
     22    <ShipSlowAccel>0.0</ShipSlowAccel>
     23  </SinkingAnim>
    2124    <DelayTime>0.0</DelayTime>
    2225    <SinkRate>0.5</SinkRate>
    2326    <SinkAccel>7.0</SinkAccel>
  • source/simulation2/components/CCmpDecay.cpp

     
    2424
    2525#include "ICmpPosition.h"
    2626#include "ICmpTerrain.h"
     27#include "ICmpWaterManager.h"
    2728#include "ICmpVisual.h"
    2829
    2930/**
     
    4243 *
    4344 * Must not be used on network-synchronised entities, unless \<Inactive\> is present.
    4445 */
     46
    4547class CCmpDecay : public ICmpDecay
    4648{
    4749public:
     
    5355
    5456    bool m_Active;
    5557    bool m_ShipSink;
     58    float m_ShipSlowRate;
     59    float m_ShipSlowAccel;
     60    fixed m_ShipSinkDepth;
    5661    float m_DelayTime;
    5762    float m_SinkRate;
    5863    float m_SinkAccel;
     
    8691            "</optional>"
    8792            "<optional>"
    8893                "<element name='SinkingAnim' a:help='If this element is present, the entity will decay in a ship-like manner'>"
    89                     "<empty/>"
     94                    "<interleave>"
     95                        "<element name='ShipSlowRate'><ref name='nonNegativeDecimal'/></element>"
     96                        "<element name='ShipSlowAccel'><ref name='nonNegativeDecimal'/></element>"
     97                    "</interleave>"
    9098                "</element>"
    9199            "</optional>";
    92100    }
     
    95103    {
    96104        m_Active = !paramNode.GetChild("Inactive").IsOk();
    97105        m_ShipSink = paramNode.GetChild("SinkingAnim").IsOk();
     106        if (m_ShipSink)
     107        {
     108            m_ShipSlowRate = paramNode.GetChild("SinkingAnim").GetChild("ShipSlowRate").ToFixed().ToFloat();
     109            m_ShipSlowAccel = paramNode.GetChild("SinkingAnim").GetChild("ShipSlowAccel").ToFixed().ToFloat();
     110        }
    98111        m_DelayTime = paramNode.GetChild("DelayTime").ToFixed().ToFloat();
    99112        m_SinkRate = paramNode.GetChild("SinkRate").ToFixed().ToFloat();
    100113        m_SinkAccel = paramNode.GetChild("SinkAccel").ToFixed().ToFloat();
     
    141154            const CMessageInterpolate& msgData = static_cast<const CMessageInterpolate&> (msg);
    142155
    143156            CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
     157            CmpPtr<ICmpWaterManager> cmpWaterManager(GetSystemEntity());
    144158            if (!cmpPosition || !cmpPosition->IsInWorld())
    145159            {
    146160                // If there's no position (this usually shouldn't happen), destroy the unit immediately
     
    180194                    // lacking randomness we'll trick
    181195                    m_SinkingAngleX = (pos.X.ToInt_RoundToNearest() % 30 - 15) / 15.0;
    182196                    m_SinkingAngleZ = (pos.Z.ToInt_RoundToNearest() % 30) / 40.0;
    183                     m_TotalSinkDepth += 10.f;
     197
     198                    m_ShipSinkDepth = pos.Y - cmpTerrain->GetGroundLevel(pos.X, pos.Z);
     199                    m_TotalSinkDepth += 10.0f;
    184200                }
    185201                // probably 0 in both cases but we'll remember it anyway.
    186202                m_InitialXRotation = cmpPosition->GetRotation().X;
     
    193209            {
    194210                float t = m_CurrentTime - m_DelayTime;
    195211                float depth = (m_SinkRate * t) + (m_SinkAccel * t * t);
    196 
    197212                if (m_ShipSink)
    198213                {
    199                     // exponential sinking with tilting
    200                     float tilt_time = t > 5.f ? 5.f : t;
    201                     float tiltSink = tilt_time * tilt_time / 5.f;
    202                     entity_pos_t RotX = entity_pos_t::FromFloat(((m_InitialXRotation.ToFloat() * (5.f - tiltSink)) + (m_SinkingAngleX * tiltSink)) / 5.f);
    203                     entity_pos_t RotZ = entity_pos_t::FromFloat(((m_InitialZRotation.ToFloat() * (3.f - tilt_time)) + (m_SinkingAngleZ * tilt_time)) / 3.f);
    204                     cmpPosition->SetXZRotation(RotX,RotZ);
    205                    
    206                     depth = m_SinkRate * (exp(t - 1.f) - 0.54881163609f) + (m_SinkAccel * exp(t - 4.f) - 0.01831563888f);
     214                    CFixedVector3D pos = cmpPosition->GetPosition();
     215                    if (pos.Y > cmpWaterManager->GetWaterLevel(pos.X, pos.Z) - m_ShipSinkDepth)
     216                    { //If moving towards the water's floor use exponential sinking with tilting
     217                        float tilt_time = t > 5.f ? 5.f : t;
     218                        float tiltSink = tilt_time * tilt_time / 5.f;
     219                        entity_pos_t RotX = entity_pos_t::FromFloat(((m_InitialXRotation.ToFloat() * (5.f - tiltSink)) + (m_SinkingAngleX * tiltSink)) / 5.f);
     220                        entity_pos_t RotZ = entity_pos_t::FromFloat(((m_InitialZRotation.ToFloat() * (3.f - tilt_time)) + (m_SinkingAngleZ * tilt_time)) / 3.f);
     221                        cmpPosition->SetXZRotation(RotX,RotZ);
     222                        depth = m_SinkRate * (exp(t - 1.f) - 0.54881163609f) + (m_SinkAccel * exp(t - 4.f) - 0.01831563888f);
     223                    }
     224                    else
     225                    { //Else use the slower sink
     226                        depth = (m_ShipSlowRate * t) + (m_ShipSlowAccel * t * t) + m_ShipSinkDepth.ToFloat();
     227                    }
    207228                    if (depth < 0.f)
    208229                        depth = 0.f;
    209230                }
    210                
    211231                cmpPosition->SetHeightOffset(entity_pos_t::FromFloat(-depth));
    212232
    213233                if (depth > m_TotalSinkDepth)