BleedingIndicator.c
//! indicator wrapper for a specific bleeding source.
class BleedingIndicator extends Managed
{
protected bool m_Initialized;
protected bool m_Terminating = false; //doesn't spawn more drops and ends when the last one does
protected bool m_EndNow = false;
protected bool m_IsRunning = false;
protected int m_DropSpawnsQueued;
protected int m_ActiveDropsCount;
protected int m_Severity;
protected int m_SourceID; //pairs this with the 'BleedingSource' bit/ID
protected GameplayEffectsDataBleeding m_ParentMetaData;
protected array<float> m_DropProbabilityArray;
protected float m_AverageFrequency; //average drops per interval. NOT changeable on the fly, just a helper value!
protected float m_SequenceTick;
protected float m_SequenceDuration;
protected float m_TimeElapsedTotal;
protected float m_TimeElapsedSequence;
protected float m_LastDropSpawnTime; //relative to the TOTAL time, not the sequence!
protected float m_DropSpawnMinDelay;
protected float m_DropSpawnMaxDelay;
protected int m_CurrentDropProbabilityStep;
protected int m_DropProbabilityRollsCount;
protected vector m_BasePosition;
ref set<ref BleedingIndicatorDropData> m_ActiveDrops;
ref set<int> m_CleanupQueue;
void BleedingIndicator(int source_ID, int severity, GameplayEffectsDataBleeding parent)
{
m_Initialized = false;
m_SourceID = source_ID;
m_Severity = severity;
m_ParentMetaData = parent;
m_CurrentDropProbabilityStep = 0;
m_ActiveDrops = new set<ref BleedingIndicatorDropData>;
m_CleanupQueue = new set<int>;
m_DropProbabilityArray = m_ParentMetaData.GetProbabilities(m_Severity);
m_DropProbabilityRollsCount = m_DropProbabilityArray.Count();
switch (m_Severity)
{
case BleedingIndicationConstants.INDICATOR_SEVERITY_LOW:
{
m_SequenceDuration = BleedingIndicationConstants.SEQUENCE_DURATION_LOW;
m_AverageFrequency = BleedingIndicationConstants.SEQUENCE_DROP_AVERAGE_LOW;
m_DropSpawnMinDelay = BleedingIndicationConstants.SEQUENCE_DROP_DELAY_MIN_LOW;
m_DropSpawnMaxDelay = BleedingIndicationConstants.SEQUENCE_DROP_DELAY_MAX_LOW;
break;
}
case BleedingIndicationConstants.INDICATOR_SEVERITY_MEDIUM:
{
m_SequenceDuration = BleedingIndicationConstants.SEQUENCE_DURATION_MEDIUM;
m_AverageFrequency = BleedingIndicationConstants.SEQUENCE_DROP_AVERAGE_MEDIUM;
m_DropSpawnMinDelay = BleedingIndicationConstants.SEQUENCE_DROP_DELAY_MIN_MEDIUM;
m_DropSpawnMaxDelay = BleedingIndicationConstants.SEQUENCE_DROP_DELAY_MAX_MEDIUM;
break;
}
case BleedingIndicationConstants.INDICATOR_SEVERITY_HIGH:
{
m_SequenceDuration = BleedingIndicationConstants.SEQUENCE_DURATION_HIGH;
m_AverageFrequency = BleedingIndicationConstants.SEQUENCE_DROP_AVERAGE_HIGH;
m_DropSpawnMinDelay = BleedingIndicationConstants.SEQUENCE_DROP_DELAY_MIN_HIGH;
m_DropSpawnMaxDelay = BleedingIndicationConstants.SEQUENCE_DROP_DELAY_MAX_HIGH;
break;
}
default:
{
m_AverageFrequency = BleedingIndicationConstants.SEQUENCE_DROP_AVERAGE_LOW;
m_DropSpawnMinDelay = BleedingIndicationConstants.SEQUENCE_DROP_DELAY_MIN_LOW;
m_DropSpawnMaxDelay = BleedingIndicationConstants.SEQUENCE_DROP_DELAY_MAX_LOW;
Debug.Log("Unknown severity value!");
}
#ifdef DIAG_DEVELOPER
if (DbgBleedingIndicationStaticInfo.m_DbgUseOverrideValues)
{
m_SequenceDuration = DbgBleedingIndicationStaticInfo.m_DbgSequenceDuration;
m_DropSpawnMinDelay = DbgBleedingIndicationStaticInfo.m_DbgDropMinDelay;
m_DropSpawnMaxDelay = DbgBleedingIndicationStaticInfo.m_DbgDropMaxDelay;
}
#endif
}
m_TimeElapsedTotal = 0;
m_TimeElapsedSequence = 0;
}
void InitIndicator(vector position)
{
m_BasePosition = position;
ResetIndicator();
m_Initialized = true;
}
void StopIndicator(bool instant = false)
{
if (!m_Terminating)
{
m_IsRunning = false;
if (instant)
{
m_EndNow = true;
}
m_Terminating = true;
}
}
protected void StartRunningDrops()
{
m_ActiveDropsCount = 0;
m_IsRunning = true;
TrySpawnNextDrop();
m_DropSpawnsQueued = 0;
m_CurrentDropProbabilityStep = (int)(m_DropProbabilityRollsCount - (m_DropProbabilityRollsCount / m_AverageFrequency));
}
//! Are any drops currently being animated?
protected bool IsRunningDrops()
{
return m_ActiveDropsCount > 0;
}
void TrySpawnNextDrop()
{
ImageWidget dropImage;
if (Class.CastTo(dropImage,m_ParentMetaData.GetNextDropImage()) && !dropImage.IsVisible()) //IsVisible false means the drop is free to be used
{
BleedingIndicatorDropData data = new BleedingIndicatorDropData(dropImage,m_Severity);
data.SetBasePosition(m_BasePosition);
data.StartDrop();
m_ActiveDrops.Insert(data);
m_ActiveDropsCount++;
}
m_LastDropSpawnTime = m_TimeElapsedTotal;
m_DropSpawnsQueued--;
}
protected void ResetSequence()
{
m_CurrentDropProbabilityStep = 0;
m_TimeElapsedSequence = 0;
m_DropSpawnsQueued = 0;
}
void ResetIndicator()
{
m_Terminating = false;
m_EndNow = false;
m_TimeElapsedTotal = 0;
m_CurrentDropProbabilityStep = 0;
m_TimeElapsedSequence = 0;
m_LastDropSpawnTime = 0;
m_DropSpawnsQueued = 0;
}
void Update(float timeSlice)
{
if ( !m_Initialized )
{
return;
}
#ifdef DIAG_DEVELOPER
if (DbgBleedingIndicationStaticInfo.m_DbgUseOverrideValues)
{
m_SequenceDuration = DbgBleedingIndicationStaticInfo.m_DbgSequenceDuration;
}
#endif
m_SequenceTick = m_SequenceDuration / m_DropProbabilityRollsCount;
//run drops, if possible
if (!m_Terminating)
{
if (m_IsRunning)
{
if (m_TimeElapsedSequence > (m_SequenceTick * m_CurrentDropProbabilityStep))
{
if (m_CurrentDropProbabilityStep < m_DropProbabilityRollsCount)
{
float rnd = Math.RandomFloat01();
if (rnd < m_DropProbabilityArray[m_CurrentDropProbabilityStep])
{
m_DropSpawnsQueued++;
}
m_CurrentDropProbabilityStep++;
}
}
float sinceLastDrop = m_TimeElapsedTotal - m_LastDropSpawnTime;
if (m_TimeElapsedSequence > m_SequenceDuration)
{
ResetSequence();
}
else if (m_DropSpawnsQueued > 0) //spawn queued drop
{
if (sinceLastDrop >= m_DropSpawnMinDelay)
{
TrySpawnNextDrop();
}
}
else if (sinceLastDrop > m_DropSpawnMaxDelay)
{
TrySpawnNextDrop(); //guaranteed drop
m_CurrentDropProbabilityStep++; //substitutes a regular roll..
}
}
else //1st drop ignores delay
{
StartRunningDrops();
}
}
for (int i = 0; i < m_ActiveDropsCount; i++)
{
if (!m_EndNow)
{
//Simulate drops
m_ActiveDrops[i].Update(timeSlice);
}
else
{
m_ActiveDrops[i].StopDrop();
}
if (!m_ActiveDrops[i].IsRunning())
{
m_CleanupQueue.Insert(i);
}
}
//Cleanup drops
for (i = m_CleanupQueue.Count() - 1; i >= 0; i--)
{
m_ActiveDrops.Remove(m_CleanupQueue[i]);
m_ActiveDropsCount--;
}
m_CleanupQueue.Clear();
if (m_Terminating && !IsRunningDrops())
{
m_EndNow = true;
}
m_TimeElapsedTotal += timeSlice;
m_TimeElapsedSequence += timeSlice;
}
bool GetEndNow()
{
return m_EndNow;
}
int GetSeverity()
{
return m_Severity;
}
}