mirror of
https://gitlab.com/ryandwyer/perfect-dark
synced 2026-07-04 12:09:54 -04:00
13133 lines
374 KiB
C
13133 lines
374 KiB
C
#include <ultra64.h>
|
|
#include "constants.h"
|
|
#include "game/bondmove.h"
|
|
#include "game/cheats.h"
|
|
#include "game/chraction.h"
|
|
#include "game/inv.h"
|
|
#include "game/game_006900.h"
|
|
#include "game/chr.h"
|
|
#include "game/prop.h"
|
|
#include "game/propsnd.h"
|
|
#include "game/game_096360.h"
|
|
#include "game/acosfasinf.h"
|
|
#include "game/game_096b20.h"
|
|
#include "game/quaternion.h"
|
|
#include "game/game_097aa0.h"
|
|
#include "game/bondgun.h"
|
|
#include "game/gunfx.h"
|
|
#include "game/game_0b0fd0.h"
|
|
#include "game/modeldef.h"
|
|
#include "game/modelmgr.h"
|
|
#include "game/tex.h"
|
|
#include "game/camera.h"
|
|
#include "game/player.h"
|
|
#include "game/mtxf2lbulk.h"
|
|
#include "game/gfxmemory.h"
|
|
#include "game/sight.h"
|
|
#include "game/inv.h"
|
|
#include "game/playermgr.h"
|
|
#include "game/smoke.h"
|
|
#include "game/game_1531a0.h"
|
|
#include "game/file.h"
|
|
#include "game/lv.h"
|
|
#include "game/texdecompress.h"
|
|
#include "game/game_176080.h"
|
|
#include "game/training.h"
|
|
#include "game/lang.h"
|
|
#include "game/mplayer/mplayer.h"
|
|
#include "game/pak.h"
|
|
#include "game/options.h"
|
|
#include "game/propobj.h"
|
|
#include "game/objectives.h"
|
|
#include "bss.h"
|
|
#include "lib/collision.h"
|
|
#include "lib/vi.h"
|
|
#include "lib/joy.h"
|
|
#include "lib/main.h"
|
|
#include "lib/model.h"
|
|
#include "lib/snd.h"
|
|
#include "lib/rng.h"
|
|
#include "lib/mtx.h"
|
|
#include "lib/anim.h"
|
|
#include "lib/lib_317f0.h"
|
|
#include "data.h"
|
|
#include "types.h"
|
|
|
|
#define GUNLOADSTATE_FLUX 0
|
|
#define GUNLOADSTATE_MODEL 1
|
|
#define GUNLOADSTATE_TEXTURES 2
|
|
#define GUNLOADSTATE_DLS 3
|
|
#define GUNLOADSTATE_LOADED 4
|
|
|
|
#define MASTERLOADSTATE_FLUX 0
|
|
#define MASTERLOADSTATE_HANDS 1
|
|
#define MASTERLOADSTATE_GUN 2
|
|
#define MASTERLOADSTATE_CARTS 3
|
|
#define MASTERLOADSTATE_LOADED 4
|
|
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
struct sndstate *g_CasingAudioHandles[2];
|
|
s32 var8009d0d8;
|
|
u32 fill2;
|
|
struct sndstate *g_BgunAudioHandles[4];
|
|
s32 var8009d0dc;
|
|
u32 fill2_2;
|
|
s32 var8009d0f0[3];
|
|
u32 var8009d0fc;
|
|
u32 var8009d100;
|
|
u32 var8009d104;
|
|
u32 var8009d108;
|
|
u32 var8009d10c;
|
|
u32 var8009d110;
|
|
u32 var8009d114;
|
|
u32 var8009d118;
|
|
u32 var8009d11c;
|
|
u32 var8009d120;
|
|
u32 var8009d124;
|
|
u32 var8009d128;
|
|
u32 var8009d12c;
|
|
u32 var8009d130;
|
|
u32 var8009d134;
|
|
u32 var8009d138;
|
|
u32 var8009d13c;
|
|
f32 var8009d140;
|
|
struct hand *var8009d144;
|
|
s32 var8009d148;
|
|
u32 var8009d14c;
|
|
struct fireslot g_Fireslots[NUM_FIRESLOTS];
|
|
#elif VERSION >= VERSION_NTSC_1_0
|
|
struct sndstate *g_CasingAudioHandles[2];
|
|
s32 var8009d0d8;
|
|
s32 var8009d0dc;
|
|
struct sndstate *g_BgunAudioHandles[4];
|
|
s32 var8009d0f0[3];
|
|
u32 var8009d0fc;
|
|
u32 var8009d100;
|
|
u32 var8009d104;
|
|
u32 var8009d108;
|
|
u32 var8009d10c;
|
|
u32 var8009d110;
|
|
u32 var8009d114;
|
|
u32 var8009d118;
|
|
u32 var8009d11c;
|
|
u32 var8009d120;
|
|
u32 var8009d124;
|
|
u32 var8009d128;
|
|
u32 var8009d12c;
|
|
u32 var8009d130;
|
|
u32 var8009d134;
|
|
u32 var8009d138;
|
|
u32 var8009d13c;
|
|
f32 var8009d140;
|
|
struct hand *var8009d144;
|
|
s32 var8009d148;
|
|
u32 var8009d14c;
|
|
struct fireslot g_Fireslots[NUM_FIRESLOTS];
|
|
#else
|
|
s32 var8009d0dc;
|
|
u32 var800a1800nb;
|
|
s32 var8009d0f0[3];
|
|
u32 var8009d0fc;
|
|
u32 var8009d100;
|
|
u32 var8009d104;
|
|
u32 var8009d108;
|
|
u32 var8009d10c;
|
|
u32 var8009d110;
|
|
u32 var8009d114;
|
|
u32 var8009d118;
|
|
u32 var8009d11c;
|
|
u32 var8009d120;
|
|
u32 var8009d124;
|
|
u32 var8009d128;
|
|
u32 var8009d12c;
|
|
u32 var8009d130;
|
|
u32 var8009d134;
|
|
u32 var8009d138;
|
|
u32 var8009d13c;
|
|
f32 var8009d140;
|
|
struct hand *var8009d144;
|
|
s32 var8009d148;
|
|
u32 var8009d14c;
|
|
struct sndstate *g_CasingAudioHandles[2];
|
|
s32 var8009d0d8;
|
|
struct sndstate *g_BgunAudioHandles[4];
|
|
struct fireslot g_Fireslots[NUM_FIRESLOTS];
|
|
u32 fill2[1];
|
|
#endif
|
|
|
|
Lights1 var80070090 = gdSPDefLights1(0x96, 0x96, 0x96, 0xff, 0xff, 0xff, 0xb2, 0x4d, 0x2e);
|
|
|
|
u32 var800700a8 = 0x00025800;
|
|
u32 var800700ac = 0x0001e000;
|
|
|
|
u16 g_CartFileNums[] = {
|
|
FILE_GCARTRIDGE,
|
|
FILE_GCARTRIFLE,
|
|
FILE_GCARTBLUE,
|
|
FILE_GCARTSHELL,
|
|
};
|
|
|
|
u32 var800700b8 = 0x00000000;
|
|
|
|
char var800700bc[][10] = {
|
|
{ 'i','d','l','e' }, // "idle"
|
|
{ 'p','r','e','p','a','r','e' }, // "prepare"
|
|
{ 'c','a','n','t','u','s','e' }, // "cantuse"
|
|
{ 'n','o','a','m','m','o' }, // "noammo"
|
|
{ 'u','s','e','2' }, // "use2"
|
|
{ 'c','h','a','n','g','e' }, // "change"
|
|
{ 'u','p','g','r','a','d','e' }, // "upgrade"
|
|
{ 'c','h','a','n','g','e','f','n' }, // "changefn"
|
|
{ 'i','d','l','e','s','t','u','c','k' }, // "idlestuck"
|
|
{ 'x','x','x' }, // "xxx"
|
|
};
|
|
|
|
#if !MATCHING || VERSION >= VERSION_NTSC_1_0
|
|
void bgunRumble(s32 handnum, s32 weaponnum)
|
|
{
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
u32 stack;
|
|
s32 contpadtouse1;
|
|
s32 contpadtouse2;
|
|
bool singlewield = false;
|
|
s32 contpad1;
|
|
s32 contpad2;
|
|
s32 contpad1hasrumble;
|
|
s32 contpad2hasrumble;
|
|
|
|
joyGetContpadNumsForPlayer(g_Vars.currentplayernum, &contpad1, &contpad2);
|
|
|
|
if (optionsGetControlMode(g_Vars.currentplayerstats->mpindex) >= CONTROLMODE_21
|
|
&& contpad1 >= 0 && contpad2 >= 0) {
|
|
contpad1hasrumble = pakGetType(contpad1) == PAKTYPE_RUMBLE;
|
|
contpad2hasrumble = pakGetType(contpad2) == PAKTYPE_RUMBLE;
|
|
|
|
if (!weaponHasFlag(weaponnum, WEAPONFLAG_DUALWIELD)) {
|
|
singlewield = true;
|
|
}
|
|
|
|
if (contpad1hasrumble && contpad2hasrumble) {
|
|
if (singlewield) {
|
|
pakRumble(contpad1, 0.2f, 2, 4);
|
|
pakRumble(contpad2, 0.2f, 2, 4);
|
|
} else {
|
|
s32 contpadtouse1 = contpad1;
|
|
|
|
if (handnum == HAND_LEFT) {
|
|
contpadtouse1 = contpad2;
|
|
}
|
|
|
|
pakRumble(contpadtouse1, 0.2f, 2, 4);
|
|
}
|
|
} else {
|
|
s32 contpadtouse2 = contpad1;
|
|
|
|
if (contpad2hasrumble) {
|
|
contpadtouse2 = contpad2;
|
|
}
|
|
|
|
pakRumble(contpadtouse2, 0.2f, 2, 4);
|
|
}
|
|
} else {
|
|
if (contpad1 >= 0) {
|
|
pakRumble(contpad1, 0.2f, 2, 4);
|
|
}
|
|
}
|
|
#else
|
|
s32 stack1;
|
|
s32 stack2;
|
|
s8 contpad1;
|
|
s8 contpad2;
|
|
bool contpad1hasrumble;
|
|
bool contpad2hasrumble;
|
|
s32 contpadtouse1;
|
|
s32 contpadtouse2;
|
|
|
|
if (optionsGetControlMode(g_Vars.currentplayerstats->mpindex) >= CONTROLMODE_21) {
|
|
contpad1hasrumble = pakGetType(g_Vars.currentplayernum) == PAKTYPE_RUMBLE;
|
|
contpad2hasrumble = pakGetType(g_Vars.currentplayernum + PLAYERCOUNT()) == PAKTYPE_RUMBLE;
|
|
|
|
if (contpad1hasrumble && contpad2hasrumble) {
|
|
contpadtouse1 = g_Vars.currentplayernum;
|
|
|
|
if (handnum == HAND_LEFT) {
|
|
contpadtouse1 += PLAYERCOUNT();
|
|
}
|
|
|
|
pakRumble(contpadtouse1, 0.2f, 2, 4);
|
|
} else {
|
|
contpadtouse2 = g_Vars.currentplayernum;
|
|
|
|
if (contpad2hasrumble) {
|
|
contpadtouse2 += PLAYERCOUNT();
|
|
}
|
|
|
|
pakRumble(contpadtouse2, 0.2f, 2, 4);
|
|
}
|
|
} else {
|
|
pakRumble(g_Vars.currentplayernum, 0.2f, 2, 4);
|
|
}
|
|
#endif
|
|
}
|
|
#else
|
|
GLOBAL_ASM(
|
|
glabel bgunRumble
|
|
/* f095b30: 27bdffd0 */ addiu $sp,$sp,-48
|
|
/* f095b34: 3c08800a */ lui $t0,%hi(g_Vars)
|
|
/* f095b38: 2508e6c0 */ addiu $t0,$t0,%lo(g_Vars)
|
|
/* f095b3c: 8d0e0288 */ lw $t6,0x288($t0)
|
|
/* f095b40: afbf0014 */ sw $ra,0x14($sp)
|
|
/* f095b44: afa40030 */ sw $a0,0x30($sp)
|
|
/* f095b48: afa50034 */ sw $a1,0x34($sp)
|
|
/* f095b4c: 0fc53380 */ jal optionsGetControlMode
|
|
/* f095b50: 8dc40070 */ lw $a0,0x70($t6)
|
|
/* f095b54: 3c08800a */ lui $t0,%hi(g_Vars)
|
|
/* f095b58: 28410004 */ slti $at,$v0,0x4
|
|
/* f095b5c: 1420007c */ bnez $at,.NB0f095d50
|
|
/* f095b60: 2508e6c0 */ addiu $t0,$t0,%lo(g_Vars)
|
|
/* f095b64: 0fc44336 */ jal pakGetType
|
|
/* f095b68: 8104028f */ lb $a0,0x28f($t0)
|
|
/* f095b6c: 3c08800a */ lui $t0,%hi(g_Vars)
|
|
/* f095b70: 2508e6c0 */ addiu $t0,$t0,%lo(g_Vars)
|
|
/* f095b74: 8d0f006c */ lw $t7,0x6c($t0)
|
|
/* f095b78: 24050001 */ addiu $a1,$zero,0x1
|
|
/* f095b7c: 00453026 */ xor $a2,$v0,$a1
|
|
/* f095b80: 11e00003 */ beqz $t7,.NB0f095b90
|
|
/* f095b84: 2cc60001 */ sltiu $a2,$a2,0x1
|
|
/* f095b88: 10000002 */ beqz $zero,.NB0f095b94
|
|
/* f095b8c: 00a05025 */ or $t2,$a1,$zero
|
|
.NB0f095b90:
|
|
/* f095b90: 00005025 */ or $t2,$zero,$zero
|
|
.NB0f095b94:
|
|
/* f095b94: 8d180068 */ lw $t8,0x68($t0)
|
|
/* f095b98: 00004825 */ or $t1,$zero,$zero
|
|
/* f095b9c: 00001825 */ or $v1,$zero,$zero
|
|
/* f095ba0: 13000003 */ beqz $t8,.NB0f095bb0
|
|
/* f095ba4: 00001025 */ or $v0,$zero,$zero
|
|
/* f095ba8: 10000001 */ beqz $zero,.NB0f095bb0
|
|
/* f095bac: 00a04825 */ or $t1,$a1,$zero
|
|
.NB0f095bb0:
|
|
/* f095bb0: 8d190064 */ lw $t9,0x64($t0)
|
|
/* f095bb4: 13200003 */ beqz $t9,.NB0f095bc4
|
|
/* f095bb8: 00000000 */ sll $zero,$zero,0x0
|
|
/* f095bbc: 10000001 */ beqz $zero,.NB0f095bc4
|
|
/* f095bc0: 00a01825 */ or $v1,$a1,$zero
|
|
.NB0f095bc4:
|
|
/* f095bc4: 8d0c0070 */ lw $t4,0x70($t0)
|
|
/* f095bc8: 11800003 */ beqz $t4,.NB0f095bd8
|
|
/* f095bcc: 00000000 */ sll $zero,$zero,0x0
|
|
/* f095bd0: 10000001 */ beqz $zero,.NB0f095bd8
|
|
/* f095bd4: 00a01025 */ or $v0,$a1,$zero
|
|
.NB0f095bd8:
|
|
/* f095bd8: 8d18028c */ lw $t8,0x28c($t0)
|
|
/* f095bdc: 00436821 */ addu $t5,$v0,$v1
|
|
/* f095be0: 01a97021 */ addu $t6,$t5,$t1
|
|
/* f095be4: 01ca7821 */ addu $t7,$t6,$t2
|
|
/* f095be8: 01f82021 */ addu $a0,$t7,$t8
|
|
/* f095bec: 0004ce00 */ sll $t9,$a0,0x18
|
|
/* f095bf0: 00192603 */ sra $a0,$t9,0x18
|
|
/* f095bf4: 0fc44336 */ jal pakGetType
|
|
/* f095bf8: afa6001c */ sw $a2,0x1c($sp)
|
|
/* f095bfc: 8fa6001c */ lw $a2,0x1c($sp)
|
|
/* f095c00: 3c08800a */ lui $t0,%hi(g_Vars)
|
|
/* f095c04: 2508e6c0 */ addiu $t0,$t0,%lo(g_Vars)
|
|
/* f095c08: 10c0002a */ beqz $a2,.NB0f095cb4
|
|
/* f095c0c: 24050001 */ addiu $a1,$zero,0x1
|
|
/* f095c10: 14450028 */ bne $v0,$a1,.NB0f095cb4
|
|
/* f095c14: 8fae0030 */ lw $t6,0x30($sp)
|
|
/* f095c18: 15c5001c */ bne $t6,$a1,.NB0f095c8c
|
|
/* f095c1c: 8d0b028c */ lw $t3,0x28c($t0)
|
|
/* f095c20: 8d0f0070 */ lw $t7,0x70($t0)
|
|
/* f095c24: 00005025 */ or $t2,$zero,$zero
|
|
/* f095c28: 00004825 */ or $t1,$zero,$zero
|
|
/* f095c2c: 11e00003 */ beqz $t7,.NB0f095c3c
|
|
/* f095c30: 00001825 */ or $v1,$zero,$zero
|
|
/* f095c34: 10000001 */ beqz $zero,.NB0f095c3c
|
|
/* f095c38: 240a0001 */ addiu $t2,$zero,0x1
|
|
.NB0f095c3c:
|
|
/* f095c3c: 8d18006c */ lw $t8,0x6c($t0)
|
|
/* f095c40: 00001025 */ or $v0,$zero,$zero
|
|
/* f095c44: 13000003 */ beqz $t8,.NB0f095c54
|
|
/* f095c48: 00000000 */ sll $zero,$zero,0x0
|
|
/* f095c4c: 10000001 */ beqz $zero,.NB0f095c54
|
|
/* f095c50: 24090001 */ addiu $t1,$zero,0x1
|
|
.NB0f095c54:
|
|
/* f095c54: 8d190068 */ lw $t9,0x68($t0)
|
|
/* f095c58: 13200003 */ beqz $t9,.NB0f095c68
|
|
/* f095c5c: 00000000 */ sll $zero,$zero,0x0
|
|
/* f095c60: 10000001 */ beqz $zero,.NB0f095c68
|
|
/* f095c64: 24030001 */ addiu $v1,$zero,0x1
|
|
.NB0f095c68:
|
|
/* f095c68: 8d0c0064 */ lw $t4,0x64($t0)
|
|
/* f095c6c: 11800003 */ beqz $t4,.NB0f095c7c
|
|
/* f095c70: 00000000 */ sll $zero,$zero,0x0
|
|
/* f095c74: 10000001 */ beqz $zero,.NB0f095c7c
|
|
/* f095c78: 24020001 */ addiu $v0,$zero,0x1
|
|
.NB0f095c7c:
|
|
/* f095c7c: 01626821 */ addu $t5,$t3,$v0
|
|
/* f095c80: 01a37021 */ addu $t6,$t5,$v1
|
|
/* f095c84: 01c97821 */ addu $t7,$t6,$t1
|
|
/* f095c88: 01ea5821 */ addu $t3,$t7,$t2
|
|
.NB0f095c8c:
|
|
/* f095c8c: 000b2600 */ sll $a0,$t3,0x18
|
|
/* f095c90: 0004c603 */ sra $t8,$a0,0x18
|
|
/* f095c94: 3c053e4c */ lui $a1,0x3e4c
|
|
/* f095c98: 34a5cccd */ ori $a1,$a1,0xcccd
|
|
/* f095c9c: 03002025 */ or $a0,$t8,$zero
|
|
/* f095ca0: 24060002 */ addiu $a2,$zero,0x2
|
|
/* f095ca4: 0fc45e2f */ jal pakRumble
|
|
/* f095ca8: 24070004 */ addiu $a3,$zero,0x4
|
|
/* f095cac: 1000002f */ beqz $zero,.NB0f095d6c
|
|
/* f095cb0: 8fbf0014 */ lw $ra,0x14($sp)
|
|
.NB0f095cb4:
|
|
/* f095cb4: 1445001c */ bne $v0,$a1,.NB0f095d28
|
|
/* f095cb8: 8d0b028c */ lw $t3,0x28c($t0)
|
|
/* f095cbc: 8d0c0070 */ lw $t4,0x70($t0)
|
|
/* f095cc0: 00005025 */ or $t2,$zero,$zero
|
|
/* f095cc4: 00004825 */ or $t1,$zero,$zero
|
|
/* f095cc8: 11800003 */ beqz $t4,.NB0f095cd8
|
|
/* f095ccc: 00001825 */ or $v1,$zero,$zero
|
|
/* f095cd0: 10000001 */ beqz $zero,.NB0f095cd8
|
|
/* f095cd4: 240a0001 */ addiu $t2,$zero,0x1
|
|
.NB0f095cd8:
|
|
/* f095cd8: 8d0d006c */ lw $t5,0x6c($t0)
|
|
/* f095cdc: 00001025 */ or $v0,$zero,$zero
|
|
/* f095ce0: 11a00003 */ beqz $t5,.NB0f095cf0
|
|
/* f095ce4: 00000000 */ sll $zero,$zero,0x0
|
|
/* f095ce8: 10000001 */ beqz $zero,.NB0f095cf0
|
|
/* f095cec: 24090001 */ addiu $t1,$zero,0x1
|
|
.NB0f095cf0:
|
|
/* f095cf0: 8d0e0068 */ lw $t6,0x68($t0)
|
|
/* f095cf4: 11c00003 */ beqz $t6,.NB0f095d04
|
|
/* f095cf8: 00000000 */ sll $zero,$zero,0x0
|
|
/* f095cfc: 10000001 */ beqz $zero,.NB0f095d04
|
|
/* f095d00: 24030001 */ addiu $v1,$zero,0x1
|
|
.NB0f095d04:
|
|
/* f095d04: 8d0f0064 */ lw $t7,0x64($t0)
|
|
/* f095d08: 11e00003 */ beqz $t7,.NB0f095d18
|
|
/* f095d0c: 00000000 */ sll $zero,$zero,0x0
|
|
/* f095d10: 10000001 */ beqz $zero,.NB0f095d18
|
|
/* f095d14: 24020001 */ addiu $v0,$zero,0x1
|
|
.NB0f095d18:
|
|
/* f095d18: 0162c021 */ addu $t8,$t3,$v0
|
|
/* f095d1c: 0303c821 */ addu $t9,$t8,$v1
|
|
/* f095d20: 03296021 */ addu $t4,$t9,$t1
|
|
/* f095d24: 018a5821 */ addu $t3,$t4,$t2
|
|
.NB0f095d28:
|
|
/* f095d28: 000b2600 */ sll $a0,$t3,0x18
|
|
/* f095d2c: 00046e03 */ sra $t5,$a0,0x18
|
|
/* f095d30: 3c053e4c */ lui $a1,0x3e4c
|
|
/* f095d34: 34a5cccd */ ori $a1,$a1,0xcccd
|
|
/* f095d38: 01a02025 */ or $a0,$t5,$zero
|
|
/* f095d3c: 24060002 */ addiu $a2,$zero,0x2
|
|
/* f095d40: 0fc45e2f */ jal pakRumble
|
|
/* f095d44: 24070004 */ addiu $a3,$zero,0x4
|
|
/* f095d48: 10000008 */ beqz $zero,.NB0f095d6c
|
|
/* f095d4c: 8fbf0014 */ lw $ra,0x14($sp)
|
|
.NB0f095d50:
|
|
/* f095d50: 3c053e4c */ lui $a1,0x3e4c
|
|
/* f095d54: 34a5cccd */ ori $a1,$a1,0xcccd
|
|
/* f095d58: 8104028f */ lb $a0,0x28f($t0)
|
|
/* f095d5c: 24060002 */ addiu $a2,$zero,0x2
|
|
/* f095d60: 0fc45e2f */ jal pakRumble
|
|
/* f095d64: 24070004 */ addiu $a3,$zero,0x4
|
|
/* f095d68: 8fbf0014 */ lw $ra,0x14($sp)
|
|
.NB0f095d6c:
|
|
/* f095d6c: 27bd0030 */ addiu $sp,$sp,0x30
|
|
/* f095d70: 03e00008 */ jr $ra
|
|
/* f095d74: 00000000 */ sll $zero,$zero,0x0
|
|
);
|
|
#endif
|
|
|
|
s32 bgunGetUnequippedReloadIndex(s32 weaponnum)
|
|
{
|
|
if (weaponnum == WEAPON_CROSSBOW) {
|
|
return 0;
|
|
}
|
|
|
|
if (weaponnum == WEAPON_SHOTGUN) {
|
|
return 1;
|
|
}
|
|
|
|
if (weaponnum == WEAPON_DY357MAGNUM) {
|
|
return 2;
|
|
}
|
|
|
|
if (weaponnum == WEAPON_DY357LX) {
|
|
return 3;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* The magnums, shotgun and crossbow are special because that the game remembers
|
|
* how much ammo is loaded in their clips when the weapon is not being used.
|
|
* Their clips are gradually reloaded while the weapon is not in use, and that
|
|
* gradual reloading is handled by this function.
|
|
*
|
|
* The gunroundsspent value is actually a countdown timer,
|
|
* not the number of rounds as the name suggests.
|
|
*/
|
|
void bgunTickUnequippedReload(void)
|
|
{
|
|
s32 i;
|
|
s32 j;
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
for (j = 0; j < 4; j++) {
|
|
u16 spent = g_Vars.currentplayer->hands[i].gunroundsspent[j];
|
|
|
|
if (spent > g_Vars.lvupdate60) {
|
|
spent -= g_Vars.lvupdate60;
|
|
} else {
|
|
spent = 0;
|
|
}
|
|
|
|
g_Vars.currentplayer->hands[i].gunroundsspent[j] = spent;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool bgunTestGunVisCommand(struct gunviscmd *cmd, struct hand *hand)
|
|
{
|
|
bool result = true;
|
|
|
|
switch (cmd->type) {
|
|
case GUNVISCMD_CHECKUPGRADE:
|
|
if (((hand->gset.unk0639 >> cmd->param) & 1) == 0) {
|
|
result = false;
|
|
}
|
|
break;
|
|
case GUNVISCMD_CHECKINLEFTHAND:
|
|
if (hand != &g_Vars.currentplayer->hands[HAND_LEFT]) {
|
|
result = false;
|
|
}
|
|
break;
|
|
case GUNVISCMD_CHECKINRIGHTHAND:
|
|
if (hand != &g_Vars.currentplayer->hands[HAND_RIGHT]) {
|
|
result = false;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void bgunSetPartVisible(s16 partnum, bool visible, struct hand *hand, struct modeldef *modeldef)
|
|
{
|
|
struct modelnode *node;
|
|
|
|
if (partnum == MODELPART_HAND_LEFT || partnum == MODELPART_HAND_RIGHT) {
|
|
if (g_Vars.currentplayer->gunctrl.handmodeldef) {
|
|
node = modelGetPart(g_Vars.currentplayer->gunctrl.handmodeldef, partnum);
|
|
|
|
if (node) {
|
|
struct modelrodata_toggle *rodata = &node->rodata->toggle;
|
|
u32 *ptr = &hand->handsavedata[rodata->rwdataindex];
|
|
*ptr = visible;
|
|
}
|
|
}
|
|
} else {
|
|
node = modelGetPart(modeldef, partnum);
|
|
|
|
if (node) {
|
|
struct modelrodata_toggle *rodata = &node->rodata->toggle;
|
|
u32 *ptr = &hand->unk0a6c[rodata->rwdataindex];
|
|
*ptr = visible;
|
|
}
|
|
}
|
|
}
|
|
|
|
void bgunExecuteGunVisCommands(struct hand *hand, struct modeldef *modeldef, struct gunviscmd *commands)
|
|
{
|
|
struct gunviscmd *cmd = commands;
|
|
bool done = false;
|
|
|
|
if (cmd == NULL) {
|
|
return;
|
|
}
|
|
|
|
while (!done) {
|
|
if (bgunTestGunVisCommand(cmd, hand)) {
|
|
if (cmd->op == GUNVISOP_IFTRUE_SETVISIBLE) {
|
|
bgunSetPartVisible(cmd->partnum, true, hand, modeldef);
|
|
}
|
|
|
|
if (cmd->op == GUNVISOP_IFTRUE_SETHIDDEN) {
|
|
bgunSetPartVisible(cmd->partnum, false, hand, modeldef);
|
|
}
|
|
|
|
if (cmd->op == GUNVISOP_SETVISIBILITY) {
|
|
bgunSetPartVisible(cmd->partnum, true, hand, modeldef);
|
|
}
|
|
} else {
|
|
if (cmd->op == GUNVISOP_SETVISIBILITY) {
|
|
bgunSetPartVisible(cmd->partnum, false, hand, modeldef);
|
|
}
|
|
}
|
|
|
|
cmd++;
|
|
|
|
if (cmd->type == GUNVISCMD_END) {
|
|
done = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
void bgun0f098030(struct hand *hand, struct modeldef *modeldef)
|
|
{
|
|
struct weapon *weapon = weaponFindById(hand->gset.weaponnum);
|
|
s32 i;
|
|
s32 j;
|
|
|
|
bgunExecuteGunVisCommands(hand, modeldef, weapon->gunviscmds);
|
|
bgunSetPartVisible(MODELPART_0042, false, hand, modeldef);
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
if (weapon->ammos[i] && (weapon->ammos[i]->flags & AMMOFLAG_QTYAFFECTSPARTVIS)) {
|
|
for (j = 0; j < hand->clipsizes[i]; j++) {
|
|
if (j >= hand->loadedammo[i]) {
|
|
bgunSetPartVisible(j + 100, false, hand, modeldef);
|
|
} else {
|
|
bgunSetPartVisible(j + 100, true, hand, modeldef);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
f32 bgun0f09815c(struct hand *hand)
|
|
{
|
|
if (hand->animmode == HANDANIMMODE_BUSY && hand->unk0ce8 != NULL) {
|
|
if (hand->unk0ce8->unk04 < 0) {
|
|
return modelGetNumAnimFrames(&hand->gunmodel) - modelGetCurAnimFrame(&hand->gunmodel);
|
|
}
|
|
|
|
return modelGetCurAnimFrame(&hand->gunmodel);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void bgun0f0981e8(struct hand *hand, struct modeldef *modeldef)
|
|
{
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
f32 s4;
|
|
f32 s2;
|
|
#else
|
|
s32 s2;
|
|
s32 s4;
|
|
#endif
|
|
struct guncmd *cmd;
|
|
f32 animspeed;
|
|
bool done;
|
|
f32 animspeedmult;
|
|
s32 partnums[15];
|
|
bool partsvisible[15];
|
|
s32 partframes[15];
|
|
s32 s0;
|
|
s32 index;
|
|
|
|
hand->unk0cc8_04 = false;
|
|
|
|
if (hand->animmode == HANDANIMMODE_BUSY && bgun0f09815c(hand) >= modelGetNumAnimFrames(&hand->gunmodel) - 1) {
|
|
hand->animmode = HANDANIMMODE_IDLE;
|
|
}
|
|
|
|
// This condition looks like a bug (using | instead of ||), but it happens
|
|
// to make no difference anyway. Brackets added for clarity.
|
|
if ((hand->animmode == (u32)HANDANIMMODE_BUSY) | (hand->animload >= 0)) {
|
|
if (hand->gangstarot > 0.0f) {
|
|
hand->animframeinc = 0;
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
hand->animframeincfreal = 0.0f;
|
|
#endif
|
|
}
|
|
|
|
if (hand->animload >= 0) {
|
|
animspeedmult = 1.0f;
|
|
animspeed = hand->unk0ce8->unk04 / 10000.0f;
|
|
|
|
if (hand->unk0d0e_07 && g_Vars.currentplayer->hands[HAND_LEFT].inuse) {
|
|
animspeedmult = RANDOMFRAC() * 0.77f + 0.7f;
|
|
}
|
|
|
|
if (hand->unk0ce8 && animspeed < 0.0f) {
|
|
modelSetAnimation(&hand->gunmodel, hand->animload, false, 0.0f, animspeedmult * animspeed, 0.0f);
|
|
modelSetAnimFrame(&hand->gunmodel, modelGetNumAnimFrames(&hand->gunmodel));
|
|
} else {
|
|
modelSetAnimation(&hand->gunmodel, hand->animload, false, 0.0f, animspeedmult * animspeed, 0.0f);
|
|
}
|
|
|
|
hand->animload = -1;
|
|
hand->animmode = HANDANIMMODE_BUSY;
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
hand->animframeincfreal = modelGetAbsAnimSpeed(&hand->gunmodel) * PALUPF(hand->animframeinc);
|
|
#endif
|
|
}
|
|
|
|
if (hand->unk0cc8_02) {
|
|
hand->animframeinc = 0;
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
hand->animframeincfreal = 0.0f;
|
|
#endif
|
|
}
|
|
|
|
s4 = bgun0f09815c(hand);
|
|
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
s2 = hand->animframeincfreal + s4;
|
|
#else
|
|
s2 = hand->animframeinc + s4;
|
|
#endif
|
|
|
|
if (s4 == 0 && s2 > 0) {
|
|
s4--;
|
|
}
|
|
|
|
if (hand->unk0ce8) {
|
|
done = false;
|
|
cmd = hand->unk0ce8;
|
|
|
|
if (cmd) {
|
|
s0 = 0;
|
|
|
|
do {
|
|
if (cmd->type == GUNCMD_END) {
|
|
done = true;
|
|
} else if (cmd->type == GUNCMD_SHOWPART || cmd->type == GUNCMD_HIDEPART) {
|
|
if (s2 >= cmd->unk02) {
|
|
s32 i;
|
|
index = -1;
|
|
|
|
for (i = 0; i < s0; i++) {
|
|
if (cmd->unk04 == partnums[i]) {
|
|
index = i;
|
|
}
|
|
}
|
|
|
|
if (index == -1) {
|
|
index = s0;
|
|
s0++;
|
|
|
|
if (1);
|
|
|
|
partnums[index] = cmd->unk04;
|
|
partframes[index] = -1;
|
|
}
|
|
|
|
if (cmd->unk02 > partframes[index]) {
|
|
partframes[index] = cmd->unk02;
|
|
partsvisible[index] = cmd->type == GUNCMD_SHOWPART ? true : false;
|
|
}
|
|
}
|
|
} else {
|
|
switch (cmd->type) {
|
|
case GUNCMD_WAITFORZRELEASED:
|
|
if (hand->unk0cc8_01) {
|
|
if (s2 >= cmd->unk02 && s4 < cmd->unk02 && s4 < s2) {
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
f32 tmp = cmd->unk02 - bgun0f09815c(hand);
|
|
tmp /= 2;
|
|
|
|
if (hand->animframeincfreal > tmp) {
|
|
#if PAL
|
|
hand->animframeinc = tmp * 0.83333333f / modelGetAbsAnimSpeed(&hand->gunmodel);
|
|
#else
|
|
hand->animframeinc = tmp / modelGetAbsAnimSpeed(&hand->gunmodel);
|
|
#endif
|
|
hand->animframeincfreal = modelGetAbsAnimSpeed(&hand->gunmodel) * PALUPF(hand->animframeinc);
|
|
}
|
|
|
|
s2 = hand->animframeincfreal + s4;
|
|
#else
|
|
s32 tmp = cmd->unk02 - (s32) bgun0f09815c(hand);
|
|
tmp /= 2;
|
|
|
|
if (hand->animframeinc > tmp) {
|
|
hand->animframeinc = tmp;
|
|
}
|
|
|
|
s2 = hand->animframeinc + s4;
|
|
#endif
|
|
}
|
|
}
|
|
break;
|
|
case GUNCMD_REPEATUNTILFULL:
|
|
if (hand->unk0cc8_03 && s2 >= cmd->unk02 && s4 < cmd->unk02 && s4 < s2) {
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
f32 sp78 = s2;
|
|
|
|
while (sp78 >= cmd->unk02) {
|
|
sp78 += cmd->unk04 - cmd->unk02;
|
|
}
|
|
|
|
s4 = sp78;
|
|
hand->animframeinc = 0;
|
|
hand->animframeincfreal = 0;
|
|
#else
|
|
s32 sp78 = cmd->unk04 + (((s32)s2 - cmd->unk02) % ((cmd->unk02 - cmd->unk04) + 1));
|
|
s4 = sp78;
|
|
hand->animframeinc = 0;
|
|
#endif
|
|
|
|
modelSetAnimFrame(&hand->gunmodel, sp78);
|
|
hand->animloopcount++;
|
|
s2 = sp78;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
cmd++;
|
|
} while (!done);
|
|
|
|
if (s0 > 0) {
|
|
s32 i;
|
|
|
|
for (i = 0; i < s0; i++) {
|
|
bgunSetPartVisible(partnums[i], partsvisible[i], hand, modeldef);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
modelSetAnimPlaySpeed(&hand->gunmodel, PALUPF(4.0f), 0);
|
|
modelTickAnimQuarterSpeed(&hand->gunmodel, hand->animframeinc, true);
|
|
#else
|
|
modelTickAnim(&hand->gunmodel, hand->animframeinc, true);
|
|
#endif
|
|
|
|
s2 = bgun0f09815c(hand);
|
|
|
|
if (hand->unk0ce8) {
|
|
bool done = false;
|
|
struct guncmd *cmd = hand->unk0ce8;
|
|
f32 speed = 1.0f;
|
|
bool hasspeed = false;
|
|
#if VERSION < VERSION_NTSC_1_0
|
|
struct sndstate *audiohandle;
|
|
#endif
|
|
|
|
if (cmd) {
|
|
do {
|
|
if (cmd->type == GUNCMD_END) {
|
|
done = true;
|
|
} else {
|
|
if (s2 >= cmd->unk02 && s4 < cmd->unk02 && s4 < s2) {
|
|
switch (cmd->type) {
|
|
case GUNCMD_PLAYSOUND:
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
if (hasspeed) {
|
|
snd00010718(0, 0, 0x7fff, 0x40, cmd->unk04, speed, 1, -1, 1);
|
|
hasspeed = false;
|
|
} else {
|
|
snd00010718(0, 0, 0x7fff, 0x40, cmd->unk04, 1.0f, 1, -1, 1);
|
|
}
|
|
#else
|
|
audiohandle = sndStart(var80095200, cmd->unk04, NULL, -1, -1, -1, -1, -1);
|
|
|
|
if (hasspeed && audiohandle) {
|
|
hasspeed = false;
|
|
audioPostEvent(audiohandle, 16, *(s32 *)&speed);
|
|
}
|
|
#endif
|
|
break;
|
|
case GUNCMD_SETSOUNDSPEED:
|
|
speed = cmd->unk04 / 1000.0f;
|
|
hasspeed = true;
|
|
break;
|
|
case GUNCMD_POPOUTSACKOFPILLS:
|
|
hand->unk0cc8_04++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
cmd++;
|
|
} while (!done);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool bgun0f098884(struct guncmd *cmd, struct gset *gset)
|
|
{
|
|
s32 result = false;
|
|
|
|
if (cmd->unk01 == 0) {
|
|
return true;
|
|
}
|
|
|
|
if (cmd->unk01 == 1 && g_Vars.currentplayer->hands[HAND_LEFT].inuse == true) {
|
|
result = true;
|
|
}
|
|
|
|
if (cmd->unk01 == 2 && gset->weaponfunc == FUNC_SECONDARY) {
|
|
result = true;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void bgunStartAnimation(struct guncmd *cmd, s32 handnum, struct hand *hand)
|
|
{
|
|
if (cmd->type != GUNCMD_PLAYANIMATION) {
|
|
struct guncmd *loopcmd = cmd;
|
|
s32 done = false;
|
|
u32 rand = random() % 100;
|
|
|
|
while (loopcmd->type != GUNCMD_END) {
|
|
if (bgun0f098884(loopcmd, &hand->gset) && !done) {
|
|
if (loopcmd->type == GUNCMD_INCLUDE) {
|
|
done = true;
|
|
bgunStartAnimation((struct guncmd *)loopcmd->unk04, handnum, hand);
|
|
} else if (loopcmd->type == GUNCMD_RANDOM) {
|
|
if ((struct guncmd *)loopcmd->unk04 != hand->unk0d80 && loopcmd->unk02 > rand) {
|
|
done = true;
|
|
bgunStartAnimation((struct guncmd *)loopcmd->unk04, handnum, hand);
|
|
}
|
|
}
|
|
}
|
|
|
|
loopcmd++;
|
|
}
|
|
} else {
|
|
hand->animload = cmd->unk02;
|
|
hand->animmode = HANDANIMMODE_IDLE;
|
|
hand->unk0cc8_01 = 0;
|
|
hand->unk0cc8_03 = false;
|
|
hand->unk0ce8 = cmd;
|
|
hand->animloopcount = 0;
|
|
hand->unk0cc8_02 = 0;
|
|
hand->unk0d0e_07 = false;
|
|
hand->unk0d80 = cmd;
|
|
}
|
|
}
|
|
|
|
bool bgun0f098a44(struct hand *hand, s32 time)
|
|
{
|
|
struct guncmd *cmd = hand->unk0ce8;
|
|
s32 waittimekeyframe = -1;
|
|
s32 zreleasekeyframe = -1;
|
|
|
|
if (hand->animmode == HANDANIMMODE_IDLE) {
|
|
return (hand->animload == -1);
|
|
}
|
|
|
|
while (cmd->type != GUNCMD_END && waittimekeyframe == -1) {
|
|
if (cmd->type == GUNCMD_WAITFORZRELEASED) {
|
|
zreleasekeyframe = cmd->unk02;
|
|
}
|
|
|
|
if (cmd->type == GUNCMD_WAITTIME && time == cmd->unk04) {
|
|
waittimekeyframe = cmd->unk02;
|
|
}
|
|
|
|
cmd++;
|
|
}
|
|
|
|
if (waittimekeyframe >= 0) {
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
if (hand->unk0cc8_01 && bgun0f09815c(hand) <= zreleasekeyframe) {
|
|
return false;
|
|
}
|
|
|
|
return (bgun0f09815c(hand) + hand->animframeincfreal >= waittimekeyframe);
|
|
#else
|
|
if (hand->unk0cc8_01 && (s32)bgun0f09815c(hand) <= zreleasekeyframe) {
|
|
return false;
|
|
}
|
|
|
|
return (bgun0f09815c(hand) + hand->animframeinc >= waittimekeyframe);
|
|
#endif
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
s32 bgun0f098b80(struct hand *hand, s32 arg1)
|
|
{
|
|
struct guncmd *cmd = hand->unk0ce8;
|
|
s32 keyframe = -1;
|
|
|
|
if (hand->animmode == HANDANIMMODE_IDLE) {
|
|
return 0;
|
|
}
|
|
|
|
while (cmd->type != GUNCMD_END && keyframe == -1) {
|
|
if (cmd->type == GUNCMD_WAITTIME) {
|
|
if (cmd->unk04 == arg1) {
|
|
keyframe = cmd->unk02;
|
|
}
|
|
}
|
|
|
|
cmd++;
|
|
}
|
|
|
|
if (keyframe == -1) {
|
|
keyframe = 0;
|
|
}
|
|
|
|
return keyframe;
|
|
}
|
|
|
|
bool bgunIsAnimBusy(struct hand *hand)
|
|
{
|
|
return hand->animmode != HANDANIMMODE_IDLE;
|
|
}
|
|
|
|
void bgunResetAnim(struct hand *hand)
|
|
{
|
|
hand->animload = -1;
|
|
hand->animmode = HANDANIMMODE_IDLE;
|
|
hand->unk0cc8_01 = false;
|
|
hand->unk0cc8_03 = false;
|
|
hand->unk0ce8 = NULL;
|
|
hand->animloopcount = 0;
|
|
hand->unk0cc8_02 = false;
|
|
hand->unk0d0e_07 = false;
|
|
}
|
|
|
|
void bgunGetWeaponInfo(struct handweaponinfo *info, s32 handnum)
|
|
{
|
|
s32 weaponnum = bgunGetWeaponNum2(handnum);
|
|
|
|
info->weaponnum = weaponnum;
|
|
info->definition = g_Weapons[weaponnum];
|
|
info->gunctrl = &g_Vars.currentplayer->gunctrl;
|
|
}
|
|
|
|
/**
|
|
* Return values:
|
|
* -1 = gun function doesn't exist or ammo fully depleted
|
|
* 0 = trigger reload
|
|
* 1 = has ammo in clip and ammo in reserve
|
|
* 2 = has ammo in clip but none in reserve
|
|
* 3 = gun doesn't use ammo or clip is full
|
|
*/
|
|
s32 bgun0f098ca0(s32 funcnum, struct handweaponinfo *info, struct hand *hand)
|
|
{
|
|
s32 result = 3;
|
|
struct weaponfunc *func = weaponGetFunction(&hand->gset, funcnum);
|
|
|
|
if (!func) {
|
|
return -1;
|
|
}
|
|
|
|
if (func->ammoindex != -1) {
|
|
s32 ammoindex = func->ammoindex;
|
|
|
|
if (info->gunctrl->ammotypes[ammoindex] >= 0
|
|
&& hand->loadedammo[ammoindex] < hand->clipsizes[ammoindex]) {
|
|
s32 minqty = 1;
|
|
|
|
if (info->weaponnum == WEAPON_SHOTGUN && funcnum == FUNC_SECONDARY) {
|
|
minqty = 2;
|
|
}
|
|
|
|
if (info->weaponnum == WEAPON_TRANQUILIZER && funcnum == FUNC_SECONDARY) {
|
|
minqty = bgunGetMinClipQty(WEAPON_TRANQUILIZER, FUNC_SECONDARY);
|
|
}
|
|
|
|
result = 1;
|
|
|
|
if (hand->loadedammo[ammoindex] < minqty) {
|
|
result = 0;
|
|
|
|
if (g_Vars.currentplayer->ammoheldarr[info->gunctrl->ammotypes[ammoindex]] == 0) {
|
|
result = -1;
|
|
}
|
|
} else {
|
|
if (g_Vars.currentplayer->ammoheldarr[info->gunctrl->ammotypes[ammoindex]] == 0) {
|
|
result = 2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void bgun0f098df8(s32 weaponfunc, struct handweaponinfo *info, struct hand *hand, u8 onebullet, u8 checkunequipped)
|
|
{
|
|
struct weaponfunc *func = weaponGetFunction(&hand->gset, weaponfunc);
|
|
|
|
if (func && func->ammoindex != -1) {
|
|
s32 ammoindex = func->ammoindex;
|
|
|
|
if (info->gunctrl->ammotypes[ammoindex] >= 0) {
|
|
s32 amount = hand->clipsizes[ammoindex] - hand->loadedammo[ammoindex];
|
|
|
|
s32 reloadindex = bgunGetUnequippedReloadIndex(info->weaponnum);
|
|
|
|
if (g_FrIsValidWeapon) {
|
|
reloadindex = -1;
|
|
}
|
|
|
|
if (checkunequipped && reloadindex >= 0) {
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
amount -= hand->gunroundsspent[reloadindex] / TICKS(256);
|
|
#else
|
|
amount -= hand->gunroundsspent[reloadindex] >> 8;
|
|
#endif
|
|
}
|
|
|
|
if (onebullet) {
|
|
amount = 1;
|
|
}
|
|
|
|
if (amount > g_Vars.currentplayer->ammoheldarr[info->gunctrl->ammotypes[ammoindex]]) {
|
|
amount = g_Vars.currentplayer->ammoheldarr[info->gunctrl->ammotypes[ammoindex]];
|
|
}
|
|
|
|
#if VERSION >= VERSION_JPN_FINAL
|
|
// In most versions of the game, reloading the shotgun while going
|
|
// through a teleport in Deep Sea will cause the shotgun to load
|
|
// more ammo than its capacity. JPN Final fixes this here.
|
|
if (amount > hand->clipsizes[ammoindex] - hand->loadedammo[ammoindex]) {
|
|
amount = hand->clipsizes[ammoindex] - hand->loadedammo[ammoindex];
|
|
}
|
|
#endif
|
|
|
|
hand->loadedammo[ammoindex] += amount;
|
|
g_Vars.currentplayer->ammoheldarr[info->gunctrl->ammotypes[ammoindex]] -= amount;
|
|
|
|
if (info->definition->ammos[ammoindex]->flags & AMMOFLAG_NORESERVE) {
|
|
g_Vars.currentplayer->ammoheldarr[info->gunctrl->ammotypes[ammoindex]] = 0;
|
|
}
|
|
|
|
if (func);
|
|
}
|
|
}
|
|
}
|
|
|
|
void bgun0f098f8c(struct handweaponinfo *info, struct hand *hand)
|
|
{
|
|
s32 i;
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
if (weaponGetFunction(&hand->gset, i)) {
|
|
bgun0f098df8(i, info, hand, 0, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool bgun0f099008(s32 handnum)
|
|
{
|
|
struct handweaponinfo info;
|
|
|
|
bgunGetWeaponInfo(&info, handnum);
|
|
|
|
if (bgun0f098ca0(0, &info, &g_Vars.currentplayer->hands[handnum]) > 0) {
|
|
return true;
|
|
}
|
|
|
|
if (bgun0f098ca0(1, &info, &g_Vars.currentplayer->hands[handnum]) > 0) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool bgun0f0990b0(struct weaponfunc *basefunc, struct weapon *weapon)
|
|
{
|
|
if (!basefunc) {
|
|
return true;
|
|
}
|
|
|
|
if (basefunc->type == INVENTORYFUNCTYPE_NONE) {
|
|
return true;
|
|
}
|
|
|
|
if ((basefunc->type & 0xff) == INVENTORYFUNCTYPE_MELEE) {
|
|
return true;
|
|
}
|
|
|
|
if ((basefunc->type & 0xff) == INVENTORYFUNCTYPE_SPECIAL) {
|
|
struct weaponfunc_special *func = (struct weaponfunc_special *)basefunc;
|
|
|
|
if (func->specialfunc != HANDATTACKTYPE_DETONATE
|
|
&& func->specialfunc != HANDATTACKTYPE_BOOST
|
|
&& func->specialfunc != HANDATTACKTYPE_REVERTBOOST) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if ((basefunc->type & 0xff) == INVENTORYFUNCTYPE_THROW) {
|
|
if (basefunc->ammoindex <= -1) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (basefunc->ammoindex >= 0
|
|
&& weapon->ammos[basefunc->ammoindex]
|
|
&& bgunGetAmmoCount(weapon->ammos[basefunc->ammoindex]->type) <= 0) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool bgun0f099188(struct hand *hand, s32 gunfunc)
|
|
{
|
|
struct weaponfunc *func = weaponGetFunction(&hand->gset, gunfunc);
|
|
struct weapon *weapon = weaponFindById(hand->gset.weaponnum);
|
|
|
|
if (bgunIsUsingSecondaryFunction() == gunfunc) {
|
|
return false;
|
|
}
|
|
|
|
return bgun0f0990b0(func, weapon);
|
|
}
|
|
|
|
s32 bgunTickIncIdle(struct handweaponinfo *info, s32 handnum, struct hand *hand, s32 lvupdate)
|
|
{
|
|
bool usesec;
|
|
s32 gunfunc = bgunIsUsingSecondaryFunction();
|
|
s32 sp34;
|
|
s32 sp30;
|
|
bool changefunc;
|
|
s32 next;
|
|
struct hand *lhand;
|
|
struct weaponfunc *func;
|
|
|
|
hand->lastdirvalid = false;
|
|
hand->burstbullets = 0;
|
|
#if VERSION < VERSION_PAL_BETA
|
|
hand->animframeincfreal = hand->animframeinc;
|
|
#endif
|
|
hand->shotremainder = 0;
|
|
|
|
// If ready to change gun due to manual switch, just do that
|
|
if (bgunIsReadyToSwitch(handnum) && bgunSetState(handnum, HANDSTATE_CHANGEGUN)) {
|
|
return lvupdate;
|
|
}
|
|
|
|
if (gunfunc == hand->gset.weaponfunc) {
|
|
hand->unk0cc8_07 = false;
|
|
}
|
|
|
|
hand->unk0cc8_08 = false;
|
|
|
|
if (hand->inuse) {
|
|
sp34 = bgun0f098ca0(hand->gset.weaponfunc, info, hand);
|
|
|
|
// Handle changing gun function
|
|
if (gunfunc != hand->gset.weaponfunc && hand->modenext != HANDMODE_RELOAD) {
|
|
changefunc = true;
|
|
|
|
if (hand->unk0cc8_07 && bgun0f098ca0(1 - hand->gset.weaponfunc, info, hand) < 0) {
|
|
changefunc = false;
|
|
}
|
|
|
|
if (changefunc && info->weaponnum == WEAPON_COMBATKNIFE) {
|
|
if (sp34 == 0) {
|
|
hand->count60 = 0;
|
|
hand->count = 0;
|
|
hand->gset.weaponfunc = gunfunc;
|
|
|
|
if (bgunSetState(handnum, HANDSTATE_RELOAD)) {
|
|
return lvupdate;
|
|
}
|
|
} else {
|
|
if (sp34 < 0) {
|
|
changefunc = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (changefunc) {
|
|
hand->unk0cc8_07 = false;
|
|
|
|
if (bgunSetState(handnum, HANDSTATE_CHANGEFUNC)) {
|
|
return lvupdate;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (sp34 < 0) {
|
|
// Attempted to shoot with no ammo
|
|
|
|
// Consider switching to another weapon
|
|
if (weaponHasFlag(info->weaponnum, WEAPONFLAG_THROWABLE)
|
|
&& (info->weaponnum != WEAPON_REMOTEMINE || handnum != HAND_LEFT)
|
|
&& bgunSetState(handnum, HANDSTATE_AUTOSWITCH)) {
|
|
return lvupdate;
|
|
}
|
|
|
|
// Consider switching to other gun function
|
|
usesec = FUNCISSEC();
|
|
|
|
if (usesec == gunfunc) {
|
|
sp30 = bgun0f098ca0(1 - hand->gset.weaponfunc, info, hand);
|
|
|
|
if (bgun0f099188(hand, 1 - hand->gset.weaponfunc)
|
|
&& info->weaponnum != WEAPON_REAPER) {
|
|
if (info->gunctrl->wantammo) {
|
|
func = weaponGetFunction(&hand->gset, 1 - hand->gset.weaponfunc);
|
|
|
|
if ((func->type & 0xff) != INVENTORYFUNCTYPE_MELEE) {
|
|
sp30 = -1;
|
|
}
|
|
} else {
|
|
sp30 = -1;
|
|
}
|
|
}
|
|
|
|
if (sp30 < 0) {
|
|
hand->unk0cc8_08 = true;
|
|
} else {
|
|
if (!weaponHasFlag(info->weaponnum, WEAPONFLAG_04000000)
|
|
|| hand->gset.weaponfunc == FUNC_SECONDARY) {
|
|
hand->unk0cc8_07 = true;
|
|
|
|
if (bgunSetState(handnum, HANDSTATE_CHANGEFUNC)) {
|
|
return lvupdate;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else if (sp34 == 0) {
|
|
// Clip is empty
|
|
if (hand->triggeron && info->weaponnum != WEAPON_NONE) {
|
|
hand->unk0cc8_01 = false;
|
|
|
|
if (bgunSetState(handnum, HANDSTATE_ATTACKEMPTY)) {
|
|
return lvupdate;
|
|
}
|
|
} else {
|
|
hand->count60 = 0;
|
|
hand->count = 0;
|
|
|
|
if (bgunSetState(handnum, HANDSTATE_RELOAD)) {
|
|
return lvupdate;
|
|
}
|
|
}
|
|
} else {
|
|
// Clip has ammo
|
|
if (hand->triggeron || (hand->activatesecondary && hand->gset.weaponfunc == FUNC_SECONDARY)) {
|
|
if (info->weaponnum != WEAPON_NONE) {
|
|
g_Vars.currentplayer->doautoselect = false;
|
|
|
|
hand->mode = HANDMODE_1;
|
|
hand->count = 0;
|
|
hand->count60 = 0;
|
|
hand->triggerreleased = false;
|
|
hand->activatesecondary = false;
|
|
|
|
if (bgunSetState(handnum, HANDSTATE_ATTACK)) {
|
|
return lvupdate;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Not attacking, but the player may have attempted
|
|
// to change guns or reload while firing
|
|
if (hand->modenext != HANDMODE_NONE) {
|
|
next = hand->modenext;
|
|
|
|
hand->mode = hand->modenext;
|
|
hand->count60 = 0;
|
|
hand->count = 0;
|
|
hand->modenext = HANDMODE_NONE;
|
|
|
|
if (next == HANDMODE_RELOAD && sp34 < 2 && sp34 >= 0) {
|
|
if (bgunSetState(handnum, HANDSTATE_RELOAD)) {
|
|
if (handnum && handnum && handnum);
|
|
return lvupdate;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (handnum == HAND_RIGHT) {
|
|
if (info->gunctrl->wantammo) {
|
|
bgunAutoSwitchWeapon();
|
|
} else {
|
|
lhand = &g_Vars.currentplayer->hands[1] - handnum;
|
|
|
|
if ((hand->unk0cc8_08 || !hand->inuse)
|
|
&& (lhand->unk0cc8_08 || !lhand->inuse)
|
|
&& (hand->triggeron || lhand->triggeron)) {
|
|
bgunAutoSwitchWeapon();
|
|
}
|
|
|
|
hand->unk0cc8_08 = lhand->unk0cc8_08 = false;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void bgun0f099780(struct hand *hand, f32 angle)
|
|
{
|
|
hand->useposrot = true;
|
|
|
|
mtx4LoadXRotation(angle, &hand->posrotmtx);
|
|
|
|
hand->posrotmtx.m[3][0] = 0;
|
|
hand->posrotmtx.m[3][1] = (1.0f - cosf(angle)) * -80.0f;
|
|
hand->posrotmtx.m[3][2] = sinf(angle) * 15.0f;
|
|
}
|
|
|
|
s32 bgunTickIncAutoSwitch(struct handweaponinfo *info, s32 handnum, struct hand *hand, s32 lvupdate)
|
|
{
|
|
u32 stack;
|
|
s32 someval;
|
|
s32 gunfunc = bgunIsUsingSecondaryFunction();
|
|
|
|
if (!hand->inuse && bgunSetState(handnum, HANDSTATE_IDLE)) {
|
|
return lvupdate;
|
|
}
|
|
|
|
if (hand->stateminor == 0) {
|
|
s32 delay = TICKS(16);
|
|
|
|
if (g_Vars.normmplayerisrunning) {
|
|
delay = TICKS(12);
|
|
}
|
|
|
|
if (hand->stateframes >= delay) {
|
|
hand->stateminor++;
|
|
} else {
|
|
bgun0f099780(hand, hand->stateframes * 0.87252569198608f / delay);
|
|
}
|
|
}
|
|
|
|
if (hand->stateminor == 1) {
|
|
hand->lastdirvalid = false;
|
|
#if VERSION < VERSION_PAL_BETA
|
|
hand->animframeincfreal = hand->animframeinc;
|
|
#endif
|
|
hand->shotremainder = 0;
|
|
|
|
if (bgunIsReadyToSwitch(handnum) && bgunSetState(handnum, HANDSTATE_CHANGEGUN)) {
|
|
if (g_Vars.mplayerisrunning && (IS8MB() || PLAYERCOUNT() != 1)) {
|
|
playermgrDeleteWeapon(handnum);
|
|
}
|
|
|
|
bgunFreeHeldRocket(handnum);
|
|
|
|
hand->mode = HANDMODE_6;
|
|
hand->stateminor = 2;
|
|
hand->count = 0;
|
|
return 0;
|
|
}
|
|
|
|
if (hand->inuse) {
|
|
someval = bgun0f098ca0(gunfunc, info, hand);
|
|
|
|
if (info->weaponnum == WEAPON_TIMEDMINE || info->weaponnum == WEAPON_PROXIMITYMINE) {
|
|
hand->gset.weaponfunc = gunfunc;
|
|
}
|
|
|
|
if (info->weaponnum == WEAPON_REMOTEMINE
|
|
&& gunfunc != hand->gset.weaponfunc
|
|
&& bgunSetState(handnum, HANDSTATE_CHANGEFUNC)) {
|
|
return lvupdate;
|
|
}
|
|
|
|
if (g_Vars.currentplayer->doautoselect) {
|
|
struct hand *otherhand = &g_Vars.currentplayer->hands[1 - handnum];
|
|
struct handweaponinfo otherinfo;
|
|
bool ready = true;
|
|
|
|
bgunGetWeaponInfo(&otherinfo, 1 - handnum);
|
|
|
|
if (otherhand->inuse) {
|
|
if (bgun0f098ca0(0, &otherinfo, otherhand) >= 0) {
|
|
ready = false;
|
|
}
|
|
|
|
if (bgun0f098ca0(1, &otherinfo, otherhand) >= 0) {
|
|
ready = false;
|
|
}
|
|
|
|
if (bgun0f099188(otherhand, otherhand->gset.weaponfunc)) {
|
|
ready = true;
|
|
}
|
|
}
|
|
|
|
if (otherhand->state != HANDSTATE_IDLE && otherhand->state != HANDSTATE_AUTOSWITCH) {
|
|
ready = false;
|
|
}
|
|
|
|
if (ready) {
|
|
bgunAutoSwitchWeapon();
|
|
}
|
|
}
|
|
|
|
if (someval <= 1 && someval >= 0) {
|
|
if (g_Vars.currentplayer->hands[1 - handnum].state != HANDSTATE_RELOAD) {
|
|
hand->count60 = 0;
|
|
hand->count = 0;
|
|
|
|
if (bgunSetState(handnum, HANDSTATE_RELOAD)) {
|
|
if (info->weaponnum == WEAPON_COMBATKNIFE) {
|
|
hand->mode = HANDMODE_11;
|
|
hand->pausetime60 = TICKS(17);
|
|
hand->count60 = 0;
|
|
hand->count = -1;
|
|
hand->stateminor = 2;
|
|
}
|
|
|
|
return lvupdate;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (hand->modenext) {
|
|
hand->mode = hand->modenext;
|
|
hand->count60 = 0;
|
|
hand->count = 0;
|
|
hand->modenext = HANDMODE_NONE;
|
|
}
|
|
}
|
|
|
|
bgun0f099780(hand, 0.87252569198608f);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool bgunIsReloading(struct hand *hand)
|
|
{
|
|
if (hand->state == HANDSTATE_RELOAD) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
s32 bgunTickIncReload(struct handweaponinfo *info, s32 handnum, struct hand *hand, s32 lvupdate)
|
|
{
|
|
u32 stack;
|
|
struct weaponfunc *func = gsetGetWeaponFunction(&hand->gset);
|
|
|
|
if (g_Vars.currentplayer->isdead) {
|
|
hand->animmode = HANDANIMMODE_IDLE;
|
|
hand->animload = -1;
|
|
|
|
if (bgunSetState(handnum, HANDSTATE_IDLE)) {
|
|
return lvupdate;
|
|
}
|
|
}
|
|
|
|
if (hand->statecycles == 0) {
|
|
struct hand *hand2 = &g_Vars.currentplayer->hands[1 - handnum];
|
|
|
|
hand->gs_int1 = -1;
|
|
hand->gs_int2 = 0;
|
|
|
|
if (hand2->state == HANDSTATE_RELOAD && hand2->stateframes < TICKS(20)) {
|
|
hand->stateminor = 9;
|
|
}
|
|
}
|
|
|
|
if (hand->stateminor == 9) {
|
|
struct hand *hand2 = &g_Vars.currentplayer->hands[1 - handnum];
|
|
|
|
if (hand2->state == HANDSTATE_RELOAD && hand2->stateframes < TICKS(20)) {
|
|
return 0;
|
|
}
|
|
|
|
hand->stateframes = 0;
|
|
hand->statecycles = 0;
|
|
hand->stateminor = 0;
|
|
hand->statelastframe = 0;
|
|
}
|
|
|
|
if (hand->stateminor == 0) {
|
|
if (hand->statecycles == 0) {
|
|
if (func && (func->ammoindex == 0 || func->ammoindex == 1)) {
|
|
if (info->definition->ammos[func->ammoindex]->reload_animation
|
|
&& info->weaponnum != WEAPON_COMBATKNIFE) {
|
|
bgunStartAnimation(info->definition->ammos[func->ammoindex]->reload_animation, handnum, hand);
|
|
|
|
hand->unk0d0e_07 = true;
|
|
|
|
if (info->definition->ammos[func->ammoindex]->flags & AMMOFLAG_INCREMENTALRELOAD) {
|
|
hand->unk0cc8_03 = true;
|
|
}
|
|
|
|
if (info->weaponnum == WEAPON_GRENADE || info->weaponnum == WEAPON_NBOMB) {
|
|
hand->ejectstate = EJECTSTATE_INACTIVE;
|
|
}
|
|
} else {
|
|
hand->stateminor++;
|
|
}
|
|
} else {
|
|
if (bgunSetState(handnum, HANDSTATE_IDLE)) {
|
|
return lvupdate;
|
|
}
|
|
}
|
|
} else {
|
|
if (info->definition->ammos[func->ammoindex]->flags & AMMOFLAG_INCREMENTALRELOAD) {
|
|
if (bgun0f098a44(hand, 1)) {
|
|
if ((hand->stateflags & HANDSTATEFLAG_00000010) == 0) {
|
|
s32 value;
|
|
|
|
bgun0f098df8(hand->gset.weaponfunc, info, hand, 1, 0);
|
|
hand->stateflags |= HANDSTATEFLAG_00000010;
|
|
value = bgun0f098ca0(hand->gset.weaponfunc, info, hand);
|
|
|
|
if (value >= 2) {
|
|
hand->unk0cc8_03 = false;
|
|
}
|
|
|
|
if (value == -1) {
|
|
hand->unk0cc8_03 = false;
|
|
}
|
|
}
|
|
} else {
|
|
hand->stateflags = 0;
|
|
}
|
|
|
|
if (hand->triggeron) {
|
|
hand->unk0cc8_03 = false;
|
|
}
|
|
|
|
#if VERSION >= VERSION_JPN_FINAL
|
|
if (g_Vars.currentplayer->devicesactive & ~g_Vars.currentplayer->devicesinhibit & DEVICE_EYESPY) {
|
|
hand->unk0cc8_03 = false;
|
|
}
|
|
#endif
|
|
} else {
|
|
if ((hand->stateflags & HANDSTATEFLAG_00000010) == 0) {
|
|
if (bgun0f098a44(hand, 1)) {
|
|
bgun0f098df8(hand->gset.weaponfunc, info, hand, 0, 0);
|
|
hand->stateflags |= HANDSTATEFLAG_00000010;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (hand->animmode != HANDANIMMODE_BUSY) {
|
|
if (bgunSetState(handnum, HANDSTATE_IDLE)) {
|
|
return lvupdate;
|
|
}
|
|
}
|
|
|
|
if (1);
|
|
}
|
|
}
|
|
|
|
if (hand->stateminor == 1) {
|
|
if (hand->count60 > TICKS(15) || !hand->visible) {
|
|
hand->mode = HANDMODE_11;
|
|
hand->stateminor++;
|
|
hand->pausetime60 = TICKS(17);
|
|
hand->count60 = 0;
|
|
hand->count = 0;
|
|
} else {
|
|
bgun0f099780(hand, (hand->count60 * 0.87252569198608f) / TICKS(16));
|
|
}
|
|
}
|
|
|
|
if (hand->stateminor == 2) {
|
|
if (hand->count == 0) {
|
|
if (info->weaponnum == WEAPON_COMBATKNIFE
|
|
&& func->ammoindex >= 0
|
|
&& info->definition->ammos[func->ammoindex]->reload_animation) {
|
|
bgunStartAnimation(info->definition->ammos[func->ammoindex]->reload_animation, handnum, hand);
|
|
hand->unk0cc8_02 = true;
|
|
}
|
|
|
|
if ((hand->stateflags & HANDSTATEFLAG_00000010) == 0) {
|
|
bgun0f098df8(hand->gset.weaponfunc, info, hand, 0, 0);
|
|
}
|
|
|
|
if (g_Vars.lvupdate240 > 0
|
|
&& g_Vars.currentplayer->cameramode != CAMERAMODE_THIRDPERSON
|
|
&& bgun0f09dd7c()
|
|
&& !g_PlayerInvincible
|
|
&& !g_Vars.currentplayer->isdead) {
|
|
switch (info->weaponnum) {
|
|
case WEAPON_NONE:
|
|
case WEAPON_UNARMED:
|
|
case WEAPON_COMBATKNIFE:
|
|
case WEAPON_LASER:
|
|
case WEAPON_GRENADE:
|
|
case WEAPON_TIMEDMINE:
|
|
case WEAPON_PROXIMITYMINE:
|
|
case WEAPON_REMOTEMINE:
|
|
case WEAPON_ECMMINE:
|
|
case WEAPON_COMMSRIDER:
|
|
case WEAPON_TRACERBUG:
|
|
case WEAPON_TARGETAMPLIFIER:
|
|
case WEAPON_BRIEFCASE2:
|
|
// No reload sound
|
|
break;
|
|
default:
|
|
sndStart(var80095200, SFX_RELOAD_DEFAULT, 0, -1, -1, -1, -1, -1);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (hand->count60 >= hand->pausetime60 && hand->count >= 2) {
|
|
hand->mode = HANDMODE_12;
|
|
hand->stateminor++;
|
|
hand->count60 = 0;
|
|
hand->count = 0;
|
|
} else {
|
|
bgun0f099780(hand, 0.87252569198608f);
|
|
}
|
|
}
|
|
|
|
if (hand->stateminor == 3) {
|
|
if (info->weaponnum == WEAPON_COMBATKNIFE) {
|
|
hand->animmode = HANDANIMMODE_IDLE;
|
|
}
|
|
|
|
if (hand->count == 0) {
|
|
g_Vars.currentplayer->doautoselect = false;
|
|
}
|
|
|
|
if (hand->count60 >= TICKS(23)
|
|
|| !weaponGetModelNum2(info->weaponnum)
|
|
|| !weaponHasFlag(info->weaponnum, WEAPONFLAG_00000040)
|
|
|| weaponHasFlag(info->weaponnum, WEAPONFLAG_00000080)) {
|
|
hand->mode = HANDMODE_NONE;
|
|
hand->count60 = 0;
|
|
hand->count = 0;
|
|
|
|
if (bgunSetState(handnum, HANDSTATE_IDLE)) {
|
|
return lvupdate;
|
|
}
|
|
} else {
|
|
bgun0f099780(hand, (TICKS(23) - hand->count60) * 0.87252569198608f / TICKS(23));
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
s32 bgunTickIncChangeFunc(struct handweaponinfo *info, s32 handnum, struct hand *hand, s32 lvupdate)
|
|
{
|
|
struct guncmd *cmd;
|
|
bool more = false;
|
|
|
|
if (hand->statecycles == 0) {
|
|
if (hand->gset.weaponfunc == FUNC_PRIMARY) {
|
|
cmd = gsetGetPriToSecAnim(&hand->gset);
|
|
hand->gset.weaponfunc = FUNC_SECONDARY;
|
|
} else {
|
|
cmd = gsetGetSecToPriAnim(&hand->gset);
|
|
hand->gset.weaponfunc = FUNC_PRIMARY;
|
|
}
|
|
|
|
more = false;
|
|
|
|
if (cmd != NULL) {
|
|
bgunStartAnimation(cmd, handnum, hand);
|
|
more = true;
|
|
g_Vars.currentplayer->hands[HAND_RIGHT].unk0dd4 = -1;
|
|
}
|
|
} else {
|
|
if (hand->animmode == HANDANIMMODE_BUSY) {
|
|
more = true;
|
|
}
|
|
}
|
|
|
|
if (!more && bgunSetState(handnum, HANDSTATE_IDLE)) {
|
|
return lvupdate;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
s32 bgun0f09a3f8(struct hand *hand, struct weaponfunc *func)
|
|
{
|
|
bool burst = false;
|
|
bool smallburst = false;
|
|
struct gunctrl *ctrl = &g_Vars.currentplayer->gunctrl;
|
|
|
|
if ((func->flags & FUNCFLAG_BURST3) && hand->burstbullets < 3) {
|
|
// Make automatics do single shot when holding aim
|
|
if (!g_Vars.currentplayer->insightaimmode || (func->type & 0xff00) != 0x100) {
|
|
// Not aiming and not an automatic weapon
|
|
smallburst = true;
|
|
}
|
|
}
|
|
|
|
if ((func->flags & FUNCFLAG_BURST2) && hand->burstbullets < 2) {
|
|
smallburst = true;
|
|
}
|
|
|
|
if ((func->flags & FUNCFLAG_BURST5) && hand->burstbullets < 5) {
|
|
smallburst = true;
|
|
}
|
|
|
|
if ((func->flags & FUNCFLAG_BURST50) && hand->burstbullets < 50) {
|
|
burst = true;
|
|
}
|
|
|
|
if (smallburst) {
|
|
burst = true;
|
|
}
|
|
|
|
if (hand->triggeron || (hand->stateflags & HANDSTATEFLAG_00000010) == 0 || burst) {
|
|
if (func->ammoindex >= 0
|
|
&& hand->loadedammo[func->ammoindex] == 0
|
|
&& ctrl->ammotypes[func->ammoindex] >= 0) {
|
|
// Clip is empty
|
|
return -1;
|
|
}
|
|
|
|
if ((func->type & 0xff00) == 0x100) {
|
|
struct weaponfunc_shootauto *autofunc = (struct weaponfunc_shootauto *) func;
|
|
|
|
if (autofunc->turretaccel > 0) {
|
|
if (hand->gs_float1 < 1) {
|
|
hand->gs_float1 += LVUPDATE60FREAL() / autofunc->turretaccel;
|
|
|
|
if (hand->gs_float1 > 1) {
|
|
hand->gs_float1 = 1;
|
|
return 1;
|
|
}
|
|
}
|
|
} else {
|
|
hand->gs_float1 = 1;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
hand->gs_float1 = 1;
|
|
|
|
if (smallburst) {
|
|
if (hand->burstbullets > 0) {
|
|
s32 delay = 3;
|
|
|
|
if (hand->gset.weaponnum == WEAPON_SHOTGUN) {
|
|
delay = TICKS(13);
|
|
}
|
|
|
|
if (hand->stateframes < delay) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
hand->stateframes = 0;
|
|
}
|
|
|
|
if ((func->flags & FUNCFLAG_BURST3) && hand->burstbullets == 2) {
|
|
smallburst = false;
|
|
}
|
|
|
|
if ((func->flags & FUNCFLAG_BURST2) && hand->burstbullets == 1) {
|
|
smallburst = false;
|
|
}
|
|
|
|
if ((func->flags & FUNCFLAG_BURST5) && hand->burstbullets == 4) {
|
|
smallburst = false;
|
|
}
|
|
|
|
if (smallburst) {
|
|
return 1;
|
|
}
|
|
|
|
return 2;
|
|
}
|
|
|
|
if ((func->type & 0xff00) == (INVENTORYFUNCTYPE_SHOOT_AUTOMATIC & 0xff00)) {
|
|
struct weaponfunc_shootauto *autofunc = (struct weaponfunc_shootauto *) func;
|
|
|
|
if (autofunc->turretdecel > 0) {
|
|
if (hand->gs_float1 > 0) {
|
|
hand->gs_float1 -= LVUPDATE60FREAL() / autofunc->turretdecel;
|
|
|
|
if (hand->gs_float1 < 0) {
|
|
hand->gs_float1 = 0;
|
|
return -1;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
} else {
|
|
hand->gs_float1 = 0;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
void bgun0f09a6f8(struct handweaponinfo *info, s32 handnum, struct hand *hand, struct weaponfunc *func)
|
|
{
|
|
bool usesammo = true;
|
|
|
|
static u32 rontime = 2;
|
|
static u32 rofftime = 4;
|
|
|
|
mainOverrideVariable("rontime", &rontime);
|
|
mainOverrideVariable("rofftime", &rofftime);
|
|
|
|
hand->firing = true;
|
|
|
|
if ((func->type & 0xff00) == 0x100) {
|
|
struct weaponfunc_shootauto *autofunc = (struct weaponfunc_shootauto *) func;
|
|
f32 tmp;
|
|
f32 tmp2;
|
|
|
|
tmp = autofunc->initialrpm + (autofunc->maxrpm - autofunc->initialrpm) * hand->gs_float1;
|
|
tmp2 = tmp / 60.0f * (LVUPDATE60FREAL() / 60.0f) + hand->shotremainder;
|
|
|
|
hand->shotstotake = tmp2;
|
|
hand->shotremainder = tmp2 - hand->shotstotake;
|
|
|
|
if (hand->shotstotake <= 0) {
|
|
if ((hand->stateflags & HANDSTATEFLAG_00000010) == 0) {
|
|
hand->shotstotake++;
|
|
} else {
|
|
hand->firing = false;
|
|
}
|
|
}
|
|
} else {
|
|
hand->shotstotake = 1;
|
|
|
|
if (hand->gset.weaponnum == WEAPON_LASER) {
|
|
usesammo = false;
|
|
}
|
|
}
|
|
|
|
hand->burstbullets += hand->shotstotake;
|
|
|
|
if (func->flags & FUNCFLAG_NOMUZZLEFLASH) {
|
|
hand->flashon = false;
|
|
} else {
|
|
hand->flashon = true;
|
|
}
|
|
|
|
bgunStartSlide(handnum);
|
|
|
|
hand->loadslide = 0;
|
|
|
|
if (hand->firing) {
|
|
hand->statevar1 = hand->stateframes;
|
|
hand->stateflags |= HANDSTATEFLAG_00000020;
|
|
hand->stateflags |= HANDSTATEFLAG_00000010;
|
|
|
|
bgunRumble(handnum, info->weaponnum);
|
|
|
|
if (usesammo && func->ammoindex >= 0) {
|
|
hand->loadedammo[func->ammoindex] -= hand->shotstotake;
|
|
|
|
if (hand->loadedammo[func->ammoindex] < 0) {
|
|
// Note: loadedammo is negative
|
|
hand->shotstotake += hand->loadedammo[func->ammoindex];
|
|
hand->loadedammo[func->ammoindex] = 0;
|
|
}
|
|
}
|
|
|
|
switch (func->type & 0xff00) {
|
|
case 0:
|
|
case 0x100:
|
|
hand->attacktype = HANDATTACKTYPE_SHOOT;
|
|
break;
|
|
case 0x200:
|
|
hand->attacktype = HANDATTACKTYPE_SHOOTPROJECTILE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (hand->firing) {
|
|
bool playsound = false;
|
|
|
|
if (gsetGetFireslotDuration(&hand->gset) > 0) {
|
|
if (g_Vars.lvframe60 != g_Vars.currentplayer->hands[1 - handnum].lastshootframe60
|
|
&& g_Vars.lvframe60 > hand->allowshootframe) {
|
|
hand->allowshootframe = g_Vars.lvframe60 + gsetGetFireslotDuration(&hand->gset);
|
|
playsound = true;
|
|
}
|
|
} else {
|
|
if (hand->firing) {
|
|
playsound = true;
|
|
}
|
|
}
|
|
|
|
if (playsound) {
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
OSPri prevpri = osGetThreadPri(0);
|
|
osSetThreadPri(0, osGetThreadPri(&g_AudioManager.thread) + 1);
|
|
#endif
|
|
|
|
if (hand->audiohandle2 && sndGetState(hand->audiohandle2) != AL_STOPPED) {
|
|
audioStop(hand->audiohandle2);
|
|
}
|
|
|
|
if (hand->audiohandle3 && sndGetState(hand->audiohandle3) != AL_STOPPED) {
|
|
audioStop(hand->audiohandle3);
|
|
}
|
|
|
|
if (gsetGetSingleShootSound(&hand->gset)) {
|
|
struct sndstate *handle = NULL;
|
|
|
|
if (hand->audiohandle2 == NULL) {
|
|
handle = sndStart(var80095200, gsetGetSingleShootSound(&hand->gset), &hand->audiohandle2, -1, -1, -1, -1, -1);
|
|
} else if (hand->audiohandle3 == NULL) {
|
|
handle = sndStart(var80095200, gsetGetSingleShootSound(&hand->gset), &hand->audiohandle3, -1, -1, -1, -1, -1);
|
|
}
|
|
|
|
hand->lastshootframe60 = g_Vars.lvframe60;
|
|
|
|
if (hand->gset.weaponnum == WEAPON_MAULER && handle) {
|
|
s32 matmot = hand->matmot1;
|
|
f32 tmp;
|
|
f32 frac = matmot / 3.0f;
|
|
|
|
if (frac > 1.0f) {
|
|
frac = 1.0f;
|
|
}
|
|
|
|
tmp = 1.0f - frac * 0.4f;
|
|
|
|
audioPostEvent(handle, 16, *(s32 *) &tmp);
|
|
}
|
|
|
|
}
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
osSetThreadPri(0, prevpri);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
bool bgun0f09aba4(struct hand *hand, struct handweaponinfo *info, s32 handnum, struct weaponfunc_shoot *func)
|
|
{
|
|
s32 unk24;
|
|
s32 unk25;
|
|
s32 sum;
|
|
s32 unk26;
|
|
s32 unk27;
|
|
s32 recoverytime60;
|
|
s32 frames;
|
|
struct weapon *weapondef;
|
|
f32 mult1;
|
|
f32 recoildist;
|
|
f32 recoilangle;
|
|
f32 mult2;
|
|
u32 stack;
|
|
|
|
#if PAL
|
|
unk24 = func->unk24;
|
|
unk25 = func->unk25;
|
|
unk26 = func->unk26;
|
|
unk27 = func->unk27;
|
|
recoverytime60 = func->recoverytime60;
|
|
weapondef = info->definition;
|
|
|
|
if (unk24 >= 4) {
|
|
unk24 = TICKS(unk24);
|
|
}
|
|
|
|
if (unk25 >= 4) {
|
|
unk25 = TICKS(unk25);
|
|
}
|
|
|
|
if (unk26 >= 4) {
|
|
unk26 = TICKS(unk26);
|
|
}
|
|
|
|
if (unk27 >= 4) {
|
|
unk27 = TICKS(unk27);
|
|
}
|
|
|
|
if (recoverytime60 >= 4) {
|
|
recoverytime60 = TICKS(recoverytime60);
|
|
}
|
|
|
|
sum = unk24 + unk25;
|
|
#elif VERSION >= VERSION_JPN_FINAL
|
|
unk24 = func->unk24;
|
|
unk25 = func->unk25;
|
|
unk26 = func->unk26;
|
|
unk27 = func->unk27;
|
|
recoverytime60 = func->recoverytime60;
|
|
weapondef = info->definition;
|
|
sum = unk24 + unk25;
|
|
#else
|
|
unk24 = func->unk24;
|
|
unk25 = func->unk25;
|
|
sum = unk24 + unk25;
|
|
unk26 = func->unk26;
|
|
unk27 = func->unk27;
|
|
recoverytime60 = func->recoverytime60;
|
|
weapondef = info->definition;
|
|
#endif
|
|
|
|
frames = hand->stateframes - hand->statevar1;
|
|
|
|
if (sum < 1) {
|
|
sum = 0;
|
|
} else {
|
|
if (hand->triggerreleased
|
|
&& hand->triggeron
|
|
&& frames >= unk26
|
|
&& unk26 > 0
|
|
&& unk27 >= 0
|
|
&& (hand->stateflags & HANDSTATEFLAG_00000040) == 0
|
|
&& frames + unk27 < sum) {
|
|
hand->stateflags |= HANDSTATEFLAG_00000040;
|
|
hand->statevar1 = frames;
|
|
|
|
hand->rotxstart = hand->rotxoffset;
|
|
hand->rotxend = 0;
|
|
|
|
hand->posend.x = 0;
|
|
hand->posend.y = 0;
|
|
hand->posend.z = 0;
|
|
|
|
hand->posstart.x = hand->posoffset.x;
|
|
hand->posstart.y = hand->posoffset.y;
|
|
hand->posstart.z = hand->posoffset.z;
|
|
}
|
|
|
|
if (hand->stateflags & HANDSTATEFLAG_00000040) {
|
|
if (unk27 > frames - hand->statevar1) {
|
|
mult1 = cosf((f32)(unk27 - frames + hand->statevar1) * 1.5707963705063f / (f32)unk27) * 0.5f + 0.5f;
|
|
|
|
hand->rotxoffset = modelTweenRotAxis(hand->rotxstart, hand->rotxend, mult1);
|
|
hand->useposrot = true;
|
|
|
|
hand->posoffset.x = (hand->posend.x - hand->posstart.x) * mult1 + hand->posstart.x;
|
|
hand->posoffset.y = (hand->posend.y - hand->posstart.y) * mult1 + hand->posstart.y;
|
|
hand->posoffset.z = (hand->posend.z - hand->posstart.z) * mult1 + hand->posstart.z;
|
|
|
|
mtx4LoadXRotation(hand->rotxoffset, &hand->posrotmtx);
|
|
mtx4SetTranslation(&hand->posoffset, &hand->posrotmtx);
|
|
} else {
|
|
mtx4LoadIdentity(&hand->posrotmtx);
|
|
hand->useposrot = false;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (frames < sum && (hand->stateflags & HANDSTATEFLAG_00000040) == 0) {
|
|
recoildist = func->recoildist;
|
|
recoilangle = func->recoilangle;
|
|
|
|
if ((hand->stateflags & HANDSTATEFLAG_00000080) == 0) {
|
|
hand->stateflags |= HANDSTATEFLAG_00000080;
|
|
hand->rotxstart = hand->rotxoffset;
|
|
hand->posstart.x = hand->posoffset.x;
|
|
hand->posstart.y = hand->posoffset.y;
|
|
hand->posstart.z = hand->posoffset.z;
|
|
}
|
|
|
|
hand->rotxend = M_BADTAU - (recoilangle * M_BADTAU) / 360.0f;
|
|
|
|
hand->posend.x = (func0f0b131c(handnum) - hand->aimpos.x) * recoildist / 1000.0f;
|
|
hand->posend.y = 0;
|
|
hand->posend.z = (weapondef->posz - hand->aimpos.z) * recoildist / 1000.0f;
|
|
|
|
if (frames < unk24) {
|
|
mult2 = sinf(frames * 1.5707963705063f / (f32)unk24);
|
|
} else {
|
|
mult2 = cosf((f32)(frames - unk24) * M_PI / (f32)unk25) * 0.5f + 0.5f;
|
|
}
|
|
|
|
hand->rotxoffset = modelTweenRotAxis(hand->rotxstart, hand->rotxend, mult2);
|
|
hand->useposrot = true;
|
|
|
|
hand->posoffset.x = (hand->posend.x - hand->posstart.x) * mult2 + hand->posstart.x;
|
|
hand->posoffset.y = (hand->posend.y - hand->posstart.y) * mult2 + hand->posstart.y;
|
|
hand->posoffset.z = (hand->posend.z - hand->posstart.z) * mult2 + hand->posstart.z;
|
|
|
|
mtx4LoadXRotation(hand->rotxoffset, &hand->posrotmtx);
|
|
mtx4SetTranslation(&hand->posoffset, &hand->posrotmtx);
|
|
}
|
|
}
|
|
|
|
if (sum <= frames) {
|
|
if (unk27 >= 0 && hand->triggerreleased && hand->triggeron) {
|
|
return true;
|
|
} else if (sum + recoverytime60 <= frames) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool bgunTickIncAttackingShoot(struct handweaponinfo *info, s32 handnum, struct hand *hand)
|
|
{
|
|
static u32 var80070128 = 99;
|
|
|
|
struct weaponfunc *func = gsetGetWeaponFunction(&hand->gset);
|
|
bool sp68;
|
|
s32 sp64;
|
|
s32 sp60;
|
|
|
|
if (func == NULL) {
|
|
return true;
|
|
}
|
|
|
|
if (hand->stateminor == 0) {
|
|
sp64 = 1;
|
|
|
|
mainOverrideVariable("gkef", &var80070128);
|
|
|
|
if (hand->statecycles == 0) {
|
|
hand->gs_float1 = 0;
|
|
|
|
if (func->fire_animation) {
|
|
bgunStartAnimation(func->fire_animation, handnum, hand);
|
|
hand->unk0cc8_01 = true;
|
|
}
|
|
|
|
hand->burstbullets = 0;
|
|
}
|
|
|
|
if (!bgun0f098a44(hand, 2)) {
|
|
sp64 = 0;
|
|
}
|
|
|
|
if (sp64) {
|
|
hand->stateminor = 1;
|
|
}
|
|
|
|
hand->matmot2 = hand->gs_float1;
|
|
}
|
|
|
|
if (hand->stateminor == 1) {
|
|
sp60 = bgun0f09a3f8(hand, func);
|
|
|
|
if ((func->type & 0xff00) == 0x100) {
|
|
struct weaponfunc_shootauto *autofunc = (struct weaponfunc_shootauto *) func;
|
|
f32 floats[12];
|
|
|
|
if (autofunc->vibrationstart != NULL && autofunc->vibrationmax != NULL) {
|
|
func0f097b64(autofunc->vibrationstart, autofunc->vibrationmax, hand->gs_float1, floats);
|
|
func0f097b40(hand->upgrademult, floats, hand->finalmult);
|
|
}
|
|
}
|
|
|
|
if (sp60 > 0) {
|
|
bgun0f09a6f8(info, handnum, hand, func);
|
|
}
|
|
|
|
if (sp60 < 0 || sp60 == 2) {
|
|
hand->stateminor = 2;
|
|
}
|
|
|
|
hand->matmot2 = hand->gs_float1;
|
|
|
|
if (hand->triggeron && hand->matmot2 < 0.4f) {
|
|
hand->matmot2 = 0.4f;
|
|
}
|
|
|
|
if (hand->triggerreleased) {
|
|
hand->unk0cc8_01 = false;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
if (hand->stateminor == 2) {
|
|
if (hand->stateflags & HANDSTATEFLAG_00000020) {
|
|
sp68 = bgun0f09aba4(hand, info, handnum, (struct weaponfunc_shoot *) func);
|
|
} else {
|
|
sp68 = true;
|
|
}
|
|
|
|
if (hand->gset.weaponnum == WEAPON_SHOTGUN && hand->animmode == HANDANIMMODE_BUSY) {
|
|
sp68 = false;
|
|
}
|
|
|
|
hand->matmot2 = hand->gs_float1;
|
|
|
|
if (sp68 && !hand->triggeron) {
|
|
hand->matmot2 = 0;
|
|
}
|
|
|
|
if (hand->gset.weaponnum == WEAPON_MAULER) {
|
|
hand->matmot1 = 0;
|
|
}
|
|
|
|
return sp68;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool bgunTickIncAttackingThrow(s32 handnum, struct hand *hand)
|
|
{
|
|
struct weaponfunc_throw *func = (struct weaponfunc_throw *) gsetGetWeaponFunction(&hand->gset);
|
|
|
|
if (func == NULL) {
|
|
return true;
|
|
}
|
|
|
|
if (hand->stateminor == 0) {
|
|
if (hand->statecycles == 0) {
|
|
if (func->base.flags & FUNCFLAG_DISCARDWEAPON) {
|
|
invRemoveItemByNum(hand->gset.weaponnum);
|
|
g_Vars.currentplayer->gunctrl.unk1583_04 = true;
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
bgunSwitchToPrevious();
|
|
#else
|
|
bgunAutoSwitchWeapon();
|
|
#endif
|
|
hand->primetimer60 = 0;
|
|
return true;
|
|
}
|
|
|
|
if (func->base.fire_animation) {
|
|
bgunStartAnimation(func->base.fire_animation, handnum, hand);
|
|
hand->unk0cc8_01 = true;
|
|
}
|
|
}
|
|
|
|
if (func->base.fire_animation) {
|
|
if (hand->triggerreleased) {
|
|
hand->unk0cc8_01 = false;
|
|
}
|
|
|
|
if (bgun0f098a44(hand, 2)) {
|
|
hand->stateminor = 1;
|
|
hand->unk0cc8_01 = false;
|
|
}
|
|
} else {
|
|
hand->stateminor = 1;
|
|
}
|
|
}
|
|
|
|
if (hand->stateminor == 1) {
|
|
hand->firing = true;
|
|
hand->attacktype = HANDATTACKTYPE_THROWPROJECTILE;
|
|
hand->loadedammo[func->base.ammoindex]--;
|
|
hand->stateminor = 2;
|
|
return false;
|
|
}
|
|
|
|
if (hand->stateminor == 2) {
|
|
if (hand->stateframes > TICKS(func->recoverytime60)) {
|
|
return true;
|
|
}
|
|
|
|
if (hand->gset.weaponnum == WEAPON_REMOTEMINE
|
|
&& bgunIsUsingSecondaryFunction() == true
|
|
&& hand->triggerreleased
|
|
&& hand->triggeron) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// This state is only used after having a grenade explode in the player's
|
|
// hand. It waits 4 seconds before finishing, which means the player won't
|
|
// pull out another grenade until the flames have cleared.
|
|
if (hand->stateminor == 55) {
|
|
bgunResetAnim(hand);
|
|
|
|
if (hand->stateframes > TICKS(func->activatetime60 + 240)) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
hand->primetimer60 = hand->stateframes;
|
|
|
|
// If held a grenade too long, force throw it and enter the wait state
|
|
if (hand->gset.weaponnum == WEAPON_GRENADE
|
|
&& hand->gset.weaponfunc == FUNC_PRIMARY
|
|
&& hand->primetimer60 > TICKS(func->activatetime60)) {
|
|
hand->firing = true;
|
|
hand->attacktype = HANDATTACKTYPE_THROWPROJECTILE;
|
|
hand->loadedammo[func->base.ammoindex]--;
|
|
hand->stateminor = 55;
|
|
|
|
return false;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
s32 bgunGetMinClipQty(s32 weaponnum, s32 funcnum)
|
|
{
|
|
if (weaponnum == WEAPON_TRANQUILIZER && funcnum == FUNC_SECONDARY) {
|
|
return 4;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
const char var7f1ab8ac[] = "changegunmem type %d CurrentPlayer->gunctrl.gunmemtype %d\n";
|
|
const char var7f1ab8e8[] = "LockTimer: %d\n";
|
|
const char var7f1ab8f8[] = "BriGun: Releasing gunmem - current gunmemtype %d gunmemnew %d\n";
|
|
const char var7f1ab938[] = "GiveMem: %d\n";
|
|
|
|
u32 var8007012c = 0x00000000;
|
|
u32 var80070130 = 0x00000000;
|
|
|
|
bool bgunTickIncAttackingMelee(s32 handnum, struct hand *hand)
|
|
{
|
|
struct weaponfunc *func = gsetGetWeaponFunction(&hand->gset);
|
|
|
|
if (func == NULL) {
|
|
return true;
|
|
}
|
|
|
|
if (hand->gset.weaponnum == WEAPON_REAPER) {
|
|
if (hand->statecycles == 0) {
|
|
hand->matmot2 = 0.1f;
|
|
hand->burstbullets = 0;
|
|
}
|
|
|
|
hand->firing = true;
|
|
hand->attacktype = HANDATTACKTYPE_MELEE;
|
|
hand->burstbullets++;
|
|
|
|
if (hand->triggeron) {
|
|
hand->matmot2 += 0.01f * LVUPDATE60FREAL();
|
|
|
|
if (hand->matmot2 > 1) {
|
|
hand->matmot2 = 1;
|
|
}
|
|
} else {
|
|
hand->matmot2 = 0;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
if (hand->stateminor == 0) {
|
|
if (hand->statecycles == 0) {
|
|
hand->firing = true;
|
|
hand->attacktype = HANDATTACKTYPE_MELEENOUNCLOAK;
|
|
|
|
if (func->fire_animation) {
|
|
bgunStartAnimation(func->fire_animation, handnum, hand);
|
|
hand->unk0cc8_01 = true;
|
|
}
|
|
}
|
|
|
|
if (func->fire_animation) {
|
|
if (hand->triggerreleased) {
|
|
hand->unk0cc8_01 = false;
|
|
}
|
|
|
|
if (bgun0f098a44(hand, 2)) {
|
|
hand->stateminor = 1;
|
|
hand->unk0cc8_01 = false;
|
|
}
|
|
} else {
|
|
hand->stateminor = 1;
|
|
}
|
|
}
|
|
|
|
if (hand->stateminor == 3 && bgun0f098a44(hand, 3)) {
|
|
hand->stateminor = 1;
|
|
hand->unk0cc8_01 = false;
|
|
}
|
|
|
|
if (hand->stateminor == 1) {
|
|
hand->firing = true;
|
|
hand->attacktype = HANDATTACKTYPE_MELEE;
|
|
|
|
if (hand->gset.weaponnum == WEAPON_TRANQUILIZER && func->ammoindex >= 0) {
|
|
if (hand->loadedammo[func->ammoindex] > bgunGetMinClipQty(WEAPON_TRANQUILIZER, FUNC_SECONDARY)) {
|
|
hand->loadedammo[func->ammoindex] -= bgunGetMinClipQty(WEAPON_TRANQUILIZER, FUNC_SECONDARY);
|
|
} else {
|
|
hand->loadedammo[func->ammoindex] = 0;
|
|
}
|
|
}
|
|
|
|
if (func->fire_animation) {
|
|
if (func->fire_animation && !bgun0f098a44(hand, 3)) {
|
|
hand->stateminor = 3;
|
|
} else {
|
|
hand->stateminor = 2;
|
|
}
|
|
}
|
|
|
|
if (cheatIsActive(CHEAT_HURRICANEFISTS)) {
|
|
hand->stateminor = 2;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
if (hand->stateminor == 2) {
|
|
if (!bgunIsAnimBusy(hand)) {
|
|
return true;
|
|
}
|
|
|
|
if (cheatIsActive(CHEAT_HURRICANEFISTS) && hand->gset.weaponnum == WEAPON_UNARMED) {
|
|
return true;
|
|
}
|
|
|
|
if (hand->stateframes > TICKS(60)) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool bgunTickIncAttackingSpecial(struct hand *hand)
|
|
{
|
|
struct weaponfunc_special *func = (struct weaponfunc_special *) gsetGetWeaponFunction(&hand->gset);
|
|
|
|
if (!func) {
|
|
return true;
|
|
}
|
|
|
|
if (hand->stateminor == 0) {
|
|
hand->stateminor = 1;
|
|
}
|
|
|
|
if (hand->stateminor == 1) {
|
|
hand->firing = true;
|
|
hand->attacktype = func->specialfunc;
|
|
|
|
if (func->base.ammoindex >= 0) {
|
|
hand->loadedammo[func->base.ammoindex]--;
|
|
}
|
|
|
|
hand->stateminor = 2;
|
|
return false;
|
|
}
|
|
|
|
if (hand->stateminor == 2) {
|
|
if (hand->stateframes > TICKS(func->recoverytime60)) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
s32 bgunTickIncAttackEmpty(struct handweaponinfo *info, s32 handnum, struct hand *hand, s32 lvupdate)
|
|
{
|
|
u32 stack;
|
|
bool playsound = false;
|
|
|
|
switch (info->weaponnum) {
|
|
case WEAPON_FALCON2:
|
|
case WEAPON_FALCON2_SILENCER:
|
|
case WEAPON_FALCON2_SCOPE:
|
|
case WEAPON_MAGSEC4:
|
|
case WEAPON_MAULER:
|
|
case WEAPON_PHOENIX:
|
|
case WEAPON_DY357MAGNUM:
|
|
case WEAPON_DY357LX:
|
|
case WEAPON_CMP150:
|
|
case WEAPON_CYCLONE:
|
|
case WEAPON_CALLISTO:
|
|
case WEAPON_RCP120:
|
|
case WEAPON_LAPTOPGUN:
|
|
case WEAPON_REAPER:
|
|
case WEAPON_TRANQUILIZER:
|
|
case WEAPON_PP9I:
|
|
case WEAPON_CC13:
|
|
// These weapons are weapons with visible finger trigger animations
|
|
if (hand->stateframes > TICKS(25)) {
|
|
hand->stateframes -= TICKS(25);
|
|
hand->stateflags = 0;
|
|
|
|
bgunResetAnim(hand);
|
|
}
|
|
|
|
if (hand->animmode != HANDANIMMODE_BUSY) {
|
|
bool restartedanim = false;
|
|
|
|
if ((hand->stateflags & HANDSTATEFLAG_00000010) == 0) {
|
|
struct weaponfunc *func = NULL;
|
|
|
|
if (info->definition) {
|
|
func = gsetGetWeaponFunction(&hand->gset);
|
|
}
|
|
|
|
if (func && func->fire_animation) {
|
|
bgunStartAnimation(func->fire_animation, handnum, hand);
|
|
restartedanim = true;
|
|
}
|
|
}
|
|
|
|
if (!restartedanim && hand->stateframes > TICKS(25)) {
|
|
playsound = true;
|
|
}
|
|
} else if (bgun0f098a44(hand, 5)) {
|
|
playsound = true;
|
|
}
|
|
break;
|
|
default:
|
|
// Weapons without visible trigger animations must
|
|
// still play the click sound every 25 frames
|
|
if (hand->stateframes > TICKS(25)) {
|
|
playsound = true;
|
|
|
|
hand->stateframes -= TICKS(25);
|
|
hand->stateflags = 0;
|
|
|
|
bgunResetAnim(hand);
|
|
}
|
|
}
|
|
|
|
hand->mode = HANDMODE_13;
|
|
hand->count60 = 0;
|
|
hand->count = 0;
|
|
|
|
if (playsound && (hand->stateflags & HANDSTATEFLAG_00000010) == 0) {
|
|
hand->stateflags |= HANDSTATEFLAG_00000010;
|
|
|
|
switch (info->weaponnum) {
|
|
case WEAPON_PHOENIX:
|
|
case WEAPON_CALLISTO:
|
|
case WEAPON_FARSIGHT:
|
|
{
|
|
// Maian weapons have a wet sounding click effect
|
|
f32 speed = 2.07f;
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
OSPri prevpri = osGetThreadPri(0);
|
|
struct sndstate *handle;
|
|
osSetThreadPri(0, osGetThreadPri(&g_AudioManager.thread) + 1);
|
|
#else
|
|
struct sndstate *handle;
|
|
#endif
|
|
|
|
handle = sndStart(var80095200, SFX_HIT_WATER, NULL, -1, -1, -1, -1, -1);
|
|
|
|
if (handle) {
|
|
audioPostEvent(handle, 16, *(s32 *)&speed);
|
|
}
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
osSetThreadPri(0, prevpri);
|
|
#endif
|
|
}
|
|
// fall-through - unsure if intentional
|
|
case WEAPON_TRANQUILIZER:
|
|
case WEAPON_PSYCHOSISGUN:
|
|
{
|
|
// The tranquliser and psychosis gun use the standard click
|
|
// effect but slightly faster.
|
|
f32 speed = 1.5f;
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
OSPri prevpri = osGetThreadPri(0);
|
|
struct sndstate *handle;
|
|
osSetThreadPri(0, osGetThreadPri(&g_AudioManager.thread) + 1);
|
|
#else
|
|
struct sndstate *handle;
|
|
#endif
|
|
|
|
handle = sndStart(var80095200, SFX_FIREEMPTY, NULL, -1, -1, -1, -1, -1);
|
|
|
|
if (handle) {
|
|
audioPostEvent(handle, 16, *(s32 *)&speed);
|
|
}
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
osSetThreadPri(0, prevpri);
|
|
#endif
|
|
}
|
|
break;
|
|
case WEAPON_UNARMED:
|
|
case WEAPON_COMBATKNIFE:
|
|
case WEAPON_GRENADE:
|
|
case WEAPON_NBOMB:
|
|
case WEAPON_TIMEDMINE:
|
|
case WEAPON_PROXIMITYMINE:
|
|
case WEAPON_REMOTEMINE:
|
|
case WEAPON_COMBATBOOST:
|
|
// No sound effect
|
|
break;
|
|
default:
|
|
// Default click sound effect
|
|
sndStart(var80095200, SFX_FIREEMPTY, NULL, -1, -1, -1, -1, -1);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Handle releasing trigger
|
|
if (!hand->triggeron) {
|
|
hand->mode = HANDMODE_NONE;
|
|
hand->count60 = 0;
|
|
hand->count = 0;
|
|
|
|
if (bgunSetState(handnum, HANDSTATE_IDLE)) {
|
|
return lvupdate;
|
|
}
|
|
|
|
bgunResetAnim(hand);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
s32 bgunTickIncAttack(struct handweaponinfo *info, s32 handnum, struct hand *hand, s32 lvupdate)
|
|
{
|
|
u32 stack;
|
|
struct weaponfunc *func = NULL;
|
|
bool finished = true;
|
|
u32 stack2;
|
|
|
|
if (info->definition) {
|
|
func = gsetGetWeaponFunction(&hand->gset);
|
|
}
|
|
|
|
if (func != NULL) {
|
|
switch (func->type & 0xff) {
|
|
case INVENTORYFUNCTYPE_SHOOT:
|
|
finished = bgunTickIncAttackingShoot(info, handnum, hand);
|
|
break;
|
|
case INVENTORYFUNCTYPE_THROW:
|
|
finished = bgunTickIncAttackingThrow(handnum, hand);
|
|
break;
|
|
case INVENTORYFUNCTYPE_MELEE:
|
|
finished = bgunTickIncAttackingMelee(handnum, hand);
|
|
break;
|
|
case INVENTORYFUNCTYPE_SPECIAL:
|
|
finished = bgunTickIncAttackingSpecial(hand);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (finished) {
|
|
if (hand->gset.weaponnum == WEAPON_REAPER && hand->triggeron) {
|
|
hand->gset.weaponfunc = FUNC_SECONDARY;
|
|
finished = false;
|
|
}
|
|
|
|
if (finished && bgunSetState(handnum, HANDSTATE_IDLE)) {
|
|
return lvupdate;
|
|
}
|
|
}
|
|
|
|
if (1);
|
|
if (1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool bgunIsReadyToSwitch(s32 handnum)
|
|
{
|
|
struct player *player = g_Vars.currentplayer;
|
|
|
|
// Dont switch if... something firing range related
|
|
if (g_FrIsValidWeapon
|
|
&& frGetWeaponBySlot(frGetSlot()) == player->hands[HAND_RIGHT].gset.weaponnum
|
|
&& g_Vars.currentplayer->gunctrl.unk1583_04 == false) {
|
|
return false;
|
|
}
|
|
|
|
// Don't switch right hand if left hand is about to auto switch
|
|
if (handnum == HAND_RIGHT
|
|
&& player->hands[HAND_LEFT].inuse
|
|
&& player->hands[HAND_LEFT].state == HANDSTATE_AUTOSWITCH
|
|
&& player->hands[HAND_LEFT].stateminor == 0) {
|
|
return false;
|
|
}
|
|
|
|
if (player->gunctrl.switchtoweaponnum >= 0) {
|
|
return true;
|
|
}
|
|
|
|
if (handnum == HAND_LEFT) {
|
|
if (handnum == HAND_LEFT) {
|
|
if (player->hands[HAND_RIGHT].state == HANDSTATE_RELOAD) {
|
|
return false;
|
|
}
|
|
|
|
if (player->hands[HAND_RIGHT].state == HANDSTATE_CHANGEFUNC) {
|
|
return false;
|
|
}
|
|
|
|
if (player->hands[HAND_RIGHT].state == HANDSTATE_ATTACK) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (player->hands[handnum].inuse && !player->gunctrl.dualwielding) {
|
|
return true;
|
|
}
|
|
|
|
if (!player->hands[handnum].inuse && player->gunctrl.dualwielding) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool bgunCanFreeWeapon(s32 handnum)
|
|
{
|
|
struct player *player = g_Vars.currentplayer;
|
|
|
|
if (player->hands[handnum].state == HANDSTATE_CHANGEGUN
|
|
&& player->hands[handnum].stateminor == 2
|
|
&& player->hands[handnum].count >= 3
|
|
&& player->gunctrl.unk1583_04 == false) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool bgun0f09bf44(s32 handnum)
|
|
{
|
|
bool result = true;
|
|
struct player *player = g_Vars.currentplayer;
|
|
|
|
if (!bgun0f09dd7c()) {
|
|
result = false;
|
|
}
|
|
|
|
if (player->gunctrl.switchtoweaponnum != -1) {
|
|
result = false;
|
|
}
|
|
|
|
if (handnum == HAND_LEFT && player->gunctrl.dualwielding != player->hands[handnum].inuse) {
|
|
result = false;
|
|
}
|
|
|
|
if (player->gunctrl.gunmemnew >= 0) {
|
|
result = false;
|
|
}
|
|
|
|
if (player->hands[1 - handnum].state == HANDSTATE_RELOAD) {
|
|
result = false;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
s32 bgunTickIncChangeGun(struct handweaponinfo *info, s32 handnum, struct hand *hand, s32 lvupdate)
|
|
{
|
|
u32 stack;
|
|
struct weapon *weapon = info->definition;
|
|
|
|
if (hand->statecycles == 0) {
|
|
if (g_Vars.normmplayerisrunning == false) {
|
|
hand->pausetime60 = 0;
|
|
} else {
|
|
hand->pausetime60 = 0;
|
|
}
|
|
}
|
|
|
|
// Handle unequip animation
|
|
if (hand->stateminor == 0) {
|
|
bool skipanim = false;
|
|
|
|
if (weaponHasFlag(info->weaponnum, WEAPONFLAG_THROWABLE)
|
|
&& (info->weaponnum != WEAPON_REMOTEMINE || handnum != HAND_LEFT)
|
|
&& bgun0f098ca0(0, info, hand) < 0) {
|
|
skipanim = true;
|
|
}
|
|
|
|
hand->count = 0;
|
|
|
|
if (!skipanim) {
|
|
if (weapon->unequip_animation
|
|
&& hand->inuse == true
|
|
&& !(hand->ejectstate != EJECTSTATE_INACTIVE && hand->ejecttype == EJECTTYPE_GUN)) {
|
|
if (hand->statecycles == 0) {
|
|
bgunStartAnimation(weapon->unequip_animation, handnum, hand);
|
|
} else if (hand->animmode == HANDANIMMODE_IDLE) {
|
|
hand->stateminor++;
|
|
}
|
|
} else {
|
|
hand->stateflags |= HANDSTATEFLAG_00000001;
|
|
|
|
if (hand->ejectstate == EJECTSTATE_INIT) {
|
|
return 0;
|
|
}
|
|
|
|
hand->stateminor++;
|
|
}
|
|
} else {
|
|
hand->stateminor++;
|
|
}
|
|
|
|
if (hand->stateminor == 1) {
|
|
hand->stateframes = 0;
|
|
}
|
|
}
|
|
|
|
// Handle possible delay between gun disappearing and new one equipping,
|
|
// as well as throwing the gun if that's what we're doing
|
|
if (hand->stateminor == 1) {
|
|
s32 delay = TICKS(16);
|
|
bool somebool = false;
|
|
u32 stack2;
|
|
|
|
hand->count = 0;
|
|
|
|
if (g_Vars.normmplayerisrunning) {
|
|
delay = TICKS(12);
|
|
}
|
|
|
|
if (weapon->unequip_animation && (hand->stateflags & HANDSTATEFLAG_00000001) == 0) {
|
|
delay = 1;
|
|
}
|
|
|
|
if (!hand->inuse) {
|
|
delay = 1;
|
|
}
|
|
|
|
if (hand->ejecttype == EJECTTYPE_GUN && (hand->ejectstate == EJECTSTATE_INIT || hand->ejectstate == EJECTSTATE_AIRBORNE)) {
|
|
somebool = true;
|
|
}
|
|
|
|
if (g_Vars.currentplayer->gunctrl.unk1583_04 == 1) {
|
|
somebool = true;
|
|
}
|
|
|
|
if (hand->stateframes >= delay) {
|
|
if (!somebool) {
|
|
if (g_Vars.mplayerisrunning && (IS8MB() || PLAYERCOUNT() != 1)) {
|
|
playermgrDeleteWeapon(handnum);
|
|
}
|
|
|
|
bgunFreeHeldRocket(handnum);
|
|
hand->mode = HANDMODE_6;
|
|
hand->stateminor++;
|
|
} else {
|
|
bgun0f099780(hand, 0.87252569198608f);
|
|
|
|
if (g_Vars.currentplayer->gunctrl.unk1583_04 == 1 && hand->inuse) {
|
|
hand->firing = true;
|
|
hand->attacktype = HANDATTACKTYPE_THROWPROJECTILE;
|
|
hand->gset.weaponfunc = FUNC_SECONDARY;
|
|
}
|
|
}
|
|
} else {
|
|
bgun0f099780(hand, hand->stateframes * 0.87252569198608f / delay);
|
|
}
|
|
}
|
|
|
|
// Handle equip animation
|
|
if (hand->stateminor == 2) {
|
|
hand->animmode = HANDANIMMODE_IDLE;
|
|
|
|
if (hand->pausechange == 0 || hand->pausetime60 <= hand->count60) {
|
|
if (hand->mode == HANDMODE_6) {
|
|
if (bgun0f09bf44(handnum)) {
|
|
hand->mode = HANDMODE_7;
|
|
|
|
if (!hand->inuse && bgunSetState(handnum, HANDSTATE_IDLE)) {
|
|
return lvupdate;
|
|
}
|
|
}
|
|
} else {
|
|
if (bgun0f09dd7c()) {
|
|
if (info->definition->equip_animation) {
|
|
bgunStartAnimation(info->definition->equip_animation, handnum, hand);
|
|
hand->unk0cc8_02 = true;
|
|
}
|
|
|
|
hand->mode = HANDMODE_8;
|
|
hand->stateminor++;
|
|
hand->count60 = 0;
|
|
hand->count = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (hand->mode == HANDMODE_6 || hand->mode == HANDMODE_7) {
|
|
bgun0f099780(hand, 0.87252569198608f);
|
|
}
|
|
}
|
|
|
|
// Handle delay if new weapon has no equip animation, and play sound
|
|
if (hand->stateminor == 3) {
|
|
s32 delay = TICKS(23);
|
|
|
|
if (g_Vars.normmplayerisrunning) {
|
|
delay = TICKS(12);
|
|
}
|
|
|
|
if (weaponHasFlag(hand->gset.weaponnum, WEAPONFLAG_00004000)) {
|
|
hand->animmode = HANDANIMMODE_IDLE;
|
|
} else if (weapon->equip_animation) {
|
|
delay = 1;
|
|
}
|
|
|
|
if (hand->count == 0) {
|
|
if (g_Vars.mplayerisrunning && (IS8MB() || PLAYERCOUNT() != 1)) {
|
|
playermgrCreateWeapon(handnum);
|
|
}
|
|
|
|
bgun0f098f8c(info, hand);
|
|
|
|
if (weaponHasFlag(info->weaponnum, WEAPONFLAG_THROWABLE)
|
|
&& (info->weaponnum != WEAPON_REMOTEMINE || handnum != HAND_LEFT)
|
|
&& bgun0f098ca0(0, info, hand) < 0
|
|
&& bgunSetState(handnum, HANDSTATE_AUTOSWITCH)) {
|
|
hand->stateminor = 1;
|
|
return lvupdate;
|
|
}
|
|
|
|
g_Vars.currentplayer->doautoselect = false;
|
|
|
|
if (g_Vars.lvupdate240 > 0
|
|
&& g_Vars.currentplayer->cameramode != CAMERAMODE_THIRDPERSON
|
|
&& bgun0f09dd7c()
|
|
&& !g_PlayerInvincible
|
|
&& !g_Vars.currentplayer->isdead) {
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
struct sndstate *handle1;
|
|
f32 speed1;
|
|
struct sndstate *handle2;
|
|
OSPri prevpri1;
|
|
f32 speed2;
|
|
OSPri prevpri2;
|
|
struct sndstate *handle3;
|
|
f32 speed3;
|
|
OSPri prevpri3;
|
|
#else
|
|
struct sndstate *handle1;
|
|
f32 speed1;
|
|
struct sndstate *handle2;
|
|
f32 speed2;
|
|
struct sndstate *handle3;
|
|
f32 speed3;
|
|
#endif
|
|
|
|
switch (info->weaponnum) {
|
|
case WEAPON_HORIZONSCANNER:
|
|
speed1 = 3.5f;
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
prevpri1 = osGetThreadPri(0);
|
|
osSetThreadPri(0, osGetThreadPri(&g_AudioManager.thread) + 1);
|
|
#endif
|
|
handle1 = sndStart(var80095200, SFX_EQUIP_HORIZONSCANNER, 0, -1, -1, -1, -1, -1);
|
|
|
|
if (handle1) {
|
|
audioPostEvent(handle1, 16, *(s32 *)&speed1);
|
|
}
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
osSetThreadPri(0, prevpri1);
|
|
#endif
|
|
break;
|
|
case WEAPON_LASER:
|
|
sndStart(var80095200, SFX_PICKUP_LASER, 0, -1, -1, -1, -1, -1);
|
|
break;
|
|
case WEAPON_COMBATKNIFE:
|
|
sndStart(var80095200, SFX_PICKUP_KNIFE, 0, -1, -1, -1, -1, -1);
|
|
break;
|
|
case WEAPON_REMOTEMINE:
|
|
if (handnum == HAND_RIGHT) {
|
|
sndStart(var80095200, SFX_PICKUP_MINE, 0, -1, -1, -1, -1, -1);
|
|
}
|
|
break;
|
|
case WEAPON_TIMEDMINE:
|
|
case WEAPON_PROXIMITYMINE:
|
|
case WEAPON_ECMMINE:
|
|
case WEAPON_DATAUPLINK:
|
|
case WEAPON_RTRACKER:
|
|
case WEAPON_PRESIDENTSCANNER:
|
|
case WEAPON_DOORDECODER:
|
|
case WEAPON_AUTOSURGEON:
|
|
case WEAPON_COMMSRIDER:
|
|
case WEAPON_TRACERBUG:
|
|
case WEAPON_TARGETAMPLIFIER:
|
|
sndStart(var80095200, SFX_PICKUP_MINE, 0, -1, -1, -1, -1, -1);
|
|
break;
|
|
case WEAPON_TRANQUILIZER:
|
|
case WEAPON_PSYCHOSISGUN:
|
|
speed2 = 1.5f;
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
prevpri2 = osGetThreadPri(0);
|
|
osSetThreadPri(0, osGetThreadPri(&g_AudioManager.thread) + 1);
|
|
#endif
|
|
|
|
handle2 = sndStart(var80095200, SFX_PICKUP_GUN, 0, -1, -1, -1, -1, -1);
|
|
|
|
if (handle2) {
|
|
audioPostEvent(handle2, 16, *(s32 *)&speed2);
|
|
}
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
osSetThreadPri(0, prevpri2);
|
|
#endif
|
|
break;
|
|
case WEAPON_REAPER:
|
|
speed3 = 0.85f;
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
prevpri3 = osGetThreadPri(0);
|
|
osSetThreadPri(0, osGetThreadPri(&g_AudioManager.thread) + 1);
|
|
#endif
|
|
|
|
handle3 = sndStart(var80095200, SFX_PICKUP_GUN, 0, -1, -1, -1, -1, -1);
|
|
|
|
if (handle3) {
|
|
audioPostEvent(handle3, 16, *(s32 *)&speed3);
|
|
}
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
osSetThreadPri(0, prevpri3);
|
|
#endif
|
|
break;
|
|
case WEAPON_NONE:
|
|
case WEAPON_UNARMED:
|
|
case WEAPON_LAPTOPGUN:
|
|
case WEAPON_CROSSBOW:
|
|
case WEAPON_GRENADE:
|
|
case WEAPON_NBOMB:
|
|
case WEAPON_COMBATBOOST:
|
|
case WEAPON_CLOAKINGDEVICE:
|
|
case WEAPON_EXPLOSIVES:
|
|
case WEAPON_SKEDARBOMB:
|
|
case WEAPON_DISGUISE40:
|
|
case WEAPON_DISGUISE41:
|
|
case WEAPON_FLIGHTPLANS:
|
|
case WEAPON_RESEARCHTAPE:
|
|
case WEAPON_BACKUPDISK:
|
|
case WEAPON_KEYCARD45:
|
|
case WEAPON_KEYCARD46:
|
|
case WEAPON_KEYCARD47:
|
|
case WEAPON_KEYCARD48:
|
|
case WEAPON_KEYCARD49:
|
|
case WEAPON_KEYCARD4A:
|
|
case WEAPON_KEYCARD4B:
|
|
case WEAPON_KEYCARD4C:
|
|
case WEAPON_SUITCASE:
|
|
case WEAPON_BRIEFCASE:
|
|
case WEAPON_NECKLACE:
|
|
case WEAPON_BRIEFCASE2:
|
|
// No equip sound
|
|
break;
|
|
default:
|
|
sndStart(var80095200, SFX_PICKUP_GUN, 0, -1, -1, -1, -1, -1);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (hand->count60 >= delay
|
|
|| !weaponGetModelNum2(info->weaponnum)
|
|
|| !weaponHasFlag(info->weaponnum, WEAPONFLAG_00000040)
|
|
|| weaponHasFlag(info->weaponnum, WEAPONFLAG_00000080)) {
|
|
hand->mode = HANDMODE_NONE;
|
|
hand->stateminor++;
|
|
|
|
if (weaponHasFlag(hand->gset.weaponnum, WEAPONFLAG_00004000) == 0) {
|
|
hand->unk0cc8_02 = false;
|
|
}
|
|
|
|
hand->count60 = 0;
|
|
hand->count = 0;
|
|
} else {
|
|
bgun0f099780(hand, (delay - hand->count60) * 0.87252569198608f / delay);
|
|
}
|
|
}
|
|
|
|
// Wait for equip animation to finish then go to idle state
|
|
if (hand->stateminor == 4) {
|
|
if (info->definition->equip_animation && !weaponHasFlag(hand->gset.weaponnum, WEAPONFLAG_00004000)) {
|
|
if (hand->animmode == HANDANIMMODE_IDLE) {
|
|
if (bgunSetState(handnum, HANDSTATE_IDLE)) {
|
|
return lvupdate;
|
|
}
|
|
}
|
|
} else {
|
|
if (bgunSetState(handnum, HANDSTATE_IDLE)) {
|
|
return lvupdate;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* This function may have implemented an early beta feature where the gun could
|
|
* be held at the side of the screen, pointed upwards. The feature was shown in
|
|
* a demo video but doesn't exist in any public version of the game.
|
|
*/
|
|
s32 bgunTickIncState2(struct handweaponinfo *info, s32 handnum, struct hand *hand, s32 lvupdate)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
s32 bgunTickInc(struct handweaponinfo *info, s32 handnum, s32 lvupdate)
|
|
{
|
|
s32 result = 0;
|
|
struct hand *hand = &g_Vars.currentplayer->hands[handnum];
|
|
s32 prevstate = hand->state;
|
|
|
|
hand->firing = false;
|
|
hand->flashon = false;
|
|
hand->stateframes += lvupdate;
|
|
|
|
if (g_Vars.lvupdate240 > 0) {
|
|
hand->count60 += g_Vars.lvupdate60;
|
|
hand->count++;
|
|
}
|
|
|
|
hand->useposrot = false;
|
|
|
|
switch (hand->state) {
|
|
case HANDSTATE_IDLE:
|
|
result = bgunTickIncIdle(info, handnum, hand, lvupdate);
|
|
break;
|
|
case HANDSTATE_RELOAD:
|
|
result = bgunTickIncReload(info, handnum, hand, lvupdate);
|
|
break;
|
|
case HANDSTATE_ATTACK:
|
|
result = bgunTickIncAttack(info, handnum, hand, lvupdate);
|
|
break;
|
|
case HANDSTATE_2:
|
|
result = bgunTickIncState2(info, handnum, hand, lvupdate);
|
|
break;
|
|
case HANDSTATE_CHANGEGUN:
|
|
result = bgunTickIncChangeGun(info, handnum, hand, lvupdate);
|
|
break;
|
|
case HANDSTATE_ATTACKEMPTY:
|
|
result = bgunTickIncAttackEmpty(info, handnum, hand, lvupdate);
|
|
break;
|
|
case HANDSTATE_AUTOSWITCH:
|
|
result = bgunTickIncAutoSwitch(info, handnum, hand, lvupdate);
|
|
break;
|
|
case HANDSTATE_CHANGEFUNC:
|
|
result = bgunTickIncChangeFunc(info, handnum, hand, lvupdate);
|
|
break;
|
|
}
|
|
|
|
hand->statelastframe = hand->stateframes;
|
|
|
|
if (hand->state != prevstate) {
|
|
hand->statelastframe = -result;
|
|
} else {
|
|
hand->stateframes -= result;
|
|
hand->statecycles++;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
bool bgunSetState(s32 handnum, s32 state)
|
|
{
|
|
bool valid = true;
|
|
struct hand *hand = &g_Vars.currentplayer->hands[handnum];
|
|
|
|
// Sanity check - don't allow changing function if there is no other
|
|
if (state == HANDSTATE_CHANGEFUNC && weaponGetFunction(&hand->gset, 1 - hand->gset.weaponfunc) == NULL) {
|
|
valid = false;
|
|
}
|
|
|
|
if (valid) {
|
|
hand->state = state;
|
|
hand->stateframes = 0;
|
|
hand->stateflags = 0;
|
|
hand->statecycles = 0;
|
|
hand->stateminor = 0;
|
|
hand->statelastframe = 0;
|
|
}
|
|
|
|
return valid;
|
|
}
|
|
|
|
void bgunTickHand(s32 handnum)
|
|
{
|
|
struct hand *hand = &g_Vars.currentplayer->hands[handnum];
|
|
struct handweaponinfo info;
|
|
s32 lvupdate;
|
|
s32 i = 20;
|
|
|
|
if (handnum);
|
|
if (handnum);
|
|
if (handnum);
|
|
if (handnum);
|
|
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
if (handnum);
|
|
#endif
|
|
|
|
bgunGetWeaponInfo(&info, handnum);
|
|
|
|
lvupdate = g_Vars.lvupdate60;
|
|
|
|
hand->animframeinc = g_Vars.lvupdate60;
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
hand->animframeincfreal = modelGetAbsAnimSpeed(&hand->gunmodel) * PALUPF(hand->animframeinc);
|
|
#else
|
|
hand->animframeincfreal += PALUPF(g_Vars.lvupdate60);
|
|
#endif
|
|
|
|
while (i >= 0) {
|
|
lvupdate = bgunTickInc(&info, handnum, lvupdate);
|
|
i--;
|
|
|
|
if (lvupdate <= 0) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void bgunTickSwitch(void)
|
|
{
|
|
bgunTickSwitch2();
|
|
}
|
|
|
|
void bgunInitHandAnims(void)
|
|
{
|
|
struct hand *hand;
|
|
s32 i;
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
if (i == 0) {
|
|
hand = &g_Vars.currentplayer->hands[1];
|
|
} else {
|
|
hand = &g_Vars.currentplayer->hands[0];
|
|
}
|
|
|
|
hand->gangstarot = 0;
|
|
hand->state = HANDSTATE_IDLE;
|
|
hand->animload = -1;
|
|
hand->animmode = HANDANIMMODE_IDLE;
|
|
|
|
animInit(&hand->anim);
|
|
|
|
hand->gunmodel.anim = &hand->anim;
|
|
hand->handmodel.anim = &hand->anim;
|
|
}
|
|
}
|
|
|
|
f32 bgunGetNoiseRadius(s32 handnum)
|
|
{
|
|
return g_Vars.currentplayer->hands[handnum].noiseradius;
|
|
}
|
|
|
|
void bgunDecreaseNoiseRadius(void)
|
|
{
|
|
struct player *player = g_Vars.currentplayer;
|
|
f32 consideramount;
|
|
struct gset gsetleft;
|
|
struct gset gsetright;
|
|
struct noisesettings noisesettingsleft;
|
|
struct noisesettings noisesettingsright;
|
|
f32 subamount;
|
|
|
|
gsetPopulateFromCurrentPlayer(HAND_LEFT, &gsetleft);
|
|
gsetPopulateFromCurrentPlayer(HAND_RIGHT, &gsetright);
|
|
|
|
gsetGetNoiseSettings(&gsetleft, &noisesettingsleft);
|
|
gsetGetNoiseSettings(&gsetright, &noisesettingsright);
|
|
|
|
// Right hand
|
|
if (bgunIsFiring(HAND_RIGHT)) {
|
|
player->hands[HAND_RIGHT].noiseradius += noisesettingsright.incradius;
|
|
|
|
if (player->hands[HAND_RIGHT].noiseradius > noisesettingsright.maxradius) {
|
|
player->hands[HAND_RIGHT].noiseradius = noisesettingsright.maxradius;
|
|
}
|
|
}
|
|
|
|
subamount = g_Vars.lvupdate60freal * noisesettingsright.incradius / (noisesettingsright.decbasespeed * 60.0f);
|
|
consideramount = (player->hands[HAND_RIGHT].noiseradius - noisesettingsright.minradius) * g_Vars.lvupdate60freal / (noisesettingsright.decremspeed * 60.0f);
|
|
|
|
if (consideramount > subamount) {
|
|
subamount = consideramount;
|
|
}
|
|
|
|
player->hands[HAND_RIGHT].noiseradius -= subamount;
|
|
|
|
if (player->hands[HAND_RIGHT].noiseradius < noisesettingsright.minradius) {
|
|
player->hands[HAND_RIGHT].noiseradius = noisesettingsright.minradius;
|
|
}
|
|
|
|
// Left hand
|
|
if (bgunIsFiring(HAND_LEFT)) {
|
|
player->hands[HAND_LEFT].noiseradius += noisesettingsleft.incradius;
|
|
|
|
if (player->hands[HAND_LEFT].noiseradius > noisesettingsleft.maxradius) {
|
|
player->hands[HAND_LEFT].noiseradius = noisesettingsleft.maxradius;
|
|
}
|
|
}
|
|
|
|
subamount = g_Vars.lvupdate60freal * noisesettingsleft.incradius / (noisesettingsleft.decbasespeed * 60.0f);
|
|
consideramount = (player->hands[HAND_LEFT].noiseradius - noisesettingsleft.minradius) * g_Vars.lvupdate60freal / (noisesettingsleft.decremspeed * 60.0f);
|
|
|
|
if (consideramount > subamount) {
|
|
subamount = consideramount;
|
|
}
|
|
|
|
player->hands[HAND_LEFT].noiseradius -= subamount;
|
|
|
|
if (player->hands[HAND_LEFT].noiseradius < noisesettingsleft.minradius) {
|
|
player->hands[HAND_LEFT].noiseradius = noisesettingsleft.minradius;
|
|
}
|
|
}
|
|
|
|
void bgunCalculateBlend(s32 handnum)
|
|
{
|
|
s32 sp60[2];
|
|
s32 sp58[2];
|
|
struct weapon *weapon = weaponFindById(bgunGetWeaponNum(handnum));
|
|
f32 sway = weapon->sway;
|
|
struct player *player = g_Vars.currentplayer;
|
|
|
|
sp60[handnum] = (player->hands[handnum].curblendpos + 2) % 4;
|
|
sp58[handnum] = (player->hands[handnum].curblendpos + 1) % 4;
|
|
player->hands[handnum].curblendpos = sp58[handnum];
|
|
|
|
player->hands[handnum].blendlook[sp60[handnum]].x = (RANDOMFRAC() - 0.5f) * 0.08f * sway;
|
|
player->hands[handnum].blendlook[sp60[handnum]].y = (RANDOMFRAC() - 0.5f) * 0.1f * sway;
|
|
player->hands[handnum].blendlook[sp60[handnum]].z = -1;
|
|
|
|
player->hands[handnum].blendup[sp60[handnum]].x = (RANDOMFRAC() - 0.5f) * 0.1f * sway;
|
|
player->hands[handnum].blendup[sp60[handnum]].y = 1;
|
|
player->hands[handnum].blendup[sp60[handnum]].z = (RANDOMFRAC() - 0.5f) * 0.1f * sway;
|
|
|
|
player->hands[handnum].blendpos[sp60[handnum]].x = (RANDOMFRAC() * 0.75f) + 1.5f;
|
|
player->hands[handnum].blendpos[sp60[handnum]].y = (2 + RANDOMFRAC()) * player->hands[handnum].blendscale1;
|
|
player->hands[handnum].blendpos[sp60[handnum]].z = (RANDOMFRAC() - 0.5f) * 2.5f;
|
|
|
|
if (player->hands[handnum].sideflag < 0) {
|
|
player->hands[handnum].blendpos[sp60[handnum]].x *= -1;
|
|
|
|
if (player->hands[handnum].sideflag == -2) {
|
|
player->hands[handnum].sideflag = 1;
|
|
} else {
|
|
player->hands[handnum].sideflag = -2;
|
|
}
|
|
} else {
|
|
if (player->hands[handnum].sideflag == 2) {
|
|
player->hands[handnum].sideflag = -1;
|
|
} else {
|
|
player->hands[handnum].sideflag = 2;
|
|
}
|
|
}
|
|
|
|
player->hands[handnum].blendscale1 = -player->hands[handnum].blendscale1;
|
|
}
|
|
|
|
void bgunUpdateBlend(struct hand *hand, s32 handnum)
|
|
{
|
|
u32 stack[3];
|
|
s32 i;
|
|
struct coord sp5c = {0, 0, 0};
|
|
struct coord sp50 = {0, 0, -1};
|
|
struct coord sp44 = {0, 1, 0};
|
|
s32 pos = hand->curblendpos;
|
|
struct player *player = g_Vars.currentplayer;
|
|
|
|
func0f096b70(&hand->blendpos[(pos + 3) % 4], &hand->blendpos[pos], &hand->blendpos[(pos + 1) % 4], &hand->blendpos[(pos + 2) % 4], hand->dampt, &sp5c);
|
|
func0f096b70(&hand->blendlook[(pos + 3) % 4], &hand->blendlook[pos], &hand->blendlook[(pos + 1) % 4], &hand->blendlook[(pos + 2) % 4], hand->dampt, &sp50);
|
|
func0f096b70(&hand->blendup[(pos + 3) % 4], &hand->blendup[pos], &hand->blendup[(pos + 1) % 4], &hand->blendup[(pos + 2) % 4], hand->dampt, &sp44);
|
|
|
|
sp5c.x *= player->gunposamplitude;
|
|
sp5c.y *= player->gunposamplitude;
|
|
sp5c.z *= player->gunposamplitude;
|
|
|
|
sp5c.x += hand->adjustdamp.x;
|
|
sp5c.y += hand->adjustdamp.y;
|
|
|
|
sp5c.x += handGetXShift(handnum);
|
|
|
|
for (i = 0; i < g_Vars.lvupdate240; i++) {
|
|
hand->damppossum.x = (PAL ? 0.9847f : 0.9872f) * hand->damppossum.x + sp5c.f[0];
|
|
hand->damppossum.y = (PAL ? 0.9847f : 0.9872f) * hand->damppossum.y + sp5c.f[1];
|
|
hand->damppossum.z = (PAL ? 0.9847f : 0.9872f) * hand->damppossum.z + sp5c.f[2];
|
|
|
|
hand->damplooksum.x = (PAL ? 0.9847f : 0.9872f) * hand->damplooksum.x + sp50.f[0];
|
|
hand->damplooksum.y = (PAL ? 0.9847f : 0.9872f) * hand->damplooksum.y + sp50.f[1];
|
|
hand->damplooksum.z = (PAL ? 0.9847f : 0.9872f) * hand->damplooksum.z + sp50.f[2];
|
|
|
|
hand->dampupsum.x = (PAL ? 0.9847f : 0.9872f) * hand->dampupsum.x + sp44.f[0];
|
|
hand->dampupsum.y = (PAL ? 0.9847f : 0.9872f) * hand->dampupsum.y + sp44.f[1];
|
|
hand->dampupsum.z = (PAL ? 0.9847f : 0.9872f) * hand->dampupsum.z + sp44.f[2];
|
|
}
|
|
|
|
hand->damppos.x = hand->damppossum.x * (PAL ? 0.01529997587204f : 0.012799978f) * 2;
|
|
hand->damppos.y = hand->damppossum.y * (PAL ? 0.01529997587204f : 0.012799978f) * 2;
|
|
hand->damppos.z = hand->damppossum.z * (PAL ? 0.01529997587204f : 0.012799978f) * 2;
|
|
|
|
hand->damplook.x = hand->damplooksum.x * (PAL ? 0.01529997587204f : 0.012799978f);
|
|
hand->damplook.y = hand->damplooksum.y * (PAL ? 0.01529997587204f : 0.012799978f);
|
|
hand->damplook.z = hand->damplooksum.z * (PAL ? 0.01529997587204f : 0.012799978f);
|
|
|
|
hand->dampup.x = hand->dampupsum.x * (PAL ? 0.01529997587204f : 0.012799978f);
|
|
hand->dampup.y = hand->dampupsum.y * (PAL ? 0.01529997587204f : 0.012799978f);
|
|
hand->dampup.z = hand->dampupsum.z * (PAL ? 0.01529997587204f : 0.012799978f);
|
|
}
|
|
|
|
u32 var80070158 = 0x04e50764;
|
|
u32 var8007015c = 0x05360529;
|
|
u32 var80070160 = 0x0531052a;
|
|
u32 var80070164 = 0x052b052c;
|
|
u32 var80070168 = 0x052c052d;
|
|
u32 var8007016c = 0x052b052b;
|
|
u32 var80070170 = 0x052e052f;
|
|
u32 var80070174 = 0x052f0530;
|
|
u32 var80070178 = 0x05310532;
|
|
u32 var8007017c = 0x05320533;
|
|
u32 var80070180 = 0x05340535;
|
|
u32 var80070184 = 0x05360537;
|
|
u32 var80070188 = 0x05380530;
|
|
u32 var8007018c = 0x0539053a;
|
|
u32 var80070190 = 0x0532053b;
|
|
u32 var80070194 = 0x05310766;
|
|
u32 var80070198 = 0x07670768;
|
|
u32 var8007019c = 0x0769076a;
|
|
u32 var800701a0 = 0x076b076c;
|
|
u32 var800701a4 = 0x076d0000;
|
|
u32 var800701a8 = 0x0000ffff;
|
|
|
|
void bgun0f09d8dc(f32 breathing, f32 arg1, f32 arg2, f32 arg3, f32 arg4)
|
|
{
|
|
f32 dampt[2];
|
|
struct player *player = g_Vars.currentplayer;
|
|
u32 stack;
|
|
s32 i;
|
|
f32 sp50 = arg2;
|
|
f32 sp4c;
|
|
u32 stack2;
|
|
|
|
if (sp50 < 0.0f) {
|
|
sp50 = -sp50;
|
|
}
|
|
|
|
if (arg1 > 0.8f) {
|
|
player->gunposamplitude = 1.0f;
|
|
} else {
|
|
if (arg1 > 0.1f) {
|
|
f32 tmp = 1.0f - cosf((arg1 - 0.1f) * M_BADTAU / 2.8f);
|
|
player->gunposamplitude = 0.8f * tmp + 0.2f;
|
|
} else {
|
|
player->gunposamplitude = 0.1f;
|
|
}
|
|
}
|
|
|
|
if (bmoveGetCrouchPos() != CROUCHPOS_SQUAT) {
|
|
if (player->gunposamplitude < 0.3f * g_Vars.currentplayer->bondbreathing) {
|
|
player->gunposamplitude = 0.3f * g_Vars.currentplayer->bondbreathing;
|
|
}
|
|
}
|
|
|
|
if (player->gunposamplitude < 0.5f * sp50) {
|
|
player->gunposamplitude = 0.5f * sp50;
|
|
}
|
|
|
|
for (i = 0; i < g_Vars.lvupdate240; i++) {
|
|
player->gunampsum = (PAL ? 0.9847f : 0.9872f) * player->gunampsum + player->gunposamplitude;
|
|
}
|
|
|
|
player->gunposamplitude = (PAL ? 0.01529997587204f : 0.012799978256226f) * player->gunampsum;
|
|
|
|
if (breathing < 0.016666667535901f * sp50) {
|
|
breathing = 0.016666667535901f * sp50;
|
|
}
|
|
|
|
for (i = 0; i < g_Vars.lvupdate240; i++) {
|
|
player->cyclesum = (PAL ? 0.9847f : 0.9872f) * player->cyclesum + breathing;
|
|
}
|
|
|
|
breathing = player->cyclesum * (PAL ? 0.01529997587204f : 0.012799978256226f);
|
|
sp4c = breathing * g_Vars.lvupdate60freal;
|
|
dampt[0] = player->hands[0].dampt + sp4c;
|
|
|
|
while (dampt[0] >= 1.0f) {
|
|
bgunCalculateBlend(HAND_RIGHT);
|
|
dampt[0] -= 1.0f;
|
|
player->syncoffset++;
|
|
}
|
|
|
|
player->synccount += g_Vars.lvupdate60freal;
|
|
|
|
if (player->synccount > 60.0f) {
|
|
player->synccount = 0.0f;
|
|
player->syncchange = (RANDOMFRAC() - 0.5f) * 0.2f / 60.0f;
|
|
}
|
|
|
|
if (player->syncchange + sp4c > 0.0f) {
|
|
player->gunsync += player->syncchange;
|
|
}
|
|
|
|
if (player->gunsync > 0.5f) {
|
|
player->gunsync = 0.5f;
|
|
} else if (player->gunsync < -0.5f) {
|
|
player->gunsync = -0.5f;
|
|
} else if (player->gunsync < 0.1f && player->gunsync > -0.1f) {
|
|
if (player->gunsync > 0.0f) {
|
|
player->gunsync = -0.1f;
|
|
} else {
|
|
player->gunsync = 0.1f;
|
|
}
|
|
}
|
|
|
|
dampt[1] = dampt[0] + player->syncoffset + player->gunsync;
|
|
|
|
while (dampt[1] >= 1.0f) {
|
|
bgunCalculateBlend(HAND_LEFT);
|
|
dampt[1] -= 1.0f;
|
|
player->syncoffset--;
|
|
}
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
player->hands[i].dampt = dampt[i];
|
|
player->hands[i].adjustdamp.x = -1.75f * arg3 + -0.8f * arg4;
|
|
player->hands[i].adjustdamp.y = -2.0f * arg2;
|
|
}
|
|
}
|
|
|
|
bool bgun0f09dd7c(void)
|
|
{
|
|
if (g_Vars.currentplayer->gunctrl.gunmemowner) {
|
|
return false;
|
|
}
|
|
|
|
return g_Vars.currentplayer->gunctrl.gunmemtype == 0
|
|
|| (g_Vars.currentplayer->gunctrl.gunmemnew < 0
|
|
&& g_Vars.currentplayer->gunctrl.masterloadstate == MASTERLOADSTATE_LOADED);
|
|
}
|
|
|
|
u32 bgunGetGunMemType(void)
|
|
{
|
|
return g_Vars.currentplayer->gunctrl.gunmemtype;
|
|
}
|
|
|
|
struct modeldef *bgun0f09dddc(void)
|
|
{
|
|
return g_Vars.currentplayer->gunctrl.gunmodeldef;
|
|
}
|
|
|
|
u8 *bgunGetGunMem(void)
|
|
{
|
|
return g_Vars.currentplayer->gunctrl.gunmem;
|
|
}
|
|
|
|
u32 bgunCalculateGunMemCapacity(void)
|
|
{
|
|
if (IS4MB() && PLAYERCOUNT() == 2) {
|
|
return var800700ac;
|
|
}
|
|
|
|
if (PLAYERCOUNT() == 1) {
|
|
switch (g_Vars.stagenum) {
|
|
case STAGE_CHICAGO:
|
|
case STAGE_AIRBASE:
|
|
case STAGE_VILLA:
|
|
case STAGE_AIRFORCEONE:
|
|
case STAGE_ATTACKSHIP:
|
|
return var800700a8 + 0x6400;
|
|
}
|
|
}
|
|
|
|
return var800700a8;
|
|
}
|
|
|
|
void bgunFreeGunMem(void)
|
|
{
|
|
g_Vars.currentplayer->gunctrl.gunmemowner = GUNMEMOWNER_FREE;
|
|
}
|
|
|
|
void bgunSetGunMemWeapon(s32 weaponnum)
|
|
{
|
|
struct player *player = g_Vars.currentplayer;
|
|
|
|
if (player->gunctrl.gunmemowner == GUNMEMOWNER_BONDGUN) {
|
|
player->gunctrl.masterloadstate = MASTERLOADSTATE_FLUX;
|
|
player->gunctrl.gunloadstate = GUNLOADSTATE_FLUX;
|
|
player->gunctrl.gunmemnew = weaponnum;
|
|
player->gunctrl.gunlocktimer = -1;
|
|
} else {
|
|
player->gunctrl.gunmemnew = weaponnum;
|
|
}
|
|
}
|
|
|
|
void bgun0f09df9c(void)
|
|
{
|
|
s32 i;
|
|
struct casing *end;
|
|
struct casing *casing;
|
|
|
|
g_Vars.currentplayer->gunctrl.handfilenum = 0xffff;
|
|
g_Vars.currentplayer->gunctrl.handmodeldef = NULL;
|
|
g_Vars.currentplayer->gunctrl.unk15a0 = 0;
|
|
g_Vars.currentplayer->gunctrl.unk15a4 = 0;
|
|
g_Vars.currentplayer->gunctrl.masterloadstate = MASTERLOADSTATE_FLUX;
|
|
g_Vars.currentplayer->gunctrl.gunloadstate = GUNLOADSTATE_FLUX;
|
|
|
|
end = g_Casings + ARRAYCOUNT(g_Casings);
|
|
casing = g_Casings;
|
|
|
|
while (casing < end) {
|
|
casing->modeldef = NULL;
|
|
casing++;
|
|
}
|
|
|
|
g_CasingsActive = false;
|
|
}
|
|
|
|
bool bgun0f09e004(s32 newowner)
|
|
{
|
|
struct player *player = g_Vars.currentplayer;
|
|
|
|
if (player->gunctrl.gunmemowner == newowner) {
|
|
return true;
|
|
}
|
|
|
|
if (player->gunctrl.gunlocktimer < 0) {
|
|
player->gunctrl.gunlocktimer--;
|
|
|
|
if (player->gunctrl.gunlocktimer < -2) {
|
|
player->gunctrl.gunlocktimer = 0;
|
|
player->gunctrl.gunmemowner = newowner;
|
|
return true;
|
|
}
|
|
} else {
|
|
bool unlock = false;
|
|
|
|
switch (player->gunctrl.gunmemowner) {
|
|
case GUNMEMOWNER_BONDGUN:
|
|
if (player->gunctrl.gunmemtype != -1) {
|
|
player->gunctrl.gunmemnew = player->gunctrl.gunmemtype;
|
|
}
|
|
|
|
player->gunctrl.gunmemtype = -1;
|
|
bgun0f09df9c();
|
|
player->gunctrl.unk1583_06 = true;
|
|
unlock = true;
|
|
break;
|
|
case GUNMEMOWNER_CHRBODY:
|
|
if (g_Vars.mplayerisrunning) {
|
|
unlock = true;
|
|
}
|
|
|
|
if (!player->haschrbody) {
|
|
unlock = true;
|
|
}
|
|
|
|
if (newowner == GUNMEMOWNER_INVMENU && var8009dfc0 != 0) {
|
|
unlock = true;
|
|
playerRemoveChrBody();
|
|
}
|
|
break;
|
|
case GUNMEMOWNER_3:
|
|
unlock = true;
|
|
break;
|
|
case GUNMEMOWNER_CHANGING:
|
|
case GUNMEMOWNER_FREE:
|
|
unlock = true;
|
|
break;
|
|
}
|
|
|
|
if (unlock) {
|
|
player->gunctrl.gunlocktimer = -1;
|
|
player->gunctrl.gunmemowner = GUNMEMOWNER_CHANGING;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* This function loads resources for a gun change.
|
|
*
|
|
* The caller sets properties in the player's gunctrl struct which tell this
|
|
* function what to load, where the gunmem is that it can use, and how much
|
|
* gunmem there is. This function is then called a couple of times on subsequent
|
|
* ticks, loading data incrementally to avoid a significant lag spike.
|
|
*
|
|
* The function keeps track of its progress in the gunloadstate property, and
|
|
* updates the gunmem properties to reflect its usage.
|
|
*
|
|
* The first call loads the model definition from the ROM and decompresses it.
|
|
* The second call loads and decompress to 3 textures.
|
|
* This continues on further calls until all textures are loaded.
|
|
* The final call does some one-off processing on the model's display lists.
|
|
*
|
|
* Although the name contains "Gun", it's used for more than just the gun model.
|
|
* It's used for the hand model, the gun model and the cartridge model.
|
|
*/
|
|
void bgunTickGunLoad(void)
|
|
{
|
|
s32 i;
|
|
s32 numthistick;
|
|
u32 remaining;
|
|
s32 padding;
|
|
u32 allocsize;
|
|
u32 loadsize;
|
|
u32 ptr;
|
|
struct player *player = g_Vars.currentplayer;
|
|
struct modeldef *modeldef;
|
|
struct fileinfo *fileinfo;
|
|
struct fileinfo *gunfileinfo;
|
|
s32 newvalue;
|
|
u32 end;
|
|
u32 stack;
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
u32 stack2;
|
|
#endif
|
|
|
|
if (player->gunctrl.gunloadstate == GUNLOADSTATE_MODEL) {
|
|
osSyncPrintf("BriGun: BriGunLoadTick process GUN_LOADSTATE_LOAD_OBJ\n");
|
|
|
|
ptr = *player->gunctrl.loadmemptr;
|
|
remaining = *player->gunctrl.loadmemremaining;
|
|
|
|
// Align ptr to the next 16 byte boundary
|
|
if (ptr % 16) {
|
|
padding = 16 - (ptr % 16);
|
|
ptr += padding;
|
|
remaining -= padding;
|
|
}
|
|
|
|
*player->gunctrl.loadmemptr = ptr;
|
|
*player->gunctrl.loadmemremaining = remaining;
|
|
|
|
loadsize = ALIGN64(fileGetInflatedSize(player->gunctrl.loadfilenum)) + 0x8000;
|
|
|
|
osSyncPrintf("BriGun: Loading - %s, pMem 0x%08x Size %d\n");
|
|
|
|
if (loadsize > remaining) {
|
|
osSyncPrintf("BriGun: Warning: LoadSize > MemSize, clamping decomp. buffer from %d to %d (%d Bytes)\n", allocsize, remaining, remaining);
|
|
loadsize = remaining;
|
|
}
|
|
|
|
// Load the model file to ptr
|
|
g_LoadType = LOADTYPE_GUN;
|
|
|
|
osSyncPrintf("BriGun: obLoadto at 0x%08x, size %d\n", ptr, loadsize);
|
|
|
|
modeldef = fileLoadToAddr(player->gunctrl.loadfilenum, FILELOADMETHOD_EXTRAMEM, (u8 *)ptr, loadsize);
|
|
|
|
// Reserve some space for textures
|
|
allocsize = fileGetLoadedSize(player->gunctrl.loadfilenum) + 0xe00;
|
|
|
|
osSyncPrintf("BriGun: Used size %d (Ob Size %d)\n");
|
|
osSyncPrintf("BriGun: block len %d usedsize %d\n");
|
|
osSyncPrintf("BriGun: obln ram_len %d block_len %d\n");
|
|
osSyncPrintf("BriGun: new used size %d\n");
|
|
|
|
fileGetLoadedSize(player->gunctrl.loadfilenum);
|
|
|
|
fileinfo = &g_FileInfo[player->gunctrl.loadfilenum];
|
|
fileinfo->allocsize = allocsize;
|
|
end = ALIGN16((s32)ptr + allocsize);
|
|
allocsize = end - ptr;
|
|
if (1);
|
|
remaining -= allocsize;
|
|
|
|
osSyncPrintf("BriGun: Texture Block at 0x%08x size %d, endp 0x%08x\n");
|
|
|
|
texInitPool(&player->gunctrl.unk15c0, (u8 *)end, remaining);
|
|
|
|
// Tidy up the model
|
|
modelPromoteTypeToPointer(modeldef);
|
|
modelPromoteOffsetsToPointers(modeldef, 0x05000000, (uintptr_t)modeldef);
|
|
|
|
*player->gunctrl.loadtomodeldef = modeldef;
|
|
|
|
player->gunctrl.nexttexturetoload = 0;
|
|
player->gunctrl.fileinfo = *fileinfo;
|
|
|
|
osSyncPrintf("BriGun: Set Load State: GUN_LOADSTATE_DECOMPRESS_TEXTURES\n");
|
|
player->gunctrl.gunloadstate = GUNLOADSTATE_TEXTURES;
|
|
return;
|
|
}
|
|
|
|
if (player->gunctrl.gunloadstate == GUNLOADSTATE_TEXTURES) {
|
|
osSyncPrintf("BriGun: BriGunLoadTick process GUN_LOADSTATE_DECOMPRESS_TEXTURES\n");
|
|
|
|
gunfileinfo = &player->gunctrl.fileinfo;
|
|
fileinfo = &g_FileInfo[player->gunctrl.loadfilenum];
|
|
*fileinfo = *gunfileinfo;
|
|
modeldef = *player->gunctrl.loadtomodeldef;
|
|
|
|
// Load textures - up to 3 per call
|
|
numthistick = 0;
|
|
|
|
for (i = player->gunctrl.nexttexturetoload; i < modeldef->numtexconfigs; i++) {
|
|
osSyncPrintf("BriGun: at texture %d\n", i);
|
|
|
|
if (modeldef->texconfigs[i].texturenum < NUM_TEXTURES) {
|
|
osSyncPrintf("BriGun: Uncompress %d of %d\n", i, modeldef->numtexconfigs);
|
|
texLoad(&modeldef->texconfigs[i].texturenum, &player->gunctrl.unk15c0, true);
|
|
modeldef->texconfigs[i].unk0b = 1;
|
|
}
|
|
|
|
numthistick++;
|
|
|
|
if (numthistick == 3) {
|
|
return;
|
|
}
|
|
|
|
// @bug: This should be incremented prior to the return, otherwise
|
|
// subsequent ticks will waste time loading a texture that's already
|
|
// been loaded.
|
|
player->gunctrl.nexttexturetoload++;
|
|
}
|
|
|
|
*gunfileinfo = *fileinfo;
|
|
|
|
osSyncPrintf("BriGun: Set Load State: GUN_LOADSTATE_DECOMPRESS_DLS\n");
|
|
player->gunctrl.gunloadstate = GUNLOADSTATE_DLS;
|
|
return;
|
|
}
|
|
|
|
if (player->gunctrl.gunloadstate == GUNLOADSTATE_DLS) {
|
|
osSyncPrintf("BriGun: BriGunLoadTick process GUN_LOADSTATE_DECOMPRESS_DLS\n");
|
|
|
|
fileinfo = &g_FileInfo[player->gunctrl.loadfilenum];
|
|
*fileinfo = player->gunctrl.fileinfo;
|
|
modeldef = *player->gunctrl.loadtomodeldef;
|
|
|
|
modeldef0f1a7560(modeldef, player->gunctrl.loadfilenum, 0x05000000, modeldef, &player->gunctrl.unk15c0, false);
|
|
|
|
fileGetInflatedSize(player->gunctrl.loadfilenum);
|
|
fileGetLoadedSize(player->gunctrl.loadfilenum);
|
|
fileGetLoadedSize(player->gunctrl.loadfilenum);
|
|
fileGetLoadedSize(player->gunctrl.loadfilenum);
|
|
|
|
modelAllocateRwData(modeldef);
|
|
|
|
osSyncPrintf("BriGun: propgfx_decompress 0x%08x\n");
|
|
osSyncPrintf("BriGun: DL waste space %d from %d (Used %d, Ramlen %d, ObSize %d)\n");
|
|
osSyncPrintf("Increase GUNSAVESIZE to %d!!!\n");
|
|
|
|
newvalue = ALIGN64(texGetPoolLeftPos(&player->gunctrl.unk15c0));
|
|
remaining = *player->gunctrl.loadmemremaining;
|
|
remaining -= (s32)(newvalue - *player->gunctrl.loadmemptr);
|
|
|
|
*player->gunctrl.loadmemptr = newvalue;
|
|
*player->gunctrl.loadmemremaining = remaining;
|
|
|
|
osSyncPrintf("BriGun: Set Load State: GUN_LOADSTATE_LOADED\n");
|
|
player->gunctrl.gunloadstate = GUNLOADSTATE_LOADED;
|
|
|
|
#if PIRACYCHECKS
|
|
{
|
|
s32 *ptr = (s32 *)&tagsReset;
|
|
s32 *end = (s32 *)&tagFindById;
|
|
u32 checksum = 0;
|
|
|
|
while (ptr < end) {
|
|
checksum -= ~*ptr;
|
|
ptr++;
|
|
}
|
|
|
|
if (checksum != CHECKSUM_PLACEHOLDER) {
|
|
ptr = (s32 *)&tagsReset + 3;
|
|
|
|
if (1);
|
|
end = &ptr[7];
|
|
|
|
while (ptr < end) {
|
|
*ptr |= 0xff;
|
|
ptr++;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
const char var7f1abcd8[] = "need a new gun loading (lock %d gunmemnew %d)\n";
|
|
const char var7f1abd08[] = "loading gun file: %d type: %d\n";
|
|
const char var7f1abd28[] = "BriGun: Process MASTER_GUN_LOADSTATE_FLUX\n";
|
|
const char var7f1abd54[] = "BriGun: Set Master State: MASTER_GUN_LOADSTATE_HANDS\n";
|
|
const char var7f1abd8c[] = "BriGun: Process MASTER_GUN_LOADSTATE_HANDS\n";
|
|
const char var7f1abdb8[] = "BriGun: Setup Hand Load\n";
|
|
const char var7f1abdd4[] = "Hand : Using cached hands\n";
|
|
const char var7f1abdf0[] = "Hand : Look ma no hands!\n";
|
|
const char var7f1abe0c[] = "BriGun: Set Master State: MASTER_GUN_LOADSTATE_GUN\n";
|
|
const char var7f1abe40[] = "BriGun: Process MASTER_GUN_LOADSTATE_GUN\n";
|
|
const char var7f1abe6c[] = "BriGun: Setup Gun Load\n";
|
|
const char var7f1abe84[] = "BriGun: Set Master State: MASTER_GUN_LOADSTATE_CARTS\n";
|
|
const char var7f1abebc[] = "BriGun: Process MASTER_GUN_LOADSTATE_CARTS\n";
|
|
const char var7f1abee8[] = "BriGun: Cart Loaded setting GUN_LOADSTATE_FLUX\n";
|
|
const char var7f1abf18[] = "BriGun: Cart loading - looking for carts\n";
|
|
const char var7f1abf44[] = "BriGun: Loading cart %d\n";
|
|
const char var7f1abf60[] = "BriGun: Request for cart %d ignored - cart already loaded\n";
|
|
const char var7f1abf9c[] = "BriGun: Compile Hand 0x%08x Gun 0x%0x8\n";
|
|
const char var7f1abfc4[] = "Gun : Compiled Gun 0x%08x\n";
|
|
const char var7f1abfe4[] = "Gun : Compiled Size %d\n";
|
|
const char var7f1ac000[] = "Hand : Compiled Hand 0x%08x\n";
|
|
const char var7f1ac020[] = "Hand : Compiled Size %d\n";
|
|
const char var7f1ac03c[] = "Gun : Compile overhead %d bytes\n";
|
|
const char var7f1ac060[] = "Hand : Hand Obj 0x%08x Gun Obj 0x%08x \n";
|
|
const char var7f1ac08c[] = "Gun : After Comp : Base 0x%08x Free %d\n";
|
|
const char var7f1ac0b8[] = "Gun : After Cached Setup : Base 0x%08x Free %d\n";
|
|
const char var7f1ac0ec[] = "Gun : TotalUsed %d, Free %d\n";
|
|
const char var7f1ac10c[] = "BriGun: Set Master State: MASTER_GUN_LOADSTATE_LOADED\n";
|
|
const char var7f1ac144[] = "GunLockTimer: %d\n";
|
|
|
|
void bgunTickMasterLoad(void)
|
|
{
|
|
s32 newweaponnum;
|
|
struct player *player = g_Vars.currentplayer;
|
|
bool hashands;
|
|
u16 handfilenum;
|
|
s32 sum;
|
|
u16 filenum;
|
|
s32 i;
|
|
struct casing *casing;
|
|
struct hand *hand;
|
|
struct weaponfunc *func;
|
|
struct weaponfunc *shootfunc;
|
|
struct weapon *weapondef;
|
|
s32 casingindex;
|
|
struct inventory_ammo *ammodef;
|
|
s32 value;
|
|
s32 bodynum;
|
|
s32 headnum;
|
|
|
|
if ((player->gunctrl.gunmemowner == GUNMEMOWNER_BONDGUN || bgun0f09e004(GUNMEMOWNER_BONDGUN)) && player->gunctrl.gunmemnew >= 0) {
|
|
if (player->gunctrl.gunlocktimer == 0) {
|
|
newweaponnum = player->gunctrl.gunmemnew;
|
|
|
|
playerChooseBodyAndHead(&bodynum, &headnum, NULL);
|
|
|
|
handfilenum = g_HeadsAndBodies[bodynum].handfilenum;
|
|
|
|
if (IS4MB()) {
|
|
handfilenum = FILE_GCOMBATHANDSLOD;
|
|
}
|
|
|
|
filenum = weaponGetModelNum(newweaponnum);
|
|
|
|
if (player->gunctrl.masterloadstate != MASTERLOADSTATE_LOADED || newweaponnum != player->gunctrl.gunmemtype) {
|
|
if (filenum) {
|
|
hashands = false;
|
|
|
|
if (weaponHasFlag(newweaponnum, WEAPONFLAG_HASHANDS)) {
|
|
hashands = true;
|
|
}
|
|
|
|
if (newweaponnum == WEAPON_UNARMED) {
|
|
// For unarmed, the fists are implemented
|
|
// as weapon models rather than hand models
|
|
filenum = handfilenum;
|
|
handfilenum = 0 * (player->gunctrl.gunloadstate == 4);
|
|
hashands = false;
|
|
}
|
|
|
|
if (player->gunctrl.masterloadstate == MASTERLOADSTATE_FLUX) {
|
|
casing = g_Casings;
|
|
|
|
while (casing < &g_Casings[ARRAYCOUNT(g_Casings)]) {
|
|
if (casing->modeldef == player->gunctrl.cartmodeldef) {
|
|
casing->modeldef = NULL;
|
|
}
|
|
|
|
casing++;
|
|
}
|
|
|
|
g_CasingsActive = false;
|
|
|
|
casing = g_Casings;
|
|
|
|
while (casing < &g_Casings[ARRAYCOUNT(g_Casings)]) {
|
|
if (casing->modeldef != NULL) {
|
|
g_CasingsActive = true;
|
|
}
|
|
|
|
casing++;
|
|
}
|
|
|
|
player->gunctrl.cartmodeldef = NULL;
|
|
player->gunctrl.masterloadstate = MASTERLOADSTATE_HANDS;
|
|
} else if (player->gunctrl.masterloadstate == MASTERLOADSTATE_HANDS) {
|
|
if (hashands) {
|
|
if (handfilenum != player->gunctrl.handfilenum) {
|
|
if (player->gunctrl.gunloadstate == GUNLOADSTATE_FLUX) {
|
|
player->gunctrl.unk15a0 = bgunGetGunMem();
|
|
player->gunctrl.unk15a4 = bgunCalculateGunMemCapacity();
|
|
player->gunctrl.gunloadstate = GUNLOADSTATE_MODEL;
|
|
player->gunctrl.loadfilenum = handfilenum;
|
|
player->gunctrl.loadtomodeldef = &player->gunctrl.handmodeldef;
|
|
player->gunctrl.loadmemptr = (u32 *) &player->gunctrl.unk15a0;
|
|
player->gunctrl.loadmemremaining = (u32 *) &player->gunctrl.unk15a4;
|
|
}
|
|
|
|
bgunTickGunLoad();
|
|
|
|
if (player->gunctrl.gunloadstate == GUNLOADSTATE_LOADED) {
|
|
player->gunctrl.handfilenum = handfilenum;
|
|
} else {
|
|
return;
|
|
}
|
|
}
|
|
} else {
|
|
player->gunctrl.handfilenum = 0;
|
|
player->gunctrl.handmodeldef = NULL;
|
|
player->gunctrl.unk15a0 = bgunGetGunMem();
|
|
player->gunctrl.unk15a4 = bgunCalculateGunMemCapacity();
|
|
}
|
|
|
|
player->gunctrl.masterloadstate = MASTERLOADSTATE_GUN;
|
|
player->gunctrl.gunloadstate = GUNLOADSTATE_FLUX;
|
|
} else if (player->gunctrl.masterloadstate == MASTERLOADSTATE_GUN) {
|
|
if (player->gunctrl.gunloadstate == GUNLOADSTATE_FLUX) {
|
|
player->gunctrl.unk15a8 = (u8 *) player->gunctrl.unk15a0;
|
|
player->gunctrl.unk15ac = player->gunctrl.unk15a4;
|
|
player->gunctrl.gunloadstate = GUNLOADSTATE_MODEL;
|
|
player->gunctrl.loadfilenum = filenum;
|
|
player->gunctrl.loadtomodeldef = &player->gunctrl.gunmodeldef;
|
|
player->gunctrl.loadmemptr = (u32 *) &player->gunctrl.unk15a8;
|
|
player->gunctrl.loadmemremaining = (u32 *) &player->gunctrl.unk15ac;
|
|
}
|
|
|
|
bgunTickGunLoad();
|
|
|
|
if (player->gunctrl.gunloadstate == GUNLOADSTATE_LOADED) {
|
|
player->gunctrl.masterloadstate = MASTERLOADSTATE_CARTS;
|
|
player->gunctrl.gunloadstate = GUNLOADSTATE_FLUX;
|
|
}
|
|
} else if (player->gunctrl.masterloadstate == MASTERLOADSTATE_CARTS) {
|
|
if (player->gunctrl.gunloadstate == GUNLOADSTATE_LOADED) {
|
|
player->gunctrl.gunloadstate = GUNLOADSTATE_FLUX;
|
|
}
|
|
|
|
if (player->gunctrl.gunloadstate == GUNLOADSTATE_FLUX && player->gunctrl.cartmodeldef == NULL && PLAYERCOUNT() == 1) {
|
|
for (i = 0; i < 2; i++) {
|
|
hand = player->hands + i;
|
|
func = gsetGetWeaponFunction2(&hand->gset);
|
|
shootfunc = NULL;
|
|
weapondef = weaponFindById(player->gunctrl.weaponnum);
|
|
casingindex = -1;
|
|
|
|
if (func != NULL) {
|
|
if ((func->type & 0xff) == INVENTORYFUNCTYPE_SHOOT) {
|
|
shootfunc = func;
|
|
}
|
|
|
|
if (weapondef && shootfunc) {
|
|
ammodef = func->ammoindex >= 0 ? weapondef->ammos[func->ammoindex] : NULL;
|
|
|
|
if (ammodef) {
|
|
casingindex = ammodef->casingeject;
|
|
}
|
|
}
|
|
|
|
if (casingindex >= 0) {
|
|
if (player->gunctrl.cartmodeldef == NULL) {
|
|
filenum = g_CartFileNums[casingindex];
|
|
player->gunctrl.loadfilenum = filenum;
|
|
player->gunctrl.gunloadstate = GUNLOADSTATE_MODEL;
|
|
player->gunctrl.loadtomodeldef = &player->gunctrl.cartmodeldef;
|
|
player->gunctrl.loadmemptr = (u32 *) &player->gunctrl.unk15a8;
|
|
player->gunctrl.loadmemremaining = (u32 *) &player->gunctrl.unk15ac;
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (player->gunctrl.gunloadstate != GUNLOADSTATE_FLUX) {
|
|
bgunTickGunLoad();
|
|
return;
|
|
}
|
|
|
|
sum = 0;
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
hand = &player->hands[i];
|
|
|
|
modelInit(&hand->gunmodel, player->gunctrl.gunmodeldef, (union modelrwdata **)hand->unk0a6c, 0);
|
|
|
|
if (player->gunctrl.handmodeldef != 0) {
|
|
modelInit(&hand->handmodel, player->gunctrl.handmodeldef, (union modelrwdata **)hand->handsavedata, false);
|
|
}
|
|
|
|
hand->unk0dcc = (s32 *) player->gunctrl.unk15a8;
|
|
|
|
value = bgunCreateModelCmdList(&hand->gunmodel, player->gunctrl.gunmodeldef->rootnode, (s32 *) player->gunctrl.unk15a8);
|
|
|
|
sum += value;
|
|
player->gunctrl.unk15a8 += value;
|
|
player->gunctrl.unk15ac -= value;
|
|
|
|
if (player->gunctrl.handmodeldef != 0) {
|
|
hand->unk0dd0 = (s32 *) player->gunctrl.unk15a8;
|
|
|
|
value = bgunCreateModelCmdList(&hand->handmodel, player->gunctrl.handmodeldef->rootnode, (s32 *) player->gunctrl.unk15a8);
|
|
|
|
sum += value;
|
|
player->gunctrl.unk15a8 += value;
|
|
player->gunctrl.unk15ac -= value;
|
|
}
|
|
}
|
|
|
|
hand = &player->hands[0];
|
|
hand->unk0dd4 = -1;
|
|
|
|
if (player->gunctrl.unk15ac > 3200) {
|
|
hand->unk0dd8 = (Mtxf *) player->gunctrl.unk15a8;
|
|
player->gunctrl.unk15a8 += 3200;
|
|
player->gunctrl.unk15ac -= 3200;
|
|
} else {
|
|
hand->unk0dd8 = 0;
|
|
}
|
|
|
|
bgunCalculateGunMemCapacity();
|
|
|
|
player->gunctrl.masterloadstate = MASTERLOADSTATE_LOADED;
|
|
player->gunctrl.gunmemtype = newweaponnum;
|
|
player->gunctrl.gunmemnew = -1;
|
|
}
|
|
}
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
else {
|
|
player->gunctrl.masterloadstate = MASTERLOADSTATE_LOADED;
|
|
player->gunctrl.gunmemtype = newweaponnum;
|
|
player->gunctrl.gunmemnew = -1;
|
|
}
|
|
#endif
|
|
}
|
|
} else {
|
|
player->gunctrl.gunlocktimer--;
|
|
|
|
if (player->gunctrl.gunlocktimer < -2) {
|
|
player->gunctrl.gunlocktimer = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void bgunTickLoad(void)
|
|
{
|
|
s32 i;
|
|
|
|
for (i = 0; i < g_Vars.lvupdate240; i += 8) {
|
|
bgunTickMasterLoad();
|
|
}
|
|
}
|
|
|
|
bool bgun0f09eae4(void)
|
|
{
|
|
// PAL adds a check for the eyespy being used
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
if ((g_Vars.currentplayer->devicesactive & ~g_Vars.currentplayer->devicesinhibit & DEVICE_EYESPY)) {
|
|
g_Vars.currentplayer->gunctrl.unk1583_06 = false;
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
bgun0f09df9c();
|
|
|
|
if (g_Vars.currentplayer->gunctrl.weaponnum != WEAPON_NONE) {
|
|
g_Vars.currentplayer->gunctrl.gunmemnew = g_Vars.currentplayer->gunctrl.weaponnum;
|
|
} else {
|
|
return false;
|
|
}
|
|
|
|
if (g_Vars.currentplayer->gunctrl.gunmemtype != -1) {
|
|
return false;
|
|
}
|
|
|
|
if (g_Vars.currentplayer->gunctrl.gunmemowner != GUNMEMOWNER_BONDGUN) {
|
|
bgun0f09e004(GUNMEMOWNER_BONDGUN);
|
|
|
|
if (g_Vars.currentplayer->gunctrl.gunmemowner != GUNMEMOWNER_BONDGUN) {
|
|
g_Vars.lockscreen = true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bgun0f09df9c();
|
|
|
|
do {
|
|
bgunTickMasterLoad();
|
|
} while (!bgun0f09dd7c());
|
|
|
|
g_Vars.currentplayer->gunctrl.unk1583_06 = false;
|
|
|
|
return false;
|
|
}
|
|
|
|
struct modeldef *bgunGetCartModeldef(void)
|
|
{
|
|
return g_Vars.currentplayer->gunctrl.cartmodeldef;
|
|
}
|
|
|
|
void bgun0f09ebcc(struct defaultobj *obj, struct coord *coord, s16 *rooms, Mtxf *matrix1, struct coord *velocity, Mtxf *matrix2, struct prop *prop, struct coord *pos)
|
|
{
|
|
struct prop *objprop = obj->prop;
|
|
|
|
if (objprop) {
|
|
propActivate(objprop);
|
|
propEnable(objprop);
|
|
mtx00015f04(obj->model->scale, matrix1);
|
|
func0f06a580(obj, coord, matrix1, rooms);
|
|
|
|
if (obj->type == OBJTYPE_WEAPON && ((struct weaponobj *) obj)->weaponnum == WEAPON_BOLT) {
|
|
s32 beamnum = boltbeamFindByProp(objprop);
|
|
|
|
if (beamnum == -1) {
|
|
beamnum = boltbeamCreate(objprop);
|
|
}
|
|
|
|
if (beamnum != -1) {
|
|
boltbeamSetHeadPos(beamnum, pos);
|
|
boltbeamSetTailPos(beamnum, pos);
|
|
}
|
|
}
|
|
|
|
func0f0685e4(objprop);
|
|
|
|
if (obj->hidden & OBJHFLAG_PROJECTILE) {
|
|
obj->projectile->flags |= PROJECTILEFLAG_AIRBORNE;
|
|
obj->projectile->ownerprop = prop;
|
|
|
|
projectileSetSticky(objprop);
|
|
mtx4Copy(matrix2, (Mtxf *)&obj->projectile->mtx);
|
|
|
|
obj->projectile->speed.x = velocity->x;
|
|
obj->projectile->speed.y = velocity->y;
|
|
obj->projectile->speed.z = velocity->z;
|
|
obj->projectile->obj = obj;
|
|
obj->projectile->unk0d8 = g_Vars.lvframenum;
|
|
}
|
|
}
|
|
}
|
|
|
|
void bgun0f09ed2c(struct defaultobj *obj, struct coord *newpos, Mtxf *arg2, struct coord *velocity, Mtxf *arg4)
|
|
{
|
|
struct prop *objprop = obj->prop;
|
|
struct coord pos;
|
|
s16 rooms[8];
|
|
|
|
if (objprop) {
|
|
struct prop *playerprop = g_Vars.currentplayer->prop;
|
|
|
|
pos.x = playerprop->pos.x;
|
|
pos.y = playerprop->pos.y;
|
|
pos.z = playerprop->pos.z;
|
|
|
|
roomsCopy(playerprop->rooms, rooms);
|
|
|
|
bgun0f09ebcc(obj, &pos, rooms, arg2, velocity, arg4, playerprop, newpos);
|
|
|
|
if (obj->hidden & OBJHFLAG_PROJECTILE) {
|
|
obj->projectile->flags |= PROJECTILEFLAG_LAUNCHING;
|
|
|
|
obj->projectile->nextsteppos.x = newpos->x;
|
|
obj->projectile->nextsteppos.y = newpos->y;
|
|
obj->projectile->nextsteppos.z = newpos->z;
|
|
}
|
|
}
|
|
}
|
|
|
|
struct defaultobj *bgunCreateThrownProjectile2(struct chrdata *chr, struct gset *gset, struct coord *pos, s16 *rooms, Mtxf *arg4, struct coord *velocity)
|
|
{
|
|
struct defaultobj *obj = NULL;
|
|
struct weaponfunc *basefunc;
|
|
struct weaponfunc_throw *func;
|
|
struct weapon *weapon = weaponFindById(gset->weaponnum);
|
|
struct weaponobj *weaponobj;
|
|
struct autogunobj *autogun;
|
|
Mtxf mtx;
|
|
s32 playernum;
|
|
|
|
if (weapon == NULL) {
|
|
return false;
|
|
}
|
|
|
|
basefunc = weapon->functions[gset->weaponfunc];
|
|
func = (struct weaponfunc_throw *) basefunc;
|
|
|
|
if (func == NULL) {
|
|
return false;
|
|
}
|
|
|
|
if (gset->weaponnum == WEAPON_COMBATKNIFE) {
|
|
guRotateF(mtx.m, 90.0f / (RANDOMFRAC() + 12.1f),
|
|
arg4->m[1][0], arg4->m[1][1], arg4->m[1][2]);
|
|
} else {
|
|
mtxLoadRandomRotation(&mtx);
|
|
}
|
|
|
|
if (gset->weaponnum == WEAPON_LAPTOPGUN) {
|
|
autogun = laptopDeploy(func->projectilemodelnum, gset, chr);
|
|
|
|
if (autogun != NULL) {
|
|
obj = &autogun->base;
|
|
}
|
|
} else {
|
|
weaponobj = weaponCreateProjectileFromGset(func->projectilemodelnum, gset, chr);
|
|
|
|
if (weaponobj != NULL) {
|
|
obj = &weaponobj->base;
|
|
|
|
// Note this timer is converted to 240 time immediately below
|
|
weaponobj->timer240 = func->activatetime60;
|
|
|
|
if (weaponobj->timer240 >= 2) {
|
|
weaponobj->timer240 = TICKS(weaponobj->timer240 * 4);
|
|
}
|
|
|
|
if (weaponobj->weaponnum == WEAPON_GRENADE || weaponobj->weaponnum == WEAPON_NBOMB) {
|
|
propSetDangerous(weaponobj->base.prop);
|
|
}
|
|
|
|
if (func->projectilemodelnum == MODEL_CHRREMOTEMINE
|
|
|| func->projectilemodelnum == MODEL_CHRTIMEDMINE
|
|
|| func->projectilemodelnum == MODEL_CHRPROXIMITYMINE
|
|
|| func->projectilemodelnum == MODEL_CHRECMMINE) {
|
|
weaponobj->base.flags3 |= OBJFLAG3_00000008;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (obj != NULL) {
|
|
bgun0f09ebcc(obj, pos, rooms, arg4, velocity, &mtx, chr->prop, pos);
|
|
|
|
obj->hidden &= 0x0fffffff;
|
|
|
|
if (g_Vars.normmplayerisrunning) {
|
|
playernum = mpPlayerGetIndex(chr);
|
|
} else {
|
|
playernum = playermgrGetPlayerNumByProp(chr->prop);
|
|
}
|
|
|
|
obj->hidden |= playernum << 28;
|
|
|
|
if (obj->hidden & OBJHFLAG_PROJECTILE) {
|
|
obj->projectile->flags |= PROJECTILEFLAG_00000002;
|
|
obj->projectile->unk08c = 0.1f;
|
|
obj->projectile->pickuptimer240 = TICKS(240);
|
|
|
|
propsnd0f0939f8(NULL, obj->prop, SFX_THROW, -1,
|
|
-1, 0, 0, 0, NULL, -1, NULL, -1, -1, -1, -1);
|
|
}
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
|
|
/**
|
|
* handnum supports some unusual values:
|
|
*
|
|
* 0 = right hand
|
|
* 1 = left hand
|
|
* 2 = fumbling grenade from right hand (due to nbomb)
|
|
* 3 = fumbling grenade from left hand (actually not possible)
|
|
*/
|
|
void bgunCreateThrownProjectile(s32 handnum, struct gset *gset)
|
|
{
|
|
struct coord velocity = {0, 0, 0};
|
|
Mtxf sp1f4;
|
|
struct coord sp1e8;
|
|
struct coord sp1dc;
|
|
struct prop *playerprop = g_Vars.currentplayer->prop;
|
|
struct coord *prevpos = &g_Vars.currentplayer->bondprevpos;
|
|
struct coord *extrapos = &g_Vars.currentplayer->bondextrapos;
|
|
Mtxf sp190;
|
|
struct defaultobj *obj;
|
|
struct weaponobj *weapon;
|
|
struct coord muzzlepos;
|
|
struct coord spawnpos;
|
|
s16 spawnrooms[8];
|
|
bool droppinggrenade = false;
|
|
struct hand *hand;
|
|
struct coord aimpos;
|
|
struct coord sp140;
|
|
f32 frac;
|
|
f32 radians;
|
|
Mtxf spf8;
|
|
Mtxf spb8;
|
|
Mtxf sp78;
|
|
f32 sp68[4];
|
|
f32 sp58[4];
|
|
f32 sp48[4];
|
|
struct trainingdata *data;
|
|
u32 stack;
|
|
|
|
if (handnum >= 2) {
|
|
droppinggrenade = true;
|
|
handnum -= 2;
|
|
}
|
|
|
|
hand = g_Vars.currentplayer->hands + handnum;
|
|
|
|
muzzlepos.x = g_Vars.currentplayer->hands[handnum].muzzlepos.x;
|
|
muzzlepos.y = g_Vars.currentplayer->hands[handnum].muzzlepos.y;
|
|
muzzlepos.z = g_Vars.currentplayer->hands[handnum].muzzlepos.z;
|
|
|
|
mtx4LoadIdentity(&sp1f4);
|
|
|
|
if (gset->weaponnum == WEAPON_COMBATKNIFE) {
|
|
mtx4LoadZRotation(4.711639f, &sp1f4);
|
|
mtx4LoadXRotation(3.1410925f, &sp190);
|
|
mtx4MultMtx4InPlace(&sp190, &sp1f4);
|
|
}
|
|
|
|
mtx4Copy(&g_Vars.currentplayer->hands[handnum].muzzlemat, &sp190);
|
|
|
|
guNormalize(&sp190.m[0][0], &sp190.m[0][1], &sp190.m[0][2]);
|
|
guNormalize(&sp190.m[1][0], &sp190.m[1][1], &sp190.m[1][2]);
|
|
guNormalize(&sp190.m[2][0], &sp190.m[2][1], &sp190.m[2][2]);
|
|
|
|
sp190.m[3][0] = 0.0f;
|
|
sp190.m[3][1] = 0.0f;
|
|
sp190.m[3][2] = 0.0f;
|
|
|
|
mtx4MultMtx4InPlace(&sp190, &sp1f4);
|
|
|
|
playerSetPerimEnabled(playerprop, false);
|
|
|
|
if (cdTestLos11(&playerprop->pos, playerprop->rooms, &muzzlepos, spawnrooms, CDTYPE_ALL) != CDRESULT_COLLISION) {
|
|
spawnpos.x = muzzlepos.x;
|
|
spawnpos.y = muzzlepos.y;
|
|
spawnpos.z = muzzlepos.z;
|
|
} else {
|
|
spawnpos.x = playerprop->pos.x;
|
|
spawnpos.y = playerprop->pos.y;
|
|
spawnpos.z = playerprop->pos.z;
|
|
|
|
roomsCopy(playerprop->rooms, spawnrooms);
|
|
}
|
|
|
|
playerSetPerimEnabled(playerprop, true);
|
|
|
|
bgunCalculatePlayerShotSpread(&sp1e8, &sp1dc, handnum, true);
|
|
mtx4RotateVecInPlace(camGetProjectionMtxF(), &sp1dc);
|
|
|
|
if (droppinggrenade) {
|
|
// Dropping a grenade because player is in an nbomb storm
|
|
velocity.x = sp1dc.x * 1.6666666f;
|
|
velocity.y = sp1dc.y * 1.6666666f;
|
|
velocity.z = sp1dc.z * 1.6666666f;
|
|
} else if (gsetHasFunctionFlags(&hand->gset, FUNCFLAG_CALCULATETRAJECTORY)) {
|
|
// Calculate the velocity based on the trajectory to the aimpos
|
|
func0f061d54(0, 0, 0);
|
|
|
|
if (hand->hasdotinfo) {
|
|
aimpos.x = hand->dotpos.x;
|
|
aimpos.y = hand->dotpos.y;
|
|
aimpos.z = hand->dotpos.z;
|
|
|
|
chrCalculateTrajectory(&spawnpos, 21.666666f, &aimpos, &sp140);
|
|
|
|
radians = acosf(sp1dc.f[0] * sp140.f[0] + sp1dc.f[1] * sp140.f[1] + sp1dc.f[2] * sp140.f[2]);
|
|
|
|
// Check within 20 degrees
|
|
if (radians > 0.34901026f || radians < -0.34901026f) {
|
|
mtx00016b58(&spf8, 0, 0, 0, sp1dc.x, sp1dc.y, sp1dc.z, 0, 1, 0);
|
|
mtx00016b58(&spb8, 0, 0, 0, sp140.x, sp140.y, sp140.z, 0, 1, 0);
|
|
|
|
quaternion0f097044(&spf8, sp68);
|
|
quaternion0f097044(&spb8, sp58);
|
|
quaternion0f0976c0(sp68, sp58);
|
|
|
|
frac = 0.34901025891304f / radians;
|
|
|
|
if (frac < 0.0f) {
|
|
frac = -frac;
|
|
}
|
|
|
|
quaternionSlerp(sp68, sp58, frac, sp48);
|
|
quaternionToMtx(sp48, &sp78);
|
|
|
|
sp1dc.x = -sp78.m[2][0];
|
|
sp1dc.y = -sp78.m[2][1];
|
|
sp1dc.z = -sp78.m[2][2];
|
|
} else {
|
|
sp1dc.x = sp140.x;
|
|
sp1dc.y = sp140.y;
|
|
sp1dc.z = sp140.z;
|
|
}
|
|
}
|
|
|
|
velocity.x = sp1dc.x * 21.666666f;
|
|
velocity.y = sp1dc.y * 21.666666f;
|
|
velocity.z = sp1dc.z * 21.666666f;
|
|
} else {
|
|
// Simple velocity
|
|
velocity.x = sp1dc.x * 16.666666f;
|
|
velocity.y = sp1dc.y * 16.666666f;
|
|
velocity.z = sp1dc.z * 16.666666f;
|
|
|
|
if (gset->weaponnum == WEAPON_GRENADE || gset->weaponnum == WEAPON_NBOMB) {
|
|
velocity.y += 1.6666666f;
|
|
} else {
|
|
velocity.y += 5.0f;
|
|
}
|
|
}
|
|
|
|
if (gset->weaponnum == WEAPON_LAPTOPGUN) {
|
|
bgunFreeWeapon(handnum);
|
|
}
|
|
|
|
// Add player movement to velocity
|
|
if (g_Vars.lvupdate240 > 0) {
|
|
velocity.x += (playerprop->pos.x - prevpos->x + extrapos->x) / g_Vars.lvupdate60freal;
|
|
velocity.y += (playerprop->pos.y - prevpos->y + extrapos->y) / g_Vars.lvupdate60freal;
|
|
velocity.z += (playerprop->pos.z - prevpos->z + extrapos->z) / g_Vars.lvupdate60freal;
|
|
}
|
|
|
|
obj = bgunCreateThrownProjectile2(g_Vars.currentplayer->prop->chr, gset, &spawnpos, spawnrooms, &sp1f4, &velocity);
|
|
|
|
if (obj) {
|
|
if (obj->type == OBJTYPE_WEAPON) {
|
|
weapon = (struct weaponobj *)obj;
|
|
|
|
if (gset->weaponnum == WEAPON_GRENADE && gset->weaponfunc == FUNC_PRIMARY) {
|
|
if (weapon->timer240 < hand->primetimer60 * 4) {
|
|
weapon->timer240 = 0;
|
|
} else {
|
|
weapon->timer240 -= hand->primetimer60 * 4;
|
|
}
|
|
|
|
weapon->gunfunc = gset->weaponfunc;
|
|
} else if (gset->weaponnum == WEAPON_ECMMINE && g_Vars.stagenum == STAGE_CITRAINING) {
|
|
data = dtGetData();
|
|
|
|
if (data->intraining) {
|
|
data->obj = obj;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (obj->hidden & OBJHFLAG_PROJECTILE) {
|
|
obj->projectile->flags |= PROJECTILEFLAG_LAUNCHING;
|
|
obj->projectile->nextsteppos.x = muzzlepos.x;
|
|
obj->projectile->nextsteppos.y = muzzlepos.y;
|
|
obj->projectile->nextsteppos.z = muzzlepos.z;
|
|
|
|
if (gset->weaponnum == WEAPON_GRENADE && gset->weaponfunc == FUNC_SECONDARY) {
|
|
obj->projectile->unk08c = 1.0f;
|
|
}
|
|
|
|
if (gset->weaponnum == WEAPON_COMBATKNIFE) {
|
|
// In theory, weapon can be uninitialised here,
|
|
// but in practice it's always set.
|
|
weapon->base.projectile->flags |= PROJECTILEFLAG_00000002;
|
|
weapon->base.projectile->unk08c = 0.1f;
|
|
weapon->base.projectile->pickuptimer240 = TICKS(240);
|
|
weapon->base.hidden |= OBJHFLAG_THROWNKNIFE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void bgunUpdateHeldRocket(s32 handnum)
|
|
{
|
|
struct hand *hand = &g_Vars.currentplayer->hands[handnum];
|
|
struct defaultobj *obj = &hand->rocket->base;
|
|
|
|
if (obj) {
|
|
struct prop *objprop = obj->prop;
|
|
Mtxf mtx;
|
|
|
|
if (objprop) {
|
|
struct prop *playerprop = g_Vars.currentplayer->prop;
|
|
struct model *model = obj->model;
|
|
|
|
if (!hand->firedrocket) {
|
|
mtx4Copy(&hand->posmtx, &mtx);
|
|
|
|
mtx.m[3][0] = 0;
|
|
mtx.m[3][1] = 0;
|
|
mtx.m[3][2] = 0;
|
|
|
|
mtx00015f04(obj->model->scale, &mtx);
|
|
func0f06a580(obj, &hand->muzzlepos, &mtx, playerprop->rooms);
|
|
propDeregisterRooms(objprop);
|
|
}
|
|
|
|
model->matrices = gfxAllocate(model->definition->nummatrices * sizeof(Mtxf));
|
|
|
|
mtx4Copy(&hand->muzzlemat, &model->matrices[0]);
|
|
modelUpdateRelationsQuick(model, model->definition->rootnode);
|
|
|
|
objprop->flags |= PROPFLAG_ONANYSCREENTHISTICK | PROPFLAG_ONTHISSCREENTHISTICK;
|
|
objprop->z = -model->matrices[0].m[3][2];
|
|
}
|
|
}
|
|
}
|
|
|
|
void bgunCreateHeldRocket(s32 handnum, struct weaponfunc_shootprojectile *func)
|
|
{
|
|
struct hand *hand = &g_Vars.currentplayer->hands[handnum];
|
|
struct weaponobj *obj;
|
|
|
|
if (hand->rocket == NULL) {
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
hand->firedrocket = false;
|
|
#endif
|
|
|
|
obj = weaponCreateProjectileFromWeaponNum(func->projectilemodelnum, WEAPON_ROCKET, g_Vars.currentplayer->prop->chr);
|
|
|
|
if (obj != NULL) {
|
|
hand->rocket = obj;
|
|
hand->firedrocket = false;
|
|
|
|
obj->timer240 = 1;
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
obj->base.flags |= OBJFLAG_HELDROCKET;
|
|
#endif
|
|
obj->base.flags2 |= OBJFLAG2_THROWTHROUGH;
|
|
}
|
|
}
|
|
}
|
|
|
|
void bgunFreeHeldRocket(s32 handnum)
|
|
{
|
|
struct hand *hand = &g_Vars.currentplayer->hands[handnum];
|
|
|
|
if (hand->rocket) {
|
|
objFreePermanently(&hand->rocket->base, true);
|
|
hand->rocket = NULL;
|
|
}
|
|
}
|
|
|
|
void bgunCreateFiredProjectile(s32 handnum)
|
|
{
|
|
struct weapon *weapondef;
|
|
struct hand *hand;
|
|
Mtxf sp270;
|
|
struct coord sp264;
|
|
f32 sp260;
|
|
f32 sp25c;
|
|
struct coord sp250;
|
|
Mtxf sp210;
|
|
struct coord sp204;
|
|
struct coord sp1f8;
|
|
struct prop *playerprop;
|
|
struct coord *prevpos;
|
|
struct coord *extrapos;
|
|
struct coord spawnpos;
|
|
struct weaponobj *weapon;
|
|
struct weaponfunc *tmp;
|
|
struct weaponfunc_shootprojectile *funcdef;
|
|
struct coord aimpos;
|
|
struct coord sp1bc;
|
|
f32 frac;
|
|
f32 radians;
|
|
Mtxf sp174;
|
|
Mtxf sp134;
|
|
Mtxf spf4;
|
|
f32 spe4[4];
|
|
f32 spd4[4];
|
|
f32 spc4[4];
|
|
|
|
hand = g_Vars.currentplayer->hands + handnum;
|
|
|
|
playerprop = g_Vars.currentplayer->prop;
|
|
prevpos = &g_Vars.currentplayer->bondprevpos;
|
|
extrapos = &g_Vars.currentplayer->bondextrapos;
|
|
|
|
weapondef = weaponFindById(hand->gset.weaponnum);
|
|
|
|
if (weapondef) {
|
|
tmp = weapondef->functions[hand->gset.weaponfunc];
|
|
|
|
if (tmp && tmp->type == INVENTORYFUNCTYPE_SHOOT_PROJECTILE) {
|
|
funcdef = (struct weaponfunc_shootprojectile *)tmp;
|
|
|
|
mtx4LoadIdentity(&sp270);
|
|
bgunCalculatePlayerShotSpread(&sp204, &sp1f8, handnum, true);
|
|
mtx4RotateVecInPlace(camGetProjectionMtxF(), &sp1f8);
|
|
|
|
spawnpos.x = hand->muzzlepos.x;
|
|
spawnpos.y = hand->muzzlepos.y;
|
|
spawnpos.z = hand->muzzlepos.z;
|
|
|
|
if (hand->gset.weaponnum == WEAPON_SLAYER && hand->gset.weaponfunc == FUNC_SECONDARY) {
|
|
spawnpos.x += 50.0f * sp1f8.x;
|
|
spawnpos.y += 50.0f * sp1f8.y;
|
|
spawnpos.z += 50.0f * sp1f8.z;
|
|
}
|
|
|
|
sp260 = funcdef->speed * 1.6666666f / 60.0f;
|
|
sp25c = funcdef->traveldist * 1.6666666f;
|
|
|
|
if (gsetHasFunctionFlags(&hand->gset, FUNCFLAG_CALCULATETRAJECTORY)) {
|
|
func0f061d54(0, 0, 0);
|
|
|
|
if (hand->hasdotinfo) {
|
|
aimpos.x = hand->dotpos.x;
|
|
aimpos.y = hand->dotpos.y;
|
|
aimpos.z = hand->dotpos.z;
|
|
|
|
chrCalculateTrajectory(&spawnpos, sp25c, &aimpos, &sp1bc);
|
|
|
|
radians = acosf(sp1f8.f[0] * sp1bc.f[0] + sp1f8.f[1] * sp1bc.f[1] + sp1f8.f[2] * sp1bc.f[2]);
|
|
|
|
if (radians > 0.17450513f || radians < -0.17450513f) {
|
|
mtx00016b58(&sp174, 0.0f, 0.0f, 0.0f, sp1f8.x, sp1f8.y, sp1f8.z, 0.0f, 1.0f, 0.0f);
|
|
mtx00016b58(&sp134, 0.0f, 0.0f, 0.0f, sp1bc.x, sp1bc.y, sp1bc.z, 0.0f, 1.0f, 0.0f);
|
|
|
|
quaternion0f097044(&sp174, spe4);
|
|
quaternion0f097044(&sp134, spd4);
|
|
quaternion0f0976c0(spe4, spd4);
|
|
|
|
frac = 0.17450513f / radians;
|
|
|
|
if (frac < 0.0f) {
|
|
frac = -frac;
|
|
}
|
|
|
|
quaternionSlerp(spe4, spd4, frac, spc4);
|
|
quaternionToMtx(spc4, &spf4);
|
|
|
|
sp1f8.x = -spf4.m[2][0];
|
|
sp1f8.y = -spf4.m[2][1];
|
|
sp1f8.z = -spf4.m[2][2];
|
|
} else {
|
|
sp1f8.x = sp1bc.x;
|
|
sp1f8.y = sp1bc.y;
|
|
sp1f8.z = sp1bc.z;
|
|
}
|
|
}
|
|
}
|
|
|
|
sp250.x = sp1f8.x * sp260;
|
|
sp250.y = sp1f8.y * sp260;
|
|
sp250.z = sp1f8.z * sp260;
|
|
|
|
sp264.x = sp250.f[0] * g_Vars.lvupdate60freal + sp1f8.f[0] * sp25c;
|
|
sp264.y = sp250.f[1] * g_Vars.lvupdate60freal + sp1f8.f[1] * sp25c;
|
|
sp264.z = sp250.f[2] * g_Vars.lvupdate60freal + sp1f8.f[2] * sp25c;
|
|
|
|
if ((funcdef->base.base.flags & FUNCFLAG_FLYBYWIRE) == 0 && g_Vars.lvupdate240 > 0) {
|
|
sp264.x += (playerprop->pos.x - prevpos->x + extrapos->x) / g_Vars.lvupdate60freal;
|
|
sp264.y += (playerprop->pos.y - prevpos->y + extrapos->y) / g_Vars.lvupdate60freal;
|
|
sp264.z += (playerprop->pos.z - prevpos->z + extrapos->z) / g_Vars.lvupdate60freal;
|
|
}
|
|
|
|
mtx4Copy(&g_Vars.currentplayer->hands[handnum].posmtx, &sp210);
|
|
|
|
sp210.m[3][0] = 0.0f;
|
|
sp210.m[3][1] = 0.0f;
|
|
sp210.m[3][2] = 0.0f;
|
|
|
|
if (hand->rocket) {
|
|
hand->firedrocket = true;
|
|
|
|
weapon = hand->rocket;
|
|
weapon->base.flags2 &= ~OBJFLAG2_THROWTHROUGH;
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
weapon->base.flags &= ~OBJFLAG_HELDROCKET;
|
|
#endif
|
|
|
|
if (funcdef->base.base.flags & FUNCFLAG_HOMINGROCKET) {
|
|
weapon->weaponnum = WEAPON_HOMINGROCKET;
|
|
}
|
|
} else if (hand->gset.weaponnum == WEAPON_ROCKETLAUNCHER || hand->gset.weaponnum == WEAPON_SLAYER) {
|
|
u32 stack;
|
|
s32 weaponnum = WEAPON_ROCKET;
|
|
|
|
if (funcdef->base.base.flags & FUNCFLAG_HOMINGROCKET) {
|
|
weaponnum = WEAPON_HOMINGROCKET;
|
|
}
|
|
|
|
weapon = weaponCreateProjectileFromWeaponNum(funcdef->projectilemodelnum, weaponnum, g_Vars.currentplayer->prop->chr);
|
|
} else if (hand->gset.weaponnum == WEAPON_CROSSBOW) {
|
|
weapon = weaponCreateProjectileFromWeaponNum(funcdef->projectilemodelnum, WEAPON_BOLT, g_Vars.currentplayer->prop->chr);
|
|
|
|
if (weapon) {
|
|
weapon->gunfunc = hand->gset.weaponfunc;
|
|
}
|
|
} else if (hand->gset.weaponnum == WEAPON_DEVASTATOR) {
|
|
weapon = weaponCreateProjectileFromWeaponNum(funcdef->projectilemodelnum, WEAPON_GRENADEROUND, g_Vars.currentplayer->prop->chr);
|
|
|
|
if (weapon) {
|
|
weapon->gunfunc = hand->gset.weaponfunc;
|
|
}
|
|
} else if (hand->gset.weaponnum == WEAPON_SUPERDRAGON) {
|
|
weapon = weaponCreateProjectileFromWeaponNum(funcdef->projectilemodelnum, WEAPON_GRENADEROUND, g_Vars.currentplayer->prop->chr);
|
|
|
|
if (weapon) {
|
|
weapon->gunfunc = FUNC_2;
|
|
}
|
|
} else {
|
|
weapon = weaponCreateProjectileFromGset(funcdef->projectilemodelnum, &hand->gset, g_Vars.currentplayer->prop->chr);
|
|
}
|
|
|
|
if (weapon) {
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
bool failed = false;
|
|
Mtxf sp78;
|
|
struct coord sp6c;
|
|
struct coord sp60;
|
|
|
|
if (weapon->base.model && weapon->base.model->definition) {
|
|
weapon->timer240 = funcdef->timer60;
|
|
|
|
if (weapon->timer240 != -1) {
|
|
weapon->timer240 = TICKS(weapon->timer240 * 4);
|
|
}
|
|
|
|
weapon->base.hidden &= 0x0fffffff;
|
|
weapon->base.hidden |= g_Vars.currentplayernum << 28;
|
|
|
|
bgun0f09ed2c(&weapon->base, &spawnpos, &sp210, &sp264, &sp270);
|
|
|
|
if (weapon->base.hidden & OBJHFLAG_PROJECTILE) {
|
|
if (funcdef->base.base.flags & FUNCFLAG_PROJECTILE_LIGHTWEIGHT) {
|
|
weapon->base.projectile->flags |= PROJECTILEFLAG_LIGHTWEIGHT;
|
|
} else if (funcdef->base.base.flags & FUNCFLAG_PROJECTILE_POWERED) {
|
|
weapon->base.projectile->flags |= PROJECTILEFLAG_POWERED;
|
|
}
|
|
|
|
weapon->base.projectile->targetprop = g_Vars.currentplayer->trackedprops[0].prop;
|
|
|
|
if (funcdef->scale != 1.0f) {
|
|
weapon->base.model->scale *= funcdef->scale;
|
|
|
|
mtx3ToMtx4(weapon->base.realrot, &sp78);
|
|
mtx00015f04(funcdef->scale, &sp78);
|
|
mtx4ToMtx3(&sp78, weapon->base.realrot);
|
|
}
|
|
|
|
weapon->base.projectile->powerlimit240 = TICKS(1200);
|
|
weapon->base.projectile->unk0a8 = weapon->base.prop->pos.y;
|
|
weapon->base.projectile->unk0ac = weapon->base.projectile->speed.y;
|
|
weapon->base.projectile->unk010 = sp250.x;
|
|
weapon->base.projectile->unk014 = sp250.y;
|
|
weapon->base.projectile->unk018 = sp250.z;
|
|
weapon->base.projectile->pickuptimer240 = TICKS(240);
|
|
weapon->base.projectile->unk08c = funcdef->reflectangle;
|
|
weapon->base.projectile->unk098 = funcdef->unk50 * 1.6666666f;
|
|
|
|
if (funcdef->soundnum > 0) {
|
|
propsnd0f0939f8(NULL, weapon->base.prop, funcdef->soundnum, -1, -1, 0, 0, 0, 0, -1.0f, 0, -1, -1.0f, -1.0f, -1.0f);
|
|
}
|
|
|
|
if (funcdef->base.base.flags & FUNCFLAG_FLYBYWIRE) {
|
|
playerLaunchSlayerRocket(weapon);
|
|
}
|
|
|
|
if (weapon->base.projectile->flags & PROJECTILEFLAG_LAUNCHING) {
|
|
projectileLaunch(&weapon->base, weapon->base.projectile, &sp6c, &sp60);
|
|
}
|
|
} else {
|
|
failed = true;
|
|
}
|
|
} else {
|
|
failed = true;
|
|
}
|
|
|
|
if (failed) {
|
|
weapon->timer240 = -1;
|
|
|
|
if (weapon->base.prop) {
|
|
propFree(weapon->base.prop);
|
|
}
|
|
|
|
if (weapon->base.model) {
|
|
modelmgrFreeModel(weapon->base.model);
|
|
}
|
|
|
|
weapon->base.prop = NULL;
|
|
weapon->base.model = NULL;
|
|
}
|
|
#else
|
|
// NTSC beta doesn't have any of the failure checks
|
|
Mtxf sp78;
|
|
struct coord sp6c;
|
|
struct coord sp60;
|
|
|
|
weapon->timer240 = funcdef->timer60;
|
|
|
|
if (weapon->timer240 != -1) {
|
|
weapon->timer240 = TICKS(weapon->timer240 * 4);
|
|
}
|
|
|
|
weapon->base.hidden &= 0x0fffffff;
|
|
weapon->base.hidden |= g_Vars.currentplayernum << 28;
|
|
|
|
bgun0f09ed2c(&weapon->base, &spawnpos, &sp210, &sp264, &sp270);
|
|
|
|
if (weapon->base.hidden & OBJHFLAG_PROJECTILE) {
|
|
if (funcdef->base.base.flags & FUNCFLAG_PROJECTILE_LIGHTWEIGHT) {
|
|
weapon->base.projectile->flags |= PROJECTILEFLAG_LIGHTWEIGHT;
|
|
} else if (funcdef->base.base.flags & FUNCFLAG_PROJECTILE_POWERED) {
|
|
weapon->base.projectile->flags |= PROJECTILEFLAG_POWERED;
|
|
}
|
|
|
|
weapon->base.projectile->targetprop = g_Vars.currentplayer->trackedprops[0].prop;
|
|
|
|
if (funcdef->scale != 1.0f) {
|
|
weapon->base.model->scale *= funcdef->scale;
|
|
|
|
mtx3ToMtx4(weapon->base.realrot, &sp78);
|
|
mtx00015f04(funcdef->scale, &sp78);
|
|
mtx4ToMtx3(&sp78, weapon->base.realrot);
|
|
}
|
|
|
|
weapon->base.projectile->powerlimit240 = TICKS(1200);
|
|
weapon->base.projectile->unk0a8 = weapon->base.prop->pos.y;
|
|
weapon->base.projectile->unk0ac = weapon->base.projectile->speed.y;
|
|
weapon->base.projectile->unk010 = sp250.x;
|
|
weapon->base.projectile->unk014 = sp250.y;
|
|
weapon->base.projectile->unk018 = sp250.z;
|
|
weapon->base.projectile->pickuptimer240 = TICKS(240);
|
|
weapon->base.projectile->unk08c = funcdef->reflectangle;
|
|
weapon->base.projectile->unk098 = funcdef->unk50 * 1.6666666f;
|
|
|
|
if (funcdef->soundnum > 0) {
|
|
propsnd0f0939f8(NULL, weapon->base.prop, funcdef->soundnum, -1, -1, 0, 0, 0, 0, -1.0f, 0, -1, -1.0f, -1.0f, -1.0f);
|
|
}
|
|
|
|
if (funcdef->base.base.flags & FUNCFLAG_FLYBYWIRE) {
|
|
playerLaunchSlayerRocket(weapon);
|
|
}
|
|
|
|
if (weapon->base.projectile->flags & PROJECTILEFLAG_LAUNCHING) {
|
|
projectileLaunch(&weapon->base, weapon->base.projectile, &sp6c, &sp60);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void bgunSwivel(f32 screenx, f32 screeny, f32 crossdamp, f32 aimdamp)
|
|
{
|
|
f32 screenwidth = camGetScreenWidth();
|
|
f32 screenheight = camGetScreenHeight();
|
|
struct player *player = g_Vars.currentplayer;
|
|
struct coord aimpos;
|
|
s32 l;
|
|
s32 h;
|
|
f32 x[2];
|
|
f32 y[2];
|
|
bool ignore[2] = {false, false};
|
|
s32 numframes;
|
|
struct hand *hand;
|
|
struct coord sp94;
|
|
f32 sp8c[2];
|
|
|
|
x[HAND_RIGHT] = x[HAND_LEFT] = screenx;
|
|
y[HAND_RIGHT] = y[HAND_LEFT] = screeny;
|
|
|
|
ignore[HAND_LEFT] = !player->hands[HAND_LEFT].inuse;
|
|
ignore[HAND_RIGHT] = !player->hands[HAND_RIGHT].inuse;
|
|
|
|
// If using right hand only and reloading,
|
|
// recentre until the reload animation is almost complete
|
|
if (!player->hands[HAND_LEFT].inuse
|
|
&& player->hands[HAND_RIGHT].state == HANDSTATE_RELOAD
|
|
&& player->hands[HAND_RIGHT].unk0ce8) {
|
|
numframes = 25;
|
|
|
|
if (player->hands[HAND_RIGHT].gset.weaponnum == WEAPON_CROSSBOW) {
|
|
numframes = 5;
|
|
}
|
|
|
|
if ((s32)bgun0f09815c(&player->hands[HAND_RIGHT]) < modelGetNumAnimFrames(&player->hands[HAND_RIGHT].gunmodel) - numframes) {
|
|
x[HAND_RIGHT] = 0.0f;
|
|
y[HAND_RIGHT] = 0.0f;
|
|
ignore[HAND_RIGHT] = true;
|
|
}
|
|
}
|
|
|
|
if (player->hands[HAND_LEFT].gset.weaponnum == WEAPON_REMOTEMINE) {
|
|
x[HAND_LEFT] = g_Vars.currentplayer->speedtheta * 0.3f + g_Vars.currentplayer->gunextraaimx;
|
|
y[HAND_LEFT] = -g_Vars.currentplayer->speedverta * 0.1f + g_Vars.currentplayer->gunextraaimy;
|
|
ignore[HAND_LEFT] = true;
|
|
}
|
|
|
|
if (player->hands[HAND_RIGHT].gset.weaponnum == WEAPON_UNARMED) {
|
|
x[HAND_RIGHT] = g_Vars.currentplayer->speedtheta * 0.3f + g_Vars.currentplayer->gunextraaimx;
|
|
y[HAND_RIGHT] = -g_Vars.currentplayer->speedverta * 0.1f + g_Vars.currentplayer->gunextraaimy;
|
|
ignore[HAND_RIGHT] = true;
|
|
}
|
|
|
|
if (g_Vars.currentplayer->teleportstate != TELEPORTSTATE_INACTIVE) {
|
|
ignore[HAND_LEFT] = ignore[HAND_RIGHT] = true;
|
|
}
|
|
|
|
// This loop only iterates once
|
|
for (h = 0; h < 1; h++) {
|
|
if (!ignore[h]) {
|
|
hand = &player->hands[h];
|
|
|
|
if (hand->hasdotinfo && !g_Vars.mplayerisrunning) {
|
|
sp94.x = hand->dotpos.x;
|
|
sp94.y = hand->dotpos.y;
|
|
sp94.z = hand->dotpos.z;
|
|
|
|
mtx4TransformVecInPlace(camGetWorldToScreenMtxf(), &sp94);
|
|
|
|
if (!(sp94.z < 0.0000001f) || !(sp94.z > -0.0000001f)) {
|
|
if (sp94.z > -6000.0f) {
|
|
cam0f0b4d04(&sp94, sp8c);
|
|
|
|
x[h] = sp8c[0];
|
|
y[h] = sp8c[1];
|
|
|
|
x[h] = 2.0f * (x[h] / viGetViewWidth()) - 1.0f;
|
|
y[h] = 2.0f * (y[h] / viGetViewHeight()) - 1.0f;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
player->oldcrosspos[0] = player->crosspos[0];
|
|
player->oldcrosspos[1] = player->crosspos[1];
|
|
|
|
if (crossdamp != player->guncrossdamp) {
|
|
player->crosspossum[0] = player->crosspossum[0] * (1.0f - player->guncrossdamp) / (1.0f - crossdamp);
|
|
player->crosspossum[1] = player->crosspossum[1] * (1.0f - player->guncrossdamp) / (1.0f - crossdamp);
|
|
player->guncrossdamp = crossdamp;
|
|
}
|
|
|
|
if (aimdamp != player->gunaimdamp) {
|
|
player->crosssum2[0] = player->crosssum2[0] * (1.0f - player->gunaimdamp) / (1.0f - aimdamp);
|
|
player->crosssum2[1] = player->crosssum2[1] * (1.0f - player->gunaimdamp) / (1.0f - aimdamp);
|
|
player->gunaimdamp = aimdamp;
|
|
}
|
|
|
|
for (l = 0; l < g_Vars.lvupdate240; l++) {
|
|
player->crosspossum[0] = player->crosspossum[0] * crossdamp + screenx;
|
|
player->crosspossum[1] = player->crosspossum[1] * crossdamp + screeny;
|
|
|
|
for (h = 0; h < 2; h++) {
|
|
hand = &player->hands[h];
|
|
hand->guncrosspossum[0] = (PAL ? 0.913f : 0.9269697f) * hand->guncrosspossum[0] + x[h];
|
|
hand->guncrosspossum[1] = (PAL ? 0.913f : 0.9269697f) * hand->guncrosspossum[1] + y[h];
|
|
}
|
|
}
|
|
|
|
player->crosspos[0] = player->crosspossum[0] * (1.0f - crossdamp) * screenwidth * 0.5f + screenwidth * 0.5f;
|
|
player->crosspos[1] = player->crosspossum[1] * (1.0f - crossdamp) * screenheight * 0.5f + screenheight * 0.5f;
|
|
|
|
if (player->crosspos[0] < 3.0f) {
|
|
player->crosspos[0] = 3.0f;
|
|
} else if (player->crosspos[0] > screenwidth - 4.0f) {
|
|
player->crosspos[0] = screenwidth - 4.0f;
|
|
}
|
|
|
|
if (player->crosspos[1] < 3.0f) {
|
|
player->crosspos[1] = 3.0f;
|
|
} else if (player->crosspos[1] > screenheight - 4.0f) {
|
|
player->crosspos[1] = screenheight - 4.0f;
|
|
}
|
|
|
|
player->crosspos[0] += camGetScreenLeft();
|
|
player->crosspos[1] += camGetScreenTop();
|
|
|
|
for (h = 0; h < 2; h++) {
|
|
player->hands[h].crosspos[0] = player->hands[h].guncrosspossum[0] * (PAL ? 0.08700001f : 0.07303029f) * screenwidth * 0.5f + screenwidth * 0.5f;
|
|
player->hands[h].crosspos[1] = player->hands[h].guncrosspossum[1] * (PAL ? 0.08700001f : 0.07303029f) * screenheight * 0.5f + screenheight * 0.5f;
|
|
|
|
if (player->hands[h].crosspos[0] < 3.0f) {
|
|
player->hands[h].crosspos[0] = 3.0f;
|
|
} else if (player->hands[h].crosspos[0] > screenwidth - 4.0f) {
|
|
player->hands[h].crosspos[0] = screenwidth - 4.0f;
|
|
}
|
|
|
|
if (player->hands[h].crosspos[1] < 3.0f) {
|
|
player->hands[h].crosspos[1] = 3.0f;
|
|
} else if (player->hands[h].crosspos[1] > screenheight - 4.0f) {
|
|
player->hands[h].crosspos[1] = screenheight - 4.0f;
|
|
}
|
|
|
|
player->hands[h].crosspos[0] += camGetScreenLeft();
|
|
player->hands[h].crosspos[1] += camGetScreenTop();
|
|
}
|
|
|
|
for (l = 0; l < g_Vars.lvupdate240; l++) {
|
|
player->crosssum2[0] = player->crosssum2[0] * aimdamp + screenx;
|
|
player->crosssum2[1] = player->crosssum2[1] * aimdamp + screeny;
|
|
}
|
|
|
|
player->crosspos2[0] = player->crosssum2[0] * (1.0f - aimdamp) * screenwidth * 0.5f + screenwidth * 0.5f;
|
|
player->crosspos2[1] = player->crosssum2[1] * (1.0f - aimdamp) * screenheight * 0.5f + screenheight * 0.5f;
|
|
player->crosspos2[0] += camGetScreenLeft();
|
|
player->crosspos2[1] += camGetScreenTop();
|
|
|
|
cam0f0b4c3c(player->crosspos2, &aimpos, 1000);
|
|
|
|
bgunSetAimPos(&aimpos);
|
|
}
|
|
|
|
/**
|
|
* Swivel the gun towards the given screen coordinates, dampening the movement
|
|
* speed as it reaches the target.
|
|
*
|
|
* This is used for auto aim, the CMP's follow lock-on, and general turning.
|
|
*/
|
|
void bgunSwivelWithDamp(f32 screenx, f32 screeny, f32 crossdamp)
|
|
{
|
|
struct weapon *weapon = weaponFindById(bgunGetWeaponNum(HAND_RIGHT));
|
|
f32 aimdamp = PAL ? weapon->aimsettings->aimdamppal : weapon->aimsettings->aimdamp;
|
|
|
|
if (aimdamp < crossdamp) {
|
|
aimdamp = crossdamp;
|
|
}
|
|
|
|
bgunSwivel(screenx, screeny, crossdamp, aimdamp);
|
|
}
|
|
|
|
/**
|
|
* Swivel the gun towards the given screen coordinates without slowing the speed
|
|
* speed as it reaches the target.
|
|
*
|
|
* This is used when manual aiming.
|
|
*/
|
|
void bgunSwivelWithoutDamp(f32 screenx, f32 screeny)
|
|
{
|
|
struct weapon *weapon = weaponFindById(bgunGetWeaponNum(HAND_RIGHT));
|
|
f32 aimdamp = PAL ? weapon->aimsettings->aimdamppal : weapon->aimsettings->aimdamp;
|
|
|
|
bgunSwivel(screenx, screeny, PAL ? 0.935f : 0.945f, aimdamp);
|
|
}
|
|
|
|
void bgunGetCrossPos(f32 *x, f32 *y)
|
|
{
|
|
struct player *player = g_Vars.currentplayer;
|
|
|
|
*x = player->crosspos[0];
|
|
*y = player->crosspos[1];
|
|
}
|
|
|
|
void bgun0f0a0c08(struct coord *arg0, struct coord *arg1)
|
|
{
|
|
arg0->x = 0;
|
|
arg0->y = 0;
|
|
arg0->z = 0;
|
|
|
|
cam0f0b4c3c(g_Vars.currentplayer->crosspos, arg1, 1);
|
|
}
|
|
|
|
void bgun0f0a0c44(s32 handnum, struct coord *arg1, struct coord *arg2)
|
|
{
|
|
arg1->x = 0;
|
|
arg1->y = 0;
|
|
arg1->z = 0;
|
|
|
|
cam0f0b4c3c(g_Vars.currentplayer->hands[handnum].crosspos, arg2, 1);
|
|
}
|
|
|
|
void bgunCalculatePlayerShotSpread(struct coord *arg0, struct coord *arg1, s32 handnum, bool dorandom)
|
|
{
|
|
f32 crosspos[2];
|
|
f32 spread = 0;
|
|
f32 scaledspread;
|
|
f32 randfactor;
|
|
struct weaponfunc *func = currentPlayerGetWeaponFunction(handnum);
|
|
struct player *player = g_Vars.currentplayer;
|
|
|
|
if (func != NULL && (func->type & 0xff) == INVENTORYFUNCTYPE_SHOOT) {
|
|
struct weaponfunc_shoot *shootfunc = (struct weaponfunc_shoot *) func;
|
|
spread = shootfunc->spread;
|
|
}
|
|
|
|
// Unsure what this is
|
|
if (weaponHasAimFlag(bgunGetWeaponNum2(handnum), INVAIMFLAG_ACCURATESINGLESHOT)
|
|
&& player->hands[handnum].burstbullets == 1) {
|
|
spread *= 0.25f;
|
|
}
|
|
|
|
// Decrease spread if double crouched
|
|
if (bmoveGetCrouchPos() == CROUCHPOS_SQUAT) {
|
|
spread *= 0.5f;
|
|
}
|
|
|
|
// Increase spread if dual wielding
|
|
if (player->hands[HAND_LEFT].inuse) {
|
|
spread *= 1.5f;
|
|
}
|
|
|
|
scaledspread = 120.0f * spread / viGetFovY();
|
|
|
|
if (dorandom) {
|
|
randfactor = (RANDOMFRAC() - 0.5f) * RANDOMFRAC();
|
|
} else {
|
|
randfactor = 0;
|
|
}
|
|
|
|
crosspos[0] = player->crosspos[0] + randfactor * scaledspread * camGetScreenWidth()
|
|
/ (viGetHeight() * camGetPerspAspect());
|
|
|
|
if (dorandom) {
|
|
randfactor = (RANDOMFRAC() - 0.5f) * RANDOMFRAC();
|
|
} else {
|
|
randfactor = 0;
|
|
}
|
|
|
|
crosspos[1] = player->crosspos[1] + (randfactor * scaledspread * camGetScreenHeight())
|
|
/ viGetHeight();
|
|
|
|
arg0->x = 0;
|
|
arg0->y = 0;
|
|
arg0->z = 0;
|
|
|
|
cam0f0b4c3c(crosspos, arg1, 1);
|
|
}
|
|
|
|
void bgunCalculateBotShotSpread(struct coord *arg0, s32 weaponnum, s32 funcnum, bool arg3, s32 crouchpos, bool dual)
|
|
{
|
|
f32 spread = 0.0f;
|
|
f32 radius;
|
|
struct weapon *weapondef = weaponFindById(weaponnum);
|
|
f32 x;
|
|
f32 y;
|
|
Mtxf mtx;
|
|
struct coord sp48;
|
|
u32 stack;
|
|
|
|
if (weapondef) {
|
|
struct weaponfunc *funcdef = weapondef->functions[funcnum];
|
|
|
|
if (funcdef && (funcdef->type & 0xff) == INVENTORYFUNCTYPE_SHOOT) {
|
|
struct weaponfunc_shoot *shootfunc = (struct weaponfunc_shoot *)funcdef;
|
|
spread = shootfunc->spread;
|
|
}
|
|
}
|
|
|
|
if (arg3 && weaponHasAimFlag(weaponnum, INVAIMFLAG_ACCURATESINGLESHOT)) {
|
|
spread *= 0.25f;
|
|
}
|
|
|
|
if (crouchpos == CROUCHPOS_SQUAT) {
|
|
spread *= 0.5f;
|
|
}
|
|
|
|
if (dual) {
|
|
spread *= 1.5f;
|
|
}
|
|
|
|
radius = 120.0f * spread / viGetFovY();
|
|
x = (RANDOMFRAC() - 0.5f) * RANDOMFRAC() * radius;
|
|
y = (RANDOMFRAC() - 0.5f) * RANDOMFRAC() * radius;
|
|
|
|
sp48.x = g_Vars.currentplayer->c_scalex * x;
|
|
sp48.y = g_Vars.currentplayer->c_scaley * y;
|
|
sp48.z = -1.0f;
|
|
|
|
guNormalize(&sp48.x, &sp48.y, &sp48.z);
|
|
mtx00016b58(&mtx, 0.0f, 0.0f, 0.0f, arg0->x, arg0->y, arg0->z, 0.0f, -1.0f, 0.0f);
|
|
mtx4RotateVec(&mtx, &sp48, arg0);
|
|
}
|
|
|
|
bool bgunGetLastShootInfo(struct coord *pos, struct coord *dir, s32 handnum)
|
|
{
|
|
struct hand *hand = &g_Vars.currentplayer->hands[handnum];
|
|
|
|
if (!hand->lastdirvalid) {
|
|
return false;
|
|
}
|
|
|
|
pos->x = hand->lastshootpos.x;
|
|
pos->y = hand->lastshootpos.y;
|
|
pos->z = hand->lastshootpos.z;
|
|
|
|
dir->x = hand->lastshootdir.x;
|
|
dir->y = hand->lastshootdir.y;
|
|
dir->z = hand->lastshootdir.z;
|
|
|
|
return true;
|
|
}
|
|
|
|
void bgunSetLastShootInfo(struct coord *pos, struct coord *dir, s32 handnum)
|
|
{
|
|
struct hand *hand = &g_Vars.currentplayer->hands[handnum];
|
|
|
|
hand->lastdirvalid = true;
|
|
|
|
hand->lastshootpos.x = pos->x;
|
|
hand->lastshootpos.y = pos->y;
|
|
hand->lastshootpos.z = pos->z;
|
|
|
|
hand->lastshootdir.x = dir->x;
|
|
hand->lastshootdir.y = dir->y;
|
|
hand->lastshootdir.z = dir->z;
|
|
}
|
|
|
|
s32 bgunGetShotsToTake(s32 handnum)
|
|
{
|
|
struct hand *hand = &g_Vars.currentplayer->hands[handnum];
|
|
|
|
return hand->shotstotake;
|
|
}
|
|
|
|
void bgunFreeWeapon(s32 handnum)
|
|
{
|
|
struct player *player = g_Vars.currentplayer;
|
|
s32 i;
|
|
|
|
if (player->hands[handnum].inuse) {
|
|
for (i = 0; i < 2; i++) {
|
|
if (player->gunctrl.ammotypes[i] >= 0) {
|
|
s32 spaceinclip = player->hands[handnum].clipsizes[i] - player->hands[handnum].loadedammo[i];
|
|
s32 index = bgunGetUnequippedReloadIndex(player->gunctrl.weaponnum);
|
|
|
|
if (index != -1) {
|
|
#if VERSION >= VERSION_JPN_FINAL
|
|
player->hands[handnum].gunroundsspent[index] = (spaceinclip << 8) + 0xff;
|
|
#elif VERSION >= VERSION_PAL_BETA
|
|
player->hands[handnum].gunroundsspent[index] = spaceinclip * 213 + 212;
|
|
#else
|
|
player->hands[handnum].gunroundsspent[index] = (spaceinclip << 8) | 0xff;
|
|
#endif
|
|
}
|
|
|
|
if (player->hands[handnum].loadedammo[i] > 0) {
|
|
player->ammoheldarr[player->gunctrl.ammotypes[i]] += player->hands[handnum].loadedammo[i];
|
|
}
|
|
|
|
player->hands[handnum].loadedammo[i] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (g_Vars.mplayerisrunning && (IS8MB() || PLAYERCOUNT() != 1)) {
|
|
playermgrDeleteWeapon(handnum);
|
|
}
|
|
|
|
bgunFreeHeldRocket(handnum);
|
|
}
|
|
|
|
void bgunTickSwitch2(void)
|
|
{
|
|
struct player *player = g_Vars.currentplayer;
|
|
struct gunctrl *ctrl = &g_Vars.currentplayer->gunctrl;
|
|
s32 i;
|
|
|
|
if (ctrl->switchtoweaponnum >= 0) {
|
|
if (bgunCanFreeWeapon(HAND_RIGHT) && bgunCanFreeWeapon(HAND_LEFT)) {
|
|
s32 weaponnum = player->gunctrl.weaponnum;
|
|
s32 previnuse = player->hands[HAND_LEFT].inuse;
|
|
struct hand *lefthand;
|
|
struct hand *righthand;
|
|
|
|
if (currentPlayerGetDeviceState(ctrl->switchtoweaponnum) != DEVICESTATE_UNEQUIPPED) {
|
|
ctrl->switchtoweaponnum = WEAPON_UNARMED;
|
|
}
|
|
|
|
#if VERSION == VERSION_JPN_FINAL
|
|
if (ctrl->switchtoweaponnum == WEAPON_COMBATKNIFE) {
|
|
ctrl->switchtoweaponnum = WEAPON_UNARMED;
|
|
}
|
|
#endif
|
|
|
|
if (ctrl->dualwielding && !invHasDoubleWeaponIncAllGuns(ctrl->switchtoweaponnum, ctrl->switchtoweaponnum)) {
|
|
ctrl->dualwielding = false;
|
|
}
|
|
|
|
func0f0d7364();
|
|
|
|
bgunFreeWeapon(HAND_LEFT);
|
|
bgunFreeWeapon(HAND_RIGHT);
|
|
|
|
if (weaponnum == WEAPON_HORIZONSCANNER) {
|
|
g_Vars.currentplayer->insightaimmode = false;
|
|
}
|
|
|
|
if (weaponnum == WEAPON_RCP120) {
|
|
s32 amount = player->hands[HAND_RIGHT].matmot1;
|
|
|
|
if (amount > player->ammoheldarr[ctrl->ammotypes[0]]) {
|
|
amount = player->ammoheldarr[ctrl->ammotypes[0]];
|
|
}
|
|
|
|
player->ammoheldarr[ctrl->ammotypes[0]] -= amount;
|
|
}
|
|
|
|
if (weaponnum == WEAPON_HORIZONSCANNER) {
|
|
g_Vars.currentplayer->zoomintimemax = 0;
|
|
g_Vars.currentplayer->zoomintime = g_Vars.currentplayer->zoomintimemax;
|
|
g_Vars.currentplayer->zoominfovynew = 60;
|
|
g_Vars.currentplayer->zoominfovy = g_Vars.currentplayer->zoominfovynew;
|
|
}
|
|
|
|
lefthand = &player->hands[HAND_LEFT];
|
|
righthand = &player->hands[HAND_RIGHT];
|
|
|
|
if (ctrl->switchtoweaponnum == WEAPON_NONE) {
|
|
lefthand->inuse = false;
|
|
righthand->inuse = false;
|
|
ctrl->weaponnum = WEAPON_NONE;
|
|
} else {
|
|
bgunSetGunMemWeapon(ctrl->switchtoweaponnum);
|
|
ctrl->weaponnum = ctrl->switchtoweaponnum;
|
|
lefthand->inuse = true;
|
|
righthand->inuse = true;
|
|
}
|
|
|
|
if (ctrl->weaponnum == WEAPON_REMOTEMINE) {
|
|
ctrl->dualwielding = true;
|
|
}
|
|
|
|
if (!ctrl->dualwielding) {
|
|
lefthand->inuse = false;
|
|
}
|
|
|
|
if (weaponnum <= WEAPON_PSYCHOSISGUN && weaponnum >= WEAPON_UNARMED) {
|
|
player->gunctrl.prevweaponnum = weaponnum;
|
|
}
|
|
|
|
if (previnuse) {
|
|
player->gunctrl.unk1583_01 = true;
|
|
} else {
|
|
player->gunctrl.unk1583_01 = false;
|
|
}
|
|
|
|
g_Vars.currentplayer->gunctrl.invertgunfunc = false;
|
|
g_Vars.currentplayer->usedowntime = -1;
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
player->hands[i].ejectstate = EJECTSTATE_INACTIVE;
|
|
player->hands[i].ejecttype = EJECTTYPE_GUN;
|
|
player->hands[i].unk0d0f_02 = false;
|
|
player->hands[i].activatesecondary = false;
|
|
|
|
player->hands[i].matmot1 = 0.0f;
|
|
player->hands[i].matmot2 = 0.0f;
|
|
player->hands[i].matmot3 = 0.0f;
|
|
player->hands[i].angledamper = 0.0f;
|
|
player->hands[i].gunsmokepoint = 0.0f;
|
|
player->hands[i].burstbullets = 0;
|
|
player->hands[i].loadslide = 0.0f;
|
|
player->hands[i].allowshootframe = 0;
|
|
player->hands[i].lastshootframe60 = 0;
|
|
player->hands[i].gset.weaponfunc = FUNC_PRIMARY;
|
|
player->hands[i].gset.weaponnum = ctrl->weaponnum;
|
|
player->hands[i].gset.unk0639 = (ctrl->upgradewant >> (i * 4)) & 0xf;
|
|
player->hands[i].gangstarot = 0.0f;
|
|
|
|
bgun0f0abd30(i);
|
|
|
|
animInit(&player->hands[i].anim);
|
|
|
|
if (player->hands[i].audiohandle && sndGetState(player->hands[i].audiohandle) != AL_STOPPED) {
|
|
audioStop(player->hands[i].audiohandle);
|
|
}
|
|
}
|
|
|
|
invCalculateCurrentIndex();
|
|
|
|
ctrl->switchtoweaponnum = -1;
|
|
ctrl->fnfader = 0;
|
|
|
|
if (ctrl->weaponnum == WEAPON_DISGUISE40 || ctrl->weaponnum == WEAPON_DISGUISE41) {
|
|
struct chrdata *chr = player->prop->chr;
|
|
|
|
sndStart(var80095200, SFX_DISGUISE_ON, 0, -1, -1, -1, -1, -1);
|
|
|
|
g_Vars.currentplayer->disguised = true;
|
|
|
|
chr->hidden |= CHRHFLAG_DISGUISED;
|
|
|
|
if (g_Vars.stagenum == STAGE_RESCUE) {
|
|
chr->hidden |= CHRHFLAG_UNTARGETABLE;
|
|
}
|
|
|
|
invRemoveItemByNum(ctrl->weaponnum);
|
|
bgunCycleBack();
|
|
}
|
|
|
|
ctrl->curfnstr = 0;
|
|
ctrl->fnstrtimer = 0;
|
|
ctrl->unk1583_04 = false;
|
|
}
|
|
} else {
|
|
if (((player->hands[HAND_LEFT].inuse && !player->gunctrl.dualwielding)
|
|
|| (!player->hands[HAND_LEFT].inuse && player->gunctrl.dualwielding))
|
|
&& bgunCanFreeWeapon(HAND_LEFT)) {
|
|
bgunFreeWeapon(HAND_LEFT);
|
|
player->hands[HAND_LEFT].inuse = player->gunctrl.dualwielding;
|
|
}
|
|
}
|
|
}
|
|
|
|
void bgunEquipWeapon(s32 weaponnum)
|
|
{
|
|
struct player *player = g_Vars.currentplayer;
|
|
|
|
if (player->gunctrl.weaponnum == weaponnum && player->gunctrl.switchtoweaponnum == -1) {
|
|
return;
|
|
}
|
|
|
|
player->gunctrl.switchtoweaponnum = weaponnum;
|
|
player->gunctrl.wantammo = false;
|
|
}
|
|
|
|
s32 bgunGetWeaponNum(s32 handnum)
|
|
{
|
|
if (!g_Vars.currentplayer->hands[handnum].inuse) {
|
|
return WEAPON_NONE;
|
|
}
|
|
|
|
return g_Vars.currentplayer->gunctrl.weaponnum;
|
|
}
|
|
|
|
s32 bgunGetWeaponNum2(s32 handnum)
|
|
{
|
|
return bgunGetWeaponNum(handnum);
|
|
}
|
|
|
|
bool bgun0f0a1a10(s32 weaponnum)
|
|
{
|
|
if (weaponHasFlag(weaponnum, WEAPONFLAG_00000400)
|
|
&& (bgunGetAmmoTypeForWeapon(weaponnum, FUNC_PRIMARY) == 0 || bgunGetAmmoQtyForWeapon(weaponnum, FUNC_PRIMARY) > 0)) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
s32 bgunGetSwitchToWeapon(s32 handnum)
|
|
{
|
|
s32 weaponnum;
|
|
|
|
if (g_Vars.currentplayer->gunctrl.switchtoweaponnum >= 0) {
|
|
weaponnum = g_Vars.currentplayer->gunctrl.switchtoweaponnum;
|
|
} else {
|
|
weaponnum = g_Vars.currentplayer->gunctrl.weaponnum;
|
|
}
|
|
|
|
if (!g_Vars.currentplayer->gunctrl.dualwielding && handnum == HAND_LEFT) {
|
|
weaponnum = WEAPON_NONE;
|
|
}
|
|
|
|
return weaponnum;
|
|
}
|
|
|
|
void bgunSwitchToPrevious(void)
|
|
{
|
|
if (g_Vars.tickmode != TICKMODE_CUTSCENE) {
|
|
struct player *player = g_Vars.currentplayer;
|
|
s32 dualweaponnum;
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
if (invHasSingleWeaponIncAllGuns(player->gunctrl.prevweaponnum)) {
|
|
bgunEquipWeapon2(HAND_RIGHT, player->gunctrl.prevweaponnum);
|
|
|
|
dualweaponnum = invHasDoubleWeaponIncAllGuns(player->gunctrl.prevweaponnum, player->gunctrl.prevweaponnum)
|
|
* player->gunctrl.prevweaponnum * player->gunctrl.unk1583_01;
|
|
bgunEquipWeapon2(HAND_LEFT, dualweaponnum);
|
|
} else {
|
|
bgunAutoSwitchWeapon();
|
|
}
|
|
#else
|
|
bgunEquipWeapon2(HAND_RIGHT, player->gunctrl.prevweaponnum);
|
|
bgunEquipWeapon2(HAND_LEFT, player->gunctrl.prevweaponnum * player->gunctrl.unk1583_01);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void bgunCycleForward(void)
|
|
{
|
|
s32 weaponnum1;
|
|
s32 weaponnum2;
|
|
struct player *player = g_Vars.currentplayer;
|
|
|
|
if (g_Vars.tickmode != TICKMODE_CUTSCENE) {
|
|
weaponnum1 = bgunGetSwitchToWeapon(HAND_RIGHT);
|
|
weaponnum2 = bgunGetSwitchToWeapon(HAND_LEFT);
|
|
|
|
if (weaponnum1 > WEAPON_PSYCHOSISGUN || weaponnum2 > WEAPON_PSYCHOSISGUN) {
|
|
weaponnum1 = player->gunctrl.prevweaponnum;
|
|
weaponnum2 = player->gunctrl.prevweaponnum * player->gunctrl.unk1583_01;
|
|
} else {
|
|
invChooseCycleForwardWeapon(&weaponnum1, &weaponnum2, false);
|
|
}
|
|
|
|
if (weaponnum2 != weaponnum1) {
|
|
player->gunctrl.dualwielding = false;
|
|
} else {
|
|
player->gunctrl.dualwielding = true;
|
|
}
|
|
|
|
bgunEquipWeapon(weaponnum1);
|
|
}
|
|
}
|
|
|
|
void bgunCycleBack(void)
|
|
{
|
|
s32 weaponnum1;
|
|
s32 weaponnum2;
|
|
struct player *player = g_Vars.currentplayer;
|
|
|
|
if (g_Vars.tickmode != TICKMODE_CUTSCENE) {
|
|
weaponnum1 = bgunGetSwitchToWeapon(HAND_RIGHT);
|
|
weaponnum2 = bgunGetSwitchToWeapon(HAND_LEFT);
|
|
|
|
if (weaponnum2 == WEAPON_REMOTEMINE) {
|
|
weaponnum2 = WEAPON_NONE;
|
|
}
|
|
|
|
if (weaponnum1 > WEAPON_PSYCHOSISGUN || weaponnum2 > WEAPON_PSYCHOSISGUN) {
|
|
weaponnum1 = player->gunctrl.prevweaponnum;
|
|
weaponnum2 = player->gunctrl.prevweaponnum * player->gunctrl.unk1583_01;
|
|
} else {
|
|
invChooseCycleBackWeapon(&weaponnum1, &weaponnum2, false);
|
|
}
|
|
|
|
if (weaponnum2 == WEAPON_NONE) {
|
|
player->gunctrl.dualwielding = false;
|
|
} else {
|
|
player->gunctrl.dualwielding = true;
|
|
}
|
|
|
|
bgunEquipWeapon(weaponnum1);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return true if the player has ammo for the given weapon (for either function)
|
|
* or if the weapon doesn't support ammo.
|
|
*
|
|
* Used by the active menu to colour the slots.
|
|
*/
|
|
bool bgunHasAmmoForWeapon(s32 weaponnum)
|
|
{
|
|
bool ammodefexists = false;
|
|
bool hasammo = false;
|
|
struct weapon *weapon = weaponFindById(weaponnum);
|
|
s32 i;
|
|
|
|
if (weapon == NULL) {
|
|
return true;
|
|
}
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
struct weaponfunc *func = weaponGetFunctionById(weaponnum, i);
|
|
|
|
if (func && func->ammoindex >= 0) {
|
|
struct inventory_ammo *ammo = weapon->ammos[func->ammoindex];
|
|
|
|
if (ammo) {
|
|
ammodefexists = true;
|
|
|
|
if (bgunGetAmmoCount(ammo->type) > 0) {
|
|
hasammo = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!ammodefexists) {
|
|
return true;
|
|
}
|
|
|
|
if (hasammo == true) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
u8 g_AutoSwitchWeaponsPrimary[] = {
|
|
WEAPON_RCP120,
|
|
WEAPON_SUPERDRAGON, // primary function
|
|
WEAPON_K7AVENGER,
|
|
WEAPON_AR34,
|
|
WEAPON_CALLISTO,
|
|
WEAPON_LAPTOPGUN,
|
|
WEAPON_DRAGON,
|
|
WEAPON_CMP150,
|
|
WEAPON_CYCLONE,
|
|
WEAPON_FARSIGHT,
|
|
WEAPON_SHOTGUN,
|
|
WEAPON_REAPER,
|
|
WEAPON_DY357LX,
|
|
WEAPON_MAULER,
|
|
WEAPON_DY357MAGNUM,
|
|
WEAPON_MAGSEC4,
|
|
WEAPON_PHOENIX,
|
|
WEAPON_FALCON2_SCOPE,
|
|
WEAPON_FALCON2,
|
|
WEAPON_FALCON2_SILENCER,
|
|
WEAPON_SNIPERRIFLE,
|
|
WEAPON_CROSSBOW,
|
|
WEAPON_TRANQUILIZER,
|
|
WEAPON_LASER,
|
|
WEAPON_SUPERDRAGON, // secondary function
|
|
WEAPON_DEVASTATOR,
|
|
WEAPON_ROCKETLAUNCHER,
|
|
WEAPON_SLAYER,
|
|
WEAPON_GRENADE,
|
|
WEAPON_NBOMB,
|
|
WEAPON_PROXIMITYMINE,
|
|
WEAPON_TIMEDMINE,
|
|
WEAPON_REMOTEMINE,
|
|
WEAPON_COMBATKNIFE,
|
|
WEAPON_UNARMED,
|
|
};
|
|
|
|
u8 g_AutoSwitchWeaponsSecondary[] = {
|
|
WEAPON_REAPER,
|
|
WEAPON_DY357LX,
|
|
WEAPON_DY357MAGNUM,
|
|
WEAPON_FALCON2_SCOPE,
|
|
WEAPON_FALCON2,
|
|
WEAPON_FALCON2_SILENCER,
|
|
WEAPON_UNARMED,
|
|
};
|
|
|
|
/**
|
|
* Automatically choose and equip a new weapon after trying to fire a weapon
|
|
* which is out of ammo.
|
|
*
|
|
* The weapon preference order is stored in two arrays; one for weapons which
|
|
* should have their primary functions considered and which require ammo, and
|
|
* another for weapons which should have their secondary functions considered
|
|
* and don't require ammo for those functions. The second is only used if no
|
|
* weapons are usable from the primary array.
|
|
*
|
|
* For the primary array, the weapon must not be out of ammo. If the player's
|
|
* current weapon is not in the primary array then the first available primary
|
|
* will be selected. If the player's current weapon is in the primary array then
|
|
* the last available weapon earlier than their current weapon will be selected.
|
|
* If there are no weapons earlier than their current weapon then the first
|
|
* weapon after their current weapon is selected.
|
|
*
|
|
* In the primary array, the SuperDragon is a special case and appears twice.
|
|
* The first use is for the primary function while the second use is for the
|
|
* secondary function.
|
|
*
|
|
* For the secondary array, the player's current weapon must not be in the
|
|
* array. The first available weapon is selected. The player's "wantammo" flag
|
|
* will be set which will force the weapon onto the second function.
|
|
*/
|
|
void bgunAutoSwitchWeapon(void)
|
|
{
|
|
s32 i;
|
|
struct weapon *weapon;
|
|
struct weaponfunc *func;
|
|
s32 weaponnum;
|
|
s32 newweaponnum = -1;
|
|
s32 firstweaponnum = -1;
|
|
s32 foundsuperdragon = 0;
|
|
bool foundcurrent = false;
|
|
s32 curweaponnum = g_Vars.currentplayer->gunctrl.weaponnum;
|
|
bool wantammo = false;
|
|
|
|
if (g_Vars.tickmode == TICKMODE_CUTSCENE) {
|
|
return;
|
|
}
|
|
|
|
// Loop through g_AutoSwitchWeaponsPrimary, checking which weapons the
|
|
// player has which are usable. Stop when both a usable weapon is found
|
|
// and when the player's current weapon is found. Note the first and last
|
|
// usable weapons.
|
|
i = 0;
|
|
|
|
do {
|
|
bool usable = false;
|
|
|
|
if (invHasSingleWeaponIncAllGuns(g_AutoSwitchWeaponsPrimary[i])) {
|
|
weaponnum = g_AutoSwitchWeaponsPrimary[i];
|
|
weapon = weaponFindById(weaponnum);
|
|
func = weaponGetFunctionById(weaponnum, FUNC_PRIMARY);
|
|
|
|
if (!bgun0f0990b0(func, weapon) && (func->flags & FUNCFLAG_AUTOSWITCHUNSELECTABLE) == 0) {
|
|
usable = true;
|
|
}
|
|
|
|
if (weaponnum == WEAPON_SUPERDRAGON && !foundsuperdragon) {
|
|
foundsuperdragon++;
|
|
} else {
|
|
func = weaponGetFunctionById(weaponnum, FUNC_SECONDARY);
|
|
|
|
if (!bgun0f0990b0(func, weapon) && (func->flags & FUNCFLAG_AUTOSWITCHUNSELECTABLE) == 0) {
|
|
usable = true;
|
|
}
|
|
}
|
|
|
|
if (weaponnum == curweaponnum) {
|
|
foundcurrent = true;
|
|
} else if (usable) {
|
|
newweaponnum = weaponnum;
|
|
|
|
if (firstweaponnum == -1) {
|
|
firstweaponnum = weaponnum;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (++i >= ARRAYCOUNT(g_AutoSwitchWeaponsPrimary)) {
|
|
break;
|
|
}
|
|
} while (newweaponnum == -1 || !foundcurrent);
|
|
|
|
if (!foundcurrent) {
|
|
newweaponnum = firstweaponnum;
|
|
}
|
|
|
|
if (newweaponnum == -1) {
|
|
newweaponnum = WEAPON_UNARMED;
|
|
}
|
|
|
|
if (newweaponnum == WEAPON_UNARMED) {
|
|
bool foundcurrent = false;
|
|
s32 firstweaponnum = -1;
|
|
s32 weaponnum;
|
|
|
|
// No usable weapon was found in the primary array,
|
|
// so search the secondary array.
|
|
for (i = 0; i < ARRAYCOUNT(g_AutoSwitchWeaponsSecondary); i++) {
|
|
weaponnum = g_AutoSwitchWeaponsSecondary[i];
|
|
|
|
if (invHasSingleWeaponIncAllGuns(weaponnum)) {
|
|
if (weaponnum == curweaponnum) {
|
|
foundcurrent = true;
|
|
}
|
|
|
|
if (firstweaponnum == -1) {
|
|
firstweaponnum = weaponnum;
|
|
}
|
|
}
|
|
}
|
|
|
|
newweaponnum = firstweaponnum;
|
|
|
|
if (newweaponnum == -1) {
|
|
newweaponnum = WEAPON_UNARMED;
|
|
}
|
|
|
|
if (foundcurrent) {
|
|
newweaponnum = -1;
|
|
}
|
|
|
|
wantammo = true;
|
|
}
|
|
|
|
// Switch to newweaponnum
|
|
if (newweaponnum >= 0 && newweaponnum != curweaponnum) {
|
|
if (invHasDoubleWeaponIncAllGuns(newweaponnum, newweaponnum)) {
|
|
g_Vars.currentplayer->gunctrl.dualwielding = true;
|
|
} else {
|
|
g_Vars.currentplayer->gunctrl.dualwielding = false;
|
|
}
|
|
|
|
bgunEquipWeapon(newweaponnum);
|
|
|
|
if (wantammo) {
|
|
g_Vars.currentplayer->gunctrl.wantammo = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
void bgunEquipWeapon2(s32 handnum, s32 weaponnum)
|
|
{
|
|
if (handnum == HAND_LEFT) {
|
|
if (weaponnum == WEAPON_NONE) {
|
|
g_Vars.currentplayer->gunctrl.dualwielding = false;
|
|
} else {
|
|
g_Vars.currentplayer->gunctrl.dualwielding = true;
|
|
}
|
|
} else {
|
|
if (weaponnum > WEAPON_SUICIDEPILL) {
|
|
weaponnum = WEAPON_UNARMED;
|
|
}
|
|
|
|
bgunEquipWeapon(weaponnum);
|
|
}
|
|
}
|
|
|
|
s32 bgunIsFiring(s32 handnum)
|
|
{
|
|
return g_Vars.currentplayer->hands[handnum].firing;
|
|
}
|
|
|
|
s32 bgunGetAttackType(s32 handnum)
|
|
{
|
|
return g_Vars.currentplayer->hands[handnum].attacktype;
|
|
}
|
|
|
|
char *bgunGetName(s32 weaponnum)
|
|
{
|
|
struct weapon *weapon = g_Weapons[weaponnum];
|
|
|
|
if (weapon) {
|
|
return langGet(weapon->name);
|
|
}
|
|
|
|
return "** error\n";
|
|
}
|
|
|
|
u16 bgunGetNameId(s32 weaponnum)
|
|
{
|
|
struct weapon *weapon = g_Weapons[weaponnum];
|
|
|
|
if (weapon) {
|
|
return weapon->name;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
char *bgunGetShortName(s32 weaponnum)
|
|
{
|
|
struct weapon *weapon = g_Weapons[weaponnum];
|
|
|
|
if (weapon) {
|
|
return langGet(weapon->shortname);
|
|
}
|
|
|
|
return "** error\n";
|
|
}
|
|
|
|
const char var7f1ac170[] = "wantedfn %d tiggle %d\n";
|
|
|
|
void bgunReloadIfPossible(s32 handnum)
|
|
{
|
|
struct player *player = g_Vars.currentplayer;
|
|
|
|
if (bgunGetAmmoTypeForWeapon(bgunGetWeaponNum(handnum), FUNC_PRIMARY)
|
|
&& player->hands[handnum].modenext == HANDMODE_NONE) {
|
|
player->hands[handnum].modenext = HANDMODE_RELOAD;
|
|
}
|
|
}
|
|
|
|
void bgunSetAdjustPos(f32 angle)
|
|
{
|
|
struct player *player = g_Vars.currentplayer;
|
|
|
|
player->hands[0].adjustpos.z = (1 - cosf(angle)) * 5;
|
|
player->hands[1].adjustpos.z = (1 - cosf(angle)) * 5;
|
|
}
|
|
|
|
void bgunStartSlide(s32 handnum)
|
|
{
|
|
g_Vars.currentplayer->hands[handnum].slideinc = true;
|
|
}
|
|
|
|
/**
|
|
* Update the slide on weapons which have them (eg. Falcon 2).
|
|
*
|
|
* The slide moves back and then forward when firing. If the gun no longer has
|
|
* any ammo loaded in it, the slide moves back and remains in the back position.
|
|
*/
|
|
void bgunUpdateSlide(s32 handnum)
|
|
{
|
|
f32 slidemax = 0.0f;
|
|
struct weaponfunc *funcdef = currentPlayerGetWeaponFunction(handnum);
|
|
struct player *player = g_Vars.currentplayer;
|
|
|
|
if (funcdef && ((funcdef->type & 0xff) == INVENTORYFUNCTYPE_SHOOT)) {
|
|
struct weaponfunc_shoot *shootfunc = (struct weaponfunc_shoot *)funcdef;
|
|
slidemax = shootfunc->slidemax;
|
|
}
|
|
|
|
if (player->hands[handnum].slideinc) {
|
|
// Slide is moving backwards
|
|
if (player->hands[handnum].slidetrans < slidemax) {
|
|
player->hands[handnum].slidetrans += slidemax * 0.25f * g_Vars.lvupdate60freal;
|
|
}
|
|
|
|
if (player->hands[handnum].slidetrans >= slidemax) {
|
|
player->hands[handnum].slidetrans = slidemax;
|
|
player->hands[handnum].slideinc = false;
|
|
}
|
|
} else if (player->hands[handnum].loadedammo[FUNC_PRIMARY] > 0) {
|
|
if (bgun0f098a44(&player->hands[handnum], 3)) {
|
|
// Slide is moving forwards
|
|
if (player->hands[handnum].slidetrans > 0.0f) {
|
|
player->hands[handnum].slidetrans -= slidemax * 0.16666667f * g_Vars.lvupdate60freal;
|
|
}
|
|
|
|
if (player->hands[handnum].slidetrans < 0.0f) {
|
|
player->hands[handnum].slidetrans = 0.0f;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
f32 bgun0f0a2498(f32 arg0, f32 arg1, f32 arg2, f32 arg3)
|
|
{
|
|
f32 a = arg0 - arg2;
|
|
|
|
return asinf(a / sqrtf(a * a + (arg1 - arg3) * (arg1 - arg3)));
|
|
}
|
|
|
|
void bgun0f0a24f0(struct coord *arg0, s32 handnum)
|
|
{
|
|
struct coord b;
|
|
struct coord a;
|
|
|
|
bgun0f0a0c44(handnum, &a, &b);
|
|
|
|
b.x *= 1000;
|
|
b.y *= 1000;
|
|
b.z *= 1000;
|
|
|
|
arg0->x = b.x;
|
|
arg0->y = b.y;
|
|
arg0->z = b.z;
|
|
}
|
|
|
|
/**
|
|
* This function is a callback that is passed to model code.
|
|
*/
|
|
void bgun0f0a256c(s32 mtxindex, Mtxf *mtx)
|
|
{
|
|
Mtxf sp78;
|
|
Mtxf sp38;
|
|
struct coord rot;
|
|
|
|
if (mtxindex == var8009d148) {
|
|
if (var8009d144->ejectstate == EJECTSTATE_INIT) {
|
|
var8009d144->unk0d14 = mtx->m[3][0];
|
|
var8009d144->unk0d18 = mtx->m[3][1];
|
|
var8009d144->unk0d1c = mtx->m[3][2];
|
|
|
|
var8009d144->unk0d2c[0][0] = mtx->m[0][0];
|
|
var8009d144->unk0d2c[0][1] = mtx->m[0][1];
|
|
var8009d144->unk0d2c[0][2] = mtx->m[0][2];
|
|
var8009d144->unk0d2c[1][0] = mtx->m[1][0];
|
|
var8009d144->unk0d2c[1][1] = mtx->m[1][1];
|
|
var8009d144->unk0d2c[1][2] = mtx->m[1][2];
|
|
var8009d144->unk0d2c[2][0] = mtx->m[2][0];
|
|
var8009d144->unk0d2c[2][1] = mtx->m[2][1];
|
|
var8009d144->unk0d2c[2][2] = mtx->m[2][2];
|
|
} else if (var8009d144->ejectstate >= EJECTSTATE_AIRBORNE) {
|
|
mtx->m[3][0] = var8009d144->unk0d14;
|
|
mtx->m[3][1] = var8009d144->unk0d18;
|
|
mtx->m[3][2] = var8009d144->unk0d1c;
|
|
|
|
mtx->m[0][0] = var8009d144->unk0d2c[0][0];
|
|
mtx->m[0][1] = var8009d144->unk0d2c[0][1];
|
|
mtx->m[0][2] = var8009d144->unk0d2c[0][2];
|
|
mtx->m[1][0] = var8009d144->unk0d2c[1][0];
|
|
mtx->m[1][1] = var8009d144->unk0d2c[1][1];
|
|
mtx->m[1][2] = var8009d144->unk0d2c[1][2];
|
|
mtx->m[2][0] = var8009d144->unk0d2c[2][0];
|
|
mtx->m[2][1] = var8009d144->unk0d2c[2][1];
|
|
mtx->m[2][2] = var8009d144->unk0d2c[2][2];
|
|
}
|
|
}
|
|
|
|
if (mtxindex == var8009d0dc) {
|
|
rot.x = 0.0f;
|
|
rot.y = 0.0f;
|
|
rot.z = var8009d140;
|
|
|
|
mtx4LoadIdentity(&sp78);
|
|
mtx4LoadRotation(&rot, &sp78);
|
|
mtx4MultMtx4(mtx, &sp78, &sp38);
|
|
mtx4Copy(&sp38, mtx);
|
|
}
|
|
|
|
if (mtxindex == var8009d0f0[0] || mtxindex == var8009d0f0[1] || mtxindex == var8009d0f0[2]) {
|
|
rot.x = 0.0f;
|
|
rot.y = 0.0f;
|
|
rot.z = 2.0f * -var8009d140;
|
|
|
|
mtx4LoadIdentity(&sp78);
|
|
mtx4LoadRotation(&rot, &sp78);
|
|
mtx4MultMtx4(mtx, &sp78, &sp38);
|
|
mtx4Copy(&sp38, mtx);
|
|
}
|
|
}
|
|
|
|
bool bgun0f0a27c8(void)
|
|
{
|
|
struct hand *hand;
|
|
struct weaponfunc *func;
|
|
|
|
hand = &g_Vars.currentplayer->hands[HAND_RIGHT];
|
|
func = gsetGetWeaponFunction2(&hand->gset);
|
|
|
|
if (func
|
|
&& (func->type & 0xff) == INVENTORYFUNCTYPE_MELEE
|
|
&& hand->state == HANDSTATE_ATTACK
|
|
&& hand->unk0ce8 != NULL
|
|
&& hand->animmode == HANDANIMMODE_BUSY
|
|
&& !bgun0f098a44(hand, 2)) {
|
|
return true;
|
|
}
|
|
|
|
hand = &g_Vars.currentplayer->hands[HAND_LEFT];
|
|
|
|
if (hand->inuse) {
|
|
func = gsetGetWeaponFunction2(&hand->gset);
|
|
|
|
if (func
|
|
&& (func->type & 0xff) == INVENTORYFUNCTYPE_MELEE
|
|
&& hand->state == HANDSTATE_ATTACK
|
|
&& hand->unk0ce8 != NULL
|
|
&& hand->animmode == HANDANIMMODE_BUSY
|
|
&& !bgun0f098a44(hand, 2)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* This function is the same as above but it doesn't call bgun0f098a44().
|
|
*
|
|
* This function is unused.
|
|
*/
|
|
bool bgun0f0a28d8(void)
|
|
{
|
|
struct hand *hand;
|
|
struct weaponfunc *func;
|
|
|
|
hand = &g_Vars.currentplayer->hands[HAND_RIGHT];
|
|
func = gsetGetWeaponFunction2(&hand->gset);
|
|
|
|
if (func
|
|
&& (func->type & 0xff) == INVENTORYFUNCTYPE_MELEE
|
|
&& hand->state == HANDSTATE_ATTACK
|
|
&& hand->unk0ce8 != NULL
|
|
&& hand->animmode == HANDANIMMODE_BUSY) {
|
|
return true;
|
|
}
|
|
|
|
hand = &g_Vars.currentplayer->hands[HAND_LEFT];
|
|
|
|
if (hand->inuse) {
|
|
func = gsetGetWeaponFunction2(&hand->gset);
|
|
|
|
if (func
|
|
&& (func->type & 0xff) == INVENTORYFUNCTYPE_MELEE
|
|
&& hand->state == HANDSTATE_ATTACK
|
|
&& hand->unk0ce8 != NULL
|
|
&& hand->animmode == HANDANIMMODE_BUSY) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void bgunHandlePlayerDead(void)
|
|
{
|
|
struct player *player = g_Vars.currentplayer;
|
|
s32 i;
|
|
|
|
if (player->gunctrl.weaponnum != WEAPON_NONE && player->gunctrl.switchtoweaponnum != WEAPON_NONE) {
|
|
// Eject held weapons
|
|
if (player->hands[HAND_LEFT].inuse) {
|
|
player->hands[HAND_LEFT].ejectstate = EJECTSTATE_INIT;
|
|
player->hands[HAND_LEFT].ejecttype = EJECTTYPE_GUN;
|
|
}
|
|
|
|
if (player->hands[HAND_RIGHT].inuse) {
|
|
player->hands[HAND_RIGHT].ejectstate = EJECTSTATE_INIT;
|
|
player->hands[HAND_RIGHT].ejecttype = EJECTTYPE_GUN;
|
|
}
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
player->hands[i].matmot1 = 0;
|
|
player->hands[i].matmot2 = 0;
|
|
player->hands[i].matmot3 = 0;
|
|
|
|
bgunSetState(i, HANDSTATE_IDLE);
|
|
}
|
|
|
|
bgunEquipWeapon2(HAND_LEFT, WEAPON_NONE);
|
|
bgunEquipWeapon2(HAND_RIGHT, WEAPON_NONE);
|
|
}
|
|
}
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
bool bgunIsMissionCritical(s32 weaponnum)
|
|
{
|
|
if (weaponnum == WEAPON_TIMEDMINE
|
|
|| weaponnum == WEAPON_REMOTEMINE
|
|
|| weaponnum == WEAPON_ECMMINE
|
|
|| weaponnum == WEAPON_TRACERBUG) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
void bgunDisarm(struct prop *attackerprop)
|
|
{
|
|
struct player *player = g_Vars.currentplayer;
|
|
s32 weaponnum = player->hands[0].gset.weaponnum;
|
|
struct chrdata *chr;
|
|
s32 modelnum;
|
|
s32 i;
|
|
bool drop;
|
|
|
|
if (!weaponHasFlag(weaponnum, WEAPONFLAG_UNDROPPABLE) && weaponnum <= WEAPON_RCP45) {
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
// Coop must not allow player to drop a mission critical weapon
|
|
// because AI lists can fail the mission if the player has zero
|
|
// quantity.
|
|
if (g_Vars.coopplayernum >= 0
|
|
&& (attackerprop == g_Vars.bond->prop || attackerprop == g_Vars.coop->prop)
|
|
&& bgunIsMissionCritical(weaponnum)) {
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if (weaponnum <= WEAPON_UNARMED || player->gunctrl.switchtoweaponnum != -1) {
|
|
return;
|
|
}
|
|
|
|
chr = player->prop->chr;
|
|
drop = true;
|
|
|
|
// RC-P120 and cloaking device: turn off cloak if active
|
|
if (weaponnum == WEAPON_RCP120) {
|
|
g_Vars.currentplayer->devicesactive &= ~DEVICE_CLOAKRCP120;
|
|
}
|
|
|
|
if (weaponnum == WEAPON_CLOAKINGDEVICE) {
|
|
g_Vars.currentplayer->devicesactive &= ~DEVICE_CLOAKDEVICE;
|
|
}
|
|
|
|
// Grenade and nbomb: if pin is pulled, throw it?
|
|
// Or drop it at player's feet with the pin pulled maybe...
|
|
if (weaponnum == WEAPON_GRENADE || weaponnum == WEAPON_NBOMB) {
|
|
for (i = 0; i < 2; i++) {
|
|
struct weaponfunc *func = gsetGetWeaponFunction(&player->hands[i].gset);
|
|
|
|
if ((func->type & 0xff) == INVENTORYFUNCTYPE_THROW
|
|
&& player->hands[i].state == HANDSTATE_ATTACK
|
|
&& player->hands[i].stateminor == 0) {
|
|
drop = false;
|
|
bgunCreateThrownProjectile(i + 2, &player->hands[i].gset);
|
|
}
|
|
}
|
|
}
|
|
|
|
weaponDeleteFromChr(chr, HAND_RIGHT);
|
|
weaponDeleteFromChr(chr, HAND_LEFT);
|
|
|
|
// Actually drop the weapon
|
|
modelnum = playermgrGetModelOfWeapon(weaponnum);
|
|
|
|
if (modelnum >= 0 && drop) {
|
|
struct prop *prop2 = weaponCreateForChr(chr, modelnum, weaponnum, OBJFLAG_WEAPON_AICANNOTUSE, NULL, NULL);
|
|
|
|
if (prop2 && prop2->obj) {
|
|
struct defaultobj *obj = prop2->obj;
|
|
objSetDropped(prop2, DROPTYPE_DEFAULT);
|
|
|
|
if (obj->hidden & OBJHFLAG_PROJECTILE) {
|
|
obj->projectile->pickuptimer240 = TICKS(240);
|
|
obj->projectile->pickupby = attackerprop;
|
|
}
|
|
|
|
objDrop(prop2, true);
|
|
}
|
|
}
|
|
|
|
invRemoveItemByNum(weaponnum);
|
|
|
|
player->hands[1].state = HANDSTATE_IDLE;
|
|
player->hands[1].ejectstate = EJECTSTATE_INIT;
|
|
player->hands[1].ejecttype = EJECTTYPE_GUN;
|
|
player->hands[0].ejectstate = EJECTSTATE_INIT;
|
|
player->hands[0].ejecttype = EJECTTYPE_GUN;
|
|
player->hands[0].state = HANDSTATE_IDLE;
|
|
|
|
// Exit slayer rocket mode if player was using it
|
|
if (player->visionmode == VISIONMODE_SLAYERROCKET) {
|
|
struct weaponobj *rocket = g_Vars.currentplayer->slayerrocket;
|
|
|
|
if (rocket && rocket->base.prop) {
|
|
rocket->timer240 = 0;
|
|
}
|
|
|
|
player->visionmode = VISIONMODE_NORMAL;
|
|
}
|
|
|
|
bgunEquipWeapon2(HAND_RIGHT, WEAPON_UNARMED);
|
|
bgunEquipWeapon2(HAND_LEFT, WEAPON_NONE);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Execute some sort of command list that was generated by the function below.
|
|
*
|
|
* With this function stubbed, part of the CMP150 model does not render.
|
|
*/
|
|
void bgunExecuteModelCmdList(s32 *ptr)
|
|
{
|
|
union modelrwdata *rwdata;
|
|
struct modelnode *node;
|
|
|
|
if (ptr != NULL) {
|
|
while (*ptr != 6) {
|
|
switch (*ptr) {
|
|
case 0:
|
|
rwdata = (union modelrwdata *)ptr[1];
|
|
node = (struct modelnode *)ptr[2];
|
|
rwdata->distance.visible = false;
|
|
node->child = (struct modelnode *)ptr[3];
|
|
ptr += 4;
|
|
break;
|
|
case 1:
|
|
rwdata = (union modelrwdata *)ptr[1];
|
|
node = (struct modelnode *)ptr[2];
|
|
rwdata->toggle.visible = true;
|
|
node->child = (struct modelnode *)ptr[3];
|
|
ptr += 4;
|
|
break;
|
|
case 2:
|
|
rwdata = (union modelrwdata *)ptr[1];
|
|
rwdata->headspot.headmodeldef = NULL;
|
|
rwdata->headspot.rwdatas = NULL;
|
|
ptr += 2;
|
|
break;
|
|
case 3:
|
|
rwdata = (union modelrwdata *)ptr[1];
|
|
rwdata->type0b.unk00 = 0;
|
|
ptr += 2;
|
|
break;
|
|
case 4:
|
|
rwdata = (union modelrwdata *)ptr[1];
|
|
rwdata->chrgunfire.visible = false;
|
|
ptr += 2;
|
|
break;
|
|
case 5:
|
|
rwdata = (union modelrwdata *)ptr[1];
|
|
rwdata->dl.vertices = (struct gfxvtx *)ptr[2];
|
|
rwdata->dl.gdl = (Gfx *)ptr[3];
|
|
rwdata->dl.colours = (struct colour *)ptr[4];
|
|
ptr += 5;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generate some sort of command list to be executed by the function above.
|
|
*
|
|
* This appears to be a performance optimisation, so the tick code can quickly
|
|
* iterate the command list to update part visibility rather than iterate the
|
|
* full model tree.
|
|
*/
|
|
s32 bgunCreateModelCmdList(struct model *model, struct modelnode *nodearg, s32 *ptr)
|
|
{
|
|
s32 len = 0;
|
|
struct modelnode *node = nodearg;
|
|
union modelrodata *rodata;
|
|
union modelrwdata *rwdata;
|
|
|
|
while (node) {
|
|
u32 type = node->type;
|
|
|
|
switch ((u8)type) {
|
|
case MODELNODETYPE_DISTANCE:
|
|
rodata = node->rodata;
|
|
rwdata = modelGetNodeRwData(model, node);
|
|
rwdata->distance.visible = false;
|
|
node->child = rodata->distance.target;
|
|
ptr[0] = 0;
|
|
ptr[1] = (s32)rwdata;
|
|
ptr[2] = (s32)node;
|
|
ptr[3] = (s32)rodata->distance.target;
|
|
ptr += 4;
|
|
len += 16;
|
|
break;
|
|
case MODELNODETYPE_TOGGLE:
|
|
rodata = node->rodata;
|
|
rwdata = modelGetNodeRwData(model, node);
|
|
rwdata->toggle.visible = true;
|
|
node->child = rodata->toggle.target;
|
|
ptr[0] = 1;
|
|
ptr[1] = (s32)rwdata;
|
|
ptr[2] = (s32)node;
|
|
ptr[3] = (s32)rodata->toggle.target;
|
|
ptr += 4;
|
|
len += 16;
|
|
break;
|
|
case MODELNODETYPE_HEADSPOT:
|
|
rwdata = modelGetNodeRwData(model, node);
|
|
rwdata->headspot.headmodeldef = NULL;
|
|
rwdata->headspot.rwdatas = NULL;
|
|
ptr[0] = 2;
|
|
ptr[1] = (s32)rwdata;
|
|
ptr += 2;
|
|
len += 8;
|
|
break;
|
|
case MODELNODETYPE_0B:
|
|
rwdata = modelGetNodeRwData(model, node);
|
|
rwdata->type0b.unk00 = 0;
|
|
ptr[0] = 3;
|
|
ptr[1] = (s32)rwdata;
|
|
ptr += 2;
|
|
len += 8;
|
|
break;
|
|
case MODELNODETYPE_CHRGUNFIRE:
|
|
rwdata = modelGetNodeRwData(model, node);
|
|
rwdata->chrgunfire.visible = false;
|
|
ptr[0] = 4;
|
|
ptr[1] = (s32)rwdata;
|
|
ptr += 2;
|
|
len += 8;
|
|
break;
|
|
case MODELNODETYPE_DL:
|
|
rodata = node->rodata;
|
|
rwdata = modelGetNodeRwData(model, node);
|
|
rwdata->dl.vertices = rodata->dl.vertices;
|
|
rwdata->dl.gdl = rodata->dl.opagdl;
|
|
rwdata->dl.colours = (void *)ALIGN8((uintptr_t)&rodata->dl.vertices[rodata->dl.numvertices]);
|
|
ptr[0] = 5;
|
|
ptr[1] = (s32)rwdata;
|
|
ptr[2] = (s32)rwdata->dl.vertices;
|
|
ptr[3] = (s32)rwdata->dl.gdl;
|
|
ptr[4] = (s32)rwdata->dl.colours;
|
|
ptr += 5;
|
|
len += 20;
|
|
break;
|
|
}
|
|
|
|
if (node->child) {
|
|
node = node->child;
|
|
} else {
|
|
while (node) {
|
|
if (node == nodearg->parent) {
|
|
node = NULL;
|
|
break;
|
|
}
|
|
|
|
if (node->next) {
|
|
node = node->next;
|
|
break;
|
|
}
|
|
|
|
node = node->parent;
|
|
}
|
|
}
|
|
}
|
|
|
|
*ptr = 6;
|
|
len += 4;
|
|
|
|
return len;
|
|
}
|
|
|
|
u32 var800701ec = 0x00000000;
|
|
u32 var800701f0 = 0x00000000;
|
|
u32 var800701f4 = 0x00000000;
|
|
u32 var800701f8 = 0x00000000;
|
|
u32 var800701fc = 0x00000000;
|
|
|
|
struct guncmd var80070200[2] = {
|
|
{ GUNCMD_PLAYANIMATION, 0, ANIM_0434, 10000 },
|
|
{ GUNCMD_END },
|
|
};
|
|
|
|
void bgunStartDetonateAnimation(s32 playernum)
|
|
{
|
|
s32 prevplayernum = g_Vars.currentplayernum;
|
|
setCurrentPlayerNum(playernum);
|
|
|
|
if (g_Vars.currentplayer->hands[HAND_LEFT].gset.weaponnum == WEAPON_REMOTEMINE) {
|
|
bgunStartAnimation(var80070200, 1, &g_Vars.currentplayer->hands[HAND_LEFT]);
|
|
}
|
|
|
|
setCurrentPlayerNum(prevplayernum);
|
|
}
|
|
|
|
/**
|
|
* Update the gangsta-style rotation of the player's gun.
|
|
*
|
|
* When close to an enemy and aiming at them with a pistol, the gun is rotated
|
|
* sideways. The enemy and aiming check is done elsewhere (autoaim code) and
|
|
* sets the gunctrl's gangsta property to true or false based on whether this
|
|
* criteria is met on the current (or previous?) frame.
|
|
*
|
|
* bgunUpdateGangsta uses this property and increments the rotation of the gun
|
|
* accordingly. It also checks that the gun is in a state that allows gangsta
|
|
* rotation (reloading and equip/unequip do not). It also implements a delay on
|
|
* reverting to the normal rotation.
|
|
*/
|
|
void bgunUpdateGangsta(struct hand *hand, s32 handnum, struct coord *arg2, struct weaponfunc *funcdef, Mtxf *arg4, Mtxf *arg5)
|
|
{
|
|
f32 tmp;
|
|
struct coord sp38 = {0, 0, 0};
|
|
|
|
if (g_Vars.currentplayer->gunctrl.gangsta
|
|
&& funcdef
|
|
&& (funcdef->type & 0xff) == INVENTORYFUNCTYPE_SHOOT
|
|
&& (hand->state == HANDSTATE_IDLE
|
|
|| hand->state == HANDSTATE_2
|
|
|| hand->state == HANDSTATE_ATTACKEMPTY
|
|
|| hand->state == HANDSTATE_ATTACK)) {
|
|
if (hand->gangstarot < 1.0f) {
|
|
// Rotate into gangsta position
|
|
hand->ispare1 += g_Vars.lvupdate240;
|
|
|
|
if (hand->ispare1 > TICKS(60)) {
|
|
hand->gangstarot += LVUPDATE60FREAL() / 30.0f;
|
|
|
|
if (hand->gangstarot > 1.0f) {
|
|
hand->gangstarot = 1.0f;
|
|
}
|
|
}
|
|
} else {
|
|
// Already in gangsta position
|
|
hand->ispare1 = 0;
|
|
}
|
|
} else {
|
|
// At this point we don't want the gun to be in the gangsta position.
|
|
// However we don't want it to revert immediately, so a timer is used.
|
|
f32 inversespeed = 30.0f;
|
|
|
|
if (hand->animmode == HANDANIMMODE_BUSY) {
|
|
// Revert faster
|
|
inversespeed = 15.0f;
|
|
}
|
|
|
|
if (hand->gangstarot > 0.0f) {
|
|
bool revert = false;
|
|
|
|
hand->ispare1 += g_Vars.lvupdate240;
|
|
|
|
if (hand->gangstarot < 1.0f) {
|
|
hand->ispare1 = TICKS(244);
|
|
}
|
|
|
|
if (hand->ispare1 > TICKS(120)) {
|
|
revert = true;
|
|
}
|
|
|
|
if (hand->animmode == HANDANIMMODE_BUSY && funcdef && (funcdef->type & 0xff) != INVENTORYFUNCTYPE_SHOOT) {
|
|
revert = true;
|
|
}
|
|
|
|
if (hand->state != HANDSTATE_IDLE
|
|
&& hand->state != HANDSTATE_2
|
|
&& hand->state != HANDSTATE_ATTACKEMPTY
|
|
&& hand->state != HANDSTATE_ATTACK) {
|
|
revert = true;
|
|
}
|
|
|
|
if (revert) {
|
|
hand->gangstarot -= LVUPDATE60FREAL() / inversespeed;
|
|
}
|
|
|
|
if (hand->gangstarot < 0.0f) {
|
|
hand->gangstarot = 0.0f;
|
|
}
|
|
} else {
|
|
// Not rotated
|
|
hand->ispare1 = 0;
|
|
}
|
|
}
|
|
|
|
tmp = -cosf(hand->gangstarot * M_PI) * 0.5f + 0.50f;
|
|
sp38.z = (tmp * 66.6f * 0.017453292f) * (handnum != HAND_RIGHT ? 1.0f : -1.0f);
|
|
|
|
mtx4LoadRotation(&sp38, arg4);
|
|
mtx00015be0(arg4, arg5);
|
|
|
|
arg2->y += 4.0f * hand->gangstarot;
|
|
arg2->x += 2.0f * hand->gangstarot * (handnum != HAND_RIGHT ? 1.0f : -1.0f);
|
|
}
|
|
|
|
/**
|
|
* Check if smoke needs to be created at the muzzle of the current weapon.
|
|
*
|
|
* gunsmokepoint is basically the temperature of the gun. It increases when
|
|
* firing and cools down when idle. It's only used for pistols; automatics will
|
|
* create smoke based on the number of shots in the current burst.
|
|
*
|
|
* createsmoke must be set to create any smoke at all.
|
|
*
|
|
* forcecreatesmoke controls whether smoke should be created while the gun is
|
|
* still firing.
|
|
*/
|
|
void bgunUpdateSmoke(struct hand *hand, s32 handnum, s32 weaponnum, struct weaponfunc *funcdef)
|
|
{
|
|
if (hand->firing) {
|
|
if (weaponnum == WEAPON_DY357MAGNUM || weaponnum == WEAPON_DY357LX) {
|
|
if ((funcdef->type & 0xff) == INVENTORYFUNCTYPE_SHOOT) {
|
|
hand->gunsmokepoint += 0.6f;
|
|
}
|
|
} else {
|
|
hand->gunsmokepoint += 0.2f;
|
|
}
|
|
}
|
|
|
|
hand->gunsmokepoint -= LVUPDATE60FREAL() / 120.0f;
|
|
|
|
if (hand->gunsmokepoint < 0.0f) {
|
|
hand->gunsmokepoint = 0.0f;
|
|
}
|
|
|
|
if (funcdef && (funcdef->type & 0xff) == INVENTORYFUNCTYPE_SHOOT) {
|
|
f32 mult = 1.0f;
|
|
|
|
if (g_Vars.currentplayer->hands[HAND_LEFT].inuse) {
|
|
mult = 1.5f;
|
|
}
|
|
|
|
hand->forcecreatesmoke = false;
|
|
|
|
switch (weaponnum) {
|
|
case WEAPON_FALCON2:
|
|
case WEAPON_FALCON2_SCOPE:
|
|
if (hand->gunsmokepoint * mult > 0.66f) {
|
|
hand->createsmoke = true;
|
|
}
|
|
break;
|
|
case WEAPON_MAGSEC4:
|
|
case WEAPON_MAULER:
|
|
if (hand->gunsmokepoint * mult > 0.75f) {
|
|
hand->createsmoke = true;
|
|
}
|
|
break;
|
|
case WEAPON_DY357MAGNUM:
|
|
case WEAPON_DY357LX:
|
|
if (hand->gunsmokepoint * mult > 0.9f) {
|
|
hand->createsmoke = true;
|
|
}
|
|
break;
|
|
case WEAPON_CMP150:
|
|
case WEAPON_DRAGON:
|
|
case WEAPON_K7AVENGER:
|
|
case WEAPON_AR34:
|
|
case WEAPON_SUPERDRAGON:
|
|
hand->forcecreatesmoke = true;
|
|
|
|
if (hand->burstbullets > 14) {
|
|
hand->createsmoke = true;
|
|
}
|
|
break;
|
|
case WEAPON_CYCLONE:
|
|
case WEAPON_LAPTOPGUN:
|
|
if (hand->burstbullets > 20) {
|
|
hand->createsmoke = true;
|
|
}
|
|
|
|
hand->forcecreatesmoke = true;
|
|
break;
|
|
case WEAPON_RCP120:
|
|
hand->forcecreatesmoke = true;
|
|
|
|
if (hand->burstbullets > 25) {
|
|
hand->createsmoke = true;
|
|
}
|
|
break;
|
|
case WEAPON_REAPER:
|
|
hand->forcecreatesmoke = true;
|
|
// fall-through
|
|
case WEAPON_SHOTGUN:
|
|
if (hand->firing) {
|
|
hand->createsmoke = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (hand->createsmoke && (hand->state != HANDSTATE_ATTACK || hand->forcecreatesmoke)) {
|
|
struct coord smokepos;
|
|
s16 smokerooms[2];
|
|
s32 smoketype = SMOKETYPE_MUZZLE_AUTOMATIC;
|
|
|
|
switch (weaponnum) {
|
|
case WEAPON_FALCON2:
|
|
case WEAPON_FALCON2_SCOPE:
|
|
case WEAPON_MAGSEC4:
|
|
case WEAPON_MAULER:
|
|
case WEAPON_DY357MAGNUM:
|
|
case WEAPON_DY357LX:
|
|
smoketype = SMOKETYPE_MUZZLE_PISTOL;
|
|
break;
|
|
case WEAPON_REAPER:
|
|
smoketype = SMOKETYPE_MUZZLE_REAPER;
|
|
break;
|
|
case WEAPON_SHOTGUN:
|
|
smoketype = SMOKETYPE_MUZZLE_SHOTGUN;
|
|
break;
|
|
}
|
|
|
|
smokerooms[0] = g_Vars.currentplayer->cam_room;
|
|
smokerooms[1] = -1;
|
|
|
|
smokepos.x = hand->muzzlepos.x;
|
|
smokepos.y = hand->muzzlepos.y;
|
|
smokepos.z = hand->muzzlepos.z;
|
|
|
|
hand->gunsmokepoint = 0.0f;
|
|
|
|
if (smokeCreateForHand(&smokepos, smokerooms, smoketype, handnum)) {
|
|
hand->createsmoke = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update the red beam and dot (used by the Falcon 2 and its variants).
|
|
*/
|
|
void bgunUpdateLasersight(struct hand *hand, struct modeldef *modeldef, s32 handnum, u8 *allocation)
|
|
{
|
|
struct modelnode *node;
|
|
struct coord beamfar;
|
|
struct coord dotpos;
|
|
struct coord dotrot;
|
|
struct coord beamnear;
|
|
s32 mtxindex;
|
|
struct coord sp54;
|
|
struct coord sp48;
|
|
struct coord sp3c;
|
|
struct coord sp30;
|
|
bool busy;
|
|
|
|
node = modelGetPart(modeldef, MODELPART_GUN_LASERSIGHT);
|
|
|
|
if (node) {
|
|
mtxindex = modelFindNodeMtxIndex(node, 0);
|
|
|
|
beamnear.x = ((Mtxf *)((uintptr_t)allocation + mtxindex * sizeof(Mtxf)))->m[3][0];
|
|
beamnear.y = ((Mtxf *)((uintptr_t)allocation + mtxindex * sizeof(Mtxf)))->m[3][1];
|
|
beamnear.z = ((Mtxf *)((uintptr_t)allocation + mtxindex * sizeof(Mtxf)))->m[3][2];
|
|
|
|
mtx4TransformVecInPlace(camGetProjectionMtxF(), &beamnear);
|
|
|
|
if (hand->useposrot
|
|
|| (g_Vars.currentplayer->devicesactive & ~g_Vars.currentplayer->devicesinhibit & DEVICE_XRAYSCANNER)) {
|
|
beamfar.x = 0.0f;
|
|
beamfar.y = 0.0f;
|
|
beamfar.z = 1.0f;
|
|
|
|
mtx4RotateVecInPlace(&hand->cammtx, &beamfar);
|
|
|
|
sp48.x = beamfar.x;
|
|
sp48.y = beamfar.y;
|
|
sp48.z = beamfar.z;
|
|
|
|
sp3c.x = beamnear.x;
|
|
sp3c.y = beamnear.y;
|
|
sp3c.z = beamnear.z;
|
|
|
|
mtx4TransformVec(camGetWorldToScreenMtxf(), &sp3c, &sp54);
|
|
mtx4RotateVec(camGetProjectionMtxF(), &sp48, &sp30);
|
|
|
|
beamfar.x *= 500.0f;
|
|
beamfar.y *= 500.0f;
|
|
beamfar.z *= 500.0f;
|
|
|
|
mtx4RotateVecInPlace(camGetProjectionMtxF(), &beamfar);
|
|
|
|
beamfar.x += beamnear.x;
|
|
beamfar.y += beamnear.y;
|
|
beamfar.z += beamnear.z;
|
|
|
|
lasersightSetBeam(handnum, 1, &beamnear, &beamfar);
|
|
return;
|
|
}
|
|
|
|
busy = false;
|
|
|
|
if (hand->animmode == HANDANIMMODE_BUSY) {
|
|
busy = true;
|
|
}
|
|
|
|
if (busy) {
|
|
mtxindex = modelFindNodeMtxIndex(node, 0);
|
|
|
|
beamfar.x = 0.0f;
|
|
beamfar.y = 0.0f;
|
|
beamfar.z = 500.0f;
|
|
|
|
mtx4TransformVecInPlace((Mtxf *)((uintptr_t)allocation + mtxindex * sizeof(Mtxf)), &beamfar);
|
|
} else {
|
|
cam0f0b4c3c(g_Vars.currentplayer->crosspos, &beamfar, 1);
|
|
|
|
beamfar.x *= 500.0f;
|
|
beamfar.y *= 500.0f;
|
|
beamfar.z *= 500.0f;
|
|
}
|
|
|
|
mtx4TransformVecInPlace(camGetProjectionMtxF(), &beamfar);
|
|
lasersightSetBeam(handnum, 1, &beamnear, &beamfar);
|
|
|
|
if (handnum == HAND_RIGHT && hand->hasdotinfo && !busy) {
|
|
dotpos.x = hand->dotpos.x;
|
|
dotpos.y = hand->dotpos.y;
|
|
dotpos.z = hand->dotpos.z;
|
|
|
|
dotrot.x = hand->dotrot.x;
|
|
dotrot.y = hand->dotrot.y;
|
|
dotrot.z = hand->dotrot.z;
|
|
|
|
lasersightSetDot(handnum, &dotpos, &dotrot);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Increment the main barrel spinning, play sounds and (probably) fire shots.
|
|
*/
|
|
void bgunUpdateReaper(struct hand *hand, struct modeldef *modeldef)
|
|
{
|
|
struct modelnode *node;
|
|
f32 f2;
|
|
f32 f12;
|
|
s32 tmp;
|
|
|
|
node = modelGetPart(modeldef, MODELPART_REAPER_002C);
|
|
|
|
if (hand->matmot3 <= hand->matmot2) {
|
|
if (hand->matmot2 < 0.0f) {
|
|
hand->matmot2 += 0.01f * LVUPDATE60FREAL();
|
|
|
|
if (hand->matmot2 > 0.0f) {
|
|
hand->matmot2 = 0.0f;
|
|
}
|
|
}
|
|
|
|
hand->matmot3 = hand->matmot2;
|
|
} else {
|
|
f12 = LVUPDATE60FREAL() * 0.005;
|
|
|
|
if (hand->matmot2 < 0.0000001f) {
|
|
hand->matmot2 = -0.14f;
|
|
|
|
if (hand->matmot3 < 0.15f) {
|
|
f12 *= 4.0f;
|
|
}
|
|
}
|
|
|
|
f2 = hand->matmot3 - hand->matmot2;
|
|
|
|
if (f12 < f2) {
|
|
f2 = f12;
|
|
}
|
|
|
|
hand->matmot3 -= f2;
|
|
}
|
|
|
|
if (hand->matmot3 < 0.0f) {
|
|
hand->matmot1 = hand->matmot1 - (1.0f - cosf(hand->matmot3 * M_PI)) * 0.5f * LVUPDATE60FREAL() * 0.2f;
|
|
} else {
|
|
hand->matmot1 = hand->matmot1 + (1.0f - cosf(hand->matmot3 * M_PI)) * 0.5f * LVUPDATE60FREAL() * 0.2f;
|
|
}
|
|
|
|
tmp = hand->matmot1 / 6.2831802368164f;
|
|
hand->matmot1 -= tmp * 6.2831802368164f;
|
|
var8009d140 = hand->matmot1;
|
|
|
|
if (hand->audiohandle == NULL && hand->matmot3 > 0.1f && g_Vars.lvupdate240 != 0) {
|
|
sndStart(var80095200, SFX_805E, &hand->audiohandle, -1, -1, -1.0f, -1, -1);
|
|
}
|
|
|
|
if (hand->audiohandle != NULL) {
|
|
f32 sp34 = hand->matmot3 / 0.50f + 0.4f;
|
|
s32 a2 = 0x7fff;
|
|
|
|
if (hand->matmot3 < 0.1f) {
|
|
audioStop(hand->audiohandle);
|
|
} else {
|
|
if (hand->matmot3 < 0.6f) {
|
|
a2 = (hand->matmot3 - 0.1f) * 32767.0f / 0.5f;
|
|
}
|
|
|
|
audioPostEvent(hand->audiohandle, 8, a2);
|
|
audioPostEvent(hand->audiohandle, 0x10, *(s32 *)&sp34);
|
|
}
|
|
}
|
|
|
|
if (node) {
|
|
var8009d0dc = modelFindNodeMtxIndex(node, 0);
|
|
g_ModelJointPositionedFunc = bgun0f0a256c;
|
|
var8009d0f0[0] = var8009d0f0[1] = var8009d0f0[2] = -1;
|
|
}
|
|
|
|
node = modelGetPart(modeldef, MODELPART_REAPER_002D);
|
|
|
|
if (node) {
|
|
var8009d0f0[0] = modelFindNodeMtxIndex(node, 0);
|
|
}
|
|
|
|
node = modelGetPart(modeldef, MODELPART_REAPER_002E);
|
|
|
|
if (node) {
|
|
var8009d0f0[1] = modelFindNodeMtxIndex(node, 0);
|
|
}
|
|
|
|
node = modelGetPart(modeldef, MODELPART_REAPER_002F);
|
|
|
|
if (node) {
|
|
var8009d0f0[2] = modelFindNodeMtxIndex(node, 0);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Move/extend the scope on the gun model when the zoom function is used.
|
|
*/
|
|
void bgunUpdateSniperRifle(struct modeldef *modeldef, u8 *allocation)
|
|
{
|
|
struct modelnode *nodes[4];
|
|
f32 sp88[4] = {0, 0, 0, 0};
|
|
s32 i;
|
|
f32 f26;
|
|
s32 mtxindex;
|
|
struct coord sp70;
|
|
|
|
f26 = 1.0f - (currentPlayerGetGunZoomFov() - 2.0f) / 58.0f;
|
|
|
|
nodes[0] = modelGetPart(modeldef, MODELPART_SNIPERRIFLE_SCOPE1);
|
|
nodes[1] = modelGetPart(modeldef, MODELPART_SNIPERRIFLE_SCOPE2);
|
|
nodes[2] = modelGetPart(modeldef, MODELPART_SNIPERRIFLE_SCOPE3);
|
|
nodes[3] = modelGetPart(modeldef, MODELPART_SNIPERRIFLE_SCOPE4);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
if (nodes[i]) {
|
|
f32 f20 = f26 * 4.0f;
|
|
mtxindex = modelFindNodeMtxIndex(nodes[i], 0);
|
|
sp88[i] = f20 - i;
|
|
|
|
if (f20 < i) {
|
|
sp88[i] = 0.0f;
|
|
}
|
|
|
|
sp88[i] *= 100.0f;
|
|
|
|
sp70.x = 0.0f;
|
|
sp70.y = 0.0f;
|
|
sp70.z = sp88[i];
|
|
|
|
mtx4RotateVecInPlace((Mtxf *)((uintptr_t)allocation + mtxindex * sizeof(Mtxf)), &sp70);
|
|
|
|
((Mtxf *)((uintptr_t)allocation + mtxindex * sizeof(Mtxf)))->m[3][0] += sp70.x;
|
|
((Mtxf *)((uintptr_t)allocation + mtxindex * sizeof(Mtxf)))->m[3][1] += sp70.y;
|
|
((Mtxf *)((uintptr_t)allocation + mtxindex * sizeof(Mtxf)))->m[3][2] += sp70.z;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Animate the cartridge slider thing in the Devastator model.
|
|
*/
|
|
void bgunUpdateDevastator(struct hand *hand, u8 *allocation, struct modeldef *modeldef)
|
|
{
|
|
struct modelnode *node = modelGetPart(modeldef, MODELPART_DEVASTATOR_0028);
|
|
|
|
if (node) {
|
|
s32 mtxindex = modelFindNodeMtxIndex(node, 0);
|
|
struct coord sp24;
|
|
|
|
hand->loadslide += 0.01f * LVUPDATE60FREAL();
|
|
|
|
if (hand->loadslide > 1.0f) {
|
|
hand->loadslide = 1.0f;
|
|
}
|
|
|
|
sp24.x = hand->loadslide * -10.0f * 1.636f;
|
|
sp24.y = 0.0f;
|
|
sp24.z = 0.0f;
|
|
|
|
mtx4RotateVecInPlace((Mtxf *)((uintptr_t)allocation + mtxindex * sizeof(Mtxf)), &sp24);
|
|
|
|
((Mtxf *)((uintptr_t)allocation + mtxindex * sizeof(Mtxf)))->m[3][0] += sp24.x;
|
|
((Mtxf *)((uintptr_t)allocation + mtxindex * sizeof(Mtxf)))->m[3][1] += sp24.y;
|
|
((Mtxf *)((uintptr_t)allocation + mtxindex * sizeof(Mtxf)))->m[3][2] += sp24.z;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Display the shotgun's starburst when appropriate.
|
|
*
|
|
* This logic is different to most guns, likely because most guns display the
|
|
* starburst when the trigger is pressed while the shotgun has the double blast
|
|
* function.
|
|
*/
|
|
void bgunUpdateShotgun(struct hand *hand, u8 *allocation, bool *arg2, struct modeldef *modeldef)
|
|
{
|
|
if (hand->flashon) {
|
|
hand->matmot1 = 1.0f;
|
|
}
|
|
|
|
if (hand->matmot1 > 0.0f) {
|
|
hand->matmot1 -= LVUPDATE60FREAL() / 6.0f;
|
|
|
|
if (hand->matmot1 < 0.01f) {
|
|
hand->matmot1 = 0.0f;
|
|
}
|
|
}
|
|
|
|
if (hand->matmot1 > 0.0f) {
|
|
s32 sp34;
|
|
s32 sp28[3] = {0, 0, 0};
|
|
struct modelnode *node = modelGetPart(modeldef, MODELPART_SHOTGUN_0050);
|
|
|
|
*arg2 = true;
|
|
|
|
if (node) {
|
|
sp34 = modelFindNodeMtxIndex(node, 0);
|
|
|
|
mtx00015ea8((1.0f - hand->matmot1) * 8.0f + 0.5f, (Mtxf *)((uintptr_t)allocation + sp34 * sizeof(Mtxf)));
|
|
mtx00015df0((1.0f - hand->matmot1) * 3.0f + 1.0f, (Mtxf *)((uintptr_t)allocation + sp34 * sizeof(Mtxf)));
|
|
mtx00015e4c((1.0f - hand->matmot1) * 3.0f + 1.0f, (Mtxf *)((uintptr_t)allocation + sp34 * sizeof(Mtxf)));
|
|
}
|
|
}
|
|
}
|
|
|
|
void bgunUpdateLaser(struct hand *hand)
|
|
{
|
|
if (hand->firing && hand->gset.weaponfunc == FUNC_SECONDARY) {
|
|
if (hand->audiohandle == NULL && g_Vars.lvupdate240 != 0) {
|
|
sndStart(var80095200, SFX_LASER_STREAM, &hand->audiohandle, -1, -1, -1, -1, -1);
|
|
}
|
|
|
|
hand->matmot1 = 1;
|
|
return;
|
|
}
|
|
|
|
if (hand->matmot1 > 0) {
|
|
hand->matmot1 -= LVUPDATE60FREAL() / 10.0f;
|
|
} else if (hand->audiohandle != NULL && sndGetState(hand->audiohandle) != AL_STOPPED) {
|
|
audioStop(hand->audiohandle);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create ammo casing so they can be ejected during reload.
|
|
*/
|
|
void bgunUpdateMagnum(struct hand *hand, s32 handnum, struct modeldef *modeldef, Mtxf *mtx)
|
|
{
|
|
f32 ground = g_Vars.currentplayer->vv_ground;
|
|
s32 i;
|
|
|
|
if (modeldef != NULL) {
|
|
for (i = 0; i < hand->unk0cc8_04; i++) {
|
|
struct modelnode *node = modelGetPart(modeldef, 0x0a + random() % 6);
|
|
|
|
if (node) {
|
|
s32 index = modelFindNodeMtxIndex(node, 0);
|
|
Mtxf *tmp = mtx;
|
|
Mtxf sp4c;
|
|
|
|
tmp += index;
|
|
|
|
mtx4Copy(tmp, &sp4c);
|
|
mtx00015f04(9.999999f, &sp4c);
|
|
mtx4MultMtx4InPlace(camGetProjectionMtxF(), &sp4c);
|
|
|
|
casingCreateForHand(handnum, ground, &sp4c);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create and/or update the rocket prop that sits inside the rocket launcher.
|
|
*/
|
|
void bgunUpdateRocketLauncher(struct hand *hand, s32 handnum, struct weaponfunc_shootprojectile *func)
|
|
{
|
|
if (hand->rocket == NULL && hand->loadedammo[0] > 0) {
|
|
bgunCreateHeldRocket(handnum, func);
|
|
}
|
|
|
|
if (hand->rocket) {
|
|
bgunUpdateHeldRocket(handnum);
|
|
}
|
|
}
|
|
|
|
void bgun0f0a45d0(struct hand *hand, struct modeldef *modeldef, bool isdetonator)
|
|
{
|
|
struct modelnode *node = NULL;
|
|
|
|
switch (hand->ejecttype) {
|
|
case EJECTTYPE_GUN:
|
|
if (isdetonator) {
|
|
node = modelGetPart(modeldef, 0x2a);
|
|
} else {
|
|
node = modelGetPart(modeldef, 0x37);
|
|
}
|
|
break;
|
|
case EJECTTYPE_GRENADEPIN:
|
|
node = modelGetPart(modeldef, 0x2b);
|
|
break;
|
|
case EJECTTYPE_TRANQCASE:
|
|
node = modelGetPart(modeldef, 0x2b);
|
|
break;
|
|
}
|
|
|
|
if (node) {
|
|
var8009d148 = modelFindNodeMtxIndex(node, 0);
|
|
g_ModelJointPositionedFunc = bgun0f0a256c;
|
|
} else {
|
|
var8009d148 = -1;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* With this function stubbed, the tranquilizer's spent ammo does not detach
|
|
* when reloading, and the pulled pin on grenades and nbombs appears to move
|
|
* with the model rather than detaching properly.
|
|
*/
|
|
void bgunTickEject(struct hand *hand, struct modeldef *modeldef, bool isdetonator)
|
|
{
|
|
f32 lvupdate;
|
|
struct coord spd0;
|
|
Mtxf sp90;
|
|
struct coord sp84;
|
|
Mtxf sp44;
|
|
s32 i;
|
|
f32 newval;
|
|
f32 mult = 3;
|
|
|
|
switch (hand->ejectstate) {
|
|
case EJECTSTATE_INIT:
|
|
switch (hand->ejecttype) {
|
|
case EJECTTYPE_GUN:
|
|
hand->unk0d20.f[0] = (RANDOMFRAC() - 0.5f) * 0.5333333f * 0.0625f + 0.5333333f;
|
|
hand->unk0d20.f[1] = RANDOMFRAC() * 2.5f * 0.0625f + 2.5f;
|
|
hand->unk0d20.f[2] = 0.0f;
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
spd0.f[0] = RANDOMFRAC() * PALUPF(2.0f * M_BADTAU) / 184.0f - 0.03414231f;
|
|
spd0.f[1] = RANDOMFRAC() * PALUPF(2.0f * M_BADTAU) / 184.0f - 0.03414231f;
|
|
spd0.f[2] = RANDOMFRAC() * PALUPF(2.0f * M_BADTAU) / 184.0f - 0.03414231f;
|
|
#else
|
|
spd0.f[0] = RANDOMFRAC() * 2.0f * M_BADTAU / 184.0f - 0.03414231f;
|
|
spd0.f[1] = RANDOMFRAC() * 2.0f * M_BADTAU / 184.0f - 0.03414231f;
|
|
spd0.f[2] = RANDOMFRAC() * 2.0f * M_BADTAU / 184.0f - 0.03414231f;
|
|
#endif
|
|
break;
|
|
case EJECTTYPE_GRENADEPIN:
|
|
hand->unk0d20.f[0] = -((RANDOMFRAC() - 0.5f) * 0.5333333f * 0.0625f + mult * 0.5333333f);
|
|
hand->unk0d20.f[1] = RANDOMFRAC() * 2.5f * 0.125f + 2.5f;
|
|
hand->unk0d20.f[2] = -(RANDOMFRAC() + 1.0f);
|
|
spd0.f[0] = (RANDOMFRAC() + 3.0f) * PALUPF(M_BADTAU) / 208.0f;
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
spd0.f[1] = RANDOMFRAC() * PALUPF(2.0f * M_BADTAU) / 544.0f - 0.0115481345f;
|
|
spd0.f[2] = RANDOMFRAC() * PALUPF(2.0f * M_BADTAU) / 544.0f - 0.0115481345f;
|
|
#else
|
|
spd0.f[1] = RANDOMFRAC() * 2.0f * M_BADTAU / 544.0f - 0.0115481345f;
|
|
spd0.f[2] = RANDOMFRAC() * 2.0f * M_BADTAU / 544.0f - 0.0115481345f;
|
|
#endif
|
|
break;
|
|
case EJECTTYPE_TRANQCASE:
|
|
hand->unk0d20.f[0] = 0.0f;
|
|
hand->unk0d20.f[1] = RANDOMFRAC() * 2.5f * 0.125f + 2.5f;
|
|
hand->unk0d20.f[2] = (RANDOMFRAC() + 1.0f) * 0.25f;
|
|
spd0.f[0] = (RANDOMFRAC() + 3.0f) * PALUPF(M_BADTAU) / 368.0f;
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
spd0.f[1] = RANDOMFRAC() * PALUPF(2.0f * M_BADTAU) / 944.0f - 0.006654857f;
|
|
spd0.f[2] = RANDOMFRAC() * PALUPF(2.0f * M_BADTAU) / 944.0f - 0.006654857f;
|
|
#else
|
|
spd0.f[1] = RANDOMFRAC() * 2.0f * M_BADTAU / 944.0f - 0.006654857f;
|
|
spd0.f[2] = RANDOMFRAC() * 2.0f * M_BADTAU / 944.0f - 0.006654857f;
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
hand->unk0d10 = hand->unk0d14 - 200.0f;
|
|
|
|
mtx4LoadRotation(&spd0, &sp90);
|
|
mtx4ToMtx3(&sp90, hand->unk0d50);
|
|
|
|
if (g_Vars.lvupdate240 > 0 && hand->ejecttype != EJECTTYPE_GUN) {
|
|
sp84.f[0] = (hand->posmtx.m[3][0] - hand->prevmtx.m[3][0]) / g_Vars.lvupdate60freal;
|
|
sp84.f[1] = (hand->posmtx.m[3][1] - hand->prevmtx.m[3][1]) / g_Vars.lvupdate60freal;
|
|
sp84.f[2] = (hand->posmtx.m[3][2] - hand->prevmtx.m[3][2]) / g_Vars.lvupdate60freal;
|
|
|
|
mtx00017588(hand->posmtx.m, sp44.m);
|
|
mtx4RotateVecInPlace(&sp44, &sp84);
|
|
|
|
hand->unk0d20.f[0] += sp84.f[0] * 0.3f;
|
|
hand->unk0d20.f[1] += sp84.f[1] * 0.3f;
|
|
hand->unk0d20.f[2] += sp84.f[2] * 0.3f;
|
|
}
|
|
|
|
hand->ejectstate = EJECTSTATE_AIRBORNE;
|
|
break;
|
|
case EJECTSTATE_AIRBORNE:
|
|
lvupdate = g_Vars.lvupdate60freal;
|
|
|
|
if (g_Vars.currentplayer->isdead && lvupdate > 1.5f) {
|
|
lvupdate = 1.5f;
|
|
}
|
|
|
|
newval = hand->unk0d20.f[1] - lvupdate * 0.2777778f;
|
|
|
|
if (hand->unk0d18 < hand->unk0d10) {
|
|
hand->ejectstate = EJECTSTATE_FINISHED;
|
|
break;
|
|
}
|
|
|
|
hand->unk0d18 += lvupdate * 0.5f * (hand->unk0d20.f[1] + newval);
|
|
hand->unk0d14 += lvupdate * hand->unk0d20.f[0];
|
|
hand->unk0d1c += lvupdate * hand->unk0d20.f[2];
|
|
|
|
hand->unk0d20.f[1] = newval;
|
|
|
|
for (i = 0; i < g_Vars.lvupdate240; i++) {
|
|
mtx00016110(hand->unk0d50, hand->unk0d2c);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
void bgun0f0a4e44(struct hand *hand, struct weapon *weapondef, struct modeldef *modeldef,
|
|
struct weaponfunc *funcdef, s32 maxburst, u8 *allocation, s32 weaponnum,
|
|
bool **arg7, s32 mtxindex, Mtxf *arg9, Mtxf *arg10)
|
|
{
|
|
Mtxf spd8;
|
|
s32 index;
|
|
s32 shotstotake;
|
|
bool spc4[3] = {false, false, false};
|
|
Mtxf *mtx;
|
|
s32 i;
|
|
s32 partnum;
|
|
f32 spb4;
|
|
f32 muzzlez;
|
|
Mtxf sp70;
|
|
|
|
index = hand->burstbullets % maxburst;
|
|
shotstotake = hand->shotstotake;
|
|
|
|
spb4 = RANDOMFRAC() * 0.25f + 1.0f;
|
|
muzzlez = weapondef->muzzlez;
|
|
|
|
mtx4LoadIdentity(&spd8);
|
|
|
|
if (funcdef && (funcdef->flags & FUNCFLAG_00000001)) {
|
|
mtx4LoadZRotation(RANDOMFRAC() * M_BADTAU, &spd8);
|
|
}
|
|
|
|
mtx4LoadZRotation((RANDOMFRAC() * 0.3 - 0.15), &spd8);
|
|
|
|
mtx = (Mtxf *)allocation;
|
|
mtx += mtxindex;
|
|
|
|
mtx4MultMtx4InPlace(mtx, &spd8);
|
|
mtx00015f04(spb4, &spd8);
|
|
mtx00015ea8(muzzlez, &spd8);
|
|
mtx4Copy(&spd8, mtx);
|
|
|
|
if (shotstotake == 0 && weaponnum != WEAPON_REAPER) {
|
|
shotstotake++;
|
|
}
|
|
|
|
for (i = 0; i < shotstotake; i++) {
|
|
spc4[index] = true;
|
|
index++;
|
|
|
|
if (index >= maxburst) {
|
|
index = 0;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < maxburst; i++) {
|
|
if (spc4[i] && arg7[i] != NULL) {
|
|
*arg7[i] = true;
|
|
}
|
|
}
|
|
|
|
for (partnum = 0x50; partnum <= 0x52; partnum++) {
|
|
struct modelnode *node = modelGetPart(modeldef, partnum);
|
|
struct coord sp60;
|
|
|
|
if (node && weaponnum != WEAPON_REAPER && weaponnum != WEAPON_SHOTGUN) {
|
|
struct modelrodata_position *rodata = &node->rodata->position;
|
|
s32 mtxindex = modelFindNodeMtxIndex(node, 0);
|
|
|
|
sp60.x = rodata->pos.x * spd8.m[0][0] + rodata->pos.y * spd8.m[1][0] + rodata->pos.z * spd8.m[2][0] + spd8.m[3][0];
|
|
sp60.y = rodata->pos.x * spd8.m[0][1] + rodata->pos.y * spd8.m[1][1] + rodata->pos.z * spd8.m[2][1] + spd8.m[3][1];
|
|
sp60.z = rodata->pos.x * spd8.m[0][2] + rodata->pos.y * spd8.m[1][2] + rodata->pos.z * spd8.m[2][2] + spd8.m[3][2];
|
|
|
|
mtx4LoadIdentity(&sp70);
|
|
mtx4Align(sp70.m, RANDOMFRAC() * M_BADTAU, -sp60.x, -sp60.y, -sp60.z);
|
|
mtx00015f04(0.10000001f * spb4, &sp70);
|
|
|
|
mtx = (Mtxf *)allocation;
|
|
|
|
mtx00016e98(arg10->m, 0, mtx->m[3][0] - hand->aimpos.x, mtx->m[3][1] - hand->aimpos.y, mtx->m[3][2] - hand->aimpos.z);
|
|
mtx4MultMtx4InPlace(arg10, &sp70);
|
|
mtx00016710(muzzlez, sp70.m);
|
|
mtx4MultMtx4InPlace(arg9, &sp70);
|
|
mtx4SetTranslation(&sp60, &sp70);
|
|
|
|
mtx = (Mtxf *)allocation;
|
|
mtx += mtxindex;
|
|
|
|
mtx4Copy(&sp70, mtx);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create casing and beam for a fired weapon,
|
|
* and uncloak if the weapon is a throwable or fired projectile.
|
|
*/
|
|
void bgunCreateFx(struct hand *hand, s32 handnum, struct weaponfunc *funcdef, s32 weaponnum, struct modeldef *modeldef, u8 *allocation)
|
|
{
|
|
f32 ground;
|
|
bool createbeam = true;
|
|
|
|
g_Vars.currentplayer->gunctrl.unk1583_04 = false;
|
|
|
|
if (funcdef) {
|
|
ground = g_Vars.currentplayer->vv_ground;
|
|
|
|
if (modeldef && weaponnum != WEAPON_DY357MAGNUM && weaponnum != WEAPON_DY357LX) {
|
|
s32 partnum = MODELPART_GUN_CARTEJECTPOS;
|
|
struct modelnode *node;
|
|
|
|
if (weaponnum == WEAPON_REAPER) {
|
|
partnum = (hand->burstbullets & 1) == 1 ? MODELPART_REAPER_CARTEJECTPOS1 : MODELPART_REAPER_CARTEJECTPOS2;
|
|
}
|
|
|
|
node = modelGetPart(modeldef, partnum);
|
|
|
|
if (node) {
|
|
Mtxf *mtx = (Mtxf *)allocation;
|
|
Mtxf sp24;
|
|
|
|
mtx += modelFindNodeMtxIndex(node, 0);
|
|
|
|
mtx4Copy(mtx, &sp24);
|
|
mtx00015f04(9.999999f, &sp24);
|
|
mtx4MultMtx4InPlace(camGetProjectionMtxF(), &sp24);
|
|
|
|
casingCreateForHand(handnum, ground, &sp24);
|
|
} else {
|
|
casingCreateForHand(handnum, ground, &hand->posmtx);
|
|
}
|
|
|
|
bgunSetPartVisible(MODELPART_GUN_CARTFLAPCLOSED, false, hand, modeldef);
|
|
bgunSetPartVisible(MODELPART_GUN_CARTFLAPOPEN, true, hand, modeldef);
|
|
}
|
|
|
|
if (funcdef->type == INVENTORYFUNCTYPE_SHOOT_PROJECTILE) {
|
|
chrUncloakTemporarily(g_Vars.currentplayer->prop->chr);
|
|
} else if ((funcdef->type & 0xff) == INVENTORYFUNCTYPE_THROW) {
|
|
chrUncloakTemporarily(g_Vars.currentplayer->prop->chr);
|
|
}
|
|
}
|
|
|
|
if (funcdef) {
|
|
if ((funcdef->type & 0xff) == INVENTORYFUNCTYPE_MELEE || (funcdef->type & INVENTORYFUNCTYPE_0200)) {
|
|
createbeam = false;
|
|
}
|
|
|
|
if ((funcdef->type & 0xff) == INVENTORYFUNCTYPE_SPECIAL) {
|
|
createbeam = false;
|
|
}
|
|
|
|
if ((funcdef->type & 0xff) == INVENTORYFUNCTYPE_THROW) {
|
|
createbeam = false;
|
|
}
|
|
}
|
|
|
|
if (createbeam) {
|
|
switch (weaponnum) {
|
|
case WEAPON_FALCON2:
|
|
case WEAPON_FALCON2_SILENCER:
|
|
case WEAPON_FALCON2_SCOPE:
|
|
case WEAPON_MAGSEC4:
|
|
case WEAPON_MAULER:
|
|
case WEAPON_PHOENIX:
|
|
case WEAPON_DY357MAGNUM:
|
|
case WEAPON_DY357LX:
|
|
case WEAPON_CMP150:
|
|
case WEAPON_CYCLONE:
|
|
case WEAPON_CALLISTO:
|
|
case WEAPON_RCP120:
|
|
case WEAPON_LAPTOPGUN:
|
|
case WEAPON_DRAGON:
|
|
case WEAPON_K7AVENGER:
|
|
case WEAPON_AR34:
|
|
case WEAPON_SUPERDRAGON:
|
|
case WEAPON_REAPER:
|
|
case WEAPON_SNIPERRIFLE:
|
|
case WEAPON_FARSIGHT:
|
|
case WEAPON_TRANQUILIZER:
|
|
case WEAPON_PP9I:
|
|
case WEAPON_CC13:
|
|
case WEAPON_KL01313:
|
|
case WEAPON_KF7SPECIAL:
|
|
case WEAPON_ZZT:
|
|
case WEAPON_DMC:
|
|
case WEAPON_AR53:
|
|
case WEAPON_RCP45:
|
|
beamCreateForHand(handnum);
|
|
hand->numfires++;
|
|
return;
|
|
case WEAPON_LASER:
|
|
hand->numfires++;
|
|
beamCreateForHand(handnum);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void bgun0f0a5550(s32 handnum)
|
|
{
|
|
u8 *mtxallocation;
|
|
Mtxf sp2c4;
|
|
Mtxf sp284;
|
|
struct modeldef *modeldef = NULL;
|
|
struct coord sp274 = {0, 0, 0};
|
|
Mtxf sp234;
|
|
Mtxf sp1f4;
|
|
union modelrodata *rodata;
|
|
bool *sp1e4[3] = {NULL, NULL, NULL};
|
|
s32 sp1e0 = 0;
|
|
struct modelnode *node;
|
|
struct player *player = g_Vars.currentplayer;
|
|
struct hand *hand = player->hands + handnum;
|
|
struct weaponfunc *funcdef;
|
|
struct weaponfunc_shoot *shootfunc = NULL;
|
|
s32 i;
|
|
s32 weaponnum = bgunGetWeaponNum2(handnum);
|
|
struct weapon *weapondef;
|
|
Mtxf *mtx;
|
|
bool isdetonator = false;
|
|
f32 fspare1;
|
|
f32 fspare2;
|
|
struct coord sp1a4;
|
|
Mtxf sp164;
|
|
Mtxf sp124;
|
|
struct coord sp118;
|
|
s32 j;
|
|
|
|
weapondef = weaponFindById(weaponnum);
|
|
|
|
if (handnum == HAND_LEFT && weaponnum == WEAPON_REMOTEMINE) {
|
|
isdetonator = true;
|
|
}
|
|
|
|
funcdef = gsetGetWeaponFunction2(&hand->gset);
|
|
|
|
if (funcdef && (funcdef->type & 0xff) == INVENTORYFUNCTYPE_SHOOT) {
|
|
shootfunc = (struct weaponfunc_shoot *)funcdef;
|
|
}
|
|
|
|
bgunUpdateBlend(hand, handnum);
|
|
|
|
if (handnum == HAND_RIGHT) {
|
|
if (weaponHasFlag(bgunGetWeaponNum2(HAND_LEFT), WEAPONFLAG_00000040)) {
|
|
hand->xshift += 2.0f * g_Vars.lvupdate60freal / 240.0f;
|
|
|
|
if (hand->xshift > 2.0f) {
|
|
hand->xshift = 2.0f;
|
|
}
|
|
} else {
|
|
hand->xshift -= 2.0f * g_Vars.lvupdate60freal / 240.0f;
|
|
|
|
if (hand->xshift < 0.0f) {
|
|
hand->xshift = 0.0f;
|
|
}
|
|
}
|
|
} else {
|
|
if (weaponHasFlag(bgunGetWeaponNum2(HAND_RIGHT), WEAPONFLAG_00000040)) {
|
|
hand->xshift -= 2.0f * g_Vars.lvupdate60freal / 240.0f;
|
|
|
|
if (hand->xshift < -2.0f) {
|
|
hand->xshift = -2.0f;
|
|
}
|
|
} else {
|
|
hand->xshift += 2.0f * g_Vars.lvupdate60freal / 240.0f;
|
|
|
|
if (hand->xshift > 0.0f) {
|
|
hand->xshift = 0.0f;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (handnum == HAND_RIGHT) {
|
|
sp274.x = func0f0b131c(handnum) + hand->damppos.f[0] + hand->adjustpos.f[0];
|
|
sp274.y = weapondef->posy + hand->damppos.f[1] + hand->adjustpos.f[1];
|
|
sp274.z = weapondef->posz + hand->damppos.f[2] + hand->adjustpos.f[2];
|
|
} else if (isdetonator) {
|
|
sp274.x = 6.5f + hand->damppos.f[0] - hand->adjustpos.f[0];
|
|
sp274.y = -16.5f + hand->damppos.f[1] + hand->adjustpos.f[1];
|
|
sp274.z = -16.0f + hand->damppos.f[2] + hand->adjustpos.f[2];
|
|
} else {
|
|
sp274.x = func0f0b131c(handnum) + hand->damppos.f[0] - hand->adjustpos.f[0];
|
|
sp274.y = weapondef->posy + hand->damppos.f[1] + hand->adjustpos.f[1];
|
|
sp274.z = weapondef->posz + hand->damppos.f[2] + hand->adjustpos.f[2];
|
|
}
|
|
|
|
sp274.y += player->guncloseroffset * 5.0f / -90.0f * 50.0f;
|
|
sp274.z -= player->guncloseroffset * 15.0f / -90.0f * 50.0f;
|
|
|
|
if (hand->firing && shootfunc && g_Vars.lvupdate240 != 0 && shootfunc->recoilsettings != NULL) {
|
|
sp274.x += (RANDOMFRAC() - 0.5f) * shootfunc->recoilsettings->xrange * hand->finalmult[0];
|
|
sp274.y += (RANDOMFRAC() - 0.5f) * shootfunc->recoilsettings->yrange * hand->finalmult[0];
|
|
sp274.z += (RANDOMFRAC() - 0.5f) * shootfunc->recoilsettings->zrange * hand->finalmult[0];
|
|
}
|
|
|
|
hand->fspare1 = (player->crosspos2[0] - camGetScreenLeft() - camGetScreenWidth() * 0.5f) * weapondef->aimsettings->guntransside / (camGetScreenWidth() * 0.5f);
|
|
|
|
if (player->crosspos2[1] - camGetScreenTop() > camGetScreenHeight() * 0.5f) {
|
|
hand->fspare2 = (player->crosspos2[1] - camGetScreenTop() - camGetScreenHeight() * 0.5f) * weapondef->aimsettings->guntransdown / (camGetScreenHeight() * 0.5f);
|
|
} else {
|
|
hand->fspare2 = (player->crosspos2[1] - camGetScreenTop() - camGetScreenHeight() * 0.5f) * weapondef->aimsettings->guntransup / (camGetScreenHeight() * 0.5f);
|
|
}
|
|
|
|
fspare1 = hand->fspare1;
|
|
fspare2 = hand->fspare2;
|
|
|
|
sp274.f[0] += fspare1;
|
|
sp274.f[1] -= fspare2;
|
|
|
|
hand->visible = true;
|
|
|
|
if (!weaponHasFlag(weaponnum, WEAPONFLAG_00000040)
|
|
|| weaponHasFlag(weaponnum, WEAPONFLAG_00000080)
|
|
|| hand->mode == HANDMODE_6
|
|
|| hand->mode == HANDMODE_7
|
|
|| !bgun0f09dd7c()
|
|
|| hand->inuse == false
|
|
|| bgunGetGunMemType() == 0) {
|
|
hand->visible = false;
|
|
}
|
|
|
|
if (hand->visible) {
|
|
modeldef = player->gunctrl.gunmodeldef;
|
|
mtxallocation = gfxAllocate(modeldef->nummatrices * sizeof(Mtxf));
|
|
|
|
if (weaponHasFlag(weaponnum, WEAPONFLAG_02000000)) {
|
|
for (i = 0; i < modeldef->nummatrices; i++) {
|
|
mtx = (Mtxf *)(mtxallocation + i * sizeof(Mtxf));
|
|
mtx4LoadIdentity(mtx);
|
|
}
|
|
}
|
|
|
|
bgunExecuteModelCmdList(hand->unk0dcc);
|
|
|
|
if (player->gunctrl.handmodeldef != NULL) {
|
|
bgunExecuteModelCmdList(hand->unk0dd0);
|
|
}
|
|
|
|
bgun0f098030(hand, modeldef);
|
|
|
|
if (weaponHasFlag(weaponnum, WEAPONFLAG_00002000)) {
|
|
bgun0f0981e8(hand, modeldef);
|
|
}
|
|
}
|
|
|
|
mtx4LoadIdentity(&sp234);
|
|
|
|
if (PLAYERCOUNT() == 1 && IS8MB() && weaponHasFlag(weaponnum, WEAPONFLAG_GANGSTA)) {
|
|
bgunUpdateGangsta(hand, handnum, &sp274, funcdef, &sp284, &sp234);
|
|
}
|
|
|
|
if (hand->useposrot) {
|
|
sp274.f[0] += hand->posrotmtx.m[3][0];
|
|
sp274.f[1] += hand->posrotmtx.m[3][1];
|
|
sp274.f[2] += hand->posrotmtx.m[3][2];
|
|
|
|
mtx00015be0(&hand->posrotmtx, &sp234);
|
|
|
|
sp234.m[3][0] = 0.0f;
|
|
sp234.m[3][1] = 0.0f;
|
|
sp234.m[3][2] = 0.0f;
|
|
} else {
|
|
hand->rotxoffset = 0.0f;
|
|
hand->posoffset.x = 0.0f;
|
|
hand->posoffset.y = 0.0f;
|
|
hand->posoffset.z = 0.0f;
|
|
}
|
|
|
|
mtx00016d58(&sp284, 0.0f, 0.0f, 0.0f,
|
|
hand->damplook.x, hand->damplook.y, hand->damplook.z,
|
|
hand->dampup.x, hand->dampup.y, hand->dampup.z);
|
|
|
|
mtx00015be0(&sp284, &sp234);
|
|
|
|
sp1a4.x = 0.0f;
|
|
sp1a4.y = M_PI;
|
|
sp1a4.z = 0.0f;
|
|
|
|
mtx4LoadRotation(&sp1a4, &sp164);
|
|
|
|
sp1a4.y = 0.0f;
|
|
|
|
bgun0f0a24f0(&sp118, handnum);
|
|
|
|
sp1a4.y = -bgun0f0a2498(sp118.x, sp118.z, sp274.f[0], sp274.f[2]);
|
|
sp1a4.x = bgun0f0a2498(sp118.y, sp118.z, sp274.f[1], sp274.f[2]);
|
|
|
|
hand->lastrotangx = sp1a4.f[0];
|
|
hand->lastrotangy = sp1a4.f[1];
|
|
|
|
mtx4LoadRotation(&sp1a4, &sp124);
|
|
mtx4MultMtx4(&sp124, &sp164, &sp284);
|
|
mtx4MultMtx4InPlace(&sp284, &sp234);
|
|
mtx4Copy(&sp234, &sp2c4);
|
|
mtx4SetTranslation(&sp274, &sp2c4);
|
|
|
|
mtx4Copy(&sp2c4, &hand->cammtx);
|
|
mtx4Copy(&hand->posmtx, &hand->prevmtx);
|
|
|
|
mtx00015be4(camGetProjectionMtxF(), &hand->cammtx, &hand->posmtx);
|
|
|
|
if (hand->visible) {
|
|
for (j = 0x5a; j < 0x5d; j++) {
|
|
node = modelGetPart(modeldef, j);
|
|
|
|
if (node) {
|
|
rodata = node->rodata;
|
|
sp1e4[sp1e0] = (bool *)&hand->unk0a6c[rodata->toggle.rwdataindex];
|
|
sp1e0++;
|
|
}
|
|
}
|
|
|
|
hand->gunmodel.matrices = (Mtxf *)mtxallocation;
|
|
hand->handmodel.matrices = (Mtxf *)mtxallocation;
|
|
|
|
if (weaponHasFlag(weaponnum, WEAPONFLAG_DUALFLIP) && handnum == HAND_LEFT) {
|
|
mtx00015e24(-1, &sp2c4);
|
|
}
|
|
|
|
mtx00015f04(0.10000001f, &sp2c4);
|
|
|
|
mtx4Copy(&sp2c4, (Mtxf *)mtxallocation);
|
|
|
|
if (hand->unk0cc8_04 > 0) {
|
|
switch (weaponnum) {
|
|
case WEAPON_GRENADE:
|
|
case WEAPON_NBOMB:
|
|
hand->ejectstate = EJECTSTATE_INIT;
|
|
hand->ejecttype = EJECTTYPE_GRENADEPIN;
|
|
break;
|
|
case WEAPON_TRANQUILIZER:
|
|
hand->ejectstate = EJECTSTATE_INIT;
|
|
hand->ejecttype = EJECTTYPE_TRANQCASE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
var8009d144 = hand;
|
|
|
|
if (hand->ejectstate > EJECTSTATE_INACTIVE) {
|
|
bgun0f0a45d0(hand, modeldef, isdetonator);
|
|
}
|
|
|
|
var8009d0dc = -1;
|
|
var8009d0f0[0] = var8009d0f0[1] = var8009d0f0[2] = -1;
|
|
|
|
switch (weaponnum) {
|
|
case WEAPON_LASER:
|
|
bgunUpdateLaser(hand);
|
|
break;
|
|
case WEAPON_REAPER:
|
|
bgunUpdateReaper(hand, modeldef);
|
|
break;
|
|
}
|
|
|
|
{
|
|
bool a0 = true;
|
|
struct modelrenderdata renderdata = {NULL, true, 3};
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
bool a3 = false;
|
|
#endif
|
|
s32 spcc;
|
|
Mtxf *spc8;
|
|
Mtxf *spc4;
|
|
Mtxf sp84;
|
|
u32 sp80;
|
|
struct coord sp74;
|
|
s32 stack;
|
|
s32 sp6c;
|
|
|
|
renderdata.unk00 = &sp2c4;
|
|
renderdata.unk10 = hand->gunmodel.matrices;
|
|
|
|
if (hand->animmode != HANDANIMMODE_IDLE) {
|
|
a0 = false;
|
|
}
|
|
|
|
switch (weaponnum) {
|
|
case WEAPON_REAPER:
|
|
a0 = false;
|
|
break;
|
|
case WEAPON_COMBATKNIFE:
|
|
if (player->hands[HAND_LEFT].loadedammo[0] == 0) {
|
|
a0 = false;
|
|
}
|
|
// fall through
|
|
case WEAPON_GRENADE:
|
|
case WEAPON_NBOMB:
|
|
case WEAPON_TIMEDMINE:
|
|
case WEAPON_PROXIMITYMINE:
|
|
case WEAPON_REMOTEMINE:
|
|
case WEAPON_ECMMINE:
|
|
if (player->hands[HAND_RIGHT].loadedammo[0] == 0) {
|
|
a0 = false;
|
|
}
|
|
|
|
if (player->hands[handnum].state == HANDSTATE_AUTOSWITCH) {
|
|
a0 = false;
|
|
}
|
|
|
|
if (player->hands[handnum].state == HANDSTATE_ATTACK) {
|
|
a0 = false;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (hand->ejectstate != EJECTSTATE_INACTIVE) {
|
|
a0 = false;
|
|
}
|
|
|
|
if (player->hands[handnum].state == HANDSTATE_CHANGEGUN
|
|
&& player->hands[handnum].stateminor < 2
|
|
&& weapondef->unequip_animation != NULL) {
|
|
a0 = false;
|
|
}
|
|
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
switch (modelGetAnimNum(&hand->gunmodel)) {
|
|
case ANIM_GUN_CROSSBOW_EQUIP:
|
|
case ANIM_GUN_LAPTOP_EQUIP:
|
|
case ANIM_GUN_LAPTOP_UNEQUIP:
|
|
case ANIM_GUN_LAPTOP_RELOAD:
|
|
case ANIM_GUN_FALCON2_RELOAD:
|
|
case ANIM_GUN_CMP150_RELOAD:
|
|
case ANIM_GUN_FARSIGHT_SHOOT:
|
|
case ANIM_GUN_SHOTGUN_SHOOT_SINGLE:
|
|
case ANIM_GUN_REAPER_SHOOT:
|
|
case ANIM_GUN_MAGSEC4_RELOAD:
|
|
case ANIM_GUN_CYCLONE_RELOAD:
|
|
case ANIM_GUN_SNIPER_RELOAD:
|
|
case ANIM_GUN_PHOENIX_RELOAD:
|
|
case ANIM_GUN_FALCON2_RELOAD_SCOPE:
|
|
case ANIM_GUN_REMOTEMINE_EQUIP:
|
|
a3 = 1;
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
if (a0) {
|
|
if (player->hands[HAND_RIGHT].unk0dd4 == -1) {
|
|
mtx4LoadIdentity(&sp84);
|
|
|
|
spc4 = hand->gunmodel.matrices;
|
|
|
|
renderdata.unk00 = &sp84;
|
|
renderdata.unk10 = player->hands[HAND_RIGHT].unk0dd8;
|
|
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
var8005efd8_2 = true;
|
|
|
|
if (a3) {
|
|
var8005efb0_2 = true;
|
|
}
|
|
|
|
modelSetMatricesWithAnim(&renderdata, &hand->gunmodel);
|
|
|
|
var8005efd8_2 = false;
|
|
|
|
if (a3) {
|
|
var8005efb0_2 = false;
|
|
}
|
|
#else
|
|
modelSetMatricesWithAnim(&renderdata, &hand->gunmodel);
|
|
#endif
|
|
|
|
player->hands[HAND_RIGHT].unk0dd4 = 1;
|
|
|
|
hand->gunmodel.matrices = spc4;
|
|
}
|
|
|
|
spc8 = player->hands[HAND_RIGHT].unk0dd8;
|
|
spc4 = hand->gunmodel.matrices;
|
|
|
|
for (spcc = 0; spcc < hand->gunmodel.definition->nummatrices; spcc++) {
|
|
mtx00015be4(&sp2c4, spc8, spc4);
|
|
spc8++;
|
|
spc4++;
|
|
}
|
|
} else {
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
var8005efd8_2 = true;
|
|
|
|
if (a3) {
|
|
var8005efb0_2 = true;
|
|
}
|
|
|
|
modelSetMatricesWithAnim(&renderdata, &hand->gunmodel);
|
|
|
|
var8005efd8_2 = false;
|
|
|
|
if (a3) {
|
|
var8005efb0_2 = false;
|
|
}
|
|
#else
|
|
modelSetMatricesWithAnim(&renderdata, &hand->gunmodel);
|
|
#endif
|
|
}
|
|
|
|
g_ModelJointPositionedFunc = 0;
|
|
|
|
node = modelGetPart(modeldef, MODELPART_GUN_SLIDE);
|
|
|
|
if (node) {
|
|
sp80 = modelFindNodeMtxIndex(node, 0);
|
|
|
|
bgunUpdateSlide(handnum);
|
|
|
|
sp74.f[0] = 0.0f;
|
|
sp74.f[1] = 0.0f;
|
|
sp74.f[2] = -hand->slidetrans;
|
|
|
|
mtx = (Mtxf *)mtxallocation;
|
|
mtx += sp80;
|
|
|
|
mtx4RotateVecInPlace(mtx, &sp74);
|
|
|
|
mtx->m[3][0] += sp74.f[0];
|
|
mtx->m[3][1] += sp74.f[1];
|
|
mtx->m[3][2] += sp74.f[2];
|
|
}
|
|
|
|
if (sp1e4[0] != NULL) {
|
|
*sp1e4[0] = false;
|
|
}
|
|
|
|
if (sp1e4[1] != NULL) {
|
|
*sp1e4[1] = false;
|
|
}
|
|
|
|
if (sp1e4[2] != NULL) {
|
|
*sp1e4[2] = false;
|
|
}
|
|
|
|
switch (weaponnum) {
|
|
case WEAPON_SNIPERRIFLE:
|
|
bgunUpdateSniperRifle(modeldef, mtxallocation);
|
|
break;
|
|
case WEAPON_DEVASTATOR:
|
|
bgunUpdateDevastator(hand, mtxallocation, modeldef);
|
|
break;
|
|
case WEAPON_SHOTGUN:
|
|
bgunUpdateShotgun(hand, mtxallocation, sp1e4[0], modeldef);
|
|
break;
|
|
}
|
|
|
|
node = modelGetPart(modeldef, MODELPART_GUN_MUZZLEPOS);
|
|
|
|
if (weaponnum == WEAPON_REAPER) {
|
|
if (hand->flashon || hand->firing) {
|
|
node = modelGetPart(modeldef, MODELPART_REAPER_001E + (hand->burstbullets % 3));
|
|
} else {
|
|
node = modelGetPart(modeldef, MODELPART_REAPER_001E + (g_Vars.lvframenum % 3));
|
|
}
|
|
}
|
|
|
|
if (node) {
|
|
sp6c = modelFindNodeMtxIndex(node, 0);
|
|
|
|
mtx = (Mtxf *)mtxallocation;
|
|
mtx += sp6c;
|
|
|
|
hand->muzzlepos.f[0] = mtx->m[3][0];
|
|
hand->muzzlepos.f[1] = mtx->m[3][1];
|
|
hand->muzzlepos.f[2] = mtx->m[3][2];
|
|
|
|
mtx4Copy(mtx, &hand->muzzlemat);
|
|
mtx4TransformVecInPlace(camGetProjectionMtxF(), &hand->muzzlepos);
|
|
|
|
hand->muzzlez = -((Mtxf *)((uintptr_t)mtxallocation + sp6c * sizeof(Mtxf)))->m[3][2];
|
|
|
|
if (hand->flashon && sp1e0 > 0 && weaponnum != WEAPON_SHOTGUN && g_Vars.lvupdate240 != 0) {
|
|
bgun0f0a4e44(hand, weapondef, modeldef, funcdef, sp1e0, mtxallocation, weaponnum, sp1e4, sp6c, &sp234, &sp1f4);
|
|
}
|
|
} else if (weaponnum == WEAPON_GRENADE
|
|
|| weaponnum == WEAPON_TIMEDMINE
|
|
|| weaponnum == WEAPON_REMOTEMINE
|
|
|| weaponnum == WEAPON_PROXIMITYMINE
|
|
|| weaponnum == WEAPON_NBOMB) {
|
|
sp6c = modelFindNodeMtxIndex(modelGetPart(modeldef, MODELPART_GUN_HOLDPOS), 0);
|
|
|
|
mtx = (Mtxf *)mtxallocation;
|
|
mtx += sp6c;
|
|
|
|
hand->muzzlepos.x = mtx->m[3][0];
|
|
hand->muzzlepos.y = mtx->m[3][1];
|
|
hand->muzzlepos.z = mtx->m[3][2];
|
|
|
|
mtx4Copy(mtx, &hand->muzzlemat);
|
|
mtx4TransformVecInPlace(camGetProjectionMtxF(), &hand->muzzlepos);
|
|
|
|
hand->muzzlez = -((Mtxf *)((uintptr_t)mtxallocation + sp6c * sizeof(Mtxf)))->m[3][2];
|
|
} else {
|
|
hand->muzzlepos.x = hand->posmtx.m[3][0];
|
|
hand->muzzlepos.y = hand->posmtx.m[3][1];
|
|
hand->muzzlepos.z = hand->posmtx.m[3][2];
|
|
|
|
mtx4Copy(&hand->posmtx, &hand->muzzlemat);
|
|
|
|
hand->muzzlez = -hand->cammtx.m[3][2];
|
|
}
|
|
}
|
|
} else {
|
|
hand->muzzlepos.x = hand->posmtx.m[3][0];
|
|
hand->muzzlepos.y = hand->posmtx.m[3][1];
|
|
hand->muzzlepos.z = hand->posmtx.m[3][2];
|
|
|
|
mtx4Copy(&hand->posmtx, &hand->muzzlemat);
|
|
|
|
hand->muzzlez = -hand->cammtx.m[3][2];
|
|
}
|
|
|
|
switch (weaponnum) {
|
|
case WEAPON_ROCKETLAUNCHER:
|
|
bgunUpdateRocketLauncher(hand, handnum, (struct weaponfunc_shootprojectile *)funcdef);
|
|
break;
|
|
case WEAPON_DY357MAGNUM:
|
|
case WEAPON_DY357LX:
|
|
if (hand->unk0cc8_04 > 0) {
|
|
bgunUpdateMagnum(hand, handnum, modeldef, (Mtxf *)mtxallocation);
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (hand->firing && g_Vars.lvupdate240 != 0) {
|
|
bgunCreateFx(hand, handnum, funcdef, weaponnum, modeldef, mtxallocation);
|
|
}
|
|
|
|
if (PLAYERCOUNT() == 1 && IS8MB() && g_Vars.lvupdate240 != 0) {
|
|
bgunUpdateSmoke(hand, handnum, weaponnum, funcdef);
|
|
}
|
|
|
|
if (hand->ejectstate > EJECTSTATE_INACTIVE) {
|
|
bgunTickEject(hand, modeldef, isdetonator);
|
|
}
|
|
|
|
if (PLAYERCOUNT() == 1 && IS8MB() && hand->visible
|
|
&& weaponnum >= WEAPON_FALCON2 && weaponnum <= WEAPON_FALCON2_SCOPE) {
|
|
bgunUpdateLasersight(hand, modeldef, handnum, mtxallocation);
|
|
} else {
|
|
lasersightFree(handnum);
|
|
}
|
|
|
|
hand->animframeinc = 0;
|
|
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
hand->animframeincfreal = 0;
|
|
#endif
|
|
}
|
|
|
|
void bgunTickMaulerCharge(void)
|
|
{
|
|
struct player *player = g_Vars.currentplayer;
|
|
s32 i;
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
struct hand *hand = &player->hands[i];
|
|
u32 charging = false;
|
|
|
|
if (hand->inuse) {
|
|
if (bgunIsReloading(hand)) {
|
|
// Reloading - reset charge amount
|
|
hand->matmot1 = 0;
|
|
} else if (hand->gset.weaponfunc == FUNC_SECONDARY) {
|
|
// Charging or fully charged
|
|
s32 oldvalue = hand->matmot1;
|
|
s32 newvalue;
|
|
|
|
if (hand->loadedammo[0] >= 2 && hand->matmot1 < 5) {
|
|
charging = true;
|
|
hand->matmot1 += g_Vars.lvupdate60freal * 0.05f;
|
|
}
|
|
|
|
if (hand->matmot1 > 5) {
|
|
hand->matmot1 = 5;
|
|
}
|
|
|
|
newvalue = hand->matmot1;
|
|
|
|
if (oldvalue != newvalue && hand->loadedammo[0] >= 2) {
|
|
hand->loadedammo[0]--;
|
|
}
|
|
} else {
|
|
// Using primary function - make the charge wear off slowly
|
|
hand->matmot1 -= g_Vars.lvupdate60freal * 0.005f;
|
|
|
|
if (hand->matmot1 < 0) {
|
|
hand->matmot1 = 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Probable @bug: In other places where audio is started and then
|
|
* its speed is adjusted, the game raises the priority of the main
|
|
* thread (this thread) to above the audio thread's priority so that
|
|
* the audio thread cannot execute and start playing the audio
|
|
* between the calls to sndStart and audioPostEvent. But this pattern
|
|
* is not done here.
|
|
*
|
|
* There is a known issue where the Mauler charge sound is played
|
|
* correctly then the game proceeds to play other unrelated sound
|
|
* effects before eventually crashing. It's suspected that this lack
|
|
* of thread priority adjusting is the root cause. Perhaps a race
|
|
* condition exists where the audio thread does something with the
|
|
* sound while this thread is in the middle of reconfiguring it.
|
|
* This is not yet confirmed.
|
|
*/
|
|
if (hand->audiohandle == NULL
|
|
&& hand->matmot1 > 0.1f
|
|
&& charging
|
|
&& g_Vars.lvupdate240 != 0) {
|
|
sndStart(var80095200, SFX_MAULER_CHARGE, &hand->audiohandle, -1, -1, -1, -1, -1);
|
|
}
|
|
|
|
if (hand->audiohandle) {
|
|
f32 speed = 0.5f + hand->matmot1 / 3.0f + sinf(g_20SecIntervalFrac * M_PI * 32.0f) * 0.03f;
|
|
|
|
if (hand->matmot1 < 0.1f || !charging) {
|
|
audioStop(hand->audiohandle);
|
|
} else {
|
|
audioPostEvent(hand->audiohandle, 16, *(s32 *)&speed);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void bgunTickGameplay2(void)
|
|
{
|
|
struct player *player = g_Vars.currentplayer;
|
|
struct hand *hand;
|
|
u32 stack[3];
|
|
s32 i;
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
if (g_Vars.currentplayernum == 0) {
|
|
projectilesDebug();
|
|
}
|
|
#endif
|
|
|
|
if (player->gunctrl.unk1583_06) {
|
|
// empty
|
|
} else {
|
|
bgunTickLoad();
|
|
}
|
|
|
|
// Return control to Jo if eyespy has been deselected
|
|
if ((g_Vars.currentplayer->devicesactive & ~g_Vars.currentplayer->devicesinhibit & DEVICE_EYESPY) == 0
|
|
&& player->eyespy) {
|
|
player->eyespy->active = false;
|
|
}
|
|
|
|
if ((g_Vars.currentplayer->devicesactive & ~g_Vars.currentplayer->devicesinhibit & DEVICE_XRAYSCANNER)
|
|
&& (bgunGetWeaponNum(HAND_RIGHT) != WEAPON_FARSIGHT || player->gunsightoff)) {
|
|
// Using normal xray scanner (not Farsight zoom)
|
|
if (player->visionmode != VISIONMODE_XRAY) {
|
|
player->erasertime = 0;
|
|
} else {
|
|
player->erasertime += g_Vars.lvupdate240;
|
|
}
|
|
|
|
player->visionmode = VISIONMODE_XRAY;
|
|
player->ecol_1 = 24;
|
|
player->ecol_2 = 8;
|
|
player->ecol_3 = 24;
|
|
player->epcol_0 = 2;
|
|
player->epcol_1 = 0;
|
|
player->epcol_2 = 1;
|
|
} else {
|
|
if (player->gunsightoff == 0) {
|
|
if (player->hands[HAND_RIGHT].gset.weaponnum == WEAPON_FARSIGHT) {
|
|
// Aiming with the Farsight
|
|
if (player->visionmode != VISIONMODE_XRAY) {
|
|
player->erasertime = 0;
|
|
} else {
|
|
player->erasertime += g_Vars.lvupdate240;
|
|
}
|
|
|
|
player->visionmode = VISIONMODE_XRAY;
|
|
player->ecol_1 = 16;
|
|
player->ecol_2 = 24;
|
|
player->ecol_3 = 8;
|
|
player->epcol_0 = 0;
|
|
player->epcol_1 = 1;
|
|
player->epcol_2 = 2;
|
|
} else {
|
|
// Aiming with non-Farsight
|
|
if (player->visionmode != VISIONMODE_SLAYERROCKET) {
|
|
player->visionmode = VISIONMODE_NORMAL;
|
|
}
|
|
}
|
|
} else {
|
|
// Not aiming
|
|
if (player->visionmode != VISIONMODE_SLAYERROCKET) {
|
|
player->visionmode = VISIONMODE_NORMAL;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (player->gunctrl.weaponnum == WEAPON_MAULER) {
|
|
bgunTickMaulerCharge();
|
|
}
|
|
|
|
if (g_Vars.lvupdate240 == 0) {
|
|
for (i = 0; i < 2; i++) {
|
|
hand = &player->hands[i];
|
|
|
|
if (hand->audiohandle) {
|
|
audioStop(hand->audiohandle);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (g_Vars.currentplayer->devicesactive &
|
|
~g_Vars.currentplayer->devicesinhibit & DEVICE_CLOAKRCP120) {
|
|
if (player->gunctrl.weaponnum == WEAPON_RCP120) {
|
|
struct chrdata *chr = player->prop->chr;
|
|
|
|
// Handle RCP120 cloak ammo usage
|
|
if ((chr->hidden & CHRHFLAG_CLOAKED) && chr->cloakfadefinished == true) {
|
|
hand = &player->hands[HAND_RIGHT];
|
|
hand->matmot1 += LVUPDATE60FREAL() * 0.4f;
|
|
|
|
if (hand->matmot1 > 1.0f) {
|
|
s32 usedqty = hand->matmot1;
|
|
|
|
if (usedqty > hand->loadedammo[0]) {
|
|
usedqty = hand->loadedammo[0];
|
|
}
|
|
|
|
hand->matmot1 -= usedqty;
|
|
hand->loadedammo[0] -= usedqty;
|
|
|
|
// If out of ammo, turn off cloak
|
|
if (hand->loadedammo[0] == 0 && hand->state != HANDSTATE_RELOAD) {
|
|
s32 stilltogo = hand->matmot1;
|
|
|
|
if (stilltogo > player->ammoheldarr[player->gunctrl.ammotypes[0]]) {
|
|
g_Vars.currentplayer->devicesactive &= ~DEVICE_CLOAKRCP120;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
// No longer using RCP120, so turn off cloak
|
|
player->devicesactive &= ~DEVICE_CLOAKRCP120;
|
|
}
|
|
} else if (player->gunctrl.weaponnum == WEAPON_RCP120) {
|
|
hand = &player->hands[HAND_RIGHT];
|
|
|
|
// I think this is handling situations where the player has turned off
|
|
// RCP120 cloak but there's still a bit of ammo to be subtracted on
|
|
// this tick.
|
|
if (hand->matmot1 > 1.0f) {
|
|
s32 usedqty = hand->matmot1;
|
|
|
|
if (usedqty > hand->loadedammo[0]) {
|
|
usedqty = hand->loadedammo[0];
|
|
}
|
|
|
|
hand->matmot1 -= usedqty;
|
|
hand->loadedammo[0] -= usedqty;
|
|
|
|
if (hand->matmot1 > 1.0f) {
|
|
s32 usedqty = hand->matmot1;
|
|
|
|
if (usedqty > player->ammoheldarr[player->gunctrl.ammotypes[0]]) {
|
|
usedqty = player->ammoheldarr[player->gunctrl.ammotypes[0]];
|
|
}
|
|
|
|
player->ammoheldarr[player->gunctrl.ammotypes[0]] -= usedqty;
|
|
hand->matmot1 = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
bgunTickUnequippedReload();
|
|
bgun0f0a5550(HAND_RIGHT);
|
|
|
|
if (player->hands[HAND_LEFT].inuse) {
|
|
bgun0f0a5550(HAND_LEFT);
|
|
} else {
|
|
player->hands[HAND_LEFT].ejectstate = EJECTSTATE_INACTIVE;
|
|
}
|
|
|
|
bgunIsUsingSecondaryFunction();
|
|
}
|
|
|
|
s8 bgunFreeFireslotWrapper(s32 slotnum)
|
|
{
|
|
#if VERSION < VERSION_NTSC_1_0
|
|
if (slotnum >= 0) {
|
|
if (g_Fireslots[slotnum].unk04nb && sndGetState(g_Fireslots[slotnum].unk04nb) != AL_STOPPED) {
|
|
audioStop(g_Fireslots[slotnum].unk04nb);
|
|
}
|
|
|
|
if (g_Fireslots[slotnum].unk08nb && sndGetState(g_Fireslots[slotnum].unk08nb) != AL_STOPPED) {
|
|
audioStop(g_Fireslots[slotnum].unk08nb);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return bgunFreeFireslot(slotnum);
|
|
}
|
|
|
|
s8 bgunFreeFireslot(s32 fireslot_id)
|
|
{
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
if (fireslot_id >= 0 && fireslot_id < NUM_FIRESLOTS) {
|
|
g_Fireslots[fireslot_id].endlvframe = -1;
|
|
}
|
|
#else
|
|
if (fireslot_id >= 0) {
|
|
g_Fireslots[fireslot_id].endlvframe = -1;
|
|
}
|
|
#endif
|
|
|
|
return -1;
|
|
}
|
|
|
|
s32 bgunAllocateFireslot(void)
|
|
{
|
|
s32 index = -1;
|
|
s32 i;
|
|
|
|
for (i = 0; i < ARRAYCOUNT(g_Fireslots); i++) {
|
|
if (g_Fireslots[i].endlvframe < 0) {
|
|
g_Fireslots[i].endlvframe = 0;
|
|
|
|
#if VERSION < VERSION_NTSC_1_0
|
|
g_Fireslots[i].unk04nb = 0;
|
|
g_Fireslots[i].unk08nb = 0;
|
|
#endif
|
|
|
|
g_Fireslots[i].beam.age = -1;
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return index;
|
|
}
|
|
|
|
u32 var8007029c = 0x00000000;
|
|
u32 var800702a0 = 0x00000001;
|
|
u32 var800702a4 = 0x00000003;
|
|
u32 var800702a8 = 0x00000000;
|
|
u32 var800702ac = 0x00000000;
|
|
u32 var800702b0 = 0x00000000;
|
|
u32 var800702b4 = 0x00000000;
|
|
u32 var800702b8 = 0x00000000;
|
|
u32 var800702bc = 0x00000000;
|
|
u32 var800702c0 = 0x00000000;
|
|
u32 var800702c4 = 0x00000000;
|
|
u32 var800702c8 = 0x00000000;
|
|
u32 var800702cc = 0x00000000;
|
|
u32 var800702d0 = 0x00000000;
|
|
u32 var800702d4 = 0x00000000;
|
|
u32 var800702d8 = 0x00000000;
|
|
u32 var800702dc = 0x00000001;
|
|
|
|
#if MATCHING
|
|
#if PAL
|
|
GLOBAL_ASM(
|
|
glabel bgunRender
|
|
.late_rodata
|
|
glabel var7f1aca8c
|
|
.word 0x3faaaaab
|
|
glabel var7f1aca90
|
|
.word 0x3f3ebebf
|
|
.text
|
|
/* f0a7138: 27bdfeb0 */ addiu $sp,$sp,-336
|
|
/* f0a713c: afbf0034 */ sw $ra,0x34($sp)
|
|
/* f0a7140: afb50030 */ sw $s5,0x30($sp)
|
|
/* f0a7144: afb4002c */ sw $s4,0x2c($sp)
|
|
/* f0a7148: afb30028 */ sw $s3,0x28($sp)
|
|
/* f0a714c: afb20024 */ sw $s2,0x24($sp)
|
|
/* f0a7150: afb10020 */ sw $s1,0x20($sp)
|
|
/* f0a7154: afb0001c */ sw $s0,0x1c($sp)
|
|
/* f0a7158: afa40150 */ sw $a0,0x150($sp)
|
|
/* f0a715c: 8c8f0000 */ lw $t7,0x0($a0)
|
|
/* f0a7160: 3c198007 */ lui $t9,%hi(var8007029c)
|
|
/* f0a7164: 3c11800a */ lui $s1,%hi(g_Vars)
|
|
/* f0a7168: 2739029c */ addiu $t9,$t9,%lo(var8007029c)
|
|
/* f0a716c: 26319fc0 */ addiu $s1,$s1,%lo(g_Vars)
|
|
/* f0a7170: 272a003c */ addiu $t2,$t9,0x3c
|
|
/* f0a7174: 27b8010c */ addiu $t8,$sp,0x10c
|
|
/* f0a7178: afaf014c */ sw $t7,0x14c($sp)
|
|
.L0f0a717c:
|
|
/* f0a717c: 8f210000 */ lw $at,0x0($t9)
|
|
/* f0a7180: 2739000c */ addiu $t9,$t9,0xc
|
|
/* f0a7184: 2718000c */ addiu $t8,$t8,0xc
|
|
/* f0a7188: af01fff4 */ sw $at,-0xc($t8)
|
|
/* f0a718c: 8f21fff8 */ lw $at,-0x8($t9)
|
|
/* f0a7190: af01fff8 */ sw $at,-0x8($t8)
|
|
/* f0a7194: 8f21fffc */ lw $at,-0x4($t9)
|
|
/* f0a7198: 172afff8 */ bne $t9,$t2,.L0f0a717c
|
|
/* f0a719c: af01fffc */ sw $at,-0x4($t8)
|
|
/* f0a71a0: 8f210000 */ lw $at,0x0($t9)
|
|
/* f0a71a4: af010000 */ sw $at,0x0($t8)
|
|
/* f0a71a8: 8e330284 */ lw $s3,0x284($s1)
|
|
/* f0a71ac: 24010001 */ addiu $at,$zero,0x1
|
|
/* f0a71b0: 966b0010 */ lhu $t3,0x10($s3)
|
|
/* f0a71b4: 1561000d */ bne $t3,$at,.L0f0a71ec
|
|
/* f0a71b8: 00001025 */ or $v0,$zero,$zero
|
|
/* f0a71bc: 24040f48 */ addiu $a0,$zero,0xf48
|
|
/* f0a71c0: 8e2c0284 */ lw $t4,0x284($s1)
|
|
.L0f0a71c4:
|
|
/* f0a71c4: 01821821 */ addu $v1,$t4,$v0
|
|
/* f0a71c8: 8c6d0854 */ lw $t5,0x854($v1)
|
|
/* f0a71cc: 244207a4 */ addiu $v0,$v0,0x7a4
|
|
/* f0a71d0: 11a00002 */ beqz $t5,.L0f0a71dc
|
|
/* f0a71d4: 00000000 */ nop
|
|
/* f0a71d8: ac600850 */ sw $zero,0x850($v1)
|
|
.L0f0a71dc:
|
|
/* f0a71dc: 5444fff9 */ bnel $v0,$a0,.L0f0a71c4
|
|
/* f0a71e0: 8e2c0284 */ lw $t4,0x284($s1)
|
|
/* f0a71e4: 100002d5 */ b .L0f0a7d3c
|
|
/* f0a71e8: 8fbf0034 */ lw $ra,0x34($sp)
|
|
.L0f0a71ec:
|
|
/* f0a71ec: 0fc5d9ad */ jal mblurRender
|
|
/* f0a71f0: 8fa4014c */ lw $a0,0x14c($sp)
|
|
/* f0a71f4: afa2014c */ sw $v0,0x14c($sp)
|
|
/* f0a71f8: 0c002ca0 */ jal vi0000b280
|
|
/* f0a71fc: 00402025 */ or $a0,$v0,$zero
|
|
/* f0a7200: afa2014c */ sw $v0,0x14c($sp)
|
|
/* f0a7204: 0c002c74 */ jal vi0000b1d0
|
|
/* f0a7208: 00402025 */ or $a0,$v0,$zero
|
|
/* f0a720c: 244e0008 */ addiu $t6,$v0,0x8
|
|
/* f0a7210: afae014c */ sw $t6,0x14c($sp)
|
|
/* f0a7214: 0c002f40 */ jal viGetViewLeft
|
|
/* f0a7218: 0040a825 */ or $s5,$v0,$zero
|
|
/* f0a721c: 00028400 */ sll $s0,$v0,0x10
|
|
/* f0a7220: 00107c03 */ sra $t7,$s0,0x10
|
|
/* f0a7224: 0c002f44 */ jal viGetViewTop
|
|
/* f0a7228: 01e08025 */ or $s0,$t7,$zero
|
|
/* f0a722c: 44822000 */ mtc1 $v0,$f4
|
|
/* f0a7230: 44908000 */ mtc1 $s0,$f16
|
|
/* f0a7234: 3c014080 */ lui $at,0x4080
|
|
/* f0a7238: 468021a0 */ cvt.s.w $f6,$f4
|
|
/* f0a723c: 44810000 */ mtc1 $at,$f0
|
|
/* f0a7240: 3c01ed00 */ lui $at,0xed00
|
|
/* f0a7244: 468084a0 */ cvt.s.w $f18,$f16
|
|
/* f0a7248: 46003202 */ mul.s $f8,$f6,$f0
|
|
/* f0a724c: 00000000 */ nop
|
|
/* f0a7250: 46009102 */ mul.s $f4,$f18,$f0
|
|
/* f0a7254: 4600428d */ trunc.w.s $f10,$f8
|
|
/* f0a7258: 4600218d */ trunc.w.s $f6,$f4
|
|
/* f0a725c: 44085000 */ mfc1 $t0,$f10
|
|
/* f0a7260: 440b3000 */ mfc1 $t3,$f6
|
|
/* f0a7264: 310a0fff */ andi $t2,$t0,0xfff
|
|
/* f0a7268: 0141c825 */ or $t9,$t2,$at
|
|
/* f0a726c: 316c0fff */ andi $t4,$t3,0xfff
|
|
/* f0a7270: 000c6b00 */ sll $t5,$t4,0xc
|
|
/* f0a7274: 032d7025 */ or $t6,$t9,$t5
|
|
/* f0a7278: 0c002f22 */ jal viGetViewWidth
|
|
/* f0a727c: aeae0000 */ sw $t6,0x0($s5)
|
|
/* f0a7280: 00029400 */ sll $s2,$v0,0x10
|
|
/* f0a7284: 00127c03 */ sra $t7,$s2,0x10
|
|
/* f0a7288: 0c002f40 */ jal viGetViewLeft
|
|
/* f0a728c: 01e09025 */ or $s2,$t7,$zero
|
|
/* f0a7290: 0002a400 */ sll $s4,$v0,0x10
|
|
/* f0a7294: 00144c03 */ sra $t1,$s4,0x10
|
|
/* f0a7298: 0c002f44 */ jal viGetViewTop
|
|
/* f0a729c: 0120a025 */ or $s4,$t1,$zero
|
|
/* f0a72a0: 00028400 */ sll $s0,$v0,0x10
|
|
/* f0a72a4: 00104403 */ sra $t0,$s0,0x10
|
|
/* f0a72a8: 0c002f26 */ jal viGetViewHeight
|
|
/* f0a72ac: 01008025 */ or $s0,$t0,$zero
|
|
/* f0a72b0: 00505021 */ addu $t2,$v0,$s0
|
|
/* f0a72b4: 448a4000 */ mtc1 $t2,$f8
|
|
/* f0a72b8: 0292c821 */ addu $t9,$s4,$s2
|
|
/* f0a72bc: 44992000 */ mtc1 $t9,$f4
|
|
/* f0a72c0: 468042a0 */ cvt.s.w $f10,$f8
|
|
/* f0a72c4: 3c014080 */ lui $at,0x4080
|
|
/* f0a72c8: 44810000 */ mtc1 $at,$f0
|
|
/* f0a72cc: 3c053fc0 */ lui $a1,0x3fc0
|
|
/* f0a72d0: 3c06447a */ lui $a2,0x447a
|
|
/* f0a72d4: 468021a0 */ cvt.s.w $f6,$f4
|
|
/* f0a72d8: 46005402 */ mul.s $f16,$f10,$f0
|
|
/* f0a72dc: 00000000 */ nop
|
|
/* f0a72e0: 46003202 */ mul.s $f8,$f6,$f0
|
|
/* f0a72e4: 4600848d */ trunc.w.s $f18,$f16
|
|
/* f0a72e8: 4600428d */ trunc.w.s $f10,$f8
|
|
/* f0a72ec: 440b9000 */ mfc1 $t3,$f18
|
|
/* f0a72f0: 440e5000 */ mfc1 $t6,$f10
|
|
/* f0a72f4: 316c0fff */ andi $t4,$t3,0xfff
|
|
/* f0a72f8: 31cf0fff */ andi $t7,$t6,0xfff
|
|
/* f0a72fc: 000f4b00 */ sll $t1,$t7,0xc
|
|
/* f0a7300: 01894025 */ or $t0,$t4,$t1
|
|
/* f0a7304: aea80004 */ sw $t0,0x4($s5)
|
|
/* f0a7308: 0c002b29 */ jal vi0000aca4
|
|
/* f0a730c: 8fa4014c */ lw $a0,0x14c($sp)
|
|
/* f0a7310: 8e2a0284 */ lw $t2,0x284($s1)
|
|
/* f0a7314: afa2014c */ sw $v0,0x14c($sp)
|
|
/* f0a7318: 91581bfc */ lbu $t8,0x1bfc($t2)
|
|
/* f0a731c: 53000016 */ beqzl $t8,.L0f0a7378
|
|
/* f0a7320: 8e2b006c */ lw $t3,0x6c($s1)
|
|
/* f0a7324: 0fc54bc7 */ jal optionsGetScreenRatio
|
|
/* f0a7328: 00000000 */ nop
|
|
/* f0a732c: 24010001 */ addiu $at,$zero,0x1
|
|
/* f0a7330: 14410008 */ bne $v0,$at,.L0f0a7354
|
|
/* f0a7334: 00000000 */ nop
|
|
/* f0a7338: 0fc2f4d6 */ jal player0f0bd358
|
|
/* f0a733c: 00000000 */ nop
|
|
/* f0a7340: 3c017f1b */ lui $at,%hi(var7f1aca8c)
|
|
/* f0a7344: c430ca8c */ lwc1 $f16,%lo(var7f1aca8c)($at)
|
|
/* f0a7348: 46100082 */ mul.s $f2,$f0,$f16
|
|
/* f0a734c: 10000005 */ b .L0f0a7364
|
|
/* f0a7350: 44061000 */ mfc1 $a2,$f2
|
|
.L0f0a7354:
|
|
/* f0a7354: 0fc2f4d6 */ jal player0f0bd358
|
|
/* f0a7358: 00000000 */ nop
|
|
/* f0a735c: 46000086 */ mov.s $f2,$f0
|
|
/* f0a7360: 44061000 */ mfc1 $a2,$f2
|
|
.L0f0a7364:
|
|
/* f0a7364: 8fa4014c */ lw $a0,0x14c($sp)
|
|
/* f0a7368: 0c002c3a */ jal vi0000b0e8
|
|
/* f0a736c: 3c054270 */ lui $a1,0x4270
|
|
/* f0a7370: afa2014c */ sw $v0,0x14c($sp)
|
|
/* f0a7374: 8e2b006c */ lw $t3,0x6c($s1)
|
|
.L0f0a7378:
|
|
/* f0a7378: 24010001 */ addiu $at,$zero,0x1
|
|
/* f0a737c: 51600004 */ beqzl $t3,.L0f0a7390
|
|
/* f0a7380: 00002825 */ or $a1,$zero,$zero
|
|
/* f0a7384: 10000002 */ b .L0f0a7390
|
|
/* f0a7388: 24050001 */ addiu $a1,$zero,0x1
|
|
/* f0a738c: 00002825 */ or $a1,$zero,$zero
|
|
.L0f0a7390:
|
|
/* f0a7390: 8e390068 */ lw $t9,0x68($s1)
|
|
/* f0a7394: 53200004 */ beqzl $t9,.L0f0a73a8
|
|
/* f0a7398: 00002025 */ or $a0,$zero,$zero
|
|
/* f0a739c: 10000002 */ b .L0f0a73a8
|
|
/* f0a73a0: 24040001 */ addiu $a0,$zero,0x1
|
|
/* f0a73a4: 00002025 */ or $a0,$zero,$zero
|
|
.L0f0a73a8:
|
|
/* f0a73a8: 8e2d0064 */ lw $t5,0x64($s1)
|
|
/* f0a73ac: 51a00004 */ beqzl $t5,.L0f0a73c0
|
|
/* f0a73b0: 00001025 */ or $v0,$zero,$zero
|
|
/* f0a73b4: 10000002 */ b .L0f0a73c0
|
|
/* f0a73b8: 24020001 */ addiu $v0,$zero,0x1
|
|
/* f0a73bc: 00001025 */ or $v0,$zero,$zero
|
|
.L0f0a73c0:
|
|
/* f0a73c0: 8e2e0070 */ lw $t6,0x70($s1)
|
|
/* f0a73c4: 51c00004 */ beqzl $t6,.L0f0a73d8
|
|
/* f0a73c8: 00001825 */ or $v1,$zero,$zero
|
|
/* f0a73cc: 10000002 */ b .L0f0a73d8
|
|
/* f0a73d0: 24030001 */ addiu $v1,$zero,0x1
|
|
/* f0a73d4: 00001825 */ or $v1,$zero,$zero
|
|
.L0f0a73d8:
|
|
/* f0a73d8: 00627821 */ addu $t7,$v1,$v0
|
|
/* f0a73dc: 01e46021 */ addu $t4,$t7,$a0
|
|
/* f0a73e0: 01854821 */ addu $t1,$t4,$a1
|
|
/* f0a73e4: 15210008 */ bne $t1,$at,.L0f0a7408
|
|
/* f0a73e8: 3c088009 */ lui $t0,%hi(g_Is4Mb)
|
|
/* f0a73ec: 91080af0 */ lbu $t0,%lo(g_Is4Mb)($t0)
|
|
/* f0a73f0: 24010001 */ addiu $at,$zero,0x1
|
|
/* f0a73f4: 51010005 */ beql $t0,$at,.L0f0a740c
|
|
/* f0a73f8: 0000a025 */ or $s4,$zero,$zero
|
|
/* f0a73fc: 0fc2be93 */ jal lasersightRenderBeam
|
|
/* f0a7400: 8fa4014c */ lw $a0,0x14c($sp)
|
|
/* f0a7404: afa2014c */ sw $v0,0x14c($sp)
|
|
.L0f0a7408:
|
|
/* f0a7408: 0000a025 */ or $s4,$zero,$zero
|
|
.L0f0a740c:
|
|
/* f0a740c: 26700638 */ addiu $s0,$s3,0x638
|
|
/* f0a7410: 8fb500e4 */ lw $s5,0xe4($sp)
|
|
/* f0a7414: 24120019 */ addiu $s2,$zero,0x1e
|
|
.L0f0a7418:
|
|
/* f0a7418: 0fc2867c */ jal bgunGetWeaponNum2
|
|
/* f0a741c: 02802025 */ or $a0,$s4,$zero
|
|
/* f0a7420: afa200ec */ sw $v0,0xec($sp)
|
|
/* f0a7424: 820a0007 */ lb $t2,0x7($s0)
|
|
/* f0a7428: 8fa4014c */ lw $a0,0x14c($sp)
|
|
/* f0a742c: 260501dc */ addiu $a1,$s0,0x1dc
|
|
/* f0a7430: 114001f2 */ beqz $t2,.L0f0a7bfc
|
|
/* f0a7434: 00003025 */ or $a2,$zero,$zero
|
|
/* f0a7438: 26180384 */ addiu $t8,$s0,0x384
|
|
/* f0a743c: afb8003c */ sw $t8,0x3c($sp)
|
|
/* f0a7440: 0fc2b2e4 */ jal beamRender
|
|
/* f0a7444: 00003825 */ or $a3,$zero,$zero
|
|
/* f0a7448: afa2014c */ sw $v0,0x14c($sp)
|
|
/* f0a744c: 92040000 */ lbu $a0,0x0($s0)
|
|
/* f0a7450: 0fc2c5f0 */ jal weaponHasFlag
|
|
/* f0a7454: 34058000 */ dli $a1,0x8000
|
|
/* f0a7458: 10400030 */ beqz $v0,.L0f0a751c
|
|
/* f0a745c: 8fab014c */ lw $t3,0x14c($sp)
|
|
/* f0a7460: 25790008 */ addiu $t9,$t3,0x8
|
|
/* f0a7464: afb9014c */ sw $t9,0x14c($sp)
|
|
/* f0a7468: 3c0dbc00 */ lui $t5,0xbc00
|
|
/* f0a746c: 3c0e8000 */ lui $t6,0x8000
|
|
/* f0a7470: 35ce0040 */ ori $t6,$t6,0x40
|
|
/* f0a7474: 35ad0002 */ ori $t5,$t5,0x2
|
|
/* f0a7478: ad6d0000 */ sw $t5,0x0($t3)
|
|
/* f0a747c: ad6e0004 */ sw $t6,0x4($t3)
|
|
/* f0a7480: 8faf014c */ lw $t7,0x14c($sp)
|
|
/* f0a7484: 3c090386 */ lui $t1,0x386
|
|
/* f0a7488: 3c088007 */ lui $t0,%hi(var80070090+0x08)
|
|
/* f0a748c: 25ec0008 */ addiu $t4,$t7,0x8
|
|
/* f0a7490: afac014c */ sw $t4,0x14c($sp)
|
|
/* f0a7494: 25080098 */ addiu $t0,$t0,%lo(var80070090+0x08)
|
|
/* f0a7498: 35290010 */ ori $t1,$t1,0x10
|
|
/* f0a749c: ade90000 */ sw $t1,0x0($t7)
|
|
/* f0a74a0: ade80004 */ sw $t0,0x4($t7)
|
|
/* f0a74a4: 8faa014c */ lw $t2,0x14c($sp)
|
|
/* f0a74a8: 3c0b0388 */ lui $t3,0x388
|
|
/* f0a74ac: 3c198007 */ lui $t9,%hi(var80070090)
|
|
/* f0a74b0: 25580008 */ addiu $t8,$t2,0x8
|
|
/* f0a74b4: afb8014c */ sw $t8,0x14c($sp)
|
|
/* f0a74b8: 27390090 */ addiu $t9,$t9,%lo(var80070090)
|
|
/* f0a74bc: 356b0010 */ ori $t3,$t3,0x10
|
|
/* f0a74c0: ad4b0000 */ sw $t3,0x0($t2)
|
|
/* f0a74c4: ad590004 */ sw $t9,0x4($t2)
|
|
/* f0a74c8: 8fad014c */ lw $t5,0x14c($sp)
|
|
/* f0a74cc: 3c0f0384 */ lui $t7,0x384
|
|
/* f0a74d0: 35ef0010 */ ori $t7,$t7,0x10
|
|
/* f0a74d4: 25ae0008 */ addiu $t6,$t5,0x8
|
|
/* f0a74d8: afae014c */ sw $t6,0x14c($sp)
|
|
/* f0a74dc: adaf0000 */ sw $t7,0x0($t5)
|
|
/* f0a74e0: 0fc2d5ea */ jal camGetLookAt
|
|
/* f0a74e4: afad00d4 */ sw $t5,0xd4($sp)
|
|
/* f0a74e8: 8fa500d4 */ lw $a1,0xd4($sp)
|
|
/* f0a74ec: 3c080382 */ lui $t0,0x382
|
|
/* f0a74f0: 35080010 */ ori $t0,$t0,0x10
|
|
/* f0a74f4: aca20004 */ sw $v0,0x4($a1)
|
|
/* f0a74f8: 8fac014c */ lw $t4,0x14c($sp)
|
|
/* f0a74fc: 25890008 */ addiu $t1,$t4,0x8
|
|
/* f0a7500: afa9014c */ sw $t1,0x14c($sp)
|
|
/* f0a7504: ad880000 */ sw $t0,0x0($t4)
|
|
/* f0a7508: 0fc2d5ea */ jal camGetLookAt
|
|
/* f0a750c: afac00d0 */ sw $t4,0xd0($sp)
|
|
/* f0a7510: 8fa300d0 */ lw $v1,0xd0($sp)
|
|
/* f0a7514: 244a0010 */ addiu $t2,$v0,0x10
|
|
/* f0a7518: ac6a0004 */ sw $t2,0x4($v1)
|
|
.L0f0a751c:
|
|
/* f0a751c: 8fb8014c */ lw $t8,0x14c($sp)
|
|
/* f0a7520: 3c19bc00 */ lui $t9,0xbc00
|
|
/* f0a7524: 3739000e */ ori $t9,$t9,0xe
|
|
/* f0a7528: 270b0008 */ addiu $t3,$t8,0x8
|
|
/* f0a752c: afab014c */ sw $t3,0x14c($sp)
|
|
/* f0a7530: 3c014396 */ lui $at,0x4396
|
|
/* f0a7534: 44817000 */ mtc1 $at,$f14
|
|
/* f0a7538: 44806000 */ mtc1 $zero,$f12
|
|
/* f0a753c: af190000 */ sw $t9,0x0($t8)
|
|
/* f0a7540: 0c005b73 */ jal mtx00016dcc
|
|
/* f0a7544: afb800cc */ sw $t8,0xcc($sp)
|
|
/* f0a7548: 8fa300cc */ lw $v1,0xcc($sp)
|
|
/* f0a754c: 24050010 */ addiu $a1,$zero,0x10
|
|
/* f0a7550: ac620004 */ sw $v0,0x4($v1)
|
|
/* f0a7554: 0c006a47 */ jal modelGetPart
|
|
/* f0a7558: 8e04038c */ lw $a0,0x38c($s0)
|
|
/* f0a755c: 10400014 */ beqz $v0,.L0f0a75b0
|
|
/* f0a7560: afa200e8 */ sw $v0,0xe8($sp)
|
|
/* f0a7564: 8e04038c */ lw $a0,0x38c($s0)
|
|
/* f0a7568: 0c006a47 */ jal modelGetPart
|
|
/* f0a756c: 24050011 */ addiu $a1,$zero,0x11
|
|
/* f0a7570: 8fa4003c */ lw $a0,0x3c($sp)
|
|
/* f0a7574: 0c006a87 */ jal modelGetNodeRwData
|
|
/* f0a7578: 00402825 */ or $a1,$v0,$zero
|
|
/* f0a757c: 10400003 */ beqz $v0,.L0f0a758c
|
|
/* f0a7580: 3c06800a */ lui $a2,%hi(var8009cf88)
|
|
/* f0a7584: 240d0001 */ addiu $t5,$zero,0x1
|
|
/* f0a7588: ac4d0000 */ sw $t5,0x0($v0)
|
|
.L0f0a758c:
|
|
/* f0a758c: 240e0001 */ addiu $t6,$zero,0x1
|
|
/* f0a7590: afae0014 */ sw $t6,0x14($sp)
|
|
/* f0a7594: 8fa4003c */ lw $a0,0x3c($sp)
|
|
/* f0a7598: 8fa500e8 */ lw $a1,0xe8($sp)
|
|
/* f0a759c: 24c6cf88 */ addiu $a2,$a2,%lo(var8009cf88)
|
|
/* f0a75a0: 8fa7014c */ lw $a3,0x14c($sp)
|
|
/* f0a75a4: 0fc1fefe */ jal tvscreenRender
|
|
/* f0a75a8: afa00010 */ sw $zero,0x10($sp)
|
|
/* f0a75ac: afa2014c */ sw $v0,0x14c($sp)
|
|
.L0f0a75b0:
|
|
/* f0a75b0: 8faf014c */ lw $t7,0x14c($sp)
|
|
/* f0a75b4: 8e250284 */ lw $a1,0x284($s1)
|
|
/* f0a75b8: 240c0004 */ addiu $t4,$zero,0x4
|
|
/* f0a75bc: afac013c */ sw $t4,0x13c($sp)
|
|
/* f0a75c0: afaf0118 */ sw $t7,0x118($sp)
|
|
/* f0a75c4: 8ca300d8 */ lw $v1,0xd8($a1)
|
|
/* f0a75c8: 3c078007 */ lui $a3,%hi(g_InCutscene)
|
|
/* f0a75cc: 14600013 */ bnez $v1,.L0f0a761c
|
|
/* f0a75d0: 00000000 */ nop
|
|
/* f0a75d4: 8ce70764 */ lw $a3,%lo(g_InCutscene)($a3)
|
|
/* f0a75d8: 14e00010 */ bnez $a3,.L0f0a761c
|
|
/* f0a75dc: 00000000 */ nop
|
|
/* f0a75e0: 8ca20480 */ lw $v0,0x480($a1)
|
|
/* f0a75e4: 50400007 */ beqzl $v0,.L0f0a7604
|
|
/* f0a75e8: 8caa1c54 */ lw $t2,0x1c54($a1)
|
|
/* f0a75ec: 1040000b */ beqz $v0,.L0f0a761c
|
|
/* f0a75f0: 00000000 */ nop
|
|
/* f0a75f4: 80490037 */ lb $t1,0x37($v0)
|
|
/* f0a75f8: 15200008 */ bnez $t1,.L0f0a761c
|
|
/* f0a75fc: 00000000 */ nop
|
|
/* f0a7600: 8caa1c54 */ lw $t2,0x1c54($a1)
|
|
.L0f0a7604:
|
|
/* f0a7604: 8ca800c4 */ lw $t0,0xc4($a1)
|
|
/* f0a7608: 0140c027 */ nor $t8,$t2,$zero
|
|
/* f0a760c: 01185824 */ and $t3,$t0,$t8
|
|
/* f0a7610: 31790001 */ andi $t9,$t3,0x1
|
|
/* f0a7614: 57200016 */ bnezl $t9,.L0f0a7670
|
|
/* f0a7618: 92681615 */ lbu $t0,0x1615($s3)
|
|
.L0f0a761c:
|
|
/* f0a761c: 14600078 */ bnez $v1,.L0f0a7800
|
|
/* f0a7620: 3c078007 */ lui $a3,%hi(g_InCutscene)
|
|
/* f0a7624: 8ce70764 */ lw $a3,%lo(g_InCutscene)($a3)
|
|
/* f0a7628: 54e00076 */ bnezl $a3,.L0f0a7804
|
|
/* f0a762c: 926d1614 */ lbu $t5,0x1614($s3)
|
|
/* f0a7630: 8ca20480 */ lw $v0,0x480($a1)
|
|
/* f0a7634: 50400007 */ beqzl $v0,.L0f0a7654
|
|
/* f0a7638: 8caf1c54 */ lw $t7,0x1c54($a1)
|
|
/* f0a763c: 50400071 */ beqzl $v0,.L0f0a7804
|
|
/* f0a7640: 926d1614 */ lbu $t5,0x1614($s3)
|
|
/* f0a7644: 804d0037 */ lb $t5,0x37($v0)
|
|
/* f0a7648: 55a0006e */ bnezl $t5,.L0f0a7804
|
|
/* f0a764c: 926d1614 */ lbu $t5,0x1614($s3)
|
|
/* f0a7650: 8caf1c54 */ lw $t7,0x1c54($a1)
|
|
.L0f0a7654:
|
|
/* f0a7654: 8cae00c4 */ lw $t6,0xc4($a1)
|
|
/* f0a7658: 01e06027 */ nor $t4,$t7,$zero
|
|
/* f0a765c: 01cc4824 */ and $t1,$t6,$t4
|
|
/* f0a7660: 312a0008 */ andi $t2,$t1,0x8
|
|
/* f0a7664: 51400067 */ beqzl $t2,.L0f0a7804
|
|
/* f0a7668: 926d1614 */ lbu $t5,0x1614($s3)
|
|
/* f0a766c: 92681615 */ lbu $t0,0x1615($s3)
|
|
.L0f0a7670:
|
|
/* f0a7670: 92781614 */ lbu $t8,0x1614($s3)
|
|
/* f0a7674: 26641614 */ addiu $a0,$s3,0x1614
|
|
/* f0a7678: 0118082a */ slt $at,$t0,$t8
|
|
/* f0a767c: 50200009 */ beqzl $at,.L0f0a76a4
|
|
/* f0a7680: 90820002 */ lbu $v0,0x2($a0)
|
|
/* f0a7684: 90830000 */ lbu $v1,0x0($a0)
|
|
/* f0a7688: 908b0002 */ lbu $t3,0x2($a0)
|
|
/* f0a768c: 0163082a */ slt $at,$t3,$v1
|
|
/* f0a7690: 50200004 */ beqzl $at,.L0f0a76a4
|
|
/* f0a7694: 90820002 */ lbu $v0,0x2($a0)
|
|
/* f0a7698: 1000000a */ b .L0f0a76c4
|
|
/* f0a769c: 00601025 */ or $v0,$v1,$zero
|
|
/* f0a76a0: 90820002 */ lbu $v0,0x2($a0)
|
|
.L0f0a76a4:
|
|
/* f0a76a4: 90860001 */ lbu $a2,0x1($a0)
|
|
/* f0a76a8: 00401825 */ or $v1,$v0,$zero
|
|
/* f0a76ac: 0046082a */ slt $at,$v0,$a2
|
|
/* f0a76b0: 10200003 */ beqz $at,.L0f0a76c0
|
|
/* f0a76b4: 00000000 */ nop
|
|
/* f0a76b8: 10000001 */ b .L0f0a76c0
|
|
/* f0a76bc: 00c01825 */ or $v1,$a2,$zero
|
|
.L0f0a76c0:
|
|
/* f0a76c0: 00601025 */ or $v0,$v1,$zero
|
|
.L0f0a76c4:
|
|
/* f0a76c4: 90890003 */ lbu $t1,0x3($a0)
|
|
/* f0a76c8: 0002ce00 */ sll $t9,$v0,0x18
|
|
/* f0a76cc: 00026c00 */ sll $t5,$v0,0x10
|
|
/* f0a76d0: 032d7825 */ or $t7,$t9,$t5
|
|
/* f0a76d4: 00027200 */ sll $t6,$v0,0x8
|
|
/* f0a76d8: 01ee6025 */ or $t4,$t7,$t6
|
|
/* f0a76dc: 012c5021 */ addu $t2,$t1,$t4
|
|
/* f0a76e0: afaa0140 */ sw $t2,0x140($sp)
|
|
/* f0a76e4: 8ca300d8 */ lw $v1,0xd8($a1)
|
|
/* f0a76e8: 14600021 */ bnez $v1,.L0f0a7770
|
|
/* f0a76ec: 00000000 */ nop
|
|
/* f0a76f0: 14e0001f */ bnez $a3,.L0f0a7770
|
|
/* f0a76f4: 00000000 */ nop
|
|
/* f0a76f8: 8ca20480 */ lw $v0,0x480($a1)
|
|
/* f0a76fc: 50400007 */ beqzl $v0,.L0f0a771c
|
|
/* f0a7700: 8cab1c54 */ lw $t3,0x1c54($a1)
|
|
/* f0a7704: 1040001a */ beqz $v0,.L0f0a7770
|
|
/* f0a7708: 00000000 */ nop
|
|
/* f0a770c: 80480037 */ lb $t0,0x37($v0)
|
|
/* f0a7710: 15000017 */ bnez $t0,.L0f0a7770
|
|
/* f0a7714: 00000000 */ nop
|
|
/* f0a7718: 8cab1c54 */ lw $t3,0x1c54($a1)
|
|
.L0f0a771c:
|
|
/* f0a771c: 8cb800c4 */ lw $t8,0xc4($a1)
|
|
/* f0a7720: 3c02800a */ lui $v0,%hi(var8009caec+0x3)
|
|
/* f0a7724: 0160c827 */ nor $t9,$t3,$zero
|
|
/* f0a7728: 03196824 */ and $t5,$t8,$t9
|
|
/* f0a772c: 31af0001 */ andi $t7,$t5,0x1
|
|
/* f0a7730: 11e0000f */ beqz $t7,.L0f0a7770
|
|
/* f0a7734: 00000000 */ nop
|
|
/* f0a7738: 9042caef */ lbu $v0,%lo(var8009caec+0x3)($v0)
|
|
/* f0a773c: 3c06800a */ lui $a2,%hi(var8009caf0)
|
|
/* f0a7740: 90c6caf0 */ lbu $a2,%lo(var8009caf0)($a2)
|
|
/* f0a7744: 00027600 */ sll $t6,$v0,0x18
|
|
/* f0a7748: 00024c00 */ sll $t1,$v0,0x10
|
|
/* f0a774c: 01c96025 */ or $t4,$t6,$t1
|
|
/* f0a7750: 00025200 */ sll $t2,$v0,0x8
|
|
/* f0a7754: 018a4025 */ or $t0,$t4,$t2
|
|
/* f0a7758: afa200b0 */ sw $v0,0xb0($sp)
|
|
/* f0a775c: afa200b4 */ sw $v0,0xb4($sp)
|
|
/* f0a7760: afa200b8 */ sw $v0,0xb8($sp)
|
|
/* f0a7764: 00c8a821 */ addu $s5,$a2,$t0
|
|
/* f0a7768: 1000001f */ b .L0f0a77e8
|
|
/* f0a776c: afa600bc */ sw $a2,0xbc($sp)
|
|
.L0f0a7770:
|
|
/* f0a7770: 5460001e */ bnezl $v1,.L0f0a77ec
|
|
/* f0a7774: 8fb900ec */ lw $t9,0xec($sp)
|
|
/* f0a7778: 54e0001c */ bnezl $a3,.L0f0a77ec
|
|
/* f0a777c: 8fb900ec */ lw $t9,0xec($sp)
|
|
/* f0a7780: 8ca20480 */ lw $v0,0x480($a1)
|
|
/* f0a7784: 50400007 */ beqzl $v0,.L0f0a77a4
|
|
/* f0a7788: 8cb91c54 */ lw $t9,0x1c54($a1)
|
|
/* f0a778c: 50400017 */ beqzl $v0,.L0f0a77ec
|
|
/* f0a7790: 8fb900ec */ lw $t9,0xec($sp)
|
|
/* f0a7794: 804b0037 */ lb $t3,0x37($v0)
|
|
/* f0a7798: 55600014 */ bnezl $t3,.L0f0a77ec
|
|
/* f0a779c: 8fb900ec */ lw $t9,0xec($sp)
|
|
/* f0a77a0: 8cb91c54 */ lw $t9,0x1c54($a1)
|
|
.L0f0a77a4:
|
|
/* f0a77a4: 8cb800c4 */ lw $t8,0xc4($a1)
|
|
/* f0a77a8: 240200ff */ addiu $v0,$zero,0xff
|
|
/* f0a77ac: 03206827 */ nor $t5,$t9,$zero
|
|
/* f0a77b0: 030d7824 */ and $t7,$t8,$t5
|
|
/* f0a77b4: 31ee0008 */ andi $t6,$t7,0x8
|
|
/* f0a77b8: 11c0000b */ beqz $t6,.L0f0a77e8
|
|
/* f0a77bc: 24050080 */ addiu $a1,$zero,0x80
|
|
/* f0a77c0: 00024e00 */ sll $t1,$v0,0x18
|
|
/* f0a77c4: 00006400 */ sll $t4,$zero,0x10
|
|
/* f0a77c8: 012c5025 */ or $t2,$t1,$t4
|
|
/* f0a77cc: 00004200 */ sll $t0,$zero,0x8
|
|
/* f0a77d0: 01485825 */ or $t3,$t2,$t0
|
|
/* f0a77d4: 00aba821 */ addu $s5,$a1,$t3
|
|
/* f0a77d8: afa200a0 */ sw $v0,0xa0($sp)
|
|
/* f0a77dc: afa000a4 */ sw $zero,0xa4($sp)
|
|
/* f0a77e0: afa000a8 */ sw $zero,0xa8($sp)
|
|
/* f0a77e4: afa500ac */ sw $a1,0xac($sp)
|
|
.L0f0a77e8:
|
|
/* f0a77e8: 8fb900ec */ lw $t9,0xec($sp)
|
|
.L0f0a77ec:
|
|
/* f0a77ec: 24010001 */ addiu $at,$zero,0x1
|
|
/* f0a77f0: 5721003d */ bnel $t9,$at,.L0f0a78e8
|
|
/* f0a77f4: 8e6f00bc */ lw $t7,0xbc($s3)
|
|
/* f0a77f8: 1000003a */ b .L0f0a78e4
|
|
/* f0a77fc: afb50140 */ sw $s5,0x140($sp)
|
|
.L0f0a7800:
|
|
/* f0a7800: 926d1614 */ lbu $t5,0x1614($s3)
|
|
.L0f0a7804:
|
|
/* f0a7804: 92781617 */ lbu $t8,0x1617($s3)
|
|
/* f0a7808: 92691615 */ lbu $t1,0x1615($s3)
|
|
/* f0a780c: 92681616 */ lbu $t0,0x1616($s3)
|
|
/* f0a7810: 000d7e00 */ sll $t7,$t5,0x18
|
|
/* f0a7814: 030f7025 */ or $t6,$t8,$t7
|
|
/* f0a7818: 00096400 */ sll $t4,$t1,0x10
|
|
/* f0a781c: 01cc5025 */ or $t2,$t6,$t4
|
|
/* f0a7820: 00085a00 */ sll $t3,$t0,0x8
|
|
/* f0a7824: 014bc825 */ or $t9,$t2,$t3
|
|
/* f0a7828: afb90140 */ sw $t9,0x140($sp)
|
|
/* f0a782c: 920d0000 */ lbu $t5,0x0($s0)
|
|
/* f0a7830: 24010006 */ addiu $at,$zero,0x6
|
|
/* f0a7834: 0320a825 */ or $s5,$t9,$zero
|
|
/* f0a7838: 15a1002a */ bne $t5,$at,.L0f0a78e4
|
|
/* f0a783c: 3c04ff00 */ lui $a0,0xff00
|
|
/* f0a7840: 3c014248 */ lui $at,0x4248
|
|
/* f0a7844: 44812000 */ mtc1 $at,$f4
|
|
/* f0a7848: c612023c */ lwc1 $f18,0x23c($s0)
|
|
/* f0a784c: 24060001 */ addiu $a2,$zero,0x1
|
|
/* f0a7850: 3c014f00 */ lui $at,0x4f00
|
|
/* f0a7854: 46049182 */ mul.s $f6,$f18,$f4
|
|
/* f0a7858: 3484007f */ ori $a0,$a0,0x7f
|
|
/* f0a785c: 4458f800 */ cfc1 $t8,$31
|
|
/* f0a7860: 44c6f800 */ ctc1 $a2,$31
|
|
/* f0a7864: 00000000 */ nop
|
|
/* f0a7868: 46003224 */ cvt.w.s $f8,$f6
|
|
/* f0a786c: 4446f800 */ cfc1 $a2,$31
|
|
/* f0a7870: 00000000 */ nop
|
|
/* f0a7874: 30c60078 */ andi $a2,$a2,0x78
|
|
/* f0a7878: 50c00013 */ beqzl $a2,.L0f0a78c8
|
|
/* f0a787c: 44064000 */ mfc1 $a2,$f8
|
|
/* f0a7880: 44814000 */ mtc1 $at,$f8
|
|
/* f0a7884: 24060001 */ addiu $a2,$zero,0x1
|
|
/* f0a7888: 46083201 */ sub.s $f8,$f6,$f8
|
|
/* f0a788c: 44c6f800 */ ctc1 $a2,$31
|
|
/* f0a7890: 00000000 */ nop
|
|
/* f0a7894: 46004224 */ cvt.w.s $f8,$f8
|
|
/* f0a7898: 4446f800 */ cfc1 $a2,$31
|
|
/* f0a789c: 00000000 */ nop
|
|
/* f0a78a0: 30c60078 */ andi $a2,$a2,0x78
|
|
/* f0a78a4: 14c00005 */ bnez $a2,.L0f0a78bc
|
|
/* f0a78a8: 00000000 */ nop
|
|
/* f0a78ac: 44064000 */ mfc1 $a2,$f8
|
|
/* f0a78b0: 3c018000 */ lui $at,0x8000
|
|
/* f0a78b4: 10000007 */ b .L0f0a78d4
|
|
/* f0a78b8: 00c13025 */ or $a2,$a2,$at
|
|
.L0f0a78bc:
|
|
/* f0a78bc: 10000005 */ b .L0f0a78d4
|
|
/* f0a78c0: 2406ffff */ addiu $a2,$zero,-1
|
|
/* f0a78c4: 44064000 */ mfc1 $a2,$f8
|
|
.L0f0a78c8:
|
|
/* f0a78c8: 00000000 */ nop
|
|
/* f0a78cc: 04c0fffb */ bltz $a2,.L0f0a78bc
|
|
/* f0a78d0: 00000000 */ nop
|
|
.L0f0a78d4:
|
|
/* f0a78d4: 44d8f800 */ ctc1 $t8,$31
|
|
/* f0a78d8: 0fc01a40 */ jal colourBlend
|
|
/* f0a78dc: 03202825 */ or $a1,$t9,$zero
|
|
/* f0a78e0: afa20140 */ sw $v0,0x140($sp)
|
|
.L0f0a78e4:
|
|
/* f0a78e4: 8e6f00bc */ lw $t7,0xbc($s3)
|
|
.L0f0a78e8:
|
|
/* f0a78e8: 0fc08af9 */ jal chrGetCloakAlpha
|
|
/* f0a78ec: 8de40004 */ lw $a0,0x4($t7)
|
|
/* f0a78f0: 284100ff */ slti $at,$v0,0xff
|
|
/* f0a78f4: 1020000f */ beqz $at,.L0f0a7934
|
|
/* f0a78f8: 240c0001 */ addiu $t4,$zero,0x1
|
|
/* f0a78fc: 44825000 */ mtc1 $v0,$f10
|
|
/* f0a7900: 3c017f1b */ lui $at,%hi(var7f1aca90)
|
|
/* f0a7904: c432ca90 */ lwc1 $f18,%lo(var7f1aca90)($at)
|
|
/* f0a7908: 46805420 */ cvt.s.w $f16,$f10
|
|
/* f0a790c: 8fa40140 */ lw $a0,0x140($sp)
|
|
/* f0a7910: 240e0005 */ addiu $t6,$zero,0x5
|
|
/* f0a7914: afae013c */ sw $t6,0x13c($sp)
|
|
/* f0a7918: afa40144 */ sw $a0,0x144($sp)
|
|
/* f0a791c: 46128102 */ mul.s $f4,$f16,$f18
|
|
/* f0a7920: 4600218d */ trunc.w.s $f6,$f4
|
|
/* f0a7924: 44033000 */ mfc1 $v1,$f6
|
|
/* f0a7928: 00000000 */ nop
|
|
/* f0a792c: 24750041 */ addiu $s5,$v1,0x41
|
|
/* f0a7930: afb50140 */ sw $s5,0x140($sp)
|
|
.L0f0a7934:
|
|
/* f0a7934: 0c0059d8 */ jal mtx00016760
|
|
/* f0a7938: afac0110 */ sw $t4,0x110($sp)
|
|
/* f0a793c: 8e020218 */ lw $v0,0x218($s0)
|
|
/* f0a7940: 50400017 */ beqzl $v0,.L0f0a79a0
|
|
/* f0a7944: 8fa400ec */ lw $a0,0xec($sp)
|
|
/* f0a7948: 8c460018 */ lw $a2,0x18($v0)
|
|
/* f0a794c: afa00094 */ sw $zero,0x94($sp)
|
|
/* f0a7950: 50c00013 */ beqzl $a2,.L0f0a79a0
|
|
/* f0a7954: 8fa400ec */ lw $a0,0xec($sp)
|
|
/* f0a7958: 8cc80008 */ lw $t0,0x8($a2)
|
|
/* f0a795c: 240a0001 */ addiu $t2,$zero,0x1
|
|
/* f0a7960: 27a4010c */ addiu $a0,$sp,0x10c
|
|
/* f0a7964: 1100000d */ beqz $t0,.L0f0a799c
|
|
/* f0a7968: 00c02825 */ or $a1,$a2,$zero
|
|
/* f0a796c: afaa0094 */ sw $t2,0x94($sp)
|
|
/* f0a7970: 0c0087bd */ jal modelRender
|
|
/* f0a7974: afa60098 */ sw $a2,0x98($sp)
|
|
/* f0a7978: 8fa60098 */ lw $a2,0x98($sp)
|
|
/* f0a797c: 8ccb0008 */ lw $t3,0x8($a2)
|
|
/* f0a7980: 8cc4000c */ lw $a0,0xc($a2)
|
|
/* f0a7984: 0fc30cfc */ jal mtxF2LBulk
|
|
/* f0a7988: 8565000e */ lh $a1,0xe($t3)
|
|
/* f0a798c: 8e0d021c */ lw $t5,0x21c($s0)
|
|
/* f0a7990: 51a00003 */ beqzl $t5,.L0f0a79a0
|
|
/* f0a7994: 8fa400ec */ lw $a0,0xec($sp)
|
|
/* f0a7998: ae000218 */ sw $zero,0x218($s0)
|
|
.L0f0a799c:
|
|
/* f0a799c: 8fa400ec */ lw $a0,0xec($sp)
|
|
.L0f0a79a0:
|
|
/* f0a79a0: 0fc2c5f0 */ jal weaponHasFlag
|
|
/* f0a79a4: 24050020 */ addiu $a1,$zero,0x20
|
|
/* f0a79a8: 1040000e */ beqz $v0,.L0f0a79e4
|
|
/* f0a79ac: 24010001 */ addiu $at,$zero,0x1
|
|
/* f0a79b0: 8fb80118 */ lw $t8,0x118($sp)
|
|
/* f0a79b4: 3c0fb600 */ lui $t7,0xb600
|
|
/* f0a79b8: 24093000 */ addiu $t1,$zero,0x3000
|
|
/* f0a79bc: 27190008 */ addiu $t9,$t8,0x8
|
|
/* f0a79c0: afb90118 */ sw $t9,0x118($sp)
|
|
/* f0a79c4: af090004 */ sw $t1,0x4($t8)
|
|
/* f0a79c8: 16800004 */ bnez $s4,.L0f0a79dc
|
|
/* f0a79cc: af0f0000 */ sw $t7,0x0($t8)
|
|
/* f0a79d0: 240e0003 */ addiu $t6,$zero,0x3
|
|
/* f0a79d4: 10000003 */ b .L0f0a79e4
|
|
/* f0a79d8: afae0148 */ sw $t6,0x148($sp)
|
|
.L0f0a79dc:
|
|
/* f0a79dc: 240c0002 */ addiu $t4,$zero,0x2
|
|
/* f0a79e0: afac0148 */ sw $t4,0x148($sp)
|
|
.L0f0a79e4:
|
|
/* f0a79e4: 8e28006c */ lw $t0,0x6c($s1)
|
|
/* f0a79e8: 00002825 */ or $a1,$zero,$zero
|
|
/* f0a79ec: 00002025 */ or $a0,$zero,$zero
|
|
/* f0a79f0: 11000003 */ beqz $t0,.L0f0a7a00
|
|
/* f0a79f4: 00001025 */ or $v0,$zero,$zero
|
|
/* f0a79f8: 10000001 */ b .L0f0a7a00
|
|
/* f0a79fc: 24050001 */ addiu $a1,$zero,0x1
|
|
.L0f0a7a00:
|
|
/* f0a7a00: 8e2a0068 */ lw $t2,0x68($s1)
|
|
/* f0a7a04: 00001825 */ or $v1,$zero,$zero
|
|
/* f0a7a08: 11400003 */ beqz $t2,.L0f0a7a18
|
|
/* f0a7a0c: 00000000 */ nop
|
|
/* f0a7a10: 10000001 */ b .L0f0a7a18
|
|
/* f0a7a14: 24040001 */ addiu $a0,$zero,0x1
|
|
.L0f0a7a18:
|
|
/* f0a7a18: 8e2b0064 */ lw $t3,0x64($s1)
|
|
/* f0a7a1c: 11600003 */ beqz $t3,.L0f0a7a2c
|
|
/* f0a7a20: 00000000 */ nop
|
|
/* f0a7a24: 10000001 */ b .L0f0a7a2c
|
|
/* f0a7a28: 24020001 */ addiu $v0,$zero,0x1
|
|
.L0f0a7a2c:
|
|
/* f0a7a2c: 8e2d0070 */ lw $t5,0x70($s1)
|
|
/* f0a7a30: 11a00003 */ beqz $t5,.L0f0a7a40
|
|
/* f0a7a34: 00000000 */ nop
|
|
/* f0a7a38: 10000001 */ b .L0f0a7a40
|
|
/* f0a7a3c: 24030001 */ addiu $v1,$zero,0x1
|
|
.L0f0a7a40:
|
|
/* f0a7a40: 0062c021 */ addu $t8,$v1,$v0
|
|
/* f0a7a44: 0304c821 */ addu $t9,$t8,$a0
|
|
/* f0a7a48: 03257821 */ addu $t7,$t9,$a1
|
|
/* f0a7a4c: 15e10036 */ bne $t7,$at,.L0f0a7b28
|
|
/* f0a7a50: 24050041 */ addiu $a1,$zero,0x41
|
|
/* f0a7a54: 0c006a47 */ jal modelGetPart
|
|
/* f0a7a58: 8e04038c */ lw $a0,0x38c($s0)
|
|
/* f0a7a5c: 50400033 */ beqzl $v0,.L0f0a7b2c
|
|
/* f0a7a60: 27a4010c */ addiu $a0,$sp,0x10c
|
|
/* f0a7a64: 8c440004 */ lw $a0,0x4($v0)
|
|
/* f0a7a68: 00002825 */ or $a1,$zero,$zero
|
|
/* f0a7a6c: 84890010 */ lh $t1,0x10($a0)
|
|
/* f0a7a70: 5920002e */ blezl $t1,.L0f0a7b2c
|
|
/* f0a7a74: 27a4010c */ addiu $a0,$sp,0x10c
|
|
/* f0a7a78: 8e2a0034 */ lw $t2,0x34($s1)
|
|
.L0f0a7a7c:
|
|
/* f0a7a7c: 8c8e000c */ lw $t6,0xc($a0)
|
|
/* f0a7a80: 00056080 */ sll $t4,$a1,0x2
|
|
/* f0a7a84: 01520019 */ multu $t2,$s2
|
|
/* f0a7a88: 01856023 */ subu $t4,$t4,$a1
|
|
/* f0a7a8c: 000c6080 */ sll $t4,$t4,0x2
|
|
/* f0a7a90: 01cc1021 */ addu $v0,$t6,$t4
|
|
/* f0a7a94: 8448000a */ lh $t0,0xa($v0)
|
|
/* f0a7a98: 0005c880 */ sll $t9,$a1,0x2
|
|
/* f0a7a9c: 0325c823 */ subu $t9,$t9,$a1
|
|
/* f0a7aa0: 0019c880 */ sll $t9,$t9,0x2
|
|
/* f0a7aa4: 24420002 */ addiu $v0,$v0,0x2
|
|
/* f0a7aa8: 00005812 */ mflo $t3
|
|
/* f0a7aac: 010b6823 */ subu $t5,$t0,$t3
|
|
/* f0a7ab0: a44d0008 */ sh $t5,0x8($v0)
|
|
/* f0a7ab4: 8c98000c */ lw $t8,0xc($a0)
|
|
/* f0a7ab8: 03197821 */ addu $t7,$t8,$t9
|
|
/* f0a7abc: 85e9000a */ lh $t1,0xa($t7)
|
|
/* f0a7ac0: 2921a000 */ slti $at,$t1,-24576
|
|
/* f0a7ac4: 50200014 */ beqzl $at,.L0f0a7b18
|
|
/* f0a7ac8: 84980010 */ lh $t8,0x10($a0)
|
|
/* f0a7acc: 848e0010 */ lh $t6,0x10($a0)
|
|
/* f0a7ad0: 00001825 */ or $v1,$zero,$zero
|
|
/* f0a7ad4: 59c00010 */ blezl $t6,.L0f0a7b18
|
|
/* f0a7ad8: 84980010 */ lh $t8,0x10($a0)
|
|
/* f0a7adc: 8c8c000c */ lw $t4,0xc($a0)
|
|
.L0f0a7ae0:
|
|
/* f0a7ae0: 00035080 */ sll $t2,$v1,0x2
|
|
/* f0a7ae4: 01435023 */ subu $t2,$t2,$v1
|
|
/* f0a7ae8: 000a5080 */ sll $t2,$t2,0x2
|
|
/* f0a7aec: 018a1021 */ addu $v0,$t4,$t2
|
|
/* f0a7af0: 8448000a */ lh $t0,0xa($v0)
|
|
/* f0a7af4: 24630001 */ addiu $v1,$v1,0x1
|
|
/* f0a7af8: 24420002 */ addiu $v0,$v0,0x2
|
|
/* f0a7afc: 250b2000 */ addiu $t3,$t0,0x2000
|
|
/* f0a7b00: a44b0008 */ sh $t3,0x8($v0)
|
|
/* f0a7b04: 848d0010 */ lh $t5,0x10($a0)
|
|
/* f0a7b08: 006d082a */ slt $at,$v1,$t5
|
|
/* f0a7b0c: 5420fff4 */ bnezl $at,.L0f0a7ae0
|
|
/* f0a7b10: 8c8c000c */ lw $t4,0xc($a0)
|
|
/* f0a7b14: 84980010 */ lh $t8,0x10($a0)
|
|
.L0f0a7b18:
|
|
/* f0a7b18: 24a50001 */ addiu $a1,$a1,0x1
|
|
/* f0a7b1c: 00b8082a */ slt $at,$a1,$t8
|
|
/* f0a7b20: 5420ffd6 */ bnezl $at,.L0f0a7a7c
|
|
/* f0a7b24: 8e2a0034 */ lw $t2,0x34($s1)
|
|
.L0f0a7b28:
|
|
/* f0a7b28: 27a4010c */ addiu $a0,$sp,0x10c
|
|
.L0f0a7b2c:
|
|
/* f0a7b2c: 0c0087bd */ jal modelRender
|
|
/* f0a7b30: 8fa5003c */ lw $a1,0x3c($sp)
|
|
/* f0a7b34: 8e791594 */ lw $t9,0x1594($s3)
|
|
/* f0a7b38: 3c0f8007 */ lui $t7,%hi(var800702dc)
|
|
/* f0a7b3c: 53200013 */ beqzl $t9,.L0f0a7b8c
|
|
/* f0a7b40: 8fac0118 */ lw $t4,0x118($sp)
|
|
/* f0a7b44: 8def02dc */ lw $t7,%lo(var800702dc)($t7)
|
|
/* f0a7b48: 8fa90140 */ lw $t1,0x140($sp)
|
|
/* f0a7b4c: 51e0000f */ beqzl $t7,.L0f0a7b8c
|
|
/* f0a7b50: 8fac0118 */ lw $t4,0x118($sp)
|
|
/* f0a7b54: afa9007c */ sw $t1,0x7c($sp)
|
|
/* f0a7b58: 8e0e0390 */ lw $t6,0x390($s0)
|
|
/* f0a7b5c: 26050534 */ addiu $a1,$s0,0x534
|
|
/* f0a7b60: 00a02025 */ or $a0,$a1,$zero
|
|
/* f0a7b64: ae0e0540 */ sw $t6,0x540($s0)
|
|
/* f0a7b68: 0c007308 */ jal modelUpdateRelations
|
|
/* f0a7b6c: afa50054 */ sw $a1,0x54($sp)
|
|
/* f0a7b70: 8fa50054 */ lw $a1,0x54($sp)
|
|
/* f0a7b74: afb50140 */ sw $s5,0x140($sp)
|
|
/* f0a7b78: 0c0087bd */ jal modelRender
|
|
/* f0a7b7c: 27a4010c */ addiu $a0,$sp,0x10c
|
|
/* f0a7b80: 8fa4007c */ lw $a0,0x7c($sp)
|
|
/* f0a7b84: afa40140 */ sw $a0,0x140($sp)
|
|
/* f0a7b88: 8fac0118 */ lw $t4,0x118($sp)
|
|
.L0f0a7b8c:
|
|
/* f0a7b8c: 8fa400ec */ lw $a0,0xec($sp)
|
|
/* f0a7b90: 24050020 */ addiu $a1,$zero,0x20
|
|
/* f0a7b94: 0fc2c5f0 */ jal weaponHasFlag
|
|
/* f0a7b98: afac014c */ sw $t4,0x14c($sp)
|
|
/* f0a7b9c: 10400007 */ beqz $v0,.L0f0a7bbc
|
|
/* f0a7ba0: 8faa014c */ lw $t2,0x14c($sp)
|
|
/* f0a7ba4: 25480008 */ addiu $t0,$t2,0x8
|
|
/* f0a7ba8: afa8014c */ sw $t0,0x14c($sp)
|
|
/* f0a7bac: 3c0bb600 */ lui $t3,0xb600
|
|
/* f0a7bb0: 240d3000 */ addiu $t5,$zero,0x3000
|
|
/* f0a7bb4: ad4d0004 */ sw $t5,0x4($t2)
|
|
/* f0a7bb8: ad4b0000 */ sw $t3,0x0($t2)
|
|
.L0f0a7bbc:
|
|
/* f0a7bbc: 8e18038c */ lw $t8,0x38c($s0)
|
|
/* f0a7bc0: 8e040390 */ lw $a0,0x390($s0)
|
|
/* f0a7bc4: 0fc30cfc */ jal mtxF2LBulk
|
|
/* f0a7bc8: 8705000e */ lh $a1,0xe($t8)
|
|
/* f0a7bcc: 0c0059e1 */ jal mtx00016784
|
|
/* f0a7bd0: 00000000 */ nop
|
|
/* f0a7bd4: 8fb9014c */ lw $t9,0x14c($sp)
|
|
/* f0a7bd8: 3c09bc00 */ lui $t1,0xbc00
|
|
/* f0a7bdc: 3529000e */ ori $t1,$t1,0xe
|
|
/* f0a7be0: 272f0008 */ addiu $t7,$t9,0x8
|
|
/* f0a7be4: afaf014c */ sw $t7,0x14c($sp)
|
|
/* f0a7be8: af290000 */ sw $t1,0x0($t9)
|
|
/* f0a7bec: 0c002adb */ jal viGetPerspScale
|
|
/* f0a7bf0: afb90074 */ sw $t9,0x74($sp)
|
|
/* f0a7bf4: 8fa30074 */ lw $v1,0x74($sp)
|
|
/* f0a7bf8: ac620004 */ sw $v0,0x4($v1)
|
|
.L0f0a7bfc:
|
|
/* f0a7bfc: 26940001 */ addiu $s4,$s4,0x1
|
|
/* f0a7c00: 24010002 */ addiu $at,$zero,0x2
|
|
/* f0a7c04: 1681fe04 */ bne $s4,$at,.L0f0a7418
|
|
/* f0a7c08: 261007a4 */ addiu $s0,$s0,0x7a4
|
|
/* f0a7c0c: afb500e4 */ sw $s5,0xe4($sp)
|
|
/* f0a7c10: 0fc2baf8 */ jal casingsRender
|
|
/* f0a7c14: 27a4014c */ addiu $a0,$sp,0x14c
|
|
/* f0a7c18: 0fc5d8a6 */ jal mblur0f176298
|
|
/* f0a7c1c: 00000000 */ nop
|
|
/* f0a7c20: 0fc5d8ab */ jal mblur0f1762ac
|
|
/* f0a7c24: 8fa4014c */ lw $a0,0x14c($sp)
|
|
/* f0a7c28: afa2014c */ sw $v0,0x14c($sp)
|
|
/* f0a7c2c: 0c002c74 */ jal vi0000b1d0
|
|
/* f0a7c30: 00402025 */ or $a0,$v0,$zero
|
|
/* f0a7c34: 244e0008 */ addiu $t6,$v0,0x8
|
|
/* f0a7c38: afae014c */ sw $t6,0x14c($sp)
|
|
/* f0a7c3c: 0c002f40 */ jal viGetViewLeft
|
|
/* f0a7c40: 00408825 */ or $s1,$v0,$zero
|
|
/* f0a7c44: 00028400 */ sll $s0,$v0,0x10
|
|
/* f0a7c48: 00106403 */ sra $t4,$s0,0x10
|
|
/* f0a7c4c: 0c002f44 */ jal viGetViewTop
|
|
/* f0a7c50: 01808025 */ or $s0,$t4,$zero
|
|
/* f0a7c54: 44824000 */ mtc1 $v0,$f8
|
|
/* f0a7c58: 44902000 */ mtc1 $s0,$f4
|
|
/* f0a7c5c: 3c014080 */ lui $at,0x4080
|
|
/* f0a7c60: 468042a0 */ cvt.s.w $f10,$f8
|
|
/* f0a7c64: 44810000 */ mtc1 $at,$f0
|
|
/* f0a7c68: 3c01ed00 */ lui $at,0xed00
|
|
/* f0a7c6c: 468021a0 */ cvt.s.w $f6,$f4
|
|
/* f0a7c70: 46005402 */ mul.s $f16,$f10,$f0
|
|
/* f0a7c74: 00000000 */ nop
|
|
/* f0a7c78: 46003202 */ mul.s $f8,$f6,$f0
|
|
/* f0a7c7c: 4600848d */ trunc.w.s $f18,$f16
|
|
/* f0a7c80: 4600428d */ trunc.w.s $f10,$f8
|
|
/* f0a7c84: 44089000 */ mfc1 $t0,$f18
|
|
/* f0a7c88: 44195000 */ mfc1 $t9,$f10
|
|
/* f0a7c8c: 310b0fff */ andi $t3,$t0,0xfff
|
|
/* f0a7c90: 01616825 */ or $t5,$t3,$at
|
|
/* f0a7c94: 332f0fff */ andi $t7,$t9,0xfff
|
|
/* f0a7c98: 000f4b00 */ sll $t1,$t7,0xc
|
|
/* f0a7c9c: 01a97025 */ or $t6,$t5,$t1
|
|
/* f0a7ca0: 0c002f22 */ jal viGetViewWidth
|
|
/* f0a7ca4: ae2e0000 */ sw $t6,0x0($s1)
|
|
/* f0a7ca8: 00029400 */ sll $s2,$v0,0x10
|
|
/* f0a7cac: 00126403 */ sra $t4,$s2,0x10
|
|
/* f0a7cb0: 0c002f40 */ jal viGetViewLeft
|
|
/* f0a7cb4: 01809025 */ or $s2,$t4,$zero
|
|
/* f0a7cb8: 0002a400 */ sll $s4,$v0,0x10
|
|
/* f0a7cbc: 00145403 */ sra $t2,$s4,0x10
|
|
/* f0a7cc0: 0c002f44 */ jal viGetViewTop
|
|
/* f0a7cc4: 0140a025 */ or $s4,$t2,$zero
|
|
/* f0a7cc8: 00028400 */ sll $s0,$v0,0x10
|
|
/* f0a7ccc: 00104403 */ sra $t0,$s0,0x10
|
|
/* f0a7cd0: 0c002f26 */ jal viGetViewHeight
|
|
/* f0a7cd4: 01008025 */ or $s0,$t0,$zero
|
|
/* f0a7cd8: 00505821 */ addu $t3,$v0,$s0
|
|
/* f0a7cdc: 448b8000 */ mtc1 $t3,$f16
|
|
/* f0a7ce0: 02926821 */ addu $t5,$s4,$s2
|
|
/* f0a7ce4: 448d5000 */ mtc1 $t5,$f10
|
|
/* f0a7ce8: 468084a0 */ cvt.s.w $f18,$f16
|
|
/* f0a7cec: 3c014080 */ lui $at,0x4080
|
|
/* f0a7cf0: 44812000 */ mtc1 $at,$f4
|
|
/* f0a7cf4: 46805420 */ cvt.s.w $f16,$f10
|
|
/* f0a7cf8: 46049182 */ mul.s $f6,$f18,$f4
|
|
/* f0a7cfc: 44819000 */ mtc1 $at,$f18
|
|
/* f0a7d00: 00000000 */ nop
|
|
/* f0a7d04: 46128102 */ mul.s $f4,$f16,$f18
|
|
/* f0a7d08: 4600320d */ trunc.w.s $f8,$f6
|
|
/* f0a7d0c: 4600218d */ trunc.w.s $f6,$f4
|
|
/* f0a7d10: 44194000 */ mfc1 $t9,$f8
|
|
/* f0a7d14: 440e3000 */ mfc1 $t6,$f6
|
|
/* f0a7d18: 332f0fff */ andi $t7,$t9,0xfff
|
|
/* f0a7d1c: 31cc0fff */ andi $t4,$t6,0xfff
|
|
/* f0a7d20: 000c5300 */ sll $t2,$t4,0xc
|
|
/* f0a7d24: 01ea4025 */ or $t0,$t7,$t2
|
|
/* f0a7d28: ae280004 */ sw $t0,0x4($s1)
|
|
/* f0a7d2c: 8fb80150 */ lw $t8,0x150($sp)
|
|
/* f0a7d30: 8fab014c */ lw $t3,0x14c($sp)
|
|
/* f0a7d34: af0b0000 */ sw $t3,0x0($t8)
|
|
/* f0a7d38: 8fbf0034 */ lw $ra,0x34($sp)
|
|
.L0f0a7d3c:
|
|
/* f0a7d3c: 8fb0001c */ lw $s0,0x1c($sp)
|
|
/* f0a7d40: 8fb10020 */ lw $s1,0x20($sp)
|
|
/* f0a7d44: 8fb20024 */ lw $s2,0x24($sp)
|
|
/* f0a7d48: 8fb30028 */ lw $s3,0x28($sp)
|
|
/* f0a7d4c: 8fb4002c */ lw $s4,0x2c($sp)
|
|
/* f0a7d50: 8fb50030 */ lw $s5,0x30($sp)
|
|
/* f0a7d54: 03e00008 */ jr $ra
|
|
/* f0a7d58: 27bd0150 */ addiu $sp,$sp,0x150
|
|
);
|
|
#elif VERSION >= VERSION_NTSC_1_0
|
|
GLOBAL_ASM(
|
|
glabel bgunRender
|
|
.late_rodata
|
|
glabel var7f1aca8c
|
|
.word 0x3faaaaab
|
|
glabel var7f1aca90
|
|
.word 0x3f3ebebf
|
|
.text
|
|
/* f0a7138: 27bdfeb0 */ addiu $sp,$sp,-336
|
|
/* f0a713c: afbf0034 */ sw $ra,0x34($sp)
|
|
/* f0a7140: afb50030 */ sw $s5,0x30($sp)
|
|
/* f0a7144: afb4002c */ sw $s4,0x2c($sp)
|
|
/* f0a7148: afb30028 */ sw $s3,0x28($sp)
|
|
/* f0a714c: afb20024 */ sw $s2,0x24($sp)
|
|
/* f0a7150: afb10020 */ sw $s1,0x20($sp)
|
|
/* f0a7154: afb0001c */ sw $s0,0x1c($sp)
|
|
/* f0a7158: afa40150 */ sw $a0,0x150($sp)
|
|
/* f0a715c: 8c8f0000 */ lw $t7,0x0($a0)
|
|
/* f0a7160: 3c198007 */ lui $t9,%hi(var8007029c)
|
|
/* f0a7164: 3c11800a */ lui $s1,%hi(g_Vars)
|
|
/* f0a7168: 2739029c */ addiu $t9,$t9,%lo(var8007029c)
|
|
/* f0a716c: 26319fc0 */ addiu $s1,$s1,%lo(g_Vars)
|
|
/* f0a7170: 272a003c */ addiu $t2,$t9,0x3c
|
|
/* f0a7174: 27b8010c */ addiu $t8,$sp,0x10c
|
|
/* f0a7178: afaf014c */ sw $t7,0x14c($sp)
|
|
.L0f0a717c:
|
|
/* f0a717c: 8f210000 */ lw $at,0x0($t9)
|
|
/* f0a7180: 2739000c */ addiu $t9,$t9,0xc
|
|
/* f0a7184: 2718000c */ addiu $t8,$t8,0xc
|
|
/* f0a7188: af01fff4 */ sw $at,-0xc($t8)
|
|
/* f0a718c: 8f21fff8 */ lw $at,-0x8($t9)
|
|
/* f0a7190: af01fff8 */ sw $at,-0x8($t8)
|
|
/* f0a7194: 8f21fffc */ lw $at,-0x4($t9)
|
|
/* f0a7198: 172afff8 */ bne $t9,$t2,.L0f0a717c
|
|
/* f0a719c: af01fffc */ sw $at,-0x4($t8)
|
|
/* f0a71a0: 8f210000 */ lw $at,0x0($t9)
|
|
/* f0a71a4: af010000 */ sw $at,0x0($t8)
|
|
/* f0a71a8: 8e330284 */ lw $s3,0x284($s1)
|
|
/* f0a71ac: 24010001 */ addiu $at,$zero,0x1
|
|
/* f0a71b0: 966b0010 */ lhu $t3,0x10($s3)
|
|
/* f0a71b4: 1561000d */ bne $t3,$at,.L0f0a71ec
|
|
/* f0a71b8: 00001025 */ or $v0,$zero,$zero
|
|
/* f0a71bc: 24040f48 */ addiu $a0,$zero,0xf48
|
|
/* f0a71c0: 8e2c0284 */ lw $t4,0x284($s1)
|
|
.L0f0a71c4:
|
|
/* f0a71c4: 01821821 */ addu $v1,$t4,$v0
|
|
/* f0a71c8: 8c6d0854 */ lw $t5,0x854($v1)
|
|
/* f0a71cc: 244207a4 */ addiu $v0,$v0,0x7a4
|
|
/* f0a71d0: 11a00002 */ beqz $t5,.L0f0a71dc
|
|
/* f0a71d4: 00000000 */ nop
|
|
/* f0a71d8: ac600850 */ sw $zero,0x850($v1)
|
|
.L0f0a71dc:
|
|
/* f0a71dc: 5444fff9 */ bnel $v0,$a0,.L0f0a71c4
|
|
/* f0a71e0: 8e2c0284 */ lw $t4,0x284($s1)
|
|
/* f0a71e4: 100002d5 */ b .L0f0a7d3c
|
|
/* f0a71e8: 8fbf0034 */ lw $ra,0x34($sp)
|
|
.L0f0a71ec:
|
|
/* f0a71ec: 0fc5d9ad */ jal mblurRender
|
|
/* f0a71f0: 8fa4014c */ lw $a0,0x14c($sp)
|
|
/* f0a71f4: afa2014c */ sw $v0,0x14c($sp)
|
|
/* f0a71f8: 0c002ca0 */ jal vi0000b280
|
|
/* f0a71fc: 00402025 */ or $a0,$v0,$zero
|
|
/* f0a7200: afa2014c */ sw $v0,0x14c($sp)
|
|
/* f0a7204: 0c002c74 */ jal vi0000b1d0
|
|
/* f0a7208: 00402025 */ or $a0,$v0,$zero
|
|
/* f0a720c: 244e0008 */ addiu $t6,$v0,0x8
|
|
/* f0a7210: afae014c */ sw $t6,0x14c($sp)
|
|
/* f0a7214: 0c002f40 */ jal viGetViewLeft
|
|
/* f0a7218: 0040a825 */ or $s5,$v0,$zero
|
|
/* f0a721c: 00028400 */ sll $s0,$v0,0x10
|
|
/* f0a7220: 00107c03 */ sra $t7,$s0,0x10
|
|
/* f0a7224: 0c002f44 */ jal viGetViewTop
|
|
/* f0a7228: 01e08025 */ or $s0,$t7,$zero
|
|
/* f0a722c: 44822000 */ mtc1 $v0,$f4
|
|
/* f0a7230: 44908000 */ mtc1 $s0,$f16
|
|
/* f0a7234: 3c014080 */ lui $at,0x4080
|
|
/* f0a7238: 468021a0 */ cvt.s.w $f6,$f4
|
|
/* f0a723c: 44810000 */ mtc1 $at,$f0
|
|
/* f0a7240: 3c01ed00 */ lui $at,0xed00
|
|
/* f0a7244: 468084a0 */ cvt.s.w $f18,$f16
|
|
/* f0a7248: 46003202 */ mul.s $f8,$f6,$f0
|
|
/* f0a724c: 00000000 */ nop
|
|
/* f0a7250: 46009102 */ mul.s $f4,$f18,$f0
|
|
/* f0a7254: 4600428d */ trunc.w.s $f10,$f8
|
|
/* f0a7258: 4600218d */ trunc.w.s $f6,$f4
|
|
/* f0a725c: 44085000 */ mfc1 $t0,$f10
|
|
/* f0a7260: 440b3000 */ mfc1 $t3,$f6
|
|
/* f0a7264: 310a0fff */ andi $t2,$t0,0xfff
|
|
/* f0a7268: 0141c825 */ or $t9,$t2,$at
|
|
/* f0a726c: 316c0fff */ andi $t4,$t3,0xfff
|
|
/* f0a7270: 000c6b00 */ sll $t5,$t4,0xc
|
|
/* f0a7274: 032d7025 */ or $t6,$t9,$t5
|
|
/* f0a7278: 0c002f22 */ jal viGetViewWidth
|
|
/* f0a727c: aeae0000 */ sw $t6,0x0($s5)
|
|
/* f0a7280: 00029400 */ sll $s2,$v0,0x10
|
|
/* f0a7284: 00127c03 */ sra $t7,$s2,0x10
|
|
/* f0a7288: 0c002f40 */ jal viGetViewLeft
|
|
/* f0a728c: 01e09025 */ or $s2,$t7,$zero
|
|
/* f0a7290: 0002a400 */ sll $s4,$v0,0x10
|
|
/* f0a7294: 00144c03 */ sra $t1,$s4,0x10
|
|
/* f0a7298: 0c002f44 */ jal viGetViewTop
|
|
/* f0a729c: 0120a025 */ or $s4,$t1,$zero
|
|
/* f0a72a0: 00028400 */ sll $s0,$v0,0x10
|
|
/* f0a72a4: 00104403 */ sra $t0,$s0,0x10
|
|
/* f0a72a8: 0c002f26 */ jal viGetViewHeight
|
|
/* f0a72ac: 01008025 */ or $s0,$t0,$zero
|
|
/* f0a72b0: 00505021 */ addu $t2,$v0,$s0
|
|
/* f0a72b4: 448a4000 */ mtc1 $t2,$f8
|
|
/* f0a72b8: 0292c821 */ addu $t9,$s4,$s2
|
|
/* f0a72bc: 44992000 */ mtc1 $t9,$f4
|
|
/* f0a72c0: 468042a0 */ cvt.s.w $f10,$f8
|
|
/* f0a72c4: 3c014080 */ lui $at,0x4080
|
|
/* f0a72c8: 44810000 */ mtc1 $at,$f0
|
|
/* f0a72cc: 3c053fc0 */ lui $a1,0x3fc0
|
|
/* f0a72d0: 3c06447a */ lui $a2,0x447a
|
|
/* f0a72d4: 468021a0 */ cvt.s.w $f6,$f4
|
|
/* f0a72d8: 46005402 */ mul.s $f16,$f10,$f0
|
|
/* f0a72dc: 00000000 */ nop
|
|
/* f0a72e0: 46003202 */ mul.s $f8,$f6,$f0
|
|
/* f0a72e4: 4600848d */ trunc.w.s $f18,$f16
|
|
/* f0a72e8: 4600428d */ trunc.w.s $f10,$f8
|
|
/* f0a72ec: 440b9000 */ mfc1 $t3,$f18
|
|
/* f0a72f0: 440e5000 */ mfc1 $t6,$f10
|
|
/* f0a72f4: 316c0fff */ andi $t4,$t3,0xfff
|
|
/* f0a72f8: 31cf0fff */ andi $t7,$t6,0xfff
|
|
/* f0a72fc: 000f4b00 */ sll $t1,$t7,0xc
|
|
/* f0a7300: 01894025 */ or $t0,$t4,$t1
|
|
/* f0a7304: aea80004 */ sw $t0,0x4($s5)
|
|
/* f0a7308: 0c002b29 */ jal vi0000aca4
|
|
/* f0a730c: 8fa4014c */ lw $a0,0x14c($sp)
|
|
/* f0a7310: 8e2a0284 */ lw $t2,0x284($s1)
|
|
/* f0a7314: afa2014c */ sw $v0,0x14c($sp)
|
|
/* f0a7318: 91581bfc */ lbu $t8,0x1bfc($t2)
|
|
/* f0a731c: 53000016 */ beqzl $t8,.L0f0a7378
|
|
/* f0a7320: 8e2b006c */ lw $t3,0x6c($s1)
|
|
/* f0a7324: 0fc54bc7 */ jal optionsGetScreenRatio
|
|
/* f0a7328: 00000000 */ nop
|
|
/* f0a732c: 24010001 */ addiu $at,$zero,0x1
|
|
/* f0a7330: 14410008 */ bne $v0,$at,.L0f0a7354
|
|
/* f0a7334: 00000000 */ nop
|
|
/* f0a7338: 0fc2f4d6 */ jal player0f0bd358
|
|
/* f0a733c: 00000000 */ nop
|
|
/* f0a7340: 3c017f1b */ lui $at,%hi(var7f1aca8c)
|
|
/* f0a7344: c430ca8c */ lwc1 $f16,%lo(var7f1aca8c)($at)
|
|
/* f0a7348: 46100082 */ mul.s $f2,$f0,$f16
|
|
/* f0a734c: 10000005 */ b .L0f0a7364
|
|
/* f0a7350: 44061000 */ mfc1 $a2,$f2
|
|
.L0f0a7354:
|
|
/* f0a7354: 0fc2f4d6 */ jal player0f0bd358
|
|
/* f0a7358: 00000000 */ nop
|
|
/* f0a735c: 46000086 */ mov.s $f2,$f0
|
|
/* f0a7360: 44061000 */ mfc1 $a2,$f2
|
|
.L0f0a7364:
|
|
/* f0a7364: 8fa4014c */ lw $a0,0x14c($sp)
|
|
/* f0a7368: 0c002c3a */ jal vi0000b0e8
|
|
/* f0a736c: 3c054270 */ lui $a1,0x4270
|
|
/* f0a7370: afa2014c */ sw $v0,0x14c($sp)
|
|
/* f0a7374: 8e2b006c */ lw $t3,0x6c($s1)
|
|
.L0f0a7378:
|
|
/* f0a7378: 24010001 */ addiu $at,$zero,0x1
|
|
/* f0a737c: 51600004 */ beqzl $t3,.L0f0a7390
|
|
/* f0a7380: 00002825 */ or $a1,$zero,$zero
|
|
/* f0a7384: 10000002 */ b .L0f0a7390
|
|
/* f0a7388: 24050001 */ addiu $a1,$zero,0x1
|
|
/* f0a738c: 00002825 */ or $a1,$zero,$zero
|
|
.L0f0a7390:
|
|
/* f0a7390: 8e390068 */ lw $t9,0x68($s1)
|
|
/* f0a7394: 53200004 */ beqzl $t9,.L0f0a73a8
|
|
/* f0a7398: 00002025 */ or $a0,$zero,$zero
|
|
/* f0a739c: 10000002 */ b .L0f0a73a8
|
|
/* f0a73a0: 24040001 */ addiu $a0,$zero,0x1
|
|
/* f0a73a4: 00002025 */ or $a0,$zero,$zero
|
|
.L0f0a73a8:
|
|
/* f0a73a8: 8e2d0064 */ lw $t5,0x64($s1)
|
|
/* f0a73ac: 51a00004 */ beqzl $t5,.L0f0a73c0
|
|
/* f0a73b0: 00001025 */ or $v0,$zero,$zero
|
|
/* f0a73b4: 10000002 */ b .L0f0a73c0
|
|
/* f0a73b8: 24020001 */ addiu $v0,$zero,0x1
|
|
/* f0a73bc: 00001025 */ or $v0,$zero,$zero
|
|
.L0f0a73c0:
|
|
/* f0a73c0: 8e2e0070 */ lw $t6,0x70($s1)
|
|
/* f0a73c4: 51c00004 */ beqzl $t6,.L0f0a73d8
|
|
/* f0a73c8: 00001825 */ or $v1,$zero,$zero
|
|
/* f0a73cc: 10000002 */ b .L0f0a73d8
|
|
/* f0a73d0: 24030001 */ addiu $v1,$zero,0x1
|
|
/* f0a73d4: 00001825 */ or $v1,$zero,$zero
|
|
.L0f0a73d8:
|
|
/* f0a73d8: 00627821 */ addu $t7,$v1,$v0
|
|
/* f0a73dc: 01e46021 */ addu $t4,$t7,$a0
|
|
/* f0a73e0: 01854821 */ addu $t1,$t4,$a1
|
|
/* f0a73e4: 15210008 */ bne $t1,$at,.L0f0a7408
|
|
/* f0a73e8: 3c088009 */ lui $t0,%hi(g_Is4Mb)
|
|
/* f0a73ec: 91080af0 */ lbu $t0,%lo(g_Is4Mb)($t0)
|
|
/* f0a73f0: 24010001 */ addiu $at,$zero,0x1
|
|
/* f0a73f4: 51010005 */ beql $t0,$at,.L0f0a740c
|
|
/* f0a73f8: 0000a025 */ or $s4,$zero,$zero
|
|
/* f0a73fc: 0fc2be93 */ jal lasersightRenderBeam
|
|
/* f0a7400: 8fa4014c */ lw $a0,0x14c($sp)
|
|
/* f0a7404: afa2014c */ sw $v0,0x14c($sp)
|
|
.L0f0a7408:
|
|
/* f0a7408: 0000a025 */ or $s4,$zero,$zero
|
|
.L0f0a740c:
|
|
/* f0a740c: 26700638 */ addiu $s0,$s3,0x638
|
|
/* f0a7410: 8fb500e4 */ lw $s5,0xe4($sp)
|
|
/* f0a7414: 24120019 */ addiu $s2,$zero,0x19
|
|
.L0f0a7418:
|
|
/* f0a7418: 0fc2867c */ jal bgunGetWeaponNum2
|
|
/* f0a741c: 02802025 */ or $a0,$s4,$zero
|
|
/* f0a7420: afa200ec */ sw $v0,0xec($sp)
|
|
/* f0a7424: 820a0007 */ lb $t2,0x7($s0)
|
|
/* f0a7428: 8fa4014c */ lw $a0,0x14c($sp)
|
|
/* f0a742c: 260501dc */ addiu $a1,$s0,0x1dc
|
|
/* f0a7430: 114001f2 */ beqz $t2,.L0f0a7bfc
|
|
/* f0a7434: 00003025 */ or $a2,$zero,$zero
|
|
/* f0a7438: 26180384 */ addiu $t8,$s0,0x384
|
|
/* f0a743c: afb8003c */ sw $t8,0x3c($sp)
|
|
/* f0a7440: 0fc2b2e4 */ jal beamRender
|
|
/* f0a7444: 00003825 */ or $a3,$zero,$zero
|
|
/* f0a7448: afa2014c */ sw $v0,0x14c($sp)
|
|
/* f0a744c: 92040000 */ lbu $a0,0x0($s0)
|
|
/* f0a7450: 0fc2c5f0 */ jal weaponHasFlag
|
|
/* f0a7454: 34058000 */ dli $a1,0x8000
|
|
/* f0a7458: 10400030 */ beqz $v0,.L0f0a751c
|
|
/* f0a745c: 8fab014c */ lw $t3,0x14c($sp)
|
|
/* f0a7460: 25790008 */ addiu $t9,$t3,0x8
|
|
/* f0a7464: afb9014c */ sw $t9,0x14c($sp)
|
|
/* f0a7468: 3c0dbc00 */ lui $t5,0xbc00
|
|
/* f0a746c: 3c0e8000 */ lui $t6,0x8000
|
|
/* f0a7470: 35ce0040 */ ori $t6,$t6,0x40
|
|
/* f0a7474: 35ad0002 */ ori $t5,$t5,0x2
|
|
/* f0a7478: ad6d0000 */ sw $t5,0x0($t3)
|
|
/* f0a747c: ad6e0004 */ sw $t6,0x4($t3)
|
|
/* f0a7480: 8faf014c */ lw $t7,0x14c($sp)
|
|
/* f0a7484: 3c090386 */ lui $t1,0x386
|
|
/* f0a7488: 3c088007 */ lui $t0,%hi(var80070090+0x08)
|
|
/* f0a748c: 25ec0008 */ addiu $t4,$t7,0x8
|
|
/* f0a7490: afac014c */ sw $t4,0x14c($sp)
|
|
/* f0a7494: 25080098 */ addiu $t0,$t0,%lo(var80070090+0x08)
|
|
/* f0a7498: 35290010 */ ori $t1,$t1,0x10
|
|
/* f0a749c: ade90000 */ sw $t1,0x0($t7)
|
|
/* f0a74a0: ade80004 */ sw $t0,0x4($t7)
|
|
/* f0a74a4: 8faa014c */ lw $t2,0x14c($sp)
|
|
/* f0a74a8: 3c0b0388 */ lui $t3,0x388
|
|
/* f0a74ac: 3c198007 */ lui $t9,%hi(var80070090)
|
|
/* f0a74b0: 25580008 */ addiu $t8,$t2,0x8
|
|
/* f0a74b4: afb8014c */ sw $t8,0x14c($sp)
|
|
/* f0a74b8: 27390090 */ addiu $t9,$t9,%lo(var80070090)
|
|
/* f0a74bc: 356b0010 */ ori $t3,$t3,0x10
|
|
/* f0a74c0: ad4b0000 */ sw $t3,0x0($t2)
|
|
/* f0a74c4: ad590004 */ sw $t9,0x4($t2)
|
|
/* f0a74c8: 8fad014c */ lw $t5,0x14c($sp)
|
|
/* f0a74cc: 3c0f0384 */ lui $t7,0x384
|
|
/* f0a74d0: 35ef0010 */ ori $t7,$t7,0x10
|
|
/* f0a74d4: 25ae0008 */ addiu $t6,$t5,0x8
|
|
/* f0a74d8: afae014c */ sw $t6,0x14c($sp)
|
|
/* f0a74dc: adaf0000 */ sw $t7,0x0($t5)
|
|
/* f0a74e0: 0fc2d5ea */ jal camGetLookAt
|
|
/* f0a74e4: afad00d4 */ sw $t5,0xd4($sp)
|
|
/* f0a74e8: 8fa500d4 */ lw $a1,0xd4($sp)
|
|
/* f0a74ec: 3c080382 */ lui $t0,0x382
|
|
/* f0a74f0: 35080010 */ ori $t0,$t0,0x10
|
|
/* f0a74f4: aca20004 */ sw $v0,0x4($a1)
|
|
/* f0a74f8: 8fac014c */ lw $t4,0x14c($sp)
|
|
/* f0a74fc: 25890008 */ addiu $t1,$t4,0x8
|
|
/* f0a7500: afa9014c */ sw $t1,0x14c($sp)
|
|
/* f0a7504: ad880000 */ sw $t0,0x0($t4)
|
|
/* f0a7508: 0fc2d5ea */ jal camGetLookAt
|
|
/* f0a750c: afac00d0 */ sw $t4,0xd0($sp)
|
|
/* f0a7510: 8fa300d0 */ lw $v1,0xd0($sp)
|
|
/* f0a7514: 244a0010 */ addiu $t2,$v0,0x10
|
|
/* f0a7518: ac6a0004 */ sw $t2,0x4($v1)
|
|
.L0f0a751c:
|
|
/* f0a751c: 8fb8014c */ lw $t8,0x14c($sp)
|
|
/* f0a7520: 3c19bc00 */ lui $t9,0xbc00
|
|
/* f0a7524: 3739000e */ ori $t9,$t9,0xe
|
|
/* f0a7528: 270b0008 */ addiu $t3,$t8,0x8
|
|
/* f0a752c: afab014c */ sw $t3,0x14c($sp)
|
|
/* f0a7530: 3c014396 */ lui $at,0x4396
|
|
/* f0a7534: 44817000 */ mtc1 $at,$f14
|
|
/* f0a7538: 44806000 */ mtc1 $zero,$f12
|
|
/* f0a753c: af190000 */ sw $t9,0x0($t8)
|
|
/* f0a7540: 0c005b73 */ jal mtx00016dcc
|
|
/* f0a7544: afb800cc */ sw $t8,0xcc($sp)
|
|
/* f0a7548: 8fa300cc */ lw $v1,0xcc($sp)
|
|
/* f0a754c: 24050010 */ addiu $a1,$zero,0x10
|
|
/* f0a7550: ac620004 */ sw $v0,0x4($v1)
|
|
/* f0a7554: 0c006a47 */ jal modelGetPart
|
|
/* f0a7558: 8e04038c */ lw $a0,0x38c($s0)
|
|
/* f0a755c: 10400014 */ beqz $v0,.L0f0a75b0
|
|
/* f0a7560: afa200e8 */ sw $v0,0xe8($sp)
|
|
/* f0a7564: 8e04038c */ lw $a0,0x38c($s0)
|
|
/* f0a7568: 0c006a47 */ jal modelGetPart
|
|
/* f0a756c: 24050011 */ addiu $a1,$zero,0x11
|
|
/* f0a7570: 8fa4003c */ lw $a0,0x3c($sp)
|
|
/* f0a7574: 0c006a87 */ jal modelGetNodeRwData
|
|
/* f0a7578: 00402825 */ or $a1,$v0,$zero
|
|
/* f0a757c: 10400003 */ beqz $v0,.L0f0a758c
|
|
/* f0a7580: 3c06800a */ lui $a2,%hi(var8009cf88)
|
|
/* f0a7584: 240d0001 */ addiu $t5,$zero,0x1
|
|
/* f0a7588: ac4d0000 */ sw $t5,0x0($v0)
|
|
.L0f0a758c:
|
|
/* f0a758c: 240e0001 */ addiu $t6,$zero,0x1
|
|
/* f0a7590: afae0014 */ sw $t6,0x14($sp)
|
|
/* f0a7594: 8fa4003c */ lw $a0,0x3c($sp)
|
|
/* f0a7598: 8fa500e8 */ lw $a1,0xe8($sp)
|
|
/* f0a759c: 24c6cf88 */ addiu $a2,$a2,%lo(var8009cf88)
|
|
/* f0a75a0: 8fa7014c */ lw $a3,0x14c($sp)
|
|
/* f0a75a4: 0fc1fefe */ jal tvscreenRender
|
|
/* f0a75a8: afa00010 */ sw $zero,0x10($sp)
|
|
/* f0a75ac: afa2014c */ sw $v0,0x14c($sp)
|
|
.L0f0a75b0:
|
|
/* f0a75b0: 8faf014c */ lw $t7,0x14c($sp)
|
|
/* f0a75b4: 8e250284 */ lw $a1,0x284($s1)
|
|
/* f0a75b8: 240c0004 */ addiu $t4,$zero,0x4
|
|
/* f0a75bc: afac013c */ sw $t4,0x13c($sp)
|
|
/* f0a75c0: afaf0118 */ sw $t7,0x118($sp)
|
|
/* f0a75c4: 8ca300d8 */ lw $v1,0xd8($a1)
|
|
/* f0a75c8: 3c078007 */ lui $a3,%hi(g_InCutscene)
|
|
/* f0a75cc: 14600013 */ bnez $v1,.L0f0a761c
|
|
/* f0a75d0: 00000000 */ nop
|
|
/* f0a75d4: 8ce70764 */ lw $a3,%lo(g_InCutscene)($a3)
|
|
/* f0a75d8: 14e00010 */ bnez $a3,.L0f0a761c
|
|
/* f0a75dc: 00000000 */ nop
|
|
/* f0a75e0: 8ca20480 */ lw $v0,0x480($a1)
|
|
/* f0a75e4: 50400007 */ beqzl $v0,.L0f0a7604
|
|
/* f0a75e8: 8caa1c54 */ lw $t2,0x1c54($a1)
|
|
/* f0a75ec: 1040000b */ beqz $v0,.L0f0a761c
|
|
/* f0a75f0: 00000000 */ nop
|
|
/* f0a75f4: 80490037 */ lb $t1,0x37($v0)
|
|
/* f0a75f8: 15200008 */ bnez $t1,.L0f0a761c
|
|
/* f0a75fc: 00000000 */ nop
|
|
/* f0a7600: 8caa1c54 */ lw $t2,0x1c54($a1)
|
|
.L0f0a7604:
|
|
/* f0a7604: 8ca800c4 */ lw $t0,0xc4($a1)
|
|
/* f0a7608: 0140c027 */ nor $t8,$t2,$zero
|
|
/* f0a760c: 01185824 */ and $t3,$t0,$t8
|
|
/* f0a7610: 31790001 */ andi $t9,$t3,0x1
|
|
/* f0a7614: 57200016 */ bnezl $t9,.L0f0a7670
|
|
/* f0a7618: 92681615 */ lbu $t0,0x1615($s3)
|
|
.L0f0a761c:
|
|
/* f0a761c: 14600078 */ bnez $v1,.L0f0a7800
|
|
/* f0a7620: 3c078007 */ lui $a3,%hi(g_InCutscene)
|
|
/* f0a7624: 8ce70764 */ lw $a3,%lo(g_InCutscene)($a3)
|
|
/* f0a7628: 54e00076 */ bnezl $a3,.L0f0a7804
|
|
/* f0a762c: 926d1614 */ lbu $t5,0x1614($s3)
|
|
/* f0a7630: 8ca20480 */ lw $v0,0x480($a1)
|
|
/* f0a7634: 50400007 */ beqzl $v0,.L0f0a7654
|
|
/* f0a7638: 8caf1c54 */ lw $t7,0x1c54($a1)
|
|
/* f0a763c: 50400071 */ beqzl $v0,.L0f0a7804
|
|
/* f0a7640: 926d1614 */ lbu $t5,0x1614($s3)
|
|
/* f0a7644: 804d0037 */ lb $t5,0x37($v0)
|
|
/* f0a7648: 55a0006e */ bnezl $t5,.L0f0a7804
|
|
/* f0a764c: 926d1614 */ lbu $t5,0x1614($s3)
|
|
/* f0a7650: 8caf1c54 */ lw $t7,0x1c54($a1)
|
|
.L0f0a7654:
|
|
/* f0a7654: 8cae00c4 */ lw $t6,0xc4($a1)
|
|
/* f0a7658: 01e06027 */ nor $t4,$t7,$zero
|
|
/* f0a765c: 01cc4824 */ and $t1,$t6,$t4
|
|
/* f0a7660: 312a0008 */ andi $t2,$t1,0x8
|
|
/* f0a7664: 51400067 */ beqzl $t2,.L0f0a7804
|
|
/* f0a7668: 926d1614 */ lbu $t5,0x1614($s3)
|
|
/* f0a766c: 92681615 */ lbu $t0,0x1615($s3)
|
|
.L0f0a7670:
|
|
/* f0a7670: 92781614 */ lbu $t8,0x1614($s3)
|
|
/* f0a7674: 26641614 */ addiu $a0,$s3,0x1614
|
|
/* f0a7678: 0118082a */ slt $at,$t0,$t8
|
|
/* f0a767c: 50200009 */ beqzl $at,.L0f0a76a4
|
|
/* f0a7680: 90820002 */ lbu $v0,0x2($a0)
|
|
/* f0a7684: 90830000 */ lbu $v1,0x0($a0)
|
|
/* f0a7688: 908b0002 */ lbu $t3,0x2($a0)
|
|
/* f0a768c: 0163082a */ slt $at,$t3,$v1
|
|
/* f0a7690: 50200004 */ beqzl $at,.L0f0a76a4
|
|
/* f0a7694: 90820002 */ lbu $v0,0x2($a0)
|
|
/* f0a7698: 1000000a */ b .L0f0a76c4
|
|
/* f0a769c: 00601025 */ or $v0,$v1,$zero
|
|
/* f0a76a0: 90820002 */ lbu $v0,0x2($a0)
|
|
.L0f0a76a4:
|
|
/* f0a76a4: 90860001 */ lbu $a2,0x1($a0)
|
|
/* f0a76a8: 00401825 */ or $v1,$v0,$zero
|
|
/* f0a76ac: 0046082a */ slt $at,$v0,$a2
|
|
/* f0a76b0: 10200003 */ beqz $at,.L0f0a76c0
|
|
/* f0a76b4: 00000000 */ nop
|
|
/* f0a76b8: 10000001 */ b .L0f0a76c0
|
|
/* f0a76bc: 00c01825 */ or $v1,$a2,$zero
|
|
.L0f0a76c0:
|
|
/* f0a76c0: 00601025 */ or $v0,$v1,$zero
|
|
.L0f0a76c4:
|
|
/* f0a76c4: 90890003 */ lbu $t1,0x3($a0)
|
|
/* f0a76c8: 0002ce00 */ sll $t9,$v0,0x18
|
|
/* f0a76cc: 00026c00 */ sll $t5,$v0,0x10
|
|
/* f0a76d0: 032d7825 */ or $t7,$t9,$t5
|
|
/* f0a76d4: 00027200 */ sll $t6,$v0,0x8
|
|
/* f0a76d8: 01ee6025 */ or $t4,$t7,$t6
|
|
/* f0a76dc: 012c5021 */ addu $t2,$t1,$t4
|
|
/* f0a76e0: afaa0140 */ sw $t2,0x140($sp)
|
|
/* f0a76e4: 8ca300d8 */ lw $v1,0xd8($a1)
|
|
/* f0a76e8: 14600021 */ bnez $v1,.L0f0a7770
|
|
/* f0a76ec: 00000000 */ nop
|
|
/* f0a76f0: 14e0001f */ bnez $a3,.L0f0a7770
|
|
/* f0a76f4: 00000000 */ nop
|
|
/* f0a76f8: 8ca20480 */ lw $v0,0x480($a1)
|
|
/* f0a76fc: 50400007 */ beqzl $v0,.L0f0a771c
|
|
/* f0a7700: 8cab1c54 */ lw $t3,0x1c54($a1)
|
|
/* f0a7704: 1040001a */ beqz $v0,.L0f0a7770
|
|
/* f0a7708: 00000000 */ nop
|
|
/* f0a770c: 80480037 */ lb $t0,0x37($v0)
|
|
/* f0a7710: 15000017 */ bnez $t0,.L0f0a7770
|
|
/* f0a7714: 00000000 */ nop
|
|
/* f0a7718: 8cab1c54 */ lw $t3,0x1c54($a1)
|
|
.L0f0a771c:
|
|
/* f0a771c: 8cb800c4 */ lw $t8,0xc4($a1)
|
|
/* f0a7720: 3c02800a */ lui $v0,%hi(var8009caec+0x3)
|
|
/* f0a7724: 0160c827 */ nor $t9,$t3,$zero
|
|
/* f0a7728: 03196824 */ and $t5,$t8,$t9
|
|
/* f0a772c: 31af0001 */ andi $t7,$t5,0x1
|
|
/* f0a7730: 11e0000f */ beqz $t7,.L0f0a7770
|
|
/* f0a7734: 00000000 */ nop
|
|
/* f0a7738: 9042caef */ lbu $v0,%lo(var8009caec+0x3)($v0)
|
|
/* f0a773c: 3c06800a */ lui $a2,%hi(var8009caf0)
|
|
/* f0a7740: 90c6caf0 */ lbu $a2,%lo(var8009caf0)($a2)
|
|
/* f0a7744: 00027600 */ sll $t6,$v0,0x18
|
|
/* f0a7748: 00024c00 */ sll $t1,$v0,0x10
|
|
/* f0a774c: 01c96025 */ or $t4,$t6,$t1
|
|
/* f0a7750: 00025200 */ sll $t2,$v0,0x8
|
|
/* f0a7754: 018a4025 */ or $t0,$t4,$t2
|
|
/* f0a7758: afa200b0 */ sw $v0,0xb0($sp)
|
|
/* f0a775c: afa200b4 */ sw $v0,0xb4($sp)
|
|
/* f0a7760: afa200b8 */ sw $v0,0xb8($sp)
|
|
/* f0a7764: 00c8a821 */ addu $s5,$a2,$t0
|
|
/* f0a7768: 1000001f */ b .L0f0a77e8
|
|
/* f0a776c: afa600bc */ sw $a2,0xbc($sp)
|
|
.L0f0a7770:
|
|
/* f0a7770: 5460001e */ bnezl $v1,.L0f0a77ec
|
|
/* f0a7774: 8fb900ec */ lw $t9,0xec($sp)
|
|
/* f0a7778: 54e0001c */ bnezl $a3,.L0f0a77ec
|
|
/* f0a777c: 8fb900ec */ lw $t9,0xec($sp)
|
|
/* f0a7780: 8ca20480 */ lw $v0,0x480($a1)
|
|
/* f0a7784: 50400007 */ beqzl $v0,.L0f0a77a4
|
|
/* f0a7788: 8cb91c54 */ lw $t9,0x1c54($a1)
|
|
/* f0a778c: 50400017 */ beqzl $v0,.L0f0a77ec
|
|
/* f0a7790: 8fb900ec */ lw $t9,0xec($sp)
|
|
/* f0a7794: 804b0037 */ lb $t3,0x37($v0)
|
|
/* f0a7798: 55600014 */ bnezl $t3,.L0f0a77ec
|
|
/* f0a779c: 8fb900ec */ lw $t9,0xec($sp)
|
|
/* f0a77a0: 8cb91c54 */ lw $t9,0x1c54($a1)
|
|
.L0f0a77a4:
|
|
/* f0a77a4: 8cb800c4 */ lw $t8,0xc4($a1)
|
|
/* f0a77a8: 240200ff */ addiu $v0,$zero,0xff
|
|
/* f0a77ac: 03206827 */ nor $t5,$t9,$zero
|
|
/* f0a77b0: 030d7824 */ and $t7,$t8,$t5
|
|
/* f0a77b4: 31ee0008 */ andi $t6,$t7,0x8
|
|
/* f0a77b8: 11c0000b */ beqz $t6,.L0f0a77e8
|
|
/* f0a77bc: 24050080 */ addiu $a1,$zero,0x80
|
|
/* f0a77c0: 00024e00 */ sll $t1,$v0,0x18
|
|
/* f0a77c4: 00006400 */ sll $t4,$zero,0x10
|
|
/* f0a77c8: 012c5025 */ or $t2,$t1,$t4
|
|
/* f0a77cc: 00004200 */ sll $t0,$zero,0x8
|
|
/* f0a77d0: 01485825 */ or $t3,$t2,$t0
|
|
/* f0a77d4: 00aba821 */ addu $s5,$a1,$t3
|
|
/* f0a77d8: afa200a0 */ sw $v0,0xa0($sp)
|
|
/* f0a77dc: afa000a4 */ sw $zero,0xa4($sp)
|
|
/* f0a77e0: afa000a8 */ sw $zero,0xa8($sp)
|
|
/* f0a77e4: afa500ac */ sw $a1,0xac($sp)
|
|
.L0f0a77e8:
|
|
/* f0a77e8: 8fb900ec */ lw $t9,0xec($sp)
|
|
.L0f0a77ec:
|
|
/* f0a77ec: 24010001 */ addiu $at,$zero,0x1
|
|
/* f0a77f0: 5721003d */ bnel $t9,$at,.L0f0a78e8
|
|
/* f0a77f4: 8e6f00bc */ lw $t7,0xbc($s3)
|
|
/* f0a77f8: 1000003a */ b .L0f0a78e4
|
|
/* f0a77fc: afb50140 */ sw $s5,0x140($sp)
|
|
.L0f0a7800:
|
|
/* f0a7800: 926d1614 */ lbu $t5,0x1614($s3)
|
|
.L0f0a7804:
|
|
/* f0a7804: 92781617 */ lbu $t8,0x1617($s3)
|
|
/* f0a7808: 92691615 */ lbu $t1,0x1615($s3)
|
|
/* f0a780c: 92681616 */ lbu $t0,0x1616($s3)
|
|
/* f0a7810: 000d7e00 */ sll $t7,$t5,0x18
|
|
/* f0a7814: 030f7025 */ or $t6,$t8,$t7
|
|
/* f0a7818: 00096400 */ sll $t4,$t1,0x10
|
|
/* f0a781c: 01cc5025 */ or $t2,$t6,$t4
|
|
/* f0a7820: 00085a00 */ sll $t3,$t0,0x8
|
|
/* f0a7824: 014bc825 */ or $t9,$t2,$t3
|
|
/* f0a7828: afb90140 */ sw $t9,0x140($sp)
|
|
/* f0a782c: 920d0000 */ lbu $t5,0x0($s0)
|
|
/* f0a7830: 24010006 */ addiu $at,$zero,0x6
|
|
/* f0a7834: 0320a825 */ or $s5,$t9,$zero
|
|
/* f0a7838: 15a1002a */ bne $t5,$at,.L0f0a78e4
|
|
/* f0a783c: 3c04ff00 */ lui $a0,0xff00
|
|
/* f0a7840: 3c014248 */ lui $at,0x4248
|
|
/* f0a7844: 44812000 */ mtc1 $at,$f4
|
|
/* f0a7848: c612023c */ lwc1 $f18,0x23c($s0)
|
|
/* f0a784c: 24060001 */ addiu $a2,$zero,0x1
|
|
/* f0a7850: 3c014f00 */ lui $at,0x4f00
|
|
/* f0a7854: 46049182 */ mul.s $f6,$f18,$f4
|
|
/* f0a7858: 3484007f */ ori $a0,$a0,0x7f
|
|
/* f0a785c: 4458f800 */ cfc1 $t8,$31
|
|
/* f0a7860: 44c6f800 */ ctc1 $a2,$31
|
|
/* f0a7864: 00000000 */ nop
|
|
/* f0a7868: 46003224 */ cvt.w.s $f8,$f6
|
|
/* f0a786c: 4446f800 */ cfc1 $a2,$31
|
|
/* f0a7870: 00000000 */ nop
|
|
/* f0a7874: 30c60078 */ andi $a2,$a2,0x78
|
|
/* f0a7878: 50c00013 */ beqzl $a2,.L0f0a78c8
|
|
/* f0a787c: 44064000 */ mfc1 $a2,$f8
|
|
/* f0a7880: 44814000 */ mtc1 $at,$f8
|
|
/* f0a7884: 24060001 */ addiu $a2,$zero,0x1
|
|
/* f0a7888: 46083201 */ sub.s $f8,$f6,$f8
|
|
/* f0a788c: 44c6f800 */ ctc1 $a2,$31
|
|
/* f0a7890: 00000000 */ nop
|
|
/* f0a7894: 46004224 */ cvt.w.s $f8,$f8
|
|
/* f0a7898: 4446f800 */ cfc1 $a2,$31
|
|
/* f0a789c: 00000000 */ nop
|
|
/* f0a78a0: 30c60078 */ andi $a2,$a2,0x78
|
|
/* f0a78a4: 14c00005 */ bnez $a2,.L0f0a78bc
|
|
/* f0a78a8: 00000000 */ nop
|
|
/* f0a78ac: 44064000 */ mfc1 $a2,$f8
|
|
/* f0a78b0: 3c018000 */ lui $at,0x8000
|
|
/* f0a78b4: 10000007 */ b .L0f0a78d4
|
|
/* f0a78b8: 00c13025 */ or $a2,$a2,$at
|
|
.L0f0a78bc:
|
|
/* f0a78bc: 10000005 */ b .L0f0a78d4
|
|
/* f0a78c0: 2406ffff */ addiu $a2,$zero,-1
|
|
/* f0a78c4: 44064000 */ mfc1 $a2,$f8
|
|
.L0f0a78c8:
|
|
/* f0a78c8: 00000000 */ nop
|
|
/* f0a78cc: 04c0fffb */ bltz $a2,.L0f0a78bc
|
|
/* f0a78d0: 00000000 */ nop
|
|
.L0f0a78d4:
|
|
/* f0a78d4: 44d8f800 */ ctc1 $t8,$31
|
|
/* f0a78d8: 0fc01a40 */ jal colourBlend
|
|
/* f0a78dc: 03202825 */ or $a1,$t9,$zero
|
|
/* f0a78e0: afa20140 */ sw $v0,0x140($sp)
|
|
.L0f0a78e4:
|
|
/* f0a78e4: 8e6f00bc */ lw $t7,0xbc($s3)
|
|
.L0f0a78e8:
|
|
/* f0a78e8: 0fc08af9 */ jal chrGetCloakAlpha
|
|
/* f0a78ec: 8de40004 */ lw $a0,0x4($t7)
|
|
/* f0a78f0: 284100ff */ slti $at,$v0,0xff
|
|
/* f0a78f4: 1020000f */ beqz $at,.L0f0a7934
|
|
/* f0a78f8: 240c0001 */ addiu $t4,$zero,0x1
|
|
/* f0a78fc: 44825000 */ mtc1 $v0,$f10
|
|
/* f0a7900: 3c017f1b */ lui $at,%hi(var7f1aca90)
|
|
/* f0a7904: c432ca90 */ lwc1 $f18,%lo(var7f1aca90)($at)
|
|
/* f0a7908: 46805420 */ cvt.s.w $f16,$f10
|
|
/* f0a790c: 8fa40140 */ lw $a0,0x140($sp)
|
|
/* f0a7910: 240e0005 */ addiu $t6,$zero,0x5
|
|
/* f0a7914: afae013c */ sw $t6,0x13c($sp)
|
|
/* f0a7918: afa40144 */ sw $a0,0x144($sp)
|
|
/* f0a791c: 46128102 */ mul.s $f4,$f16,$f18
|
|
/* f0a7920: 4600218d */ trunc.w.s $f6,$f4
|
|
/* f0a7924: 44033000 */ mfc1 $v1,$f6
|
|
/* f0a7928: 00000000 */ nop
|
|
/* f0a792c: 24750041 */ addiu $s5,$v1,0x41
|
|
/* f0a7930: afb50140 */ sw $s5,0x140($sp)
|
|
.L0f0a7934:
|
|
/* f0a7934: 0c0059d8 */ jal mtx00016760
|
|
/* f0a7938: afac0110 */ sw $t4,0x110($sp)
|
|
/* f0a793c: 8e020218 */ lw $v0,0x218($s0)
|
|
/* f0a7940: 50400017 */ beqzl $v0,.L0f0a79a0
|
|
/* f0a7944: 8fa400ec */ lw $a0,0xec($sp)
|
|
/* f0a7948: 8c460018 */ lw $a2,0x18($v0)
|
|
/* f0a794c: afa00094 */ sw $zero,0x94($sp)
|
|
/* f0a7950: 50c00013 */ beqzl $a2,.L0f0a79a0
|
|
/* f0a7954: 8fa400ec */ lw $a0,0xec($sp)
|
|
/* f0a7958: 8cc80008 */ lw $t0,0x8($a2)
|
|
/* f0a795c: 240a0001 */ addiu $t2,$zero,0x1
|
|
/* f0a7960: 27a4010c */ addiu $a0,$sp,0x10c
|
|
/* f0a7964: 1100000d */ beqz $t0,.L0f0a799c
|
|
/* f0a7968: 00c02825 */ or $a1,$a2,$zero
|
|
/* f0a796c: afaa0094 */ sw $t2,0x94($sp)
|
|
/* f0a7970: 0c0087bd */ jal modelRender
|
|
/* f0a7974: afa60098 */ sw $a2,0x98($sp)
|
|
/* f0a7978: 8fa60098 */ lw $a2,0x98($sp)
|
|
/* f0a797c: 8ccb0008 */ lw $t3,0x8($a2)
|
|
/* f0a7980: 8cc4000c */ lw $a0,0xc($a2)
|
|
/* f0a7984: 0fc30cfc */ jal mtxF2LBulk
|
|
/* f0a7988: 8565000e */ lh $a1,0xe($t3)
|
|
/* f0a798c: 8e0d021c */ lw $t5,0x21c($s0)
|
|
/* f0a7990: 51a00003 */ beqzl $t5,.L0f0a79a0
|
|
/* f0a7994: 8fa400ec */ lw $a0,0xec($sp)
|
|
/* f0a7998: ae000218 */ sw $zero,0x218($s0)
|
|
.L0f0a799c:
|
|
/* f0a799c: 8fa400ec */ lw $a0,0xec($sp)
|
|
.L0f0a79a0:
|
|
/* f0a79a0: 0fc2c5f0 */ jal weaponHasFlag
|
|
/* f0a79a4: 24050020 */ addiu $a1,$zero,0x20
|
|
/* f0a79a8: 1040000e */ beqz $v0,.L0f0a79e4
|
|
/* f0a79ac: 24010001 */ addiu $at,$zero,0x1
|
|
/* f0a79b0: 8fb80118 */ lw $t8,0x118($sp)
|
|
/* f0a79b4: 3c0fb600 */ lui $t7,0xb600
|
|
/* f0a79b8: 24093000 */ addiu $t1,$zero,0x3000
|
|
/* f0a79bc: 27190008 */ addiu $t9,$t8,0x8
|
|
/* f0a79c0: afb90118 */ sw $t9,0x118($sp)
|
|
/* f0a79c4: af090004 */ sw $t1,0x4($t8)
|
|
/* f0a79c8: 16800004 */ bnez $s4,.L0f0a79dc
|
|
/* f0a79cc: af0f0000 */ sw $t7,0x0($t8)
|
|
/* f0a79d0: 240e0003 */ addiu $t6,$zero,0x3
|
|
/* f0a79d4: 10000003 */ b .L0f0a79e4
|
|
/* f0a79d8: afae0148 */ sw $t6,0x148($sp)
|
|
.L0f0a79dc:
|
|
/* f0a79dc: 240c0002 */ addiu $t4,$zero,0x2
|
|
/* f0a79e0: afac0148 */ sw $t4,0x148($sp)
|
|
.L0f0a79e4:
|
|
/* f0a79e4: 8e28006c */ lw $t0,0x6c($s1)
|
|
/* f0a79e8: 00002825 */ or $a1,$zero,$zero
|
|
/* f0a79ec: 00002025 */ or $a0,$zero,$zero
|
|
/* f0a79f0: 11000003 */ beqz $t0,.L0f0a7a00
|
|
/* f0a79f4: 00001025 */ or $v0,$zero,$zero
|
|
/* f0a79f8: 10000001 */ b .L0f0a7a00
|
|
/* f0a79fc: 24050001 */ addiu $a1,$zero,0x1
|
|
.L0f0a7a00:
|
|
/* f0a7a00: 8e2a0068 */ lw $t2,0x68($s1)
|
|
/* f0a7a04: 00001825 */ or $v1,$zero,$zero
|
|
/* f0a7a08: 11400003 */ beqz $t2,.L0f0a7a18
|
|
/* f0a7a0c: 00000000 */ nop
|
|
/* f0a7a10: 10000001 */ b .L0f0a7a18
|
|
/* f0a7a14: 24040001 */ addiu $a0,$zero,0x1
|
|
.L0f0a7a18:
|
|
/* f0a7a18: 8e2b0064 */ lw $t3,0x64($s1)
|
|
/* f0a7a1c: 11600003 */ beqz $t3,.L0f0a7a2c
|
|
/* f0a7a20: 00000000 */ nop
|
|
/* f0a7a24: 10000001 */ b .L0f0a7a2c
|
|
/* f0a7a28: 24020001 */ addiu $v0,$zero,0x1
|
|
.L0f0a7a2c:
|
|
/* f0a7a2c: 8e2d0070 */ lw $t5,0x70($s1)
|
|
/* f0a7a30: 11a00003 */ beqz $t5,.L0f0a7a40
|
|
/* f0a7a34: 00000000 */ nop
|
|
/* f0a7a38: 10000001 */ b .L0f0a7a40
|
|
/* f0a7a3c: 24030001 */ addiu $v1,$zero,0x1
|
|
.L0f0a7a40:
|
|
/* f0a7a40: 0062c021 */ addu $t8,$v1,$v0
|
|
/* f0a7a44: 0304c821 */ addu $t9,$t8,$a0
|
|
/* f0a7a48: 03257821 */ addu $t7,$t9,$a1
|
|
/* f0a7a4c: 15e10036 */ bne $t7,$at,.L0f0a7b28
|
|
/* f0a7a50: 24050041 */ addiu $a1,$zero,0x41
|
|
/* f0a7a54: 0c006a47 */ jal modelGetPart
|
|
/* f0a7a58: 8e04038c */ lw $a0,0x38c($s0)
|
|
/* f0a7a5c: 50400033 */ beqzl $v0,.L0f0a7b2c
|
|
/* f0a7a60: 27a4010c */ addiu $a0,$sp,0x10c
|
|
/* f0a7a64: 8c440004 */ lw $a0,0x4($v0)
|
|
/* f0a7a68: 00002825 */ or $a1,$zero,$zero
|
|
/* f0a7a6c: 84890010 */ lh $t1,0x10($a0)
|
|
/* f0a7a70: 5920002e */ blezl $t1,.L0f0a7b2c
|
|
/* f0a7a74: 27a4010c */ addiu $a0,$sp,0x10c
|
|
/* f0a7a78: 8e2a0034 */ lw $t2,0x34($s1)
|
|
.L0f0a7a7c:
|
|
/* f0a7a7c: 8c8e000c */ lw $t6,0xc($a0)
|
|
/* f0a7a80: 00056080 */ sll $t4,$a1,0x2
|
|
/* f0a7a84: 01520019 */ multu $t2,$s2
|
|
/* f0a7a88: 01856023 */ subu $t4,$t4,$a1
|
|
/* f0a7a8c: 000c6080 */ sll $t4,$t4,0x2
|
|
/* f0a7a90: 01cc1021 */ addu $v0,$t6,$t4
|
|
/* f0a7a94: 8448000a */ lh $t0,0xa($v0)
|
|
/* f0a7a98: 0005c880 */ sll $t9,$a1,0x2
|
|
/* f0a7a9c: 0325c823 */ subu $t9,$t9,$a1
|
|
/* f0a7aa0: 0019c880 */ sll $t9,$t9,0x2
|
|
/* f0a7aa4: 24420002 */ addiu $v0,$v0,0x2
|
|
/* f0a7aa8: 00005812 */ mflo $t3
|
|
/* f0a7aac: 010b6823 */ subu $t5,$t0,$t3
|
|
/* f0a7ab0: a44d0008 */ sh $t5,0x8($v0)
|
|
/* f0a7ab4: 8c98000c */ lw $t8,0xc($a0)
|
|
/* f0a7ab8: 03197821 */ addu $t7,$t8,$t9
|
|
/* f0a7abc: 85e9000a */ lh $t1,0xa($t7)
|
|
/* f0a7ac0: 2921a000 */ slti $at,$t1,-24576
|
|
/* f0a7ac4: 50200014 */ beqzl $at,.L0f0a7b18
|
|
/* f0a7ac8: 84980010 */ lh $t8,0x10($a0)
|
|
/* f0a7acc: 848e0010 */ lh $t6,0x10($a0)
|
|
/* f0a7ad0: 00001825 */ or $v1,$zero,$zero
|
|
/* f0a7ad4: 59c00010 */ blezl $t6,.L0f0a7b18
|
|
/* f0a7ad8: 84980010 */ lh $t8,0x10($a0)
|
|
/* f0a7adc: 8c8c000c */ lw $t4,0xc($a0)
|
|
.L0f0a7ae0:
|
|
/* f0a7ae0: 00035080 */ sll $t2,$v1,0x2
|
|
/* f0a7ae4: 01435023 */ subu $t2,$t2,$v1
|
|
/* f0a7ae8: 000a5080 */ sll $t2,$t2,0x2
|
|
/* f0a7aec: 018a1021 */ addu $v0,$t4,$t2
|
|
/* f0a7af0: 8448000a */ lh $t0,0xa($v0)
|
|
/* f0a7af4: 24630001 */ addiu $v1,$v1,0x1
|
|
/* f0a7af8: 24420002 */ addiu $v0,$v0,0x2
|
|
/* f0a7afc: 250b2000 */ addiu $t3,$t0,0x2000
|
|
/* f0a7b00: a44b0008 */ sh $t3,0x8($v0)
|
|
/* f0a7b04: 848d0010 */ lh $t5,0x10($a0)
|
|
/* f0a7b08: 006d082a */ slt $at,$v1,$t5
|
|
/* f0a7b0c: 5420fff4 */ bnezl $at,.L0f0a7ae0
|
|
/* f0a7b10: 8c8c000c */ lw $t4,0xc($a0)
|
|
/* f0a7b14: 84980010 */ lh $t8,0x10($a0)
|
|
.L0f0a7b18:
|
|
/* f0a7b18: 24a50001 */ addiu $a1,$a1,0x1
|
|
/* f0a7b1c: 00b8082a */ slt $at,$a1,$t8
|
|
/* f0a7b20: 5420ffd6 */ bnezl $at,.L0f0a7a7c
|
|
/* f0a7b24: 8e2a0034 */ lw $t2,0x34($s1)
|
|
.L0f0a7b28:
|
|
/* f0a7b28: 27a4010c */ addiu $a0,$sp,0x10c
|
|
.L0f0a7b2c:
|
|
/* f0a7b2c: 0c0087bd */ jal modelRender
|
|
/* f0a7b30: 8fa5003c */ lw $a1,0x3c($sp)
|
|
/* f0a7b34: 8e791594 */ lw $t9,0x1594($s3)
|
|
/* f0a7b38: 3c0f8007 */ lui $t7,%hi(var800702dc)
|
|
/* f0a7b3c: 53200013 */ beqzl $t9,.L0f0a7b8c
|
|
/* f0a7b40: 8fac0118 */ lw $t4,0x118($sp)
|
|
/* f0a7b44: 8def02dc */ lw $t7,%lo(var800702dc)($t7)
|
|
/* f0a7b48: 8fa90140 */ lw $t1,0x140($sp)
|
|
/* f0a7b4c: 51e0000f */ beqzl $t7,.L0f0a7b8c
|
|
/* f0a7b50: 8fac0118 */ lw $t4,0x118($sp)
|
|
/* f0a7b54: afa9007c */ sw $t1,0x7c($sp)
|
|
/* f0a7b58: 8e0e0390 */ lw $t6,0x390($s0)
|
|
/* f0a7b5c: 26050534 */ addiu $a1,$s0,0x534
|
|
/* f0a7b60: 00a02025 */ or $a0,$a1,$zero
|
|
/* f0a7b64: ae0e0540 */ sw $t6,0x540($s0)
|
|
/* f0a7b68: 0c007308 */ jal modelUpdateRelations
|
|
/* f0a7b6c: afa50054 */ sw $a1,0x54($sp)
|
|
/* f0a7b70: 8fa50054 */ lw $a1,0x54($sp)
|
|
/* f0a7b74: afb50140 */ sw $s5,0x140($sp)
|
|
/* f0a7b78: 0c0087bd */ jal modelRender
|
|
/* f0a7b7c: 27a4010c */ addiu $a0,$sp,0x10c
|
|
/* f0a7b80: 8fa4007c */ lw $a0,0x7c($sp)
|
|
/* f0a7b84: afa40140 */ sw $a0,0x140($sp)
|
|
/* f0a7b88: 8fac0118 */ lw $t4,0x118($sp)
|
|
.L0f0a7b8c:
|
|
/* f0a7b8c: 8fa400ec */ lw $a0,0xec($sp)
|
|
/* f0a7b90: 24050020 */ addiu $a1,$zero,0x20
|
|
/* f0a7b94: 0fc2c5f0 */ jal weaponHasFlag
|
|
/* f0a7b98: afac014c */ sw $t4,0x14c($sp)
|
|
/* f0a7b9c: 10400007 */ beqz $v0,.L0f0a7bbc
|
|
/* f0a7ba0: 8faa014c */ lw $t2,0x14c($sp)
|
|
/* f0a7ba4: 25480008 */ addiu $t0,$t2,0x8
|
|
/* f0a7ba8: afa8014c */ sw $t0,0x14c($sp)
|
|
/* f0a7bac: 3c0bb600 */ lui $t3,0xb600
|
|
/* f0a7bb0: 240d3000 */ addiu $t5,$zero,0x3000
|
|
/* f0a7bb4: ad4d0004 */ sw $t5,0x4($t2)
|
|
/* f0a7bb8: ad4b0000 */ sw $t3,0x0($t2)
|
|
.L0f0a7bbc:
|
|
/* f0a7bbc: 8e18038c */ lw $t8,0x38c($s0)
|
|
/* f0a7bc0: 8e040390 */ lw $a0,0x390($s0)
|
|
/* f0a7bc4: 0fc30cfc */ jal mtxF2LBulk
|
|
/* f0a7bc8: 8705000e */ lh $a1,0xe($t8)
|
|
/* f0a7bcc: 0c0059e1 */ jal mtx00016784
|
|
/* f0a7bd0: 00000000 */ nop
|
|
/* f0a7bd4: 8fb9014c */ lw $t9,0x14c($sp)
|
|
/* f0a7bd8: 3c09bc00 */ lui $t1,0xbc00
|
|
/* f0a7bdc: 3529000e */ ori $t1,$t1,0xe
|
|
/* f0a7be0: 272f0008 */ addiu $t7,$t9,0x8
|
|
/* f0a7be4: afaf014c */ sw $t7,0x14c($sp)
|
|
/* f0a7be8: af290000 */ sw $t1,0x0($t9)
|
|
/* f0a7bec: 0c002adb */ jal viGetPerspScale
|
|
/* f0a7bf0: afb90074 */ sw $t9,0x74($sp)
|
|
/* f0a7bf4: 8fa30074 */ lw $v1,0x74($sp)
|
|
/* f0a7bf8: ac620004 */ sw $v0,0x4($v1)
|
|
.L0f0a7bfc:
|
|
/* f0a7bfc: 26940001 */ addiu $s4,$s4,0x1
|
|
/* f0a7c00: 24010002 */ addiu $at,$zero,0x2
|
|
/* f0a7c04: 1681fe04 */ bne $s4,$at,.L0f0a7418
|
|
/* f0a7c08: 261007a4 */ addiu $s0,$s0,0x7a4
|
|
/* f0a7c0c: afb500e4 */ sw $s5,0xe4($sp)
|
|
/* f0a7c10: 0fc2baf8 */ jal casingsRender
|
|
/* f0a7c14: 27a4014c */ addiu $a0,$sp,0x14c
|
|
/* f0a7c18: 0fc5d8a6 */ jal mblur0f176298
|
|
/* f0a7c1c: 00000000 */ nop
|
|
/* f0a7c20: 0fc5d8ab */ jal mblur0f1762ac
|
|
/* f0a7c24: 8fa4014c */ lw $a0,0x14c($sp)
|
|
/* f0a7c28: afa2014c */ sw $v0,0x14c($sp)
|
|
/* f0a7c2c: 0c002c74 */ jal vi0000b1d0
|
|
/* f0a7c30: 00402025 */ or $a0,$v0,$zero
|
|
/* f0a7c34: 244e0008 */ addiu $t6,$v0,0x8
|
|
/* f0a7c38: afae014c */ sw $t6,0x14c($sp)
|
|
/* f0a7c3c: 0c002f40 */ jal viGetViewLeft
|
|
/* f0a7c40: 00408825 */ or $s1,$v0,$zero
|
|
/* f0a7c44: 00028400 */ sll $s0,$v0,0x10
|
|
/* f0a7c48: 00106403 */ sra $t4,$s0,0x10
|
|
/* f0a7c4c: 0c002f44 */ jal viGetViewTop
|
|
/* f0a7c50: 01808025 */ or $s0,$t4,$zero
|
|
/* f0a7c54: 44824000 */ mtc1 $v0,$f8
|
|
/* f0a7c58: 44902000 */ mtc1 $s0,$f4
|
|
/* f0a7c5c: 3c014080 */ lui $at,0x4080
|
|
/* f0a7c60: 468042a0 */ cvt.s.w $f10,$f8
|
|
/* f0a7c64: 44810000 */ mtc1 $at,$f0
|
|
/* f0a7c68: 3c01ed00 */ lui $at,0xed00
|
|
/* f0a7c6c: 468021a0 */ cvt.s.w $f6,$f4
|
|
/* f0a7c70: 46005402 */ mul.s $f16,$f10,$f0
|
|
/* f0a7c74: 00000000 */ nop
|
|
/* f0a7c78: 46003202 */ mul.s $f8,$f6,$f0
|
|
/* f0a7c7c: 4600848d */ trunc.w.s $f18,$f16
|
|
/* f0a7c80: 4600428d */ trunc.w.s $f10,$f8
|
|
/* f0a7c84: 44089000 */ mfc1 $t0,$f18
|
|
/* f0a7c88: 44195000 */ mfc1 $t9,$f10
|
|
/* f0a7c8c: 310b0fff */ andi $t3,$t0,0xfff
|
|
/* f0a7c90: 01616825 */ or $t5,$t3,$at
|
|
/* f0a7c94: 332f0fff */ andi $t7,$t9,0xfff
|
|
/* f0a7c98: 000f4b00 */ sll $t1,$t7,0xc
|
|
/* f0a7c9c: 01a97025 */ or $t6,$t5,$t1
|
|
/* f0a7ca0: 0c002f22 */ jal viGetViewWidth
|
|
/* f0a7ca4: ae2e0000 */ sw $t6,0x0($s1)
|
|
/* f0a7ca8: 00029400 */ sll $s2,$v0,0x10
|
|
/* f0a7cac: 00126403 */ sra $t4,$s2,0x10
|
|
/* f0a7cb0: 0c002f40 */ jal viGetViewLeft
|
|
/* f0a7cb4: 01809025 */ or $s2,$t4,$zero
|
|
/* f0a7cb8: 0002a400 */ sll $s4,$v0,0x10
|
|
/* f0a7cbc: 00145403 */ sra $t2,$s4,0x10
|
|
/* f0a7cc0: 0c002f44 */ jal viGetViewTop
|
|
/* f0a7cc4: 0140a025 */ or $s4,$t2,$zero
|
|
/* f0a7cc8: 00028400 */ sll $s0,$v0,0x10
|
|
/* f0a7ccc: 00104403 */ sra $t0,$s0,0x10
|
|
/* f0a7cd0: 0c002f26 */ jal viGetViewHeight
|
|
/* f0a7cd4: 01008025 */ or $s0,$t0,$zero
|
|
/* f0a7cd8: 00505821 */ addu $t3,$v0,$s0
|
|
/* f0a7cdc: 448b8000 */ mtc1 $t3,$f16
|
|
/* f0a7ce0: 02926821 */ addu $t5,$s4,$s2
|
|
/* f0a7ce4: 448d5000 */ mtc1 $t5,$f10
|
|
/* f0a7ce8: 468084a0 */ cvt.s.w $f18,$f16
|
|
/* f0a7cec: 3c014080 */ lui $at,0x4080
|
|
/* f0a7cf0: 44812000 */ mtc1 $at,$f4
|
|
/* f0a7cf4: 46805420 */ cvt.s.w $f16,$f10
|
|
/* f0a7cf8: 46049182 */ mul.s $f6,$f18,$f4
|
|
/* f0a7cfc: 44819000 */ mtc1 $at,$f18
|
|
/* f0a7d00: 00000000 */ nop
|
|
/* f0a7d04: 46128102 */ mul.s $f4,$f16,$f18
|
|
/* f0a7d08: 4600320d */ trunc.w.s $f8,$f6
|
|
/* f0a7d0c: 4600218d */ trunc.w.s $f6,$f4
|
|
/* f0a7d10: 44194000 */ mfc1 $t9,$f8
|
|
/* f0a7d14: 440e3000 */ mfc1 $t6,$f6
|
|
/* f0a7d18: 332f0fff */ andi $t7,$t9,0xfff
|
|
/* f0a7d1c: 31cc0fff */ andi $t4,$t6,0xfff
|
|
/* f0a7d20: 000c5300 */ sll $t2,$t4,0xc
|
|
/* f0a7d24: 01ea4025 */ or $t0,$t7,$t2
|
|
/* f0a7d28: ae280004 */ sw $t0,0x4($s1)
|
|
/* f0a7d2c: 8fb80150 */ lw $t8,0x150($sp)
|
|
/* f0a7d30: 8fab014c */ lw $t3,0x14c($sp)
|
|
/* f0a7d34: af0b0000 */ sw $t3,0x0($t8)
|
|
/* f0a7d38: 8fbf0034 */ lw $ra,0x34($sp)
|
|
.L0f0a7d3c:
|
|
/* f0a7d3c: 8fb0001c */ lw $s0,0x1c($sp)
|
|
/* f0a7d40: 8fb10020 */ lw $s1,0x20($sp)
|
|
/* f0a7d44: 8fb20024 */ lw $s2,0x24($sp)
|
|
/* f0a7d48: 8fb30028 */ lw $s3,0x28($sp)
|
|
/* f0a7d4c: 8fb4002c */ lw $s4,0x2c($sp)
|
|
/* f0a7d50: 8fb50030 */ lw $s5,0x30($sp)
|
|
/* f0a7d54: 03e00008 */ jr $ra
|
|
/* f0a7d58: 27bd0150 */ addiu $sp,$sp,0x150
|
|
);
|
|
#else
|
|
GLOBAL_ASM(
|
|
glabel bgunRender
|
|
.late_rodata
|
|
glabel var7f1aca8c
|
|
.word 0x3faaaaab
|
|
glabel var7f1aca90
|
|
.word 0x3f3ebebf
|
|
.text
|
|
/* f0a4e84: 27bdfeb8 */ addiu $sp,$sp,-328
|
|
/* f0a4e88: afbf0034 */ sw $ra,0x34($sp)
|
|
/* f0a4e8c: afb50030 */ sw $s5,0x30($sp)
|
|
/* f0a4e90: afb4002c */ sw $s4,0x2c($sp)
|
|
/* f0a4e94: afb30028 */ sw $s3,0x28($sp)
|
|
/* f0a4e98: afb20024 */ sw $s2,0x24($sp)
|
|
/* f0a4e9c: afb10020 */ sw $s1,0x20($sp)
|
|
/* f0a4ea0: afb0001c */ sw $s0,0x1c($sp)
|
|
/* f0a4ea4: afa40148 */ sw $a0,0x148($sp)
|
|
/* f0a4ea8: 8c8f0000 */ lw $t7,0x0($a0)
|
|
/* f0a4eac: 3c198007 */ lui $t9,%hi(var8007029c)
|
|
/* f0a4eb0: 3c11800a */ lui $s1,%hi(g_Vars)
|
|
/* f0a4eb4: 2739295c */ addiu $t9,$t9,%lo(var8007029c)
|
|
/* f0a4eb8: 2631e6c0 */ addiu $s1,$s1,%lo(g_Vars)
|
|
/* f0a4ebc: 272a003c */ addiu $t2,$t9,0x3c
|
|
/* f0a4ec0: 27b80104 */ addiu $t8,$sp,0x104
|
|
/* f0a4ec4: afaf0144 */ sw $t7,0x144($sp)
|
|
.NB0f0a4ec8:
|
|
/* f0a4ec8: 8f210000 */ lw $at,0x0($t9)
|
|
/* f0a4ecc: 2739000c */ addiu $t9,$t9,0xc
|
|
/* f0a4ed0: 2718000c */ addiu $t8,$t8,0xc
|
|
/* f0a4ed4: af01fff4 */ sw $at,-0xc($t8)
|
|
/* f0a4ed8: 8f21fff8 */ lw $at,-0x8($t9)
|
|
/* f0a4edc: af01fff8 */ sw $at,-0x8($t8)
|
|
/* f0a4ee0: 8f21fffc */ lw $at,-0x4($t9)
|
|
/* f0a4ee4: 172afff8 */ bne $t9,$t2,.NB0f0a4ec8
|
|
/* f0a4ee8: af01fffc */ sw $at,-0x4($t8)
|
|
/* f0a4eec: 8f210000 */ lw $at,0x0($t9)
|
|
/* f0a4ef0: af010000 */ sw $at,0x0($t8)
|
|
/* f0a4ef4: 8e330284 */ lw $s3,0x284($s1)
|
|
/* f0a4ef8: 24010001 */ addiu $at,$zero,0x1
|
|
/* f0a4efc: 966b0010 */ lhu $t3,0x10($s3)
|
|
/* f0a4f00: 1561000d */ bne $t3,$at,.NB0f0a4f38
|
|
/* f0a4f04: 00001025 */ or $v0,$zero,$zero
|
|
/* f0a4f08: 24040f48 */ addiu $a0,$zero,0xf48
|
|
/* f0a4f0c: 8e2c0284 */ lw $t4,0x284($s1)
|
|
.NB0f0a4f10:
|
|
/* f0a4f10: 01821821 */ addu $v1,$t4,$v0
|
|
/* f0a4f14: 8c6d0854 */ lw $t5,0x854($v1)
|
|
/* f0a4f18: 244207a4 */ addiu $v0,$v0,0x7a4
|
|
/* f0a4f1c: 11a00002 */ beqz $t5,.NB0f0a4f28
|
|
/* f0a4f20: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a4f24: ac600850 */ sw $zero,0x850($v1)
|
|
.NB0f0a4f28:
|
|
/* f0a4f28: 5444fff9 */ bnel $v0,$a0,.NB0f0a4f10
|
|
/* f0a4f2c: 8e2c0284 */ lw $t4,0x284($s1)
|
|
/* f0a4f30: 100002cd */ beqz $zero,.NB0f0a5a68
|
|
/* f0a4f34: 8fbf0034 */ lw $ra,0x34($sp)
|
|
.NB0f0a4f38:
|
|
/* f0a4f38: 0fc5c4d5 */ jal mblurRender
|
|
/* f0a4f3c: 8fa40144 */ lw $a0,0x144($sp)
|
|
/* f0a4f40: afa20144 */ sw $v0,0x144($sp)
|
|
/* f0a4f44: 0c002d00 */ jal vi0000b280
|
|
/* f0a4f48: 00402025 */ or $a0,$v0,$zero
|
|
/* f0a4f4c: afa20144 */ sw $v0,0x144($sp)
|
|
/* f0a4f50: 0c002cd4 */ jal vi0000b1d0
|
|
/* f0a4f54: 00402025 */ or $a0,$v0,$zero
|
|
/* f0a4f58: 244e0008 */ addiu $t6,$v0,0x8
|
|
/* f0a4f5c: afae0144 */ sw $t6,0x144($sp)
|
|
/* f0a4f60: 0c002fb5 */ jal viGetViewLeft
|
|
/* f0a4f64: 0040a825 */ or $s5,$v0,$zero
|
|
/* f0a4f68: 00028400 */ sll $s0,$v0,0x10
|
|
/* f0a4f6c: 00107c03 */ sra $t7,$s0,0x10
|
|
/* f0a4f70: 0c002fb9 */ jal viGetViewTop
|
|
/* f0a4f74: 01e08025 */ or $s0,$t7,$zero
|
|
/* f0a4f78: 44822000 */ mtc1 $v0,$f4
|
|
/* f0a4f7c: 44908000 */ mtc1 $s0,$f16
|
|
/* f0a4f80: 3c014080 */ lui $at,0x4080
|
|
/* f0a4f84: 468021a0 */ cvt.s.w $f6,$f4
|
|
/* f0a4f88: 44810000 */ mtc1 $at,$f0
|
|
/* f0a4f8c: 3c01ed00 */ lui $at,0xed00
|
|
/* f0a4f90: 468084a0 */ cvt.s.w $f18,$f16
|
|
/* f0a4f94: 46003202 */ mul.s $f8,$f6,$f0
|
|
/* f0a4f98: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a4f9c: 46009102 */ mul.s $f4,$f18,$f0
|
|
/* f0a4fa0: 4600428d */ trunc.w.s $f10,$f8
|
|
/* f0a4fa4: 4600218d */ trunc.w.s $f6,$f4
|
|
/* f0a4fa8: 44085000 */ mfc1 $t0,$f10
|
|
/* f0a4fac: 440b3000 */ mfc1 $t3,$f6
|
|
/* f0a4fb0: 310a0fff */ andi $t2,$t0,0xfff
|
|
/* f0a4fb4: 0141c825 */ or $t9,$t2,$at
|
|
/* f0a4fb8: 316c0fff */ andi $t4,$t3,0xfff
|
|
/* f0a4fbc: 000c6b00 */ sll $t5,$t4,0xc
|
|
/* f0a4fc0: 032d7025 */ or $t6,$t9,$t5
|
|
/* f0a4fc4: 0c002f97 */ jal viGetViewWidth
|
|
/* f0a4fc8: aeae0000 */ sw $t6,0x0($s5)
|
|
/* f0a4fcc: 00029400 */ sll $s2,$v0,0x10
|
|
/* f0a4fd0: 00127c03 */ sra $t7,$s2,0x10
|
|
/* f0a4fd4: 0c002fb5 */ jal viGetViewLeft
|
|
/* f0a4fd8: 01e09025 */ or $s2,$t7,$zero
|
|
/* f0a4fdc: 0002a400 */ sll $s4,$v0,0x10
|
|
/* f0a4fe0: 00144c03 */ sra $t1,$s4,0x10
|
|
/* f0a4fe4: 0c002fb9 */ jal viGetViewTop
|
|
/* f0a4fe8: 0120a025 */ or $s4,$t1,$zero
|
|
/* f0a4fec: 00028400 */ sll $s0,$v0,0x10
|
|
/* f0a4ff0: 00104403 */ sra $t0,$s0,0x10
|
|
/* f0a4ff4: 0c002f9b */ jal viGetViewHeight
|
|
/* f0a4ff8: 01008025 */ or $s0,$t0,$zero
|
|
/* f0a4ffc: 00505021 */ addu $t2,$v0,$s0
|
|
/* f0a5000: 448a4000 */ mtc1 $t2,$f8
|
|
/* f0a5004: 0292c821 */ addu $t9,$s4,$s2
|
|
/* f0a5008: 44992000 */ mtc1 $t9,$f4
|
|
/* f0a500c: 468042a0 */ cvt.s.w $f10,$f8
|
|
/* f0a5010: 3c014080 */ lui $at,0x4080
|
|
/* f0a5014: 44810000 */ mtc1 $at,$f0
|
|
/* f0a5018: 3c053fc0 */ lui $a1,0x3fc0
|
|
/* f0a501c: 3c06447a */ lui $a2,0x447a
|
|
/* f0a5020: 468021a0 */ cvt.s.w $f6,$f4
|
|
/* f0a5024: 46005402 */ mul.s $f16,$f10,$f0
|
|
/* f0a5028: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a502c: 46003202 */ mul.s $f8,$f6,$f0
|
|
/* f0a5030: 4600848d */ trunc.w.s $f18,$f16
|
|
/* f0a5034: 4600428d */ trunc.w.s $f10,$f8
|
|
/* f0a5038: 440b9000 */ mfc1 $t3,$f18
|
|
/* f0a503c: 440e5000 */ mfc1 $t6,$f10
|
|
/* f0a5040: 316c0fff */ andi $t4,$t3,0xfff
|
|
/* f0a5044: 31cf0fff */ andi $t7,$t6,0xfff
|
|
/* f0a5048: 000f4b00 */ sll $t1,$t7,0xc
|
|
/* f0a504c: 01894025 */ or $t0,$t4,$t1
|
|
/* f0a5050: aea80004 */ sw $t0,0x4($s5)
|
|
/* f0a5054: 0c002b89 */ jal vi0000aca4
|
|
/* f0a5058: 8fa40144 */ lw $a0,0x144($sp)
|
|
/* f0a505c: 8e2a0284 */ lw $t2,0x284($s1)
|
|
/* f0a5060: afa20144 */ sw $v0,0x144($sp)
|
|
/* f0a5064: 91581bfc */ lbu $t8,0x1bfc($t2)
|
|
/* f0a5068: 53000016 */ beqzl $t8,.NB0f0a50c4
|
|
/* f0a506c: 8e2b006c */ lw $t3,0x6c($s1)
|
|
/* f0a5070: 0fc53582 */ jal optionsGetScreenRatio
|
|
/* f0a5074: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a5078: 24010001 */ addiu $at,$zero,0x1
|
|
/* f0a507c: 14410008 */ bne $v0,$at,.NB0f0a50a0
|
|
/* f0a5080: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a5084: 0fc2ebf0 */ jal player0f0bd358
|
|
/* f0a5088: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a508c: 3c017f1a */ lui $at,%hi(var7f1aca8c)
|
|
/* f0a5090: c4306dd4 */ lwc1 $f16,%lo(var7f1aca8c)($at)
|
|
/* f0a5094: 46100082 */ mul.s $f2,$f0,$f16
|
|
/* f0a5098: 10000005 */ beqz $zero,.NB0f0a50b0
|
|
/* f0a509c: 44061000 */ mfc1 $a2,$f2
|
|
.NB0f0a50a0:
|
|
/* f0a50a0: 0fc2ebf0 */ jal player0f0bd358
|
|
/* f0a50a4: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a50a8: 46000086 */ mov.s $f2,$f0
|
|
/* f0a50ac: 44061000 */ mfc1 $a2,$f2
|
|
.NB0f0a50b0:
|
|
/* f0a50b0: 8fa40144 */ lw $a0,0x144($sp)
|
|
/* f0a50b4: 0c002c9a */ jal vi0000b0e8
|
|
/* f0a50b8: 3c054270 */ lui $a1,0x4270
|
|
/* f0a50bc: afa20144 */ sw $v0,0x144($sp)
|
|
/* f0a50c0: 8e2b006c */ lw $t3,0x6c($s1)
|
|
.NB0f0a50c4:
|
|
/* f0a50c4: 24010001 */ addiu $at,$zero,0x1
|
|
/* f0a50c8: 51600004 */ beqzl $t3,.NB0f0a50dc
|
|
/* f0a50cc: 00002825 */ or $a1,$zero,$zero
|
|
/* f0a50d0: 10000002 */ beqz $zero,.NB0f0a50dc
|
|
/* f0a50d4: 24050001 */ addiu $a1,$zero,0x1
|
|
/* f0a50d8: 00002825 */ or $a1,$zero,$zero
|
|
.NB0f0a50dc:
|
|
/* f0a50dc: 8e390068 */ lw $t9,0x68($s1)
|
|
/* f0a50e0: 53200004 */ beqzl $t9,.NB0f0a50f4
|
|
/* f0a50e4: 00002025 */ or $a0,$zero,$zero
|
|
/* f0a50e8: 10000002 */ beqz $zero,.NB0f0a50f4
|
|
/* f0a50ec: 24040001 */ addiu $a0,$zero,0x1
|
|
/* f0a50f0: 00002025 */ or $a0,$zero,$zero
|
|
.NB0f0a50f4:
|
|
/* f0a50f4: 8e2d0064 */ lw $t5,0x64($s1)
|
|
/* f0a50f8: 51a00004 */ beqzl $t5,.NB0f0a510c
|
|
/* f0a50fc: 00001025 */ or $v0,$zero,$zero
|
|
/* f0a5100: 10000002 */ beqz $zero,.NB0f0a510c
|
|
/* f0a5104: 24020001 */ addiu $v0,$zero,0x1
|
|
/* f0a5108: 00001025 */ or $v0,$zero,$zero
|
|
.NB0f0a510c:
|
|
/* f0a510c: 8e2e0070 */ lw $t6,0x70($s1)
|
|
/* f0a5110: 51c00004 */ beqzl $t6,.NB0f0a5124
|
|
/* f0a5114: 00001825 */ or $v1,$zero,$zero
|
|
/* f0a5118: 10000002 */ beqz $zero,.NB0f0a5124
|
|
/* f0a511c: 24030001 */ addiu $v1,$zero,0x1
|
|
/* f0a5120: 00001825 */ or $v1,$zero,$zero
|
|
.NB0f0a5124:
|
|
/* f0a5124: 00627821 */ addu $t7,$v1,$v0
|
|
/* f0a5128: 01e46021 */ addu $t4,$t7,$a0
|
|
/* f0a512c: 01854821 */ addu $t1,$t4,$a1
|
|
/* f0a5130: 15210008 */ bne $t1,$at,.NB0f0a5154
|
|
/* f0a5134: 3c088009 */ lui $t0,%hi(g_Is4Mb)
|
|
/* f0a5138: 910830e0 */ lbu $t0,%lo(g_Is4Mb)($t0)
|
|
/* f0a513c: 24010001 */ addiu $at,$zero,0x1
|
|
/* f0a5140: 51010005 */ beql $t0,$at,.NB0f0a5158
|
|
/* f0a5144: 0000a025 */ or $s4,$zero,$zero
|
|
/* f0a5148: 0fc2b5eb */ jal lasersightRenderBeam
|
|
/* f0a514c: 8fa40144 */ lw $a0,0x144($sp)
|
|
/* f0a5150: afa20144 */ sw $v0,0x144($sp)
|
|
.NB0f0a5154:
|
|
/* f0a5154: 0000a025 */ or $s4,$zero,$zero
|
|
.NB0f0a5158:
|
|
/* f0a5158: 26700638 */ addiu $s0,$s3,0x638
|
|
/* f0a515c: 8fb500dc */ lw $s5,0xdc($sp)
|
|
/* f0a5160: 24120019 */ addiu $s2,$zero,0x19
|
|
.NB0f0a5164:
|
|
/* f0a5164: 0fc27de9 */ jal bgunGetWeaponNum2
|
|
/* f0a5168: 02802025 */ or $a0,$s4,$zero
|
|
/* f0a516c: afa200e4 */ sw $v0,0xe4($sp)
|
|
/* f0a5170: 820a0007 */ lb $t2,0x7($s0)
|
|
/* f0a5174: 8fa40144 */ lw $a0,0x144($sp)
|
|
/* f0a5178: 260501dc */ addiu $a1,$s0,0x1dc
|
|
/* f0a517c: 114001ea */ beqz $t2,.NB0f0a5928
|
|
/* f0a5180: 00003025 */ or $a2,$zero,$zero
|
|
/* f0a5184: 26180384 */ addiu $t8,$s0,0x384
|
|
/* f0a5188: afb80038 */ sw $t8,0x38($sp)
|
|
/* f0a518c: 0fc2aa3c */ jal beamRender
|
|
/* f0a5190: 00003825 */ or $a3,$zero,$zero
|
|
/* f0a5194: afa20144 */ sw $v0,0x144($sp)
|
|
/* f0a5198: 92040000 */ lbu $a0,0x0($s0)
|
|
/* f0a519c: 0fc2bd48 */ jal weaponHasFlag
|
|
/* f0a51a0: 34058000 */ dli $a1,0x8000
|
|
/* f0a51a4: 10400030 */ beqz $v0,.NB0f0a5268
|
|
/* f0a51a8: 8fab0144 */ lw $t3,0x144($sp)
|
|
/* f0a51ac: 25790008 */ addiu $t9,$t3,0x8
|
|
/* f0a51b0: afb90144 */ sw $t9,0x144($sp)
|
|
/* f0a51b4: 3c0dbc00 */ lui $t5,0xbc00
|
|
/* f0a51b8: 3c0e8000 */ lui $t6,0x8000
|
|
/* f0a51bc: 35ce0040 */ ori $t6,$t6,0x40
|
|
/* f0a51c0: 35ad0002 */ ori $t5,$t5,0x2
|
|
/* f0a51c4: ad6d0000 */ sw $t5,0x0($t3)
|
|
/* f0a51c8: ad6e0004 */ sw $t6,0x4($t3)
|
|
/* f0a51cc: 8faf0144 */ lw $t7,0x144($sp)
|
|
/* f0a51d0: 3c090386 */ lui $t1,0x386
|
|
/* f0a51d4: 3c088007 */ lui $t0,%hi(var80070090+0x8)
|
|
/* f0a51d8: 25ec0008 */ addiu $t4,$t7,0x8
|
|
/* f0a51dc: afac0144 */ sw $t4,0x144($sp)
|
|
/* f0a51e0: 25082758 */ addiu $t0,$t0,%lo(var80070090+0x8)
|
|
/* f0a51e4: 35290010 */ ori $t1,$t1,0x10
|
|
/* f0a51e8: ade90000 */ sw $t1,0x0($t7)
|
|
/* f0a51ec: ade80004 */ sw $t0,0x4($t7)
|
|
/* f0a51f0: 8faa0144 */ lw $t2,0x144($sp)
|
|
/* f0a51f4: 3c0b0388 */ lui $t3,0x388
|
|
/* f0a51f8: 3c198007 */ lui $t9,%hi(var80070090)
|
|
/* f0a51fc: 25580008 */ addiu $t8,$t2,0x8
|
|
/* f0a5200: afb80144 */ sw $t8,0x144($sp)
|
|
/* f0a5204: 27392750 */ addiu $t9,$t9,%lo(var80070090)
|
|
/* f0a5208: 356b0010 */ ori $t3,$t3,0x10
|
|
/* f0a520c: ad4b0000 */ sw $t3,0x0($t2)
|
|
/* f0a5210: ad590004 */ sw $t9,0x4($t2)
|
|
/* f0a5214: 8fad0144 */ lw $t5,0x144($sp)
|
|
/* f0a5218: 3c0f0384 */ lui $t7,0x384
|
|
/* f0a521c: 35ef0010 */ ori $t7,$t7,0x10
|
|
/* f0a5220: 25ae0008 */ addiu $t6,$t5,0x8
|
|
/* f0a5224: afae0144 */ sw $t6,0x144($sp)
|
|
/* f0a5228: adaf0000 */ sw $t7,0x0($t5)
|
|
/* f0a522c: 0fc2cd42 */ jal camGetLookAt
|
|
/* f0a5230: afad00cc */ sw $t5,0xcc($sp)
|
|
/* f0a5234: 8fa500cc */ lw $a1,0xcc($sp)
|
|
/* f0a5238: 3c080382 */ lui $t0,0x382
|
|
/* f0a523c: 35080010 */ ori $t0,$t0,0x10
|
|
/* f0a5240: aca20004 */ sw $v0,0x4($a1)
|
|
/* f0a5244: 8fac0144 */ lw $t4,0x144($sp)
|
|
/* f0a5248: 25890008 */ addiu $t1,$t4,0x8
|
|
/* f0a524c: afa90144 */ sw $t1,0x144($sp)
|
|
/* f0a5250: ad880000 */ sw $t0,0x0($t4)
|
|
/* f0a5254: 0fc2cd42 */ jal camGetLookAt
|
|
/* f0a5258: afac00c8 */ sw $t4,0xc8($sp)
|
|
/* f0a525c: 8fa300c8 */ lw $v1,0xc8($sp)
|
|
/* f0a5260: 244a0010 */ addiu $t2,$v0,0x10
|
|
/* f0a5264: ac6a0004 */ sw $t2,0x4($v1)
|
|
.NB0f0a5268:
|
|
/* f0a5268: 8fb80144 */ lw $t8,0x144($sp)
|
|
/* f0a526c: 3c19bc00 */ lui $t9,0xbc00
|
|
/* f0a5270: 3739000e */ ori $t9,$t9,0xe
|
|
/* f0a5274: 270b0008 */ addiu $t3,$t8,0x8
|
|
/* f0a5278: afab0144 */ sw $t3,0x144($sp)
|
|
/* f0a527c: 3c014396 */ lui $at,0x4396
|
|
/* f0a5280: 44817000 */ mtc1 $at,$f14
|
|
/* f0a5284: 44806000 */ mtc1 $zero,$f12
|
|
/* f0a5288: af190000 */ sw $t9,0x0($t8)
|
|
/* f0a528c: 0c005f57 */ jal mtx00016dcc
|
|
/* f0a5290: afb800c4 */ sw $t8,0xc4($sp)
|
|
/* f0a5294: 8fa300c4 */ lw $v1,0xc4($sp)
|
|
/* f0a5298: 24050010 */ addiu $a1,$zero,0x10
|
|
/* f0a529c: ac620004 */ sw $v0,0x4($v1)
|
|
/* f0a52a0: 0c006ea3 */ jal modelGetPart
|
|
/* f0a52a4: 8e04038c */ lw $a0,0x38c($s0)
|
|
/* f0a52a8: 10400014 */ beqz $v0,.NB0f0a52fc
|
|
/* f0a52ac: afa200e0 */ sw $v0,0xe0($sp)
|
|
/* f0a52b0: 8e04038c */ lw $a0,0x38c($s0)
|
|
/* f0a52b4: 0c006ea3 */ jal modelGetPart
|
|
/* f0a52b8: 24050011 */ addiu $a1,$zero,0x11
|
|
/* f0a52bc: 8fa40038 */ lw $a0,0x38($sp)
|
|
/* f0a52c0: 0c006bab */ jal modelGetNodeRwData
|
|
/* f0a52c4: 00402825 */ or $a1,$v0,$zero
|
|
/* f0a52c8: 10400003 */ beqz $v0,.NB0f0a52d8
|
|
/* f0a52cc: 3c06800a */ lui $a2,%hi(var8009cf88)
|
|
/* f0a52d0: 240d0001 */ addiu $t5,$zero,0x1
|
|
/* f0a52d4: ac4d0000 */ sw $t5,0x0($v0)
|
|
.NB0f0a52d8:
|
|
/* f0a52d8: 240e0001 */ addiu $t6,$zero,0x1
|
|
/* f0a52dc: afae0014 */ sw $t6,0x14($sp)
|
|
/* f0a52e0: 8fa40038 */ lw $a0,0x38($sp)
|
|
/* f0a52e4: 8fa500e0 */ lw $a1,0xe0($sp)
|
|
/* f0a52e8: 24c616b8 */ addiu $a2,$a2,%lo(var8009cf88)
|
|
/* f0a52ec: 8fa70144 */ lw $a3,0x144($sp)
|
|
/* f0a52f0: 0fc1f99c */ jal tvscreenRender
|
|
/* f0a52f4: afa00010 */ sw $zero,0x10($sp)
|
|
/* f0a52f8: afa20144 */ sw $v0,0x144($sp)
|
|
.NB0f0a52fc:
|
|
/* f0a52fc: 8faf0144 */ lw $t7,0x144($sp)
|
|
/* f0a5300: 8e250284 */ lw $a1,0x284($s1)
|
|
/* f0a5304: 240c0004 */ addiu $t4,$zero,0x4
|
|
/* f0a5308: afac0134 */ sw $t4,0x134($sp)
|
|
/* f0a530c: afaf0110 */ sw $t7,0x110($sp)
|
|
/* f0a5310: 8ca300d8 */ lw $v1,0xd8($a1)
|
|
/* f0a5314: 3c078007 */ lui $a3,%hi(g_InCutscene)
|
|
/* f0a5318: 14600013 */ bnez $v1,.NB0f0a5368
|
|
/* f0a531c: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a5320: 8ce72e24 */ lw $a3,%lo(g_InCutscene)($a3)
|
|
/* f0a5324: 14e00010 */ bnez $a3,.NB0f0a5368
|
|
/* f0a5328: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a532c: 8ca20480 */ lw $v0,0x480($a1)
|
|
/* f0a5330: 50400007 */ beqzl $v0,.NB0f0a5350
|
|
/* f0a5334: 8caa1c54 */ lw $t2,0x1c54($a1)
|
|
/* f0a5338: 1040000b */ beqz $v0,.NB0f0a5368
|
|
/* f0a533c: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a5340: 80490037 */ lb $t1,0x37($v0)
|
|
/* f0a5344: 15200008 */ bnez $t1,.NB0f0a5368
|
|
/* f0a5348: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a534c: 8caa1c54 */ lw $t2,0x1c54($a1)
|
|
.NB0f0a5350:
|
|
/* f0a5350: 8ca800c4 */ lw $t0,0xc4($a1)
|
|
/* f0a5354: 0140c027 */ nor $t8,$t2,$zero
|
|
/* f0a5358: 01185824 */ and $t3,$t0,$t8
|
|
/* f0a535c: 31790001 */ andi $t9,$t3,0x1
|
|
/* f0a5360: 57200016 */ bnezl $t9,.NB0f0a53bc
|
|
/* f0a5364: 92681615 */ lbu $t0,0x1615($s3)
|
|
.NB0f0a5368:
|
|
/* f0a5368: 14600078 */ bnez $v1,.NB0f0a554c
|
|
/* f0a536c: 3c078007 */ lui $a3,%hi(g_InCutscene)
|
|
/* f0a5370: 8ce72e24 */ lw $a3,%lo(g_InCutscene)($a3)
|
|
/* f0a5374: 54e00076 */ bnezl $a3,.NB0f0a5550
|
|
/* f0a5378: 926d1614 */ lbu $t5,0x1614($s3)
|
|
/* f0a537c: 8ca20480 */ lw $v0,0x480($a1)
|
|
/* f0a5380: 50400007 */ beqzl $v0,.NB0f0a53a0
|
|
/* f0a5384: 8caf1c54 */ lw $t7,0x1c54($a1)
|
|
/* f0a5388: 50400071 */ beqzl $v0,.NB0f0a5550
|
|
/* f0a538c: 926d1614 */ lbu $t5,0x1614($s3)
|
|
/* f0a5390: 804d0037 */ lb $t5,0x37($v0)
|
|
/* f0a5394: 55a0006e */ bnezl $t5,.NB0f0a5550
|
|
/* f0a5398: 926d1614 */ lbu $t5,0x1614($s3)
|
|
/* f0a539c: 8caf1c54 */ lw $t7,0x1c54($a1)
|
|
.NB0f0a53a0:
|
|
/* f0a53a0: 8cae00c4 */ lw $t6,0xc4($a1)
|
|
/* f0a53a4: 01e06027 */ nor $t4,$t7,$zero
|
|
/* f0a53a8: 01cc4824 */ and $t1,$t6,$t4
|
|
/* f0a53ac: 312a0008 */ andi $t2,$t1,0x8
|
|
/* f0a53b0: 51400067 */ beqzl $t2,.NB0f0a5550
|
|
/* f0a53b4: 926d1614 */ lbu $t5,0x1614($s3)
|
|
/* f0a53b8: 92681615 */ lbu $t0,0x1615($s3)
|
|
.NB0f0a53bc:
|
|
/* f0a53bc: 92781614 */ lbu $t8,0x1614($s3)
|
|
/* f0a53c0: 26641614 */ addiu $a0,$s3,0x1614
|
|
/* f0a53c4: 0118082a */ slt $at,$t0,$t8
|
|
/* f0a53c8: 50200009 */ beqzl $at,.NB0f0a53f0
|
|
/* f0a53cc: 90820002 */ lbu $v0,0x2($a0)
|
|
/* f0a53d0: 90830000 */ lbu $v1,0x0($a0)
|
|
/* f0a53d4: 908b0002 */ lbu $t3,0x2($a0)
|
|
/* f0a53d8: 0163082a */ slt $at,$t3,$v1
|
|
/* f0a53dc: 50200004 */ beqzl $at,.NB0f0a53f0
|
|
/* f0a53e0: 90820002 */ lbu $v0,0x2($a0)
|
|
/* f0a53e4: 1000000a */ beqz $zero,.NB0f0a5410
|
|
/* f0a53e8: 00601025 */ or $v0,$v1,$zero
|
|
/* f0a53ec: 90820002 */ lbu $v0,0x2($a0)
|
|
.NB0f0a53f0:
|
|
/* f0a53f0: 90860001 */ lbu $a2,0x1($a0)
|
|
/* f0a53f4: 00401825 */ or $v1,$v0,$zero
|
|
/* f0a53f8: 0046082a */ slt $at,$v0,$a2
|
|
/* f0a53fc: 10200003 */ beqz $at,.NB0f0a540c
|
|
/* f0a5400: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a5404: 10000001 */ beqz $zero,.NB0f0a540c
|
|
/* f0a5408: 00c01825 */ or $v1,$a2,$zero
|
|
.NB0f0a540c:
|
|
/* f0a540c: 00601025 */ or $v0,$v1,$zero
|
|
.NB0f0a5410:
|
|
/* f0a5410: 90890003 */ lbu $t1,0x3($a0)
|
|
/* f0a5414: 0002ce00 */ sll $t9,$v0,0x18
|
|
/* f0a5418: 00026c00 */ sll $t5,$v0,0x10
|
|
/* f0a541c: 032d7825 */ or $t7,$t9,$t5
|
|
/* f0a5420: 00027200 */ sll $t6,$v0,0x8
|
|
/* f0a5424: 01ee6025 */ or $t4,$t7,$t6
|
|
/* f0a5428: 012c5021 */ addu $t2,$t1,$t4
|
|
/* f0a542c: afaa0138 */ sw $t2,0x138($sp)
|
|
/* f0a5430: 8ca300d8 */ lw $v1,0xd8($a1)
|
|
/* f0a5434: 14600021 */ bnez $v1,.NB0f0a54bc
|
|
/* f0a5438: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a543c: 14e0001f */ bnez $a3,.NB0f0a54bc
|
|
/* f0a5440: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a5444: 8ca20480 */ lw $v0,0x480($a1)
|
|
/* f0a5448: 50400007 */ beqzl $v0,.NB0f0a5468
|
|
/* f0a544c: 8cab1c54 */ lw $t3,0x1c54($a1)
|
|
/* f0a5450: 1040001a */ beqz $v0,.NB0f0a54bc
|
|
/* f0a5454: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a5458: 80480037 */ lb $t0,0x37($v0)
|
|
/* f0a545c: 15000017 */ bnez $t0,.NB0f0a54bc
|
|
/* f0a5460: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a5464: 8cab1c54 */ lw $t3,0x1c54($a1)
|
|
.NB0f0a5468:
|
|
/* f0a5468: 8cb800c4 */ lw $t8,0xc4($a1)
|
|
/* f0a546c: 3c02800a */ lui $v0,%hi(var8009caef)
|
|
/* f0a5470: 0160c827 */ nor $t9,$t3,$zero
|
|
/* f0a5474: 03196824 */ and $t5,$t8,$t9
|
|
/* f0a5478: 31af0001 */ andi $t7,$t5,0x1
|
|
/* f0a547c: 11e0000f */ beqz $t7,.NB0f0a54bc
|
|
/* f0a5480: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a5484: 9042122f */ lbu $v0,%lo(var8009caef)($v0)
|
|
/* f0a5488: 3c06800a */ lui $a2,%hi(var8009caf0)
|
|
/* f0a548c: 90c61230 */ lbu $a2,%lo(var8009caf0)($a2)
|
|
/* f0a5490: 00027600 */ sll $t6,$v0,0x18
|
|
/* f0a5494: 00024c00 */ sll $t1,$v0,0x10
|
|
/* f0a5498: 01c96025 */ or $t4,$t6,$t1
|
|
/* f0a549c: 00025200 */ sll $t2,$v0,0x8
|
|
/* f0a54a0: 018a4025 */ or $t0,$t4,$t2
|
|
/* f0a54a4: afa200a8 */ sw $v0,0xa8($sp)
|
|
/* f0a54a8: afa200ac */ sw $v0,0xac($sp)
|
|
/* f0a54ac: afa200b0 */ sw $v0,0xb0($sp)
|
|
/* f0a54b0: 00c8a821 */ addu $s5,$a2,$t0
|
|
/* f0a54b4: 1000001f */ beqz $zero,.NB0f0a5534
|
|
/* f0a54b8: afa600b4 */ sw $a2,0xb4($sp)
|
|
.NB0f0a54bc:
|
|
/* f0a54bc: 5460001e */ bnezl $v1,.NB0f0a5538
|
|
/* f0a54c0: 8fb900e4 */ lw $t9,0xe4($sp)
|
|
/* f0a54c4: 54e0001c */ bnezl $a3,.NB0f0a5538
|
|
/* f0a54c8: 8fb900e4 */ lw $t9,0xe4($sp)
|
|
/* f0a54cc: 8ca20480 */ lw $v0,0x480($a1)
|
|
/* f0a54d0: 50400007 */ beqzl $v0,.NB0f0a54f0
|
|
/* f0a54d4: 8cb91c54 */ lw $t9,0x1c54($a1)
|
|
/* f0a54d8: 50400017 */ beqzl $v0,.NB0f0a5538
|
|
/* f0a54dc: 8fb900e4 */ lw $t9,0xe4($sp)
|
|
/* f0a54e0: 804b0037 */ lb $t3,0x37($v0)
|
|
/* f0a54e4: 55600014 */ bnezl $t3,.NB0f0a5538
|
|
/* f0a54e8: 8fb900e4 */ lw $t9,0xe4($sp)
|
|
/* f0a54ec: 8cb91c54 */ lw $t9,0x1c54($a1)
|
|
.NB0f0a54f0:
|
|
/* f0a54f0: 8cb800c4 */ lw $t8,0xc4($a1)
|
|
/* f0a54f4: 240200ff */ addiu $v0,$zero,0xff
|
|
/* f0a54f8: 03206827 */ nor $t5,$t9,$zero
|
|
/* f0a54fc: 030d7824 */ and $t7,$t8,$t5
|
|
/* f0a5500: 31ee0008 */ andi $t6,$t7,0x8
|
|
/* f0a5504: 11c0000b */ beqz $t6,.NB0f0a5534
|
|
/* f0a5508: 24050080 */ addiu $a1,$zero,0x80
|
|
/* f0a550c: 00024e00 */ sll $t1,$v0,0x18
|
|
/* f0a5510: 00006400 */ sll $t4,$zero,0x10
|
|
/* f0a5514: 012c5025 */ or $t2,$t1,$t4
|
|
/* f0a5518: 00004200 */ sll $t0,$zero,0x8
|
|
/* f0a551c: 01485825 */ or $t3,$t2,$t0
|
|
/* f0a5520: 00aba821 */ addu $s5,$a1,$t3
|
|
/* f0a5524: afa20098 */ sw $v0,0x98($sp)
|
|
/* f0a5528: afa0009c */ sw $zero,0x9c($sp)
|
|
/* f0a552c: afa000a0 */ sw $zero,0xa0($sp)
|
|
/* f0a5530: afa500a4 */ sw $a1,0xa4($sp)
|
|
.NB0f0a5534:
|
|
/* f0a5534: 8fb900e4 */ lw $t9,0xe4($sp)
|
|
.NB0f0a5538:
|
|
/* f0a5538: 24010001 */ addiu $at,$zero,0x1
|
|
/* f0a553c: 5721003d */ bnel $t9,$at,.NB0f0a5634
|
|
/* f0a5540: 8e6f00bc */ lw $t7,0xbc($s3)
|
|
/* f0a5544: 1000003a */ beqz $zero,.NB0f0a5630
|
|
/* f0a5548: afb50138 */ sw $s5,0x138($sp)
|
|
.NB0f0a554c:
|
|
/* f0a554c: 926d1614 */ lbu $t5,0x1614($s3)
|
|
.NB0f0a5550:
|
|
/* f0a5550: 92781617 */ lbu $t8,0x1617($s3)
|
|
/* f0a5554: 92691615 */ lbu $t1,0x1615($s3)
|
|
/* f0a5558: 92681616 */ lbu $t0,0x1616($s3)
|
|
/* f0a555c: 000d7e00 */ sll $t7,$t5,0x18
|
|
/* f0a5560: 030f7025 */ or $t6,$t8,$t7
|
|
/* f0a5564: 00096400 */ sll $t4,$t1,0x10
|
|
/* f0a5568: 01cc5025 */ or $t2,$t6,$t4
|
|
/* f0a556c: 00085a00 */ sll $t3,$t0,0x8
|
|
/* f0a5570: 014bc825 */ or $t9,$t2,$t3
|
|
/* f0a5574: afb90138 */ sw $t9,0x138($sp)
|
|
/* f0a5578: 920d0000 */ lbu $t5,0x0($s0)
|
|
/* f0a557c: 24010006 */ addiu $at,$zero,0x6
|
|
/* f0a5580: 0320a825 */ or $s5,$t9,$zero
|
|
/* f0a5584: 15a1002a */ bne $t5,$at,.NB0f0a5630
|
|
/* f0a5588: 3c04ff00 */ lui $a0,0xff00
|
|
/* f0a558c: 3c014248 */ lui $at,0x4248
|
|
/* f0a5590: 44812000 */ mtc1 $at,$f4
|
|
/* f0a5594: c612023c */ lwc1 $f18,0x23c($s0)
|
|
/* f0a5598: 24060001 */ addiu $a2,$zero,0x1
|
|
/* f0a559c: 3c014f00 */ lui $at,0x4f00
|
|
/* f0a55a0: 46049182 */ mul.s $f6,$f18,$f4
|
|
/* f0a55a4: 3484007f */ ori $a0,$a0,0x7f
|
|
/* f0a55a8: 4458f800 */ cfc1 $t8,$31
|
|
/* f0a55ac: 44c6f800 */ ctc1 $a2,$31
|
|
/* f0a55b0: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a55b4: 46003224 */ cvt.w.s $f8,$f6
|
|
/* f0a55b8: 4446f800 */ cfc1 $a2,$31
|
|
/* f0a55bc: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a55c0: 30c60078 */ andi $a2,$a2,0x78
|
|
/* f0a55c4: 50c00013 */ beqzl $a2,.NB0f0a5614
|
|
/* f0a55c8: 44064000 */ mfc1 $a2,$f8
|
|
/* f0a55cc: 44814000 */ mtc1 $at,$f8
|
|
/* f0a55d0: 24060001 */ addiu $a2,$zero,0x1
|
|
/* f0a55d4: 46083201 */ sub.s $f8,$f6,$f8
|
|
/* f0a55d8: 44c6f800 */ ctc1 $a2,$31
|
|
/* f0a55dc: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a55e0: 46004224 */ cvt.w.s $f8,$f8
|
|
/* f0a55e4: 4446f800 */ cfc1 $a2,$31
|
|
/* f0a55e8: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a55ec: 30c60078 */ andi $a2,$a2,0x78
|
|
/* f0a55f0: 14c00005 */ bnez $a2,.NB0f0a5608
|
|
/* f0a55f4: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a55f8: 44064000 */ mfc1 $a2,$f8
|
|
/* f0a55fc: 3c018000 */ lui $at,0x8000
|
|
/* f0a5600: 10000007 */ beqz $zero,.NB0f0a5620
|
|
/* f0a5604: 00c13025 */ or $a2,$a2,$at
|
|
.NB0f0a5608:
|
|
/* f0a5608: 10000005 */ beqz $zero,.NB0f0a5620
|
|
/* f0a560c: 2406ffff */ addiu $a2,$zero,-1
|
|
/* f0a5610: 44064000 */ mfc1 $a2,$f8
|
|
.NB0f0a5614:
|
|
/* f0a5614: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a5618: 04c0fffb */ bltz $a2,.NB0f0a5608
|
|
/* f0a561c: 00000000 */ sll $zero,$zero,0x0
|
|
.NB0f0a5620:
|
|
/* f0a5620: 44d8f800 */ ctc1 $t8,$31
|
|
/* f0a5624: 0fc01990 */ jal colourBlend
|
|
/* f0a5628: 03202825 */ or $a1,$t9,$zero
|
|
/* f0a562c: afa20138 */ sw $v0,0x138($sp)
|
|
.NB0f0a5630:
|
|
/* f0a5630: 8e6f00bc */ lw $t7,0xbc($s3)
|
|
.NB0f0a5634:
|
|
/* f0a5634: 0fc089b4 */ jal chrGetCloakAlpha
|
|
/* f0a5638: 8de40004 */ lw $a0,0x4($t7)
|
|
/* f0a563c: 284100ff */ slti $at,$v0,0xff
|
|
/* f0a5640: 1020000f */ beqz $at,.NB0f0a5680
|
|
/* f0a5644: 240c0001 */ addiu $t4,$zero,0x1
|
|
/* f0a5648: 44825000 */ mtc1 $v0,$f10
|
|
/* f0a564c: 3c017f1a */ lui $at,%hi(var7f1aca90)
|
|
/* f0a5650: c4326dd8 */ lwc1 $f18,%lo(var7f1aca90)($at)
|
|
/* f0a5654: 46805420 */ cvt.s.w $f16,$f10
|
|
/* f0a5658: 8fa40138 */ lw $a0,0x138($sp)
|
|
/* f0a565c: 240e0005 */ addiu $t6,$zero,0x5
|
|
/* f0a5660: afae0134 */ sw $t6,0x134($sp)
|
|
/* f0a5664: afa4013c */ sw $a0,0x13c($sp)
|
|
/* f0a5668: 46128102 */ mul.s $f4,$f16,$f18
|
|
/* f0a566c: 4600218d */ trunc.w.s $f6,$f4
|
|
/* f0a5670: 44033000 */ mfc1 $v1,$f6
|
|
/* f0a5674: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a5678: 24750041 */ addiu $s5,$v1,0x41
|
|
/* f0a567c: afb50138 */ sw $s5,0x138($sp)
|
|
.NB0f0a5680:
|
|
/* f0a5680: 0c005dbc */ jal mtx00016760
|
|
/* f0a5684: afac0108 */ sw $t4,0x108($sp)
|
|
/* f0a5688: 8e020218 */ lw $v0,0x218($s0)
|
|
/* f0a568c: 5040000f */ beqzl $v0,.NB0f0a56cc
|
|
/* f0a5690: 8fa400e4 */ lw $a0,0xe4($sp)
|
|
/* f0a5694: 8c450018 */ lw $a1,0x18($v0)
|
|
/* f0a5698: 27a40104 */ addiu $a0,$sp,0x104
|
|
/* f0a569c: 0c008be3 */ jal modelRender
|
|
/* f0a56a0: afa50090 */ sw $a1,0x90($sp)
|
|
/* f0a56a4: 8fa60090 */ lw $a2,0x90($sp)
|
|
/* f0a56a8: 8cc80008 */ lw $t0,0x8($a2)
|
|
/* f0a56ac: 8cc4000c */ lw $a0,0xc($a2)
|
|
/* f0a56b0: 0fc303f0 */ jal mtxF2LBulk
|
|
/* f0a56b4: 8505000e */ lh $a1,0xe($t0)
|
|
/* f0a56b8: 8e0a021c */ lw $t2,0x21c($s0)
|
|
/* f0a56bc: 51400003 */ beqzl $t2,.NB0f0a56cc
|
|
/* f0a56c0: 8fa400e4 */ lw $a0,0xe4($sp)
|
|
/* f0a56c4: ae000218 */ sw $zero,0x218($s0)
|
|
/* f0a56c8: 8fa400e4 */ lw $a0,0xe4($sp)
|
|
.NB0f0a56cc:
|
|
/* f0a56cc: 0fc2bd48 */ jal weaponHasFlag
|
|
/* f0a56d0: 24050020 */ addiu $a1,$zero,0x20
|
|
/* f0a56d4: 1040000e */ beqz $v0,.NB0f0a5710
|
|
/* f0a56d8: 24010001 */ addiu $at,$zero,0x1
|
|
/* f0a56dc: 8fab0110 */ lw $t3,0x110($sp)
|
|
/* f0a56e0: 3c18b600 */ lui $t8,0xb600
|
|
/* f0a56e4: 24193000 */ addiu $t9,$zero,0x3000
|
|
/* f0a56e8: 256d0008 */ addiu $t5,$t3,0x8
|
|
/* f0a56ec: afad0110 */ sw $t5,0x110($sp)
|
|
/* f0a56f0: ad790004 */ sw $t9,0x4($t3)
|
|
/* f0a56f4: 16800004 */ bnez $s4,.NB0f0a5708
|
|
/* f0a56f8: ad780000 */ sw $t8,0x0($t3)
|
|
/* f0a56fc: 240f0003 */ addiu $t7,$zero,0x3
|
|
/* f0a5700: 10000003 */ beqz $zero,.NB0f0a5710
|
|
/* f0a5704: afaf0140 */ sw $t7,0x140($sp)
|
|
.NB0f0a5708:
|
|
/* f0a5708: 24090002 */ addiu $t1,$zero,0x2
|
|
/* f0a570c: afa90140 */ sw $t1,0x140($sp)
|
|
.NB0f0a5710:
|
|
/* f0a5710: 8e2e006c */ lw $t6,0x6c($s1)
|
|
/* f0a5714: 00002825 */ or $a1,$zero,$zero
|
|
/* f0a5718: 00002025 */ or $a0,$zero,$zero
|
|
/* f0a571c: 11c00003 */ beqz $t6,.NB0f0a572c
|
|
/* f0a5720: 00001025 */ or $v0,$zero,$zero
|
|
/* f0a5724: 10000001 */ beqz $zero,.NB0f0a572c
|
|
/* f0a5728: 24050001 */ addiu $a1,$zero,0x1
|
|
.NB0f0a572c:
|
|
/* f0a572c: 8e2c0068 */ lw $t4,0x68($s1)
|
|
/* f0a5730: 00001825 */ or $v1,$zero,$zero
|
|
/* f0a5734: 11800003 */ beqz $t4,.NB0f0a5744
|
|
/* f0a5738: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a573c: 10000001 */ beqz $zero,.NB0f0a5744
|
|
/* f0a5740: 24040001 */ addiu $a0,$zero,0x1
|
|
.NB0f0a5744:
|
|
/* f0a5744: 8e280064 */ lw $t0,0x64($s1)
|
|
/* f0a5748: 11000003 */ beqz $t0,.NB0f0a5758
|
|
/* f0a574c: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a5750: 10000001 */ beqz $zero,.NB0f0a5758
|
|
/* f0a5754: 24020001 */ addiu $v0,$zero,0x1
|
|
.NB0f0a5758:
|
|
/* f0a5758: 8e2a0070 */ lw $t2,0x70($s1)
|
|
/* f0a575c: 11400003 */ beqz $t2,.NB0f0a576c
|
|
/* f0a5760: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a5764: 10000001 */ beqz $zero,.NB0f0a576c
|
|
/* f0a5768: 24030001 */ addiu $v1,$zero,0x1
|
|
.NB0f0a576c:
|
|
/* f0a576c: 00625821 */ addu $t3,$v1,$v0
|
|
/* f0a5770: 01646821 */ addu $t5,$t3,$a0
|
|
/* f0a5774: 01a5c021 */ addu $t8,$t5,$a1
|
|
/* f0a5778: 17010036 */ bne $t8,$at,.NB0f0a5854
|
|
/* f0a577c: 24050041 */ addiu $a1,$zero,0x41
|
|
/* f0a5780: 0c006ea3 */ jal modelGetPart
|
|
/* f0a5784: 8e04038c */ lw $a0,0x38c($s0)
|
|
/* f0a5788: 50400033 */ beqzl $v0,.NB0f0a5858
|
|
/* f0a578c: 27a40104 */ addiu $a0,$sp,0x104
|
|
/* f0a5790: 8c440004 */ lw $a0,0x4($v0)
|
|
/* f0a5794: 00002825 */ or $a1,$zero,$zero
|
|
/* f0a5798: 84990010 */ lh $t9,0x10($a0)
|
|
/* f0a579c: 5b20002e */ blezl $t9,.NB0f0a5858
|
|
/* f0a57a0: 27a40104 */ addiu $a0,$sp,0x104
|
|
/* f0a57a4: 8e2c0034 */ lw $t4,0x34($s1)
|
|
.NB0f0a57a8:
|
|
/* f0a57a8: 8c8f000c */ lw $t7,0xc($a0)
|
|
/* f0a57ac: 00054880 */ sll $t1,$a1,0x2
|
|
/* f0a57b0: 01920019 */ multu $t4,$s2
|
|
/* f0a57b4: 01254823 */ subu $t1,$t1,$a1
|
|
/* f0a57b8: 00094880 */ sll $t1,$t1,0x2
|
|
/* f0a57bc: 01e91021 */ addu $v0,$t7,$t1
|
|
/* f0a57c0: 844e000a */ lh $t6,0xa($v0)
|
|
/* f0a57c4: 00056880 */ sll $t5,$a1,0x2
|
|
/* f0a57c8: 01a56823 */ subu $t5,$t5,$a1
|
|
/* f0a57cc: 000d6880 */ sll $t5,$t5,0x2
|
|
/* f0a57d0: 24420002 */ addiu $v0,$v0,0x2
|
|
/* f0a57d4: 00004012 */ mflo $t0
|
|
/* f0a57d8: 01c85023 */ subu $t2,$t6,$t0
|
|
/* f0a57dc: a44a0008 */ sh $t2,0x8($v0)
|
|
/* f0a57e0: 8c8b000c */ lw $t3,0xc($a0)
|
|
/* f0a57e4: 016dc021 */ addu $t8,$t3,$t5
|
|
/* f0a57e8: 8719000a */ lh $t9,0xa($t8)
|
|
/* f0a57ec: 2b21a000 */ slti $at,$t9,-24576
|
|
/* f0a57f0: 50200014 */ beqzl $at,.NB0f0a5844
|
|
/* f0a57f4: 848b0010 */ lh $t3,0x10($a0)
|
|
/* f0a57f8: 848f0010 */ lh $t7,0x10($a0)
|
|
/* f0a57fc: 00001825 */ or $v1,$zero,$zero
|
|
/* f0a5800: 59e00010 */ blezl $t7,.NB0f0a5844
|
|
/* f0a5804: 848b0010 */ lh $t3,0x10($a0)
|
|
/* f0a5808: 8c89000c */ lw $t1,0xc($a0)
|
|
.NB0f0a580c:
|
|
/* f0a580c: 00036080 */ sll $t4,$v1,0x2
|
|
/* f0a5810: 01836023 */ subu $t4,$t4,$v1
|
|
/* f0a5814: 000c6080 */ sll $t4,$t4,0x2
|
|
/* f0a5818: 012c1021 */ addu $v0,$t1,$t4
|
|
/* f0a581c: 844e000a */ lh $t6,0xa($v0)
|
|
/* f0a5820: 24630001 */ addiu $v1,$v1,0x1
|
|
/* f0a5824: 24420002 */ addiu $v0,$v0,0x2
|
|
/* f0a5828: 25c82000 */ addiu $t0,$t6,0x2000
|
|
/* f0a582c: a4480008 */ sh $t0,0x8($v0)
|
|
/* f0a5830: 848a0010 */ lh $t2,0x10($a0)
|
|
/* f0a5834: 006a082a */ slt $at,$v1,$t2
|
|
/* f0a5838: 5420fff4 */ bnezl $at,.NB0f0a580c
|
|
/* f0a583c: 8c89000c */ lw $t1,0xc($a0)
|
|
/* f0a5840: 848b0010 */ lh $t3,0x10($a0)
|
|
.NB0f0a5844:
|
|
/* f0a5844: 24a50001 */ addiu $a1,$a1,0x1
|
|
/* f0a5848: 00ab082a */ slt $at,$a1,$t3
|
|
/* f0a584c: 5420ffd6 */ bnezl $at,.NB0f0a57a8
|
|
/* f0a5850: 8e2c0034 */ lw $t4,0x34($s1)
|
|
.NB0f0a5854:
|
|
/* f0a5854: 27a40104 */ addiu $a0,$sp,0x104
|
|
.NB0f0a5858:
|
|
/* f0a5858: 0c008be3 */ jal modelRender
|
|
/* f0a585c: 8fa50038 */ lw $a1,0x38($sp)
|
|
/* f0a5860: 8e6d1594 */ lw $t5,0x1594($s3)
|
|
/* f0a5864: 3c188007 */ lui $t8,%hi(var800702dc)
|
|
/* f0a5868: 51a00013 */ beqzl $t5,.NB0f0a58b8
|
|
/* f0a586c: 8fa90110 */ lw $t1,0x110($sp)
|
|
/* f0a5870: 8f18299c */ lw $t8,%lo(var800702dc)($t8)
|
|
/* f0a5874: 8fb90138 */ lw $t9,0x138($sp)
|
|
/* f0a5878: 5300000f */ beqzl $t8,.NB0f0a58b8
|
|
/* f0a587c: 8fa90110 */ lw $t1,0x110($sp)
|
|
/* f0a5880: afb90078 */ sw $t9,0x78($sp)
|
|
/* f0a5884: 8e0f0390 */ lw $t7,0x390($s0)
|
|
/* f0a5888: 26050534 */ addiu $a1,$s0,0x534
|
|
/* f0a588c: 00a02025 */ or $a0,$a1,$zero
|
|
/* f0a5890: ae0f0540 */ sw $t7,0x540($s0)
|
|
/* f0a5894: 0c007728 */ jal modelUpdateRelations
|
|
/* f0a5898: afa50050 */ sw $a1,0x50($sp)
|
|
/* f0a589c: 8fa50050 */ lw $a1,0x50($sp)
|
|
/* f0a58a0: afb50138 */ sw $s5,0x138($sp)
|
|
/* f0a58a4: 0c008be3 */ jal modelRender
|
|
/* f0a58a8: 27a40104 */ addiu $a0,$sp,0x104
|
|
/* f0a58ac: 8fa40078 */ lw $a0,0x78($sp)
|
|
/* f0a58b0: afa40138 */ sw $a0,0x138($sp)
|
|
/* f0a58b4: 8fa90110 */ lw $t1,0x110($sp)
|
|
.NB0f0a58b8:
|
|
/* f0a58b8: 8fa400e4 */ lw $a0,0xe4($sp)
|
|
/* f0a58bc: 24050020 */ addiu $a1,$zero,0x20
|
|
/* f0a58c0: 0fc2bd48 */ jal weaponHasFlag
|
|
/* f0a58c4: afa90144 */ sw $t1,0x144($sp)
|
|
/* f0a58c8: 10400007 */ beqz $v0,.NB0f0a58e8
|
|
/* f0a58cc: 8fac0144 */ lw $t4,0x144($sp)
|
|
/* f0a58d0: 258e0008 */ addiu $t6,$t4,0x8
|
|
/* f0a58d4: afae0144 */ sw $t6,0x144($sp)
|
|
/* f0a58d8: 3c08b600 */ lui $t0,0xb600
|
|
/* f0a58dc: 240a3000 */ addiu $t2,$zero,0x3000
|
|
/* f0a58e0: ad8a0004 */ sw $t2,0x4($t4)
|
|
/* f0a58e4: ad880000 */ sw $t0,0x0($t4)
|
|
.NB0f0a58e8:
|
|
/* f0a58e8: 8e0b038c */ lw $t3,0x38c($s0)
|
|
/* f0a58ec: 8e040390 */ lw $a0,0x390($s0)
|
|
/* f0a58f0: 0fc303f0 */ jal mtxF2LBulk
|
|
/* f0a58f4: 8565000e */ lh $a1,0xe($t3)
|
|
/* f0a58f8: 0c005dc5 */ jal mtx00016784
|
|
/* f0a58fc: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a5900: 8fad0144 */ lw $t5,0x144($sp)
|
|
/* f0a5904: 3c19bc00 */ lui $t9,0xbc00
|
|
/* f0a5908: 3739000e */ ori $t9,$t9,0xe
|
|
/* f0a590c: 25b80008 */ addiu $t8,$t5,0x8
|
|
/* f0a5910: afb80144 */ sw $t8,0x144($sp)
|
|
/* f0a5914: adb90000 */ sw $t9,0x0($t5)
|
|
/* f0a5918: 0c002b3b */ jal viGetPerspScale
|
|
/* f0a591c: afad0070 */ sw $t5,0x70($sp)
|
|
/* f0a5920: 8fa30070 */ lw $v1,0x70($sp)
|
|
/* f0a5924: ac620004 */ sw $v0,0x4($v1)
|
|
.NB0f0a5928:
|
|
/* f0a5928: 26940001 */ addiu $s4,$s4,0x1
|
|
/* f0a592c: 24010002 */ addiu $at,$zero,0x2
|
|
/* f0a5930: 1681fe0c */ bne $s4,$at,.NB0f0a5164
|
|
/* f0a5934: 261007a4 */ addiu $s0,$s0,0x7a4
|
|
/* f0a5938: afb500dc */ sw $s5,0xdc($sp)
|
|
/* f0a593c: 0fc2b250 */ jal casingsRender
|
|
/* f0a5940: 27a40144 */ addiu $a0,$sp,0x144
|
|
/* f0a5944: 0fc5c3ce */ jal mblur0f176298
|
|
/* f0a5948: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a594c: 0fc5c3d3 */ jal mblur0f1762ac
|
|
/* f0a5950: 8fa40144 */ lw $a0,0x144($sp)
|
|
/* f0a5954: afa20144 */ sw $v0,0x144($sp)
|
|
/* f0a5958: 0c002cd4 */ jal vi0000b1d0
|
|
/* f0a595c: 00402025 */ or $a0,$v0,$zero
|
|
/* f0a5960: 244f0008 */ addiu $t7,$v0,0x8
|
|
/* f0a5964: afaf0144 */ sw $t7,0x144($sp)
|
|
/* f0a5968: 0c002fb5 */ jal viGetViewLeft
|
|
/* f0a596c: 00408825 */ or $s1,$v0,$zero
|
|
/* f0a5970: 00028400 */ sll $s0,$v0,0x10
|
|
/* f0a5974: 00104c03 */ sra $t1,$s0,0x10
|
|
/* f0a5978: 0c002fb9 */ jal viGetViewTop
|
|
/* f0a597c: 01208025 */ or $s0,$t1,$zero
|
|
/* f0a5980: 44824000 */ mtc1 $v0,$f8
|
|
/* f0a5984: 44902000 */ mtc1 $s0,$f4
|
|
/* f0a5988: 3c014080 */ lui $at,0x4080
|
|
/* f0a598c: 468042a0 */ cvt.s.w $f10,$f8
|
|
/* f0a5990: 44810000 */ mtc1 $at,$f0
|
|
/* f0a5994: 3c01ed00 */ lui $at,0xed00
|
|
/* f0a5998: 468021a0 */ cvt.s.w $f6,$f4
|
|
/* f0a599c: 46005402 */ mul.s $f16,$f10,$f0
|
|
/* f0a59a0: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a59a4: 46003202 */ mul.s $f8,$f6,$f0
|
|
/* f0a59a8: 4600848d */ trunc.w.s $f18,$f16
|
|
/* f0a59ac: 4600428d */ trunc.w.s $f10,$f8
|
|
/* f0a59b0: 440e9000 */ mfc1 $t6,$f18
|
|
/* f0a59b4: 440d5000 */ mfc1 $t5,$f10
|
|
/* f0a59b8: 31c80fff */ andi $t0,$t6,0xfff
|
|
/* f0a59bc: 01015025 */ or $t2,$t0,$at
|
|
/* f0a59c0: 31b80fff */ andi $t8,$t5,0xfff
|
|
/* f0a59c4: 0018cb00 */ sll $t9,$t8,0xc
|
|
/* f0a59c8: 01597825 */ or $t7,$t2,$t9
|
|
/* f0a59cc: 0c002f97 */ jal viGetViewWidth
|
|
/* f0a59d0: ae2f0000 */ sw $t7,0x0($s1)
|
|
/* f0a59d4: 00029400 */ sll $s2,$v0,0x10
|
|
/* f0a59d8: 00124c03 */ sra $t1,$s2,0x10
|
|
/* f0a59dc: 0c002fb5 */ jal viGetViewLeft
|
|
/* f0a59e0: 01209025 */ or $s2,$t1,$zero
|
|
/* f0a59e4: 0002a400 */ sll $s4,$v0,0x10
|
|
/* f0a59e8: 00146403 */ sra $t4,$s4,0x10
|
|
/* f0a59ec: 0c002fb9 */ jal viGetViewTop
|
|
/* f0a59f0: 0180a025 */ or $s4,$t4,$zero
|
|
/* f0a59f4: 00028400 */ sll $s0,$v0,0x10
|
|
/* f0a59f8: 00107403 */ sra $t6,$s0,0x10
|
|
/* f0a59fc: 0c002f9b */ jal viGetViewHeight
|
|
/* f0a5a00: 01c08025 */ or $s0,$t6,$zero
|
|
/* f0a5a04: 00504021 */ addu $t0,$v0,$s0
|
|
/* f0a5a08: 44888000 */ mtc1 $t0,$f16
|
|
/* f0a5a0c: 02925021 */ addu $t2,$s4,$s2
|
|
/* f0a5a10: 448a5000 */ mtc1 $t2,$f10
|
|
/* f0a5a14: 468084a0 */ cvt.s.w $f18,$f16
|
|
/* f0a5a18: 3c014080 */ lui $at,0x4080
|
|
/* f0a5a1c: 44812000 */ mtc1 $at,$f4
|
|
/* f0a5a20: 46805420 */ cvt.s.w $f16,$f10
|
|
/* f0a5a24: 46049182 */ mul.s $f6,$f18,$f4
|
|
/* f0a5a28: 44819000 */ mtc1 $at,$f18
|
|
/* f0a5a2c: 00000000 */ sll $zero,$zero,0x0
|
|
/* f0a5a30: 46128102 */ mul.s $f4,$f16,$f18
|
|
/* f0a5a34: 4600320d */ trunc.w.s $f8,$f6
|
|
/* f0a5a38: 4600218d */ trunc.w.s $f6,$f4
|
|
/* f0a5a3c: 440d4000 */ mfc1 $t5,$f8
|
|
/* f0a5a40: 440f3000 */ mfc1 $t7,$f6
|
|
/* f0a5a44: 31b80fff */ andi $t8,$t5,0xfff
|
|
/* f0a5a48: 31e90fff */ andi $t1,$t7,0xfff
|
|
/* f0a5a4c: 00096300 */ sll $t4,$t1,0xc
|
|
/* f0a5a50: 030c7025 */ or $t6,$t8,$t4
|
|
/* f0a5a54: ae2e0004 */ sw $t6,0x4($s1)
|
|
/* f0a5a58: 8fab0148 */ lw $t3,0x148($sp)
|
|
/* f0a5a5c: 8fa80144 */ lw $t0,0x144($sp)
|
|
/* f0a5a60: ad680000 */ sw $t0,0x0($t3)
|
|
/* f0a5a64: 8fbf0034 */ lw $ra,0x34($sp)
|
|
.NB0f0a5a68:
|
|
/* f0a5a68: 8fb0001c */ lw $s0,0x1c($sp)
|
|
/* f0a5a6c: 8fb10020 */ lw $s1,0x20($sp)
|
|
/* f0a5a70: 8fb20024 */ lw $s2,0x24($sp)
|
|
/* f0a5a74: 8fb30028 */ lw $s3,0x28($sp)
|
|
/* f0a5a78: 8fb4002c */ lw $s4,0x2c($sp)
|
|
/* f0a5a7c: 8fb50030 */ lw $s5,0x30($sp)
|
|
/* f0a5a80: 03e00008 */ jr $ra
|
|
/* f0a5a84: 27bd0148 */ addiu $sp,$sp,0x148
|
|
);
|
|
#endif
|
|
#else
|
|
// Mismatch: Goal uses different codegen for accessing vertices
|
|
void bgunRender(Gfx **gdlptr)
|
|
{
|
|
Gfx *gdl = *gdlptr;
|
|
struct modelrenderdata renderdata = {NULL, true, 3}; // 10c
|
|
struct player *player;
|
|
s32 i;
|
|
|
|
static bool renderhand = true; // var800702dc
|
|
|
|
player = g_Vars.currentplayer;
|
|
|
|
if (player->visionmode == VISIONMODE_XRAY) {
|
|
for (i = 0; i < 2; i++) {
|
|
if (g_Vars.currentplayer->hands[i].firedrocket) {
|
|
g_Vars.currentplayer->hands[i].rocket = NULL;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
gdl = mblurRender(gdl);
|
|
gdl = vi0000b280(gdl);
|
|
gdl = vi0000b1d0(gdl);
|
|
|
|
gDPSetScissor(gdl++, G_SC_NON_INTERLACE, viGetViewLeft(), viGetViewTop(),
|
|
viGetViewLeft() + viGetViewWidth(), viGetViewTop() + viGetViewHeight());
|
|
|
|
gdl = vi0000aca4(gdl, 1.5, 1000);
|
|
|
|
if (g_Vars.currentplayer->teleportstate != TELEPORTSTATE_INACTIVE) {
|
|
f32 f2;
|
|
|
|
if (optionsGetScreenRatio() == SCREENRATIO_16_9) {
|
|
f2 = player0f0bd358() * 1.3333334f;
|
|
} else {
|
|
f2 = player0f0bd358();
|
|
}
|
|
|
|
gdl = vi0000b0e8(gdl, 60, f2);
|
|
}
|
|
|
|
if (PLAYERCOUNT() == 1 && IS8MB()) {
|
|
gdl = lasersightRenderBeam(gdl);
|
|
}
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
struct hand *hand;
|
|
s32 j;
|
|
s32 alpha;
|
|
s32 weaponnum; // ec
|
|
struct modelnode *node; // e8
|
|
u32 colour; // e4
|
|
|
|
hand = player->hands + i;
|
|
|
|
weaponnum = bgunGetWeaponNum2(i);
|
|
|
|
if (hand->visible) {
|
|
gdl = beamRender(gdl, &hand->beam, 0, 0);
|
|
|
|
if (weaponHasFlag(hand->gset.weaponnum, WEAPONFLAG_00008000)) {
|
|
gSPSetLights1(gdl++, var80070090);
|
|
gSPLookAt(gdl++, camGetLookAt());
|
|
}
|
|
|
|
gSPPerspNormalize(gdl++, mtx00016dcc(0, 300));
|
|
|
|
// There is support for guns having a TV screen on them
|
|
// but no guns have this model part so it's not used.
|
|
node = modelGetPart(hand->gunmodel.definition, MODELPART_0010);
|
|
|
|
if (node) {
|
|
union modelrwdata *rwdata = modelGetNodeRwData(&hand->gunmodel, modelGetPart(hand->gunmodel.definition, MODELPART_0011));
|
|
|
|
if (rwdata) {
|
|
rwdata->toggle.visible = true;
|
|
}
|
|
|
|
gdl = tvscreenRender(&hand->gunmodel, node, &var8009cf88, gdl, 0, 1);
|
|
}
|
|
|
|
renderdata.gdl = gdl;
|
|
renderdata.unk30 = 4;
|
|
|
|
if (USINGDEVICE(DEVICE_NIGHTVISION) || USINGDEVICE(DEVICE_IRSCANNER)) {
|
|
// 67c
|
|
u8 *col = player->gunshadecol;
|
|
u32 shade;
|
|
s32 spb0[4];
|
|
s32 spa0[4];
|
|
|
|
if (col[0] > col[1] && col[0] > col[2]) {
|
|
shade = col[0];
|
|
} else if (col[1] > col[2]) {
|
|
shade = col[1];
|
|
} else {
|
|
shade = col[2];
|
|
}
|
|
|
|
renderdata.envcolour = (shade << 24 | shade << 16 | shade << 8) + col[3];
|
|
|
|
if (USINGDEVICE(DEVICE_NIGHTVISION)) {
|
|
spb0[0] = var8009caef;
|
|
spb0[1] = var8009caef;
|
|
spb0[2] = var8009caef;
|
|
spb0[3] = var8009caf0;
|
|
|
|
colour = (spb0[0] << 24 | spb0[1] << 16 | spb0[2] << 8) + spb0[3];
|
|
} else if (USINGDEVICE(DEVICE_IRSCANNER)) {
|
|
spa0[0] = 0xff;
|
|
spa0[1] = 0;
|
|
spa0[2] = 0;
|
|
spa0[3] = 0x80;
|
|
|
|
colour = (spa0[0] << 24 | spa0[1] << 16 | spa0[2] << 8) + spa0[3];
|
|
}
|
|
|
|
if (weaponnum == WEAPON_UNARMED) {
|
|
renderdata.envcolour = colour;
|
|
}
|
|
} else {
|
|
renderdata.envcolour = player->gunshadecol[0] << 24 | player->gunshadecol[1] << 16 | player->gunshadecol[2] << 8 | player->gunshadecol[3];
|
|
colour = renderdata.envcolour;
|
|
|
|
// 838
|
|
if (hand->gset.weaponnum == WEAPON_MAULER) {
|
|
u32 weight = hand->matmot1 * 50.0f;
|
|
renderdata.envcolour = colourBlend(0xff00007f, renderdata.envcolour, weight);
|
|
}
|
|
}
|
|
|
|
// Apply transparency based on player's cloak
|
|
alpha = chrGetCloakAlpha(player->prop->chr);
|
|
|
|
if (alpha < 255) {
|
|
colour = (s32) (alpha * 0.74509805f) + 0x41;
|
|
renderdata.unk30 = 5;
|
|
renderdata.fogcolour = renderdata.envcolour;
|
|
renderdata.envcolour = colour;
|
|
}
|
|
|
|
renderdata.zbufferenabled = true;
|
|
|
|
mtx00016760();
|
|
|
|
// Render rocket launcher's rocket if it's in Jo's hand or in the launcher
|
|
if (hand->rocket) {
|
|
struct model *rocketmodel = hand->rocket->base.model; // 98
|
|
bool sp94 = false;
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
if (rocketmodel && rocketmodel->definition) {
|
|
sp94 = true;
|
|
|
|
modelRender(&renderdata, rocketmodel);
|
|
|
|
mtxF2LBulk(rocketmodel->matrices, rocketmodel->definition->nummatrices);
|
|
|
|
if (hand->firedrocket) {
|
|
hand->rocket = NULL;
|
|
}
|
|
}
|
|
|
|
if (sp94);
|
|
#else
|
|
modelRender(&renderdata, rocketmodel);
|
|
|
|
mtxF2LBulk(rocketmodel->matrices, rocketmodel->definition->nummatrices);
|
|
|
|
if (hand->firedrocket) {
|
|
hand->rocket = NULL;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (weaponHasFlag(weaponnum, WEAPONFLAG_DUALFLIP)) {
|
|
gSPClearGeometryMode(renderdata.gdl++, G_CULL_BOTH);
|
|
|
|
if (i == HAND_RIGHT) {
|
|
renderdata.cullmode = CULLMODE_BACK;
|
|
} else {
|
|
renderdata.cullmode = CULLMODE_FRONT;
|
|
}
|
|
}
|
|
|
|
// Slide the laser's liquid texture
|
|
if (PLAYERCOUNT() == 1) {
|
|
node = modelGetPart(hand->gunmodel.definition, MODELPART_GUN_LASERLIQUID);
|
|
|
|
// a5c
|
|
if (node) {
|
|
struct modelrodata_gundl *rodata;
|
|
rodata = &node->rodata->gundl;
|
|
|
|
for (j = 0; j < rodata->numvertices; j++) {
|
|
// a7c
|
|
s32 stack[2];
|
|
s32 k;
|
|
|
|
(rodata->vertices + j)->t -= g_Vars.lvupdate240 * PALUP(25);
|
|
|
|
if ((rodata->vertices + j)->t < -0x6000) {
|
|
for (k = 0; k < rodata->numvertices; k++) {
|
|
(rodata->vertices + k)->t += 0x2000;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Render the gun
|
|
modelRender(&renderdata, &hand->gunmodel);
|
|
|
|
// Render the hand
|
|
if (player->gunctrl.handmodeldef && renderhand) {
|
|
s32 prevcolour = renderdata.envcolour; // 7c
|
|
|
|
hand->handmodel.matrices = hand->gunmodel.matrices;
|
|
|
|
modelUpdateRelations(&hand->handmodel);
|
|
|
|
renderdata.envcolour = colour;
|
|
modelRender(&renderdata, &hand->handmodel);
|
|
renderdata.envcolour = prevcolour;
|
|
}
|
|
|
|
// Clean up
|
|
gdl = renderdata.gdl;
|
|
|
|
if (weaponHasFlag(weaponnum, WEAPONFLAG_DUALFLIP)) {
|
|
gSPClearGeometryMode(gdl++, G_CULL_BOTH);
|
|
}
|
|
|
|
mtxF2LBulk(hand->gunmodel.matrices, hand->gunmodel.definition->nummatrices);
|
|
mtx00016784();
|
|
|
|
gSPPerspNormalize(gdl++, viGetPerspScale());
|
|
}
|
|
}
|
|
|
|
casingsRender(&gdl);
|
|
mblur0f176298();
|
|
|
|
gdl = mblur0f1762ac(gdl);
|
|
gdl = vi0000b1d0(gdl);
|
|
|
|
gDPSetScissor(gdl++, G_SC_NON_INTERLACE, viGetViewLeft(), viGetViewTop(),
|
|
viGetViewLeft() + viGetViewWidth(), viGetViewTop() + viGetViewHeight());
|
|
|
|
*gdlptr = gdl;
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* Find and return an available audio handle out of a pool of four.
|
|
*/
|
|
struct sndstate **bgunAllocateAudioHandle(void)
|
|
{
|
|
s32 i;
|
|
|
|
for (i = 0; i < ARRAYCOUNT(g_BgunAudioHandles); i++) {
|
|
if (g_BgunAudioHandles[i] == NULL) {
|
|
return &g_BgunAudioHandles[i];
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void bgunPlayPropHitSound(struct gset *gset, struct prop *prop, s32 texturenum)
|
|
{
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
u32 rand1 = random();
|
|
u32 rand2 = random();
|
|
struct sndstate **handle;
|
|
|
|
if (g_Vars.lvupdate240 <= 0) {
|
|
return;
|
|
}
|
|
|
|
if (texturenum >= 0 && texturenum < NUM_TEXTURES
|
|
&& g_SurfaceTypes[g_Textures[texturenum].soundsurfacetype]->numsounds == 0) {
|
|
return;
|
|
}
|
|
|
|
if (gset->weaponnum == WEAPON_REMOTEMINE
|
|
|| gset->weaponnum == WEAPON_PROXIMITYMINE
|
|
|| gset->weaponnum == WEAPON_TIMEDMINE
|
|
|| gset->weaponnum == WEAPON_COMMSRIDER
|
|
|| gset->weaponnum == WEAPON_TRACERBUG
|
|
|| gset->weaponnum == WEAPON_TARGETAMPLIFIER
|
|
|| gset->weaponnum == WEAPON_ECMMINE) {
|
|
propsnd0f0939f8(NULL, prop, SFX_80AA, -1, -1, 0, 0, 0, NULL, -1, NULL, -1, -1, -1, -1);
|
|
return;
|
|
}
|
|
|
|
handle = bgunAllocateAudioHandle();
|
|
|
|
if (handle) {
|
|
if (prop->type == PROPTYPE_CHR || prop->type == PROPTYPE_PLAYER) {
|
|
struct chrdata *chr = prop->chr;
|
|
s16 soundnum = -1;
|
|
bool overridden = false;
|
|
s32 spac;
|
|
s32 spa8;
|
|
|
|
if (chrGetShield(chr) > 0) {
|
|
soundnum = SFX_SHIELD_DAMAGE;
|
|
} else if (gset->weaponnum == WEAPON_COMBATKNIFE
|
|
|| gset->weaponnum == WEAPON_COMBATKNIFE // duplicate
|
|
|| gset->weaponnum == WEAPON_BOLT) {
|
|
soundnum = SFX_05F6;
|
|
overridden = true;
|
|
} else if (gset->weaponnum == WEAPON_UNARMED
|
|
|| (gset->weaponfunc == FUNC_SECONDARY
|
|
&& (gset->weaponnum == WEAPON_FALCON2
|
|
|| gset->weaponnum == WEAPON_FALCON2_SILENCER
|
|
|| gset->weaponnum == WEAPON_FALCON2_SCOPE
|
|
|| gset->weaponnum == WEAPON_DY357MAGNUM
|
|
|| gset->weaponnum == WEAPON_DY357LX))) {
|
|
s16 sounds[] = { SFX_002F, SFX_0030, SFX_0031 };
|
|
soundnum = sounds[rand1 % ARRAYCOUNT(sounds)];
|
|
} else {
|
|
s16 sounds[] = { SFX_HIT_CHR, SFX_HIT_CHR };
|
|
soundnum = sounds[rand1 % ARRAYCOUNT(sounds)];
|
|
}
|
|
|
|
if (soundnum != -1) {
|
|
propsnd0f094ef4(&prop->pos, prop->rooms, soundnum, &spac, &spa8);
|
|
|
|
if (spac) {
|
|
sndStart(var80095200, soundnum, handle, -1, -1, -1, -1, -1);
|
|
|
|
if (*handle) {
|
|
sndAdjust(handle, 0, spac, spa8, soundnum, 1, 1, -1, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (overridden) {
|
|
return;
|
|
}
|
|
} else {
|
|
s16 soundnum = -1;
|
|
bool overridden = false;
|
|
s32 sp90;
|
|
s32 sp8c;
|
|
u32 stack;
|
|
|
|
if (texturenum == 10000) {
|
|
soundnum = SFX_SHIELD_DAMAGE;
|
|
} else if (gset->weaponnum == WEAPON_LASER) {
|
|
if (gset->weaponfunc == FUNC_PRIMARY || ((gset->unk063a % 4) == 0 && (random() % 2))) {
|
|
if ((random() % 2) == 0) {
|
|
soundnum = SFX_CLOAK_ON;
|
|
} else {
|
|
soundnum = SFX_CLOAK_OFF;
|
|
}
|
|
}
|
|
|
|
overridden = true;
|
|
} else {
|
|
if (gset->weaponnum == WEAPON_COMBATKNIFE || gset->weaponnum == WEAPON_BOLT) {
|
|
soundnum = SFX_HIT_METAL_8079;
|
|
overridden = true;
|
|
} else {
|
|
s16 sounds[] = {
|
|
SFX_001B, SFX_001C, SFX_001D, SFX_001E,
|
|
SFX_001B, SFX_001C, SFX_001D, SFX_001E,
|
|
SFX_001B, SFX_001C, SFX_001D, SFX_001E,
|
|
SFX_0023, SFX_0024, SFX_0025, SFX_0026,
|
|
SFX_0027, SFX_0028, SFX_0029, SFX_002A,
|
|
};
|
|
|
|
soundnum = sounds[rand1 % ARRAYCOUNT(sounds)];
|
|
}
|
|
}
|
|
|
|
if (soundnum != -1) {
|
|
propsnd0f094ef4(&prop->pos, prop->rooms, soundnum, &sp90, &sp8c);
|
|
|
|
if (sp90) {
|
|
sndStart(var80095200, soundnum, handle, -1, -1, -1, -1, -1);
|
|
|
|
if (*handle) {
|
|
sndAdjust(handle, 0, sp90, sp8c, soundnum, 1, 1, -1, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (overridden) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (texturenum >= 0 && texturenum < NUM_TEXTURES && g_SurfaceTypes[g_Textures[texturenum].soundsurfacetype]) {
|
|
s16 soundnum = -1;
|
|
|
|
handle = bgunAllocateAudioHandle();
|
|
|
|
if (handle) {
|
|
if (g_SurfaceTypes[g_Textures[texturenum].soundsurfacetype]->numsounds > 0) {
|
|
s32 index = rand2 % g_SurfaceTypes[g_Textures[texturenum].soundsurfacetype]->numsounds;
|
|
soundnum = g_SurfaceTypes[g_Textures[texturenum].soundsurfacetype]->sounds[index];
|
|
|
|
if (soundnum != -1) {
|
|
sndStart(var80095200, soundnum, handle, -1, -1, -1, -1, -1);
|
|
}
|
|
}
|
|
|
|
if (*handle && soundnum != -1) {
|
|
func0f09505c(*handle, &prop->pos, 400, 2500, 3000, prop->rooms, soundnum, 0x7fff, 0);
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
u32 rand1 = random();
|
|
u32 rand2 = random();
|
|
struct sndstate **handle;
|
|
|
|
if (g_Vars.lvupdate240 <= 0) {
|
|
return;
|
|
}
|
|
|
|
if (texturenum >= 0 && texturenum < NUM_TEXTURES
|
|
&& g_SurfaceTypes[g_Textures[texturenum].soundsurfacetype]->numsounds == 0) {
|
|
return;
|
|
}
|
|
|
|
if (gset->weaponnum == WEAPON_REMOTEMINE
|
|
|| gset->weaponnum == WEAPON_PROXIMITYMINE
|
|
|| gset->weaponnum == WEAPON_TIMEDMINE
|
|
|| gset->weaponnum == WEAPON_COMMSRIDER
|
|
|| gset->weaponnum == WEAPON_TRACERBUG
|
|
|| gset->weaponnum == WEAPON_TARGETAMPLIFIER
|
|
|| gset->weaponnum == WEAPON_ECMMINE) {
|
|
propsnd0f0939f8(NULL, prop, SFX_80AA, -1, -1, 0, 0, 0, NULL, -1, NULL, -1, -1, -1, -1);
|
|
return;
|
|
}
|
|
|
|
handle = bgunAllocateAudioHandle();
|
|
|
|
if (handle) {
|
|
if (prop->type == PROPTYPE_CHR || prop->type == PROPTYPE_PLAYER) {
|
|
struct chrdata *chr = prop->chr;
|
|
s16 soundnum;
|
|
bool overridden = false;
|
|
|
|
if (chrGetShield(chr) > 0) {
|
|
sndStart(var80095200, SFX_SHIELD_DAMAGE, handle, -1, -1, -1, -1, -1);
|
|
soundnum = SFX_SHIELD_DAMAGE;
|
|
} else if (gset->weaponnum == WEAPON_COMBATKNIFE
|
|
|| gset->weaponnum == WEAPON_COMBATKNIFE // duplicate
|
|
|| gset->weaponnum == WEAPON_BOLT) {
|
|
sndStart(var80095200, SFX_05F6, handle, -1, -1, -1, -1, -1);
|
|
soundnum = SFX_05F6;
|
|
overridden = true;
|
|
} else if (gset->weaponnum == WEAPON_UNARMED
|
|
|| (gset->weaponfunc == FUNC_SECONDARY
|
|
&& (gset->weaponnum == WEAPON_FALCON2
|
|
|| gset->weaponnum == WEAPON_FALCON2_SILENCER
|
|
|| gset->weaponnum == WEAPON_FALCON2_SCOPE
|
|
|| gset->weaponnum == WEAPON_DY357MAGNUM
|
|
|| gset->weaponnum == WEAPON_DY357LX))) {
|
|
s16 sounds[] = { SFX_002F, SFX_0030, SFX_0031 };
|
|
soundnum = sounds[rand1 % ARRAYCOUNT(sounds)];
|
|
sndStart(var80095200, soundnum, handle, -1, -1, -1, -1, -1);
|
|
} else {
|
|
s16 sounds[] = { SFX_HIT_CHR, SFX_HIT_CHR };
|
|
soundnum = sounds[rand1 % ARRAYCOUNT(sounds)];
|
|
sndStart(var80095200, soundnum, handle, -1, -1, -1, -1, -1);
|
|
}
|
|
|
|
if (*handle) {
|
|
func0f09505c(*handle, &prop->pos, 400, 2500, 3000, prop->rooms, soundnum, 0x7fff, 0);
|
|
}
|
|
|
|
if (overridden) {
|
|
return;
|
|
}
|
|
} else {
|
|
s16 soundnum;
|
|
bool overridden = false;
|
|
u32 stack;
|
|
|
|
if (texturenum == 10000) {
|
|
sndStart(var80095200, SFX_SHIELD_DAMAGE, handle, -1, -1, -1, -1, -1);
|
|
soundnum = SFX_SHIELD_DAMAGE;
|
|
} else if (gset->weaponnum == WEAPON_LASER) {
|
|
if (gset->weaponfunc == FUNC_PRIMARY || (gset->unk063a % 8) == 0) {
|
|
if ((random() % 2) == 0) {
|
|
soundnum = SFX_CLOAK_ON;
|
|
} else {
|
|
soundnum = SFX_CLOAK_OFF;
|
|
}
|
|
|
|
sndStart(var80095200, soundnum, handle, -1, -1, -1, -1, -1);
|
|
overridden = true;
|
|
}
|
|
} else {
|
|
if (gset->weaponnum == WEAPON_COMBATKNIFE || gset->weaponnum == WEAPON_BOLT) {
|
|
soundnum = SFX_HIT_METAL_8079;
|
|
sndStart(var80095200, soundnum, handle, -1, -1, -1, -1, -1);
|
|
overridden = true;
|
|
} else {
|
|
s16 sounds[] = {
|
|
SFX_001B, SFX_001C, SFX_001D, SFX_001E,
|
|
SFX_001B, SFX_001C, SFX_001D, SFX_001E,
|
|
SFX_001B, SFX_001C, SFX_001D, SFX_001E,
|
|
SFX_0023, SFX_0024, SFX_0025, SFX_0026,
|
|
SFX_0027, SFX_0028, SFX_0029, SFX_002A,
|
|
};
|
|
|
|
soundnum = sounds[rand1 % ARRAYCOUNT(sounds)];
|
|
sndStart(var80095200, soundnum, handle, -1, -1, -1, -1, -1);
|
|
}
|
|
}
|
|
|
|
if (*handle) {
|
|
func0f09505c(*handle, &prop->pos, 400, 2500, 3000, prop->rooms, soundnum, 0x7fff, 0);
|
|
}
|
|
|
|
if (overridden) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (texturenum >= 0 && texturenum < NUM_TEXTURES && g_SurfaceTypes[g_Textures[texturenum].soundsurfacetype]) {
|
|
s16 soundnum = -1;
|
|
|
|
handle = bgunAllocateAudioHandle();
|
|
|
|
if (handle) {
|
|
if (g_SurfaceTypes[g_Textures[texturenum].soundsurfacetype]->numsounds > 0) {
|
|
s32 index = rand2 % g_SurfaceTypes[g_Textures[texturenum].soundsurfacetype]->numsounds;
|
|
soundnum = g_SurfaceTypes[g_Textures[texturenum].soundsurfacetype]->sounds[index];
|
|
|
|
sndStart(var80095200, soundnum, handle, -1, -1, -1, -1, -1);
|
|
}
|
|
|
|
if (*handle) {
|
|
func0f09505c(*handle, &prop->pos, 400, 2500, 3000, prop->rooms, soundnum, 0x7fff, 0);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void bgunPlayGlassHitSound(struct coord *pos, s16 *rooms, s32 texturenum)
|
|
{
|
|
if (g_Vars.lvupdate240 > 0) {
|
|
struct sndstate **handle = bgunAllocateAudioHandle();
|
|
|
|
if (handle) {
|
|
sndStart(var80095200, SFX_HIT_GLASS, handle, -1, -1, -1, -1, -1);
|
|
|
|
if (*handle) {
|
|
func0f09505c(*handle, pos, 400, 2500, 3000, rooms, SFX_HIT_GLASS, 0x7fff, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void bgunPlayBgHitSound(struct gset *gset, struct coord *arg1, s32 texturenum, s16 *arg3)
|
|
{
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
struct sndstate **handle;
|
|
u32 rand1 = random();
|
|
u32 rand2 = random();
|
|
bool playdefault;
|
|
s16 soundnum;
|
|
bool overridden;
|
|
|
|
if (g_Vars.lvupdate240 <= 0) {
|
|
return;
|
|
}
|
|
|
|
if (texturenum >= 0 && texturenum < NUM_TEXTURES && g_SurfaceTypes[g_Textures[texturenum].soundsurfacetype]->numsounds == 0) {
|
|
return;
|
|
}
|
|
|
|
playdefault = true;
|
|
handle = bgunAllocateAudioHandle();
|
|
|
|
if (handle) {
|
|
soundnum = -1;
|
|
overridden = false;
|
|
|
|
if (gset->weaponnum == WEAPON_LASER) {
|
|
playdefault = false;
|
|
|
|
if (gset->weaponfunc == FUNC_PRIMARY || ((gset->unk063a % 4) == 0 && (random() % 2))) {
|
|
// Laser sounds
|
|
s16 sounds[] = {SFX_CLOAK_ON, SFX_CLOAK_OFF};
|
|
soundnum = sounds[rand1 % ARRAYCOUNT(sounds)];
|
|
sndStart(var80095200, soundnum, handle, -1, -1, -1, -1, -1);
|
|
overridden = true;
|
|
}
|
|
} else if (gset->weaponnum == WEAPON_COMBATKNIFE || gset->weaponnum == WEAPON_BOLT) {
|
|
// Knives and bolts make a metal sound
|
|
soundnum = SFX_HIT_METAL_8079;
|
|
sndStart(var80095200, soundnum, handle, -1, -1, -1, -1, -1);
|
|
overridden = true;
|
|
} else if (gset->weaponnum == WEAPON_REMOTEMINE
|
|
|| gset->weaponnum == WEAPON_PROXIMITYMINE
|
|
|| gset->weaponnum == WEAPON_TIMEDMINE
|
|
|| gset->weaponnum == WEAPON_COMMSRIDER
|
|
|| gset->weaponnum == WEAPON_TRACERBUG
|
|
|| gset->weaponnum == WEAPON_TARGETAMPLIFIER
|
|
|| gset->weaponnum == WEAPON_ECMMINE) {
|
|
// Mine landing/activation sound
|
|
soundnum = SFX_80AA;
|
|
sndStart(var80095200, soundnum, handle, -1, -1, -1, -1, -1);
|
|
overridden = true;
|
|
} else {
|
|
// Ricochet sounds
|
|
s16 sounds[] = {
|
|
SFX_0013, SFX_0014, SFX_0015, SFX_0016,
|
|
SFX_0017, SFX_0018, SFX_0019, SFX_001A,
|
|
SFX_0017, SFX_0018, SFX_0019, SFX_001A,
|
|
SFX_0017, SFX_0018, SFX_0019, SFX_001A,
|
|
SFX_001F, SFX_0020, SFX_0020, SFX_0021,
|
|
SFX_001F, SFX_0020, SFX_0020, SFX_0021,
|
|
SFX_001F, SFX_0020, SFX_0020, SFX_0021,
|
|
SFX_0023, SFX_0024, SFX_0025, SFX_0026,
|
|
SFX_0027, SFX_0028, SFX_0029, SFX_002A,
|
|
};
|
|
|
|
soundnum = sounds[rand1 % ARRAYCOUNT(sounds)];
|
|
sndStart(var80095200, soundnum, handle, -1, -1, -1, -1, -1);
|
|
overridden = false;
|
|
}
|
|
|
|
if (*handle != NULL) {
|
|
func0f09505c(*handle, arg1, 400, 2500, 3000, arg3, soundnum, 0x7fff, 0);
|
|
}
|
|
|
|
if (overridden) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (playdefault) {
|
|
handle = bgunAllocateAudioHandle();
|
|
|
|
if (handle != NULL && texturenum >= 0 && texturenum < NUM_TEXTURES) {
|
|
s16 soundnum;
|
|
struct surfacetype *type = g_SurfaceTypes[g_Textures[texturenum].soundsurfacetype];
|
|
|
|
if (type->numsounds > 0) {
|
|
soundnum = -1;
|
|
|
|
if (type != NULL) {
|
|
s32 index = rand2 % type->numsounds;
|
|
soundnum = type->sounds[index];
|
|
sndStart(var80095200, soundnum, handle, -1, -1, -1, -1, -1);
|
|
}
|
|
|
|
if (*handle != NULL) {
|
|
func0f09505c(*handle, arg1, 400, 2500, 3000, arg3, soundnum, 0x7fff, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
struct sndstate **handle;
|
|
u32 rand1 = random();
|
|
u32 rand2 = random();
|
|
s16 soundnum;
|
|
bool overridden;
|
|
|
|
if (g_Vars.lvupdate240 <= 0) {
|
|
return;
|
|
}
|
|
|
|
if (texturenum >= 0 && texturenum < NUM_TEXTURES && g_SurfaceTypes[g_Textures[texturenum].soundsurfacetype]->numsounds == 0) {
|
|
return;
|
|
}
|
|
|
|
handle = bgunAllocateAudioHandle();
|
|
|
|
if (handle) {
|
|
overridden = false;
|
|
|
|
if (gset->weaponnum == WEAPON_LASER) {
|
|
if (gset->weaponfunc == FUNC_PRIMARY || (gset->unk063a % 8) == 0) {
|
|
// Laser sounds
|
|
s16 sounds[] = {SFX_CLOAK_ON, SFX_CLOAK_OFF};
|
|
soundnum = sounds[rand1 % ARRAYCOUNT(sounds)];
|
|
sndStart(var80095200, soundnum, handle, -1, -1, -1, -1, -1);
|
|
overridden = true;
|
|
}
|
|
} else if (gset->weaponnum == WEAPON_COMBATKNIFE || gset->weaponnum == WEAPON_BOLT) {
|
|
// Knives and bolts make a metal sound
|
|
soundnum = SFX_HIT_METAL_8079;
|
|
sndStart(var80095200, soundnum, handle, -1, -1, -1, -1, -1);
|
|
overridden = true;
|
|
} else if (gset->weaponnum == WEAPON_REMOTEMINE
|
|
|| gset->weaponnum == WEAPON_PROXIMITYMINE
|
|
|| gset->weaponnum == WEAPON_TIMEDMINE
|
|
|| gset->weaponnum == WEAPON_COMMSRIDER
|
|
|| gset->weaponnum == WEAPON_TRACERBUG
|
|
|| gset->weaponnum == WEAPON_TARGETAMPLIFIER
|
|
|| gset->weaponnum == WEAPON_ECMMINE) {
|
|
// Mine landing/activation sound
|
|
sndStart(var80095200, SFX_80AA, handle, -1, -1, -1, -1, -1);
|
|
overridden = true;
|
|
} else {
|
|
// Ricochet sounds
|
|
s16 sounds[] = {
|
|
SFX_0013, SFX_0014, SFX_0015, SFX_0016,
|
|
SFX_0017, SFX_0018, SFX_0019, SFX_001A,
|
|
SFX_0017, SFX_0018, SFX_0019, SFX_001A,
|
|
SFX_0017, SFX_0018, SFX_0019, SFX_001A,
|
|
SFX_001F, SFX_0020, SFX_0020, SFX_0021,
|
|
SFX_001F, SFX_0020, SFX_0020, SFX_0021,
|
|
SFX_001F, SFX_0020, SFX_0020, SFX_0021,
|
|
SFX_0023, SFX_0024, SFX_0025, SFX_0026,
|
|
SFX_0027, SFX_0028, SFX_0029, SFX_002A,
|
|
};
|
|
|
|
soundnum = sounds[rand1 % ARRAYCOUNT(sounds)];
|
|
sndStart(var80095200, soundnum, handle, -1, -1, -1, -1, -1);
|
|
overridden = false;
|
|
}
|
|
|
|
if (*handle != NULL) {
|
|
func0f09505c(*handle, arg1, 400, 2500, 3000, arg3, soundnum, 0x7fff, 0);
|
|
}
|
|
|
|
if (overridden) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Play default surface hit sound
|
|
handle = bgunAllocateAudioHandle();
|
|
|
|
if (handle != NULL && texturenum >= 0 && texturenum < NUM_TEXTURES) {
|
|
s16 soundnum;
|
|
struct surfacetype *type = g_SurfaceTypes[g_Textures[texturenum].soundsurfacetype];
|
|
|
|
if (type->numsounds > 0) {
|
|
soundnum = -1;
|
|
|
|
if (type != NULL) {
|
|
s32 index = rand2 % type->numsounds;
|
|
soundnum = type->sounds[index];
|
|
sndStart(var80095200, soundnum, handle, -1, -1, -1, -1, -1);
|
|
}
|
|
|
|
if (*handle != NULL) {
|
|
func0f09505c(*handle, arg1, 400, 2500, 3000, arg3, soundnum, 0x7fff, 0);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void bgunSetTriggerOn(s32 handnum, bool on)
|
|
{
|
|
struct hand *hand = &g_Vars.currentplayer->hands[handnum];
|
|
|
|
hand->triggerprev = hand->triggeron;
|
|
hand->triggeron = on;
|
|
|
|
if (!on) {
|
|
hand->triggerreleased = true;
|
|
}
|
|
}
|
|
|
|
#define SETFUNCPRI() g_PlayerConfigsArray[g_Vars.currentplayerstats->mpindex].gunfuncs[(g_Vars.currentplayer->gunctrl.weaponnum - 1) >> 3] &= ~(1 << ((g_Vars.currentplayer->gunctrl.weaponnum - 1) & 7))
|
|
#define SETFUNCSEC() g_PlayerConfigsArray[g_Vars.currentplayerstats->mpindex].gunfuncs[(g_Vars.currentplayer->gunctrl.weaponnum - 1) >> 3] |= 1 << ((g_Vars.currentplayer->gunctrl.weaponnum - 1) & 7)
|
|
|
|
/**
|
|
* This is called once B has been held for 25 ticks, or earlier if pressing B+Z.
|
|
*
|
|
* The function may choose whether to change the gun function,
|
|
* or activate the secondary function without switching to it.
|
|
*
|
|
* Return the following;
|
|
* - USETIMER_CONTINUE if the B button timer should continue incrementing.
|
|
* - USETIMER_STOP if the B button timer should stop (ie. the B press is consumed)
|
|
* - USETIMER_REPEAT if this function should be called again on each frame until B is released.
|
|
*/
|
|
s32 bgunConsiderToggleGunFunction(s32 usedowntime, bool trigpressed, bool fromactivemenu)
|
|
{
|
|
switch (bgunGetWeaponNum(HAND_RIGHT)) {
|
|
case WEAPON_SNIPERRIFLE:
|
|
// At 25 ticks (or B+Z), start showing the new function
|
|
g_Vars.currentplayer->gunctrl.invertgunfunc = true;
|
|
|
|
// B+Z immediately triggers crouch or stand
|
|
if (trigpressed) {
|
|
return USETIMER_STOP;
|
|
}
|
|
|
|
// Don't do anything if B hasn't been held for 50/60ths of a second
|
|
if (usedowntime < TICKS(50)) {
|
|
return USETIMER_CONTINUE;
|
|
}
|
|
|
|
if (g_Vars.currentplayer->hands[HAND_RIGHT].gset.weaponfunc != FUNC_SECONDARY) {
|
|
return USETIMER_CONTINUE;
|
|
}
|
|
|
|
// Do crouch or stand
|
|
g_Vars.currentplayer->hands[HAND_RIGHT].activatesecondary = true;
|
|
return USETIMER_REPEAT;
|
|
case WEAPON_RCP120:
|
|
case WEAPON_LAPTOPGUN:
|
|
case WEAPON_DRAGON:
|
|
case WEAPON_REMOTEMINE:
|
|
// These weapons use temporary alt functions
|
|
g_Vars.currentplayer->gunctrl.invertgunfunc = true;
|
|
|
|
if (fromactivemenu && bgunIsUsingSecondaryFunction() == true) {
|
|
g_Vars.currentplayer->hands[HAND_RIGHT].activatesecondary = true;
|
|
}
|
|
|
|
return USETIMER_STOP;
|
|
case WEAPON_MAULER:
|
|
case WEAPON_CMP150:
|
|
case WEAPON_K7AVENGER:
|
|
case WEAPON_AR34:
|
|
case WEAPON_FARSIGHT:
|
|
case WEAPON_TIMEDMINE:
|
|
// These weapons disallow B+Z
|
|
if (!trigpressed) {
|
|
if (VALIDWEAPON()) {
|
|
if (1 - FUNCISSEC()) {
|
|
SETFUNCSEC();
|
|
} else {
|
|
SETFUNCPRI();
|
|
}
|
|
}
|
|
|
|
return USETIMER_STOP;
|
|
}
|
|
|
|
return USETIMER_CONTINUE;
|
|
default:
|
|
if (trigpressed) {
|
|
g_Vars.currentplayer->gunctrl.invertgunfunc = true;
|
|
} else {
|
|
if (VALIDWEAPON()) {
|
|
if (!FUNCISSEC()) {
|
|
SETFUNCSEC();
|
|
} else {
|
|
SETFUNCPRI();
|
|
}
|
|
}
|
|
}
|
|
|
|
return USETIMER_STOP;
|
|
}
|
|
}
|
|
|
|
void bgun0f0a8c50(void)
|
|
{
|
|
if (g_Vars.currentplayer->hands[HAND_RIGHT].activatesecondary == false) {
|
|
g_Vars.currentplayer->gunctrl.invertgunfunc = false;
|
|
}
|
|
}
|
|
|
|
bool bgunIsUsingSecondaryFunction(void)
|
|
{
|
|
struct player *player = g_Vars.currentplayer;
|
|
s32 weaponnum = player->gunctrl.weaponnum;
|
|
|
|
if (weaponnum >= WEAPON_UNARMED && weaponnum <= WEAPON_COMBATBOOST) {
|
|
s32 index = (weaponnum - 1) >> 3;
|
|
s32 value = 1 << ((weaponnum - 1) & 7);
|
|
|
|
if (g_PlayerConfigsArray[g_Vars.currentplayerstats->mpindex].gunfuncs[index] & value) {
|
|
if (player->gunctrl.invertgunfunc == true) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (player->gunctrl.invertgunfunc == true) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Tick gun-related things during first-person gameplay.
|
|
*
|
|
* This function is not called during cutscenes.
|
|
*/
|
|
void bgunTickGameplay(bool triggeron)
|
|
{
|
|
s32 gunsfiring[2] = {false, false};
|
|
struct player *player = g_Vars.currentplayer;
|
|
s32 i;
|
|
|
|
// Remove weapons if in passive mode
|
|
if (g_Vars.currentplayer->gunctrl.passivemode) {
|
|
struct chrdata *chr = g_Vars.currentplayer->prop->chr;
|
|
triggeron = false;
|
|
|
|
if (invGetCount() > 1) {
|
|
invClear();
|
|
invGiveSingleWeapon(WEAPON_UNARMED);
|
|
}
|
|
|
|
if (g_Vars.currentplayer->gunctrl.weaponnum != WEAPON_UNARMED
|
|
&& g_Vars.currentplayer->gunctrl.switchtoweaponnum != WEAPON_UNARMED) {
|
|
bgunEquipWeapon(WEAPON_UNARMED);
|
|
}
|
|
|
|
g_Vars.currentplayer->gunctrl.dualwielding = false;
|
|
g_Vars.currentplayer->devicesactive = 0;
|
|
|
|
chr->cloakpause = 0;
|
|
chr->cloakfadefrac = 0;
|
|
chr->cloakfadefinished = false;
|
|
chr->hidden &= ~CHRHFLAG_CLOAKED;
|
|
}
|
|
|
|
// Remove throwable items from inventory if there's no more left
|
|
for (i = 0; i < invGetCount(); i++) {
|
|
struct weapon *weapon;
|
|
s32 weaponnum = invGetWeaponNumByIndex(i);
|
|
s32 equippedweaponnum;
|
|
|
|
switch (weaponnum) {
|
|
case WEAPON_COMBATKNIFE:
|
|
case WEAPON_GRENADE:
|
|
case WEAPON_NBOMB:
|
|
case WEAPON_COMBATBOOST:
|
|
case WEAPON_CLOAKINGDEVICE:
|
|
case WEAPON_ECMMINE:
|
|
case WEAPON_COMMSRIDER:
|
|
case WEAPON_TRACERBUG:
|
|
case WEAPON_TARGETAMPLIFIER:
|
|
weapon = weaponFindById(weaponnum);
|
|
|
|
if (weapon && weapon->ammos[0]
|
|
&& bgunGetAmmoCount(weapon->ammos[0]->type) == 0) {
|
|
equippedweaponnum = bgunGetWeaponNum(HAND_RIGHT);
|
|
invRemoveItemByNum(weaponnum);
|
|
|
|
if (weaponnum == equippedweaponnum && !invHasSingleWeaponIncAllGuns(weaponnum)) {
|
|
invCalculateCurrentIndex();
|
|
bgunEquipWeapon(invGetWeaponNumByIndex(g_Vars.currentplayer->equipcuritem));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (g_Vars.tickmode == TICKMODE_CUTSCENE) {
|
|
triggeron = false;
|
|
g_Vars.currentplayer->hands[HAND_LEFT].firing = false;
|
|
g_Vars.currentplayer->hands[HAND_RIGHT].firing = false;
|
|
}
|
|
|
|
player->playertriggerprev = player->playertriggeron;
|
|
player->playertriggeron = triggeron;
|
|
|
|
if (triggeron == false && player->playertriggerprev) {
|
|
// Releasing trigger
|
|
player->doautoselect = true;
|
|
}
|
|
|
|
// Handle gun firing - particularly alternating
|
|
// between left and right if dual wielding
|
|
if (player->playertriggeron) {
|
|
player->playertrigtime240 += g_Vars.lvupdate240;
|
|
|
|
if (player->hands[HAND_LEFT].inuse
|
|
&& player->hands[HAND_RIGHT].inuse
|
|
&& player->gunctrl.weaponnum != WEAPON_REMOTEMINE) {
|
|
if (player->playertrigtime240 > TICKS(80)) {
|
|
gunsfiring[player->curguntofire] = 1;
|
|
|
|
if (bgun0f099008(1 - player->curguntofire)
|
|
|| player->hands[1 - player->curguntofire].triggeron) {
|
|
gunsfiring[1 - player->curguntofire] = 1;
|
|
}
|
|
} else {
|
|
if (player->playertriggerprev == false &&
|
|
(bgun0f099008(1 - player->curguntofire) || !bgun0f099008(player->curguntofire))) {
|
|
player->curguntofire = 1 - player->curguntofire;
|
|
}
|
|
|
|
gunsfiring[player->curguntofire] = 1;
|
|
gunsfiring[1 - player->curguntofire] = 0;
|
|
}
|
|
} else {
|
|
if (!player->hands[player->curguntofire].inuse
|
|
&& player->hands[1 - player->curguntofire].inuse) {
|
|
player->curguntofire = 1 - player->curguntofire;
|
|
}
|
|
|
|
if (player->gunctrl.weaponnum == WEAPON_REMOTEMINE) {
|
|
player->curguntofire = 0;
|
|
}
|
|
|
|
gunsfiring[player->curguntofire] = 1;
|
|
gunsfiring[1 - player->curguntofire] = 0;
|
|
}
|
|
} else {
|
|
player->playertrigtime240 = 0;
|
|
}
|
|
|
|
bgunSetTriggerOn(HAND_RIGHT, gunsfiring[0]);
|
|
bgunSetTriggerOn(HAND_LEFT, gunsfiring[1]);
|
|
|
|
if (g_Vars.tickmode == TICKMODE_NORMAL && g_Vars.lvupdate240 > 0) {
|
|
bgunTickHand(HAND_RIGHT);
|
|
bgunTickHand(HAND_LEFT);
|
|
bgunTickSwitch();
|
|
|
|
if (cheatIsActive(CHEAT_UNLIMITEDAMMONORELOADS)) {
|
|
s32 i;
|
|
struct weapon *weapon;
|
|
struct hand *lhand = &g_Vars.currentplayer->hands[HAND_LEFT];
|
|
struct hand *rhand = &g_Vars.currentplayer->hands[HAND_RIGHT];
|
|
|
|
weapon = weaponFindById(rhand->gset.weaponnum);
|
|
|
|
for (i = 0; i != 2; i++) {
|
|
if (weapon && weapon->ammos[i] &&
|
|
bgunAmmotypeAllowsUnlimitedAmmo(weapon->ammos[i]->type)) {
|
|
rhand->loadedammo[i] = rhand->clipsizes[i];
|
|
lhand->loadedammo[i] = lhand->clipsizes[i];
|
|
}
|
|
}
|
|
|
|
bgunGiveMaxAmmo(false);
|
|
} else if (cheatIsActive(CHEAT_UNLIMITEDAMMO)) {
|
|
bgunGiveMaxAmmo(false);
|
|
}
|
|
}
|
|
|
|
bgunDecreaseNoiseRadius();
|
|
|
|
if (player->resetshadecol) {
|
|
propCalculateShadeColour(g_Vars.currentplayer->prop, player->gunshadecol, player->floorcol);
|
|
player->resetshadecol = 0;
|
|
} else {
|
|
u8 shadecol[4];
|
|
propCalculateShadeColour(g_Vars.currentplayer->prop, shadecol, player->floorcol);
|
|
colourTween(player->gunshadecol, shadecol);
|
|
}
|
|
|
|
invIncrementHeldTime(bgunGetWeaponNum(HAND_RIGHT), bgunGetWeaponNum(HAND_LEFT));
|
|
}
|
|
|
|
void bgunSetPassiveMode(bool enable)
|
|
{
|
|
s32 i;
|
|
|
|
for (i = 0; i < PLAYERCOUNT(); i++) {
|
|
g_Vars.players[i]->gunctrl.passivemode = enable;
|
|
}
|
|
}
|
|
|
|
void bgunSetAimType(u32 aimtype)
|
|
{
|
|
g_Vars.currentplayer->aimtype = aimtype;
|
|
}
|
|
|
|
void bgunSetAimPos(struct coord *coord)
|
|
{
|
|
struct player *player = g_Vars.currentplayer;
|
|
|
|
player->hands[HAND_RIGHT].aimpos.x = handGetXShift(HAND_RIGHT) + coord->x;
|
|
player->hands[HAND_RIGHT].aimpos.y = coord->y;
|
|
player->hands[HAND_RIGHT].aimpos.z = coord->z;
|
|
|
|
player->hands[HAND_LEFT].aimpos.x = handGetXShift(HAND_LEFT) + coord->x;
|
|
player->hands[HAND_LEFT].aimpos.y = coord->y;
|
|
player->hands[HAND_LEFT].aimpos.z = coord->z;
|
|
}
|
|
|
|
void bgunSetHitPos(struct coord *coord)
|
|
{
|
|
struct player *player = g_Vars.currentplayer;
|
|
|
|
player->hands[HAND_LEFT].hitpos.x = player->hands[HAND_RIGHT].hitpos.x = coord->x;
|
|
player->hands[HAND_LEFT].hitpos.y = player->hands[HAND_RIGHT].hitpos.y = coord->y;
|
|
player->hands[HAND_LEFT].hitpos.z = player->hands[HAND_RIGHT].hitpos.z = coord->z;
|
|
}
|
|
|
|
void bgun0f0a9494(u32 operation)
|
|
{
|
|
switch (operation) {
|
|
case 0:
|
|
g_Vars.currentplayer->hands[HAND_LEFT].hasdotinfo = g_Vars.currentplayer->hands[HAND_RIGHT].hasdotinfo = false;
|
|
break;
|
|
case 1:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void bgun0f0a94d0(u32 operation, struct coord *pos, struct coord *rot)
|
|
{
|
|
struct player *player = g_Vars.currentplayer;
|
|
|
|
switch (operation) {
|
|
case 0:
|
|
if (pos->x > -100000.0f && pos->x < 100000.0f
|
|
&& pos->y > -100000.0f && pos->y < 100000.0f
|
|
&& pos->z > -100000.0f && pos->z < 100000.0f) {
|
|
player->hands[HAND_RIGHT].hasdotinfo = true;
|
|
player->hands[HAND_LEFT].hasdotinfo = true;
|
|
|
|
player->hands[HAND_LEFT].dotpos.x = player->hands[HAND_RIGHT].dotpos.x = pos->x;
|
|
player->hands[HAND_LEFT].dotpos.y = player->hands[HAND_RIGHT].dotpos.y = pos->y;
|
|
player->hands[HAND_LEFT].dotpos.z = player->hands[HAND_RIGHT].dotpos.z = pos->z;
|
|
|
|
player->hands[HAND_LEFT].dotrot.x = player->hands[HAND_RIGHT].dotrot.x = rot->x;
|
|
player->hands[HAND_LEFT].dotrot.y = player->hands[HAND_RIGHT].dotrot.y = rot->y;
|
|
player->hands[HAND_LEFT].dotrot.z = player->hands[HAND_RIGHT].dotrot.z = rot->z;
|
|
}
|
|
break;
|
|
case 1:
|
|
case 2:
|
|
lasersightSetDot(operation - 1, pos, rot);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void bgunSetGunAmmoVisible(u32 reason, bool enable)
|
|
{
|
|
if (enable) {
|
|
g_Vars.currentplayer->gunammooff &= ~reason;
|
|
} else {
|
|
g_Vars.currentplayer->gunammooff |= reason;
|
|
}
|
|
}
|
|
|
|
struct ammotype g_AmmoTypes[] = {
|
|
{ 0, 0, 0 },
|
|
{ 800, 0, 0 }, // AMMOTYPE_PISTOL
|
|
{ 800, 0, 0 }, // AMMOTYPE_SMG
|
|
{ 69, 0, 0 }, // AMMOTYPE_CROSSBOW
|
|
{ 400, 0, -2 }, // AMMOTYPE_RIFLE
|
|
{ 100, 0, 0 }, // AMMOTYPE_SHOTGUN
|
|
{ 100, 0, 0 }, // AMMOTYPE_FARSIGHT
|
|
{ 12, 0, 0 }, // AMMOTYPE_GRENADE
|
|
{ 3, 0, -2 }, // AMMOTYPE_ROCKET
|
|
{ 10, 0, 0 }, // AMMOTYPE_KNIFE
|
|
{ 200, 0, 0 }, // AMMOTYPE_MAGNUM
|
|
{ 40, 0, 0 }, // AMMOTYPE_DEVASTATOR
|
|
{ 10, 0, 1 }, // AMMOTYPE_REMOTE_MINE
|
|
{ 10, 0, 1 }, // AMMOTYPE_PROXY_MINE
|
|
{ 10, 0, 1 }, // AMMOTYPE_TIMED_MINE
|
|
{ 800, 0, 0 }, // AMMOTYPE_REAPER
|
|
{ 15, 0, -2 }, // AMMOTYPE_HOMINGROCKET
|
|
{ 50, 0, 0 }, // AMMOTYPE_DART
|
|
{ 10, 0, 0 }, // AMMOTYPE_NBOMB
|
|
{ 200, 0, 0 }, // AMMOTYPE_SEDATIVE
|
|
{ TICKS(18000), 0, 0 }, // AMMOTYPE_CLOAK
|
|
{ 4, 0, 0 }, // AMMOTYPE_BOOST
|
|
{ 200, 0, 0 }, // AMMOTYPE_PSYCHOSIS
|
|
{ 2, 0, 0 }, // AMMOTYPE_17
|
|
{ 10, 0, 0 }, // AMMOTYPE_BUG
|
|
{ 10, 0, 0 }, // AMMOTYPE_MICROCAMERA
|
|
{ 10, 0, 0 }, // AMMOTYPE_PLASTIQUE
|
|
{ 1000, 0, 0 }, // AMMOTYPE_1B
|
|
{ 10, 0, 0 }, // AMMOTYPE_1C
|
|
{ 50, 0, -1 }, // AMMOTYPE_1D
|
|
{ 1, 0, 0 }, // AMMOTYPE_TOKEN
|
|
{ 200, 0, 0 }, // AMMOTYPE_1F
|
|
{ 10, 0, 0 }, // AMMOTYPE_ECM_MINE
|
|
};
|
|
|
|
void bgunSetAmmoQuantity(s32 ammotype, s32 quantity)
|
|
{
|
|
struct player *player = g_Vars.currentplayer;
|
|
s32 weaponnum = bgunGetWeaponNum(HAND_RIGHT);
|
|
s32 funcnum = -1;
|
|
s32 magamount;
|
|
|
|
// Check if this ammo type applies to the player's equipped weapon
|
|
if (bgunGetAmmoTypeForWeapon(weaponnum, FUNC_PRIMARY) == ammotype) {
|
|
funcnum = FUNC_PRIMARY;
|
|
}
|
|
|
|
if (bgunGetAmmoTypeForWeapon(weaponnum, FUNC_SECONDARY) == ammotype) {
|
|
funcnum = FUNC_SECONDARY;
|
|
}
|
|
|
|
if (funcnum != -1 && weaponHasAmmoFlag(weaponnum, funcnum, AMMOFLAG_NORESERVE)) {
|
|
// For cloak and combat boost, ammo cannot be held outside of the weapon.
|
|
// So just add it to the loaded clip.
|
|
player->hands[0].loadedammo[funcnum] += quantity;
|
|
|
|
if (player->hands[0].loadedammo[funcnum] > player->hands[0].clipsizes[funcnum]) {
|
|
player->hands[0].loadedammo[funcnum] = player->hands[0].clipsizes[funcnum];
|
|
}
|
|
|
|
player->ammoheldarr[ammotype] = 0;
|
|
return;
|
|
}
|
|
|
|
magamount = 0;
|
|
|
|
// For throwable items, the capacity applies to reserve + loaded
|
|
if (funcnum != -1 && weaponHasAmmoFlag(weaponnum, funcnum, AMMOFLAG_EQUIPPEDISRESERVE)) {
|
|
magamount = player->hands[0].loadedammo[funcnum] + player->hands[1].loadedammo[funcnum];
|
|
}
|
|
|
|
if (quantity > g_AmmoTypes[ammotype].capacity - magamount) {
|
|
player->ammoheldarr[ammotype] = g_AmmoTypes[ammotype].capacity - magamount;
|
|
} else {
|
|
player->ammoheldarr[ammotype] = quantity;
|
|
}
|
|
}
|
|
|
|
s32 bgunGetReservedAmmoCount(s32 ammotype)
|
|
{
|
|
s32 i;
|
|
s32 j;
|
|
s32 total = g_Vars.currentplayer->ammoheldarr[ammotype];
|
|
struct player *player = g_Vars.currentplayer;
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
if (player->hands[i].inuse) {
|
|
for (j = 0; j < 2; j++) {
|
|
if (player->gunctrl.ammotypes[j] == ammotype && weaponHasAmmoFlag(player->hands[i].gset.weaponnum, j, AMMOFLAG_NORESERVE)) {
|
|
total = total + player->hands[i].loadedammo[j];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return total;
|
|
}
|
|
|
|
s32 bgunGetAmmoCount(s32 ammotype)
|
|
{
|
|
s32 i;
|
|
s32 j;
|
|
s32 total = g_Vars.currentplayer->ammoheldarr[ammotype];
|
|
struct player *player = g_Vars.currentplayer;
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
if (player->hands[i].inuse) {
|
|
for (j = 0; j < 2; j++) {
|
|
if (player->gunctrl.ammotypes[j] == ammotype) {
|
|
total = total + player->hands[i].loadedammo[j];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return total;
|
|
}
|
|
|
|
s32 bgunGetCapacityByAmmotype(s32 ammotype)
|
|
{
|
|
return g_AmmoTypes[ammotype].capacity;
|
|
}
|
|
|
|
bool bgunAmmotypeAllowsUnlimitedAmmo(u32 ammotype)
|
|
{
|
|
switch (ammotype) {
|
|
case AMMOTYPE_REMOTE_MINE:
|
|
if (g_Vars.stagenum == STAGE_CHICAGO) {
|
|
return false;
|
|
}
|
|
break;
|
|
case AMMOTYPE_TIMED_MINE:
|
|
if (g_Vars.stagenum == STAGE_AIRFORCEONE) {
|
|
return false;
|
|
}
|
|
break;
|
|
case AMMOTYPE_PSYCHOSIS:
|
|
case AMMOTYPE_17:
|
|
case AMMOTYPE_BUG:
|
|
case AMMOTYPE_MICROCAMERA:
|
|
case AMMOTYPE_PLASTIQUE:
|
|
case AMMOTYPE_1B:
|
|
case AMMOTYPE_1C:
|
|
case AMMOTYPE_1D:
|
|
case AMMOTYPE_TOKEN:
|
|
case AMMOTYPE_1F:
|
|
case AMMOTYPE_ECM_MINE:
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void bgunGiveMaxAmmo(bool force)
|
|
{
|
|
s32 i;
|
|
|
|
for (i = 0; i < ARRAYCOUNT(g_AmmoTypes); i++) {
|
|
bool give = true;
|
|
|
|
if (!force) {
|
|
give = bgunAmmotypeAllowsUnlimitedAmmo(i);
|
|
}
|
|
|
|
if (give) {
|
|
bgunSetAmmoQuantity(i, g_AmmoTypes[i].capacity);
|
|
}
|
|
}
|
|
}
|
|
|
|
u32 bgunGetAmmoTypeForWeapon(u32 weaponnum, u32 func)
|
|
{
|
|
struct weapon *weapon = weaponFindById(weaponnum);
|
|
|
|
if (!weapon) {
|
|
return 0;
|
|
}
|
|
|
|
if (!weapon->ammos[func]) {
|
|
return 0;
|
|
}
|
|
|
|
return weapon->ammos[func]->type;
|
|
}
|
|
|
|
s32 bgunGetAmmoQtyForWeapon(u32 weaponnum, u32 func)
|
|
{
|
|
struct weapon *weapon = weaponFindById(weaponnum);
|
|
|
|
if (weapon) {
|
|
struct inventory_ammo *ammo = weapon->ammos[func];
|
|
|
|
if (ammo) {
|
|
return bgunGetReservedAmmoCount(ammo->type);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void bgunSetAmmoQtyForWeapon(u32 weaponnum, u32 func, u32 quantity)
|
|
{
|
|
struct weapon *weapon = weaponFindById(weaponnum);
|
|
|
|
if (weapon) {
|
|
struct inventory_ammo *ammo = weapon->ammos[func];
|
|
|
|
if (ammo) {
|
|
bgunSetAmmoQuantity(ammo->type, quantity);
|
|
}
|
|
}
|
|
}
|
|
|
|
s32 bgunGetAmmoCapacityForWeapon(s32 weaponnum, s32 func)
|
|
{
|
|
struct weapon *weapon = weaponFindById(weaponnum);
|
|
struct inventory_ammo *ammo = weapon->ammos[func];
|
|
|
|
if (ammo) {
|
|
return g_AmmoTypes[ammo->type].capacity;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
Gfx *bgunDrawHudString(Gfx *gdl, char *text, s32 x, bool halign, s32 y, s32 valign, u32 colour)
|
|
{
|
|
s32 x1 = 0;
|
|
s32 y1 = 0;
|
|
s32 x2 = 0;
|
|
s32 y2 = 0;
|
|
s32 textheight;
|
|
s32 textwidth;
|
|
|
|
textwidth = 0;
|
|
textheight = 0;
|
|
|
|
#if VERSION >= VERSION_JPN_FINAL
|
|
textMeasure(&textheight, &textwidth, text, g_CharsNumeric, g_FontNumeric, -1);
|
|
#else
|
|
textMeasure(&textheight, &textwidth, text, g_CharsNumeric, g_FontNumeric, 0);
|
|
#endif
|
|
|
|
if (halign == HUDHALIGN_LEFT) { // left
|
|
x2 = x + textwidth;
|
|
x1 = x;
|
|
} else if (halign == HUDHALIGN_RIGHT) { // right
|
|
x1 = x - textwidth;
|
|
x2 = x;
|
|
} else if (halign == HUDHALIGN_MIDDLE) { // middle
|
|
x2 = x + textwidth / 2;
|
|
x1 = x2 - textwidth;
|
|
}
|
|
|
|
if (valign == HUDVALIGN_TOP) { // top
|
|
y2 = y + textheight;
|
|
y1 = y;
|
|
} else if (valign == HUDVALIGN_BOTTOM) { // bottom
|
|
y1 = y - textheight;
|
|
y2 = y;
|
|
} else if (valign == HUDVALIGN_MIDDLE) { // middle
|
|
y2 = y + textheight / 2;
|
|
y1 = y2 - textheight;
|
|
}
|
|
|
|
gdl = text0f153858(gdl, &x1, &y1, &x2, &y2);
|
|
gdl = textRender(gdl, &x1, &y1, text, g_CharsNumeric, g_FontNumeric, colour, 0x000000a0, viGetWidth(), viGetHeight(), 0, 0);
|
|
|
|
return gdl;
|
|
}
|
|
|
|
Gfx *bgunDrawHudInteger(Gfx *gdl, s32 value, s32 x, bool halign, s32 y, s32 valign, u32 colour)
|
|
{
|
|
char buffer[12];
|
|
|
|
sprintf(buffer, "%d\n", value);
|
|
gdl = bgunDrawHudString(gdl, buffer, x, halign, y, valign, colour);
|
|
|
|
return gdl;
|
|
}
|
|
|
|
void bgunResetAbmag(struct abmag *abmag)
|
|
{
|
|
abmag->loadedammo = 0;
|
|
abmag->change = 0;
|
|
abmag->ref = 0;
|
|
abmag->timer60 = 0;
|
|
}
|
|
|
|
void bgun0f0a9da8(struct abmag *mag, s32 remaining, s32 capacity, s32 height)
|
|
{
|
|
s32 newchange;
|
|
|
|
if (capacity > 20) {
|
|
s32 newremaining = height * remaining / capacity;
|
|
|
|
if (remaining > 0 && newremaining < 1) {
|
|
newremaining = 1;
|
|
}
|
|
|
|
capacity = height;
|
|
|
|
if (newremaining == mag->ref && mag->loadedammo > remaining) {
|
|
mag->ref++;
|
|
}
|
|
|
|
mag->loadedammo = remaining;
|
|
remaining = newremaining;
|
|
}
|
|
|
|
newchange = remaining - mag->ref;
|
|
|
|
if ((mag->change < 0 && newchange > 0) || (mag->change > 0 && newchange < 0)) {
|
|
mag->ref += mag->change;
|
|
mag->change = 0;
|
|
mag->timer60 = 0;
|
|
|
|
newchange = remaining - mag->ref;
|
|
}
|
|
|
|
if (mag->change < 0 && mag->change > newchange) {
|
|
if (mag->timer60 > -mag->change * TICKS(64)) {
|
|
mag->timer60 = -mag->change * TICKS(64);
|
|
}
|
|
}
|
|
|
|
mag->change = newchange;
|
|
|
|
if (mag->change > 0) {
|
|
height = capacity;
|
|
|
|
if (capacity < 6) {
|
|
height = 6;
|
|
}
|
|
} else {
|
|
height = 8;
|
|
|
|
if (mag->change < -3) {
|
|
height += -mag->change * 2;
|
|
}
|
|
}
|
|
|
|
if (mag->change != 0) {
|
|
mag->timer60 += (s16)g_Vars.lvupdate60 * height;
|
|
|
|
if (mag->timer60 > TICKS(255)) {
|
|
if (mag->change > 0) {
|
|
while (mag->timer60 > TICKS(255) && mag->change > 0) {
|
|
mag->change--;
|
|
mag->ref++;
|
|
mag->timer60 -= TICKS(64);
|
|
}
|
|
} else {
|
|
while (mag->timer60 > TICKS(255) && mag->change < 0) {
|
|
mag->change++;
|
|
mag->ref--;
|
|
mag->timer60 -= TICKS(64);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
mag->timer60 = 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Render an ammo gauge on the HUD.
|
|
*
|
|
* Ammo gauges can be displayed in two ways. If the capacity is less than 20,
|
|
* each bullet is displayed as a separate block with a gap between each. If the
|
|
* capacity is 20 or more, a single block covers the whole gauge and the block
|
|
* is partitioned into two (filled and empty).
|
|
*
|
|
* For the separated mode, a unit refers to a single bullet/block.
|
|
* For the merged mode, a unit refers to a single 1px high line in the gauge.
|
|
*/
|
|
Gfx *bgunDrawHudGauge(Gfx *gdl, s32 x1, s32 y1, s32 x2, s32 y2, struct abmag *abmag, s32 remaining, s32 capacity, u32 emptycolour, u32 filledcolour, bool flip)
|
|
{
|
|
s32 gaugeheight = y2 - y1;
|
|
s32 unitheight;
|
|
s32 remainder1;
|
|
s32 remainder2;
|
|
s32 gaugetop;
|
|
f32 ref;
|
|
s32 numunits = capacity;
|
|
s32 i;
|
|
|
|
bgun0f0a9da8(abmag, remaining, numunits, gaugeheight);
|
|
|
|
if (numunits > 20) {
|
|
// Use a single merged bar
|
|
ref = abmag->ref;
|
|
unitheight = 1;
|
|
numunits = gaugeheight;
|
|
gaugetop = y2 - gaugeheight;
|
|
} else {
|
|
// Use a separate block for each bullet
|
|
ref = abmag->ref;
|
|
unitheight = gaugeheight / numunits;
|
|
remainder1 = unitheight * numunits - gaugeheight;
|
|
remainder2 = (unitheight + 1) * numunits - gaugeheight;
|
|
|
|
if (remainder1 < 0) {
|
|
remainder1 = -remainder1;
|
|
}
|
|
|
|
if (remainder2 < 0) {
|
|
remainder2 = -remainder2;
|
|
}
|
|
|
|
if (remainder2 < remainder1) {
|
|
unitheight++;
|
|
}
|
|
|
|
gaugetop = y2 - unitheight * capacity + 1;
|
|
|
|
if (unitheight <= 2) {
|
|
gaugetop--;
|
|
}
|
|
}
|
|
|
|
if (unitheight == 0) {
|
|
/**
|
|
* Using separate blocks, but the clip capacity is more than the gauge
|
|
* height meaning each block is less than 1px. This is impossible
|
|
* because the gauge switches modes away from separate blocks at 20,
|
|
* therefore this code is unreachable.
|
|
*
|
|
* This code renders the gauge in the merged style, but uses 1px per
|
|
* bullet and truncates the gauge at the gaugetop if needed. This is
|
|
* clearly an early revision of the code, as it is visually misleading
|
|
* and also lacks the transition effect.
|
|
*/
|
|
s32 partitiony;
|
|
s32 tmp;
|
|
|
|
gaugeheight = y2 - gaugetop;
|
|
partitiony = y2 - gaugeheight * ref / numunits;
|
|
tmp = y2;
|
|
|
|
if (partitiony > gaugetop) {
|
|
// Render empty partition
|
|
gdl = textSetPrimColour(gdl, emptycolour);
|
|
|
|
if (flip) {
|
|
gDPFillRectangleScaled(gdl++, x1, y2 - partitiony + y1, x2, gaugeheight + y1);
|
|
} else {
|
|
gDPFillRectangleScaled(gdl++, x1, gaugetop, x2, partitiony);
|
|
}
|
|
|
|
gdl = text0f153838(gdl);
|
|
}
|
|
|
|
// Render filled partition
|
|
gdl = textSetPrimColour(gdl, filledcolour);
|
|
|
|
if (flip) {
|
|
gDPFillRectangleScaled(gdl++, x1, y2 - tmp + y1, x2, y2 - partitiony + y1);
|
|
} else {
|
|
gDPFillRectangleScaled(gdl++, x1, partitiony, x2, y2);
|
|
}
|
|
} else {
|
|
u32 colour;
|
|
s32 unittop;
|
|
s32 unitbottom;
|
|
|
|
gdl = textSetPrimColour(gdl, emptycolour);
|
|
|
|
unittop = gaugetop;
|
|
unitbottom = -1;
|
|
|
|
for (i = 0; i < numunits; i++) {
|
|
bool newstate = false;
|
|
u32 weight;
|
|
|
|
if (1);
|
|
|
|
if (abmag->change > 0) {
|
|
// Loading or reloading
|
|
if (i >= numunits - (s32)ref - abmag->change && i < numunits - (s32)ref) {
|
|
// Unit is potentially unsettled
|
|
s32 fadeamount = abmag->timer60 - (numunits - (s32)ref - i - 1) * TICKS(64);
|
|
|
|
if (fadeamount >= 0) {
|
|
if (fadeamount >= TICKS(64)) {
|
|
// Unit is transitioning to filled
|
|
#if PAL
|
|
weight = (fadeamount * 4 - TICKS(250)) / 3;
|
|
#else
|
|
weight = (fadeamount * 4 - TICKS(252)) / 3;
|
|
#endif
|
|
weight = PALUP(weight);
|
|
|
|
if (weight > 255) {
|
|
weight = 255;
|
|
}
|
|
|
|
colour = colourBlend(filledcolour, 0xffffffbf, weight);
|
|
} else {
|
|
// Unit is bright and has not started transitioning to filled yet
|
|
weight = fadeamount * 4;
|
|
weight = PALUP(weight);
|
|
|
|
#if VERSION >= VERSION_PAL_BETA
|
|
if (weight > 255) {
|
|
weight = 255;
|
|
}
|
|
#endif
|
|
|
|
colour = colourBlend(0xffffffbf, emptycolour, weight);
|
|
}
|
|
|
|
newstate = true;
|
|
}
|
|
}
|
|
} else if (abmag->change < 0) {
|
|
// Firing
|
|
if (i < numunits - (s32)ref - abmag->change && i >= numunits - (s32) ref) {
|
|
s32 fadeamount = abmag->timer60 - (i - numunits + (s32) ref) * TICKS(64);
|
|
|
|
if (fadeamount >= 0) {
|
|
weight = PALUP(fadeamount);
|
|
|
|
if (weight > 255) {
|
|
colour = emptycolour;
|
|
} else {
|
|
// Unit was recently emptied
|
|
colour = colourBlend(emptycolour, filledcolour | 0xff, weight);
|
|
}
|
|
|
|
newstate = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Special case for units which are one after the last one being
|
|
// faded. I think their colour is calculated incorrectly by the code
|
|
// above and this is resetting them to the normal filled colour.
|
|
if (abmag->change < 0) {
|
|
// Firing
|
|
if (i == numunits - (s32) ref - abmag->change) {
|
|
colour = filledcolour;
|
|
newstate = true;
|
|
}
|
|
} else {
|
|
if (i == numunits - (s32) ref) {
|
|
colour = filledcolour;
|
|
newstate = true;
|
|
}
|
|
}
|
|
|
|
// Calculate unittop and unitbottom. For merged gauges keep unittop
|
|
// as it is if possible, so the empty and filled partitions can be
|
|
// drawn whenever the state is changed in order to save gfx calls.
|
|
if (unitheight <= 2) {
|
|
if (newstate) {
|
|
if (unitbottom >= 0) {
|
|
// Render empty or transitioning unit of merged gauge
|
|
if (flip) {
|
|
gDPFillRectangleScaled(gdl++, x1, y2 - unitbottom + y1, x2, y2 - unittop + y1);
|
|
} else {
|
|
gDPFillRectangleScaled(gdl++, x1, unittop, x2, unitbottom);
|
|
}
|
|
}
|
|
|
|
unittop = gaugetop + i * unitheight;
|
|
}
|
|
|
|
unitbottom = gaugetop + i * unitheight + unitheight;
|
|
} else {
|
|
// Separate blocks - reduce unitbottom by 1 to make a gap
|
|
unittop = gaugetop + i * unitheight;
|
|
unitbottom = gaugetop + i * unitheight + unitheight - 1;
|
|
}
|
|
|
|
if (newstate) {
|
|
gDPSetPrimColorViaWord(gdl++, 0, 0, colour);
|
|
}
|
|
|
|
// For separate blocks, clip the unit bottom to the bottom of the gauge
|
|
if (unitbottom >= y2 - 1 && unitheight >= 2) {
|
|
unitbottom = y2;
|
|
}
|
|
|
|
// Render separated blocks
|
|
if (unitheight >= 3) {
|
|
if (flip) {
|
|
gDPFillRectangleScaled(gdl++, x1, y2 - unitbottom + y1, x2, y2 - unittop + y1);
|
|
} else {
|
|
gDPFillRectangleScaled(gdl++, x1, unittop, x2, unitbottom);
|
|
}
|
|
}
|
|
} // end loop
|
|
|
|
// For merged gauges, render the final partition
|
|
if (unitheight <= 2) {
|
|
s32 stack;
|
|
|
|
if (flip) {
|
|
gDPFillRectangleScaled(gdl++, x1, y2 - unitbottom + y1, x2, y2 - unittop + y1);
|
|
} else {
|
|
gDPFillRectangleScaled(gdl++, x1, unittop, x2, unitbottom);
|
|
}
|
|
}
|
|
}
|
|
|
|
gdl = text0f153838(gdl);
|
|
|
|
gDPSetRenderMode(gdl++, G_RM_AA_XLU_SURF, G_RM_AA_XLU_SURF2);
|
|
|
|
return gdl;
|
|
}
|
|
|
|
Gfx *bgunDrawHud(Gfx *gdl)
|
|
{
|
|
struct player *player = g_Vars.currentplayer;
|
|
s32 bottom = viGetViewTop() + viGetViewHeight() - 13;
|
|
s32 playercount = PLAYERCOUNT();
|
|
s32 playernum = g_Vars.currentplayernum;
|
|
struct gunctrl *ctrl;
|
|
s32 secs60;
|
|
s32 speedpilltime;
|
|
s32 ammoindex = 0;
|
|
s32 barwidth = 9;
|
|
s32 reserveheight = 36;
|
|
s32 clipheight = 57;
|
|
s32 xpos;
|
|
struct weapon *weapon = weaponFindById(player->gunctrl.weaponnum);
|
|
u32 alpha;
|
|
u32 fncolour;
|
|
s32 funcnum;
|
|
s32 fnfaderinc;
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
s32 tmpfuncnum;
|
|
struct handweaponinfo info;
|
|
#endif
|
|
struct hand *hand = &player->hands[HAND_RIGHT];
|
|
char *str;
|
|
u32 colour;
|
|
s32 x;
|
|
s32 y;
|
|
s32 textheight;
|
|
s32 textwidth;
|
|
struct weaponfunc *func;
|
|
u16 nameid;
|
|
struct hand *lefthand = &player->hands[HAND_LEFT];
|
|
|
|
ctrl = &player->gunctrl;
|
|
|
|
if (player->isdead) {
|
|
return gdl;
|
|
}
|
|
|
|
if (g_Vars.currentplayer->gunctrl.passivemode) {
|
|
return gdl;
|
|
}
|
|
|
|
if (g_Vars.lvframenum < 5) {
|
|
return gdl;
|
|
}
|
|
|
|
#if PAL
|
|
g_ScaleX = 1;
|
|
#else
|
|
g_ScaleX = g_ViRes == VIRES_HI ? 2 : 1;
|
|
#endif
|
|
|
|
gdl = text0f153628(gdl);
|
|
|
|
if (playercount >= 2) {
|
|
barwidth = 5;
|
|
reserveheight = 26;
|
|
clipheight = 47;
|
|
|
|
if (playercount == 2) {
|
|
if (IS4MB() || (optionsGetScreenSplit() != SCREENSPLIT_VERTICAL && playernum == 0)) {
|
|
bottom += 10;
|
|
} else {
|
|
bottom += 2;
|
|
}
|
|
} else if (playercount >= 3) {
|
|
if (playernum < 2) {
|
|
bottom += 10;
|
|
} else {
|
|
bottom += 2;
|
|
}
|
|
}
|
|
} else if (optionsGetEffectiveScreenSize() != SCREENSIZE_FULL) {
|
|
bottom += 8;
|
|
}
|
|
|
|
fncolour = 0xff000040;
|
|
funcnum = hand->gset.weaponfunc;
|
|
fnfaderinc = PALUP(g_Vars.lvupdate240 * 2);
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
bgunGetWeaponInfo(&info, HAND_RIGHT);
|
|
tmpfuncnum = bgunIsUsingSecondaryFunction();
|
|
|
|
if (bgun0f098ca0(tmpfuncnum, &info, hand) >= 0) {
|
|
funcnum = tmpfuncnum;
|
|
}
|
|
#endif
|
|
|
|
xpos = (viGetViewLeft() + viGetViewWidth()) / g_ScaleX - barwidth - 24;
|
|
|
|
if (playercount == 2 && (optionsGetScreenSplit() == SCREENSPLIT_VERTICAL || IS4MB()) && playernum == 0) {
|
|
xpos += 15;
|
|
} else if (playercount >= 3 && (playernum % 2) == 0) {
|
|
xpos += 15;
|
|
}
|
|
|
|
// Draw function square
|
|
if (funcnum == FUNC_SECONDARY && ctrl->fnfader < 255) {
|
|
if (ctrl->fnfader < 128) {
|
|
ctrl->fnfader = 128;
|
|
}
|
|
|
|
if (ctrl->fnfader + fnfaderinc > 255) {
|
|
ctrl->fnfader = 255;
|
|
} else {
|
|
ctrl->fnfader += fnfaderinc;
|
|
}
|
|
}
|
|
|
|
if (funcnum == FUNC_PRIMARY && ctrl->fnfader > 0) {
|
|
if (ctrl->fnfader - fnfaderinc < 0) {
|
|
ctrl->fnfader = 0;
|
|
} else {
|
|
ctrl->fnfader -= fnfaderinc;
|
|
}
|
|
}
|
|
|
|
if (ctrl->fnfader > 128) {
|
|
fncolour = ((ctrl->fnfader * 2) - 256) << 16 | 0xff000040;
|
|
}
|
|
|
|
gdl = textSetPrimColour(gdl, fncolour);
|
|
|
|
gDPFillRectangleScaled(gdl++, xpos - 13, bottom - 11, xpos - 2, bottom);
|
|
|
|
gdl = text0f153838(gdl);
|
|
|
|
// Draw weapon name and function name
|
|
if (optionsGetShowGunFunction(g_Vars.currentplayerstats->mpindex)) {
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
func = weaponGetFunctionById(hand->gset.weaponnum, funcnum);
|
|
#else
|
|
func = weaponGetFunctionById(hand->gset.weaponnum, hand->gset.weaponfunc);
|
|
#endif
|
|
nameid = invGetNameIdByIndex(invGetCurrentIndex());
|
|
str = langGet(nameid);
|
|
|
|
if (ctrl->curgunstr != nameid) {
|
|
ctrl->guntypetimer = 0;
|
|
ctrl->curgunstr = nameid;
|
|
}
|
|
|
|
if (ctrl->guntypetimer < 255) {
|
|
colour = 0x55ffffff;
|
|
|
|
if (ctrl->guntypetimer);
|
|
|
|
if (ctrl->guntypetimer + g_Vars.lvupdate60 > 255) {
|
|
ctrl->guntypetimer = 255;
|
|
} else {
|
|
ctrl->guntypetimer += (u16) g_Vars.lvupdate60;
|
|
}
|
|
|
|
textMeasure(&textheight, &textwidth, str, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0);
|
|
textwidth += 2;
|
|
|
|
if (textwidth > ctrl->guntypetimer * 3) {
|
|
textwidth = ctrl->guntypetimer * 3;
|
|
}
|
|
|
|
if (playercount >= 2) {
|
|
x = xpos - textwidth - 13;
|
|
} else {
|
|
x = xpos - textwidth - 2;
|
|
}
|
|
|
|
#if VERSION == VERSION_JPN_FINAL
|
|
y = bottom - textheight - 10;
|
|
#else
|
|
y = bottom - textheight - 15;
|
|
#endif
|
|
|
|
if (ctrl->guntypetimer > 192) {
|
|
alpha = 255 - (ctrl->guntypetimer - 192) * 255 / 63U;
|
|
colour = (colour & 0xffffff00) | alpha;
|
|
if (0xffffff00);
|
|
}
|
|
|
|
gdl = textSetPrimColour(gdl, 0);
|
|
|
|
gDPFillRectangleScaled(gdl++, x - 1, y - 1, xpos - 11, bottom);
|
|
|
|
gdl = text0f153838(gdl);
|
|
textSetWaveBlend(g_20SecIntervalFrac * 50.0f, 0, 50);
|
|
textSetWaveColours(0xffffffff, 0xffffffff);
|
|
gdl = textRenderProjected(gdl, &x, &y, str, g_CharsHandelGothicXs, g_FontHandelGothicXs, colour, textwidth, 1000, 0, 0);
|
|
textResetBlends();
|
|
}
|
|
|
|
if (func) {
|
|
langGet(func->name);
|
|
|
|
colour = 0xff5555ff;
|
|
|
|
if ((ctrl->curfnstr != func->name && ctrl->fnfader > 128) || ctrl->curfnstr == 0) {
|
|
ctrl->fnstrtimer = 0;
|
|
ctrl->curfnstr = func->name;
|
|
}
|
|
|
|
str = langGet(ctrl->curfnstr);
|
|
|
|
if (ctrl->fnstrtimer < 255) {
|
|
if (ctrl->fnstrtimer + g_Vars.lvupdate60 > 255) {
|
|
ctrl->fnstrtimer = 255;
|
|
} else {
|
|
ctrl->fnstrtimer += (u16) g_Vars.lvupdate60;
|
|
}
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
if (funcnum == FUNC_SECONDARY && func->name == ctrl->curfnstr) {
|
|
colour |= 0x00ff0000;
|
|
}
|
|
|
|
if (funcnum == FUNC_PRIMARY && func->name != ctrl->curfnstr) {
|
|
colour |= 0x00ff0000;
|
|
}
|
|
#else
|
|
if (hand->gset.weaponfunc == FUNC_SECONDARY && func->name == ctrl->curfnstr) {
|
|
colour |= 0x00ff0000;
|
|
}
|
|
|
|
if (hand->gset.weaponfunc == FUNC_PRIMARY && func->name != ctrl->curfnstr) {
|
|
colour |= 0x00ff0000;
|
|
}
|
|
#endif
|
|
|
|
textMeasure(&textheight, &textwidth, str, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0);
|
|
textwidth += 2;
|
|
|
|
if (textwidth > ctrl->fnstrtimer * 3) {
|
|
textwidth = ctrl->fnstrtimer * 3;
|
|
}
|
|
|
|
x = xpos - textwidth - 13;
|
|
#if VERSION == VERSION_JPN_FINAL
|
|
y = bottom - textheight + 3;
|
|
#else
|
|
y = bottom - textheight - 1;
|
|
#endif
|
|
|
|
if (ctrl->fnstrtimer > 192) {
|
|
alpha = 255 - (ctrl->fnstrtimer - 192) * 255 / 63U;
|
|
colour = (colour & 0xffffff00) | alpha;
|
|
}
|
|
|
|
gdl = textSetPrimColour(gdl, 0);
|
|
|
|
gDPFillRectangleScaled(gdl++, x - 1, y - 1, xpos - 11, bottom + 3);
|
|
|
|
gdl = text0f153838(gdl);
|
|
|
|
textSetWaveBlend(g_20SecIntervalFrac * 50.0f, 0, 50);
|
|
textSetWaveColours(0xffffffff, 0xffffffff);
|
|
|
|
gdl = textRenderProjected(gdl, &x, &y, str,
|
|
g_CharsHandelGothicXs, g_FontHandelGothicXs, colour, textwidth,
|
|
1000, 0, 0);
|
|
|
|
textResetBlends();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (weapon && weapon->functions[hand->gset.weaponfunc] != NULL) {
|
|
ammoindex = ((struct weaponfunc *)(weapon->functions[hand->gset.weaponfunc]))->ammoindex;
|
|
}
|
|
|
|
if (ammoindex == -1) {
|
|
if (weapon->functions[1 - hand->gset.weaponfunc] != NULL) {
|
|
ammoindex = ((struct weaponfunc *)(weapon->functions[1 - hand->gset.weaponfunc]))->ammoindex;
|
|
}
|
|
|
|
if (ammoindex == -1) {
|
|
gdl = text0f153780(gdl);
|
|
g_ScaleX = 1;
|
|
return gdl;
|
|
}
|
|
}
|
|
|
|
if (ammoindex != ctrl->lastmag) {
|
|
bgunResetAbmag(&player->hands[HAND_LEFT].abmag);
|
|
bgunResetAbmag(&hand->abmag);
|
|
bgunResetAbmag(&ctrl->abmag);
|
|
ctrl->lastmag = ammoindex;
|
|
}
|
|
|
|
// Left hand - mag
|
|
if (lefthand->inuse
|
|
&& weapon->ammos[ammoindex] != NULL
|
|
&& lefthand->gset.weaponnum != WEAPON_REMOTEMINE) {
|
|
xpos = viGetViewLeft() / g_ScaleX + 24;
|
|
|
|
if (playercount == 2 && (optionsGetScreenSplit() == SCREENSPLIT_VERTICAL || IS4MB()) && playernum == 1) {
|
|
xpos -= 14;
|
|
} else if (playercount >= 3 && (playernum & 1) == 1) {
|
|
xpos -= 14;
|
|
}
|
|
|
|
if (lefthand->clipsizes[ammoindex] > 0 && (weapon->ammos[ammoindex]->flags & AMMOFLAG_EQUIPPEDISRESERVE) == 0) {
|
|
gdl = bgunDrawHudGauge(gdl,
|
|
xpos, bottom - reserveheight - clipheight - 3, xpos + barwidth, bottom - reserveheight - 3,
|
|
&lefthand->abmag, lefthand->loadedammo[ammoindex], lefthand->clipsizes[ammoindex],
|
|
0x00300080, 0x00ff0040, false);
|
|
gdl = bgunDrawHudInteger(gdl, lefthand->loadedammo[ammoindex], xpos + barwidth + 2, true,
|
|
bottom - reserveheight - 8, 0, 0x00ff00a0);
|
|
}
|
|
}
|
|
|
|
// Right hand - mag, reserve and combat boost timer
|
|
if (hand->inuse && ctrl->ammotypes[ammoindex] >= 0) {
|
|
s32 ammotype;
|
|
s32 ammoheld;
|
|
s32 ammototal;
|
|
|
|
ammotype = player->gunctrl.ammotypes[ammoindex];
|
|
|
|
#if VERSION >= VERSION_NTSC_1_0
|
|
xpos = (viGetViewLeft() + viGetViewWidth()) / g_ScaleX - barwidth - 24;
|
|
#else
|
|
// NTSC Beta omits the brackets here. This would normally cause the
|
|
// ammo info to be misaligned for players on the right side of the
|
|
// screen and when using hi-res, but I'm not sure if hi-res can even be
|
|
// active when using multiple players...
|
|
xpos = viGetViewLeft() + viGetViewWidth() / g_ScaleX - barwidth - 24;
|
|
#endif
|
|
|
|
if (playercount == 2 && (optionsGetScreenSplit() == SCREENSPLIT_VERTICAL || IS4MB()) && playernum == 0) {
|
|
xpos += 15;
|
|
} else if (playercount >= 3 && (playernum % 2) == 0) {
|
|
xpos += 15;
|
|
}
|
|
|
|
// Mag
|
|
ammoheld = player->ammoheldarr[ammotype];
|
|
|
|
if (hand->clipsizes[ammoindex] > 0
|
|
&& weapon->ammos[ammoindex] != NULL
|
|
&& (weapon->ammos[ammoindex]->flags & AMMOFLAG_EQUIPPEDISRESERVE) == 0) {
|
|
gdl = bgunDrawHudGauge(gdl, xpos, bottom - reserveheight - clipheight - 3, xpos + barwidth,
|
|
bottom - reserveheight - 3, &hand->abmag, hand->loadedammo[ammoindex], hand->clipsizes[ammoindex],
|
|
0x00300080, 0x00ff0040, false);
|
|
gdl = bgunDrawHudInteger(gdl, hand->loadedammo[ammoindex], xpos - 2, false,
|
|
bottom - reserveheight - 8, 0, 0x00ff00a0);
|
|
}
|
|
|
|
// Reserve
|
|
if (g_AmmoTypes[ammotype].capacity > 0
|
|
&& (weapon->ammos[ammoindex]->flags & AMMOFLAG_NORESERVE) == 0) {
|
|
ammototal = ammoheld;
|
|
|
|
if (weapon->ammos[ammoindex]->flags & AMMOFLAG_EQUIPPEDISRESERVE) {
|
|
if (hand->clipsizes[ammoindex] > 0) {
|
|
ammototal += hand->loadedammo[ammoindex];
|
|
}
|
|
|
|
if (lefthand->clipsizes[ammoindex] > 0) {
|
|
ammototal += lefthand->loadedammo[ammoindex];
|
|
}
|
|
}
|
|
|
|
gdl = bgunDrawHudGauge(gdl, xpos, bottom - reserveheight, xpos + barwidth,
|
|
bottom, &ctrl->abmag, ammototal, g_AmmoTypes[ammotype].capacity,
|
|
0x00403080, 0x00ffc040, true);
|
|
gdl = bgunDrawHudInteger(gdl, ammototal, xpos - 2, false, bottom - reserveheight + 1, 0, 0x00ffc0a0);
|
|
}
|
|
|
|
// Combat boost timer
|
|
if (hand->gset.weaponnum == WEAPON_COMBATBOOST) {
|
|
s32 mins;
|
|
char text[32];
|
|
|
|
speedpilltime = g_Vars.speedpilltime;
|
|
mins = speedpilltime / TICKS(3600);
|
|
secs60 = speedpilltime - mins * TICKS(3600);
|
|
|
|
if (mins >= 1) {
|
|
sprintf(text, "%02d:%02d:%02d\n", mins, secs60 / TICKS(60), (secs60 - (secs60 / TICKS(60)) * TICKS(60)) * 100 / TICKS(60));
|
|
} else {
|
|
sprintf(text, "%02d:%02d\n", secs60 / TICKS(60), (secs60 - (secs60 / TICKS(60)) * TICKS(60)) * 100 / TICKS(60));
|
|
}
|
|
|
|
gdl = bgunDrawHudString(gdl, text, xpos + barwidth - 2, false, bottom - reserveheight + 1, 0, 0x00ffc0a0);
|
|
}
|
|
}
|
|
|
|
gdl = text0f153780(gdl);
|
|
|
|
g_ScaleX = 1;
|
|
|
|
return gdl;
|
|
}
|
|
|
|
void bgunAddBoost(s32 amount)
|
|
{
|
|
g_Vars.speedpilltime += amount;
|
|
|
|
if (g_Vars.speedpilltime > 5 * 60 * TICKS(60)) { // 5 minutes
|
|
g_Vars.speedpilltime = 5 * 60 * TICKS(60);
|
|
}
|
|
|
|
if (!g_Vars.speedpillwant) {
|
|
u32 sound = lvGetSlowMotionType() ? SFX_ARGH_JO_02AD : SFX_JO_BOOST_ACTIVATE;
|
|
|
|
sndStart(var80095200, sound, 0, -1, -1, -1, -1, -1);
|
|
}
|
|
|
|
g_Vars.speedpillwant = true;
|
|
}
|
|
|
|
void bgunSubtractBoost(s32 amount)
|
|
{
|
|
g_Vars.speedpilltime -= amount;
|
|
|
|
if (g_Vars.speedpilltime <= 0) {
|
|
g_Vars.speedpilltime = 0;
|
|
g_Vars.speedpillwant = false;
|
|
}
|
|
}
|
|
|
|
void bgunApplyBoost(void)
|
|
{
|
|
if (lvGetSlowMotionType() != SLOWMOTION_OFF) {
|
|
bgunSubtractBoost(TICKS(1200));
|
|
} else {
|
|
bgunAddBoost(TICKS(600));
|
|
}
|
|
}
|
|
|
|
void bgunRevertBoost(void)
|
|
{
|
|
if (lvGetSlowMotionType() != SLOWMOTION_OFF) {
|
|
bgunAddBoost(TICKS(1200));
|
|
} else {
|
|
bgunSubtractBoost(TICKS(600));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The main tick function as called from lvTick.
|
|
*
|
|
* This function doesn't do much because it's called during both cutscenes and
|
|
* gameplay, while most gun tick operations happen during gameplay only.
|
|
* See bgunTickGameplay for that.
|
|
*/
|
|
void bgunTickBoost(void)
|
|
{
|
|
if (g_Vars.speedpillon && g_Vars.speedpilltime > 0 && !g_Vars.in_cutscene) {
|
|
g_Vars.speedpilltime -= g_Vars.lvupdate60;
|
|
|
|
if (g_Vars.speedpilltime <= 0) {
|
|
g_Vars.speedpilltime = 0;
|
|
g_Vars.speedpillwant = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* gunsightoff is 0 if the full sight is visible, ie. player is holding R.
|
|
*
|
|
* Otherwise, gunsightoff holds bit values for reasons why the sight is off.
|
|
* This is typically 2, which is GUNSIGHTREASON_NOTAIMING.
|
|
*
|
|
* If the visible argument is true, it removes the reason from the field, thus
|
|
* making the sight visible if there are no other reasons.
|
|
*/
|
|
void bgunSetSightVisible(u32 reason, bool visible)
|
|
{
|
|
if (visible) {
|
|
g_Vars.currentplayer->gunsightoff &= ~reason;
|
|
return;
|
|
}
|
|
|
|
g_Vars.currentplayer->gunsightoff |= reason;
|
|
}
|
|
|
|
Gfx *bgunDrawSight(Gfx *gdl)
|
|
{
|
|
if (g_Vars.currentplayer->gunsightoff == 0 && !g_Vars.currentplayer->mpmenuon) {
|
|
// Player is aiming with R
|
|
gdl = sightDraw(gdl, true, currentPlayerGetSight());
|
|
} else {
|
|
gdl = sightDraw(gdl, false, currentPlayerGetSight());
|
|
}
|
|
|
|
return gdl;
|
|
}
|
|
|
|
void bgun0f0abd30(s32 handnum)
|
|
{
|
|
struct player *player = g_Vars.currentplayer;
|
|
struct hand *hand = &player->hands[handnum];
|
|
struct gunctrl *gunctrl = &player->gunctrl;
|
|
struct weapon *weapon = weaponFindById(hand->gset.weaponnum);
|
|
s32 i;
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
if (handnum == HAND_RIGHT) {
|
|
gunctrl->ammotypes[i] = -1;
|
|
}
|
|
|
|
if (weapon && weapon->ammos[i]) {
|
|
if (handnum == HAND_RIGHT) {
|
|
gunctrl->ammotypes[i] = weapon->ammos[i]->type;
|
|
}
|
|
|
|
hand->clipsizes[i] = weapon->ammos[i]->clipsize;
|
|
|
|
if (handnum == HAND_LEFT && hand->gset.weaponnum == WEAPON_REMOTEMINE) {
|
|
hand->clipsizes[i] = 0;
|
|
}
|
|
|
|
hand->loadedammo[i] = 0;
|
|
}
|
|
}
|
|
|
|
hand->upgrademult[0] = 1;
|
|
hand->upgrademult[1] = 1;
|
|
hand->finalmult[0] = 1;
|
|
hand->finalmult[1] = 1;
|
|
|
|
if (gunctrl->ammotypes[0] >= 0) {
|
|
bgunResetAbmag(&hand->abmag);
|
|
|
|
if (handnum == HAND_RIGHT) {
|
|
bgunResetAbmag(&gunctrl->abmag);
|
|
}
|
|
|
|
gunctrl->lastmag = false;
|
|
}
|
|
}
|