2020-03-12 16:26:47 +00:00
|
|
|
#include "common.h"
|
2020-04-17 13:31:11 +00:00
|
|
|
|
2020-04-08 19:29:02 +00:00
|
|
|
#include "Automobile.h"
|
|
|
|
#include "Bike.h"
|
|
|
|
#include "Camera.h"
|
|
|
|
#include "Coronas.h"
|
2020-03-12 16:26:47 +00:00
|
|
|
#include "DMAudio.h"
|
2020-04-08 19:29:02 +00:00
|
|
|
#include "Entity.h"
|
|
|
|
#include "EventList.h"
|
2020-03-12 16:26:47 +00:00
|
|
|
#include "Explosion.h"
|
2020-04-08 19:29:02 +00:00
|
|
|
#include "General.h"
|
|
|
|
#include "Fire.h"
|
|
|
|
#include "Pad.h"
|
|
|
|
#include "Particle.h"
|
|
|
|
#include "PointLights.h"
|
|
|
|
#include "Shadows.h"
|
|
|
|
#include "Timer.h"
|
|
|
|
#include "Vehicle.h"
|
|
|
|
#include "WaterLevel.h"
|
|
|
|
#include "World.h"
|
2020-03-12 16:26:47 +00:00
|
|
|
|
2020-04-15 22:56:15 +00:00
|
|
|
CExplosion gaExplosion[NUM_EXPLOSIONS];
|
2020-03-12 16:26:47 +00:00
|
|
|
|
2020-04-08 19:29:02 +00:00
|
|
|
// these two were not initialised in original code, I'm really not sure what were they meant to be
|
|
|
|
RwRGBA colMedExpl = { 0, 0, 0, 0 };
|
|
|
|
RwRGBA colUpdate = { 0, 0, 0, 0 };
|
2020-03-12 16:26:47 +00:00
|
|
|
|
2020-10-05 14:24:57 +00:00
|
|
|
const RwRGBA colAddExplosion = { 160, 160, 160, 255 };
|
|
|
|
const RwRGBA colGrenade = { 96, 96, 96, 255 };
|
|
|
|
|
2020-03-12 16:26:47 +00:00
|
|
|
int AudioHandle = AEHANDLE_NONE;
|
|
|
|
|
|
|
|
void
|
|
|
|
CExplosion::Initialise()
|
|
|
|
{
|
|
|
|
debug("Initialising CExplosion...\n");
|
2020-09-26 18:10:23 +00:00
|
|
|
ClearAllExplosions();
|
|
|
|
AudioHandle = DMAudio.CreateEntity(AUDIOTYPE_EXPLOSION, (void*)1);
|
|
|
|
if (AudioHandle >= 0)
|
|
|
|
DMAudio.SetEntityStatus(AudioHandle, true);
|
|
|
|
debug("CExplosion ready\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CExplosion::ClearAllExplosions()
|
|
|
|
{
|
2020-03-12 16:26:47 +00:00
|
|
|
for (int i = 0; i < ARRAY_SIZE(gaExplosion); i++) {
|
|
|
|
gaExplosion[i].m_ExplosionType = EXPLOSION_GRENADE;
|
2020-04-08 19:29:02 +00:00
|
|
|
gaExplosion[i].m_vecPosition = CVector(0.0f, 0.0f, 0.0f);
|
2020-03-12 16:26:47 +00:00
|
|
|
gaExplosion[i].m_fRadius = 1.0f;
|
|
|
|
gaExplosion[i].m_fPropagationRate = 0.0f;
|
2020-04-08 19:29:02 +00:00
|
|
|
gaExplosion[i].m_fZshift = 0.0f;
|
2020-03-12 16:26:47 +00:00
|
|
|
gaExplosion[i].m_pCreatorEntity = nil;
|
|
|
|
gaExplosion[i].m_pVictimEntity = nil;
|
|
|
|
gaExplosion[i].m_fStopTime = 0.0f;
|
2020-04-08 19:29:02 +00:00
|
|
|
gaExplosion[i].m_nIteration = 0;
|
|
|
|
gaExplosion[i].m_fStartTime = 0.0f;
|
|
|
|
gaExplosion[i].m_bIsBoat = false;
|
2020-10-05 16:05:13 +00:00
|
|
|
gaExplosion[i].m_bMakeSound = true;
|
2020-03-12 16:26:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-08 19:29:02 +00:00
|
|
|
void
|
|
|
|
CExplosion::Shutdown()
|
2020-03-12 16:26:47 +00:00
|
|
|
{
|
|
|
|
debug("Shutting down CExplosion...\n");
|
|
|
|
if (AudioHandle >= 0) {
|
|
|
|
DMAudio.DestroyEntity(AudioHandle);
|
|
|
|
AudioHandle = AEHANDLE_NONE;
|
|
|
|
}
|
|
|
|
debug("CExplosion shut down\n");
|
|
|
|
}
|
|
|
|
|
2020-04-08 19:29:02 +00:00
|
|
|
int8
|
|
|
|
CExplosion::GetExplosionActiveCounter(uint8 id)
|
|
|
|
{
|
|
|
|
return gaExplosion[id].m_nActiveCounter;
|
|
|
|
}
|
|
|
|
|
2020-03-12 16:26:47 +00:00
|
|
|
void
|
2020-04-08 19:29:02 +00:00
|
|
|
CExplosion::ResetExplosionActiveCounter(uint8 id)
|
2020-03-12 16:26:47 +00:00
|
|
|
{
|
2020-04-08 19:29:02 +00:00
|
|
|
gaExplosion[id].m_nActiveCounter = 0;
|
2020-03-12 16:26:47 +00:00
|
|
|
}
|
|
|
|
|
2020-04-08 19:29:02 +00:00
|
|
|
uint8
|
|
|
|
CExplosion::GetExplosionType(uint8 id)
|
2020-03-12 16:26:47 +00:00
|
|
|
{
|
2020-04-08 19:29:02 +00:00
|
|
|
return gaExplosion[id].m_ExplosionType;
|
2020-03-12 16:26:47 +00:00
|
|
|
}
|
|
|
|
|
2020-10-05 00:04:35 +00:00
|
|
|
bool
|
|
|
|
CExplosion::DoesExplosionMakeSound(uint8 id)
|
|
|
|
{
|
2020-10-05 16:05:13 +00:00
|
|
|
return gaExplosion[id].m_bMakeSound;
|
2020-10-05 00:04:35 +00:00
|
|
|
};
|
|
|
|
|
2020-03-12 16:26:47 +00:00
|
|
|
CVector *
|
|
|
|
CExplosion::GetExplosionPosition(uint8 id)
|
|
|
|
{
|
|
|
|
return &gaExplosion[id].m_vecPosition;
|
|
|
|
}
|
|
|
|
|
2020-04-08 19:29:02 +00:00
|
|
|
bool
|
2020-10-05 14:24:57 +00:00
|
|
|
CExplosion::AddExplosion(CEntity *explodingEntity, CEntity *culprit, eExplosionType type, const CVector &pos, uint32 lifetime, bool makeSound)
|
2020-03-12 16:26:47 +00:00
|
|
|
{
|
2020-04-08 19:29:02 +00:00
|
|
|
CVector pPosn;
|
|
|
|
CVector posGround;
|
|
|
|
|
|
|
|
RwRGBA colorMedium = colMedExpl;
|
2020-10-05 14:24:57 +00:00
|
|
|
RwRGBA color = colAddExplosion;
|
|
|
|
RwRGBA colorGrenade = colGrenade;
|
2020-04-08 19:29:02 +00:00
|
|
|
bool bDontExplode = false;
|
|
|
|
pPosn = pos;
|
|
|
|
pPosn.z += 5.0f;
|
2020-04-09 13:15:30 +00:00
|
|
|
#ifdef FIX_BUGS
|
|
|
|
CShadows::AddPermanentShadow(SHADOWTEX_CAR, gpShadowHeliTex, &pPosn, 8.0f, 0.0f, 0.0f, -8.0f, 200, 0, 0, 0, 10.0f, 30000, 1.0f);
|
|
|
|
#else
|
|
|
|
// last two arguments are swapped resulting in no shadow
|
2020-04-08 19:29:02 +00:00
|
|
|
CShadows::AddPermanentShadow(SHADOWTEX_CAR, gpShadowHeliTex, &pPosn, 8.0f, 0.0f, 0.0f, -8.0f, 200, 0, 0, 0, 10.0f, 1, 30000.0f);
|
2020-04-09 13:15:30 +00:00
|
|
|
#endif
|
2020-04-08 19:29:02 +00:00
|
|
|
|
|
|
|
int n = 0;
|
|
|
|
while (gaExplosion[n].m_nIteration != 0 && n < ARRAY_SIZE(gaExplosion))
|
|
|
|
n++;
|
|
|
|
if (n == ARRAY_SIZE(gaExplosion))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
CExplosion &explosion = gaExplosion[n];
|
|
|
|
explosion.m_ExplosionType = type;
|
|
|
|
explosion.m_vecPosition = pos;
|
|
|
|
explosion.m_fRadius = 1.0f;
|
|
|
|
explosion.m_fZshift = 0.0f;
|
|
|
|
explosion.m_pCreatorEntity = culprit;
|
|
|
|
if (culprit != nil)
|
|
|
|
culprit->RegisterReference(&explosion.m_pCreatorEntity);
|
|
|
|
explosion.m_pVictimEntity = explodingEntity;
|
|
|
|
if (explodingEntity != nil)
|
|
|
|
explodingEntity->RegisterReference(&explosion.m_pVictimEntity);
|
|
|
|
explosion.m_nIteration = 1;
|
|
|
|
explosion.m_nActiveCounter = 1;
|
|
|
|
explosion.m_bIsBoat = false;
|
2020-10-05 16:05:13 +00:00
|
|
|
explosion.m_bMakeSound = makeSound;
|
2020-04-08 19:29:02 +00:00
|
|
|
explosion.m_nParticlesExpireTime = lifetime != 0 ? CTimer::GetTimeInMilliseconds() + lifetime : 0;
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case EXPLOSION_GRENADE:
|
|
|
|
explosion.m_fRadius = 9.0f;
|
|
|
|
explosion.m_fPower = 300.0f;
|
|
|
|
explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;
|
|
|
|
explosion.m_fPropagationRate = 0.5f;
|
|
|
|
posGround = pos;
|
|
|
|
posGround.z = CWorld::FindGroundZFor3DCoord(posGround.x, posGround.y, posGround.z + 3.0f, nil);
|
|
|
|
CEventList::RegisterEvent(EVENT_EXPLOSION, posGround, 250);
|
2020-10-05 00:04:35 +00:00
|
|
|
if (Distance(explosion.m_vecPosition, TheCamera.GetPosition()) < 40.0f) {
|
|
|
|
uint8 tmp = CGeneral::GetRandomNumberInRange(0, 64) - 64;
|
2020-10-05 14:24:57 +00:00
|
|
|
colorGrenade.green += tmp;
|
|
|
|
colorGrenade.blue += tmp;
|
|
|
|
CParticle::AddParticle(PARTICLE_EXPLOSION_LFAST, explosion.m_vecPosition, CVector(0.0f, 0.0f, 0.0f), nil, 4.5f, colorGrenade);
|
2020-10-05 00:04:35 +00:00
|
|
|
}
|
2020-04-08 19:29:02 +00:00
|
|
|
break;
|
|
|
|
case EXPLOSION_MOLOTOV:
|
|
|
|
{
|
|
|
|
explosion.m_fRadius = 6.0f;
|
|
|
|
explosion.m_fPower = 0.0f;
|
|
|
|
explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 3000;
|
|
|
|
explosion.m_fPropagationRate = 0.5f;
|
|
|
|
posGround = pos;
|
|
|
|
bool found;
|
2020-10-05 00:04:35 +00:00
|
|
|
float tmp = CWorld::FindGroundZFor3DCoord(posGround.x, posGround.y, posGround.z + 3.0f, &found);
|
|
|
|
if (found)
|
|
|
|
posGround.z = tmp;
|
|
|
|
|
|
|
|
float waterLevel;
|
|
|
|
if (CWaterLevel::GetWaterLevelNoWaves(posGround.x, posGround.y, posGround.z, &waterLevel)
|
|
|
|
&& posGround.z < waterLevel && waterLevel - 6.0f < posGround.z) { // some subway/tunnels check?
|
2020-04-08 19:29:02 +00:00
|
|
|
bDontExplode = true;
|
2020-10-05 00:04:35 +00:00
|
|
|
} else if (found) {
|
|
|
|
gFireManager.StartFire(posGround, 1.8f, false);
|
|
|
|
}
|
2020-04-08 19:29:02 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EXPLOSION_ROCKET:
|
|
|
|
explosion.m_fRadius = 10.0f;
|
|
|
|
explosion.m_fPower = 300.0f;
|
|
|
|
explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;
|
|
|
|
explosion.m_fPropagationRate = 0.5f;
|
|
|
|
CEventList::RegisterEvent(EVENT_EXPLOSION, pos, 250);
|
|
|
|
if (Distance(explosion.m_vecPosition, TheCamera.GetPosition()) < 40.0f)
|
|
|
|
CParticle::AddParticle(PARTICLE_EXPLOSION_LFAST, explosion.m_vecPosition, CVector(0.0f, 0.0f, 0.0f), nil, 5.5f, color);
|
|
|
|
break;
|
|
|
|
case EXPLOSION_CAR:
|
|
|
|
case EXPLOSION_CAR_QUICK:
|
2020-07-18 22:37:44 +00:00
|
|
|
case EXPLOSION_BOAT:
|
2020-04-08 19:29:02 +00:00
|
|
|
explosion.m_fRadius = 9.0f;
|
|
|
|
explosion.m_fPower = 300.0f;
|
|
|
|
explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 4250;
|
|
|
|
explosion.m_fPropagationRate = 0.5f;
|
|
|
|
explosion.m_fStartTime = CTimer::GetTimeInMilliseconds();
|
|
|
|
if (explosion.m_pVictimEntity != nil) {
|
|
|
|
if (explosion.m_pVictimEntity->IsVehicle() && ((CVehicle*)explosion.m_pVictimEntity)->IsBoat())
|
|
|
|
explosion.m_bIsBoat = true;
|
|
|
|
CEventList::RegisterEvent(EVENT_EXPLOSION, EVENT_ENTITY_VEHICLE, explosion.m_pVictimEntity, nil, 1000);
|
2020-10-05 00:04:35 +00:00
|
|
|
} else {
|
2020-04-08 19:29:02 +00:00
|
|
|
CEventList::RegisterEvent(EVENT_EXPLOSION, pos, 1000);
|
2020-10-05 00:04:35 +00:00
|
|
|
}
|
2020-04-08 19:29:02 +00:00
|
|
|
|
|
|
|
if (explosion.m_pVictimEntity != nil && !explosion.m_bIsBoat) {
|
|
|
|
CVehicle *veh = (CVehicle*)explosion.m_pVictimEntity;
|
2020-10-05 00:04:35 +00:00
|
|
|
CVector componentPos;
|
2020-04-08 19:29:02 +00:00
|
|
|
|
2020-10-05 00:04:35 +00:00
|
|
|
if (veh->IsBike()) {
|
|
|
|
veh->GetComponentWorldPosition(BIKE_FORKS_REAR, componentPos);
|
|
|
|
} else if (veh->IsComponentPresent(CAR_BUMP_REAR) && veh->IsComponentPresent(CAR_WHEEL_LB)) { //mb it's another enum
|
|
|
|
CVector tmpVec;
|
|
|
|
veh->GetComponentWorldPosition(CAR_BUMP_REAR, componentPos);
|
|
|
|
veh->GetComponentWorldPosition(CAR_WHEEL_LB, tmpVec);
|
|
|
|
componentPos += tmpVec;
|
|
|
|
componentPos /= 2.0f;
|
|
|
|
} else if (veh->IsComponentPresent(CAR_BOOT)) {
|
|
|
|
veh->GetComponentWorldPosition(CAR_BOOT, componentPos);
|
|
|
|
}
|
2020-12-18 00:58:09 +00:00
|
|
|
if (componentPos.x != 0.0f) {
|
2020-10-05 00:04:35 +00:00
|
|
|
int rn = (CGeneral::GetRandomNumber() & 1) + 1;
|
2020-04-08 19:29:02 +00:00
|
|
|
for (int i = 0; i < rn; i++)
|
2020-10-05 00:04:35 +00:00
|
|
|
CParticle::AddJetExplosion(componentPos, (CGeneral::GetRandomNumber() & 7) / 7.0f + 1.5f, 0.5f);
|
2020-04-08 19:29:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EXPLOSION_HELI:
|
2020-07-18 22:37:44 +00:00
|
|
|
case EXPLOSION_HELI2:
|
2020-10-05 00:04:35 +00:00
|
|
|
if (type == EXPLOSION_HELI2) {
|
|
|
|
explosion.m_fRadius = 12.0f;
|
|
|
|
explosion.m_fPower = 500.0f;
|
|
|
|
} else {
|
|
|
|
explosion.m_fRadius = 6.0f;
|
|
|
|
explosion.m_fPower = 300.0f;
|
|
|
|
}
|
2020-04-08 19:29:02 +00:00
|
|
|
explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;
|
|
|
|
explosion.m_fPropagationRate = 0.5f;
|
|
|
|
explosion.m_fStartTime = CTimer::GetTimeInMilliseconds();
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
|
|
CVector randpos;
|
|
|
|
|
2020-10-05 00:04:35 +00:00
|
|
|
randpos.x = CGeneral::GetRandomNumber();
|
|
|
|
randpos.y = CGeneral::GetRandomNumber();
|
|
|
|
randpos.z = CGeneral::GetRandomNumber();
|
|
|
|
randpos -= CVector(128, 128, 128);
|
|
|
|
randpos /= 20.0f;
|
|
|
|
randpos += pos;
|
2020-04-08 19:29:02 +00:00
|
|
|
|
|
|
|
CParticle::AddParticle(PARTICLE_EXPLOSION_MFAST, randpos, CVector(0.0f, 0.0f, 0.0f), nil, 2.5f, color);
|
|
|
|
|
2020-10-05 00:04:35 +00:00
|
|
|
randpos.x = CGeneral::GetRandomNumber();
|
|
|
|
randpos.y = CGeneral::GetRandomNumber();
|
|
|
|
randpos.z = CGeneral::GetRandomNumber();
|
|
|
|
randpos -= CVector(128, 128, 128);
|
|
|
|
randpos /= 20.0f;
|
|
|
|
randpos += pos;
|
2020-04-08 19:29:02 +00:00
|
|
|
|
|
|
|
CParticle::AddParticle(PARTICLE_EXPLOSION_LFAST, randpos, CVector(0.0f, 0.0f, 0.0f), nil, 5.0f, color);
|
|
|
|
|
2020-10-05 00:04:35 +00:00
|
|
|
randpos.x = CGeneral::GetRandomNumber();
|
|
|
|
randpos.y = CGeneral::GetRandomNumber();
|
|
|
|
randpos.z = CGeneral::GetRandomNumber();
|
|
|
|
randpos -= CVector(128, 128, 128);
|
|
|
|
randpos /= 20.0f;
|
|
|
|
randpos += pos;
|
2020-04-08 19:29:02 +00:00
|
|
|
|
|
|
|
CParticle::AddJetExplosion(randpos, 1.4f, 3.0f);
|
|
|
|
}
|
|
|
|
CEventList::RegisterEvent(EVENT_EXPLOSION, pos, 1000);
|
|
|
|
break;
|
|
|
|
case EXPLOSION_MINE:
|
|
|
|
explosion.m_fRadius = 10.0f;
|
|
|
|
explosion.m_fPower = 150.0f;
|
|
|
|
explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;
|
|
|
|
explosion.m_fPropagationRate = 0.5f;
|
|
|
|
posGround = pos;
|
|
|
|
//posGround.z =
|
|
|
|
CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 4.0f, nil); // BUG? result is unused
|
|
|
|
CEventList::RegisterEvent(EVENT_EXPLOSION, posGround, 250);
|
|
|
|
break;
|
|
|
|
case EXPLOSION_BARREL:
|
|
|
|
explosion.m_fRadius = 7.0f;
|
|
|
|
explosion.m_fPower = 150.0f;
|
|
|
|
explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;
|
|
|
|
explosion.m_fPropagationRate = 0.5f;
|
|
|
|
for (int i = 0; i < 6; i++) {
|
|
|
|
CVector randpos;
|
2020-10-05 00:04:35 +00:00
|
|
|
randpos.x = CGeneral::GetRandomNumber();
|
|
|
|
randpos.y = CGeneral::GetRandomNumber();
|
|
|
|
randpos.z = CGeneral::GetRandomNumber();
|
|
|
|
randpos -= CVector(128, 128, 128);
|
2020-04-08 19:29:02 +00:00
|
|
|
randpos.x /= 50.0f;
|
|
|
|
randpos.y /= 50.0f;
|
|
|
|
randpos.z /= 25.0f;
|
|
|
|
randpos += pos;
|
|
|
|
CParticle::AddParticle(PARTICLE_EXPLOSION_MEDIUM, randpos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, colorMedium);
|
|
|
|
}
|
|
|
|
posGround = pos;
|
|
|
|
//posGround.z =
|
|
|
|
CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 4.0f, nil); // BUG? result is unused
|
|
|
|
CEventList::RegisterEvent(EVENT_EXPLOSION, posGround, 250);
|
|
|
|
break;
|
|
|
|
case EXPLOSION_TANK_GRENADE:
|
|
|
|
explosion.m_fRadius = 10.0f;
|
|
|
|
explosion.m_fPower = 150.0f;
|
|
|
|
explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;
|
|
|
|
explosion.m_fPropagationRate = 0.5f;
|
|
|
|
posGround = pos;
|
|
|
|
//posGround.z =
|
|
|
|
CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 4.0f, nil); // BUG? result is unused
|
|
|
|
CEventList::RegisterEvent(EVENT_EXPLOSION, posGround, 250);
|
|
|
|
break;
|
|
|
|
case EXPLOSION_HELI_BOMB:
|
|
|
|
explosion.m_fRadius = 8.0f;
|
|
|
|
explosion.m_fPower = 50.0f;
|
|
|
|
explosion.m_fStopTime = lifetime + CTimer::GetTimeInMilliseconds() + 750;
|
|
|
|
explosion.m_fPropagationRate = 0.5f;
|
|
|
|
posGround = pos;
|
|
|
|
//posGround.z =
|
|
|
|
CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z + 4.0f, nil); // BUG? result is unused
|
|
|
|
CEventList::RegisterEvent(EVENT_EXPLOSION, posGround, 250);
|
|
|
|
break;
|
2020-10-05 00:04:35 +00:00
|
|
|
default:
|
|
|
|
debug("Undefined explosion type, AddExplosion, Explosion.cpp");
|
|
|
|
break;
|
2020-04-08 19:29:02 +00:00
|
|
|
}
|
2020-10-05 00:04:35 +00:00
|
|
|
|
2020-04-08 19:29:02 +00:00
|
|
|
if (bDontExplode) {
|
|
|
|
explosion.m_nIteration = 0;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (explosion.m_fPower != 0.0f && explosion.m_nParticlesExpireTime == 0)
|
|
|
|
CWorld::TriggerExplosion(pos, explosion.m_fRadius, explosion.m_fPower, culprit, (type == EXPLOSION_ROCKET || type == EXPLOSION_CAR_QUICK || type == EXPLOSION_MINE || type == EXPLOSION_BARREL || type == EXPLOSION_TANK_GRENADE || type == EXPLOSION_HELI_BOMB));
|
|
|
|
|
2020-10-05 00:04:35 +00:00
|
|
|
if (type == EXPLOSION_MOLOTOV) {
|
|
|
|
TheCamera.CamShake(0.2f, pos.x, pos.y, pos.z);
|
|
|
|
} else {
|
|
|
|
TheCamera.CamShake(0.6f, pos.x, pos.y, pos.z);
|
|
|
|
CPad::GetPad(0)->StartShake_Distance(300, 128, pos.x, pos.y, pos.z);
|
|
|
|
}
|
2020-04-08 19:29:02 +00:00
|
|
|
return true;
|
2020-03-12 16:26:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-04-08 19:29:02 +00:00
|
|
|
CExplosion::Update()
|
2020-03-12 16:26:47 +00:00
|
|
|
{
|
2020-04-08 19:29:02 +00:00
|
|
|
RwRGBA color = colUpdate;
|
|
|
|
for (int i = 0; i < ARRAY_SIZE(gaExplosion); i++) {
|
|
|
|
CExplosion &explosion = gaExplosion[i];
|
|
|
|
if (explosion.m_nIteration == 0) continue;
|
|
|
|
|
|
|
|
if (explosion.m_nParticlesExpireTime != 0) {
|
|
|
|
if (CTimer::GetTimeInMilliseconds() > explosion.m_nParticlesExpireTime) {
|
|
|
|
explosion.m_nParticlesExpireTime = 0;
|
|
|
|
if (explosion.m_fPower != 0.0f)
|
|
|
|
CWorld::TriggerExplosion(explosion.m_vecPosition, explosion.m_fRadius, explosion.m_fPower, explosion.m_pCreatorEntity, (explosion.m_ExplosionType == EXPLOSION_ROCKET || explosion.m_ExplosionType == EXPLOSION_CAR_QUICK || explosion.m_ExplosionType == EXPLOSION_MINE || explosion.m_ExplosionType == EXPLOSION_BARREL || explosion.m_ExplosionType == EXPLOSION_TANK_GRENADE || explosion.m_ExplosionType == EXPLOSION_HELI_BOMB));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
explosion.m_fRadius += explosion.m_fPropagationRate * CTimer::GetTimeStep();
|
|
|
|
int32 someTime = explosion.m_fStopTime - CTimer::GetTimeInMilliseconds();
|
|
|
|
switch (explosion.m_ExplosionType)
|
|
|
|
{
|
|
|
|
case EXPLOSION_GRENADE:
|
|
|
|
case EXPLOSION_ROCKET:
|
|
|
|
case EXPLOSION_HELI:
|
2020-10-05 13:14:48 +00:00
|
|
|
case EXPLOSION_HELI2:
|
2020-04-08 19:29:02 +00:00
|
|
|
case EXPLOSION_MINE:
|
|
|
|
case EXPLOSION_BARREL:
|
|
|
|
if (CTimer::GetFrameCounter() & 1) {
|
|
|
|
CPointLights::AddLight(CPointLights::LIGHT_POINT, explosion.m_vecPosition, CVector(0.0f, 0.0f, 0.0f), 20.0f, 1.0f, 1.0f, 0.5f, CPointLights::FOG_NONE, true);
|
|
|
|
CCoronas::RegisterCorona((uintptr)&explosion, 255, 255, 200, 255, explosion.m_vecPosition, 8.0f, 120.0f, gpCoronaTexture[0], CCoronas::TYPE_NORMAL, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
|
|
|
|
} else
|
|
|
|
CCoronas::RegisterCorona((uintptr)&explosion, 128, 128, 100, 255, explosion.m_vecPosition, 8.0f, 120.0f, gpCoronaTexture[0], CCoronas::TYPE_NORMAL, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
|
|
|
|
CCoronas::RegisterCorona((uintptr)&explosion + 1, 30, 30, 25, 255, explosion.m_vecPosition, explosion.m_fRadius, 120.0f, gpCoronaTexture[7], CCoronas::TYPE_STAR, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
|
|
|
|
break;
|
|
|
|
case EXPLOSION_MOLOTOV:
|
|
|
|
CWorld::SetPedsOnFire(explosion.m_vecPosition.x, explosion.m_vecPosition.y, explosion.m_vecPosition.z, 6.0f, explosion.m_pCreatorEntity);
|
|
|
|
CWorld::SetCarsOnFire(explosion.m_vecPosition.x, explosion.m_vecPosition.y, explosion.m_vecPosition.z, 6.0f, explosion.m_pCreatorEntity);
|
|
|
|
if (explosion.m_nIteration < 10) {
|
|
|
|
if (explosion.m_nIteration == 1) {
|
|
|
|
CVector point1 = explosion.m_vecPosition;
|
|
|
|
point1.z += 5.0f;
|
|
|
|
CColPoint colPoint;
|
|
|
|
CEntity *pEntity;
|
2020-10-05 13:14:48 +00:00
|
|
|
if (CWorld::ProcessVerticalLine(point1, -1000.0f, colPoint, pEntity, true, false, false, false, true, false, nil))
|
|
|
|
explosion.m_fZshift = colPoint.point.z;
|
|
|
|
else
|
|
|
|
explosion.m_fZshift = explosion.m_vecPosition.z;
|
2020-04-08 19:29:02 +00:00
|
|
|
}
|
|
|
|
float ff = ((float)explosion.m_nIteration * 0.55f);
|
|
|
|
for (int i = 0; i < 5 * ff; i++) {
|
|
|
|
float angle = CGeneral::GetRandomNumber() / 256.0f * 6.28f;
|
|
|
|
|
|
|
|
CVector pos = explosion.m_vecPosition;
|
|
|
|
pos.x += ff * Sin(angle);
|
|
|
|
pos.y += ff * Cos(angle);
|
|
|
|
pos.z = explosion.m_fZshift + 0.5f;
|
|
|
|
CParticle::AddParticle(PARTICLE_EXPLOSION_MEDIUM, pos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, color, CGeneral::GetRandomNumberInRange(-3.0f, 3.0f), CGeneral::GetRandomNumberInRange(-180.0f, 180.0f));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EXPLOSION_CAR:
|
|
|
|
case EXPLOSION_CAR_QUICK:
|
2020-10-05 13:14:48 +00:00
|
|
|
case EXPLOSION_BOAT:
|
2020-04-08 19:29:02 +00:00
|
|
|
if (someTime >= 3500) {
|
2020-10-05 13:14:48 +00:00
|
|
|
if (explosion.m_pVictimEntity != nil) {
|
|
|
|
if ((CGeneral::GetRandomNumber() & 0xF) == 0 && !explosion.m_bIsBoat) {
|
2020-04-08 19:29:02 +00:00
|
|
|
CVehicle *veh = (CVehicle*)explosion.m_pVictimEntity;
|
|
|
|
uint8 component = CAR_WING_LR;
|
|
|
|
|
|
|
|
// miami leftover
|
|
|
|
if (veh->IsBike())
|
|
|
|
component = BIKE_FORKS_REAR;
|
|
|
|
|
|
|
|
if (veh->IsComponentPresent(component)) {
|
|
|
|
CVector componentPos;
|
|
|
|
veh->GetComponentWorldPosition(component, componentPos);
|
2020-10-05 13:14:48 +00:00
|
|
|
CParticle::AddJetExplosion(componentPos, 0.5f, 0.0f);
|
2020-04-08 19:29:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (CTimer::GetTimeInMilliseconds() > explosion.m_fStartTime) {
|
|
|
|
explosion.m_fStartTime = CTimer::GetTimeInMilliseconds() + 125 + (CGeneral::GetRandomNumber() & 0x7F);
|
|
|
|
CVector pos = explosion.m_pVictimEntity->GetPosition();
|
2020-10-05 13:14:48 +00:00
|
|
|
for (int i = 0; i < (CGeneral::GetRandomNumber() & 1) + 1; i++)
|
2020-04-08 19:29:02 +00:00
|
|
|
CParticle::AddParticle(PARTICLE_EXPLOSION_MEDIUM, pos, CVector(0.0f, 0.0f, 0.0f), nil, 3.5f, color);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (CTimer::GetFrameCounter() & 1) {
|
|
|
|
CPointLights::AddLight(CPointLights::LIGHT_POINT, explosion.m_vecPosition, CVector(0.0f, 0.0f, 0.0f), 15.0f, 1.0f, 0.0f, 0.0f, CPointLights::FOG_NONE, true);
|
|
|
|
CCoronas::RegisterCorona((uintptr)&explosion, 200, 100, 0, 255, explosion.m_vecPosition, 6.0f, 80.0f, gpCoronaTexture[0], CCoronas::TYPE_NORMAL, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
|
|
|
|
} else
|
|
|
|
CCoronas::RegisterCorona((uintptr)&explosion, 128, 0, 0, 255, explosion.m_vecPosition, 8.0f, 80.0f, gpCoronaTexture[0], CCoronas::TYPE_NORMAL, CCoronas::REFLECTION_ON, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
|
|
|
|
|
|
|
|
CCoronas::RegisterCorona((uintptr)&explosion + 1, 30, 15, 0, 255, explosion.m_vecPosition, explosion.m_fRadius, 80.0f, gpCoronaTexture[7], CCoronas::TYPE_STAR, CCoronas::REFLECTION_OFF, CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
|
|
|
|
} else if (explosion.m_nIteration & 1) {
|
|
|
|
if (explosion.m_pVictimEntity != nil)
|
|
|
|
CParticle::AddParticle(PARTICLE_ENGINE_SMOKE2, explosion.m_pVictimEntity->GetPosition(), CVector(0.0f, 0.0f, 0.0f), nil, CGeneral::GetRandomNumberInRange(0.5f, 0.8f), color);
|
|
|
|
CVector pos = explosion.m_vecPosition;
|
|
|
|
pos.z += 1.0f;
|
|
|
|
CParticle::AddParticle(PARTICLE_ENGINE_SMOKE2, pos, CVector(0.0f, 0.0f, 0.11f), nil, CGeneral::GetRandomNumberInRange(0.5f, 2.0f), color);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EXPLOSION_TANK_GRENADE:
|
|
|
|
case EXPLOSION_HELI_BOMB:
|
|
|
|
if (explosion.m_nIteration < 5) {
|
|
|
|
float ff = ((float)explosion.m_nIteration * 0.65f);
|
|
|
|
for (int i = 0; i < 10 * ff; i++) {
|
|
|
|
uint8 x = CGeneral::GetRandomNumber(), y = CGeneral::GetRandomNumber(), z = CGeneral::GetRandomNumber();
|
|
|
|
CVector pos(x - 128, y - 128, (z % 128) + 1);
|
|
|
|
|
|
|
|
pos.Normalise();
|
2020-10-05 13:14:48 +00:00
|
|
|
pos *= (explosion.m_nIteration + 1) * ff / 5.0f;
|
2020-04-08 19:29:02 +00:00
|
|
|
pos += explosion.m_vecPosition;
|
|
|
|
pos.z += 0.5f;
|
|
|
|
CParticle::AddParticle(PARTICLE_EXPLOSION_LARGE, pos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, color, CGeneral::GetRandomNumberInRange(-3.0f, 3.0f), CGeneral::GetRandomNumberInRange(-180.0f, 180.0f));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2020-10-05 13:14:48 +00:00
|
|
|
default:
|
|
|
|
break;
|
2020-04-08 19:29:02 +00:00
|
|
|
}
|
|
|
|
if (someTime > 0)
|
|
|
|
explosion.m_nIteration++;
|
|
|
|
else
|
|
|
|
explosion.m_nIteration = 0;
|
|
|
|
}
|
|
|
|
}
|
2020-03-12 16:26:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2020-04-08 19:29:02 +00:00
|
|
|
CExplosion::TestForExplosionInArea(eExplosionType type, float x1, float x2, float y1, float y2, float z1, float z2)
|
2020-03-12 16:26:47 +00:00
|
|
|
{
|
|
|
|
for (int i = 0; i < ARRAY_SIZE(gaExplosion); i++) {
|
2020-04-08 19:29:02 +00:00
|
|
|
if (gaExplosion[i].m_nIteration != 0) {
|
|
|
|
if (type == gaExplosion[i].m_ExplosionType) {
|
2020-03-12 16:26:47 +00:00
|
|
|
if (gaExplosion[i].m_vecPosition.x >= x1 && gaExplosion[i].m_vecPosition.x <= x2) {
|
|
|
|
if (gaExplosion[i].m_vecPosition.y >= y1 && gaExplosion[i].m_vecPosition.y <= y2) {
|
|
|
|
if (gaExplosion[i].m_vecPosition.z >= z1 && gaExplosion[i].m_vecPosition.z <= z2)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-04-08 19:29:02 +00:00
|
|
|
void
|
|
|
|
CExplosion::RemoveAllExplosionsInArea(CVector pos, float radius)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < ARRAY_SIZE(gaExplosion); i++) {
|
|
|
|
if (gaExplosion[i].m_nIteration != 0) {
|
|
|
|
if ((pos - gaExplosion[i].m_vecPosition).MagnitudeSqr() < SQR(radius))
|
|
|
|
gaExplosion[i].m_nIteration = 0;
|
|
|
|
}
|
|
|
|
}
|
2020-04-17 13:31:11 +00:00
|
|
|
}
|