#ifndef __MINEIGC_H_
#define __MINEIGC_H_
#include "modelIGC.h"
const char c_msStart = 0;
const char c_msExploded = 1;
const char c_msScattered = 2;
class CmineIGC : public TmodelIGC<ImineIGC>
{
public:
CmineIGC(void);
~CmineIGC(void);
public:
virtual HRESULT Initialize(ImissionIGC* pMission, Time now, const void* data, int dataSize);
virtual void Terminate(void);
virtual void Update(Time now);
virtual int Export(void* data) const;
virtual ObjectType GetObjectType(void) const
{
return OT_mine;
}
virtual ObjectID GetObjectID(void) const
{
return m_mineID;
}
virtual void SetCluster(IclusterIGC* cluster)
{
AddRef();
{
IclusterIGC* c = GetCluster();
if (c)
c->DeleteMine(this);
}
TmodelIGC<ImineIGC>::SetCluster(cluster);
if (cluster)
cluster->AddMine(this);
Release();
}
virtual void HandleCollision(Time timeCollision,
float tCollision,
const CollisionEntry& entry,
ImodelIGC* pmodel)
{
if (pmodel->GetObjectType() == OT_ship)
{
const float c_dtArmTime = 1.0f;
if ((pmodel->GetSide() != GetSide()) && (timeCollision >= m_time0 + c_dtArmTime))
{
const Vector& dV = pmodel->GetVelocity();
double a = dV * dV;
if (a > 1.0) {
const Vector& pMe = GetPosition();
const Vector& pHim = pmodel->GetPosition();
Vector pEnter = pHim + tCollision * dV;
Vector dP = pMe - pHim; float rMe = GetRadius();
float rHim = pmodel->GetRadius();
double r = rMe + rHim;
double halfB = dP * dV;
double c = dP * dP - r * r;
double b2ac = halfB * halfB - a * c;
if (b2ac >= 0.0f)
{
double s = sqrt(b2ac);
float tExit = (float)((halfB + s) / a);
float tStop = GetHitTest()->GetTstop();
if (tExit > tStop)
tExit = tStop;
float dt = tExit - tCollision;
if (dt > 0.0f)
{
const float c_damageMultiplier = 1.0f / (5.0f * 5.0f * 100.0f);
float speed2 = float(a);
float amount = dt * speed2 * m_mineType->GetPower() * rHim * rHim * c_damageMultiplier / (2.0f * rMe);
float endurance = m_mineType->GetEndurance();
float oldEndurance = endurance * m_fraction;
float newEndurance = oldEndurance * float(exp(-amount / endurance));
float damage = oldEndurance - newEndurance;
m_fraction = newEndurance / endurance;
Vector position1 = pHim + dV * tCollision;
const float c_radiusPlacement = 10.0f;
Vector position2 = position1 + dV * ((c_radiusPlacement + rHim) / float(sqrt(a))) + Vector::RandomPosition(c_radiusPlacement);
((IshipIGC*)pmodel)->AddMineDamage(m_mineType->GetDamageType(), damage, timeCollision,
m_launcher,
position1,
position2);
if (newEndurance < 1.0f)
GetMyMission()->GetIgcSite()->KillMineEvent(this);
else
GetThingSite()->SetMineStrength(m_fraction);
}
}
}
}
}
}
virtual ImineTypeIGC* GetMineType(void) const
{
return m_mineType;
}
virtual IshipIGC* GetLauncher(void) const
{
return m_launcher;
}
virtual void SetCreateNow (void)
{
m_bCreateNow = true;
}
virtual float GetStrength(void) const
{
return m_fraction;
}
virtual void ReduceStrength(float amount)
{
float endurance = m_mineType->GetEndurance();
float newEndurance = endurance * m_fraction * float(exp(-amount / endurance));
m_fraction = (newEndurance / endurance);
if (m_fraction < 0.25f)
GetMyMission()->GetIgcSite()->KillMineEvent(this);
else
GetThingSite()->SetMineStrength(m_fraction);
}
virtual float GetTimeFraction(void) const
{
Time timeNow = GetMyLastUpdate();
float f = (m_timeExpire - timeNow) / (m_timeExpire - m_time0);
if (f < 0.0f)
f = 0.0f;
else if (f > 1.0f)
f = 1.0f;
return f;
}
private:
ImineTypeIGC* m_mineType;
IshipIGC* m_launcher;
Time m_time0;
Time m_timeExpire;
float m_fraction;
MineID m_mineID;
bool m_bCreateNow;
};
#endif