677 lines
15 KiB
C
677 lines
15 KiB
C
#include "jirai.h"
|
|
|
|
#include <sys/types.h>
|
|
#include <libgte.h>
|
|
#include <libgpu.h>
|
|
|
|
#include "common.h"
|
|
#include "libgv/libgv.h"
|
|
#include "libdg/libdg.h"
|
|
#include "libgcl/libgcl.h"
|
|
#include "libhzd/libhzd.h"
|
|
#include "game/game.h"
|
|
#include "linkvar.h"
|
|
#include "okajima/claymore.h"
|
|
#include "chara/snake/sna_init.h"
|
|
#include "sd/g_sound.h"
|
|
|
|
extern HITTABLE GM_ClayDatas_800BDE78[8];
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
// Claymore (armed)
|
|
|
|
#define CLAYMORE_NAME GV_StrCode("claymore")
|
|
#define CLAYMORE_MODEL GV_StrCode("claymore")
|
|
|
|
#define BODY_FLAG ( DG_FLAG_TEXT | DG_FLAG_TRANS | DG_FLAG_SHADE | \
|
|
DG_FLAG_GBOUND | DG_FLAG_ONEPIECE | \
|
|
DG_FLAG_AMBIENT | DG_FLAG_IRTEXTURE )
|
|
|
|
int dword_8009F440 = 0;
|
|
int dword_8009F444 = 0;
|
|
int counter_8009F448 = 0;
|
|
SVECTOR svec_8009F44C = {-625, -250, 750, 0};
|
|
SVECTOR svec_8009F454 = {-500, -250, 750, 0};
|
|
SVECTOR svec_8009F45C = {500, 200, 500, 0};
|
|
SVECTOR svec_8009F464 = {300, 200, 300, 0};
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
static MATRIX *jirai_loader_helper_8006A798(MATRIX *arg0, MATRIX *arg1, HZD_FLR *floor)
|
|
{
|
|
MATRIX mtx1;
|
|
MATRIX mtx2;
|
|
|
|
HZD_FLR *flr;
|
|
|
|
int var_a2;
|
|
int var_a0;
|
|
int var_v1;
|
|
|
|
if (!floor)
|
|
{
|
|
*arg0 = *arg1;
|
|
}
|
|
else
|
|
{
|
|
flr = (HZD_FLR *)((int)floor | 0x80000000); // cached
|
|
|
|
var_a2 = flr->p1.h * 16;
|
|
var_v1 = flr->p2.h * 16;
|
|
var_a0 = flr->p3.h * 16;
|
|
|
|
if (var_a0 < 0)
|
|
{
|
|
var_a2 = -var_a2;
|
|
var_a0 = -var_a0;
|
|
var_v1 = -var_v1;
|
|
}
|
|
|
|
mtx1.m[2][0] = 0;
|
|
mtx1.m[0][1] = var_a2;
|
|
mtx1.m[1][0] = -var_a2;
|
|
mtx1.m[0][0] = var_a0;
|
|
mtx1.m[1][1] = var_a0;
|
|
mtx1.m[2][1] = var_v1;
|
|
mtx1.m[0][2] = 0;
|
|
mtx1.m[2][2] = var_a0;
|
|
mtx1.m[1][2] = -var_v1;
|
|
|
|
mtx2 = *arg1;
|
|
MulMatrix2(&mtx1, &mtx2);
|
|
*arg0 = mtx2;
|
|
}
|
|
|
|
return arg0;
|
|
}
|
|
|
|
static int jirai_act_helper_8006A8F4(JiraiWork *work)
|
|
{
|
|
int local_10E;
|
|
CONTROL *p_control;
|
|
SVECTOR v;
|
|
|
|
if (!(GM_PlayerStatus & PLAYER_GROUND))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
local_10E = work->field_10E;
|
|
p_control = &work->control;
|
|
|
|
if (local_10E == TRUE)
|
|
{
|
|
return 0;
|
|
}
|
|
GV_SubVec3(&p_control->mov, &GM_PlayerPosition, &v);
|
|
return GV_VecLen3(&v) < 800;
|
|
}
|
|
|
|
static void JiraiDisplayText(JiraiWork *work, int arg1)
|
|
{
|
|
SVECTOR vec;
|
|
MATRIX *matrix;
|
|
int temp_a2;
|
|
int var_a1;
|
|
int r, g, b;
|
|
const char *text;
|
|
|
|
matrix = &DG_Chanl(0)->eye_inv;
|
|
|
|
gte_SetRotMatrix(matrix);
|
|
gte_SetTransMatrix(matrix);
|
|
gte_ldv0(&work->control.mov);
|
|
gte_rtps();
|
|
gte_stsxy(&vec);
|
|
|
|
if ((work->field_130 < 16) && (arg1 == 0))
|
|
{
|
|
vec.vy -= work->field_130;
|
|
}
|
|
else
|
|
{
|
|
vec.vy -= 16;
|
|
}
|
|
|
|
if (arg1 == 0)
|
|
{
|
|
temp_a2 = work->field_130;
|
|
|
|
if (temp_a2 == 1)
|
|
{
|
|
if (GM_Weapons[WP_Claymore] >= GM_WeaponsMax[WP_Claymore])
|
|
{
|
|
var_a1 = SE_ITEM_FULL;
|
|
work->field_150 = temp_a2;
|
|
}
|
|
else
|
|
{
|
|
work->control.radar_atr = RADAR_OFF;
|
|
var_a1 = SE_ITEM_GET;
|
|
|
|
if (GM_Weapons[WP_Claymore] < 0)
|
|
{
|
|
GM_Weapons[WP_Claymore] = 0;
|
|
}
|
|
|
|
GM_Weapons[WP_Claymore]++;
|
|
|
|
work->field_140 = temp_a2;
|
|
work->field_150 = 0;
|
|
}
|
|
|
|
GM_SeSetMode(&work->control.mov, var_a1, GM_SEMODE_BOMB);
|
|
}
|
|
|
|
if (work->field_150 != 0)
|
|
{
|
|
r = 255;
|
|
g = 48;
|
|
b = 48;
|
|
}
|
|
else
|
|
{
|
|
r = 200;
|
|
g = 200;
|
|
b = 200;
|
|
}
|
|
|
|
MENU_Color(r, g, b);
|
|
text = "CLAYMORE";
|
|
}
|
|
else
|
|
{
|
|
text = "FULL";
|
|
MENU_Color(255, 48, 48);
|
|
}
|
|
|
|
if (work->control.map->index & GM_PlayerMap)
|
|
{
|
|
MENU_Locate(vec.vx + 160, vec.vy + 104, 0x12);
|
|
MENU_Printf(text);
|
|
|
|
MENU_Color(1, 1, 1);
|
|
MENU_Locate(vec.vx + 161, vec.vy + 105, 0x12);
|
|
MENU_Printf(text);
|
|
|
|
menu_Text_Init_80038B98();
|
|
}
|
|
}
|
|
|
|
static void Act(JiraiWork *work)
|
|
{
|
|
TARGET target;
|
|
CONTROL *control;
|
|
TARGET *target2;
|
|
int f130;
|
|
GV_ACT *claymore;
|
|
|
|
if (GM_GameStatus < 0)
|
|
{
|
|
GV_DestroyActor(&work->actor);
|
|
return;
|
|
}
|
|
|
|
control = &work->control;
|
|
DG_GetLightMatrix2(&control->mov, work->light);
|
|
|
|
if (work->field_134_gcl_arg == 2)
|
|
{
|
|
if (++work->field_130 < 45)
|
|
{
|
|
JiraiDisplayText(work, 0);
|
|
|
|
if ((work->field_140 != 0) && (work->field_130 == 16))
|
|
{
|
|
DG_InvisibleObjs(work->body.objs);
|
|
}
|
|
}
|
|
else if (work->field_140 != 0)
|
|
{
|
|
HZD_ExecLeaveEvent(work->control.map->hzd, &work->control.event);
|
|
GV_DestroyActor(&work->actor);
|
|
}
|
|
else
|
|
{
|
|
work->field_130 = 0;
|
|
work->field_134_gcl_arg = 3;
|
|
}
|
|
}
|
|
else if (work->field_134_gcl_arg == 3)
|
|
{
|
|
if ((++work->field_130 < 45) || jirai_act_helper_8006A8F4(work))
|
|
{
|
|
JiraiDisplayText(work, 1);
|
|
}
|
|
else
|
|
{
|
|
work->field_134_gcl_arg = 0;
|
|
work->field_130 = 0;
|
|
}
|
|
}
|
|
|
|
if (work->field_134_gcl_arg >= 2)
|
|
{
|
|
work->target->damaged &= ~TARGET_PUSH;
|
|
return;
|
|
}
|
|
|
|
target2 = work->target;
|
|
|
|
GM_ActControl(control);
|
|
GM_SetCurrentMap(work->map);
|
|
GM_ActObject2((OBJECT *)&work->body);
|
|
|
|
f130 = work->field_130;
|
|
|
|
if (f130 < 16)
|
|
{
|
|
work->field_130++;
|
|
}
|
|
|
|
if ((f130 > 15) && (f130 < 64))
|
|
{
|
|
if (f130 & 1)
|
|
{
|
|
DG_InvisibleObjs(work->body.objs);
|
|
}
|
|
else
|
|
{
|
|
DG_VisibleObjs(work->body.objs);
|
|
}
|
|
|
|
if (++work->field_130 == 64)
|
|
{
|
|
DG_InvisibleObjs(work->body.objs);
|
|
}
|
|
}
|
|
|
|
if (GM_GameStatus & STATE_THERMG)
|
|
{
|
|
DG_VisibleObjs(work->body.objs);
|
|
}
|
|
else if (work->field_130 == 64)
|
|
{
|
|
DG_InvisibleObjs(work->body.objs);
|
|
}
|
|
|
|
if (GM_CurrentItemId == IT_MineDetector)
|
|
{
|
|
GM_ConfigControlAttribute(control, 0x202D);
|
|
}
|
|
else
|
|
{
|
|
GM_ConfigControlAttribute(control, 0);
|
|
}
|
|
|
|
if (
|
|
#ifdef VR_EXE
|
|
(GM_GameStatus & (STATE_PADRELEASE | STATE_DEMO))
|
|
#else
|
|
(GM_GameStatus & (STATE_PADRELEASE | STATE_PADDEMO | STATE_DEMO))
|
|
#endif
|
|
|| (GM_PlayerStatus & PLAYER_PAD_OFF))
|
|
{
|
|
target2->class &= ~TARGET_PUSH;
|
|
target2->damaged &= ~TARGET_PUSH;
|
|
}
|
|
else
|
|
{
|
|
target2->class |= TARGET_PUSH;
|
|
}
|
|
|
|
if (((target2->damaged & TARGET_PUSH) || (dword_8009F444 != 0)) && (work->field_10E == FALSE))
|
|
{
|
|
if (dword_8009F440 == 1)
|
|
{
|
|
work->field_134_gcl_arg = dword_8009F440;
|
|
GV_DestroyActor(&work->actor);
|
|
return;
|
|
}
|
|
|
|
if ((target2->push_side & PLAYER_SIDE) && (GM_PlayerStatus & (PLAYER_INVINCIBLE | PLAYER_GROUND)))
|
|
{
|
|
target2->damaged &= ~TARGET_PUSH;
|
|
dword_8009F444 = 0;
|
|
return;
|
|
}
|
|
|
|
if (dword_8009F444 != 0)
|
|
{
|
|
work->field_144_vec.vy += 2048;
|
|
}
|
|
|
|
dword_8009F440 = 1;
|
|
work->field_10E = TRUE;
|
|
|
|
DG_VisibleObjs(work->body.objs);
|
|
|
|
sub_800790E8();
|
|
|
|
#ifdef VR_EXE
|
|
work->field_154 = 1;
|
|
#endif
|
|
|
|
GM_SetTarget(&target, 4, NO_SIDE, &target2->size);
|
|
GM_Target_8002DCCC(&target, 1, 2, 128, 0, &DG_ZeroVector);
|
|
GM_MoveTarget(&target, &target2->center);
|
|
|
|
GM_PowerTarget(&target);
|
|
HZD_ExecLeaveEvent(work->control.map->hzd, &work->control.event);
|
|
}
|
|
|
|
if (work->field_10E == TRUE)
|
|
{
|
|
if (work->field_10C == 7)
|
|
{
|
|
sub_8007913C();
|
|
}
|
|
|
|
claymore = NewClaymore(&work->control.mov, &work->field_144_vec, 2, work->field_10C);
|
|
|
|
if (!claymore)
|
|
{
|
|
work->field_10C = 0;
|
|
work->field_10E = FALSE;
|
|
}
|
|
else
|
|
{
|
|
work->field_10C--;
|
|
}
|
|
|
|
if ((work->field_10C <= 0) || !claymore)
|
|
{
|
|
work->field_134_gcl_arg = 1;
|
|
GV_DestroyActor(&work->actor);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (jirai_act_helper_8006A8F4(work))
|
|
{
|
|
work->field_134_gcl_arg = 2;
|
|
DG_VisibleObjs(work->body.objs);
|
|
work->field_130 = 0;
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
// A different version of ExecProc is used here, which checks for a proccess ID less than zero.
|
|
#define ExecProc(proc_id, mode) \
|
|
{ \
|
|
GCL_ARGS args; \
|
|
long data; \
|
|
\
|
|
if (proc_id < 0) goto skip; \
|
|
\
|
|
args.argc = 1; \
|
|
args.argv = &data; \
|
|
data = mode; \
|
|
do {} while (0); \
|
|
GCL_ExecProc(proc_id, &args); \
|
|
skip: \
|
|
}
|
|
|
|
static void Die(JiraiWork *work)
|
|
{
|
|
#ifdef VR_EXE
|
|
if (work->field_154)
|
|
#endif
|
|
{
|
|
sub_8007913C();
|
|
}
|
|
GM_FreeControl(&work->control);
|
|
GM_FreeObject((OBJECT *)&work->body);
|
|
GM_FreeTarget(work->target);
|
|
|
|
if (work->field_13C_idx >= 0)
|
|
{
|
|
GM_ClearBulName(work->control.name);
|
|
GM_ClayDatas_800BDE78[work->field_13C_idx].actor = NULL;
|
|
counter_8009F448--;
|
|
}
|
|
|
|
ExecProc(work->field_138_gcl, work->field_134_gcl_arg);
|
|
|
|
dword_8009F444 = 0;
|
|
dword_8009F440 = 0;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
static int InitJiraiTarget(JiraiWork *work, MATRIX *pMtx, int a3)
|
|
{
|
|
TARGET *target;
|
|
SVECTOR v12;
|
|
SVECTOR *v8;
|
|
|
|
target = GM_AllocTarget();
|
|
work->target = target;
|
|
if (!target)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
if (a3)
|
|
{
|
|
v12 = svec_8009F45C;
|
|
}
|
|
else
|
|
{
|
|
v12 = svec_8009F464;
|
|
}
|
|
|
|
if (a3)
|
|
{
|
|
v8 = &svec_8009F454;
|
|
}
|
|
else
|
|
{
|
|
v8 = &svec_8009F44C;
|
|
}
|
|
|
|
if (GCL_GetOption('t'))
|
|
{
|
|
GCL_StrToSV(GCL_GetParamResult(), &v12);
|
|
}
|
|
GM_SetTarget(target, 9, NO_SIDE, &v12);
|
|
target->field_3C |= 2;
|
|
DG_SetPos(pMtx);
|
|
DG_PutVector(v8, &v12, 1);
|
|
GM_MoveTarget(target, &v12);
|
|
work->field_10C = 8;
|
|
work->field_10E = FALSE;
|
|
return 0;
|
|
}
|
|
|
|
static int GetNextClayData(void)
|
|
{
|
|
int i;
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
if (!GM_ClayDatas_800BDE78[i].actor)
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
static int GetResources(JiraiWork *work, MATRIX *world, HZD_FLR *floor)
|
|
{
|
|
int map;
|
|
CONTROL *control;
|
|
HITTABLE *hittable;
|
|
MATRIX matrix;
|
|
RADAR_CONE *cone;
|
|
OBJECT_NO_ROTS *obj;
|
|
|
|
map = GM_PlayerMap;
|
|
control = &work->control;
|
|
work->field_138_gcl = -1;
|
|
work->field_13C_idx = -1;
|
|
GM_CurrentMap = map;
|
|
work->map = map;
|
|
if (GM_InitControl(control, GM_Next_BulName_8004FBA0(), 0) < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
GM_ConfigControlHazard(control, 0, 0, 0);
|
|
jirai_loader_helper_8006A798(&matrix, world, floor);
|
|
GM_ConfigControlMatrix(control, world);
|
|
work->field_144_vec.vy = ratan2(-matrix.m[0][0], -matrix.m[2][0]) & 4095;
|
|
work->field_144_vec.vx = ratan2(matrix.m[1][0], 4096) & 4095;
|
|
work->field_144_vec.vz = 0;
|
|
GM_ConfigControlAttribute(control, 0);
|
|
obj = &work->body;
|
|
GM_InitObjectNoRots(obj, CLAYMORE_MODEL, BODY_FLAG, 0);
|
|
if (!obj->objs)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
DG_SetPos2(&control->mov, &work->control.rot);
|
|
DG_PutObjs(obj->objs);
|
|
GM_ConfigObjectLight((OBJECT *)obj, work->light);
|
|
|
|
work->field_130 = 0;
|
|
work->field_138_gcl = -1;
|
|
work->field_134_gcl_arg = 0;
|
|
work->field_140 = 0;
|
|
|
|
if (InitJiraiTarget(work, world, 0) < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
work->field_13C_idx = GetNextClayData();
|
|
if (work->field_13C_idx < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
hittable = &GM_ClayDatas_800BDE78[work->field_13C_idx];
|
|
hittable->actor = &work->actor;
|
|
hittable->control = control;
|
|
hittable->data = floor;
|
|
|
|
cone = &work->control.radar_cone;
|
|
cone->len = 2000;
|
|
cone->ang = 1024;
|
|
++counter_8009F448;
|
|
cone->dir = GM_PlayerControl->rot.vy;
|
|
return 0;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
void *NewJirai(MATRIX *world, HZD_FLR *floor)
|
|
{
|
|
JiraiWork *work;
|
|
|
|
if (counter_8009F448 == 8)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
work = GV_NewActor(GV_ACTOR_LEVEL5, sizeof(JiraiWork));
|
|
if (work)
|
|
{
|
|
work->field_104_vec = GM_PlayerControl->rot;
|
|
GV_SetNamedActor(&work->actor, Act, Die, "jirai.c");
|
|
|
|
if (GetResources(work, world, floor) < 0)
|
|
{
|
|
GV_DestroyActor(&work->actor);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return (void *)work;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
static int GetResources2(JiraiWork *work, MATRIX *world, int map)
|
|
{
|
|
MATRIX matrix;
|
|
CONTROL *ctrl;
|
|
RADAR_CONE *cone;
|
|
OBJECT_NO_ROTS *obj;
|
|
|
|
work->map = map;
|
|
|
|
ctrl = &work->control;
|
|
if (GM_InitControl(ctrl, CLAYMORE_NAME, map) < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
GM_ConfigControlString(ctrl, GCL_GetOption('p'), GCL_GetOption('d'));
|
|
GM_ConfigControlHazard(ctrl, 0, -2, -2);
|
|
GM_ConfigControlAttribute(ctrl, 0);
|
|
|
|
work->field_144_vec = ctrl->rot;
|
|
obj = &work->body;
|
|
GM_InitObjectNoRots(obj, CLAYMORE_MODEL, BODY_FLAG, 0);
|
|
GM_ConfigObjectLight((OBJECT *)obj, work->light);
|
|
|
|
work->field_104_vec = ctrl->rot;
|
|
|
|
ctrl->rot.vx = ctrl->turn.vx = -1024;
|
|
ctrl->rot.vy = ctrl->turn.vy += 1024;
|
|
ctrl->mov.vy += 500;
|
|
|
|
DG_SetPos2(&ctrl->mov, &ctrl->rot);
|
|
|
|
ReadRotMatrix(&matrix);
|
|
|
|
if (InitJiraiTarget(work, &matrix, 1) < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
ctrl->mov.vy -= 500;
|
|
DG_InvisibleObjs(obj->objs);
|
|
work->field_130 = 64;
|
|
|
|
if (GCL_GetOption('e'))
|
|
{
|
|
work->field_138_gcl = GCL_StrToInt(GCL_GetParamResult());
|
|
}
|
|
else
|
|
{
|
|
work->field_138_gcl = -1;
|
|
}
|
|
|
|
work->field_134_gcl_arg = 0;
|
|
work->field_13C_idx = -1;
|
|
work->field_140 = 0;
|
|
|
|
cone = &ctrl->radar_cone;
|
|
cone->len = 2000;
|
|
cone->ang = 1024;
|
|
cone->dir = ctrl->rot.vy - 1024;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void *NewScenarioJirai(MATRIX *world, int map)
|
|
{
|
|
JiraiWork *work;
|
|
|
|
work = GV_NewActor(GV_ACTOR_AFTER, sizeof(JiraiWork));
|
|
if (work)
|
|
{
|
|
GV_SetNamedActor(&work->actor, Act, Die, "jirai.c");
|
|
if (GetResources2(work, world, map) < 0)
|
|
{
|
|
GV_DestroyActor(&work->actor);
|
|
return NULL;
|
|
}
|
|
}
|
|
return (void *)work;
|
|
}
|