perfect_dark/src/game/setuputils.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;
}