478 lines
12 KiB
C
478 lines
12 KiB
C
#include "blast.h"
|
|
|
|
#include <sys/types.h>
|
|
#include <libgte.h>
|
|
#include <libgpu.h>
|
|
|
|
#include "common.h"
|
|
#include "libgv/libgv.h"
|
|
#include "libdg/libdg.h"
|
|
#include "anime/animconv/anime.h"
|
|
#include "game/game.h"
|
|
#include "sd/g_sound.h"
|
|
#include "linkvar.h"
|
|
#include "strcode.h"
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
#define EXEC_LEVEL GV_ACTOR_AFTER
|
|
|
|
typedef struct _Work
|
|
{
|
|
GV_ACT actor;
|
|
int map;
|
|
SVECTOR pos;
|
|
DG_PRIM *prim;
|
|
int unused1;
|
|
int unused2;
|
|
int time;
|
|
TARGET target;
|
|
} Work;
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
BLAST_DATA blast_data_8009F4B8[8] = {
|
|
{ 0x100, 5, 0x3E8, 0x7D0, WP_Grenade },
|
|
{ 0x100, 5, 0x3E8, 0x7D0, WP_C4 },
|
|
{ 0x100, 5, 0x3E8, 0x7D0, WP_Claymore },
|
|
{ 0x100, 5, 0x3E8, 0x7D0, WP_Stinger },
|
|
{ 0x100, 5, 0x3E8, 0x7D0, WP_Nikita },
|
|
{ 0x100, 5, 0x3E8, 0x7D0, WP_None },
|
|
{ 0x400, 5, 0x3E8, 0x7D0, WP_Max },
|
|
{ 0, 0, 1, 1, WP_None }
|
|
};
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
STATIC SVECTOR svector_8009F558[2] = {
|
|
#ifndef VR_EXE
|
|
{100, 0, 0, 0},
|
|
#else
|
|
{50, 0, 0, 0},
|
|
#endif
|
|
{2000, 2000, 4000, 4000}
|
|
};
|
|
|
|
static void Act(Work *work)
|
|
{
|
|
int time;
|
|
|
|
GM_CurrentMap = work->map;
|
|
|
|
time = ++work->time;
|
|
|
|
if (time == 1)
|
|
{
|
|
AN_Blast_Single(&work->pos);
|
|
}
|
|
|
|
if (time == 2)
|
|
{
|
|
sub_8007913C();
|
|
}
|
|
|
|
if (time >= 30)
|
|
{
|
|
GV_DestroyActor(&work->actor);
|
|
}
|
|
}
|
|
|
|
static void Die(Work *blast)
|
|
{
|
|
if (blast->time < 2)
|
|
{
|
|
sub_8007913C();
|
|
}
|
|
|
|
GM_FreePrim(blast->prim);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
static void InitBlastTarget(BLAST_DATA *blast_data, Work *work, int side)
|
|
{
|
|
TARGET *target = &work->target;
|
|
SVECTOR size;
|
|
|
|
size.vx = size.vy = size.vz = blast_data->field_8_z;
|
|
|
|
if ( side )
|
|
{
|
|
GM_SetTarget(target, 4, NO_SIDE, &size);
|
|
}
|
|
else
|
|
{
|
|
GM_SetTarget(target, 4, ENEMY_SIDE, &size);
|
|
}
|
|
|
|
GM_Target_8002DCCC(target, 7, 2, blast_data->field_0 >> 1, blast_data->field_4, svector_8009F558);
|
|
|
|
target->weapon = blast_data->weapon;
|
|
|
|
GM_MoveTarget(&work->target, &work->pos);
|
|
GM_PowerTarget(target);
|
|
|
|
size.vx = size.vy = size.vz = blast_data->field_C;
|
|
svector_8009F558[0].vx = 50;
|
|
|
|
if ( side )
|
|
{
|
|
GM_SetTarget(target, 4, NO_SIDE, &size);
|
|
}
|
|
else
|
|
{
|
|
GM_SetTarget(target, 4, ENEMY_SIDE, &size);
|
|
}
|
|
|
|
GM_Target_8002DCCC(target, 7, 2, blast_data->field_0 >> 1, 3, svector_8009F558);
|
|
|
|
target->weapon = blast_data->weapon;
|
|
|
|
GM_MoveTarget(&work->target, &work->pos);
|
|
GM_PowerTarget(target);
|
|
|
|
if ( GM_lpfnBombExplosion && GM_lpfnBombExplosion(&work->target, GM_uBombHoming) )
|
|
{
|
|
++work->time;
|
|
}
|
|
else
|
|
{
|
|
GM_SeSet(&work->pos, SE_EXPLOSION);
|
|
}
|
|
}
|
|
|
|
static int GetResources(BLAST_DATA *blast_data, Work *work, MATRIX *world, int side)
|
|
{
|
|
work->time = 0;
|
|
work->map = GM_CurrentMap;
|
|
work->pos.vx = world->t[0];
|
|
work->pos.vy = world->t[1];
|
|
work->pos.vz = world->t[2];
|
|
InitBlastTarget(blast_data, work, side);
|
|
return 0;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
void *NewBlast(MATRIX *world, BLAST_DATA *blast_data)
|
|
{
|
|
Work *work;
|
|
|
|
work = GV_NewActor(EXEC_LEVEL, sizeof(Work));
|
|
if (work)
|
|
{
|
|
GV_SetNamedActor(&work->actor, Act, Die, "blast.c");
|
|
GM_ClaymoreMap = GM_CurrentMap;
|
|
|
|
if (GetResources(blast_data, work, world, 1) < 0)
|
|
{
|
|
|
|
GV_DestroyActor(&work->actor);
|
|
return NULL;
|
|
}
|
|
|
|
GM_SetNoise(255, 32, &work->pos);
|
|
|
|
sub_800790E8();
|
|
}
|
|
|
|
return (void *)work;
|
|
}
|
|
|
|
void *NewBlast2(MATRIX *world, BLAST_DATA *blast_data, int doSound, int side)
|
|
{
|
|
Work *work;
|
|
|
|
work = GV_NewActor(EXEC_LEVEL, sizeof(Work));
|
|
if (work)
|
|
{
|
|
GV_SetNamedActor(&work->actor, Act, Die, "blast.c");
|
|
GM_ClaymoreMap = GM_CurrentMap;
|
|
if (GetResources(blast_data, work, world, side) < 0)
|
|
{
|
|
GV_DestroyActor(&work->actor);
|
|
return NULL;
|
|
}
|
|
|
|
if (doSound)
|
|
{
|
|
GM_SetNoise(255, 32, &work->pos);
|
|
}
|
|
|
|
sub_800790E8();
|
|
}
|
|
return (void *)work;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
STATIC const unsigned char blast_anim_data_single[64] = {
|
|
0x00,0x3b,0x01,0x00, 0x05,0x01,0x00,0x02, 0x00,0x01,0x0c,0x00, 0x02,0x01,0xff,0x0a,
|
|
0x04,0xb0,0x04,0xb0, 0x02,0x00,0x01,0x0d, 0x0c,0x00,0x06,0x01, 0xff,0x02,0x00,0x01,
|
|
0x0d,0x0c,0x00,0x07, 0x01,0xff,0x0a,0x00, 0x64,0x00,0x64,0x08, 0xf8,0xf8,0xf8,0x02,
|
|
0x00,0x01,0x0a,0x00, 0x50,0x00,0x50,0x08, 0xf8,0xf8,0xf8,0x02, 0x00,0x01,0x0d,0x0f
|
|
};
|
|
STATIC const unsigned char blast_anim_data_random[64] = {
|
|
0x00,0x3b,0x01,0x00, 0x05,0x01,0x00,0x02, 0x00,0x01,0x0c,0x00, 0x04,0x01,0xff,0x0a,
|
|
0x04,0xb0,0x04,0xb0, 0x02,0x00,0x01,0x0d, 0x0c,0x00,0x0c,0x01, 0xff,0x02,0x00,0x01,
|
|
0x0d,0x0c,0x00,0x08, 0x01,0xff,0x0a,0x00, 0x64,0x00,0x64,0x08, 0xf8,0xf8,0xf8,0x02,
|
|
0x00,0x01,0x0a,0x00, 0x50,0x00,0x50,0x08, 0xf8,0xf8,0xf8,0x02, 0x00,0x01,0x0d,0x0f
|
|
};
|
|
STATIC const unsigned char blast_anim_data_mini[64] = {
|
|
0x00,0x3b,0x01,0x00, 0x05,0x01,0x00,0x02, 0x00,0x01,0x0c,0x00, 0x02,0x01,0xff,0x0a,
|
|
0x02,0x58,0x02,0x58, 0x02,0x00,0x01,0x0d, 0x0c,0x00,0x06,0x01, 0xff,0x02,0x00,0x01,
|
|
0x0d,0x0c,0x00,0x07, 0x01,0xff,0x0a,0x00, 0x32,0x00,0x32,0x08, 0xf8,0xf8,0xf8,0x02,
|
|
0x00,0x01,0x0a,0x00, 0x28,0x00,0x28,0x08, 0xf8,0xf8,0xf8,0x02, 0x00,0x01,0x0d,0x0f
|
|
};
|
|
STATIC const unsigned char blast_anim_data_minimini[64] = {
|
|
0x00,0x3b,0x01,0x00, 0x05,0x01,0x00,0x02, 0x00,0x01,0x0c,0x00, 0x02,0x01,0xff,0x0a,
|
|
0x00,0xc8,0x00,0xc8, 0x02,0x00,0x01,0x0d, 0x0c,0x00,0x06,0x01, 0xff,0x02,0x00,0x01,
|
|
0x0d,0x0c,0x00,0x07, 0x01,0xff,0x0a,0x00, 0x14,0x00,0x14,0x08, 0xf8,0xf8,0xf8,0x02,
|
|
0x00,0x01,0x0a,0x00, 0x14,0x00,0x14,0x08, 0xf8,0xf8,0xf8,0x02, 0x00,0x01,0x0d,0x0f
|
|
};
|
|
STATIC const unsigned char blast_anim_data_high[290] = {
|
|
0x01,0x17,0x04,0x00, 0x0b,0x00,0x4b,0x00, 0x90,0x00,0xd9,0x01, 0x00,0x02,0x00,0x01,
|
|
0x0c,0x00,0x02,0x01, 0xff,0x0a,0x04,0xb0, 0x04,0xb0,0x02,0x00, 0x01,0x0d,0x0c,0x00,
|
|
0x06,0x01,0xff,0x0a, 0x00,0xc8,0x00,0xc8, 0x02,0x00,0x01,0x0d, 0x0c,0x00,0x07,0x01,
|
|
0xff,0x0a,0x00,0x64, 0x00,0x64,0x08,0xf8, 0xf8,0xf8,0x02,0x00, 0x01,0x0a,0x00,0x50,
|
|
0x00,0x50,0x08,0xf8, 0xf8,0xf8,0x02,0x00, 0x01,0x0d,0x0f,0x01, 0x00,0x02,0x00,0x01,
|
|
0x01,0x00,0x02,0x00, 0x01,0x0c,0x00,0x02, 0x01,0xff,0x0a,0x03, 0xe8,0x03,0xe8,0x02,
|
|
0x00,0x01,0x0d,0x0c, 0x00,0x06,0x01,0xff, 0x0a,0x00,0xb4,0x00, 0xb4,0x02,0x00,0x01,
|
|
0x0d,0x0c,0x00,0x07, 0x01,0xff,0x0a,0x00, 0x64,0x00,0x64,0x08, 0xf8,0xf8,0xf8,0x02,
|
|
0x00,0x01,0x0a,0x00, 0x50,0x00,0x50,0x08, 0xf8,0xf8,0xf8,0x02, 0x00,0x01,0x0d,0x0f,
|
|
0x0c,0x00,0x02,0x01, 0x00,0x02,0x00,0x01, 0x0d,0x01,0x00,0x02, 0x00,0x01,0x0c,0x00,
|
|
0x02,0x01,0xff,0x0a, 0x03,0x20,0x03,0x20, 0x02,0x00,0x01,0x0d, 0x0c,0x00,0x06,0x01,
|
|
0xff,0x0a,0x00,0xa0, 0x00,0xa0,0x02,0x00, 0x01,0x0d,0x0c,0x00, 0x07,0x01,0xff,0x0a,
|
|
0x00,0x64,0x00,0x64, 0x08,0xf8,0xf8,0xf8, 0x02,0x00,0x01,0x0a, 0x00,0x50,0x00,0x50,
|
|
0x08,0xf8,0xf8,0xf8, 0x02,0x00,0x01,0x0d, 0x0f,0x0c,0x00,0x03, 0x01,0x00,0x02,0x00,
|
|
0x01,0x0d,0x01,0x00, 0x02,0x00,0x01,0x0c, 0x00,0x02,0x01,0xff, 0x0a,0x02,0x58,0x02,
|
|
0x58,0x02,0x00,0x01, 0x0d,0x0c,0x00,0x06, 0x01,0xff,0x0a,0x00, 0x8c,0x00,0x8c,0x02,
|
|
0x00,0x01,0x0d,0x0c, 0x00,0x07,0x01,0xff, 0x0a,0x00,0x64,0x00, 0x64,0x08,0xf8,0xf8,
|
|
0xf8,0x02,0x00,0x01, 0x0a,0x00,0x50,0x00, 0x50,0x08,0xf8,0xf8, 0xf8,0x02,0x00,0x01,
|
|
0x0d,0x0f
|
|
};
|
|
|
|
STATIC ANIMATION blast_anim_single = { PCX_BOMB1_FL, 4, 4, 16, 1, 2000, 1, 1000, 1000, 128, NULL, (void *)blast_anim_data_single };
|
|
STATIC ANIMATION blast_anim_random = { PCX_BOMB1_FL, 4, 4, 16, 1, 2000, 1, 1000, 1000, 128, NULL, (void *)blast_anim_data_random };
|
|
STATIC ANIMATION blast_anim_mini = { PCX_BOMB1_FL, 4, 4, 16, 1, 2000, 1, 500, 500, 128, NULL, (void *)blast_anim_data_mini };
|
|
STATIC ANIMATION blast_anim_minimini = { PCX_BOMB1_FL, 4, 4, 16, 1, 2000, 1, 200, 200, 128, NULL, (void *)blast_anim_data_minimini };
|
|
STATIC ANIMATION blast_anim_high = { PCX_BOMB1_FL, 4, 4, 16, 1, 2000, 1, 1000, 1000, 128, NULL, (void *)blast_anim_data_high };
|
|
|
|
void AN_Blast_Single(SVECTOR *pos)
|
|
{
|
|
ANIMATION *anm;
|
|
PRESCRIPT pre;
|
|
|
|
pre.pos = *pos;
|
|
pre.speed = DG_ZeroVector;
|
|
pre.s_anim = 0;
|
|
pre.scr_num = 0;
|
|
|
|
anm = &blast_anim_single;
|
|
anm->pre_script = ⪯
|
|
|
|
NewAnime( NULL, 0, anm );
|
|
}
|
|
|
|
void AN_Blast_Mini(SVECTOR *pos)
|
|
{
|
|
ANIMATION *anm;
|
|
PRESCRIPT pre;
|
|
|
|
pre.pos = *pos;
|
|
pre.speed = DG_ZeroVector;
|
|
|
|
pre.s_anim = 0;
|
|
|
|
anm = &blast_anim_mini;
|
|
anm->pre_script = ⪯
|
|
|
|
pre.scr_num = 0;
|
|
NewAnime( NULL, 0, anm );
|
|
}
|
|
|
|
void AN_Blast_Minimini(SVECTOR *pos)
|
|
{
|
|
ANIMATION *anm;
|
|
PRESCRIPT pre;
|
|
|
|
pre.pos = *pos;
|
|
pre.speed = DG_ZeroVector;
|
|
|
|
pre.s_anim = 0;
|
|
|
|
anm = &blast_anim_minimini;
|
|
anm->pre_script = ⪯
|
|
|
|
pre.scr_num = 0;
|
|
NewAnime( NULL, 0, anm );
|
|
}
|
|
|
|
void AN_Blast_Rand(SVECTOR *pos)
|
|
{
|
|
PRESCRIPT prescript;
|
|
PRESCRIPT *prescript_ptr;
|
|
MATRIX *m;
|
|
int map;
|
|
int randu;
|
|
ANIMATION *anm;
|
|
|
|
prescript.pos = *pos;
|
|
prescript.pos.vx += GV_RandS(128);
|
|
prescript.pos.vy += GV_RandS(128);
|
|
prescript.pos.vz += GV_RandS(128);
|
|
|
|
prescript.speed = DG_ZeroVector;
|
|
prescript.speed.vy += GV_RandS(64);
|
|
|
|
prescript.s_anim = 0;
|
|
|
|
randu = GV_RandU(4);
|
|
if (randu == 0)
|
|
{
|
|
anm = &blast_anim_single;
|
|
}
|
|
else
|
|
{
|
|
anm = &blast_anim_random;
|
|
}
|
|
|
|
prescript_ptr = &prescript;
|
|
map = 0;
|
|
m = NULL;
|
|
// Silly code just to get the compiler to emit
|
|
// an unnecessary move and get a match...
|
|
if (randu == 0)
|
|
{
|
|
m = NULL;
|
|
anm->pre_script = prescript_ptr;
|
|
}
|
|
else
|
|
{
|
|
anm->pre_script = prescript_ptr;
|
|
}
|
|
|
|
prescript.scr_num = 0;
|
|
NewAnime(m, map, anm);
|
|
}
|
|
|
|
void AN_Blast_high(SVECTOR *pos)
|
|
{
|
|
PRESCRIPT pre;
|
|
ANIMATION *anm;
|
|
|
|
pre.pos = *pos;
|
|
pre.pos.vy += 600;
|
|
pre.speed = DG_ZeroVector;
|
|
pre.speed.vy += 200;
|
|
pre.s_anim = 0;
|
|
|
|
anm = &blast_anim_high;
|
|
anm->pre_script = ⪯
|
|
|
|
pre.scr_num = 0;
|
|
NewAnime( NULL, 0, anm );
|
|
|
|
pre.pos = *pos;
|
|
pre.pos.vy += 400;
|
|
pre.speed = DG_ZeroVector;
|
|
pre.speed.vy += 150;
|
|
pre.s_anim = 0;
|
|
|
|
anm = &blast_anim_high;
|
|
anm->pre_script = ⪯
|
|
|
|
pre.scr_num = 1;
|
|
NewAnime( NULL, 0, anm );
|
|
|
|
pre.pos = *pos;
|
|
pre.pos.vy += 200;
|
|
pre.speed = DG_ZeroVector;
|
|
pre.speed.vy += 100;
|
|
pre.s_anim = 0;
|
|
|
|
anm = &blast_anim_high;
|
|
anm->pre_script = ⪯
|
|
|
|
pre.scr_num = 2;
|
|
NewAnime( NULL, 0, anm );
|
|
|
|
pre.pos = *pos;
|
|
pre.speed = DG_ZeroVector;
|
|
pre.speed.vy += 50;
|
|
pre.s_anim = 0;
|
|
|
|
anm = &blast_anim_high;
|
|
anm->pre_script = ⪯
|
|
|
|
pre.scr_num = 3;
|
|
NewAnime( NULL, 0, anm );
|
|
}
|
|
|
|
void AN_Blast_high2(SVECTOR *pos, SVECTOR *offset)
|
|
{
|
|
PRESCRIPT pre;
|
|
ANIMATION *anm;
|
|
|
|
pre.pos = *pos;
|
|
pre.pos.vx += offset->vx;
|
|
pre.pos.vy += offset->vy;
|
|
pre.pos.vz += offset->vz;
|
|
pre.speed = DG_ZeroVector;
|
|
pre.speed.vx += offset->vx / 3;
|
|
pre.speed.vy += offset->vy / 3;
|
|
pre.speed.vz += offset->vz / 3;
|
|
pre.s_anim = 0;
|
|
|
|
anm = &blast_anim_high;
|
|
anm->pre_script = ⪯
|
|
|
|
pre.scr_num = 0;
|
|
NewAnime( NULL, 0, anm );
|
|
|
|
pre.pos = *pos;
|
|
pre.pos.vx += (offset->vx * 3) >> 2;
|
|
pre.pos.vy += (offset->vy * 3) >> 2;
|
|
pre.pos.vz += (offset->vz * 3) >> 2;
|
|
pre.speed = DG_ZeroVector;
|
|
pre.speed.vx += ((offset->vx / 3) * 3) >> 2;
|
|
pre.speed.vy += ((offset->vy / 3) * 3) >> 2;
|
|
pre.speed.vz += ((offset->vz / 3) * 3) >> 2;
|
|
pre.s_anim = 0;
|
|
|
|
anm = &blast_anim_high;
|
|
anm->pre_script = ⪯
|
|
|
|
pre.scr_num = 1;
|
|
NewAnime( NULL, 0, anm );
|
|
|
|
pre.pos = *pos;
|
|
pre.pos.vx += offset->vx >> 1;
|
|
pre.pos.vy += offset->vy >> 1;
|
|
pre.pos.vz += offset->vz >> 1;
|
|
pre.speed = DG_ZeroVector;
|
|
pre.speed.vx += (offset->vx / 3) >> 1;
|
|
pre.speed.vy += (offset->vy / 3) >> 1;
|
|
pre.speed.vz += (offset->vz / 3) >> 1;
|
|
pre.s_anim = 0;
|
|
|
|
anm = &blast_anim_high;
|
|
anm->pre_script = ⪯
|
|
|
|
pre.scr_num = 2;
|
|
NewAnime( NULL, 0, anm );
|
|
|
|
pre.pos = *pos;
|
|
pre.speed = DG_ZeroVector;
|
|
pre.speed.vx += (offset->vx / 3) >> 2;
|
|
pre.speed.vy += (offset->vy / 3) >> 2;
|
|
pre.speed.vz += (offset->vz / 3) >> 2;
|
|
pre.s_anim = 0;
|
|
|
|
anm = &blast_anim_high;
|
|
anm->pre_script = ⪯
|
|
|
|
pre.scr_num = 3;
|
|
NewAnime( NULL, 0, anm );
|
|
}
|