forked from Ports/goldeneye-pc-port
2403 lines
83 KiB
C
2403 lines
83 KiB
C
#ifdef PORT
|
|
#include "porttick.h" /* D486 */
|
|
#endif
|
|
#include <ultra64.h>
|
|
#if defined(PORT)
|
|
#include "portaddr.h"
|
|
#else
|
|
#define PORT_N64PTR(T, x) ((T *)(x))
|
|
#endif
|
|
#include <PR/os.h>
|
|
#include <PR/gbi.h>
|
|
#include <gbi_extension.h>
|
|
#include <bondconstants.h>
|
|
#include <bondtypes.h>
|
|
#include <limits.h>
|
|
#include "bg.h"
|
|
#include "bondview.h"
|
|
#include "cheat.h"
|
|
#include "chrai.h"
|
|
#include "chraction.h"
|
|
#include "propobj.h"
|
|
#include "dyn.h"
|
|
#include "explosion.h"
|
|
#include "fr.h"
|
|
#include "image_bank.h"
|
|
#include "othermodemicrocode.h"
|
|
#include "lv.h"
|
|
#include "matrixmath.h"
|
|
#include "music.h"
|
|
#include "player.h"
|
|
#include "random.h"
|
|
#include "snd.h"
|
|
#include "stan.h"
|
|
#include "bgroomtrans.h"
|
|
#include <assets/oddtextures.h>
|
|
|
|
// bss
|
|
//CODE.bss:8007A100
|
|
// possibly printf("Allocating %d bytes for glass data (%d bits)\n",DAT_83bd5fb0 * 0x88 + 0xf & 0xfffffff0, DAT_83bd5fb0);
|
|
Mtx dword_CODE_bss_8007A100;
|
|
|
|
/**
|
|
* g_SmokeBuffer = mempAllocBytesInBank(0x1FE0, MEMPOOL_STAGE);
|
|
* printf("Allocating %d bytes for smoke data\n",0x9f60);
|
|
* Address 0x8007A140.
|
|
*/
|
|
struct Smoke *g_SmokeBuffer;
|
|
|
|
/**
|
|
* g_ExplosionBuffer = mempAllocBytesInBank(0x1740, MEMPOOL_STAGE);
|
|
* printf("Allocating %d bytes for explosion data\n",0x2e80);
|
|
* Address 0x8007A144.
|
|
*/
|
|
struct Explosion *g_ExplosionBuffer;
|
|
|
|
//CODE.bss:8007A148
|
|
s32 max_particles;
|
|
//CODE.bss:8007A14C
|
|
// printf("Allocating %d bytes for debris data (%d bits)\n", DAT_83bd2af0 * 0xa4, DAT_83bd2af0);
|
|
struct FlyingParticles *g_FlyingParticlesBuffer;
|
|
|
|
/**
|
|
* g_ScorchBuffer = mempAllocBytesInBank(0x6E0, MEMPOOL_STAGE);
|
|
* printf("Allocating %d bytes for scorch data\n",0xa50);
|
|
* sizeof each entry == 0x58
|
|
* Address 0x8007A150.
|
|
*/
|
|
struct Scorch *g_ScorchBuffer;
|
|
|
|
/**
|
|
* g_BulletImpactBuffer = mempAllocBytesInBank(0x1F40, MEMPOOL_STAGE);
|
|
* printf("Allocating %d bytes for wallhit data\n",0x3070);
|
|
* Address 0x8007A154.
|
|
* cannonically wallhitlist
|
|
*/
|
|
struct BulletImpact *g_BulletImpactBuffer;
|
|
#ifdef PORT
|
|
s32 g_BulletImpactBufferLen = BULLET_IMPACT_BUFFER_LEN_DEFAULT;
|
|
#endif
|
|
|
|
// data
|
|
//D:80040170
|
|
s32 g_NumExplosionEntries = 0;
|
|
//D:80040174
|
|
s32 g_NumSmokeEntries = 0;
|
|
//D:80040178
|
|
f32 g_SpExplosionDamageMult = 1.0;
|
|
|
|
#if defined(VERSION_EU)
|
|
s_smoketype g_SmokeTypes[] = {
|
|
// dur, appr, dis, size, bgrate, r, g, b, fgrate, propclouds
|
|
{ 1, 50, 99, 0, 0.0f, 128, 128, 128, 0.3f, 150 },
|
|
{ 400, 50, 37, 60, 0.02f, 80, 80, 96, 0.3f, 150 },
|
|
{ 400, 50, 42, 20, 0.01f, 128, 128, 128, 0.3f, 150 },
|
|
{ 525, 50, 100, 100, 0.01f, 192, 192, 192, 0.3f, 150 },
|
|
{ 525, 50, 50, 80, 0.02f, 64, 64, 64, 0.3f, 150 },
|
|
{ 640, 50, 42, 190, 0.15f, 64, 64, 64, 0.3f, 150 },
|
|
{ 750, 50, 58, 300, 0.01f, 64, 64, 64, 0.3f, 150 },
|
|
{ 50, 50, 7, 15, 0.03f, 255, 255, 255, 0.3f, 150 },
|
|
{ 17, 1, 5, 30, 0.03f, 255, 255, 255, 2.0f, 25 },
|
|
{ 21, 1, 6, 16, 0.03f, 224, 224, 224, 3.0f, 25 },
|
|
{ 750, 50, 58, 900, 0.01f, 64, 64, 64, 0.3f, 150 }
|
|
};
|
|
#else
|
|
//D:8004017C
|
|
s_smoketype g_SmokeTypes[] = {
|
|
// dur, appr, dis,size, bgrate, r, g, b, fgrate, propclouds
|
|
{ 1, 60, 99, 0, 0.0f, 128, 128, 128, 0.3f, 180},
|
|
{ 480, 60, 45, 60, 0.02f, 80, 80, 96, 0.3f, 180},
|
|
{ 480, 60, 50, 20, 0.01f, 128, 128, 128, 0.3f, 180},
|
|
{ 640, 60, 120, 100, 0.01f, 192, 192, 192, 0.3f, 180},
|
|
{ 640, 60, 60, 80, 0.02f, 64, 64, 64, 0.3f, 180},
|
|
{ 770, 60, 50, 190, 0.15f, 64, 64, 64, 0.3f, 180},
|
|
{ 900, 60, 70, 300, 0.01f, 64, 64, 64, 0.3f, 180},
|
|
{ 60, 60, 8, 15, 0.03f, 255, 255, 255, 0.3f, 180},
|
|
{ 20, 1, 6, 30, 0.03f, 255, 255, 255, 2.0f, 30},
|
|
{ 25, 1, 7, 16, 0.03f, 224, 224, 224, 3.0f, 30},
|
|
{ 900, 60, 70, 900, 0.01f, 64, 64, 64, 0.3f, 180}
|
|
};
|
|
#endif
|
|
|
|
#if defined(VERSION_EU)
|
|
s_explosiontype g_ExplosionTypes[] = {
|
|
//hrange, vrange, hchg, vchg, expsize, exprang, dmgrang, dur, proprate, flarespd, nbits, bitsize, bitdist, bithvel, bitvvel, smoketype, sndid, damage
|
|
{ 0.1f, 0.1f, 0.0f, 0.0f, 0.1f, 0.0f, 0.0f, 1, 1, 1.0f, 0, 0.1f, 0.0f, 0.0f, 0.0f, 0, 0x00, 0.0f},
|
|
{ 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 25, 1, 1.0f, 10, 5.0f, 0.0f, 2.0f, 6.0f, 7, 0x00, 0.0f},
|
|
{ 20.0f, 20.0f, 0.0f, 0.0f, 30.0f, 50.0f, 50.0f, 67, 1, 3.0f, 40, 6.0f, 5.0f, 0.7f, 6.0f, 2, EXPLOSION_1B_SFX, 0.125f},
|
|
{ 50.0f, 50.0f, 0.0f, 0.0f, 50.0f, 100.0f, 100.0f, 75, 1, 4.0f, 50, 6.0f, 10.0f, 1.0f, 6.0f, 2, EXPLOSION_1C_SFX, 0.5f},
|
|
{ 60.0f, 80.0f, 1.20000004768f, 0.360000014305f, 100.0f, 150.0f, 280.0f, 100, 2, 5.0f, 80, 8.0f, 30.0f, 2.0f, 6.0f, 1, EXPLOSION_4A_SFX, 1.0f},
|
|
{ 60.0f, 120.0f, 1.20000004768f, 0.360000014305f, 150.0f, 200.0f, 310.0f, 100, 2, 5.0f, 80, 8.0f, 30.0f, 2.0f, 6.0f, 1, EXPLOSION_4A_SFX, 2.0f},
|
|
{ 20.0f, 20.0f, 0.0f, 0.0f, 22.0f, 40.0f, 40.0f, 67, 1, 3.0f, 40, 6.0f, 5.0f, 0.7f, 6.0f, 2, EXPLOSION_1B_SFX, 0.5f},
|
|
{ 35.0f, 40.0f, 0.0f, 0.0f, 35.0f, 70.0f, 70.0f, 75, 1, 4.0f, 50, 6.0f, 10.0f, 1.0f, 6.0f, 2, EXPLOSION_1C_SFX, 1.0f},
|
|
{ 50.0f, 80.0f, 1.20000004768f, 0.360000014305f, 50.0f, 100.0f, 220.0f, 100, 2, 5.0f, 80, 8.0f, 30.0f, 2.0f, 6.0f, 1, EXPLOSION_4A_SFX, 2.0f},
|
|
{ 60.0f, 120.0f, 1.20000004768f, 0.360000014305f, 50.0f, 130.0f, 230.0f, 100, 2, 5.0f, 80, 8.0f, 30.0f, 2.0f, 6.0f, 1, EXPLOSION_4A_SFX, 2.0f},
|
|
{ 40.0f, 40.0f, 0.5f, 0.239999994635582f, 70.0f, 100.0f, 180.0f, 162, 4, 5.0f, 120, 6.0f, 30.0f, 2.5f, 6.0f, 4, EXPLOSION_5A_SFX, 1.0f},
|
|
{ 50.0f, 50.0f, 0.699999988079071f, 0.5f, 100.0f, 150.0f, 260.0f, 150, 1, 4.0f, 150, 6.0f, 30.0f, 3.0f, 6.0f, 4, EXPLOSION_4A_SFX, 2.0f},
|
|
{ 70.0f, 60.0f, 1.20000004768372f, 0.699999988079071f, 150.0f, 225.0f, 320.0f, 150, 2, 5.0f, 150, 6.0f, 30.0f, 4.0f, 12.0f, 5, EXPLOSION_4A_SFX, 4.0f},
|
|
/* standard explosion for grenades and mines */
|
|
{ 80.0f, 60.0f, 2.40000009536743f, 0.899999976158142f, 200.0f, 300.0f, 480.0f, 150, 2, 5.0f, 200, 6.0f, 30.0f, 6.0f, 15.0f, 6, EXPLOSION_4B_SFX, 4.0f},
|
|
{ 50.0f, 50.0f, 0.0f, 0.0f, 120.0f, 200.0f, 400.0f, 125, 4, 4.0f, 150, 6.0f, 30.0f, 3.0f, 6.0f, 4, EXPLOSION_4B_SFX, 4.0f},
|
|
{ 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1, 1, 1.0f, 150, 6.0f, 30.0f, 2.5f, 6.0f, 7, EXPLOSION_2B_SFX, 0.0f},
|
|
{ 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1, 1, 1.0f, 100, 6.0f, 30.0f, 2.5f, 6.0f, 7, EXPLOSION_2B_SFX, 0.0f},
|
|
{ 80.0f, 60.0f, 18.0f, 6.0f, 1500.0f, 2200.0f, 3600.0f, 250, 1, 2.0f, 0, 0.0f, 0.0f, 0.0f, 0.0f, 0, EXPLOSION_4B_SFX, 4.0f},
|
|
{ 80.0f, 60.0f, 3.59999990463257f, 1.20000004768372f, 300.0f, 450.0f, 640.0f, 50, 1, 2.0f, 0, 0.0f, 0.0f, 0.0f, 0.0f, 0, EXPLOSION_4B_SFX, 4.0f},
|
|
/* facility remote mine */
|
|
{ 90.0f, 75.0f, 3.0f, 1.0f, 250.0f, 375.0f, 600.0f, 150, 2, 5.0f, 200, 6.0f, 30.0f, 6.0f, 15.0f, 6, EXPLOSION_4B_SFX, 4.0f},
|
|
{160.0f, 120.0f, 7.19999980926514f, 2.40000009536743f, 600.0f, 450.0f, 640.0f, 50, 1, 2.0f, 0, 0.0f, 0.0f, 0.0f, 0.0f, 0, EXPLOSION_4B_SFX, 4.0f},
|
|
};
|
|
#else
|
|
s_explosiontype g_ExplosionTypes[] = {
|
|
//hrange, vrange, hchg, vchg, expsize, exprang, dmgrang, dur, proprate, flarespd, nbits, bitsize, bitdist, bithvel, bitvvel, smoketype, sndid, damage
|
|
{ 0.1f, 0.1f, 0.0f, 0.0f, 0.1f, 0.0f, 0.0f, 1, 1, 1.0f, 0, 0.1f, 0.0f, 0.0f, 0.0f, 0, NOTHING_SFX, 0.0f},
|
|
{ 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 30, 1, 1.0f, 10, 5.0f, 0.0f, 2.0f, 6.0f, 7, NOTHING_SFX, 0.0f},
|
|
{ 20.0f, 20.0f, 0.0f, 0.0f, 30.0f, 50.0f, 50.0f, 80, 1, 3.0f, 40, 6.0f, 5.0f, 0.7f, 6.0f, 2, EXPLOSION_1B_SFX, 0.125f},
|
|
{ 50.0f, 50.0f, 0.0f, 0.0f, 50.0f, 100.0f, 100.0f, 90, 1, 4.0f, 50, 6.0f, 10.0f, 1.0f, 6.0f, 2, EXPLOSION_1C_SFX, 0.5f},
|
|
{ 60.0f, 80.0f, 1.0f, 0.3f, 100.0f, 150.0f, 280.0f, 120, 2, 5.0f, 80, 8.0f, 30.0f, 2.0f, 6.0f, 1, EXPLOSION_4A_SFX, 1.0f},
|
|
{ 60.0f, 120.0f, 1.0f, 0.3f, 150.0f, 200.0f, 310.0f, 120, 2, 5.0f, 80, 8.0f, 30.0f, 2.0f, 6.0f, 1, EXPLOSION_4A_SFX, 2.0f},
|
|
{ 20.0f, 20.0f, 0.0f, 0.0f, 22.0f, 40.0f, 40.0f, 80, 1, 3.0f, 40, 6.0f, 5.0f, 0.7f, 6.0f, 2, EXPLOSION_1B_SFX, 0.5f},
|
|
{ 35.0f, 40.0f, 0.0f, 0.0f, 35.0f, 70.0f, 70.0f, 90, 1, 4.0f, 50, 6.0f, 10.0f, 1.0f, 6.0f, 2, EXPLOSION_1C_SFX, 1.0f},
|
|
{ 50.0f, 80.0f, 1.0f, 0.3f, 50.0f, 100.0f, 220.0f, 120, 2, 5.0f, 80, 8.0f, 30.0f, 2.0f, 6.0f, 1, EXPLOSION_4A_SFX, 2.0f},
|
|
{ 60.0f, 120.0f, 1.0f, 0.3f, 50.0f, 130.0f, 230.0f, 120, 2, 5.0f, 80, 8.0f, 30.0f, 2.0f, 6.0f, 1, EXPLOSION_4A_SFX, 2.0f},
|
|
{ 40.0f, 40.0f, 0.4f, 0.2f, 70.0f, 100.0f, 180.0f, 170, 4, 5.0f, 120, 6.0f, 30.0f, 2.5f, 6.0f, 4, EXPLOSION_5A_SFX, 1.0f},
|
|
{ 50.0f, 50.0f, 0.6f, 0.4f, 100.0f, 150.0f, 260.0f, 180, 1, 4.0f, 150, 6.0f, 30.0f, 3.0f, 6.0f, 4, EXPLOSION_4A_SFX, 2.0f},
|
|
{ 70.0f, 60.0f, 1.0f, 0.6f, 150.0f, 225.0f, 320.0f, 180, 2, 5.0f, 150, 6.0f, 30.0f, 4.0f, 12.0f, 5, EXPLOSION_4A_SFX, 4.0f},
|
|
{ 80.0f, 60.0f, 2.0f, 0.7f, 200.0f, 300.0f, 480.0f, 180, 2, 5.0f, 200, 6.0f, 30.0f, 6.0f, 15.0f, 6, EXPLOSION_4B_SFX, 4.0f},
|
|
{ 50.0f, 50.0f, 0.0f, 0.0f, 120.0f, 200.0f, 400.0f, 150, 4, 4.0f, 150, 6.0f, 30.0f, 3.0f, 6.0f, 4, EXPLOSION_4B_SFX, 4.0f},
|
|
{ 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1, 1, 1.0f, 150, 6.0f, 30.0f, 2.5f, 6.0f, 7, EXPLOSION_2B_SFX, 0.0f},
|
|
{ 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1, 1, 1.0f, 100, 6.0f, 30.0f, 2.5f, 6.0f, 7, EXPLOSION_2B_SFX, 0.0f},
|
|
{ 80.0f, 60.0f, 15.0f, 5.0f, 1500.0f, 2200.0f, 3600.0f, 300, 1, 2.0f, 0, 0.0f, 0.0f, 0.0f, 0.0f, 0, EXPLOSION_4B_SFX, 4.0f},
|
|
{ 80.0f, 60.0f, 3.0f, 1.0f, 300.0f, 450.0f, 640.0f, 60, 1, 2.0f, 0, 0.0f, 0.0f, 0.0f, 0.0f, 0, EXPLOSION_4B_SFX, 4.0f},
|
|
{ 90.0f, 75.0f, 2.5f, 0.87f, 250.0f, 375.0f, 600.0f, 180, 2, 5.0f, 200, 6.0f, 30.0f, 6.0f, 15.0f, 6, EXPLOSION_4B_SFX, 4.0f},
|
|
{160.0f, 120.0f, 6.0f, 2.0f, 600.0f, 450.0f, 640.0f, 60, 1, 2.0f, 0, 0.0f, 0.0f, 0.0f, 0.0f, 0, EXPLOSION_4B_SFX, 4.0f},
|
|
};
|
|
#endif
|
|
|
|
Gfx * g_ExplosionDisplayLists[] = {
|
|
&globalDL_0x078,
|
|
&globalDL_0x120,
|
|
&globalDL_0x1c8,
|
|
&globalDL_0x270,
|
|
&globalDL_0x318,
|
|
&globalDL_0x3c0,
|
|
&globalDL_0x468,
|
|
&globalDL_0x510,
|
|
&globalDL_0x5b8,
|
|
&globalDL_0x660,
|
|
&globalDL_0x708,
|
|
&globalDL_0x7b0,
|
|
&globalDL_0x858,
|
|
&globalDL_0x900,
|
|
&globalDL_0x9a8
|
|
};
|
|
|
|
s32 g_NumParticleEntries = 0;
|
|
s32 g_NumScorchEntries = 0;
|
|
// canonically nextwallhit
|
|
s32 g_NumImpactEntries = 0;
|
|
|
|
//D:8004080C
|
|
s_impacttype g_ImpactTypes[] = {
|
|
{10.0f, 10.0f, 1, 2, 8},
|
|
{ 6.0f, 6.0f, 1, 2, 8},
|
|
{ 8.0f, 8.0f, 0, 2, 8},
|
|
{20.0f, 20.0f, 1, 2, 8},
|
|
{ 6.0f, 6.0f, 1, 2, 8},
|
|
{ 8.0f, 8.0f, 1, 2, 8},
|
|
{12.0f, 12.0f, 1, 2, 8},
|
|
{ 6.0f, 6.0f, 1, 2, 8},
|
|
{20.0f, 20.0f, 1, 2, 8},
|
|
{20.0f, 20.0f, 1, 2, 8},
|
|
{20.0f, 20.0f, 1, 2, 8},
|
|
{20.0f, 20.0f, 1, 2, 8},
|
|
{20.0f, 20.0f, 1, 2, 8},
|
|
{24.0f, 24.0f, 1, 2, 8},
|
|
{ 6.0f, 6.0f, 1, 2, 1},
|
|
{ 6.0f, 6.0f, 1, 2, 1},
|
|
{24.0f, 24.0f, 2, 2, 8},
|
|
{ 6.0f, 6.0f, 1, 2, 1},
|
|
{ 8.0f, 8.0f, 1, 2, 1},
|
|
{12.0f, 12.0f, 1, 2, 1},
|
|
};
|
|
|
|
// unused / unreferenced (padding)
|
|
u32 D_800408FC = 0;
|
|
|
|
Vtx g_ExplosionRenderPartDefaultVertex = {0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff };
|
|
Vtx g_SmokeRenderPartDefaultVertex = {0, 0, 0, 0, 0, 0, 0x0, 0x0, 0x0, 0x0 };
|
|
Vtx g_ScorchDefaultVertex = {0, 0, 0, 0, 0, 0, 0x0, 0x0, 0x0, 0xDC };
|
|
Vtx g_BulletImpactDefaultVertex = {0, 0, 0, 0, 0, 0, 0x0, 0x0, 0x0, 0xDC };
|
|
|
|
|
|
// rodata
|
|
|
|
/*** prototypes */
|
|
|
|
void explosionInitFlyingParticles(coord3d *spawnpos, f32 spawn_rand_scale, f32 spawn_horiz_drift_scale, f32 spawn_vert_drift_scale, f32 spawn_tex_scale);
|
|
s32 explosionRoundFloat(f32 arg0);
|
|
void explosionSetBulletImpactAlpha(s32 arg0);
|
|
void explosionInflictDamage(PropRecord *arg0, f32 arg1, f32 arg2);
|
|
void explosionInflictDamage(struct PropRecord *arg0, f32 arg1, f32 arg2);
|
|
void explosionScorchTick(struct coord3d *pos, f32 explosion_size, s16 room);
|
|
Gfx *explosionRenderPart(struct ExplosionPart *arg0, Gfx *gdl, struct coord3d *coord);
|
|
|
|
/*** *************************************************************************************************************/
|
|
|
|
/**
|
|
* Named same as Perfect Dark.
|
|
* NTSC 0x7F09C250
|
|
*/
|
|
#if defined(VERSION_JP) || defined(VERSION_EU)
|
|
s32
|
|
#else
|
|
void
|
|
#endif
|
|
explosionCreate(PropRecord *arg0, struct coord3d *target_pos, StandTile *target_stan, s16 explosion_type, s32 arg4, s32 player, u8 *rooms, s32 arg7)
|
|
{
|
|
s_explosiontype *sp44;
|
|
struct Explosion *sp40;
|
|
f32 sp3C;
|
|
f32 sp38;
|
|
s32 var_v0;
|
|
PropRecord *sp30;
|
|
|
|
sp44 = &g_ExplosionTypes[explosion_type];
|
|
sp40 = NULL;
|
|
|
|
#if defined(VERSION_US)
|
|
if ((explosion_type != 0x10) && (explosion_type != 1))
|
|
{
|
|
g_NumExplosionEntries = 6;
|
|
}
|
|
#endif
|
|
|
|
for (var_v0 = 0; var_v0 < EXPLOSION_BUFFER_LEN; var_v0++)
|
|
{
|
|
if (g_ExplosionBuffer[var_v0].prop == NULL)
|
|
{
|
|
sp40 = &g_ExplosionBuffer[var_v0];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (sp40 != NULL)
|
|
{
|
|
sp30 = chrpropAllocate();
|
|
|
|
#if defined(VERSION_JP) || defined(VERSION_EU)
|
|
if ((explosion_type != 0x10) && (explosion_type != 1))
|
|
{
|
|
g_NumExplosionEntries = 6;
|
|
}
|
|
#endif
|
|
|
|
if ((s32) sp44->sndID > 0)
|
|
{
|
|
chrobjSndCreatePostEventDefault(sndPlaySfx((struct ALBankAlt_s *) g_musicSfxBufferPtr, (s16) sp44->sndID, NULL), target_pos);
|
|
}
|
|
|
|
if (sp30 != NULL)
|
|
{
|
|
sp30->type = PROP_TYPE_EXPLOSION;
|
|
sp30->flags |= PROPFLAG_ONSCREEN;
|
|
sp30->explosion = sp40;
|
|
var_v0 = 0;
|
|
sp30->stan = target_stan;
|
|
sp30->pos.f[0] = target_pos->f[0];
|
|
sp30->pos.f[1] = target_pos->f[1];
|
|
sp30->pos.f[2] = target_pos->f[2];
|
|
|
|
while (rooms[var_v0] != 0xff && var_v0 < 7)
|
|
{
|
|
sp30->rooms[var_v0] = rooms[var_v0];
|
|
var_v0++;
|
|
}
|
|
|
|
sp30->rooms[var_v0] = 0xFF;
|
|
|
|
if (arg7 != 0)
|
|
{
|
|
sp30->flags |= PROPFLAG_00000008;
|
|
}
|
|
|
|
chrpropActivateThisFrame(sp30);
|
|
chrpropEnable(sp30);
|
|
|
|
sp40->explosion_type = explosion_type;
|
|
sp40->age = 0;
|
|
sp40->unk3CA = -1;
|
|
sp40->unk3CD = (u8) arg4;
|
|
sp40->prop = sp30;
|
|
sp40->source = arg0;
|
|
sp40->player = (s8) player;
|
|
|
|
if (arg4 != 0)
|
|
{
|
|
if ((arg0 != NULL) && (arg0->stan != NULL))
|
|
{
|
|
sp40->pos.f[0] = arg0->pos.f[0];
|
|
sp40->pos.f[1] = stanGetPositionYValue(arg0->stan, arg0->pos.f[0], arg0->pos.f[2]) + 4.0f;
|
|
sp40->pos.f[2] = arg0->pos.f[2];
|
|
sp40->room = getTileRoom(arg0->stan);
|
|
}
|
|
else
|
|
{
|
|
sp40->pos.f[0] = target_pos->f[0];
|
|
sp40->pos.f[1] = stanGetPositionYValue(target_stan, target_pos->f[0], target_pos->f[2]) + 4.0f;
|
|
sp40->pos.f[2] = target_pos->f[2];
|
|
sp40->room = getTileRoom(target_stan);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sp40->pos.f[0] = 999999.9f;
|
|
}
|
|
|
|
sp3C = ((RANDOMFRAC() * 0.5f) + 1.0f) * sp44->explosion_size;
|
|
sp38 = RANDOMFRAC() * M_TAU_F;
|
|
|
|
sp40->parts[0].size = cosf(sp38) * sp3C;
|
|
sp40->parts[0].rot = sinf(sp38) * sp3C;
|
|
sp40->parts[0].frame = 1;
|
|
sp40->parts[0].pos.f[0] = target_pos->f[0];
|
|
sp40->parts[0].pos.f[1] = target_pos->f[1];
|
|
sp40->parts[0].pos.f[2] = target_pos->f[2];
|
|
|
|
for (var_v0 = 0; var_v0 < sp44->numshrapnelbits; var_v0++)
|
|
{
|
|
explosionInitFlyingParticles(target_pos, sp44->shrapnel_scatter_dist, sp44->shrapnel_hvel, sp44->shrapnel_vvel, sp44->shrapnel_size);
|
|
}
|
|
|
|
if (getPlayerCount() >= 2)
|
|
{
|
|
for (var_v0 = 0; var_v0 < SMOKE_BUFFER_LEN; var_v0++)
|
|
{
|
|
if (g_SmokeBuffer[var_v0].prop != NULL)
|
|
{
|
|
struct Smoke *smoke = &g_SmokeBuffer[var_v0];
|
|
|
|
if (smoke->smoke_type != 7 && smoke->smoke_type != 8 && smoke->smoke_type != 9)
|
|
{
|
|
smoke->duration = g_SmokeTypes[smoke->smoke_type].duration;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#if defined(VERSION_JP) || defined(VERSION_EU)
|
|
return sp40 != 0;
|
|
#endif
|
|
}
|
|
|
|
|
|
void setSixExplosionAndSmokeEntries(void) {
|
|
g_NumExplosionEntries = 6;
|
|
g_NumSmokeEntries = 6;
|
|
}
|
|
|
|
|
|
void explosionScreenShake(coord3d* source_pos, coord3d* source_mag, coord3d* result)
|
|
{
|
|
PropRecord* explosion_prop;
|
|
f32 angle;
|
|
f32 diff_x;
|
|
f32 diff_z;
|
|
f32 mag_scalar_x;
|
|
f32 mag_scalar_z;
|
|
f32 diff_y;
|
|
f32 explosion_mag;
|
|
|
|
s32 i;
|
|
f32 dist;
|
|
f32 dist2;
|
|
|
|
if (g_NumExplosionEntries == 0)
|
|
{
|
|
viShake(0.0f);
|
|
return;
|
|
}
|
|
|
|
angle = 0.8f;
|
|
mag_scalar_x = (cosf(angle) * source_mag->x) - (sinf(angle) * source_mag->f[2]);
|
|
mag_scalar_z = (sinf(angle) * source_mag->x) + (cosf(angle) * source_mag->f[2]);
|
|
|
|
explosion_mag = 0.0f;
|
|
|
|
for (i = 0; i < EXPLOSION_BUFFER_LEN; i++)
|
|
{
|
|
explosion_prop = g_ExplosionBuffer[i].prop;
|
|
if (explosion_prop != NULL)
|
|
{
|
|
diff_x = explosion_prop->pos.x - source_pos->x;
|
|
diff_y = explosion_prop->pos.y - source_pos->y;
|
|
diff_z = explosion_prop->pos.z - source_pos->z;
|
|
#ifndef VERSION_US
|
|
dist = sqrtf((diff_x * diff_x) + (diff_y * diff_y) + (diff_z * diff_z));
|
|
if (dist == 0.0f) { dist = 0.0001f; }
|
|
dist2 = g_ExplosionTypes[g_ExplosionBuffer[i].explosion_type].explosion_size / dist;
|
|
#else
|
|
dist = (diff_x * diff_x) + (diff_y * diff_y) + (diff_z * diff_z);
|
|
dist2 = g_ExplosionTypes[g_ExplosionBuffer[i].explosion_type].explosion_size / sqrtf(dist);
|
|
#endif
|
|
explosion_mag += dist2 * 15.0f;
|
|
}
|
|
}
|
|
|
|
#ifdef PORT
|
|
/* D486 (RULE-2): the shake counters decayed once per frame; decay at the N64's 2-ticks-per-frame pace */
|
|
if (g_NumSmokeEntries > 0)
|
|
{
|
|
if (portN64FrameStep())
|
|
{
|
|
g_NumSmokeEntries--;
|
|
}
|
|
explosion_mag++;
|
|
}
|
|
|
|
if (portN64FrameStep())
|
|
{
|
|
g_NumExplosionEntries--;
|
|
}
|
|
#else
|
|
if (g_NumSmokeEntries > 0)
|
|
{
|
|
g_NumSmokeEntries--;
|
|
explosion_mag++;
|
|
}
|
|
|
|
g_NumExplosionEntries--;
|
|
#endif
|
|
if (g_NumExplosionEntries & 2)
|
|
{
|
|
result->y = explosion_mag;
|
|
explosion_mag = -explosion_mag;
|
|
}
|
|
else
|
|
{
|
|
result->y = -explosion_mag;
|
|
}
|
|
|
|
result->x = explosion_mag * mag_scalar_x;
|
|
result->z = explosion_mag * mag_scalar_z;
|
|
|
|
viShake((f32) g_NumExplosionEntries * explosion_mag);
|
|
}
|
|
|
|
/***
|
|
* see Perfect Dark void explosionInflictDamage(struct prop *expprop)
|
|
* Address 0x7F09C9D8 (NTSC)
|
|
*/
|
|
void explosionInflictDamage(PropRecord *arg0, f32 horiz_range, f32 vert_range)
|
|
{
|
|
s32 spE0[8];
|
|
PropRecord *temp_s0;
|
|
s16 *var_s3;
|
|
s_explosiontype *temp_s6;
|
|
struct Explosion *temp_s2;
|
|
|
|
temp_s2 = arg0->explosion;
|
|
temp_s6 = &g_ExplosionTypes[temp_s2->explosion_type];
|
|
|
|
if (temp_s2->age >= temp_s2->unk3CA)
|
|
{
|
|
chraiGetPropRoomIds(arg0, &spE0[0]);
|
|
roomGetProps(&spE0[0]);
|
|
|
|
for (var_s3 = ptr_list_object_lookup_indices; *var_s3 >= 0; var_s3++)
|
|
{
|
|
temp_s0 = &g_Props[*var_s3];
|
|
|
|
if ((temp_s0 != temp_s2->source) && (temp_s0->timetoregen == 0))
|
|
{
|
|
if (temp_s0->type == PROP_TYPE_OBJ || temp_s0->type == PROP_TYPE_WEAPON || temp_s0->type == PROP_TYPE_DOOR)
|
|
{
|
|
struct ObjectRecord *spCC;
|
|
f32 xdist;
|
|
f32 ydist;
|
|
f32 zdist;
|
|
|
|
spCC = temp_s0->obj;
|
|
xdist = spCC->runtime_pos.f[0] - arg0->pos.f[0];
|
|
ydist = spCC->runtime_pos.f[1] - arg0->pos.f[1];
|
|
zdist = spCC->runtime_pos.f[2] - arg0->pos.f[2];
|
|
|
|
if ((xdist <= horiz_range)
|
|
&& (-horiz_range <= xdist)
|
|
&& (ydist <= vert_range)
|
|
&& (-vert_range <= ydist)
|
|
&& (zdist <= horiz_range)
|
|
&& (-horiz_range <= zdist))
|
|
{
|
|
f32 xfrac;
|
|
f32 yfrac;
|
|
f32 zfrac;
|
|
f32 minfrac;
|
|
|
|
xfrac = xdist / horiz_range;
|
|
yfrac = ydist / vert_range;
|
|
zfrac = zdist / horiz_range;
|
|
|
|
if (xfrac < 0.0f)
|
|
{
|
|
xfrac = -xfrac;
|
|
}
|
|
|
|
if (yfrac < 0.0f)
|
|
{
|
|
yfrac = -yfrac;
|
|
}
|
|
|
|
if (zfrac < 0.0f)
|
|
{
|
|
zfrac = -zfrac;
|
|
}
|
|
|
|
xfrac = 1.0f - xfrac;
|
|
yfrac = 1.0f - yfrac;
|
|
zfrac = 1.0f - zfrac;
|
|
|
|
minfrac = xfrac;
|
|
|
|
if (yfrac < minfrac)
|
|
{
|
|
minfrac = yfrac;
|
|
}
|
|
|
|
if (zfrac < minfrac)
|
|
{
|
|
minfrac = zfrac;
|
|
}
|
|
|
|
minfrac = minfrac * EXPLOSION_DAMAGE_SCALER * temp_s6->damage;
|
|
|
|
if (!(spCC->runtime_bitflags & 0x1000) && !(spCC->flags2 & 0x200400))
|
|
{
|
|
maybe_detonate_object_and_its_children(
|
|
temp_s0,
|
|
((RANDOMFRAC() * 0.5f) + 1.0f) * minfrac,
|
|
&spCC->runtime_pos,
|
|
0x1D,
|
|
(s32) temp_s2->player);
|
|
}
|
|
}
|
|
|
|
}
|
|
else if (temp_s0->type == PROP_TYPE_CHR || temp_s0->type == PROP_TYPE_VIEWER)
|
|
{
|
|
f32 xdist;
|
|
f32 ydist;
|
|
f32 zdist;
|
|
|
|
xdist = temp_s0->pos.f[0] - arg0->pos.f[0];
|
|
ydist = temp_s0->pos.f[1] - arg0->pos.f[1];
|
|
zdist = temp_s0->pos.f[2] - arg0->pos.f[2];
|
|
|
|
if ((xdist <= horiz_range)
|
|
&& (-horiz_range <= xdist)
|
|
&& (ydist <= vert_range)
|
|
&& (-vert_range <= ydist)
|
|
&& (zdist <= horiz_range)
|
|
&& (-horiz_range <= zdist))
|
|
{
|
|
f32 xfrac;
|
|
f32 yfrac;
|
|
f32 zfrac;
|
|
f32 minfrac;
|
|
|
|
xfrac = xdist / horiz_range;
|
|
yfrac = ydist / vert_range;
|
|
zfrac = zdist / horiz_range;
|
|
|
|
if (xfrac < 0.0f)
|
|
{
|
|
xfrac = -xfrac;
|
|
}
|
|
|
|
if (yfrac < 0.0f)
|
|
{
|
|
yfrac = -yfrac;
|
|
}
|
|
|
|
if (zfrac < 0.0f)
|
|
{
|
|
zfrac = -zfrac;
|
|
}
|
|
|
|
xfrac = 1.0f - xfrac;
|
|
yfrac = 1.0f - yfrac;
|
|
zfrac = 1.0f - zfrac;
|
|
|
|
minfrac = xfrac;
|
|
|
|
if (yfrac < minfrac)
|
|
{
|
|
minfrac = yfrac;
|
|
}
|
|
|
|
if (zfrac < minfrac)
|
|
{
|
|
minfrac = zfrac;
|
|
}
|
|
|
|
minfrac *= minfrac;
|
|
minfrac = minfrac * EXPLOSION_DAMAGE_SCALER * temp_s6->damage;
|
|
|
|
if (temp_s0->type == PROP_TYPE_CHR)
|
|
{
|
|
chrlvExplosionDamage(temp_s0->chr, &arg0->pos, minfrac, 1);
|
|
}
|
|
else
|
|
{
|
|
s32 sp90;
|
|
|
|
if ((xdist != 0.0f) || (zdist != 0.0f))
|
|
{
|
|
f32 temp_f2_3 = sqrtf((xdist * xdist) + (zdist * zdist));
|
|
xdist *= 1.0f / temp_f2_3;
|
|
zdist *= 1.0f / temp_f2_3;
|
|
}
|
|
|
|
sp90 = get_cur_playernum();
|
|
set_cur_player(getPlayerPointerIndex(temp_s0));
|
|
|
|
if (getPlayerCount() == 1)
|
|
{
|
|
minfrac *= g_SpExplosionDamageMult;
|
|
}
|
|
|
|
if (isBondInTank() == 1)
|
|
{
|
|
minfrac *= 2.0f;
|
|
}
|
|
|
|
record_damage_kills(minfrac, xdist, zdist, (s32) temp_s2->player, 1);
|
|
set_cur_player(sp90);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
temp_s2->unk3CA = temp_s2->age + (temp_s6->duration >> 2);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***
|
|
* see Perfect Dark u32 explosionTick(struct prop *prop)
|
|
*
|
|
* NTSC address 0x7F09CEE8.
|
|
*/
|
|
s32 explosionTick(PropRecord* arg0)
|
|
{
|
|
s32 var_s4;
|
|
s32 j;
|
|
s32 k;
|
|
|
|
f32 hrange;
|
|
f32 vrange;
|
|
f32 temp_f20;
|
|
f32 temp_f12;
|
|
|
|
struct Explosion *exp;
|
|
s_explosiontype *explosiontype;
|
|
|
|
f32 lvupdate;
|
|
s32 sp9C;
|
|
struct coord3d sp90;
|
|
struct coord3d sp84;
|
|
|
|
|
|
exp = arg0->explosion;
|
|
explosiontype = &g_ExplosionTypes[exp->explosion_type];
|
|
|
|
if (g_ClockTimer == 0)
|
|
{
|
|
return TICKOP_NONE;
|
|
}
|
|
|
|
lvupdate = (g_ClockTimer < 15) ? (f32) g_ClockTimer : 15.0f;
|
|
|
|
if ((exp->age >= 8) && (exp->age < explosiontype->duration))
|
|
{
|
|
hrange = explosiontype->hrange + (explosiontype->hchange * exp->age);
|
|
vrange = explosiontype->vrange + (explosiontype->vchange * exp->age);
|
|
|
|
if (exp->explosion_type == 0xE)
|
|
{
|
|
if (exp->age < 0x20)
|
|
{
|
|
arg0->pos.f[1] += 10.0f * lvupdate;
|
|
}
|
|
|
|
if (exp->age >= 0x21)
|
|
{
|
|
hrange = (exp->age * 3.0f) + 40.0f;
|
|
|
|
if (hrange > 300.0f)
|
|
{
|
|
hrange = 300.0f;
|
|
}
|
|
|
|
vrange = 20.0f;
|
|
}
|
|
}
|
|
|
|
sp9C = (s32) (((f32)explosiontype->propagationrate * (f32)exp->age) / (f32)explosiontype->duration) + 1;
|
|
#ifdef PORT
|
|
/* D486 (RULE-2): parts spawned once per frame; spawn at the N64's 2-ticks-per-frame pace */
|
|
if (!portN64FrameStep())
|
|
{
|
|
sp9C = 0;
|
|
}
|
|
#endif
|
|
for (var_s4 = 0; var_s4 < sp9C; var_s4++)
|
|
{
|
|
for (j=0; j<EXPLOSION_PARTS_LEN; j++)
|
|
{
|
|
if (exp->parts[j].frame == 0)
|
|
{
|
|
exp->parts[j].frame = 1;
|
|
|
|
exp->parts[j].pos.f[0] = arg0->pos.f[0] + ((RANDOMFRAC() - 0.5f) * hrange);
|
|
exp->parts[j].pos.f[1] = arg0->pos.f[1] + ((RANDOMFRAC() - 0.5f) * vrange);
|
|
exp->parts[j].pos.f[2] = arg0->pos.f[2] + ((RANDOMFRAC() - 0.5f) * hrange);
|
|
|
|
temp_f20 = ((RANDOMFRAC() * 0.5f) + 1.0f) * explosiontype->explosion_size;
|
|
temp_f12 = RANDOMFRAC() * M_TAU_F;
|
|
|
|
exp->parts[j].size = cosf(temp_f12) * temp_f20;
|
|
exp->parts[j].rot = sinf(temp_f12) * temp_f20;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// see Perfect Dark void explosionGetBboxAtFrame(struct coord *lower, struct coord *upper, s32 frame, struct prop *prop)
|
|
|
|
hrange = (hrange * 0.5f) + explosiontype->explosion_size * 1.5f;
|
|
vrange = (vrange * 0.5f) + explosiontype->explosion_size * 1.5f;
|
|
|
|
sp90.f[0] = arg0->pos.f[0] - hrange;
|
|
sp90.f[1] = arg0->pos.f[1] - vrange;
|
|
sp90.f[2] = arg0->pos.f[2] - hrange;
|
|
|
|
sp84.f[0] = arg0->pos.f[0] + hrange;
|
|
sp84.f[1] = arg0->pos.f[1] + vrange;
|
|
sp84.f[2] = arg0->pos.f[2] + hrange;
|
|
|
|
// end explosionGetBboxAtFrame.
|
|
|
|
chrpropUpdateRoomList(arg0, &sp90, &sp84, hrange);
|
|
|
|
vrange = explosiontype->explosion_range + (((explosiontype->dmg_range - explosiontype->explosion_range) * (f32) exp->age) / (f32) explosiontype->duration);
|
|
explosionInflictDamage(arg0, vrange, vrange);
|
|
}
|
|
|
|
for (k = 0; k < (s32) lvupdate; k++)
|
|
{
|
|
exp->age++;
|
|
|
|
for (j=0; j<EXPLOSION_PARTS_LEN; j++)
|
|
{
|
|
if (exp->parts[j].frame > 0)
|
|
{
|
|
exp->parts[j].frame++;
|
|
}
|
|
}
|
|
|
|
if (((exp->age == 0xF) && (exp->explosion_type == 0xE))
|
|
|| (((exp->age + 0x14) == (s16) explosiontype->duration) && (exp->explosion_type != 0xE)))
|
|
{
|
|
if ((exp->source != NULL) && (exp->source->stan != NULL))
|
|
{
|
|
if (exp->source->type == PROP_TYPE_OBJ)
|
|
{
|
|
struct ObjectRecord *obj = exp->source->obj;
|
|
explosionCreateSmoke(&obj->runtime_pos, exp->source->stan, (s16) explosiontype->smoketype, exp->source->rooms, (arg0->flags & 8) != 0);
|
|
}
|
|
else
|
|
{
|
|
explosionCreateSmoke(&exp->source->pos, exp->source->stan, (s16) explosiontype->smoketype, exp->source->rooms, (arg0->flags & 8) != 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
explosionCreateSmoke(&arg0->pos, arg0->stan, (s16) explosiontype->smoketype, arg0->rooms, (arg0->flags & 8) != 0);
|
|
}
|
|
}
|
|
|
|
if ((exp->age == ((s16) explosiontype->duration >> 1)) && (exp->unk3CD != 0))
|
|
{
|
|
explosionScorchTick(&exp->pos, explosiontype->explosion_size * 4.0f, exp->room);
|
|
}
|
|
}
|
|
|
|
if (exp->age >= explosiontype->duration + (s32) (16.0f * explosiontype->flareanimspeed))
|
|
{
|
|
exp->prop = NULL;
|
|
|
|
return TICKOP_FREE;
|
|
}
|
|
|
|
return TICKOP_NONE;
|
|
}
|
|
|
|
|
|
/*
|
|
* Address: 0x7F09D4EC
|
|
*/
|
|
u8 explosionChrpropExplosionTick(PropRecord* prop)
|
|
{
|
|
Mtxf* player_matrix;
|
|
|
|
player_matrix = camGetWorldToScreenMtxf();
|
|
prop->zDepth = -((((player_matrix->m[0][2] * prop->pos.x) + (player_matrix->m[1][2] * prop->pos.y)) + (player_matrix->m[2][2] * prop->pos.z)) + player_matrix->m[3][2]);
|
|
|
|
if (prop->zDepth < 100.0f)
|
|
{
|
|
prop->zDepth *= 0.5f;
|
|
}
|
|
else
|
|
{
|
|
prop->zDepth -= 100.0f;
|
|
}
|
|
|
|
if (g_ClockTimer == 0)
|
|
{
|
|
return TICKOP_NONE;
|
|
}
|
|
|
|
return TICKOP_NONE;
|
|
}
|
|
|
|
|
|
/***
|
|
* Perfect Dark Gfx *explosionRender(struct prop *prop, Gfx *gdl, bool xlupass)
|
|
*
|
|
* NTSC address 0x7F09D5A0.
|
|
*/
|
|
Gfx *explosionRenderPropExplosion(PropRecord *prop, Gfx *gdl, s32 withalpha)
|
|
{
|
|
s32 temp_s1;
|
|
struct Explosion *temp_s5;
|
|
struct coord3d *temp_s6;
|
|
s32 var_s2;
|
|
|
|
struct bbox2d sp70;
|
|
|
|
s32 temp_f10;
|
|
|
|
s32 i;
|
|
|
|
temp_s1 = prop->rooms[0];
|
|
temp_s5 = prop->explosion;
|
|
temp_s6 = getRoomPositionByIndex((s32) temp_s1);
|
|
|
|
if (withalpha == 0)
|
|
{
|
|
return gdl;
|
|
}
|
|
else
|
|
{
|
|
if (getPropCombinedRoomsBBox2D(prop, &sp70) > 0)
|
|
{
|
|
gdl = bgScissorCurrentPlayerViewF(gdl, sp70.min.f[0], sp70.min.f[1], sp70.max.f[0], sp70.max.f[1]);
|
|
}
|
|
else
|
|
{
|
|
gdl = bgScissorCurrentPlayerViewDefault(gdl);
|
|
}
|
|
|
|
gSPClearGeometryMode(gdl++, G_CULL_BOTH | G_FOG);
|
|
gSPMatrix(gdl++, osVirtualToPhysical((void*)get_BONDdata_field_10E0()), (G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION));
|
|
|
|
gdl = applyRoomMatrixToDisplayList(gdl, temp_s1);
|
|
|
|
gSPSegment(gdl++, SPSEGMENT_GETITLE, osVirtualToPhysical(pGlobalimagetable));
|
|
|
|
for (var_s2 = 14;
|
|
var_s2 >= 0;
|
|
var_s2--)
|
|
{
|
|
gSPDisplayList(gdl++, g_ExplosionDisplayLists[var_s2]);
|
|
|
|
for (i = 0; i < EXPLOSION_PARTS_LEN; i++)
|
|
{
|
|
if (temp_s5->parts[i].frame > 0
|
|
&& var_s2 == (s32)( (f32)(temp_s5->parts[i].frame - 1) / g_ExplosionTypes[temp_s5->explosion_type].flareanimspeed ) )
|
|
{
|
|
gdl = explosionRenderPart(&temp_s5->parts[i], gdl, temp_s6);
|
|
}
|
|
}
|
|
}
|
|
|
|
gSPMatrix(gdl++, osVirtualToPhysical((void*)currentPlayerGetProjectionMatrix()), (G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION));
|
|
|
|
temp_f10 = (s32) (g_ExplosionTypes[temp_s5->explosion_type].flareanimspeed * 15.0f);
|
|
|
|
for (i = 0; i < EXPLOSION_PARTS_LEN; i++)
|
|
{
|
|
if (temp_f10 < temp_s5->parts[i].frame)
|
|
{
|
|
temp_s5->parts[i].frame = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
return gdl;
|
|
}
|
|
|
|
|
|
|
|
/***
|
|
* Perfect Dark Gfx *explosionRenderPart(struct explosion *exp, struct explosionpart *part, Gfx *gdl, struct coord *coord, s32 arg4)
|
|
*
|
|
* NTSC address 0x7F09D82C.
|
|
*/
|
|
Gfx *explosionRenderPart(struct ExplosionPart *arg0, Gfx *gdl, struct coord3d *coord)
|
|
{
|
|
s32 padding1;
|
|
f32 f2;
|
|
|
|
Vtx spA0;
|
|
Mtxf *sp9C;
|
|
struct coord3d *sp98;
|
|
struct coord3d sp8C;
|
|
struct coord3d sp80;
|
|
struct coord3d sp74;
|
|
struct coord3d sp68;
|
|
|
|
f32 sp64;
|
|
f32 sp60;
|
|
f32 sp5C;
|
|
|
|
Vtx *vertices;
|
|
|
|
f32 sp54;
|
|
f32 sp50;
|
|
|
|
f32 sp4c;
|
|
f32 sp48;
|
|
f32 sp44;
|
|
|
|
f32 temp_f0;
|
|
f32 var_f12;
|
|
|
|
spA0 = g_ExplosionRenderPartDefaultVertex;
|
|
|
|
sp9C = currentPlayerGetViewToWorldMtxf();
|
|
sp98 = bondviewGetCurrentPlayersPosition();
|
|
|
|
sp64 = arg0->pos.f[0] - sp98->f[0];
|
|
sp60 = arg0->pos.f[1] - sp98->f[1];
|
|
sp5C = arg0->pos.f[2] - sp98->f[2];
|
|
|
|
temp_f0 = sqrtf((sp64 * sp64) + (sp60 * sp60) + (sp5C * sp5C));
|
|
var_f12 = temp_f0 * 0.5f;
|
|
if (var_f12 > 100.0f)
|
|
{
|
|
var_f12 = 100.0f;
|
|
}
|
|
|
|
if (temp_f0 == 0)
|
|
{
|
|
f2 = 0.0f;
|
|
}
|
|
else
|
|
{
|
|
f2 = (temp_f0 - var_f12) / temp_f0;
|
|
}
|
|
|
|
sp54 = arg0->size * f2;
|
|
sp50 = arg0->rot * f2;
|
|
|
|
sp4c = sp98->f[0] + (sp64 * f2);
|
|
sp48 = sp98->f[1] + (sp60 * f2);
|
|
sp44 = sp98->f[2] + (sp5C * f2);
|
|
|
|
vertices = dynAllocateVertices(4);
|
|
|
|
vertices[0] = spA0;
|
|
vertices[1] = spA0;
|
|
vertices[2] = spA0;
|
|
vertices[3] = spA0;
|
|
/* D252 (2026-09-18): dropped a stray vertices[4] = spA0 write here -- this
|
|
* function only allocates 4 Vtx slots (dynAllocateVertices(4) above) and
|
|
* only ever uses 4 (gSPVertex(..., 4, 0) / gSP2Triangles(0,1,2,...,2,3,0)
|
|
* below), so vertices[4] was never part of this quad's own draw -- it was
|
|
* a genuine one-Vtx-sized out-of-bounds write into whatever the next
|
|
* dynAllocate* call in the same frame claims from the shared bump-
|
|
* allocated pool (dyn.c's g_GfxMemPos), corrupting unrelated particle/
|
|
* matrix/light data. Removing it changes zero bytes of what this
|
|
* function itself draws. Prime suspect for D252's rainbow-particle
|
|
* corruption; see docs/dev/findings.md D252 for the full mechanism and
|
|
* why this required the project owner's explicit go-ahead to touch
|
|
* (decomp-verified original code, not an ABI/pointer-width artifact). */
|
|
|
|
sp8C.f[0] = sp9C->m[0][0] * sp54;
|
|
sp8C.f[1] = sp9C->m[0][1] * sp54;
|
|
sp8C.f[2] = sp9C->m[0][2] * sp54;
|
|
|
|
sp80.f[0] = sp9C->m[0][0] * sp50;
|
|
sp80.f[1] = sp9C->m[0][1] * sp50;
|
|
sp80.f[2] = sp9C->m[0][2] * sp50;
|
|
|
|
sp74.f[0] = sp9C->m[1][0] * sp54;
|
|
sp74.f[1] = sp9C->m[1][1] * sp54;
|
|
sp74.f[2] = sp9C->m[1][2] * sp54;
|
|
|
|
sp68.f[0] = sp9C->m[1][0] * sp50;
|
|
sp68.f[1] = sp9C->m[1][1] * sp50;
|
|
sp68.f[2] = sp9C->m[1][2] * sp50;
|
|
|
|
vertices[0].v.ob[0] = (sp4c - sp8C.f[0] - sp68.f[0]) * get_room_data_float1() - coord->f[0];
|
|
vertices[0].v.ob[1] = (sp48 - sp8C.f[1] - sp68.f[1]) * get_room_data_float1() - coord->f[1];
|
|
vertices[0].v.ob[2] = (sp44 - sp8C.f[2] - sp68.f[2]) * get_room_data_float1() - coord->f[2];
|
|
vertices[0].v.tc[0] = 1760;
|
|
vertices[0].v.tc[1] = 0;
|
|
|
|
vertices[1].v.ob[0] = (sp4c + sp80.f[0] - sp74.f[0]) * get_room_data_float1() - coord->f[0];
|
|
vertices[1].v.ob[1] = (sp48 + sp80.f[1] - sp74.f[1]) * get_room_data_float1() - coord->f[1];
|
|
vertices[1].v.ob[2] = (sp44 + sp80.f[2] - sp74.f[2]) * get_room_data_float1() - coord->f[2];
|
|
vertices[1].v.tc[0] = 0;
|
|
vertices[1].v.tc[1] = 0;
|
|
|
|
vertices[2].v.ob[0] = (sp4c + sp8C.f[0] + sp68.f[0]) * get_room_data_float1() - coord->f[0];
|
|
vertices[2].v.ob[1] = (sp48 + sp8C.f[1] + sp68.f[1]) * get_room_data_float1() - coord->f[1];
|
|
vertices[2].v.ob[2] = (sp44 + sp8C.f[2] + sp68.f[2]) * get_room_data_float1() - coord->f[2];
|
|
vertices[2].v.tc[0] = 0;
|
|
vertices[2].v.tc[1] = 1760;
|
|
|
|
vertices[3].v.ob[0] = (sp4c - sp80.f[0] + sp74.f[0]) * get_room_data_float1() - coord->f[0];
|
|
vertices[3].v.ob[1] = (sp48 - sp80.f[1] + sp74.f[1]) * get_room_data_float1() - coord->f[1];
|
|
vertices[3].v.ob[2] = (sp44 - sp80.f[2] + sp74.f[2]) * get_room_data_float1() - coord->f[2];
|
|
vertices[3].v.tc[0] = 1760;
|
|
vertices[3].v.tc[1] = 1760;
|
|
|
|
gSPVertex(gdl++, osVirtualToPhysical(vertices), 4, 0);
|
|
|
|
gSP2Triangles(gdl++, 0, 1, 2, 0, 0, 2, 3, 0);
|
|
|
|
return gdl;
|
|
}
|
|
|
|
|
|
|
|
/***
|
|
* Perfect Dark Gfx *smokeRenderPart(struct smoke *smoke, struct smokepart *part, Gfx *gdl, struct coord *coord, f32 size)
|
|
*
|
|
* NTSC address 0x7F09DDA4.
|
|
*/
|
|
Gfx *explosionSmokeRenderPart(struct Smoke *smoke, struct SmokePart *smoke_part, Gfx *gdl, struct coord3d *arg3)
|
|
{
|
|
Vtx *vertices;
|
|
Vtx spC0;
|
|
Mtxf *mtx;
|
|
struct coord3d spB0;
|
|
struct coord3d spA4;
|
|
struct coord3d sp98;
|
|
struct coord3d sp8C;
|
|
f32 sp88;
|
|
f32 sp84;
|
|
f32 sp80;
|
|
f32 sp7C;
|
|
f32 sp78;
|
|
u8 sp77;
|
|
struct coord3d *sp70;
|
|
f32 sp6C;
|
|
f32 sp68;
|
|
f32 sp64;
|
|
f32 temp_f0;
|
|
f32 range;
|
|
f32 mult;
|
|
f32 sp54;
|
|
f32 sp50;
|
|
f32 sp4C;
|
|
|
|
spC0 = g_SmokeRenderPartDefaultVertex;
|
|
|
|
mtx = currentPlayerGetViewToWorldMtxf();
|
|
sp70 = bondviewGetCurrentPlayersPosition();
|
|
|
|
if (g_SmokeTypes[smoke->smoke_type].rateappear >= smoke_part->count)
|
|
{
|
|
sp77 = (smoke_part->alpha / (f32) g_SmokeTypes[smoke->smoke_type].rateappear) * smoke_part->count;
|
|
}
|
|
else
|
|
{
|
|
sp77 = smoke_part->alpha;
|
|
}
|
|
|
|
vertices = dynAllocateVertices(4);
|
|
|
|
vertices[0] = spC0;
|
|
vertices[1] = spC0;
|
|
vertices[2] = spC0;
|
|
vertices[3] = spC0;
|
|
|
|
sp88 = cosf(smoke_part->rot) * smoke_part->size;
|
|
sp84 = sinf(smoke_part->rot) * smoke_part->size;
|
|
|
|
sp80 = smoke_part->pos.f[0] + (sinf(smoke_part->offset1) * 7.0f);
|
|
sp7C = smoke_part->pos.f[1];
|
|
sp78 = smoke_part->pos.f[2] + (sinf(smoke_part->offset2) * 7.0f);
|
|
|
|
sp6C = sp80 - sp70->f[0];
|
|
sp68 = sp7C - sp70->f[1];
|
|
sp64 = sp78 - sp70->f[2];
|
|
|
|
temp_f0 = sqrtf((sp6C * sp6C) + (sp68 * sp68) + (sp64 * sp64));
|
|
|
|
if (temp_f0 > 30000.0f)
|
|
{
|
|
return gdl;
|
|
}
|
|
|
|
range = temp_f0 * 0.5f;
|
|
|
|
if (range > 100.0f) {
|
|
range = 100.0f;
|
|
}
|
|
|
|
if (temp_f0 == 0.0f) {
|
|
mult = 0.0f;
|
|
} else {
|
|
mult = (temp_f0 - range) / temp_f0;
|
|
}
|
|
|
|
sp88 = sp88 * mult;
|
|
sp84 = sp84 * mult;
|
|
|
|
sp80 = sp70->f[0] + sp6C * mult;
|
|
sp7C = sp70->f[1] + sp68 * mult;
|
|
sp78 = sp70->f[2] + sp64 * mult;
|
|
|
|
spB0.f[0] = mtx->m[0][0] * sp88;
|
|
spB0.f[1] = mtx->m[0][1] * sp88;
|
|
spB0.f[2] = mtx->m[0][2] * sp88;
|
|
spA4.f[0] = mtx->m[0][0] * sp84;
|
|
spA4.f[1] = mtx->m[0][1] * sp84;
|
|
spA4.f[2] = mtx->m[0][2] * sp84;
|
|
sp98.f[0] = mtx->m[1][0] * sp88;
|
|
sp98.f[1] = mtx->m[1][1] * sp88;
|
|
sp98.f[2] = mtx->m[1][2] * sp88;
|
|
sp8C.f[0] = mtx->m[1][0] * sp84;
|
|
sp8C.f[1] = mtx->m[1][1] * sp84;
|
|
sp8C.f[2] = mtx->m[1][2] * sp84;
|
|
|
|
sp54 = ((sp80 - spB0.f[0] - sp8C.f[0]) * get_room_data_float1() - arg3->f[0]) * 10.0f;
|
|
sp50 = ((sp7C - spB0.f[1] - sp8C.f[1]) * get_room_data_float1() - arg3->f[1]) * 10.0f;
|
|
sp4C = ((sp78 - spB0.f[2] - sp8C.f[2]) * get_room_data_float1() - arg3->f[2]) * 10.0f;
|
|
|
|
if (sp54 > 30000.0f
|
|
|| sp54 < -30000.0f
|
|
|| sp50 > 30000.0f
|
|
|| sp50 < -30000.0f
|
|
|| sp4C > 30000.0f
|
|
|| sp4C < -30000.0f)
|
|
{
|
|
return gdl;
|
|
}
|
|
|
|
vertices[0].v.ob[0] = sp54;
|
|
vertices[0].v.ob[1] = sp50;
|
|
vertices[0].v.ob[2] = sp4C;
|
|
vertices[0].v.tc[0] = 1760;
|
|
vertices[0].v.tc[1] = 0;
|
|
vertices[0].v.cn[0] = g_SmokeTypes[smoke->smoke_type].r;
|
|
vertices[0].v.cn[1] = g_SmokeTypes[smoke->smoke_type].g;
|
|
vertices[0].v.cn[2] = g_SmokeTypes[smoke->smoke_type].b;
|
|
vertices[0].v.cn[3] = sp77;
|
|
|
|
vertices[1].v.ob[0] = ((((sp80 + spA4.f[0]) - sp98.f[0]) * get_room_data_float1()) - arg3->f[0]) * 10.0f;
|
|
vertices[1].v.ob[1] = ((((sp7C + spA4.f[1]) - sp98.f[1]) * get_room_data_float1()) - arg3->f[1]) * 10.0f;
|
|
vertices[1].v.ob[2] = ((((sp78 + spA4.f[2]) - sp98.f[2]) * get_room_data_float1()) - arg3->f[2]) * 10.0f;
|
|
vertices[1].v.tc[0] = 0;
|
|
vertices[1].v.tc[1] = 0;
|
|
vertices[1].v.cn[0] = g_SmokeTypes[smoke->smoke_type].r;
|
|
vertices[1].v.cn[1] = g_SmokeTypes[smoke->smoke_type].g;
|
|
vertices[1].v.cn[2] = g_SmokeTypes[smoke->smoke_type].b;
|
|
vertices[1].v.cn[3] = sp77;
|
|
|
|
vertices[2].v.ob[0] = (((sp80 + spB0.f[0] + sp8C.f[0]) * get_room_data_float1()) - arg3->f[0]) * 10.0f;
|
|
vertices[2].v.ob[1] = (((sp7C + spB0.f[1] + sp8C.f[1]) * get_room_data_float1()) - arg3->f[1]) * 10.0f;
|
|
vertices[2].v.ob[2] = (((sp78 + spB0.f[2] + sp8C.f[2]) * get_room_data_float1()) - arg3->f[2]) * 10.0f;
|
|
vertices[2].v.tc[0] = 0;
|
|
vertices[2].v.tc[1] = 1760;
|
|
vertices[2].v.cn[0] = g_SmokeTypes[smoke->smoke_type].r;
|
|
vertices[2].v.cn[1] = g_SmokeTypes[smoke->smoke_type].g;
|
|
vertices[2].v.cn[2] = g_SmokeTypes[smoke->smoke_type].b;
|
|
vertices[2].v.cn[3] = sp77;
|
|
|
|
vertices[3].v.ob[0] = ((((sp80 - spA4.f[0]) + sp98.f[0]) * get_room_data_float1()) - arg3->f[0]) * 10.0f;
|
|
vertices[3].v.ob[1] = ((((sp7C - spA4.f[1]) + sp98.f[1]) * get_room_data_float1()) - arg3->f[1]) * 10.0f;
|
|
vertices[3].v.ob[2] = ((((sp78 - spA4.f[2]) + sp98.f[2]) * get_room_data_float1()) - arg3->f[2]) * 10.0f;
|
|
vertices[3].v.tc[0] = 1760;
|
|
vertices[3].v.tc[1] = 1760;
|
|
vertices[3].v.cn[0] = g_SmokeTypes[smoke->smoke_type].r;
|
|
vertices[3].v.cn[1] = g_SmokeTypes[smoke->smoke_type].g;
|
|
vertices[3].v.cn[2] = g_SmokeTypes[smoke->smoke_type].b;
|
|
vertices[3].v.cn[3] = sp77;
|
|
|
|
gSPVertex(gdl++, osVirtualToPhysical(vertices), 4, 0);
|
|
|
|
gSP2Triangles(gdl++, 0, 1, 2, 0, 0, 2, 3, 0);
|
|
|
|
return gdl;
|
|
}
|
|
|
|
|
|
void explosionCreateSmoke(coord3d *pos, StandTile *stan, s16 smoke_type, u8 *rooms, s32 flags)
|
|
{
|
|
struct Smoke *smoke;
|
|
struct Smoke *smoke_tmp;
|
|
s32 i;
|
|
s32 player_count;
|
|
PropRecord *prop;
|
|
|
|
smoke = NULL;
|
|
player_count = getPlayerCount();
|
|
|
|
for (i = 0; i < 20; i++)
|
|
{
|
|
if (g_SmokeBuffer[i].prop == NULL)
|
|
{
|
|
smoke = &g_SmokeBuffer[i];
|
|
break;
|
|
}
|
|
else if (player_count >= 2)
|
|
{
|
|
smoke_tmp = (i + g_SmokeBuffer);
|
|
if (((smoke_tmp->smoke_type != 7) && (smoke_tmp->smoke_type != 8)) && (smoke_tmp->smoke_type != 9))
|
|
{
|
|
smoke_tmp->duration = (s16) g_SmokeTypes[smoke_tmp->smoke_type].duration;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (smoke == NULL) { return; }
|
|
|
|
prop = chrpropAllocate();
|
|
if (prop == NULL) { return; }
|
|
|
|
prop->type = 8;
|
|
prop->flags |= 2;
|
|
prop->smoke = smoke;
|
|
prop->stan = stan;
|
|
prop->pos.x = pos->x;
|
|
prop->pos.y = pos->y;
|
|
prop->pos.z = pos->z;
|
|
|
|
for (i = 0; (rooms[i] != 0xFF) && (i < 7); i++)
|
|
{
|
|
prop->rooms[i] = rooms[i];
|
|
}
|
|
prop->rooms[i] = 0xFF;
|
|
|
|
if (flags != 0)
|
|
{
|
|
prop->flags |= 8;
|
|
}
|
|
|
|
chrpropActivateThisFrame(prop);
|
|
chrpropEnable(prop);
|
|
smoke->prop = prop;
|
|
smoke->duration = 0;
|
|
smoke->smoke_type = smoke_type;
|
|
}
|
|
|
|
|
|
/***
|
|
* Perfect Dark u32 smokeTick(struct prop *prop)
|
|
*
|
|
* NTSC address 0x7F09E8AC.
|
|
*/
|
|
s32 explosionSmokeTick(PropRecord *arg0)
|
|
{
|
|
f32 temp_f2;
|
|
s32 i;
|
|
s32 j;
|
|
s32 k;
|
|
f32 lvupdate;
|
|
struct Smoke *smoke;
|
|
struct SmokePart *part;
|
|
struct coord3d bbmin;
|
|
struct coord3d bbmax;
|
|
f32 var_f14;
|
|
s32 var_v1;
|
|
|
|
smoke = arg0->smoke;
|
|
|
|
if (g_ClockTimer == 0)
|
|
{
|
|
return TICKOP_NONE;
|
|
}
|
|
|
|
lvupdate = (g_ClockTimer < 15) ? (f32) g_ClockTimer : 15.0f;
|
|
|
|
for (i = 0; i < (s32) lvupdate; i++)
|
|
{
|
|
smoke->duration += 1;
|
|
|
|
for (j = 0; j < SMOKE_PARTS_LEN; j++)
|
|
{
|
|
part = &smoke->parts[j];
|
|
|
|
if (part->size != 0.0f)
|
|
{
|
|
part->pos.f[1] += 0.3f;
|
|
part->size += 0.15f;
|
|
|
|
part->alpha -= g_SmokeTypes[smoke->smoke_type].fg_rotrate;
|
|
part->count++;
|
|
part->rot += part->deltarot;
|
|
|
|
part->offset1 += 0.02f + RANDOMFRAC() * 0.01f;
|
|
part->offset2 += 0.02f + RANDOMFRAC() * 0.01f;
|
|
|
|
if (part->alpha < 4.0f)
|
|
{
|
|
part->size = 0.0f;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (smoke->duration < g_SmokeTypes[smoke->smoke_type].duration)
|
|
{
|
|
if (smoke->duration % g_SmokeTypes[smoke->smoke_type].ratedissolve == 1)
|
|
{
|
|
for (j = 0; j < SMOKE_PARTS_LEN; j++)
|
|
{
|
|
if (smoke->parts[j].size == 0.0f)
|
|
{
|
|
part = &smoke->parts[j];
|
|
|
|
part->size = g_SmokeTypes[smoke->smoke_type].size * (RANDOMFRAC() * 0.5f + 1.0f);
|
|
part->alpha = (randomGetNext() % 70) + 110.0f;
|
|
part->count = 0;
|
|
part->rot = RANDOMFRAC() * M_TAU_F;
|
|
part->deltarot = (0.5f - RANDOMFRAC()) * g_SmokeTypes[smoke->smoke_type].bg_rotrate;
|
|
|
|
part->pos.x = arg0->pos.x;
|
|
part->pos.y = arg0->pos.y;
|
|
part->pos.z = arg0->pos.z;
|
|
|
|
part->offset1 = RANDOMFRAC() * 0.5f;
|
|
part->offset2 = RANDOMFRAC() * 0.5f;
|
|
|
|
if (smoke->duration > g_SmokeTypes[smoke->smoke_type].duration - g_SmokeTypes[smoke->smoke_type].propagated_clouds)
|
|
{
|
|
part->alpha *= (g_SmokeTypes[smoke->smoke_type].duration - smoke->duration) / (f32)g_SmokeTypes[smoke->smoke_type].propagated_clouds;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bbmin.x = arg0->pos.x - 1.0f;
|
|
bbmin.y = arg0->pos.y - 1.0f;
|
|
bbmin.z = arg0->pos.z - 1.0f;
|
|
|
|
bbmax.x = arg0->pos.x + 1.0f;
|
|
bbmax.y = arg0->pos.y + 1.0f;
|
|
bbmax.z = arg0->pos.z + 1.0f;
|
|
|
|
var_f14 = 0.0f;
|
|
|
|
for (j = 0; j < SMOKE_PARTS_LEN; j++)
|
|
{
|
|
if (smoke->parts[j].size != 0.0f)
|
|
{
|
|
for (k = 0; k < 3; k++)
|
|
{
|
|
if (bbmin.f[k] > smoke->parts[j].pos.f[k] - smoke->parts[j].size)
|
|
{
|
|
bbmin.f[k] = smoke->parts[j].pos.f[k] - smoke->parts[j].size;
|
|
}
|
|
else if (bbmax.f[k] < smoke->parts[j].pos.f[k] - smoke->parts[j].size)
|
|
{
|
|
bbmax.f[k] = smoke->parts[j].pos.f[k] - smoke->parts[j].size;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
temp_f2 = arg0->pos.f[0] - bbmin.f[0];
|
|
if (temp_f2 > 0.0f)
|
|
{
|
|
var_f14 = temp_f2;
|
|
}
|
|
|
|
if (var_f14 < arg0->pos.f[2] - bbmin.f[2])
|
|
{
|
|
var_f14 = arg0->pos.f[2] - bbmin.f[2];
|
|
}
|
|
|
|
if (var_f14 < bbmax.f[0] - arg0->pos.f[0])
|
|
{
|
|
var_f14 = bbmax.f[0] - arg0->pos.f[0];
|
|
}
|
|
|
|
if (var_f14 < bbmax.f[2] - arg0->pos.f[2])
|
|
{
|
|
var_f14 = bbmax.f[2] - arg0->pos.f[2];
|
|
}
|
|
|
|
chrpropUpdateRoomList(arg0, &bbmin, &bbmax, var_f14);
|
|
|
|
if (smoke->duration > g_SmokeTypes[smoke->smoke_type].ratedissolve)
|
|
{
|
|
var_v1 = 1;
|
|
|
|
for (j = 0; j < SMOKE_PARTS_LEN; j++)
|
|
{
|
|
if (smoke->parts[j].size > 0.0f)
|
|
{
|
|
var_v1 = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var_v1 = 0;
|
|
}
|
|
|
|
if (var_v1 != 0)
|
|
{
|
|
smoke->prop = NULL;
|
|
return TICKOP_FREE;
|
|
}
|
|
|
|
return TICKOP_NONE;
|
|
}
|
|
|
|
|
|
/*
|
|
* Address: 0x7F09EF9C
|
|
*/
|
|
u8 explosionChrpropSmokeTick(PropRecord* prop)
|
|
{
|
|
Mtxf* player_matrix;
|
|
|
|
player_matrix = camGetWorldToScreenMtxf();
|
|
prop->zDepth = -((((player_matrix->m[0][2] * prop->pos.x) + (player_matrix->m[1][2] * prop->pos.y)) + (player_matrix->m[2][2] * prop->pos.z)) + player_matrix->m[3][2]);
|
|
|
|
if (prop->zDepth < 100.0f)
|
|
{
|
|
prop->zDepth *= 0.5f;
|
|
}
|
|
else
|
|
{
|
|
prop->zDepth -= 100.0f;
|
|
}
|
|
|
|
return TICKOP_NONE;
|
|
}
|
|
|
|
|
|
extern Gfx globalDL_0x000;
|
|
|
|
/***
|
|
* NTSC address 0x7F09F03C.
|
|
*/
|
|
Gfx *explosionRenderPropSmoke(PropRecord *arg0, Gfx *gdl, s32 withalpha)
|
|
{
|
|
struct Smoke *smoke;
|
|
s32 i;
|
|
struct bbox2d sp78;
|
|
struct coord3d *temp_s5;
|
|
s32 temp_s1;
|
|
|
|
|
|
temp_s1 = arg0->rooms[0];
|
|
smoke = arg0->smoke;
|
|
temp_s5 = getRoomPositionByIndex(temp_s1);
|
|
|
|
if (withalpha == 0)
|
|
{
|
|
return gdl;
|
|
}
|
|
|
|
if (getPropCombinedRoomsBBox2D(arg0, &sp78) > 0)
|
|
{
|
|
gdl = bgScissorCurrentPlayerViewF(gdl, sp78.min.f[0], sp78.min.f[1], sp78.max.f[0], sp78.max.f[1]);
|
|
}
|
|
else
|
|
{
|
|
gdl = bgScissorCurrentPlayerViewDefault(gdl);
|
|
}
|
|
|
|
gSPClearGeometryMode(gdl++, G_CULL_BOTH | G_FOG);
|
|
|
|
gSPMatrix(gdl++, osVirtualToPhysical((void*)get_BONDdata_field_10E0()), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
|
|
|
|
gdl = applyRoomMatrixToDisplayList(gdl, temp_s1);
|
|
|
|
gSPMatrix(gdl++, osVirtualToPhysical((void*)&dword_CODE_bss_8007A100), G_MTX_NOPUSH | G_MTX_MUL | G_MTX_MODELVIEW);
|
|
|
|
gSPSegment(gdl++, SPSEGMENT_GETITLE, osVirtualToPhysical((void*)pGlobalimagetable));
|
|
|
|
gSPDisplayList(gdl++, &globalDL_0x000);
|
|
|
|
gDPSetColorDither(gdl++, G_CD_NOISE);
|
|
|
|
for (i = 0; i < SMOKE_PARTS_LEN; i++)
|
|
{
|
|
if (smoke->parts[i].size > 0.0f)
|
|
{
|
|
gdl = explosionSmokeRenderPart(smoke, &smoke->parts[i], gdl, temp_s5);
|
|
}
|
|
else
|
|
{
|
|
smoke->parts[i].size = 0.0f;
|
|
}
|
|
}
|
|
|
|
gDPSetColorDither(gdl++, G_CD_BAYER);
|
|
|
|
gSPMatrix(gdl++, osVirtualToPhysical((void*)currentPlayerGetProjectionMatrix()), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
|
|
|
|
return gdl;
|
|
}
|
|
|
|
|
|
// https://decomp.me/scratch/RT8eu
|
|
void explosionInitFlyingParticles(coord3d *spawnpos, f32 spawn_rand_scale, f32 spawn_horiz_drift_scale, f32 spawn_vert_drift_scale, f32 spawn_tex_scale)
|
|
{
|
|
// these are gray rectangles of dust created from shooting walls with guns that fall down with gravity
|
|
// a bullet will create a group of them flying off the wall
|
|
|
|
f32 rand1;
|
|
f32 rand2;
|
|
f32 rand3;
|
|
s16 unk08_upper;
|
|
s16 unk0A_upper;
|
|
s32 rand_s8;
|
|
|
|
rand1 = (2.0f * (((f32) randomGetNext()) * (1.0f / (f32)UINT_MAX))) - 1.0f;
|
|
rand2 = ((((f32) randomGetNext()) * (1.0f / (f32)UINT_MAX)) * 1.12f) - 0.12f;
|
|
rand3 = (2.0f * (((f32) randomGetNext()) * (1.0f / (f32)UINT_MAX))) - 1.0f;
|
|
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].unk00 = 1;
|
|
#ifdef PORT
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].is_splash = FALSE;
|
|
#endif
|
|
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].position.f[0] = spawnpos->f[0] + (spawn_rand_scale * rand1);
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].position.f[1] = spawnpos->f[1] + (spawn_rand_scale * rand2);
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].position.f[2] = spawnpos->f[2] + (spawn_rand_scale * rand3);
|
|
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].position_drift.f[0] = rand1 * spawn_horiz_drift_scale;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].position_drift.f[1] = rand2 * spawn_vert_drift_scale;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].position_drift.f[2] = rand3 * spawn_horiz_drift_scale;
|
|
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[0].v.ob[0] = (s16) ((s32) ((((((f32) randomGetNext()) * (1.0f / (f32)UINT_MAX)) * 0.75f) + 0.75f) * spawn_tex_scale));
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[0].v.ob[1] = 0;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[0].v.ob[2] = (s16) ((s32) ((((((f32) randomGetNext()) * (1.0f / (f32)UINT_MAX)) * 0.75f) + 0.75f) * spawn_tex_scale));
|
|
|
|
if (1)
|
|
{
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[1].v.ob[0] = (s16) ((s32) ((((((f32) randomGetNext()) * (1.0f / (f32)UINT_MAX)) * 0.75f) + 0.75f) * spawn_tex_scale));
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[1].v.ob[1] = 0;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[1].v.ob[2] = (s16) ((s32) ((((((f32) randomGetNext()) * (1.0f / (f32)UINT_MAX)) * 0.75f) + 0.75f) * (-spawn_tex_scale)));
|
|
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[2].v.ob[0] = (s16) ((s32) ((((((f32) randomGetNext()) * (1.0f / (f32)UINT_MAX)) * 0.75f) + 0.75f) * (-spawn_tex_scale)));
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[2].v.ob[1] = 0;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[2].v.ob[2] = (s16) ((s32) ((((((f32) randomGetNext()) * (1.0f / (f32)UINT_MAX)) * 0.75f) + 0.75f) * (-spawn_tex_scale)));
|
|
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[3].v.ob[0] = (s16) ((s32) ((((((f32) randomGetNext()) * (1.0f / (f32)UINT_MAX)) * 0.75f) + 0.75f) * (-spawn_tex_scale)));
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[3].v.ob[1] = 0;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[3].v.ob[2] = (s16) ((s32) ((((((f32) randomGetNext()) * (1.0f / (f32)UINT_MAX)) * 0.75f) + 0.75f) * spawn_tex_scale));
|
|
}
|
|
|
|
if (1) {}
|
|
|
|
unk08_upper = (randomGetNext() & 3) << 8;
|
|
unk0A_upper = (randomGetNext() & 3) << 8;
|
|
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[0].v.tc[0] = unk08_upper + 0xE0;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[0].v.tc[1] = unk0A_upper + 0xE0;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[1].v.tc[0] = unk08_upper + 0xE0;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[1].v.tc[1] = unk0A_upper;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[2].v.tc[0] = unk08_upper;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[2].v.tc[1] = unk0A_upper;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[3].v.tc[0] = unk08_upper;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[3].v.tc[1] = unk0A_upper + 0xE0;
|
|
|
|
if (randomGetNext() & 1)
|
|
{
|
|
rand_s8 = 0xFF - (randomGetNext() & 0x3F);
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[0].v.cn[2] = rand_s8;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[0].v.cn[1] = rand_s8;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[0].v.cn[0] = rand_s8;
|
|
rand_s8 = 0xFF - (randomGetNext() & 0x3F);
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[1].v.cn[2] = rand_s8;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[1].v.cn[1] = rand_s8;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[1].v.cn[0] = rand_s8;
|
|
rand_s8 = 0xFF - (randomGetNext() & 0x3F);
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[2].v.cn[2] = rand_s8;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[2].v.cn[1] = rand_s8;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[2].v.cn[0] = rand_s8;
|
|
rand_s8 = 0xFF - (randomGetNext() & 0x3F);
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[3].v.cn[2] = rand_s8;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[3].v.cn[1] = rand_s8;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[3].v.cn[0] = rand_s8;
|
|
}
|
|
else
|
|
{
|
|
rand_s8 = randomGetNext() & 0x3F;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[0].v.cn[2] = rand_s8;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[0].v.cn[1] = rand_s8;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[0].v.cn[0] = rand_s8;
|
|
rand_s8 = randomGetNext() & 0x3F;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[1].v.cn[2] = rand_s8;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[1].v.cn[1] = rand_s8;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[1].v.cn[0] = rand_s8;
|
|
rand_s8 = randomGetNext() & 0x3F;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[2].v.cn[2] = rand_s8;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[2].v.cn[1] = rand_s8;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[2].v.cn[0] = rand_s8;
|
|
rand_s8 = randomGetNext() & 0x3F;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[3].v.cn[2] = rand_s8;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[3].v.cn[1] = rand_s8;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[3].v.cn[0] = rand_s8;
|
|
}
|
|
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[0].v.cn[3] = 0xdc;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[1].v.cn[3] = 0xdc;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[2].v.cn[3] = 0xdc;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].vertex_list[3].v.cn[3] = 0xdc;
|
|
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].rotation.f[0] = (((f32) randomGetNext()) * (1.0f / (f32)UINT_MAX)) * M_TAU_F;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].rotation.f[1] = (((f32) randomGetNext()) * (1.0f / (f32)UINT_MAX)) * M_TAU_F;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].rotation.f[2] = (((f32) randomGetNext()) * (1.0f / (f32)UINT_MAX)) * M_TAU_F;
|
|
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].rotation_drift.f[0] = (((f32) randomGetNext()) * (1.0f / (f32)UINT_MAX)) * 0.1f;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].rotation_drift.f[1] = (((f32) randomGetNext()) * (1.0f / (f32)UINT_MAX)) * 0.1f;
|
|
g_FlyingParticlesBuffer[g_NumParticleEntries].rotation_drift.f[2] = (((f32) randomGetNext()) * (1.0f / (f32)UINT_MAX)) * 0.1f;
|
|
|
|
g_NumParticleEntries++;
|
|
if (g_NumParticleEntries >= max_particles)
|
|
{
|
|
g_NumParticleEntries = 0;
|
|
}
|
|
}
|
|
|
|
|
|
void explosionUpdateFlyingParticles(void)
|
|
{
|
|
f32 scalar;
|
|
s32 i;
|
|
s32 j;
|
|
|
|
if (g_ClockTimer < 0xF)
|
|
{
|
|
scalar = g_ClockTimer;
|
|
}
|
|
else
|
|
{
|
|
scalar = 15.0f;
|
|
}
|
|
|
|
|
|
for (i = 0; i < max_particles; i++)
|
|
{
|
|
if (g_FlyingParticlesBuffer[i].unk00 > 0)
|
|
{
|
|
g_FlyingParticlesBuffer[i].unk00 += (s32) scalar;
|
|
|
|
g_FlyingParticlesBuffer[i].rotation.f[0] += g_FlyingParticlesBuffer[i].rotation_drift.f[0] * scalar;
|
|
g_FlyingParticlesBuffer[i].rotation.f[1] += g_FlyingParticlesBuffer[i].rotation_drift.f[1] * scalar;
|
|
g_FlyingParticlesBuffer[i].rotation.f[2] += g_FlyingParticlesBuffer[i].rotation_drift.f[2] * scalar;
|
|
|
|
g_FlyingParticlesBuffer[i].position.f[0] += g_FlyingParticlesBuffer[i].position_drift.f[0] * scalar;
|
|
g_FlyingParticlesBuffer[i].position.f[2] += g_FlyingParticlesBuffer[i].position_drift.f[2] * scalar;
|
|
|
|
for (j = 0; j < (s32)scalar; j++)
|
|
{
|
|
// initially sends particles flying up
|
|
g_FlyingParticlesBuffer[i].position.f[1] += g_FlyingParticlesBuffer[i].position_drift.f[1];
|
|
|
|
// applies gravity so particles fall down
|
|
if (g_FlyingParticlesBuffer[i].position_drift.f[1] > -3.75f)
|
|
{
|
|
g_FlyingParticlesBuffer[i].position_drift.f[1] -= 0.2f;
|
|
}
|
|
}
|
|
|
|
// handles particles life time
|
|
if ((g_FlyingParticlesBuffer[i].unk00 >= 0x65) && (!(randomGetNext() & 0x1F) || (g_FlyingParticlesBuffer[i].unk00 == 0x12C)))
|
|
{
|
|
g_FlyingParticlesBuffer[i].unk00 = 0;
|
|
}
|
|
|
|
#ifdef PORT
|
|
if (g_FlyingParticlesBuffer[i].is_splash
|
|
&& g_FlyingParticlesBuffer[i].position_drift.f[1] < 0.0f
|
|
&& g_FlyingParticlesBuffer[i].position.f[1] < g_FlyingParticlesBuffer[i].splash_y)
|
|
{
|
|
g_FlyingParticlesBuffer[i].unk00 = 0;
|
|
}
|
|
#endif
|
|
|
|
// position-related. deletes particles that are too low or too high.
|
|
if ((g_FlyingParticlesBuffer[i].position.f[1] < -30000.0f) || (g_FlyingParticlesBuffer[i].position.f[1] > 30000.0f))
|
|
{
|
|
g_FlyingParticlesBuffer[i].unk00 = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef PORT
|
|
/* Bullet hitting water (PC): the N64 only drew the yellow impact flash there.
|
|
* Throw up light blue droplets (the wall-hit dust particles, recoloured) that
|
|
* vanish when they fall back through the surface, plus a white mist puff. */
|
|
#define WATER_SPLASH_DROPLETS 12
|
|
|
|
void explosionCreateWaterSplash(coord3d *pos, StandTile *stan, u8 *rooms)
|
|
{
|
|
s32 i;
|
|
s32 j;
|
|
|
|
for (i = 0; i < WATER_SPLASH_DROPLETS; i++)
|
|
{
|
|
struct FlyingParticles *drop = &g_FlyingParticlesBuffer[g_NumParticleEntries];
|
|
|
|
explosionInitFlyingParticles(pos, 2.0f, 1.0f, 6.0f, 3.0f);
|
|
|
|
drop->is_splash = TRUE;
|
|
drop->splash_y = pos->f[1];
|
|
|
|
for (j = 0; j < 4; j++)
|
|
{
|
|
u8 shade = 0xC0 + (randomGetNext() & 0x3F);
|
|
|
|
drop->vertex_list[j].v.cn[0] = shade - 0x30;
|
|
drop->vertex_list[j].v.cn[1] = shade - 0x10;
|
|
drop->vertex_list[j].v.cn[2] = 0xFF;
|
|
drop->vertex_list[j].v.cn[3] = 0xB0;
|
|
}
|
|
}
|
|
|
|
explosionCreateSmoke(pos, stan, 7, rooms, 0);
|
|
}
|
|
#endif
|
|
|
|
|
|
extern Gfx globalDL_0xa50;
|
|
|
|
/***
|
|
* NTSC address 0x7F0A0034.
|
|
*/
|
|
Gfx *explosionRenderFlyingParticles(Gfx *gdl)
|
|
{
|
|
Mtxf sp80;
|
|
s32 i;
|
|
Mtx *temp_v0_2;
|
|
struct FlyingParticles *particles;
|
|
|
|
gSPClearGeometryMode(gdl++, G_CULL_BOTH);
|
|
gSPSegment(gdl++, SPSEGMENT_GETITLE, osVirtualToPhysical((void*)pGlobalimagetable));
|
|
gSPDisplayList(gdl++, &globalDL_0xa50);
|
|
gDPSetRenderMode(gdl++, G_RM_AA_ZB_XLU_SURF, G_RM_AA_ZB_XLU_SURF2);
|
|
|
|
for (i = 0; i < max_particles; i++)
|
|
{
|
|
// HACK: regalloc has instructions backwards.
|
|
#ifdef PORT
|
|
particles = g_FlyingParticlesBuffer + i;
|
|
#else
|
|
particles = (struct FlyingParticles *)(u32)g_FlyingParticlesBuffer + i;
|
|
#endif
|
|
|
|
if (particles->unk00 > 0)
|
|
{
|
|
matrix_4x4_set_position_and_rotation_around_xyz(&particles->position, &particles->rotation, &sp80);
|
|
matrix_4x4_multiply_homogeneous_in_place(camGetWorldToScreenMtxf(), &sp80);
|
|
|
|
if ((sp80.m[3][0] < 20000.0f)
|
|
&& (sp80.m[3][0] > -20000.0f)
|
|
&& (sp80.m[3][1] < 20000.0f)
|
|
&& (sp80.m[3][1] > -20000.0f)
|
|
&& (sp80.m[3][2] < 20000.0f)
|
|
&& (sp80.m[3][2] > -20000.0f))
|
|
{
|
|
temp_v0_2 = dynAllocateMatrix();
|
|
matrix_4x4_f32_to_s32(&sp80, (Mtxf *)temp_v0_2);
|
|
|
|
gSPMatrix(gdl++, osVirtualToPhysical((void*)temp_v0_2), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
|
gSPVertex(gdl++, osVirtualToPhysical((void*)g_FlyingParticlesBuffer[i].vertex_list), 4, 0)
|
|
gSP2Triangles(gdl++, 0, 1, 2, 0, 0, 2, 3, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
return gdl;
|
|
}
|
|
|
|
|
|
|
|
|
|
/***
|
|
* NTSC address 0x7F0A027C.
|
|
*/
|
|
void explosionScorchTick(struct coord3d *pos, f32 explosion_size, s16 room)
|
|
{
|
|
Vtx sp58;
|
|
f32 sp54;
|
|
f32 sp50;
|
|
f32 sp4C;
|
|
u8 sp4B;
|
|
struct coord3d *temp_s0;
|
|
u32 temp_hi;
|
|
|
|
sp58 = g_ScorchDefaultVertex;
|
|
|
|
sp54 = RANDOMFRAC() * M_TAU_F;
|
|
sp4B = 0xFF - (randomGetNext() % 80U);
|
|
|
|
temp_s0 = getRoomPositionByIndex((s32) room);
|
|
|
|
if (getPlayerCount() < 2)
|
|
{
|
|
if (explosion_size > 200.0f)
|
|
{
|
|
explosion_size = 200.0f;
|
|
}
|
|
|
|
explosion_size *= (0.8f + (0.2f * RANDOMFRAC()));
|
|
|
|
pos->f[0] = (pos->f[0] * get_room_data_float1()) - temp_s0->f[0];
|
|
pos->f[1] = (pos->f[1] * get_room_data_float1()) - temp_s0->f[1];
|
|
pos->f[2] = (pos->f[2] * get_room_data_float1()) - temp_s0->f[2];
|
|
|
|
explosion_size *= get_room_data_float1();
|
|
|
|
sp50 = cosf(sp54) * explosion_size;
|
|
sp4C = sinf(sp54) * explosion_size;
|
|
|
|
g_ScorchBuffer[g_NumScorchEntries].roomid = room;
|
|
g_ScorchBuffer[g_NumScorchEntries].pos.f[0] = pos->f[0];
|
|
g_ScorchBuffer[g_NumScorchEntries].pos.f[1] = pos->f[1];
|
|
g_ScorchBuffer[g_NumScorchEntries].pos.f[2] = pos->f[2];
|
|
g_ScorchBuffer[g_NumScorchEntries].explosion_size = explosion_size;
|
|
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[0] = sp58;
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[1] = sp58;
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[2] = sp58;
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[3] = sp58;
|
|
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[0].v.ob[0] = (s16) (s32) (pos->f[0] + sp50);
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[0].v.ob[1] = (s16) (s32) (pos->f[1] + 0.5f);
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[0].v.ob[2] = (s16) (s32) (pos->f[2] + sp4C);
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[0].v.tc[0] = 0;
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[0].v.tc[1] = genericimage->width << 5;
|
|
temp_hi = randomGetNext() % 50U;
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[0].v.cn[2] = (u8) temp_hi;
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[0].v.cn[1] = (u8) temp_hi;
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[0].v.cn[0] = (u8) temp_hi;
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[0].v.cn[3] = sp4B;
|
|
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[1].v.ob[0] = (s16) (s32) (pos->f[0] + sp4C);
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[1].v.ob[1] = (s16) (s32) (pos->f[1] + 0.5f);
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[1].v.ob[2] = (s16) (s32) (pos->f[2] - sp50);
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[1].v.tc[0] = 0;
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[1].v.tc[1] = 0;
|
|
temp_hi = randomGetNext() % 50U;
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[1].v.cn[2] = (u8) temp_hi;
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[1].v.cn[1] = (u8) temp_hi;
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[1].v.cn[0] = (u8) temp_hi;
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[1].v.cn[3] = sp4B;
|
|
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[2].v.ob[0] = (s16) (s32) (pos->f[0] - sp50);
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[2].v.ob[1] = (s16) (s32) (pos->f[1] + 0.5f);
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[2].v.ob[2] = (s16) (s32) (pos->f[2] - sp4C);
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[2].v.tc[0] = genericimage->height << 5;
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[2].v.tc[1] = 0;
|
|
temp_hi = randomGetNext() % 50U;
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[2].v.cn[2] = (u8) temp_hi;
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[2].v.cn[1] = (u8) temp_hi;
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[2].v.cn[0] = (u8) temp_hi;
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[2].v.cn[3] = sp4B;
|
|
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[3].v.ob[0] = (s16) (s32) (pos->f[0] - sp4C);
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[3].v.ob[1] = (s16) (s32) (pos->f[1] + 0.5f);
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[3].v.ob[2] = (s16) (s32) (pos->f[2] + sp50);
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[3].v.tc[0] = genericimage->width << 5;
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[3].v.tc[1] = genericimage->height << 5;
|
|
temp_hi = randomGetNext() % 50U;
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[3].v.cn[2] = (u8) temp_hi;
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[3].v.cn[1] = (u8) temp_hi;
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[3].v.cn[0] = (u8) temp_hi;
|
|
g_ScorchBuffer[g_NumScorchEntries].vertex_list[3].v.cn[3] = sp4B;
|
|
|
|
g_NumScorchEntries++;
|
|
if (g_NumScorchEntries >= SCORCH_BUFFER_LEN)
|
|
{
|
|
g_NumScorchEntries = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Address 0x7F0A0AB4.
|
|
*/
|
|
Gfx *explosionRenderScorchBuffer(Gfx *arg0)
|
|
{
|
|
//temp_t6 = arg0;
|
|
s32 i;
|
|
s32 phi_s3 = -1;
|
|
|
|
if (getPlayerCount() >= 2)
|
|
{
|
|
return arg0;
|
|
}
|
|
else
|
|
{
|
|
gSPSetGeometryMode(arg0++, G_CULL_BACK);
|
|
gSPClearGeometryMode(arg0++, G_CULL_FRONT | G_FOG);
|
|
gDPSetColorDither(arg0++, G_CD_NOISE);
|
|
|
|
texSelect(&arg0, genericimage, 4, 1, 2);
|
|
|
|
for (i=0; i<20; i++)
|
|
{
|
|
if (g_ScorchBuffer[i].roomid >= 0 && getROOMID_isRendered(g_ScorchBuffer[i].roomid))
|
|
{
|
|
if (phi_s3 != g_ScorchBuffer[i].roomid)
|
|
{
|
|
phi_s3 = g_ScorchBuffer[i].roomid;
|
|
arg0 = applyRoomMatrixToDisplayList(arg0, g_ScorchBuffer[i].roomid);
|
|
}
|
|
|
|
/**
|
|
* Loads into the RSP vertex buffer the vertices that will be used by the gSP1Triangle commands that generates polygons.
|
|
*
|
|
* param v: the segment address of vertex list.
|
|
* param n: the number of vertices (1~32)
|
|
* param v0: Starting index in vertex buffer where vertices are to be loaded
|
|
* gSPVertex(Gfx *gdl, Vtx *v, u32 n, u32 v0)
|
|
*/
|
|
gSPVertex(arg0++, osVirtualToPhysical((void*)g_ScorchBuffer[i].vertex_list), 4, 0);
|
|
gSP2Triangles(arg0++,
|
|
0, 1, 2, 0,
|
|
0, 2, 3, 0);
|
|
}
|
|
}
|
|
|
|
gDPSetColorDither(arg0++, G_CD_BAYER);
|
|
}
|
|
|
|
return arg0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
s32 explosionRoundFloat(f32 arg0)
|
|
{
|
|
if (arg0 >= 0.0f)
|
|
{
|
|
return (s32) (arg0 + 0.5f);
|
|
}
|
|
|
|
return (s32) (arg0 - 0.5f);
|
|
}
|
|
|
|
|
|
|
|
void explosionClearBulletImpactRoomByFlag(PropRecord* arg0, s8 arg1)
|
|
{
|
|
s32 i;
|
|
for (i = 0; i < BULLET_IMPACT_BUFFER_LEN; i++)
|
|
{
|
|
if ((arg0 == g_BulletImpactBuffer[i].prop) && (arg1 == g_BulletImpactBuffer[i].room_clear_flag))
|
|
{
|
|
g_BulletImpactBuffer[i].room = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void explosionClearBulletImpactRoom(PropRecord* arg0)
|
|
{
|
|
s32 i;
|
|
for (i = 0; i < BULLET_IMPACT_BUFFER_LEN; i++)
|
|
{
|
|
if ((arg0 == g_BulletImpactBuffer[i].prop) && (g_ImpactTypes[g_BulletImpactBuffer[i].impact_type].unk1 == 2))
|
|
{
|
|
g_BulletImpactBuffer[i].room = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void explosionSetBulletImpactAlpha(s32 arg0)
|
|
{
|
|
u32 val;
|
|
s32 i;
|
|
for (i = 0; i < SMOKE_PARTS_LEN; i++)
|
|
{
|
|
val = (u32) (((f32) i / 10.0f) * 255.0f);
|
|
|
|
g_BulletImpactBuffer[arg0].vertex_list[3].v.cn[3] = val; // alpha
|
|
g_BulletImpactBuffer[arg0].vertex_list[2].v.cn[3] = val; // alpha
|
|
g_BulletImpactBuffer[arg0].vertex_list[1].v.cn[3] = val; // alpha
|
|
g_BulletImpactBuffer[arg0].vertex_list[0].v.cn[3] = val; // alpha
|
|
|
|
if (++arg0 >= BULLET_IMPACT_BUFFER_LEN)
|
|
{
|
|
arg0 = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/***
|
|
* NTSC address 0x7F0A108C.
|
|
*/
|
|
void explosionCreateBulletImpact(struct coord3d *pos, struct coord3d *arg1, s16 impact_type, s16 room, PropRecord *prop, s8 model_render_pos_index, s8 room_clear_flag)
|
|
{
|
|
Vtx spE0;
|
|
f32 spDC;
|
|
f32 spD8;
|
|
f32 spD4;
|
|
f32 temp_f6;
|
|
f32 temp_f2_2;
|
|
f32 temp_f12;
|
|
f32 spC4;
|
|
struct coord3d *temp_s0_2;
|
|
f32 spBC;
|
|
f32 spB8;
|
|
f32 spB4;
|
|
f32 spB0;
|
|
s32 temp_v1;
|
|
struct coord3d spA0;
|
|
f32 sp9C;
|
|
f32 sp98;
|
|
RenderPosView *temp_s1;
|
|
ObjectRecord *temp_s0;
|
|
f32 temp_f0;
|
|
f32 sp88;
|
|
s32 i;
|
|
struct coord3d sp78;
|
|
struct coord3d sp6C;
|
|
f32 zero = 0.0f;
|
|
s_impacttype *sp50;
|
|
u8 var_s0;
|
|
u8 sp62;
|
|
u8 sp61;
|
|
|
|
spE0 = g_BulletImpactDefaultVertex;
|
|
|
|
if (cheatIsActive(CHEAT_PAINTBALL))
|
|
{
|
|
impact_type = 0x10;
|
|
}
|
|
|
|
spA0.f[0] = pos->f[0];
|
|
spA0.f[1] = pos->f[1];
|
|
spA0.f[2] = pos->f[2];
|
|
|
|
sp50 = &g_ImpactTypes[impact_type];
|
|
|
|
sp9C = sp50->width;
|
|
sp98 = sp50->height;
|
|
|
|
if ((arg1->f[0] == 0.0f) && (arg1->f[2] == 0.0f))
|
|
{
|
|
spB8 = 0.0f;
|
|
spB4 = 0.0f;
|
|
spBC = 0.0f;
|
|
spB0 = 1.0f;
|
|
spC4 = 1.0f;
|
|
}
|
|
else
|
|
{
|
|
temp_f0 = sqrtf((arg1->f[0] * arg1->f[0]) + (arg1->f[1] * arg1->f[1]) + (arg1->f[2] * arg1->f[2]));
|
|
|
|
spDC = arg1->f[0] / temp_f0;
|
|
spD8 = arg1->f[1] / temp_f0;
|
|
spD4 = arg1->f[2] / temp_f0;
|
|
|
|
temp_f0 = sqrtf((spDC * spDC) + (spD4 * spD4));
|
|
|
|
temp_f2_2 = spDC / temp_f0;
|
|
temp_f12 = spD4 / temp_f0;
|
|
|
|
spBC = -temp_f2_2;
|
|
spB8 = spD8 * temp_f2_2;
|
|
spB4 = -temp_f0;
|
|
spB0 = spD8 * temp_f12;
|
|
spC4 = temp_f12;
|
|
}
|
|
|
|
if (prop != NULL)
|
|
{
|
|
temp_s0 = prop->obj;
|
|
temp_s1 = &temp_s0->model->render_pos[model_render_pos_index];
|
|
|
|
sp78.f[0] = spC4;
|
|
sp78.f[1] = 0.0f;
|
|
sp78.f[2] = spBC;
|
|
|
|
sp6C.f[0] = spB8;
|
|
sp6C.f[1] = spB4;
|
|
sp6C.f[2] = spB0;
|
|
|
|
mtx4RotateVecInPlace(&temp_s1->pos, &sp78);
|
|
mtx4RotateVecInPlace(&temp_s1->pos, &sp6C);
|
|
|
|
sp88 = sqrtf((sp78.f[0] * sp78.f[0]) + (sp78.f[1] * sp78.f[1]) + (sp78.f[2] * sp78.f[2]));
|
|
temp_f6 = sqrtf((sp6C.f[0] * sp6C.f[0]) + (sp6C.f[1] * sp6C.f[1]) + (sp6C.f[2] * sp6C.f[2]));
|
|
|
|
sp9C /= sp88;
|
|
sp98 /= temp_f6;
|
|
|
|
if ((sp50->unk2 < 2) && (sp50->unk1 == 2))
|
|
{
|
|
temp_s0->state |= PROPSTATE_2;
|
|
}
|
|
else
|
|
{
|
|
temp_s0->state |= PROPSTATE_DAMAGED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
temp_s0_2 = getRoomPositionByIndex((s32) room);
|
|
spA0.f[0] = (spA0.f[0] * get_room_data_float1()) - temp_s0_2->f[0];
|
|
spA0.f[1] = (spA0.f[1] * get_room_data_float1()) - temp_s0_2->f[1];
|
|
spA0.f[2] = (spA0.f[2] * get_room_data_float1()) - temp_s0_2->f[2];
|
|
sp9C *= get_room_data_float1();
|
|
sp98 *= get_room_data_float1();
|
|
}
|
|
|
|
g_BulletImpactBuffer[g_NumImpactEntries].prop = prop;
|
|
g_BulletImpactBuffer[g_NumImpactEntries].model_render_pos_index = model_render_pos_index;
|
|
g_BulletImpactBuffer[g_NumImpactEntries].room_clear_flag = room_clear_flag;
|
|
g_BulletImpactBuffer[g_NumImpactEntries].room = room;
|
|
g_BulletImpactBuffer[g_NumImpactEntries].impact_type = impact_type;
|
|
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[0] = spE0;
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[1] = spE0;
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[2] = spE0;
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[3] = spE0;
|
|
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[0].v.ob[0] = explosionRoundFloat((spA0.f[0] - (sp9C * spC4)) - (sp98 * spB8));
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[0].v.ob[1] = explosionRoundFloat((spA0.f[1] - zero) - (sp98 * spB4));
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[0].v.ob[2] = explosionRoundFloat((spA0.f[2] - (sp9C * spBC)) - (sp98 * spB0));
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[0].v.tc[0] = 0;
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[0].v.tc[1] = impactimages[impact_type].height << 5;
|
|
#ifdef DEBUG
|
|
assert(IsBadVec3d((vec3d *)g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[0].v.ob));
|
|
#endif
|
|
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[1].v.ob[0] = explosionRoundFloat((spA0.f[0] - (sp9C * spC4)) + (sp98 * spB8));
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[1].v.ob[1] = explosionRoundFloat((spA0.f[1] - zero) + (sp98 * spB4));
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[1].v.ob[2] = explosionRoundFloat((spA0.f[2] - (sp9C * spBC)) + (sp98 * spB0));
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[1].v.tc[0] = 0;
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[1].v.tc[1] = 0;
|
|
#ifdef DEBUG
|
|
assert(IsBadVec3d((vec3d *)g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[1].v.ob));
|
|
#endif
|
|
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[2].v.ob[0] = explosionRoundFloat(spA0.f[0] + (sp9C * spC4) + (sp98 * spB8));
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[2].v.ob[1] = explosionRoundFloat(spA0.f[1] + zero + (sp98 * spB4));
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[2].v.ob[2] = explosionRoundFloat(spA0.f[2] + (sp9C * spBC) + (sp98 * spB0));
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[2].v.tc[0] = impactimages[impact_type].width << 5;
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[2].v.tc[1] = 0;
|
|
#ifdef DEBUG
|
|
assert(IsBadVec3d((vec3d *)g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[2].v.ob));
|
|
#endif
|
|
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[3].v.ob[0] = explosionRoundFloat((spA0.f[0] + (sp9C * spC4)) - (sp98 * spB8));
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[3].v.ob[1] = explosionRoundFloat((spA0.f[1] + zero) - (sp98 * spB4));
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[3].v.ob[2] = explosionRoundFloat((spA0.f[2] + (sp9C * spBC)) - (sp98 * spB0));
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[3].v.tc[0] = impactimages[impact_type].width << 5;
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[3].v.tc[1] = impactimages[impact_type].height << 5;
|
|
#ifdef DEBUG
|
|
assert(IsBadVec3d((vec3d *)g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[3].v.ob));
|
|
#endif
|
|
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
switch (sp50->apptype)
|
|
{
|
|
default:
|
|
#ifdef DEBUG
|
|
osSyncPrintf("Wallhit colour %d not implemented, substituting black\n", sp50->apptype);
|
|
#endif
|
|
var_s0 = 0;
|
|
break;
|
|
|
|
case 1:
|
|
temp_v1 = 0xFF - (randomGetNext() % 40U);
|
|
sp61 = temp_v1;
|
|
sp62 = temp_v1;
|
|
var_s0 = temp_v1;
|
|
break;
|
|
|
|
case 0:
|
|
temp_v1 = randomGetNext() % 40U;
|
|
sp61 = temp_v1;
|
|
sp62 = temp_v1;
|
|
var_s0 = temp_v1;
|
|
break;
|
|
|
|
case 2:
|
|
var_s0 = (randomGetNext() & 1) ? 0xff : 0;
|
|
sp62 = (randomGetNext() & 1) ? 0xff : 0;
|
|
sp61 = (randomGetNext() & 1) ? 0xff : 0;
|
|
break;
|
|
}
|
|
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[i].v.cn[0] = var_s0;
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[i].v.cn[1] = sp62;
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[i].v.cn[2] = sp61;
|
|
g_BulletImpactBuffer[g_NumImpactEntries].vertex_list[i].v.cn[3] = 0xff; // alpha
|
|
}
|
|
|
|
g_NumImpactEntries++;
|
|
if (g_NumImpactEntries >= BULLET_IMPACT_BUFFER_LEN)
|
|
{
|
|
g_NumImpactEntries = 0;
|
|
}
|
|
|
|
explosionSetBulletImpactAlpha(g_NumImpactEntries);
|
|
|
|
g_BulletImpactBuffer[g_NumImpactEntries].room = -1;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***
|
|
* Perfect Dark Gfx *smokeRender(struct prop *prop, Gfx *gdl, bool xlupass)
|
|
*
|
|
* NTSC address 0x7F0A1A94.
|
|
*/
|
|
Gfx *explosionRenderBulletImpactOnProp(Gfx *gdl, PropRecord *arg1, s32 arg2)
|
|
{
|
|
s32 padding1;
|
|
s32 padding2;
|
|
|
|
s32 i; // var_s4
|
|
s32 sp50;
|
|
struct Scorch *sp4C;
|
|
s32 sp48;
|
|
union RenderPosView *render_pos;
|
|
s32 padding3;
|
|
|
|
s16 var_s5;
|
|
s32 impact_type;
|
|
s32 var_v0;
|
|
|
|
var_s5 = -1;
|
|
sp50 = 0;
|
|
sp4C = NULL;
|
|
sp48 = -1;
|
|
|
|
if (arg1 != NULL)
|
|
{
|
|
sp4C = arg1->scorch;
|
|
}
|
|
|
|
gSPClearGeometryMode(gdl++, G_CULL_BOTH);
|
|
gDPSetColorDither(gdl++, G_CD_NOISE);
|
|
|
|
for (i = 0; i < BULLET_IMPACT_BUFFER_LEN; i++)
|
|
{
|
|
if (arg1 == g_BulletImpactBuffer[i].prop)
|
|
{
|
|
if (g_BulletImpactBuffer[i].room >= 0)
|
|
{
|
|
if (arg1 || getROOMID_isRendered(g_BulletImpactBuffer[i].room))
|
|
{
|
|
impact_type = g_BulletImpactBuffer[i].impact_type;
|
|
|
|
if (arg2)
|
|
{
|
|
var_v0 = g_ImpactTypes[impact_type].unk2 < 2 && g_ImpactTypes[impact_type].unk1 == 2;
|
|
}
|
|
else
|
|
{
|
|
var_v0 = (g_ImpactTypes[impact_type].unk2 >= 2) || g_ImpactTypes[impact_type].unk1 != 2;
|
|
}
|
|
|
|
if (var_v0)
|
|
{
|
|
sp50 = 1;
|
|
|
|
if (arg1 != NULL)
|
|
{
|
|
if (var_s5 != g_BulletImpactBuffer[i].model_render_pos_index)
|
|
{
|
|
render_pos = &sp4C->model->render_pos[g_BulletImpactBuffer[i].model_render_pos_index];
|
|
var_s5 = g_BulletImpactBuffer[i].model_render_pos_index;
|
|
gSPMatrix(gdl++, osVirtualToPhysical(render_pos), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (var_s5 != g_BulletImpactBuffer[i].room)
|
|
{
|
|
var_s5 = g_BulletImpactBuffer[i].room;
|
|
gdl = applyRoomMatrixToDisplayList(gdl, g_BulletImpactBuffer[i].room);
|
|
}
|
|
}
|
|
|
|
if (sp48 != impact_type)
|
|
{
|
|
texSelect(&gdl, &impactimages[impact_type], g_ImpactTypes[impact_type].unk1, g_ImpactTypes[impact_type].unk2, 2U);
|
|
sp48 = impact_type;
|
|
}
|
|
|
|
gSPVertex(gdl++, osVirtualToPhysical(g_BulletImpactBuffer[i].vertex_list), 4, 0);
|
|
gSP2Triangles(gdl++, 0, 1, 2, 0, 0, 2, 3, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((arg1 != NULL) && (sp50 == 0))
|
|
{
|
|
sp4C->unk02 &= ~(1 << arg2);
|
|
}
|
|
|
|
gDPSetColorDither(gdl++, G_CD_BAYER);
|
|
|
|
return gdl;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Gfx * explosionCallRenderBulletImpactOnProp(Gfx *arg0)
|
|
{
|
|
return explosionRenderBulletImpactOnProp(arg0, NULL, 0);
|
|
}
|
|
|
|
|