mirror of
https://gitlab.com/ryandwyer/perfect-dark
synced 2026-08-18 05:08:36 -04:00
1072 lines
30 KiB
C
1072 lines
30 KiB
C
#include <ultra64.h>
|
|
#include "constants.h"
|
|
#include "game/cheats.h"
|
|
#include "game/chr/chraction.h"
|
|
#include "game/chr/chr.h"
|
|
#include "game/game_02cde0.h"
|
|
#include "game/prop.h"
|
|
#include "game/atan2f.h"
|
|
#include "game/game_0b28d0.h"
|
|
#include "game/lv.h"
|
|
#include "game/game_1a7560.h"
|
|
#include "game/mplayer/mplayer.h"
|
|
#include "game/pad.h"
|
|
#include "game/propobj.h"
|
|
#include "bss.h"
|
|
#include "lib/memory.h"
|
|
#include "lib/model.h"
|
|
#include "lib/lib_126b0.h"
|
|
#include "lib/rng.h"
|
|
#include "lib/lib_16110.h"
|
|
#include "lib/lib_184d0.h"
|
|
#include "lib/lib_233c0.h"
|
|
#include "lib/lib_24e40.h"
|
|
#include "data.h"
|
|
#include "types.h"
|
|
|
|
s32 g_NumActiveHeadsPerGender;
|
|
u32 var8009cd24;
|
|
u32 g_ActiveMaleHeads[8];
|
|
u32 g_ActiveFemaleHeads[8];
|
|
|
|
s32 g_NumBondBodies = 0;
|
|
s32 g_NumMaleGuardHeads = 0;
|
|
s32 g_NumFemaleGuardHeads = 0;
|
|
s32 g_NumMaleGuardTeamHeads = 0;
|
|
s32 g_NumFemaleGuardTeamHeads = 0;
|
|
s32 var80062b14 = 0;
|
|
s32 var80062b18 = 0;
|
|
|
|
s32 g_BondBodies[] = {
|
|
BODY_DJBOND,
|
|
BODY_CONNERY,
|
|
BODY_DALTON,
|
|
BODY_MOORE,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
};
|
|
|
|
s32 g_MaleGuardHeads[] = {
|
|
HEAD_BEAU1,
|
|
HEAD_CHRIST,
|
|
HEAD_DARLING,
|
|
HEAD_JON,
|
|
HEAD_ROSS,
|
|
HEAD_RUSS,
|
|
HEAD_MARK2,
|
|
HEAD_JAMIE,
|
|
HEAD_DUNCAN2,
|
|
HEAD_BRIAN,
|
|
HEAD_STEVEM,
|
|
HEAD_KEITH,
|
|
HEAD_GRANT,
|
|
HEAD_PENNY,
|
|
HEAD_DAVEC,
|
|
HEAD_JONES,
|
|
HEAD_GRAHAM,
|
|
HEAD_SHAUN,
|
|
HEAD_NEIL2,
|
|
HEAD_EDMCG,
|
|
HEAD_MATT_C,
|
|
HEAD_PEER_S,
|
|
HEAD_ANDY_R,
|
|
HEAD_BEN_R,
|
|
HEAD_STEVE_K,
|
|
HEAD_SCOTT_H,
|
|
HEAD_SANCHEZ,
|
|
HEAD_COOK,
|
|
HEAD_PRYCE,
|
|
HEAD_SILKE,
|
|
HEAD_SMITH,
|
|
HEAD_GARETH,
|
|
HEAD_MURCHIE,
|
|
HEAD_WONG,
|
|
HEAD_CARTER,
|
|
HEAD_TINTIN,
|
|
HEAD_MUNTON,
|
|
HEAD_PHELPS,
|
|
HEAD_KEN,
|
|
HEAD_JOEL,
|
|
HEAD_TIM,
|
|
HEAD_ROBIN,
|
|
-1,
|
|
};
|
|
|
|
s32 g_MaleGuardTeamHeads[] = {
|
|
HEAD_BEAU1,
|
|
HEAD_CHRIST,
|
|
HEAD_DARLING,
|
|
HEAD_JON,
|
|
HEAD_ROSS,
|
|
HEAD_RUSS,
|
|
HEAD_MARK2,
|
|
HEAD_JAMIE,
|
|
HEAD_DUNCAN2,
|
|
HEAD_BRIAN,
|
|
HEAD_STEVEM,
|
|
HEAD_KEITH,
|
|
HEAD_GRANT,
|
|
HEAD_PENNY,
|
|
HEAD_DAVEC,
|
|
HEAD_JONES,
|
|
-1,
|
|
};
|
|
|
|
s32 g_FemaleGuardHeads[] = {
|
|
HEAD_LESLIE_S,
|
|
HEAD_ANKA,
|
|
HEAD_EILEEN_T,
|
|
HEAD_EILEEN_H,
|
|
-1,
|
|
};
|
|
|
|
s32 g_FemaleGuardTeamHeads[] = {
|
|
HEAD_LESLIE_S,
|
|
HEAD_ANKA,
|
|
HEAD_EILEEN_T,
|
|
HEAD_EILEEN_H,
|
|
-1,
|
|
};
|
|
|
|
s32 var80062c80 = 0;
|
|
s32 g_ActiveMaleHeadsIndex = 0;
|
|
s32 g_ActiveFemaleHeadsIndex = 0;
|
|
|
|
s32 g_FemGuardHeads[3] = {
|
|
HEAD_ALEX,
|
|
HEAD_JULIANNE,
|
|
HEAD_LAURA,
|
|
};
|
|
|
|
u32 bodyGetRace(s32 bodynum)
|
|
{
|
|
switch (bodynum) {
|
|
case BODY_SKEDAR:
|
|
case BODY_MINISKEDAR:
|
|
case BODY_SKEDARKING:
|
|
return RACE_SKEDAR;
|
|
case BODY_DRCAROLL:
|
|
return RACE_DRCAROLL;
|
|
case BODY_EYESPY:
|
|
return RACE_EYESPY;
|
|
case BODY_CHICROB:
|
|
return RACE_ROBOT;
|
|
}
|
|
|
|
return RACE_HUMAN;
|
|
}
|
|
|
|
bool bodyLoad(s32 bodynum)
|
|
{
|
|
if (!g_HeadsAndBodies[bodynum].filedata) {
|
|
g_HeadsAndBodies[bodynum].filedata = fileLoad(g_HeadsAndBodies[bodynum].filenum);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
GLOBAL_ASM(
|
|
glabel func0f02ce8c
|
|
.late_rodata
|
|
glabel var7f1a8a70
|
|
.word 0x3dccccce
|
|
glabel var7f1a8a74
|
|
.word 0x3f4ccccd
|
|
glabel var7f1a8a78
|
|
.word 0x3d4ccccd
|
|
glabel var7f1a8a7c
|
|
.word 0x3ecccccd
|
|
glabel var7f1a8a80
|
|
.word 0x3ecccccd
|
|
glabel var7f1a8a84
|
|
.word 0x3dcccccd
|
|
.text
|
|
/* f02ce8c: 00047880 */ sll $t7,$a0,0x2
|
|
/* f02ce90: 01e47821 */ addu $t7,$t7,$a0
|
|
/* f02ce94: 3c188008 */ lui $t8,%hi(g_HeadsAndBodies)
|
|
/* f02ce98: 2718cf04 */ addiu $t8,$t8,%lo(g_HeadsAndBodies)
|
|
/* f02ce9c: 000f7880 */ sll $t7,$t7,0x2
|
|
/* f02cea0: 01f81021 */ addu $v0,$t7,$t8
|
|
/* f02cea4: 3c017f1b */ lui $at,%hi(var7f1a8a70)
|
|
/* f02cea8: c4268a70 */ lwc1 $f6,%lo(var7f1a8a70)($at)
|
|
/* f02ceac: c4440004 */ lwc1 $f4,0x4($v0)
|
|
/* f02ceb0: 27bdffb8 */ addiu $sp,$sp,-72
|
|
/* f02ceb4: c44a0008 */ lwc1 $f10,0x8($v0)
|
|
/* f02ceb8: 46062202 */ mul.s $f8,$f4,$f6
|
|
/* f02cebc: afbf0014 */ sw $ra,0x14($sp)
|
|
/* f02cec0: afa40048 */ sw $a0,0x48($sp)
|
|
/* f02cec4: afa5004c */ sw $a1,0x4c($sp)
|
|
/* f02cec8: afa60050 */ sw $a2,0x50($sp)
|
|
/* f02cecc: afa70054 */ sw $a3,0x54($sp)
|
|
/* f02ced0: afa0003c */ sw $zero,0x3c($sp)
|
|
/* f02ced4: e7a80044 */ swc1 $f8,0x44($sp)
|
|
/* f02ced8: 24040007 */ addiu $a0,$zero,0x7
|
|
/* f02cedc: afa2001c */ sw $v0,0x1c($sp)
|
|
/* f02cee0: 0fc41b99 */ jal cheatIsActive
|
|
/* f02cee4: e7aa0040 */ swc1 $f10,0x40($sp)
|
|
/* f02cee8: 10400005 */ beqz $v0,.L0f02cf00
|
|
/* f02ceec: c7b00044 */ lwc1 $f16,0x44($sp)
|
|
/* f02cef0: 3c017f1b */ lui $at,%hi(var7f1a8a74)
|
|
/* f02cef4: c4328a74 */ lwc1 $f18,%lo(var7f1a8a74)($at)
|
|
/* f02cef8: 46128102 */ mul.s $f4,$f16,$f18
|
|
/* f02cefc: e7a40044 */ swc1 $f4,0x44($sp)
|
|
.L0f02cf00:
|
|
/* f02cf00: 8fb90050 */ lw $t9,0x50($sp)
|
|
/* f02cf04: 8fa8001c */ lw $t0,0x1c($sp)
|
|
/* f02cf08: 1720000a */ bnez $t9,.L0f02cf34
|
|
/* f02cf0c: 00000000 */ nop
|
|
/* f02cf10: 8d03000c */ lw $v1,0xc($t0)
|
|
/* f02cf14: 54600007 */ bnezl $v1,.L0f02cf34
|
|
/* f02cf18: afa30050 */ sw $v1,0x50($sp)
|
|
/* f02cf1c: 0fc69e11 */ jal fileLoad
|
|
/* f02cf20: 95040002 */ lhu $a0,0x2($t0)
|
|
/* f02cf24: 8fa4001c */ lw $a0,0x1c($sp)
|
|
/* f02cf28: 00401825 */ or $v1,$v0,$zero
|
|
/* f02cf2c: ac82000c */ sw $v0,0xc($a0)
|
|
/* f02cf30: afa30050 */ sw $v1,0x50($sp)
|
|
.L0f02cf34:
|
|
/* f02cf34: 0c008b49 */ jal modelCalculateRwDataLen
|
|
/* f02cf38: 8fa40050 */ lw $a0,0x50($sp)
|
|
/* f02cf3c: 8fa9001c */ lw $t1,0x1c($sp)
|
|
/* f02cf40: 8fac0050 */ lw $t4,0x50($sp)
|
|
/* f02cf44: 8d220000 */ lw $v0,0x0($t1)
|
|
/* f02cf48: 00025840 */ sll $t3,$v0,0x1
|
|
/* f02cf4c: 056200b9 */ bltzl $t3,.L0f02d234
|
|
/* f02cf50: 8fa2005c */ lw $v0,0x5c($sp)
|
|
/* f02cf54: 8d830004 */ lw $v1,0x4($t4)
|
|
/* f02cf58: 3c0d8008 */ lui $t5,%hi(g_ModelTypeChr)
|
|
/* f02cf5c: 25adce40 */ addiu $t5,$t5,%lo(g_ModelTypeChr)
|
|
/* f02cf60: 15a30090 */ bne $t5,$v1,.L0f02d1a4
|
|
/* f02cf64: 01802025 */ or $a0,$t4,$zero
|
|
/* f02cf68: 0c006a47 */ jal modelGetPart
|
|
/* f02cf6c: 24050004 */ addiu $a1,$zero,0x4
|
|
/* f02cf70: 104000af */ beqz $v0,.L0f02d230
|
|
/* f02cf74: afa2003c */ sw $v0,0x3c($sp)
|
|
/* f02cf78: 8fa7004c */ lw $a3,0x4c($sp)
|
|
/* f02cf7c: 240effff */ addiu $t6,$zero,-1
|
|
/* f02cf80: 04e1000a */ bgez $a3,.L0f02cfac
|
|
/* f02cf84: 01c72023 */ subu $a0,$t6,$a3
|
|
/* f02cf88: 0fc6395f */ jal func0f18e57c
|
|
/* f02cf8c: 27a5004c */ addiu $a1,$sp,0x4c
|
|
/* f02cf90: 8faf0050 */ lw $t7,0x50($sp)
|
|
/* f02cf94: afa20054 */ sw $v0,0x54($sp)
|
|
/* f02cf98: 84590014 */ lh $t9,0x14($v0)
|
|
/* f02cf9c: 85f80014 */ lh $t8,0x14($t7)
|
|
/* f02cfa0: 03194021 */ addu $t0,$t8,$t9
|
|
/* f02cfa4: 10000061 */ b .L0f02d12c
|
|
/* f02cfa8: a5e80014 */ sh $t0,0x14($t7)
|
|
.L0f02cfac:
|
|
/* f02cfac: 18e0005f */ blez $a3,.L0f02d12c
|
|
/* f02cfb0: 8fa90054 */ lw $t1,0x54($sp)
|
|
/* f02cfb4: 15200036 */ bnez $t1,.L0f02d090
|
|
/* f02cfb8: 3c0a800a */ lui $t2,%hi(g_Vars+0x318)
|
|
/* f02cfbc: 8d4aa2d8 */ lw $t2,%lo(g_Vars+0x318)($t2)
|
|
/* f02cfc0: 00074080 */ sll $t0,$a3,0x2
|
|
/* f02cfc4: 3c0b8009 */ lui $t3,%hi(g_Is4Mb)
|
|
/* f02cfc8: 1140001e */ beqz $t2,.L0f02d044
|
|
/* f02cfcc: 01074021 */ addu $t0,$t0,$a3
|
|
/* f02cfd0: 916b0af0 */ lbu $t3,%lo(g_Is4Mb)($t3)
|
|
/* f02cfd4: 24010001 */ addiu $at,$zero,0x1
|
|
/* f02cfd8: 00076880 */ sll $t5,$a3,0x2
|
|
/* f02cfdc: 11610019 */ beq $t3,$at,.L0f02d044
|
|
/* f02cfe0: 01a76821 */ addu $t5,$t5,$a3
|
|
/* f02cfe4: 000d6880 */ sll $t5,$t5,0x2
|
|
/* f02cfe8: 3c048008 */ lui $a0,%hi(g_HeadsAndBodies+0x2)
|
|
/* f02cfec: 008d2021 */ addu $a0,$a0,$t5
|
|
/* f02cff0: 0fc69e11 */ jal fileLoad
|
|
/* f02cff4: 9484cf06 */ lhu $a0,%lo(g_HeadsAndBodies+0x2)($a0)
|
|
/* f02cff8: 8fa5004c */ lw $a1,0x4c($sp)
|
|
/* f02cffc: 3c0e8008 */ lui $t6,%hi(g_HeadsAndBodies)
|
|
/* f02d000: 25cecf04 */ addiu $t6,$t6,%lo(g_HeadsAndBodies)
|
|
/* f02d004: 00056080 */ sll $t4,$a1,0x2
|
|
/* f02d008: 01856021 */ addu $t4,$t4,$a1
|
|
/* f02d00c: 000c6080 */ sll $t4,$t4,0x2
|
|
/* f02d010: 018e1821 */ addu $v1,$t4,$t6
|
|
/* f02d014: 94780002 */ lhu $t8,0x2($v1)
|
|
/* f02d018: 3c01800a */ lui $at,%hi(g_FileInfo)
|
|
/* f02d01c: ac62000c */ sw $v0,0xc($v1)
|
|
/* f02d020: 0018c8c0 */ sll $t9,$t8,0x3
|
|
/* f02d024: 00390821 */ addu $at,$at,$t9
|
|
/* f02d028: afa20054 */ sw $v0,0x54($sp)
|
|
/* f02d02c: ac206680 */ sw $zero,%lo(g_FileInfo)($at)
|
|
/* f02d030: 00402025 */ or $a0,$v0,$zero
|
|
/* f02d034: 0fc0b76f */ jal bodyCalculateHeadOffset
|
|
/* f02d038: 8fa60048 */ lw $a2,0x48($sp)
|
|
/* f02d03c: 10000014 */ b .L0f02d090
|
|
/* f02d040: 00000000 */ nop
|
|
.L0f02d044:
|
|
/* f02d044: 3c0f8008 */ lui $t7,%hi(g_HeadsAndBodies)
|
|
/* f02d048: 25efcf04 */ addiu $t7,$t7,%lo(g_HeadsAndBodies)
|
|
/* f02d04c: 00084080 */ sll $t0,$t0,0x2
|
|
/* f02d050: 010f1821 */ addu $v1,$t0,$t7
|
|
/* f02d054: 8c64000c */ lw $a0,0xc($v1)
|
|
/* f02d058: 5480000d */ bnezl $a0,.L0f02d090
|
|
/* f02d05c: afa40054 */ sw $a0,0x54($sp)
|
|
/* f02d060: 0fc69e11 */ jal fileLoad
|
|
/* f02d064: 94640002 */ lhu $a0,0x2($v1)
|
|
/* f02d068: 8fa7004c */ lw $a3,0x4c($sp)
|
|
/* f02d06c: 3c0a8008 */ lui $t2,%hi(g_HeadsAndBodies)
|
|
/* f02d070: 254acf04 */ addiu $t2,$t2,%lo(g_HeadsAndBodies)
|
|
/* f02d074: 00074880 */ sll $t1,$a3,0x2
|
|
/* f02d078: 01274821 */ addu $t1,$t1,$a3
|
|
/* f02d07c: 00094880 */ sll $t1,$t1,0x2
|
|
/* f02d080: 012a1821 */ addu $v1,$t1,$t2
|
|
/* f02d084: ac62000c */ sw $v0,0xc($v1)
|
|
/* f02d088: 00402025 */ or $a0,$v0,$zero
|
|
/* f02d08c: afa40054 */ sw $a0,0x54($sp)
|
|
.L0f02d090:
|
|
/* f02d090: 0c008b49 */ jal modelCalculateRwDataLen
|
|
/* f02d094: 8fa40054 */ lw $a0,0x54($sp)
|
|
/* f02d098: 8fab0050 */ lw $t3,0x50($sp)
|
|
/* f02d09c: 8fac0054 */ lw $t4,0x54($sp)
|
|
/* f02d0a0: 856d0014 */ lh $t5,0x14($t3)
|
|
/* f02d0a4: 858e0014 */ lh $t6,0x14($t4)
|
|
/* f02d0a8: 01aec021 */ addu $t8,$t5,$t6
|
|
/* f02d0ac: a5780014 */ sh $t8,0x14($t3)
|
|
/* f02d0b0: 8fb9001c */ lw $t9,0x1c($sp)
|
|
/* f02d0b4: 93aa0067 */ lbu $t2,0x67($sp)
|
|
/* f02d0b8: 8f280000 */ lw $t0,0x0($t9)
|
|
/* f02d0bc: 00084880 */ sll $t1,$t0,0x2
|
|
/* f02d0c0: 0523001b */ bgezl $t1,.L0f02d130
|
|
/* f02d0c4: 8fac0060 */ lw $t4,0x60($sp)
|
|
/* f02d0c8: 51400019 */ beqzl $t2,.L0f02d130
|
|
/* f02d0cc: 8fac0060 */ lw $t4,0x60($sp)
|
|
/* f02d0d0: 0c004b70 */ jal random
|
|
/* f02d0d4: 00000000 */ nop
|
|
/* f02d0d8: 44823000 */ mtc1 $v0,$f6
|
|
/* f02d0dc: 3c017f1b */ lui $at,%hi(var7f1a8a78)
|
|
/* f02d0e0: c4228a78 */ lwc1 $f2,%lo(var7f1a8a78)($at)
|
|
/* f02d0e4: 04410005 */ bgez $v0,.L0f02d0fc
|
|
/* f02d0e8: 46803220 */ cvt.s.w $f8,$f6
|
|
/* f02d0ec: 3c014f80 */ lui $at,0x4f80
|
|
/* f02d0f0: 44815000 */ mtc1 $at,$f10
|
|
/* f02d0f4: 00000000 */ nop
|
|
/* f02d0f8: 460a4200 */ add.s $f8,$f8,$f10
|
|
.L0f02d0fc:
|
|
/* f02d0fc: 3c012f80 */ lui $at,0x2f80
|
|
/* f02d100: 44818000 */ mtc1 $at,$f16
|
|
/* f02d104: 3c013f80 */ lui $at,0x3f80
|
|
/* f02d108: 44815000 */ mtc1 $at,$f10
|
|
/* f02d10c: 46104482 */ mul.s $f18,$f8,$f16
|
|
/* f02d110: c7b00044 */ lwc1 $f16,0x44($sp)
|
|
/* f02d114: 46029002 */ mul.s $f0,$f18,$f2
|
|
/* f02d118: 46000100 */ add.s $f4,$f0,$f0
|
|
/* f02d11c: 46022181 */ sub.s $f6,$f4,$f2
|
|
/* f02d120: 460a3200 */ add.s $f8,$f6,$f10
|
|
/* f02d124: 46088482 */ mul.s $f18,$f16,$f8
|
|
/* f02d128: e7b20044 */ swc1 $f18,0x44($sp)
|
|
.L0f02d12c:
|
|
/* f02d12c: 8fac0060 */ lw $t4,0x60($sp)
|
|
.L0f02d130:
|
|
/* f02d130: 15800013 */ bnez $t4,.L0f02d180
|
|
/* f02d134: 00000000 */ nop
|
|
/* f02d138: 0fc41b99 */ jal cheatIsActive
|
|
/* f02d13c: 2404000b */ addiu $a0,$zero,0xb
|
|
/* f02d140: 10400005 */ beqz $v0,.L0f02d158
|
|
/* f02d144: c7a40044 */ lwc1 $f4,0x44($sp)
|
|
/* f02d148: 3c017f1b */ lui $at,%hi(var7f1a8a7c)
|
|
/* f02d14c: c4268a7c */ lwc1 $f6,%lo(var7f1a8a7c)($at)
|
|
/* f02d150: 46062282 */ mul.s $f10,$f4,$f6
|
|
/* f02d154: e7aa0044 */ swc1 $f10,0x44($sp)
|
|
.L0f02d158:
|
|
/* f02d158: 0fc41b99 */ jal cheatIsActive
|
|
/* f02d15c: 24040007 */ addiu $a0,$zero,0x7
|
|
/* f02d160: 10400033 */ beqz $v0,.L0f02d230
|
|
/* f02d164: c7b00044 */ lwc1 $f16,0x44($sp)
|
|
/* f02d168: 3c013fa0 */ lui $at,0x3fa0
|
|
/* f02d16c: 44814000 */ mtc1 $at,$f8
|
|
/* f02d170: 00000000 */ nop
|
|
/* f02d174: 46088482 */ mul.s $f18,$f16,$f8
|
|
/* f02d178: 1000002d */ b .L0f02d230
|
|
/* f02d17c: e7b20044 */ swc1 $f18,0x44($sp)
|
|
.L0f02d180:
|
|
/* f02d180: 0fc41b99 */ jal cheatIsActive
|
|
/* f02d184: 2404000a */ addiu $a0,$zero,0xa
|
|
/* f02d188: 10400029 */ beqz $v0,.L0f02d230
|
|
/* f02d18c: c7a40044 */ lwc1 $f4,0x44($sp)
|
|
/* f02d190: 3c017f1b */ lui $at,%hi(var7f1a8a80)
|
|
/* f02d194: c4268a80 */ lwc1 $f6,%lo(var7f1a8a80)($at)
|
|
/* f02d198: 46062282 */ mul.s $f10,$f4,$f6
|
|
/* f02d19c: 10000024 */ b .L0f02d230
|
|
/* f02d1a0: e7aa0044 */ swc1 $f10,0x44($sp)
|
|
.L0f02d1a4:
|
|
/* f02d1a4: 3c0d8008 */ lui $t5,%hi(g_ModelTypeSkedar)
|
|
/* f02d1a8: 25adce98 */ addiu $t5,$t5,%lo(g_ModelTypeSkedar)
|
|
/* f02d1ac: 15a30020 */ bne $t5,$v1,.L0f02d230
|
|
/* f02d1b0: 0002c080 */ sll $t8,$v0,0x2
|
|
/* f02d1b4: 0701001e */ bgez $t8,.L0f02d230
|
|
/* f02d1b8: 93ab0067 */ lbu $t3,0x67($sp)
|
|
/* f02d1bc: 1160001c */ beqz $t3,.L0f02d230
|
|
/* f02d1c0: 8fb9001c */ lw $t9,0x1c($sp)
|
|
/* f02d1c4: 3c088008 */ lui $t0,%hi(g_HeadsAndBodies+0x730)
|
|
/* f02d1c8: 2508d634 */ addiu $t0,$t0,%lo(g_HeadsAndBodies+0x730)
|
|
/* f02d1cc: 57280019 */ bnel $t9,$t0,.L0f02d234
|
|
/* f02d1d0: 8fa2005c */ lw $v0,0x5c($sp)
|
|
/* f02d1d4: 0c004b70 */ jal random
|
|
/* f02d1d8: 00000000 */ nop
|
|
/* f02d1dc: 44828000 */ mtc1 $v0,$f16
|
|
/* f02d1e0: 3c017f1b */ lui $at,%hi(var7f1a8a84)
|
|
/* f02d1e4: c4228a84 */ lwc1 $f2,%lo(var7f1a8a84)($at)
|
|
/* f02d1e8: 04410005 */ bgez $v0,.L0f02d200
|
|
/* f02d1ec: 46808220 */ cvt.s.w $f8,$f16
|
|
/* f02d1f0: 3c014f80 */ lui $at,0x4f80
|
|
/* f02d1f4: 44819000 */ mtc1 $at,$f18
|
|
/* f02d1f8: 00000000 */ nop
|
|
/* f02d1fc: 46124200 */ add.s $f8,$f8,$f18
|
|
.L0f02d200:
|
|
/* f02d200: 3c012f80 */ lui $at,0x2f80
|
|
/* f02d204: 44812000 */ mtc1 $at,$f4
|
|
/* f02d208: 3c013f40 */ lui $at,0x3f40
|
|
/* f02d20c: 44819000 */ mtc1 $at,$f18
|
|
/* f02d210: 46044182 */ mul.s $f6,$f8,$f4
|
|
/* f02d214: c7a40044 */ lwc1 $f4,0x44($sp)
|
|
/* f02d218: 46061002 */ mul.s $f0,$f2,$f6
|
|
/* f02d21c: 46000280 */ add.s $f10,$f0,$f0
|
|
/* f02d220: 46025401 */ sub.s $f16,$f10,$f2
|
|
/* f02d224: 46128200 */ add.s $f8,$f16,$f18
|
|
/* f02d228: 46082182 */ mul.s $f6,$f4,$f8
|
|
/* f02d22c: e7a60044 */ swc1 $f6,0x44($sp)
|
|
.L0f02d230:
|
|
/* f02d230: 8fa2005c */ lw $v0,0x5c($sp)
|
|
.L0f02d234:
|
|
/* f02d234: 8fa90050 */ lw $t1,0x50($sp)
|
|
/* f02d238: 10400008 */ beqz $v0,.L0f02d25c
|
|
/* f02d23c: 00000000 */ nop
|
|
/* f02d240: 844f0002 */ lh $t7,0x2($v0)
|
|
/* f02d244: 852a0014 */ lh $t2,0x14($t1)
|
|
/* f02d248: 01ea082a */ slt $at,$t7,$t2
|
|
/* f02d24c: 50200007 */ beqzl $at,.L0f02d26c
|
|
/* f02d250: 8fac005c */ lw $t4,0x5c($sp)
|
|
/* f02d254: 10000005 */ b .L0f02d26c
|
|
/* f02d258: 8fac005c */ lw $t4,0x5c($sp)
|
|
.L0f02d25c:
|
|
/* f02d25c: 0fc2cca0 */ jal func0f0b3280
|
|
/* f02d260: 8fa40050 */ lw $a0,0x50($sp)
|
|
/* f02d264: afa2005c */ sw $v0,0x5c($sp)
|
|
/* f02d268: 8fac005c */ lw $t4,0x5c($sp)
|
|
.L0f02d26c:
|
|
/* f02d26c: 1180002d */ beqz $t4,.L0f02d324
|
|
/* f02d270: 01802025 */ or $a0,$t4,$zero
|
|
/* f02d274: 0c006bd6 */ jal modelSetScale
|
|
/* f02d278: 8fa50044 */ lw $a1,0x44($sp)
|
|
/* f02d27c: 8fa4005c */ lw $a0,0x5c($sp)
|
|
/* f02d280: 0c006bd9 */ jal modelSetAnimScale
|
|
/* f02d284: 8fa50040 */ lw $a1,0x40($sp)
|
|
/* f02d288: 8fa60054 */ lw $a2,0x54($sp)
|
|
/* f02d28c: 8fad001c */ lw $t5,0x1c($sp)
|
|
/* f02d290: 50c00025 */ beqzl $a2,.L0f02d328
|
|
/* f02d294: 8fbf0014 */ lw $ra,0x14($sp)
|
|
/* f02d298: 8dae0000 */ lw $t6,0x0($t5)
|
|
/* f02d29c: 8fb90050 */ lw $t9,0x50($sp)
|
|
/* f02d2a0: 000e5840 */ sll $t3,$t6,0x1
|
|
/* f02d2a4: 05620020 */ bltzl $t3,.L0f02d328
|
|
/* f02d2a8: 8fbf0014 */ lw $ra,0x14($sp)
|
|
/* f02d2ac: 87280014 */ lh $t0,0x14($t9)
|
|
/* f02d2b0: 84c90014 */ lh $t1,0x14($a2)
|
|
/* f02d2b4: 01097823 */ subu $t7,$t0,$t1
|
|
/* f02d2b8: a72f0014 */ sh $t7,0x14($t9)
|
|
/* f02d2bc: 8fa5003c */ lw $a1,0x3c($sp)
|
|
/* f02d2c0: 0fc2cca8 */ jal func0f0b32a0
|
|
/* f02d2c4: 8fa4005c */ lw $a0,0x5c($sp)
|
|
/* f02d2c8: 8faa0054 */ lw $t2,0x54($sp)
|
|
/* f02d2cc: 2401000d */ addiu $at,$zero,0xd
|
|
/* f02d2d0: 8fad0058 */ lw $t5,0x58($sp)
|
|
/* f02d2d4: 854c0006 */ lh $t4,0x6($t2)
|
|
/* f02d2d8: 55810013 */ bnel $t4,$at,.L0f02d328
|
|
/* f02d2dc: 8fbf0014 */ lw $ra,0x14($sp)
|
|
/* f02d2e0: 15a00008 */ bnez $t5,.L0f02d304
|
|
/* f02d2e4: 01402025 */ or $a0,$t2,$zero
|
|
/* f02d2e8: 0c006a47 */ jal modelGetPart
|
|
/* f02d2ec: 00002825 */ or $a1,$zero,$zero
|
|
/* f02d2f0: 10400004 */ beqz $v0,.L0f02d304
|
|
/* f02d2f4: 00402825 */ or $a1,$v0,$zero
|
|
/* f02d2f8: 0c006a87 */ jal modelGetNodeRwData
|
|
/* f02d2fc: 8fa4005c */ lw $a0,0x5c($sp)
|
|
/* f02d300: ac400000 */ sw $zero,0x0($v0)
|
|
.L0f02d304:
|
|
/* f02d304: 8fa40054 */ lw $a0,0x54($sp)
|
|
/* f02d308: 0c006a47 */ jal modelGetPart
|
|
/* f02d30c: 24050004 */ addiu $a1,$zero,0x4
|
|
/* f02d310: 10400004 */ beqz $v0,.L0f02d324
|
|
/* f02d314: 00402825 */ or $a1,$v0,$zero
|
|
/* f02d318: 0c006a87 */ jal modelGetNodeRwData
|
|
/* f02d31c: 8fa4005c */ lw $a0,0x5c($sp)
|
|
/* f02d320: ac400000 */ sw $zero,0x0($v0)
|
|
.L0f02d324:
|
|
/* f02d324: 8fbf0014 */ lw $ra,0x14($sp)
|
|
.L0f02d328:
|
|
/* f02d328: 8fa2005c */ lw $v0,0x5c($sp)
|
|
/* f02d32c: 27bd0048 */ addiu $sp,$sp,0x48
|
|
/* f02d330: 03e00008 */ jr $ra
|
|
/* f02d334: 00000000 */ nop
|
|
);
|
|
|
|
// Mismatch: The model->unk02 < headfiledata->rwdatalen statement needs to use
|
|
// bodyfiledata instead of headfiledata, but the extra reference to bodyfiledata
|
|
// causes bodyfiledata to be promoted from t registers to a registers, which
|
|
// causes significant codegen changes.
|
|
//struct model *func0f02ce8c(s32 bodynum, s32 headnum, struct modelfiledata *bodyfiledata, struct modelfiledata *headfiledata, bool sunglasses, struct model *model, bool isplayer, u8 varyheight)
|
|
//{
|
|
// f32 scale = g_HeadsAndBodies[bodynum].scale * 0.1f;
|
|
// f32 animscale = g_HeadsAndBodies[bodynum].animscale;
|
|
// struct modelnode *node = NULL;
|
|
// u32 stack[2];
|
|
//
|
|
// if (cheatIsActive(CHEAT_DKMODE)) {
|
|
// scale *= 0.8f;
|
|
// }
|
|
//
|
|
// if (bodyfiledata == NULL) {
|
|
// if (g_HeadsAndBodies[bodynum].filedata == NULL) {
|
|
// g_HeadsAndBodies[bodynum].filedata = fileLoad(g_HeadsAndBodies[bodynum].filenum);
|
|
// }
|
|
//
|
|
// bodyfiledata = g_HeadsAndBodies[bodynum].filedata;
|
|
// }
|
|
//
|
|
// modelCalculateRwDataLen(bodyfiledata);
|
|
//
|
|
// if (!g_HeadsAndBodies[bodynum].unk00_01) {
|
|
// if (bodyfiledata->type == &g_ModelTypeChr) {
|
|
// node = modelGetPart(bodyfiledata, MODELPART_CHR_HEADSPOT);
|
|
//
|
|
// if (node != NULL) {
|
|
// if (headnum < 0) {
|
|
// headfiledata = func0f18e57c(-1 - headnum, &headnum);
|
|
// bodyfiledata->rwdatalen += headfiledata->rwdatalen;
|
|
// } else if (headnum > 0) {
|
|
// if (headfiledata == NULL) {
|
|
// if (g_Vars.normmplayerisrunning && !IS4MB()) {
|
|
// headfiledata = fileLoad(g_HeadsAndBodies[headnum].filenum);
|
|
// g_HeadsAndBodies[headnum].filedata = headfiledata;
|
|
// g_FileInfo[g_HeadsAndBodies[headnum].filenum].size = 0;
|
|
// bodyCalculateHeadOffset(headfiledata, headnum, bodynum);
|
|
// } else {
|
|
// if (g_HeadsAndBodies[headnum].filedata == NULL) {
|
|
// g_HeadsAndBodies[headnum].filedata = fileLoad(g_HeadsAndBodies[headnum].filenum);
|
|
// }
|
|
//
|
|
// headfiledata = g_HeadsAndBodies[headnum].filedata;
|
|
// }
|
|
// }
|
|
//
|
|
// modelCalculateRwDataLen(headfiledata);
|
|
//
|
|
// bodyfiledata->rwdatalen += headfiledata->rwdatalen;
|
|
//
|
|
// if (g_HeadsAndBodies[bodynum].canvaryheight && varyheight) {
|
|
// // Set height to between 95% and 115%
|
|
// f32 frac = random() * (1.0f / U32_MAX) * 0.05f;
|
|
// scale *= 2.0f * frac - 0.05f + 1.0f;
|
|
// }
|
|
// }
|
|
//
|
|
// if (!isplayer) {
|
|
// if (cheatIsActive(CHEAT_SMALLCHARACTERS)) {
|
|
// scale *= 0.4f;
|
|
// }
|
|
//
|
|
// if (cheatIsActive(CHEAT_DKMODE)) {
|
|
// scale *= 1.25f;
|
|
// }
|
|
// } else {
|
|
// if (cheatIsActive(CHEAT_SMALLJO)) {
|
|
// scale *= 0.4f;
|
|
// }
|
|
// }
|
|
// }
|
|
// } else if (bodyfiledata->type == &g_ModelTypeSkedar) {
|
|
// if (g_HeadsAndBodies[bodynum].canvaryheight && varyheight && bodynum == BODY_SKEDAR) {
|
|
// // Set height to between 65% and 85%
|
|
// f32 frac = random() * (1.0f / U32_MAX);
|
|
// scale *= 2.0f * (0.1f * frac) - 0.1f + 0.75f;
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
// if (model) {
|
|
// if (model->unk02 < bodyfiledata->rwdatalen) {
|
|
// // empty
|
|
// }
|
|
// } else {
|
|
// model = func0f0b3280(bodyfiledata);
|
|
// }
|
|
//
|
|
// if (model) {
|
|
// modelSetScale(model, scale);
|
|
// modelSetAnimScale(model, animscale);
|
|
//
|
|
// if (headfiledata && !g_HeadsAndBodies[bodynum].unk00_01) {
|
|
// bodyfiledata->rwdatalen -= headfiledata->rwdatalen;
|
|
//
|
|
// func0f0b32a0(model, node, headfiledata);
|
|
//
|
|
// if ((s16)*(s32 *)&headfiledata->type == MODELTYPE_HEAD) {
|
|
// struct modelnode *node2;
|
|
//
|
|
// if (!sunglasses) {
|
|
// node2 = modelGetPart(headfiledata, MODELPART_HEAD_SUNGLASSES);
|
|
//
|
|
// if (node2) {
|
|
// union modelrwdata *rwdata = modelGetNodeRwData(model, node2);
|
|
// rwdata->toggle.visible = false;
|
|
// }
|
|
// }
|
|
//
|
|
// node2 = modelGetPart(headfiledata, MODELPART_HEAD_HUDPIECE);
|
|
//
|
|
// if (node2) {
|
|
// union modelrwdata *rwdata = modelGetNodeRwData(model, node2);
|
|
// rwdata->toggle.visible = false;
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
// return model;
|
|
//}
|
|
|
|
struct model *func0f02d338(s32 bodynum, s32 headnum, struct modelfiledata *bodyfiledata, struct modelfiledata *headfiledata, bool sunglasses, u8 varyheight)
|
|
{
|
|
return func0f02ce8c(bodynum, headnum, bodyfiledata, headfiledata, sunglasses, NULL, false, varyheight);
|
|
}
|
|
|
|
struct model *modelAllocateChr(s32 bodynum, s32 headnum, u32 spawnflags)
|
|
{
|
|
bool sunglasses = false;
|
|
u8 varyheight = true;
|
|
|
|
if (spawnflags & SPAWNFLAG_FORCESUNGLASSES) {
|
|
sunglasses = true;
|
|
} else if (spawnflags & SPAWNFLAG_MAYBESUNGLASSES) {
|
|
sunglasses = random() % 2 == 0;
|
|
}
|
|
|
|
if (spawnflags & SPAWNFLAG_FIXEDHEIGHT) {
|
|
varyheight = false;
|
|
}
|
|
|
|
return func0f02d338(bodynum, headnum, NULL, NULL, sunglasses, varyheight);
|
|
}
|
|
|
|
s32 func0f02d3f8(void)
|
|
{
|
|
return g_BondBodies[var80062c80];
|
|
}
|
|
|
|
s32 bodyChooseHead(s32 bodynum)
|
|
{
|
|
s32 head;
|
|
|
|
if (g_HeadsAndBodies[bodynum].ismale) {
|
|
head = g_ActiveMaleHeads[g_ActiveMaleHeadsIndex++];
|
|
|
|
if (g_ActiveMaleHeadsIndex == g_NumActiveHeadsPerGender) {
|
|
g_ActiveMaleHeadsIndex = 0;
|
|
}
|
|
} else if (bodynum == BODY_FEM_GUARD) {
|
|
head = g_FemGuardHeads[random() % 3];
|
|
} else {
|
|
head = g_ActiveFemaleHeads[g_ActiveFemaleHeadsIndex++];
|
|
|
|
if (g_ActiveFemaleHeadsIndex == g_NumActiveHeadsPerGender) {
|
|
g_ActiveFemaleHeadsIndex = 0;
|
|
}
|
|
}
|
|
|
|
return head;
|
|
}
|
|
|
|
/**
|
|
* Read a "packed" chr definition and create a runtime chr from it.
|
|
*
|
|
* Chr definitions are stored in a packed format in each stage's setup file.
|
|
* The packed format is used for space saving reasons.
|
|
*/
|
|
void chrUnpack(s32 stagenum, struct packedchr *packed, s32 cmdindex)
|
|
{
|
|
struct pad pad;
|
|
s16 rooms[2];
|
|
struct chrdata *chr;
|
|
struct modelfiledata *headfiledata;
|
|
struct model *model;
|
|
struct prop *prop;
|
|
s32 bodynum;
|
|
s32 headnum;
|
|
f32 angle;
|
|
s32 index;
|
|
|
|
padUnpack(packed->padnum, PADFIELD_POS | PADFIELD_LOOK | PADFIELD_ROOM, &pad);
|
|
|
|
rooms[0] = pad.room;
|
|
rooms[1] = -1;
|
|
|
|
if (cdTestVolume(&pad.pos, 20, rooms, CDTYPE_ALL, 1, 200, -200) == CDRESULT_COLLISION
|
|
&& packed->chair == -1
|
|
&& (packed->spawnflags & SPAWNFLAG_IGNORECOLLISION) == 0) {
|
|
return;
|
|
}
|
|
|
|
if (packed->spawnflags & (SPAWNFLAG_ONLYONA | SPAWNFLAG_ONLYONSA | SPAWNFLAG_ONLYONPA)) {
|
|
if ((packed->spawnflags & (SPAWNFLAG_ONLYONA | SPAWNFLAG_ONLYONSA | SPAWNFLAG_ONLYONPA)) == 0) {
|
|
return;
|
|
}
|
|
|
|
if (((packed->spawnflags & SPAWNFLAG_ONLYONA) && lvGetDifficulty() == DIFF_A)
|
|
|| ((packed->spawnflags & SPAWNFLAG_ONLYONSA) && lvGetDifficulty() == DIFF_SA)
|
|
|| ((packed->spawnflags & SPAWNFLAG_ONLYONPA) && lvGetDifficulty() == DIFF_PA)) {
|
|
// ok
|
|
} else {
|
|
return;
|
|
}
|
|
}
|
|
|
|
headnum = -55555;
|
|
headfiledata = NULL;
|
|
|
|
if (packed->bodynum == 255) {
|
|
bodynum = func0f02d3f8();
|
|
} else {
|
|
bodynum = packed->bodynum;
|
|
}
|
|
|
|
if (!g_HeadsAndBodies[bodynum].unk00_01) {
|
|
if (packed->headnum >= 0) {
|
|
headnum = packed->headnum;
|
|
} else if (headnum == -55555) {
|
|
headnum = bodyChooseHead(bodynum);
|
|
}
|
|
}
|
|
|
|
if (headnum < 0) {
|
|
index = -1 - headnum;
|
|
|
|
if (index >= 0 && index < 22) {
|
|
headfiledata = func0f18e57c(index, &headnum);
|
|
}
|
|
|
|
model = func0f02ce8c(bodynum, headnum, NULL, headfiledata, false, NULL, false, false);
|
|
} else {
|
|
model = modelAllocateChr(bodynum, headnum, packed->spawnflags);
|
|
}
|
|
|
|
if (model != NULL) {
|
|
angle = atan2f(pad.look.x, pad.look.z);
|
|
prop = propAllocateChr(model, &pad.pos, rooms, angle, ailistFindById(packed->ailistnum));
|
|
|
|
if (prop != NULL) {
|
|
propActivate(prop);
|
|
propEnable(prop);
|
|
|
|
chr = prop->chr;
|
|
chrSetChrnum(chr, packed->chrnum);
|
|
chr->hearingscale = packed->hearscale / 1000.0f;
|
|
chr->visionrange = packed->viewdist;
|
|
chr->padpreset1 = packed->padpreset;
|
|
chr->chrpreset1 = packed->chrpreset;
|
|
chr->headnum = headnum;
|
|
chr->bodynum = bodynum;
|
|
chr->race = bodyGetRace(chr->bodynum);
|
|
|
|
chr->rtracked = false;
|
|
|
|
if (bodynum == BODY_DRCAROLL) {
|
|
chr->drcarollimage_left = 0;
|
|
chr->drcarollimage_right = 0;
|
|
chr->chrheight = 185;
|
|
chr->chrwidth = 30;
|
|
} else if (bodynum == BODY_CHICROB) {
|
|
chr->unk348[0] = malloc(sizeof(struct fireslotthing), MEMPOOL_STAGE);
|
|
chr->unk348[1] = malloc(sizeof(struct fireslotthing), MEMPOOL_STAGE);
|
|
chr->unk348[0]->beam = malloc(ALIGN16(sizeof(struct beam)), MEMPOOL_STAGE);
|
|
chr->unk348[1]->beam = malloc(ALIGN16(sizeof(struct beam)), MEMPOOL_STAGE);
|
|
chr->unk348[0]->beam->age = -1;
|
|
chr->unk348[1]->beam->age = -1;
|
|
chr->chrheight = 200;
|
|
chr->chrwidth = 42;
|
|
}
|
|
|
|
if (packed->spawnflags & SPAWNFLAG_INVINCIBLE) {
|
|
chr->chrflags |= CHRCFLAG_INVINCIBLE;
|
|
}
|
|
|
|
if (packed->spawnflags & SPAWNFLAG_00000200) {
|
|
chr->hidden |= CHRHFLAG_00400000;
|
|
}
|
|
|
|
if (packed->spawnflags & SPAWNFLAG_ANTINONINTERACTABLE) {
|
|
chr->hidden |= CHRHFLAG_ANTINONINTERACTABLE;
|
|
}
|
|
|
|
if (packed->spawnflags & SPAWNFLAG_00000800) {
|
|
chr->hidden |= CHRHFLAG_08000000;
|
|
}
|
|
|
|
if (packed->spawnflags & SPAWNFLAG_HIDDEN) {
|
|
chr->chrflags |= CHRCFLAG_HIDDEN;
|
|
}
|
|
|
|
if (packed->spawnflags & SPAWNFLAG_RTRACKED) {
|
|
chr->rtracked = true;
|
|
}
|
|
|
|
if (packed->spawnflags & SPAWNFLAG_NOBLOOD) {
|
|
chr->noblood = true;
|
|
}
|
|
|
|
if (packed->spawnflags & SPAWNFLAG_BLUESIGHT) {
|
|
chr->hidden2 |= CHRH2FLAG_BLUESIGHT;
|
|
}
|
|
|
|
chr->flags = packed->flags;
|
|
chr->flags2 = packed->flags2;
|
|
|
|
if (cheatIsActive(CHEAT_MARQUIS)) {
|
|
chr->flags2 &= ~CHRFLAG1_00001000;
|
|
chr->flags2 |= CHRFLAG1_00000001;
|
|
}
|
|
|
|
chr->team = packed->team;
|
|
chr->squadron = packed->squadron;
|
|
chr->aibot = NULL;
|
|
|
|
if (packed->tude != 4) {
|
|
chr->tude = packed->tude;
|
|
} else {
|
|
chr->tude = random() % 4;
|
|
}
|
|
|
|
chr->voicebox = random() % 3;
|
|
|
|
if (!g_HeadsAndBodies[chr->bodynum].ismale) {
|
|
chr->voicebox = VOICEBOX_FEMALE;
|
|
}
|
|
|
|
chr->naturalanim = packed->naturalanim;
|
|
chr->myspecial = packed->chair;
|
|
chr->yvisang = packed->yvisang;
|
|
|
|
packed->chrindex = chr - g_ChrSlots;
|
|
|
|
chr->teamscandist = packed->teamscandist;
|
|
chr->convtalk = packed->convtalk;
|
|
|
|
if (chr->flags & CHRFLAG0_CAN_HEARSPAWN) {
|
|
chr->chrflags |= CHRCFLAG_CLONEABLE;
|
|
}
|
|
|
|
if (!g_Vars.normmplayerisrunning && g_MissionConfig.iscoop && g_Vars.numaibuddies > 0) {
|
|
chr->flags |= CHRFLAG0_AIVSAI;
|
|
}
|
|
|
|
if (random() % 5 == 0) {
|
|
// Make chr punch slower
|
|
chr->flags2 |= CHRFLAG1_ADJUSTPUNCHSPEED;
|
|
}
|
|
|
|
if (CHRRACE(chr) == RACE_SKEDAR) {
|
|
chr->chrflags |= CHRCFLAG_FORCEAUTOAIM;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
struct prop *propAllocateEyespy(struct pad *pad, s16 room)
|
|
{
|
|
s16 rooms[2];
|
|
struct prop *prop;
|
|
struct chrdata *chr;
|
|
struct model *model;
|
|
s32 inlift;
|
|
struct prop *lift;
|
|
f32 ground;
|
|
u32 stack[2];
|
|
|
|
rooms[0] = room;
|
|
rooms[1] = -1;
|
|
|
|
#if PIRACYCHECKS
|
|
{
|
|
u32 checksum = 0;
|
|
s32 *ptr = (s32 *)&lvInit;
|
|
s32 *end = (s32 *)&lvConfigureFade;
|
|
|
|
while (ptr < end) {
|
|
checksum <<= 1;
|
|
checksum ^= *ptr;
|
|
ptr++;
|
|
}
|
|
|
|
if (checksum != CHECKSUM_PLACEHOLDER) {
|
|
s32 *ptr2 = (s32 *)func00012914;
|
|
s32 *end2 = (s32 *)func00012a0c;
|
|
|
|
while (ptr2 < end2) {
|
|
ptr2[0] = 0;
|
|
ptr2++;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
model = modelAllocateChr(BODY_EYESPY, 0, 0);
|
|
|
|
if (model) {
|
|
prop = propAllocateChr(model, &pad->pos, rooms, 0, ailistFindById(GAILIST_IDLE));
|
|
|
|
if (prop) {
|
|
propActivate(prop);
|
|
propEnable(prop);
|
|
chr = prop->chr;
|
|
chrSetChrnum(chr, getNextUnusedChrnum());
|
|
chr->bodynum = BODY_EYESPY;
|
|
chr->padpreset1 = 0;
|
|
chr->chrpreset1 = 0;
|
|
chr->headnum = 0;
|
|
chr->hearingscale = 0;
|
|
chr->visionrange = 0;
|
|
chr->race = bodyGetRace(chr->bodynum);
|
|
|
|
ground = cdFindGroundY(&pad->pos, 30, rooms, NULL, NULL, NULL, NULL, &inlift, &lift);
|
|
chr->ground = ground;
|
|
chr->manground = ground;
|
|
|
|
chr->flags = 0;
|
|
chr->flags2 = 0;
|
|
chr->team = 0;
|
|
chr->squadron = 0;
|
|
chr->maxdamage = 2;
|
|
chr->tude = random() & 3;
|
|
chr->voicebox = random() % 3;
|
|
chr->naturalanim = 0;
|
|
chr->myspecial = 0;
|
|
chr->yvisang = 0;
|
|
chr->teamscandist = 0;
|
|
chr->convtalk = 0;
|
|
chr->chrwidth = 26;
|
|
chr->chrheight = 200;
|
|
func0f02e9a0(chr, 0);
|
|
chr->chrflags |= CHRCFLAG_HIDDEN;
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
chr->hidden2 |= CHRH2FLAG_0040;
|
|
#else
|
|
chr->hidden |= CHRHFLAG_00000200;
|
|
#endif
|
|
|
|
return prop;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void func0f02ddbf(void)
|
|
{
|
|
// empty
|
|
}
|
|
|
|
/**
|
|
* Tweak the head's Y offset to suit the body.
|
|
*
|
|
* By default, heads and their matching bodies align perfectly and don't need
|
|
* any tweaking. This function is used in multiplier where players can put any
|
|
* heads on any bodies.
|
|
*/
|
|
void bodyCalculateHeadOffset(struct modelfiledata *headfiledata, s32 headnum, s32 bodynum)
|
|
{
|
|
struct modelnode *node;
|
|
struct modelnode *prev;
|
|
Gfx *gdl;
|
|
s32 offset;
|
|
struct modelrodata_bbox *bbox;
|
|
s32 i;
|
|
|
|
if ((s16)(*(s32 *)&headfiledata->type) == MODELTYPE_HEAD) {
|
|
if (g_HeadsAndBodies[headnum].type == g_HeadsAndBodies[bodynum].type) {
|
|
return;
|
|
}
|
|
|
|
switch (g_HeadsAndBodies[headnum].type) {
|
|
default:
|
|
case HEADBODYTYPE_FEMALE:
|
|
offset = 0;
|
|
break;
|
|
case HEADBODYTYPE_MAIAN:
|
|
offset = 0;
|
|
break;
|
|
case HEADBODYTYPE_DEFAULT:
|
|
offset = -35;
|
|
break;
|
|
case HEADBODYTYPE_MRBLONDE:
|
|
offset = 0;
|
|
break;
|
|
case HEADBODYTYPE_CASS:
|
|
offset = -20;
|
|
break;
|
|
case HEADBODYTYPE_FEMALEGUARD:
|
|
offset = -40;
|
|
break;
|
|
}
|
|
|
|
switch (g_HeadsAndBodies[bodynum].type) {
|
|
case HEADBODYTYPE_FEMALE:
|
|
break;
|
|
case HEADBODYTYPE_MAIAN:
|
|
offset -= 30;
|
|
break;
|
|
case HEADBODYTYPE_DEFAULT:
|
|
offset += 35;
|
|
break;
|
|
case HEADBODYTYPE_MRBLONDE:
|
|
break;
|
|
case HEADBODYTYPE_CASS:
|
|
offset += 20;
|
|
break;
|
|
case HEADBODYTYPE_FEMALEGUARD:
|
|
offset += 40;
|
|
break;
|
|
}
|
|
|
|
if (g_HeadsAndBodies[bodynum].type == HEADBODYTYPE_FEMALE) {
|
|
if (g_HeadsAndBodies[headnum].type == HEADBODYTYPE_DEFAULT
|
|
|| g_HeadsAndBodies[headnum].type == HEADBODYTYPE_MRBLONDE) {
|
|
offset -= 10;
|
|
} else if (g_HeadsAndBodies[headnum].type == HEADBODYTYPE_CASS
|
|
|| g_HeadsAndBodies[headnum].type == HEADBODYTYPE_FEMALEGUARD) {
|
|
offset -= 5;
|
|
}
|
|
} else if (g_HeadsAndBodies[bodynum].type == HEADBODYTYPE_CASS
|
|
&& (g_HeadsAndBodies[headnum].type == HEADBODYTYPE_DEFAULT
|
|
|| g_HeadsAndBodies[headnum].type == HEADBODYTYPE_MRBLONDE)) {
|
|
offset -= 5;
|
|
}
|
|
|
|
// Apply the offset
|
|
if (offset != 0) {
|
|
node = NULL;
|
|
|
|
do {
|
|
prev = node;
|
|
|
|
modelIterateDisplayLists(headfiledata, &node, &gdl);
|
|
|
|
if (node && node != prev && node->type == MODELNODETYPE_DL) {
|
|
struct modelrodata_dl *rodata = &node->rodata->dl;
|
|
|
|
for (i = 0; i < rodata->numvertices; i++) {
|
|
rodata->vertices[i].y += offset;
|
|
}
|
|
}
|
|
} while (node);
|
|
|
|
bbox = modelFileDataFindBboxRodata(headfiledata);
|
|
|
|
if (bbox != NULL) {
|
|
bbox->ymin += offset;
|
|
bbox->ymax += offset;
|
|
}
|
|
}
|
|
}
|
|
}
|