Ticket #2461: ShipSinkingRefinements.patch
File ShipSinkingRefinements.patch, 5.0 KB (added by , 10 years ago) |
---|
-
binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship.xml
17 17 </Cost> 18 18 <Decay> 19 19 <Inactive/> 20 <SinkingAnim/> 20 <SinkingAnim> 21 <ShipSlowRate>0.01</ShipSlowRate> 22 <ShipSlowAccel>0.0</ShipSlowAccel> 23 </SinkingAnim> 21 24 <DelayTime>0.0</DelayTime> 22 25 <SinkRate>0.5</SinkRate> 23 26 <SinkAccel>7.0</SinkAccel> -
source/simulation2/components/CCmpDecay.cpp
24 24 25 25 #include "ICmpPosition.h" 26 26 #include "ICmpTerrain.h" 27 #include "ICmpWaterManager.h" 27 28 #include "ICmpVisual.h" 28 29 29 30 /** … … 42 43 * 43 44 * Must not be used on network-synchronised entities, unless \<Inactive\> is present. 44 45 */ 46 45 47 class CCmpDecay : public ICmpDecay 46 48 { 47 49 public: … … 53 55 54 56 bool m_Active; 55 57 bool m_ShipSink; 58 float m_ShipSlowRate; 59 float m_ShipSlowAccel; 60 fixed m_ShipSinkDepth; 56 61 float m_DelayTime; 57 62 float m_SinkRate; 58 63 float m_SinkAccel; … … 86 91 "</optional>" 87 92 "<optional>" 88 93 "<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>" 90 98 "</element>" 91 99 "</optional>"; 92 100 } … … 95 103 { 96 104 m_Active = !paramNode.GetChild("Inactive").IsOk(); 97 105 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 } 98 111 m_DelayTime = paramNode.GetChild("DelayTime").ToFixed().ToFloat(); 99 112 m_SinkRate = paramNode.GetChild("SinkRate").ToFixed().ToFloat(); 100 113 m_SinkAccel = paramNode.GetChild("SinkAccel").ToFixed().ToFloat(); … … 141 154 const CMessageInterpolate& msgData = static_cast<const CMessageInterpolate&> (msg); 142 155 143 156 CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle()); 157 CmpPtr<ICmpWaterManager> cmpWaterManager(GetSystemEntity()); 144 158 if (!cmpPosition || !cmpPosition->IsInWorld()) 145 159 { 146 160 // If there's no position (this usually shouldn't happen), destroy the unit immediately … … 180 194 // lacking randomness we'll trick 181 195 m_SinkingAngleX = (pos.X.ToInt_RoundToNearest() % 30 - 15) / 15.0; 182 196 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; 184 200 } 185 201 // probably 0 in both cases but we'll remember it anyway. 186 202 m_InitialXRotation = cmpPosition->GetRotation().X; … … 193 209 { 194 210 float t = m_CurrentTime - m_DelayTime; 195 211 float depth = (m_SinkRate * t) + (m_SinkAccel * t * t); 196 197 212 if (m_ShipSink) 198 213 { 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 } 207 228 if (depth < 0.f) 208 229 depth = 0.f; 209 230 } 210 211 231 cmpPosition->SetHeightOffset(entity_pos_t::FromFloat(-depth)); 212 232 213 233 if (depth > m_TotalSinkDepth)