345 lines
9.1 KiB
C
345 lines
9.1 KiB
C
#include <ultra64.h>
|
|
#include "constants.h"
|
|
#include "game/prop.h"
|
|
#include "game/setuputils.h"
|
|
#include "game/game_0b28d0.h"
|
|
#include "game/bg.h"
|
|
#include "game/modeldef.h"
|
|
#include "game/propobj.h"
|
|
#include "bss.h"
|
|
#include "data.h"
|
|
#include "types.h"
|
|
|
|
struct stagesetup g_StageSetup;
|
|
u8 *g_GeCreditsData;
|
|
|
|
u32 setupGetCmdLength(u32 *cmd)
|
|
{
|
|
#if VERSION < VERSION_NTSC_1_0
|
|
static u32 crash1 = 0;
|
|
|
|
mainOverrideVariable("crash1", &crash1);
|
|
#endif
|
|
|
|
switch ((u8)cmd[0]) {
|
|
case OBJTYPE_CHR: return 11;
|
|
case OBJTYPE_DOOR: return 55;
|
|
case OBJTYPE_DOORSCALE: return 2;
|
|
case OBJTYPE_BASIC: return 23;
|
|
case OBJTYPE_DEBRIS: return 23;
|
|
case OBJTYPE_GLASS: return 24;
|
|
case OBJTYPE_TINTEDGLASS: return 26;
|
|
case OBJTYPE_SAFE: return 23;
|
|
case OBJTYPE_GASBOTTLE: return 23;
|
|
case OBJTYPE_KEY: return 24;
|
|
case OBJTYPE_ALARM: return 23;
|
|
case OBJTYPE_CCTV: return 49;
|
|
case OBJTYPE_AMMOCRATE: return 24;
|
|
case OBJTYPE_WEAPON: return 26;
|
|
case OBJTYPE_SINGLEMONITOR: return 53;
|
|
case OBJTYPE_MULTIMONITOR: return 140;
|
|
case OBJTYPE_HANGINGMONITORS: return 23;
|
|
case OBJTYPE_AUTOGUN: return 43;
|
|
case OBJTYPE_LINKGUNS: return 2;
|
|
case OBJTYPE_HAT: return 23;
|
|
case OBJTYPE_GRENADEPROB: return 2;
|
|
case OBJTYPE_LINKLIFTDOOR: return 5;
|
|
case OBJTYPE_SAFEITEM: return 5;
|
|
case OBJTYPE_MULTIAMMOCRATE: return 42;
|
|
case OBJTYPE_SHIELD: return 26;
|
|
case OBJTYPE_TAG: return 4;
|
|
case OBJTYPE_RENAMEOBJ: return 10;
|
|
case OBJTYPE_BEGINOBJECTIVE: return 4;
|
|
case OBJTYPE_ENDOBJECTIVE: return 1;
|
|
case OBJECTIVETYPE_DESTROYOBJ: return 2;
|
|
case OBJECTIVETYPE_COMPFLAGS: return 2;
|
|
case OBJECTIVETYPE_FAILFLAGS: return 2;
|
|
case OBJECTIVETYPE_COLLECTOBJ: return 2;
|
|
case OBJECTIVETYPE_THROWOBJ: return 2;
|
|
case OBJECTIVETYPE_HOLOGRAPH: return 4;
|
|
case OBJECTIVETYPE_1F: return 1;
|
|
case OBJECTIVETYPE_ENTERROOM: return 4;
|
|
case OBJECTIVETYPE_THROWINROOM: return 5;
|
|
case OBJTYPE_22: return 1;
|
|
case OBJTYPE_BRIEFING: return 4;
|
|
case OBJTYPE_PADLOCKEDDOOR: return 4;
|
|
case OBJTYPE_TRUCK: return 34;
|
|
case OBJTYPE_HELI: return 35;
|
|
case OBJTYPE_TANK: return 32;
|
|
case OBJTYPE_CAMERAPOS: return 7;
|
|
case OBJTYPE_LIFT: return 37;
|
|
case OBJTYPE_CONDITIONALSCENERY: return 5;
|
|
case OBJTYPE_BLOCKEDPATH: return 4;
|
|
case OBJTYPE_HOVERBIKE: return 56;
|
|
case OBJTYPE_HOVERPROP: return 39;
|
|
case OBJTYPE_FAN: return 29;
|
|
case OBJTYPE_HOVERCAR: return 38;
|
|
case OBJTYPE_CHOPPER: return 58;
|
|
case OBJTYPE_PADEFFECT: return 3;
|
|
case OBJTYPE_MINE: return 26;
|
|
case OBJTYPE_ESCASTEP: return 27;
|
|
}
|
|
|
|
#if VERSION < VERSION_NTSC_1_0
|
|
if (crash1) {
|
|
CRASH();
|
|
}
|
|
#endif
|
|
|
|
return 1;
|
|
}
|
|
|
|
u32 *setupGetCmdByIndex(s32 wantindex)
|
|
{
|
|
u32 *cmd = g_StageSetup.props;
|
|
|
|
if (wantindex >= 0 && cmd) {
|
|
s32 cmdindex = 0;
|
|
|
|
while ((u8)cmd[0] != OBJTYPE_END) {
|
|
if (cmdindex == wantindex) {
|
|
return cmd;
|
|
}
|
|
|
|
cmd = cmd + setupGetCmdLength(cmd);
|
|
cmdindex++;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
s32 setupGetCmdIndexByTag(struct tag *tag)
|
|
{
|
|
u32 *cmd = g_StageSetup.props;
|
|
|
|
if (cmd) {
|
|
s32 cmdindex = 0;
|
|
|
|
while ((u8)cmd[0] != OBJTYPE_END) {
|
|
if ((struct tag *)cmd == tag) {
|
|
return cmdindex;
|
|
}
|
|
|
|
cmd = cmd + setupGetCmdLength(cmd);
|
|
cmdindex++;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
u32 setupGetCmdIndexByProp(struct prop *prop)
|
|
{
|
|
u32 *cmd = g_StageSetup.props;
|
|
|
|
if (cmd) {
|
|
s32 cmdindex = 0;
|
|
|
|
while ((u8)cmd[0] != OBJTYPE_END) {
|
|
if ((struct prop *)cmd[5] == prop) {
|
|
return cmdindex;
|
|
}
|
|
|
|
cmd = cmd + setupGetCmdLength(cmd);
|
|
cmdindex++;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
bool setupLoadModeldef(s32 modelnum)
|
|
{
|
|
if (g_ModelStates[modelnum].filedata == NULL) {
|
|
g_ModelStates[modelnum].filedata = modeldefLoadToNew(g_ModelStates[modelnum].fileid);
|
|
modelCalculateRwDataLen(g_ModelStates[modelnum].filedata);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool setupGetObjBbox(struct defaultobj *obj, struct coord *pos, f32 realrot[3][3], struct coord *arg3, struct coord *arg4)
|
|
{
|
|
struct modelrodata_bbox *bbox = objFindBboxRodata(obj);
|
|
|
|
if (bbox != NULL) {
|
|
arg3->x = pos->x + func0f0668fc(bbox, realrot);
|
|
arg3->y = pos->y + func0f06695c(bbox, realrot);
|
|
arg3->z = pos->z + func0f0669bc(bbox, realrot);
|
|
|
|
arg4->x = pos->x + func0f06692c(bbox, realrot);
|
|
arg4->y = pos->y + func0f06698c(bbox, realrot);
|
|
arg4->z = pos->z + func0f0669ec(bbox, realrot);
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool setup0f092304(struct defaultobj *obj, struct coord *arg1, struct coord *arg2)
|
|
{
|
|
return setupGetObjBbox(obj, &obj->prop->pos, obj->realrot, arg1, arg2);
|
|
}
|
|
|
|
void setup0f09233c(struct defaultobj *obj, struct coord *pos, f32 realrot[3][3], s16 *rooms)
|
|
{
|
|
struct coord a;
|
|
struct coord b;
|
|
u32 stack;
|
|
|
|
if (setupGetObjBbox(obj, pos, realrot, &a, &b)) {
|
|
a.x -= 1;
|
|
a.y -= 1;
|
|
a.z -= 1;
|
|
b.x += 1;
|
|
b.y += 1;
|
|
b.z += 1;
|
|
|
|
func0f1650d0(&a, &b, rooms, 7, 0);
|
|
}
|
|
}
|
|
|
|
void setup0f0923d4(struct defaultobj *obj)
|
|
{
|
|
propDeregisterRooms(obj->prop);
|
|
setup0f09233c(obj, &obj->prop->pos, obj->realrot, obj->prop->rooms);
|
|
propRegisterRooms(obj->prop);
|
|
}
|
|
|
|
struct defaultobj *setupGetObjByCmdIndex(u32 cmdindex)
|
|
{
|
|
u32 *cmd = setupGetCmdByIndex(cmdindex);
|
|
|
|
if (cmd) {
|
|
switch ((u8)cmd[0]) {
|
|
case OBJTYPE_DOOR:
|
|
case OBJTYPE_BASIC:
|
|
case OBJTYPE_KEY:
|
|
case OBJTYPE_ALARM:
|
|
case OBJTYPE_CCTV:
|
|
case OBJTYPE_AMMOCRATE:
|
|
case OBJTYPE_WEAPON:
|
|
case OBJTYPE_SINGLEMONITOR:
|
|
case OBJTYPE_MULTIMONITOR:
|
|
case OBJTYPE_HANGINGMONITORS:
|
|
case OBJTYPE_AUTOGUN:
|
|
case OBJTYPE_DEBRIS:
|
|
case OBJTYPE_HAT:
|
|
case OBJTYPE_MULTIAMMOCRATE:
|
|
case OBJTYPE_SHIELD:
|
|
case OBJTYPE_GASBOTTLE:
|
|
case OBJTYPE_TRUCK:
|
|
case OBJTYPE_HELI:
|
|
case OBJTYPE_29:
|
|
case OBJTYPE_GLASS:
|
|
case OBJTYPE_SAFE:
|
|
case OBJTYPE_TANK:
|
|
case OBJTYPE_TINTEDGLASS:
|
|
case OBJTYPE_LIFT:
|
|
case OBJTYPE_HOVERBIKE:
|
|
case OBJTYPE_HOVERPROP:
|
|
case OBJTYPE_FAN:
|
|
case OBJTYPE_HOVERCAR:
|
|
case OBJTYPE_CHOPPER:
|
|
case OBJTYPE_ESCASTEP:
|
|
return (struct defaultobj *)cmd;
|
|
case OBJTYPE_DOORSCALE:
|
|
case OBJTYPE_CHR:
|
|
case OBJTYPE_LINKGUNS:
|
|
case OBJTYPE_GRENADEPROB:
|
|
case OBJTYPE_LINKLIFTDOOR:
|
|
case OBJTYPE_TAG:
|
|
case OBJTYPE_BEGINOBJECTIVE:
|
|
case OBJTYPE_ENDOBJECTIVE:
|
|
case OBJECTIVETYPE_DESTROYOBJ:
|
|
case OBJECTIVETYPE_COMPFLAGS:
|
|
case OBJECTIVETYPE_FAILFLAGS:
|
|
case OBJECTIVETYPE_COLLECTOBJ:
|
|
case OBJECTIVETYPE_THROWOBJ:
|
|
case OBJECTIVETYPE_HOLOGRAPH:
|
|
case OBJECTIVETYPE_1F:
|
|
case OBJECTIVETYPE_ENTERROOM:
|
|
case OBJECTIVETYPE_THROWINROOM:
|
|
case OBJTYPE_22:
|
|
case OBJTYPE_BRIEFING:
|
|
case OBJTYPE_RENAMEOBJ:
|
|
case OBJTYPE_PADLOCKEDDOOR:
|
|
case OBJTYPE_SAFEITEM:
|
|
case OBJTYPE_CAMERAPOS:
|
|
case OBJTYPE_CONDITIONALSCENERY:
|
|
case OBJTYPE_BLOCKEDPATH:
|
|
case OBJTYPE_PADEFFECT:
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return (struct defaultobj *)cmd;
|
|
}
|
|
|
|
/**
|
|
* Find an object in the setup file of little importance that can be reused for
|
|
* something of greater importance.
|
|
*
|
|
* For example, if a weapon is being dropped on screen and there are no extra
|
|
* weapon structs left, this function is used to find another weapon elsewhere
|
|
* in the stage so it can be repurposed.
|
|
*
|
|
* The caller can specify if the obj must already have a prop or model. The
|
|
* caller sets these to true if the game is already at the prop or model limit.
|
|
*
|
|
* If an unused object can be found then it will be returned. Otherwise, for
|
|
* non-weapons, the function will return NULL and write some candidates to
|
|
* offscreenobjptr and anyobjptr. offscreenobjptr will be an object that is
|
|
* offscreen, while anyobjptr will be any object.
|
|
*
|
|
* In reality this function is only called with objtypes weapon and hat, and the
|
|
* hat caller is unreachable because hats don't exist in PD. So it's only used
|
|
* for weapons which means the candidate logic isn't used.
|
|
*/
|
|
struct defaultobj *setupFindObjForReuse(s32 wanttype, struct defaultobj **offscreenobjptr, struct defaultobj **anyobjptr, bool musthaveprop, bool musthavemodel, struct modelfiledata *filedata)
|
|
{
|
|
struct defaultobj *offscreenobj = NULL;
|
|
struct defaultobj *anyobj = NULL;
|
|
|
|
u32 *cmd = g_StageSetup.props;
|
|
|
|
if (cmd) {
|
|
while ((u8)cmd[0] != OBJTYPE_END) {
|
|
if ((wanttype & 0xff) == (u8)cmd[0]) {
|
|
struct defaultobj *obj = (struct defaultobj *)cmd;
|
|
|
|
if (obj->prop == NULL) {
|
|
if (!musthaveprop && !musthavemodel) {
|
|
return obj;
|
|
}
|
|
} else if (wanttype != OBJTYPE_WEAPON
|
|
&& (obj->hidden & OBJHFLAG_AIRBORNE) == 0
|
|
&& (obj->hidden2 & OBJH2FLAG_CANREGEN) == 0
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
&& (obj->flags & OBJFLAG_00800000) == 0
|
|
#endif
|
|
&& obj->prop->parent == NULL
|
|
&& (!musthavemodel || func0f0b28d0(obj->model, filedata))) {
|
|
if (offscreenobj == NULL && (obj->prop->flags & (PROPFLAG_ONTHISSCREENTHISTICK | PROPFLAG_ONANYSCREENTHISTICK | PROPFLAG_ONANYSCREENPREVTICK)) == 0) {
|
|
offscreenobj = obj;
|
|
}
|
|
|
|
if (anyobj == NULL) {
|
|
anyobj = obj;
|
|
}
|
|
}
|
|
}
|
|
|
|
cmd = cmd + setupGetCmdLength(cmd);
|
|
}
|
|
}
|
|
|
|
*offscreenobjptr = offscreenobj;
|
|
*anyobjptr = anyobj;
|
|
|
|
return NULL;
|
|
}
|