mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-08-15 14:43:32 -07:00
Add a random chance for a decay sinking event to occur.
Adds a 1/125 chance for a corpse to undergo a decay movement in a given frame. This allows a probability passed from the template to determine the sinking behavior of the entity. Fixes #7548
This commit is contained in:
parent
90505c29ee
commit
f8e0a78d6d
8 changed files with 55 additions and 18 deletions
|
|
@ -3,6 +3,7 @@
|
|||
<Decay>
|
||||
<Active>true</Active>
|
||||
<SinkingAnim>false</SinkingAnim>
|
||||
<SinkProb>1.0</SinkProb>
|
||||
<DelayTime>6</DelayTime>
|
||||
<SinkRate>10000</SinkRate>
|
||||
<SinkAccel>0</SinkAccel>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
<Decay>
|
||||
<Active>true</Active>
|
||||
<SinkingAnim>false</SinkingAnim>
|
||||
<SinkProb>1.0</SinkProb>
|
||||
<DelayTime>0.5</DelayTime>
|
||||
<SinkRate>10000</SinkRate>
|
||||
<SinkAccel>0</SinkAccel>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
<Decay>
|
||||
<Active>false</Active>
|
||||
<SinkingAnim>false</SinkingAnim>
|
||||
<SinkProb>0.25</SinkProb>
|
||||
<DelayTime>15.0</DelayTime>
|
||||
<SinkRate>0.2</SinkRate>
|
||||
<SinkAccel>0</SinkAccel>
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
<Decay>
|
||||
<Active>false</Active>
|
||||
<SinkingAnim>false</SinkingAnim>
|
||||
<SinkProb>1.0</SinkProb>
|
||||
<DelayTime>0.0</DelayTime>
|
||||
<SinkRate>3.0</SinkRate>
|
||||
<SinkAccel>9.8</SinkAccel>
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
<Decay>
|
||||
<Active>false</Active>
|
||||
<SinkingAnim>false</SinkingAnim>
|
||||
<SinkProb>0.01</SinkProb>
|
||||
<DelayTime>30.0</DelayTime>
|
||||
<SinkRate>0.01</SinkRate>
|
||||
<SinkAccel>0.0</SinkAccel>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
<Entity parent="template_unit">
|
||||
<Decay>
|
||||
<SinkingAnim>true</SinkingAnim>
|
||||
<SinkProb>1.0</SinkProb>
|
||||
<DelayTime>0.0</DelayTime>
|
||||
<SinkRate>0.5</SinkRate>
|
||||
<SinkAccel>7.0</SinkAccel>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
</Cost>
|
||||
<Decay>
|
||||
<DelayTime>0.0</DelayTime>
|
||||
<SinkProb>1.0</SinkProb>
|
||||
<SinkRate>0.0</SinkRate>
|
||||
<SinkAccel>2.0</SinkAccel>
|
||||
</Decay>
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <optional>
|
||||
#include <random>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
|
|
@ -65,6 +67,13 @@ public:
|
|||
|
||||
bool m_Active;
|
||||
bool m_ShipSink;
|
||||
bool m_Stochastic;
|
||||
|
||||
std::optional<std::minstd_rand> m_Generator;
|
||||
std::negative_binomial_distribution<> m_Distribution{ 6, 0.032 };
|
||||
std::geometric_distribution<>::result_type m_NextSink;
|
||||
|
||||
float m_SinkProb;
|
||||
float m_DelayTime;
|
||||
float m_SinkRate;
|
||||
float m_SinkAccel;
|
||||
|
|
@ -88,6 +97,9 @@ public:
|
|||
"<element name='SinkingAnim' a:help='If true, the entity will decay in a ship-like manner'>"
|
||||
"<data type='boolean'/>"
|
||||
"</element>"
|
||||
"<element name='SinkProb' a:help='The entity decays according to the supplied probability each frame.'>"
|
||||
"<ref name='nonNegativeDecimal'/>"
|
||||
"</element>"
|
||||
"<element name='DelayTime' a:help='Time to wait before starting to sink, in seconds'>"
|
||||
"<ref name='nonNegativeDecimal'/>"
|
||||
"</element>"
|
||||
|
|
@ -103,6 +115,7 @@ public:
|
|||
{
|
||||
m_Active = paramNode.GetChild("Active").ToBool();
|
||||
m_ShipSink = paramNode.GetChild("SinkingAnim").ToBool();
|
||||
m_SinkProb = paramNode.GetChild("SinkProb").ToFixed().ToFloat();
|
||||
m_DelayTime = paramNode.GetChild("DelayTime").ToFixed().ToFloat();
|
||||
m_SinkRate = paramNode.GetChild("SinkRate").ToFixed().ToFloat();
|
||||
m_SinkAccel = paramNode.GetChild("SinkAccel").ToFixed().ToFloat();
|
||||
|
|
@ -110,6 +123,11 @@ public:
|
|||
m_CurrentTime = 0.f;
|
||||
m_TotalSinkDepth = -1.f;
|
||||
|
||||
m_SinkProb < 1.f ? m_Stochastic = true : m_Stochastic = false;
|
||||
|
||||
std::negative_binomial_distribution<int>::param_type new_params(6, m_SinkProb*4);
|
||||
m_Distribution.param(new_params);
|
||||
|
||||
// Detect unsafe misconfiguration
|
||||
if (m_Active && !ENTITY_IS_LOCAL(GetEntityId()))
|
||||
{
|
||||
|
|
@ -175,6 +193,13 @@ public:
|
|||
|
||||
CFixedVector3D pos = cmpPosition->GetPosition();
|
||||
|
||||
//Use the entities position upon decay start to vary the pseudorandom seed.
|
||||
if (!m_Generator.has_value())
|
||||
{
|
||||
m_Generator.emplace(pos.X.ToInt_RoundToNearest() * pos.Z.ToInt_RoundToNearest());
|
||||
m_NextSink = m_Distribution(m_Generator.value());
|
||||
}
|
||||
|
||||
CmpPtr<ICmpTerrain> cmpTerrain(GetSystemEntity());
|
||||
if (cmpTerrain)
|
||||
{
|
||||
|
|
@ -199,27 +224,32 @@ public:
|
|||
|
||||
if (m_CurrentTime >= m_DelayTime)
|
||||
{
|
||||
float t = m_CurrentTime - m_DelayTime;
|
||||
float depth = (m_SinkRate * t) + (m_SinkAccel * t * t);
|
||||
|
||||
if (m_ShipSink)
|
||||
//If the entity should sink stochastically, use the negative binomial distribution to see if it should sink each frame.
|
||||
if ((m_Stochastic && (m_NextSink-- == 0)) || !m_Stochastic)
|
||||
{
|
||||
// exponential sinking with tilting
|
||||
float tilt_time = t > 5.f ? 5.f : t;
|
||||
float tiltSink = tilt_time * tilt_time / 5.f;
|
||||
entity_pos_t RotX = entity_pos_t::FromFloat(((m_InitialXRotation.ToFloat() * (5.f - tiltSink)) + (m_SinkingAngleX * tiltSink)) / 5.f);
|
||||
entity_pos_t RotZ = entity_pos_t::FromFloat(((m_InitialZRotation.ToFloat() * (3.f - tilt_time)) + (m_SinkingAngleZ * tilt_time)) / 3.f);
|
||||
cmpPosition->SetXZRotation(RotX,RotZ);
|
||||
m_NextSink = m_Distribution(m_Generator.value());
|
||||
float t = m_CurrentTime - m_DelayTime;
|
||||
float depth = (m_SinkRate * t) + (m_SinkAccel * t * t);
|
||||
|
||||
depth = m_SinkRate * (exp(t - 1.f) - 0.54881163609f) + (m_SinkAccel * exp(t - 4.f) - 0.01831563888f);
|
||||
if (depth < 0.f)
|
||||
depth = 0.f;
|
||||
if (m_ShipSink)
|
||||
{
|
||||
// exponential sinking with tilting
|
||||
float tilt_time = t > 5.f ? 5.f : t;
|
||||
float tiltSink = tilt_time * tilt_time / 5.f;
|
||||
entity_pos_t RotX = entity_pos_t::FromFloat(((m_InitialXRotation.ToFloat() * (5.f - tiltSink)) + (m_SinkingAngleX * tiltSink)) / 5.f);
|
||||
entity_pos_t RotZ = entity_pos_t::FromFloat(((m_InitialZRotation.ToFloat() * (3.f - tilt_time)) + (m_SinkingAngleZ * tilt_time)) / 3.f);
|
||||
cmpPosition->SetXZRotation(RotX,RotZ);
|
||||
|
||||
depth = m_SinkRate * (exp(t - 1.f) - 0.54881163609f) + (m_SinkAccel * exp(t - 4.f) - 0.01831563888f);
|
||||
if (depth < 0.f)
|
||||
depth = 0.f;
|
||||
}
|
||||
|
||||
cmpPosition->SetHeightOffset(entity_pos_t::FromFloat(-depth));
|
||||
|
||||
if (depth > m_TotalSinkDepth)
|
||||
GetSimContext().GetComponentManager().DestroyComponentsSoon(GetEntityId());
|
||||
}
|
||||
|
||||
cmpPosition->SetHeightOffset(entity_pos_t::FromFloat(-depth));
|
||||
|
||||
if (depth > m_TotalSinkDepth)
|
||||
GetSimContext().GetComponentManager().DestroyComponentsSoon(GetEntityId());
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
|||
Loading…
Reference in a new issue