From 0aa56dba607e41ae44e2edf0d62c41f3224f876a Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Wed, 25 Nov 2020 00:07:40 +1000 Subject: [PATCH] Discover MP features/unlockables structure and rename many symbols --- src/game/data/data_02a0e0.c | 112 ++++----- src/game/game_00c490.c | 2 +- src/game/game_179060.c | 68 +++--- src/game/game_17f930.c | 18 +- src/game/game_19aa80.c | 251 +++++++++---------- src/game/gamefile.c | 6 +- src/game/mplayer.c | 424 ++++++++++++++++----------------- src/gvars/gvars.c | 6 +- src/include/constants.h | 85 ++++++- src/include/game/game_19aa80.h | 22 +- src/include/game/mplayer.h | 4 +- src/include/gvars/gvars.h | 4 +- src/include/types.h | 31 ++- 13 files changed, 566 insertions(+), 467 deletions(-) diff --git a/src/game/data/data_02a0e0.c b/src/game/data/data_02a0e0.c index db9c01213..6a3266e9f 100644 --- a/src/game/data/data_02a0e0.c +++ b/src/game/data/data_02a0e0.c @@ -736,23 +736,23 @@ struct menudialog menudialog_2aba0 = { // 2abb8 struct mparena g_MpArenas[] = { // Stage, unlock, name - { STAGE_MP_SKEDAR, 0x00, L_MPMENU(119) }, - { STAGE_MP_PIPES, 0x00, L_MPMENU(120) }, - { STAGE_MP_RAVINE, 0x26, L_MPMENU(121) }, - { STAGE_MP_G5BUILDING, 0x28, L_MPMENU(122) }, - { STAGE_MP_SEWERS, 0x2c, L_MPMENU(123) }, - { STAGE_MP_WAREHOUSE, 0x25, L_MPMENU(124) }, - { STAGE_MP_GRID, 0x29, L_MPMENU(125) }, - { STAGE_MP_RUINS, 0x2d, L_MPMENU(126) }, - { STAGE_MP_AREA52, 0x00, L_MPMENU(127) }, - { STAGE_MP_BASE, 0x2e, L_MPMENU(128) }, - { STAGE_MP_FORTRESS, 0x30, L_MPMENU(130) }, - { STAGE_MP_VILLA, 0x2b, L_MPMENU(131) }, - { STAGE_MP_CARPARK, 0x23, L_MPMENU(132) }, - { STAGE_MP_TEMPLE, 0x27, L_MPMENU(133) }, - { STAGE_MP_COMPLEX, 0x24, L_MPMENU(134) }, - { STAGE_MP_FELICITY, 0x2a, L_MPMENU(135) }, - { 1, 0x00, L_MPMENU(136) }, // "Random" + { STAGE_MP_SKEDAR, 0, L_MPMENU(119) }, + { STAGE_MP_PIPES, 0, L_MPMENU(120) }, + { STAGE_MP_RAVINE, MPFEATURE_STAGE_RAVINE, L_MPMENU(121) }, + { STAGE_MP_G5BUILDING, MPFEATURE_STAGE_G5BUILDING, L_MPMENU(122) }, + { STAGE_MP_SEWERS, MPFEATURE_STAGE_SEWERS, L_MPMENU(123) }, + { STAGE_MP_WAREHOUSE, MPFEATURE_STAGE_WAREHOUSE, L_MPMENU(124) }, + { STAGE_MP_GRID, MPFEATURE_STAGE_GRID, L_MPMENU(125) }, + { STAGE_MP_RUINS, MPFEATURE_STAGE_RUINS, L_MPMENU(126) }, + { STAGE_MP_AREA52, 0, L_MPMENU(127) }, + { STAGE_MP_BASE, MPFEATURE_STAGE_BASE, L_MPMENU(128) }, + { STAGE_MP_FORTRESS, MPFEATURE_STAGE_FORTRESS, L_MPMENU(130) }, + { STAGE_MP_VILLA, MPFEATURE_STAGE_VILLA, L_MPMENU(131) }, + { STAGE_MP_CARPARK, MPFEATURE_STAGE_CARPARK, L_MPMENU(132) }, + { STAGE_MP_TEMPLE, MPFEATURE_STAGE_TEMPLE, L_MPMENU(133) }, + { STAGE_MP_COMPLEX, MPFEATURE_STAGE_COMPLEX, L_MPMENU(134) }, + { STAGE_MP_FELICITY, MPFEATURE_STAGE_FELICITY, L_MPMENU(135) }, + { 1, 0, L_MPMENU(136) }, // "Random" }; // 2ac20 @@ -2074,43 +2074,43 @@ u32 var80087264 = 0x00000000; // 2d288 struct mpweapon g_MpWeapons[] = { - /*0x00*/ { WEAPON_NONE, 0x00, 0x00, 0x00, 0x00, 1, 0x00, MODEL_CHRTT33, 0x0100 }, - /*0x01*/ { WEAPON_FALCON2, 0x01, 0x50, 0x00, 0x00, 1, 0x00, MODEL_CHRFALCON2, 0x0100 }, - /*0x02*/ { WEAPON_FALCON2_SILENCER, 0x01, 0x50, 0x00, 0x00, 1, 0x05, MODEL_CHRFALCON2SIL, 0x0100 }, - /*0x03*/ { WEAPON_FALCON2_SCOPE, 0x01, 0x50, 0x00, 0x00, 1, 0x06, MODEL_CHRFALCON2SCOPE, 0x0100 }, - /*0x04*/ { WEAPON_MAGSEC4, 0x01, 0x50, 0x00, 0x00, 1, 0x00, MODEL_CHRLEEGUN1, 0x0100 }, - /*0x05*/ { WEAPON_MAULER, 0x01, 0x5c, 0x00, 0x00, 1, 0x07, MODEL_CHRMAULER, 0x0100 }, - /*0x06*/ { WEAPON_PHOENIX, 0x01, 0x40, 0x00, 0x00, 1, 0x08, MODEL_CHRMAIANPISTOL, 0x0100 }, - /*0x07*/ { WEAPON_DY357MAGNUM, 0x0a, 0x32, 0x00, 0x00, 1, 0x00, MODEL_CHRDY357, 0x0100 }, - /*0x08*/ { WEAPON_DY357LX, 0x0a, 0x32, 0x00, 0x00, 1, 0x09, MODEL_CHRDY357TRENT, 0x0100 }, - /*0x09*/ { WEAPON_CMP150, 0x02, 0x64, 0x00, 0x00, 1, 0x00, MODEL_CHRCMP150, 0x0100 }, - /*0x0a*/ { WEAPON_CYCLONE, 0x02, 0x96, 0x00, 0x00, 1, 0x00, MODEL_CHRCYCLONE, 0x0100 }, - /*0x0b*/ { WEAPON_CALLISTONTG, 0x02, 0x96, 0x00, 0x00, 1, 0x0a, MODEL_CHRMAIANSMG, 0x0100 }, - /*0x0c*/ { WEAPON_RCP120, 0x02, 0x96, 0x00, 0x00, 1, 0x0d, MODEL_CHRRCP120, 0x0100 }, - /*0x0d*/ { WEAPON_LAPTOPGUN, 0x02, 0x96, 0x00, 0x00, 1, 0x0b, MODEL_CHRPCGUN, 0x0100 }, - /*0x0e*/ { WEAPON_DRAGON, 0x04, 0x96, 0x00, 0x00, 1, 0x00, MODEL_CHRDRAGON, 0x0100 }, - /*0x0f*/ { WEAPON_K7AVENGER, 0x04, 0x96, 0x00, 0x00, 1, 0x0c, MODEL_CHRAVENGER, 0x0100 }, - /*0x10*/ { WEAPON_AR34, 0x04, 0x64, 0x00, 0x00, 1, 0x00, MODEL_CHRAR34, 0x0100 }, - /*0x11*/ { WEAPON_SUPERDRAGON, 0x04, 0x96, 0x0b, 0x10, 1, 0x03, MODEL_CHRSUPERDRAGON, 0x0100 }, - /*0x12*/ { WEAPON_SHOTGUN, 0x05, 0x10, 0x00, 0x00, 1, 0x0e, MODEL_CHRSHOTGUN, 0x0100 }, - /*0x13*/ { WEAPON_REAPER, 0x0f, 0xc8, 0x00, 0x00, 1, 0x0f, MODEL_CHRSKMINIGUN, 0x0100 }, - /*0x14*/ { WEAPON_SNIPERRIFLE, 0x04, 0x32, 0x00, 0x00, 1, 0x00, MODEL_CHRSNIPERRIFLE, 0x0100 }, - /*0x15*/ { WEAPON_FARSIGHTXR20, 0x06, 0x0a, 0x00, 0x00, 1, 0x01, MODEL_CHRZ2020, 0x0100 }, - /*0x16*/ { WEAPON_DEVASTATOR, 0x0b, 0x10, 0x00, 0x00, 1, 0x10, MODEL_CHRDEVASTATOR, 0x0100 }, - /*0x17*/ { WEAPON_ROCKETLAUNCHER, 0x08, 0x03, 0x00, 0x00, 1, 0x00, MODEL_CHRDYROCKET, 0x0100 }, - /*0x18*/ { WEAPON_SLAYER, 0x08, 0x03, 0x00, 0x00, 1, 0x04, MODEL_CHRSKROCKET, 0x0100 }, - /*0x19*/ { WEAPON_COMBATKNIFE, 0x09, 0x05, 0x00, 0x00, 1, 0x00, MODEL_CHRKNIFE, 0x0100 }, - /*0x1a*/ { WEAPON_CROSSBOW, 0x03, 0x0a, 0x00, 0x00, 1, 0x11, MODEL_CHRCROSSBOW, 0x0100 }, - /*0x1b*/ { WEAPON_TRANQUILIZER, 0x13, 0x32, 0x00, 0x00, 1, 0x02, MODEL_CHRDRUGGUN, 0x0100 }, - /*0x1c*/ { WEAPON_GRENADE, 0x07, 0x05, 0x00, 0x00, 0, 0x00, MODEL_CHRGRENADE, 0x0100 }, - /*0x1d*/ { WEAPON_NBOMB, 0x12, 0x03, 0x00, 0x00, 0, 0x12, MODEL_CHRNBOMB, 0x0100 }, - /*0x1e*/ { WEAPON_TIMEDMINE, 0x0e, 0x05, 0x00, 0x00, 0, 0x00, MODEL_CHRTIMEDMINE, 0x0180 }, - /*0x1f*/ { WEAPON_PROXIMITYMINE, 0x0d, 0x05, 0x00, 0x00, 0, 0x13, MODEL_CHRPROXIMITYMINE, 0x0180 }, - /*0x20*/ { WEAPON_REMOTEMINE, 0x0c, 0x05, 0x00, 0x00, 0, 0x14, MODEL_CHRREMOTEMINE, 0x0180 }, - /*0x21*/ { WEAPON_LASER, 0x00, 0x00, 0x00, 0x00, 1, 0x4f, MODEL_CHRLASER, 0x0200 }, - /*0x22*/ { WEAPON_XRAYSCANNER, 0x00, 0x00, 0x00, 0x00, 1, 0x15, MODEL_CHRNIGHTSIGHT, 0x0100 }, - /*0x23*/ { WEAPON_CLOAKINGDEVICE, 0x00, 0x00, 0x00, 0x00, 1, 0x17, MODEL_CHRCLOAKER, 0x0100 }, - /*0x24*/ { WEAPON_COMBATBOOST, 0x00, 0x00, 0x00, 0x00, 1, 0x18, MODEL_CHRSPEEDPILL, 0x0100 }, - /*0x25*/ { WEAPON_MPSHIELD, 0x00, 0x00, 0x00, 0x00, 1, 0x16, MODEL_CHRSHIELD, 0x0100 }, - /*0x26*/ { WEAPON_DISABLED, 0x00, 0x00, 0x00, 0x00, 0, 0x00, 0, 0x0000 }, + /*0x00*/ { WEAPON_NONE, 0x00, 0x00, 0x00, 0x00, 1, 0, MODEL_CHRTT33, 0x0100 }, + /*0x01*/ { WEAPON_FALCON2, 0x01, 0x50, 0x00, 0x00, 1, 0, MODEL_CHRFALCON2, 0x0100 }, + /*0x02*/ { WEAPON_FALCON2_SILENCER, 0x01, 0x50, 0x00, 0x00, 1, MPFEATURE_WEAPON_FALCON2SILENCED, MODEL_CHRFALCON2SIL, 0x0100 }, + /*0x03*/ { WEAPON_FALCON2_SCOPE, 0x01, 0x50, 0x00, 0x00, 1, MPFEATURE_WEAPON_FALCON2SCOPE, MODEL_CHRFALCON2SCOPE, 0x0100 }, + /*0x04*/ { WEAPON_MAGSEC4, 0x01, 0x50, 0x00, 0x00, 1, 0, MODEL_CHRLEEGUN1, 0x0100 }, + /*0x05*/ { WEAPON_MAULER, 0x01, 0x5c, 0x00, 0x00, 1, MPFEATURE_WEAPON_MAULER, MODEL_CHRMAULER, 0x0100 }, + /*0x06*/ { WEAPON_PHOENIX, 0x01, 0x40, 0x00, 0x00, 1, MPFEATURE_WEAPON_PHOENIX, MODEL_CHRMAIANPISTOL, 0x0100 }, + /*0x07*/ { WEAPON_DY357MAGNUM, 0x0a, 0x32, 0x00, 0x00, 1, 0, MODEL_CHRDY357, 0x0100 }, + /*0x08*/ { WEAPON_DY357LX, 0x0a, 0x32, 0x00, 0x00, 1, MPFEATURE_WEAPON_DY357LX, MODEL_CHRDY357TRENT, 0x0100 }, + /*0x09*/ { WEAPON_CMP150, 0x02, 0x64, 0x00, 0x00, 1, 0, MODEL_CHRCMP150, 0x0100 }, + /*0x0a*/ { WEAPON_CYCLONE, 0x02, 0x96, 0x00, 0x00, 1, 0, MODEL_CHRCYCLONE, 0x0100 }, + /*0x0b*/ { WEAPON_CALLISTONTG, 0x02, 0x96, 0x00, 0x00, 1, MPFEATURE_WEAPON_CALLISTO, MODEL_CHRMAIANSMG, 0x0100 }, + /*0x0c*/ { WEAPON_RCP120, 0x02, 0x96, 0x00, 0x00, 1, MPFEATURE_WEAPON_RCP120, MODEL_CHRRCP120, 0x0100 }, + /*0x0d*/ { WEAPON_LAPTOPGUN, 0x02, 0x96, 0x00, 0x00, 1, MPFEATURE_WEAPON_LAPTOPGUN, MODEL_CHRPCGUN, 0x0100 }, + /*0x0e*/ { WEAPON_DRAGON, 0x04, 0x96, 0x00, 0x00, 1, 0, MODEL_CHRDRAGON, 0x0100 }, + /*0x0f*/ { WEAPON_K7AVENGER, 0x04, 0x96, 0x00, 0x00, 1, MPFEATURE_WEAPON_K7AVENGER, MODEL_CHRAVENGER, 0x0100 }, + /*0x10*/ { WEAPON_AR34, 0x04, 0x64, 0x00, 0x00, 1, 0, MODEL_CHRAR34, 0x0100 }, + /*0x11*/ { WEAPON_SUPERDRAGON, 0x04, 0x96, 0x0b, 0x10, 1, MPFEATURE_WEAPON_SUPERDRAGON, MODEL_CHRSUPERDRAGON, 0x0100 }, + /*0x12*/ { WEAPON_SHOTGUN, 0x05, 0x10, 0x00, 0x00, 1, MPFEATURE_WEAPON_SHOTGUN, MODEL_CHRSHOTGUN, 0x0100 }, + /*0x13*/ { WEAPON_REAPER, 0x0f, 0xc8, 0x00, 0x00, 1, MPFEATURE_WEAPON_REAPER, MODEL_CHRSKMINIGUN, 0x0100 }, + /*0x14*/ { WEAPON_SNIPERRIFLE, 0x04, 0x32, 0x00, 0x00, 1, 0, MODEL_CHRSNIPERRIFLE, 0x0100 }, + /*0x15*/ { WEAPON_FARSIGHTXR20, 0x06, 0x0a, 0x00, 0x00, 1, MPFEATURE_WEAPON_FARSIGHT, MODEL_CHRZ2020, 0x0100 }, + /*0x16*/ { WEAPON_DEVASTATOR, 0x0b, 0x10, 0x00, 0x00, 1, MPFEATURE_WEAPON_DEVASTATOR, MODEL_CHRDEVASTATOR, 0x0100 }, + /*0x17*/ { WEAPON_ROCKETLAUNCHER, 0x08, 0x03, 0x00, 0x00, 1, 0, MODEL_CHRDYROCKET, 0x0100 }, + /*0x18*/ { WEAPON_SLAYER, 0x08, 0x03, 0x00, 0x00, 1, MPFEATURE_WEAPON_SLAYER, MODEL_CHRSKROCKET, 0x0100 }, + /*0x19*/ { WEAPON_COMBATKNIFE, 0x09, 0x05, 0x00, 0x00, 1, 0, MODEL_CHRKNIFE, 0x0100 }, + /*0x1a*/ { WEAPON_CROSSBOW, 0x03, 0x0a, 0x00, 0x00, 1, MPFEATURE_WEAPON_CROSSBOW, MODEL_CHRCROSSBOW, 0x0100 }, + /*0x1b*/ { WEAPON_TRANQUILIZER, 0x13, 0x32, 0x00, 0x00, 1, MPFEATURE_WEAPON_TRANQUILIZER, MODEL_CHRDRUGGUN, 0x0100 }, + /*0x1c*/ { WEAPON_GRENADE, 0x07, 0x05, 0x00, 0x00, 0, 0, MODEL_CHRGRENADE, 0x0100 }, + /*0x1d*/ { WEAPON_NBOMB, 0x12, 0x03, 0x00, 0x00, 0, MPFEATURE_WEAPON_NBOMB, MODEL_CHRNBOMB, 0x0100 }, + /*0x1e*/ { WEAPON_TIMEDMINE, 0x0e, 0x05, 0x00, 0x00, 0, 0, MODEL_CHRTIMEDMINE, 0x0180 }, + /*0x1f*/ { WEAPON_PROXIMITYMINE, 0x0d, 0x05, 0x00, 0x00, 0, MPFEATURE_WEAPON_PROXIMITYMINE, MODEL_CHRPROXIMITYMINE, 0x0180 }, + /*0x20*/ { WEAPON_REMOTEMINE, 0x0c, 0x05, 0x00, 0x00, 0, MPFEATURE_WEAPON_REMOTEMINE, MODEL_CHRREMOTEMINE, 0x0180 }, + /*0x21*/ { WEAPON_LASER, 0x00, 0x00, 0x00, 0x00, 1, MPFEATURE_WEAPON_LASER, MODEL_CHRLASER, 0x0200 }, + /*0x22*/ { WEAPON_XRAYSCANNER, 0x00, 0x00, 0x00, 0x00, 1, MPFEATURE_WEAPON_XRAYSCANNER, MODEL_CHRNIGHTSIGHT, 0x0100 }, + /*0x23*/ { WEAPON_CLOAKINGDEVICE, 0x00, 0x00, 0x00, 0x00, 1, MPFEATURE_WEAPON_CLOAKINGDEVICE, MODEL_CHRCLOAKER, 0x0100 }, + /*0x24*/ { WEAPON_COMBATBOOST, 0x00, 0x00, 0x00, 0x00, 1, MPFEATURE_WEAPON_COMBATBOOST, MODEL_CHRSPEEDPILL, 0x0100 }, + /*0x25*/ { WEAPON_MPSHIELD, 0x00, 0x00, 0x00, 0x00, 1, MPFEATURE_WEAPON_SHIELD, MODEL_CHRSHIELD, 0x0100 }, + /*0x26*/ { WEAPON_DISABLED, 0x00, 0x00, 0x00, 0x00, 0, 0x00, 0, 0x0000 }, }; diff --git a/src/game/game_00c490.c b/src/game/game_00c490.c index 28f5f7f2a..8232a0975 100644 --- a/src/game/game_00c490.c +++ b/src/game/game_00c490.c @@ -3277,7 +3277,7 @@ void setupParseObjects(s32 stagenum) s32 maxsimulants; s32 slotnum; - if (mpIsChallengeComplete(CHALLENGE_UNK64)) { + if (mpIsFeatureUnlocked(MPFEATURE_8BOTS)) { maxsimulants = 8; } else { maxsimulants = 4; diff --git a/src/game/game_179060.c b/src/game/game_179060.c index 73fb0b375..9022d7a27 100644 --- a/src/game/game_179060.c +++ b/src/game/game_179060.c @@ -123,7 +123,7 @@ s16 mpChooseRandomStage(void) s32 index; for (i = 0; i < 16; i++) { - if (mpIsChallengeComplete(g_MpArenas[i].unlock)) { + if (mpIsFeatureUnlocked(g_MpArenas[i].requirefeature)) { numchallengescomplete++; } } @@ -131,7 +131,7 @@ s16 mpChooseRandomStage(void) index = random() % numchallengescomplete; for (i = 0; i < 16; i++) { - if (mpIsChallengeComplete(g_MpArenas[i].unlock)) { + if (mpIsFeatureUnlocked(g_MpArenas[i].requirefeature)) { if (index == 0) { return g_MpArenas[i].stagenum; } @@ -196,7 +196,7 @@ glabel var7f1b8074 /* f179248: 3c108008 */ lui $s0,%hi(g_MpArenas) /* f17924c: 26104b98 */ addiu $s0,$s0,%lo(g_MpArenas) .L0f179250: -/* f179250: 0fc67244 */ jal mpIsChallengeComplete +/* f179250: 0fc67244 */ jal mpIsFeatureUnlocked /* f179254: 92040002 */ lbu $a0,0x2($s0) /* f179258: 10400002 */ beqz $v0,.L0f179264 /* f17925c: 26100006 */ addiu $s0,$s0,0x6 @@ -211,7 +211,7 @@ glabel var7f1b8074 /* f17927c: 3c108008 */ lui $s0,%hi(g_MpArenas) /* f179280: 26104b98 */ addiu $s0,$s0,%lo(g_MpArenas) .L0f179284: -/* f179284: 0fc67244 */ jal mpIsChallengeComplete +/* f179284: 0fc67244 */ jal mpIsFeatureUnlocked /* f179288: 92040002 */ lbu $a0,0x2($s0) /* f17928c: 10400009 */ beqz $v0,.L0f1792b4 /* f179290: 3c0c8008 */ lui $t4,%hi(g_MpArenas+0x66) @@ -233,7 +233,7 @@ glabel var7f1b8074 /* f1792cc: 3c108008 */ lui $s0,%hi(g_MpArenas) /* f1792d0: 26104b98 */ addiu $s0,$s0,%lo(g_MpArenas) .L0f1792d4: -/* f1792d4: 0fc67244 */ jal mpIsChallengeComplete +/* f1792d4: 0fc67244 */ jal mpIsFeatureUnlocked /* f1792d8: 92040002 */ lbu $a0,0x2($s0) /* f1792dc: 10400004 */ beqz $v0,.L0f1792f0 /* f1792e0: 3c198008 */ lui $t9,%hi(g_MpArenas+0x66) @@ -260,7 +260,7 @@ glabel var7f1b8074 /* f179328: 00000000 */ nop /* f17932c: ae510000 */ sw $s1,0x0($s2) .L0f179330: -/* f179330: 0fc67244 */ jal mpIsChallengeComplete +/* f179330: 0fc67244 */ jal mpIsFeatureUnlocked /* f179334: 92040002 */ lbu $a0,0x2($s0) /* f179338: 10400002 */ beqz $v0,.L0f179344 /* f17933c: 26100006 */ addiu $s0,$s0,0x6 @@ -274,15 +274,15 @@ glabel var7f1b8074 /* f179358: 00001025 */ or $v0,$zero,$zero /* f17935c: 24090003 */ addiu $t1,$zero,0x3 /* f179360: ae490000 */ sw $t1,0x0($s2) -/* f179364: 0fc67244 */ jal mpIsChallengeComplete +/* f179364: 0fc67244 */ jal mpIsFeatureUnlocked /* f179368: 24040024 */ addiu $a0,$zero,0x24 /* f17936c: 5440004b */ bnezl $v0,.L0f17949c /* f179370: 00001025 */ or $v0,$zero,$zero -/* f179374: 0fc67244 */ jal mpIsChallengeComplete +/* f179374: 0fc67244 */ jal mpIsFeatureUnlocked /* f179378: 24040027 */ addiu $a0,$zero,0x27 /* f17937c: 54400047 */ bnezl $v0,.L0f17949c /* f179380: 00001025 */ or $v0,$zero,$zero -/* f179384: 0fc67244 */ jal mpIsChallengeComplete +/* f179384: 0fc67244 */ jal mpIsFeatureUnlocked /* f179388: 2404002a */ addiu $a0,$zero,0x2a /* f17938c: 54400043 */ bnezl $v0,.L0f17949c /* f179390: 00001025 */ or $v0,$zero,$zero @@ -291,15 +291,15 @@ glabel var7f1b8074 /* f17939c: 1000003e */ b .L0f179498 /* f1793a0: ae4b0000 */ sw $t3,0x0($s2) /* f1793a4: 8e510000 */ lw $s1,0x0($s2) -/* f1793a8: 0fc67244 */ jal mpIsChallengeComplete +/* f1793a8: 0fc67244 */ jal mpIsFeatureUnlocked /* f1793ac: 24040024 */ addiu $a0,$zero,0x24 /* f1793b0: 5440000d */ bnezl $v0,.L0f1793e8 /* f1793b4: 001160c0 */ sll $t4,$s1,0x3 -/* f1793b8: 0fc67244 */ jal mpIsChallengeComplete +/* f1793b8: 0fc67244 */ jal mpIsFeatureUnlocked /* f1793bc: 24040027 */ addiu $a0,$zero,0x27 /* f1793c0: 54400009 */ bnezl $v0,.L0f1793e8 /* f1793c4: 001160c0 */ sll $t4,$s1,0x3 -/* f1793c8: 0fc67244 */ jal mpIsChallengeComplete +/* f1793c8: 0fc67244 */ jal mpIsFeatureUnlocked /* f1793cc: 2404002a */ addiu $a0,$zero,0x2a /* f1793d0: 54400005 */ bnezl $v0,.L0f1793e8 /* f1793d4: 001160c0 */ sll $t4,$s1,0x3 @@ -314,15 +314,15 @@ glabel var7f1b8074 /* f1793f4: 1000002a */ b .L0f1794a0 /* f1793f8: 8fbf0024 */ lw $ra,0x24($sp) /* f1793fc: 8e500000 */ lw $s0,0x0($s2) -/* f179400: 0fc67244 */ jal mpIsChallengeComplete +/* f179400: 0fc67244 */ jal mpIsFeatureUnlocked /* f179404: 24040024 */ addiu $a0,$zero,0x24 /* f179408: 5440000d */ bnezl $v0,.L0f179440 /* f17940c: 001068c0 */ sll $t5,$s0,0x3 -/* f179410: 0fc67244 */ jal mpIsChallengeComplete +/* f179410: 0fc67244 */ jal mpIsFeatureUnlocked /* f179414: 24040027 */ addiu $a0,$zero,0x27 /* f179418: 54400009 */ bnezl $v0,.L0f179440 /* f17941c: 001068c0 */ sll $t5,$s0,0x3 -/* f179420: 0fc67244 */ jal mpIsChallengeComplete +/* f179420: 0fc67244 */ jal mpIsFeatureUnlocked /* f179424: 2404002a */ addiu $a0,$zero,0x2a /* f179428: 14400004 */ bnez $v0,.L0f17943c /* f17942c: 24010001 */ addiu $at,$zero,0x1 @@ -342,7 +342,7 @@ glabel var7f1b8074 /* f17945c: 92040002 */ lbu $a0,0x2($s0) .L0f179460: /* f179460: afa3003c */ sw $v1,0x3c($sp) -/* f179464: 0fc67244 */ jal mpIsChallengeComplete +/* f179464: 0fc67244 */ jal mpIsFeatureUnlocked /* f179468: afa5002c */ sw $a1,0x2c($sp) /* f17946c: 8fa3003c */ lw $v1,0x3c($sp) /* f179470: 10400002 */ beqz $v0,.L0f17947c @@ -884,9 +884,9 @@ glabel var7f1b80dc /* f179ea0: ac400df4 */ sw $zero,0xdf4($v0) /* f179ea4: 1000005b */ b .L0f17a014 /* f179ea8: e4500d94 */ swc1 $f16,0xd94($v0) -/* f179eac: 0fc62f1c */ jal mpGetBodyUnk06 +/* f179eac: 0fc62f1c */ jal mpGetBodyRequiredFeature /* f179eb0: 90c40003 */ lbu $a0,0x3($a2) -/* f179eb4: 0fc67244 */ jal mpIsChallengeComplete +/* f179eb4: 0fc67244 */ jal mpIsFeatureUnlocked /* f179eb8: 00402025 */ or $a0,$v0,$zero /* f179ebc: 54400056 */ bnezl $v0,.L0f17a018 /* f179ec0: 00001025 */ or $v0,$zero,$zero @@ -1053,7 +1053,7 @@ glabel menuhandler0017a20c /* f17a264: 00001025 */ or $v0,$zero,$zero .L0f17a268: /* f17a268: 3c048007 */ lui $a0,%hi(g_MpPlayerNum) -/* f17a26c: 0fc670b3 */ jal mpGetNumChallengesAvailable +/* f17a26c: 0fc670b3 */ jal mpGetAutoFocusedChallengeIndex /* f17a270: 8c841448 */ lw $a0,%lo(g_MpPlayerNum)($a0) /* f17a274: 100000eb */ b .L0f17a624 /* f17a278: ae020000 */ sw $v0,0x0($s0) @@ -1187,7 +1187,7 @@ glabel menuhandler0017a20c /* f17a46c: 24720001 */ addiu $s2,$v1,0x1 /* f17a470: 02403025 */ or $a2,$s2,$zero /* f17a474: 8c841448 */ lw $a0,%lo(g_MpPlayerNum)($a0) -/* f17a478: 0fc670ef */ jal func0f19c3bc +/* f17a478: 0fc670ef */ jal mpIsChallengeCompletedByPlayerWithNumPlayers2 /* f17a47c: 8fa500bc */ lw $a1,0xbc($sp) /* f17a480: 1040000d */ beqz $v0,.L0f17a4b8 /* f17a484: 8fae00c4 */ lw $t6,0xc4($sp) @@ -2556,9 +2556,9 @@ glabel var7f1b814c /* f17b6d4: ac690df4 */ sw $t1,0xdf4($v1) /* f17b6d8: 10000054 */ b .L0f17b82c /* f17b6dc: e4700d94 */ swc1 $f16,0xd94($v1) -/* f17b6e0: 0fc62ed2 */ jal mpGetHeadUnlockValue +/* f17b6e0: 0fc62ed2 */ jal mpGetHeadRequiredFeature /* f17b6e4: 90c40003 */ lbu $a0,0x3($a2) -/* f17b6e8: 0fc67244 */ jal mpIsChallengeComplete +/* f17b6e8: 0fc67244 */ jal mpIsFeatureUnlocked /* f17b6ec: 00402025 */ or $a0,$v0,$zero /* f17b6f0: 5440004f */ bnezl $v0,.L0f17b830 /* f17b6f4: 00001025 */ or $v0,$zero,$zero @@ -3549,7 +3549,7 @@ glabel var7f1b81e8 /* f17c724: 263177bc */ addiu $s1,$s1,%lo(g_MpBodies) /* f17c728: 2610772c */ addiu $s0,$s0,%lo(g_MpSimulantTypes) .L0f17c72c: -/* f17c72c: 0fc67244 */ jal mpIsChallengeComplete +/* f17c72c: 0fc67244 */ jal mpIsFeatureUnlocked /* f17c730: 92040006 */ lbu $a0,0x6($s0) /* f17c734: 10400002 */ beqz $v0,.L0f17c740 /* f17c738: 26100008 */ addiu $s0,$s0,0x8 @@ -3564,7 +3564,7 @@ glabel var7f1b81e8 /* f17c758: 263177bc */ addiu $s1,$s1,%lo(g_MpBodies) /* f17c75c: 2610772c */ addiu $s0,$s0,%lo(g_MpSimulantTypes) .L0f17c760: -/* f17c760: 0fc67244 */ jal mpIsChallengeComplete +/* f17c760: 0fc67244 */ jal mpIsFeatureUnlocked /* f17c764: 92040006 */ lbu $a0,0x6($s0) /* f17c768: 5040000a */ beqzl $v0,.L0f17c794 /* f17c76c: 26100008 */ addiu $s0,$s0,0x8 @@ -3621,7 +3621,7 @@ glabel var7f1b81e8 /* f17c828: 00008825 */ or $s1,$zero,$zero /* f17c82c: 24130012 */ addiu $s3,$zero,0x12 .L0f17c830: -/* f17c830: 0fc67244 */ jal mpIsChallengeComplete +/* f17c830: 0fc67244 */ jal mpIsFeatureUnlocked /* f17c834: 92040006 */ lbu $a0,0x6($s0) /* f17c838: 50400005 */ beqzl $v0,.L0f17c850 /* f17c83c: 26310001 */ addiu $s1,$s1,0x1 @@ -3679,7 +3679,7 @@ glabel var7f1b81e8 /* f17c8fc: 00008825 */ or $s1,$zero,$zero /* f17c900: 24130012 */ addiu $s3,$zero,0x12 .L0f17c904: -/* f17c904: 0fc67244 */ jal mpIsChallengeComplete +/* f17c904: 0fc67244 */ jal mpIsFeatureUnlocked /* f17c908: 92040006 */ lbu $a0,0x6($s0) /* f17c90c: 50400005 */ beqzl $v0,.L0f17c924 /* f17c910: 26310001 */ addiu $s1,$s1,0x1 @@ -3737,7 +3737,7 @@ glabel var7f1b81e8 /* f17c9d8: 59e00010 */ blezl $t7,.L0f17ca1c /* f17c9dc: ae920008 */ sw $s2,0x8($s4) .L0f17c9e0: -/* f17c9e0: 0fc67244 */ jal mpIsChallengeComplete +/* f17c9e0: 0fc67244 */ jal mpIsFeatureUnlocked /* f17c9e4: 92040006 */ lbu $a0,0x6($s0) /* f17c9e8: 50400003 */ beqzl $v0,.L0f17c9f8 /* f17c9ec: 8e990000 */ lw $t9,0x0($s4) @@ -3905,7 +3905,7 @@ glabel menuhandlerMpSimulantDifficulty /* f17ceb4: 2631775c */ addiu $s1,$s1,%lo(g_MpSimulantTypes+0x30) /* f17ceb8: 2610772c */ addiu $s0,$s0,%lo(g_MpSimulantTypes) .L0f17cebc: -/* f17cebc: 0fc67244 */ jal mpIsChallengeComplete +/* f17cebc: 0fc67244 */ jal mpIsFeatureUnlocked /* f17cec0: 92040006 */ lbu $a0,0x6($s0) /* f17cec4: 10400002 */ beqz $v0,.L0f17ced0 /* f17cec8: 26100008 */ addiu $s0,$s0,0x8 @@ -3920,7 +3920,7 @@ glabel menuhandlerMpSimulantDifficulty /* f17cee4: 2610772c */ addiu $s0,$s0,%lo(g_MpSimulantTypes) /* f17cee8: 24130006 */ addiu $s3,$zero,0x6 .L0f17ceec: -/* f17ceec: 0fc67244 */ jal mpIsChallengeComplete +/* f17ceec: 0fc67244 */ jal mpIsFeatureUnlocked /* f17cef0: 92040006 */ lbu $a0,0x6($s0) /* f17cef4: 5040000a */ beqzl $v0,.L0f17cf20 /* f17cef8: 26310001 */ addiu $s1,$s1,0x1 @@ -4011,7 +4011,7 @@ s32 menuhandlerMpChangeSimulantType(u32 operation, struct menuitem *item, union g_MpSimulants[g_Menus[g_MpPlayerNum].data.mpsetup.slotindex].skill); for (i = 0; i < simtypeindex; i++) { - if (mpIsChallengeComplete(g_MpSimulantTypes[i].unlockvalue)) { + if (mpIsFeatureUnlocked(g_MpSimulantTypes[i].requirefeature)) { count++; } } @@ -4067,7 +4067,7 @@ s32 menuhandlerMpSimulantSlot(u32 operation, struct menuitem *item, union handle } break; case MENUOP_CHECKHIDDEN: - if (item->param >= 4 && !mpIsChallengeComplete(CHALLENGE_UNK64)) { + if (item->param >= 4 && !mpIsFeatureUnlocked(MPFEATURE_8BOTS)) { return true; } break; @@ -6124,7 +6124,7 @@ s32 menuhandlerMpNumberOfSimulants(u32 operation, struct menuitem *item, union h { switch (operation) { case MENUOP_GETOPTIONCOUNT: - data->dropdown.value = !mpIsChallengeComplete(CHALLENGE_UNK64) ? 4 : 8; + data->dropdown.value = !mpIsFeatureUnlocked(MPFEATURE_8BOTS) ? 4 : 8; break; case MENUOP_GETOPTIONTEXT: sprintf(g_StringPointer, "%d\n", data->dropdown.value + 1); @@ -6247,7 +6247,7 @@ glabel var7f1b8430 /* f17f7a0: 2631775c */ addiu $s1,$s1,%lo(g_MpSimulantTypes+0x30) /* f17f7a4: 2610772c */ addiu $s0,$s0,%lo(g_MpSimulantTypes) .L0f17f7a8: -/* f17f7a8: 0fc67244 */ jal mpIsChallengeComplete +/* f17f7a8: 0fc67244 */ jal mpIsFeatureUnlocked /* f17f7ac: 92040006 */ lbu $a0,0x6($s0) /* f17f7b0: 10400002 */ beqz $v0,.L0f17f7bc /* f17f7b4: 26100008 */ addiu $s0,$s0,0x8 @@ -6262,7 +6262,7 @@ glabel var7f1b8430 /* f17f7d4: 00008825 */ or $s1,$zero,$zero /* f17f7d8: 24130006 */ addiu $s3,$zero,0x6 .L0f17f7dc: -/* f17f7dc: 0fc67244 */ jal mpIsChallengeComplete +/* f17f7dc: 0fc67244 */ jal mpIsFeatureUnlocked /* f17f7e0: 92040006 */ lbu $a0,0x6($s0) /* f17f7e4: 5040000a */ beqzl $v0,.L0f17f810 /* f17f7e8: 26310001 */ addiu $s1,$s1,0x1 diff --git a/src/game/game_17f930.c b/src/game/game_17f930.c index 87ec072ad..384e15256 100644 --- a/src/game/game_17f930.c +++ b/src/game/game_17f930.c @@ -328,7 +328,7 @@ s32 menuhandlerMpDisplayTeam(u32 operation, struct menuitem *item, union handler s32 menuhandlerMpOneHitKills(u32 operation, struct menuitem *item, union handlerdata *data) { if (operation == MENUOP_CHECKDISABLED || operation == MENUOP_CHECKHIDDEN) { - if (mpIsChallengeComplete(CHALLENGE_7)) { + if (mpIsFeatureUnlocked(MPFEATURE_ONEHITKILLS)) { return false; } @@ -409,7 +409,7 @@ glabel var7f1b8938 /* f17fe90: 8c2888dc */ lw $t0,%lo(var7f1b88dc)($at) /* f17fe94: 01000008 */ jr $t0 /* f17fe98: 00000000 */ nop -/* f17fe9c: 0fc67244 */ jal mpIsChallengeComplete +/* f17fe9c: 0fc67244 */ jal mpIsFeatureUnlocked /* f17fea0: 2404001d */ addiu $a0,$zero,0x1d /* f17fea4: 10400003 */ beqz $v0,.L0f17feb4 /* f17fea8: 00000000 */ nop @@ -5220,7 +5220,7 @@ glabel var7f1b897c /* f185118: 2631716c */ addiu $s1,$s1,%lo(var8008716c) /* f18511c: 26107148 */ addiu $s0,$s0,%lo(g_MpScenarioOverviews) .L0f185120: -/* f185120: 0fc67244 */ jal mpIsChallengeComplete +/* f185120: 0fc67244 */ jal mpIsFeatureUnlocked /* f185124: 92040004 */ lbu $a0,0x4($s0) /* f185128: 50400008 */ beqzl $v0,.L0f18514c /* f18512c: 26100006 */ addiu $s0,$s0,0x6 @@ -5242,7 +5242,7 @@ glabel var7f1b897c /* f185164: 2631716c */ addiu $s1,$s1,%lo(var8008716c) /* f185168: 26107148 */ addiu $s0,$s0,%lo(g_MpScenarioOverviews) .L0f18516c: -/* f18516c: 0fc67244 */ jal mpIsChallengeComplete +/* f18516c: 0fc67244 */ jal mpIsFeatureUnlocked /* f185170: 92040004 */ lbu $a0,0x4($s0) /* f185174: 5040000f */ beqzl $v0,.L0f1851b4 /* f185178: 26100006 */ addiu $s0,$s0,0x6 @@ -5272,7 +5272,7 @@ glabel var7f1b897c /* f1851cc: 00008825 */ or $s1,$zero,$zero /* f1851d0: 24130006 */ addiu $s3,$zero,0x6 .L0f1851d4: -/* f1851d4: 0fc67244 */ jal mpIsChallengeComplete +/* f1851d4: 0fc67244 */ jal mpIsFeatureUnlocked /* f1851d8: 92040004 */ lbu $a0,0x4($s0) /* f1851dc: 5040000d */ beqzl $v0,.L0f185214 /* f1851e0: 26310001 */ addiu $s1,$s1,0x1 @@ -5303,7 +5303,7 @@ glabel var7f1b897c /* f185234: 00008825 */ or $s1,$zero,$zero /* f185238: 24130006 */ addiu $s3,$zero,0x6 .L0f18523c: -/* f18523c: 0fc67244 */ jal mpIsChallengeComplete +/* f18523c: 0fc67244 */ jal mpIsFeatureUnlocked /* f185240: 92040004 */ lbu $a0,0x4($s0) /* f185244: 5040000d */ beqzl $v0,.L0f18527c /* f185248: 26310001 */ addiu $s1,$s1,0x1 @@ -5329,11 +5329,11 @@ glabel var7f1b897c /* f18528c: 24190002 */ addiu $t9,$zero,0x2 /* f185290: 12800009 */ beqz $s4,.L0f1852b8 /* f185294: aeb90000 */ sw $t9,0x0($s5) -/* f185298: 0fc67244 */ jal mpIsChallengeComplete +/* f185298: 0fc67244 */ jal mpIsFeatureUnlocked /* f18529c: 2404001f */ addiu $a0,$zero,0x1f /* f1852a0: 5440002e */ bnezl $v0,.L0f18535c /* f1852a4: 00001025 */ or $v0,$zero,$zero -/* f1852a8: 0fc67244 */ jal mpIsChallengeComplete +/* f1852a8: 0fc67244 */ jal mpIsFeatureUnlocked /* f1852ac: 24040021 */ addiu $a0,$zero,0x21 /* f1852b0: 5440002a */ bnezl $v0,.L0f18535c /* f1852b4: 00001025 */ or $v0,$zero,$zero @@ -5359,7 +5359,7 @@ glabel var7f1b897c /* f185300: 59c00015 */ blezl $t6,.L0f185358 /* f185304: aeb20008 */ sw $s2,0x8($s5) .L0f185308: -/* f185308: 0fc67244 */ jal mpIsChallengeComplete +/* f185308: 0fc67244 */ jal mpIsFeatureUnlocked /* f18530c: 92040004 */ lbu $a0,0x4($s0) /* f185310: 50400008 */ beqzl $v0,.L0f185334 /* f185314: 8ea80000 */ lw $t0,0x0($s5) diff --git a/src/game/game_19aa80.c b/src/game/game_19aa80.c index 72f9f6cc7..85f630599 100644 --- a/src/game/game_19aa80.c +++ b/src/game/game_19aa80.c @@ -377,18 +377,18 @@ glabel func0f19ab70 /* f19af38: 000f102b */ sltu $v0,$zero,$t7 ); -bool func0f19af3c(s32 chrnum, s32 challengeindex) +bool mpIsChallengeAvailableToPlayer(s32 chrnum, s32 challengeindex) { if ((g_MpSetup.chrslots & (1 << chrnum)) == 0) { return 0; } - return ((g_MpChallenges[challengeindex].completions[0] & (2 << chrnum)) != 0); + return ((g_MpChallenges[challengeindex].availability & (2 << chrnum)) != 0); } -bool mpIsChallengeAvailable(s32 challengeindex) +bool mpIsChallengeAvailableToAnyPlayer(s32 challengeindex) { - return (g_MpChallenges[challengeindex].completions[0] & (((g_MpSetup.chrslots & 0xf) << 1) | 1)) != 0; + return (g_MpChallenges[challengeindex].availability & (((g_MpSetup.chrslots & 0xf) << 1) | 1)) != 0; } void mpDetermineUnlockedFeatures(void) @@ -401,9 +401,9 @@ void mpDetermineUnlockedFeatures(void) s32 j; s32 k; - // Clear all challenge completions + // Clear all challenge availability for (challengeindex = 0; challengeindex < 30; challengeindex++) { - g_MpChallenges[challengeindex].completions[0] = 0; + g_MpChallenges[challengeindex].availability = 0; } numgifted = 0; @@ -412,10 +412,10 @@ void mpDetermineUnlockedFeatures(void) for (challengeindex = 0; challengeindex < 30; challengeindex++) { flag = 0; - if (mpIsChallengeCompletedByAnyChrWithNumPlayers(challengeindex, 1) - || mpIsChallengeCompletedByAnyChrWithNumPlayers(challengeindex, 2) - || mpIsChallengeCompletedByAnyChrWithNumPlayers(challengeindex, 3) - || mpIsChallengeCompletedByAnyChrWithNumPlayers(challengeindex, 4)) { + if (mpIsChallengeCompletedByAnyPlayerWithNumPlayers(challengeindex, 1) + || mpIsChallengeCompletedByAnyPlayerWithNumPlayers(challengeindex, 2) + || mpIsChallengeCompletedByAnyPlayerWithNumPlayers(challengeindex, 3) + || mpIsChallengeCompletedByAnyPlayerWithNumPlayers(challengeindex, 4)) { // Completed challenge flag = 1; } else if (challengeindex < 4) { @@ -426,22 +426,22 @@ void mpDetermineUnlockedFeatures(void) // Challenges are available if their previous one is complete prev = challengeindex - 1; - if (mpIsChallengeCompletedByAnyChrWithNumPlayers(prev, 1) - || mpIsChallengeCompletedByAnyChrWithNumPlayers(prev, 2) - || mpIsChallengeCompletedByAnyChrWithNumPlayers(prev, 3) - || mpIsChallengeCompletedByAnyChrWithNumPlayers(prev, 4)) { + if (mpIsChallengeCompletedByAnyPlayerWithNumPlayers(prev, 1) + || mpIsChallengeCompletedByAnyPlayerWithNumPlayers(prev, 2) + || mpIsChallengeCompletedByAnyPlayerWithNumPlayers(prev, 3) + || mpIsChallengeCompletedByAnyPlayerWithNumPlayers(prev, 4)) { flag = 1; numgifted++; } } - g_MpChallenges[challengeindex].completions[0] |= flag; + g_MpChallenges[challengeindex].availability |= flag; } // Gift up to 4 challenges for (challengeindex = 0; numgifted < 4 && challengeindex < 30; challengeindex++) { - if ((g_MpChallenges[challengeindex].completions[0] & 1) == 0) { - g_MpChallenges[challengeindex].completions[0] |= 1; + if ((g_MpChallenges[challengeindex].availability & 1) == 0) { + g_MpChallenges[challengeindex].availability |= 1; numgifted++; } } @@ -453,10 +453,10 @@ void mpDetermineUnlockedFeatures(void) for (challengeindex = 0; challengeindex < 30; challengeindex++) { flag = 0; - if (mpIsChallengeCompletedByChrWithNumPlayers(j, challengeindex, 1) - || mpIsChallengeCompletedByChrWithNumPlayers(j, challengeindex, 2) - || mpIsChallengeCompletedByChrWithNumPlayers(j, challengeindex, 3) - || mpIsChallengeCompletedByChrWithNumPlayers(j, challengeindex, 4)) { + if (mpIsChallengeCompletedByPlayerWithNumPlayers(j, challengeindex, 1) + || mpIsChallengeCompletedByPlayerWithNumPlayers(j, challengeindex, 2) + || mpIsChallengeCompletedByPlayerWithNumPlayers(j, challengeindex, 3) + || mpIsChallengeCompletedByPlayerWithNumPlayers(j, challengeindex, 4)) { // Completed challenge flag = 2 << j; } else if (challengeindex < 4) { @@ -467,51 +467,51 @@ void mpDetermineUnlockedFeatures(void) // Challenges are available if their previous one is complete prev = challengeindex - 1; - if (mpIsChallengeCompletedByChrWithNumPlayers(j, prev, 1) - || mpIsChallengeCompletedByChrWithNumPlayers(j, prev, 2) - || mpIsChallengeCompletedByChrWithNumPlayers(j, prev, 3) - || mpIsChallengeCompletedByChrWithNumPlayers(j, prev, 4)) { + if (mpIsChallengeCompletedByPlayerWithNumPlayers(j, prev, 1) + || mpIsChallengeCompletedByPlayerWithNumPlayers(j, prev, 2) + || mpIsChallengeCompletedByPlayerWithNumPlayers(j, prev, 3) + || mpIsChallengeCompletedByPlayerWithNumPlayers(j, prev, 4)) { flag = 2 << j; numgifted++; } } - g_MpChallenges[challengeindex].completions[0] |= flag; + g_MpChallenges[challengeindex].availability |= flag; } // Gift up to 4 challenges for (challengeindex = 0; numgifted < 4 && challengeindex < 30; challengeindex++) { - if ((g_MpChallenges[challengeindex].completions[0] & (2 << j)) == 0) { - g_MpChallenges[challengeindex].completions[0] |= 2 << j; + if ((g_MpChallenges[challengeindex].availability & (2 << j)) == 0) { + g_MpChallenges[challengeindex].availability |= 2 << j; numgifted++; } } } - for (j = 0; j < 80; j++) { + for (j = 0; j < ARRAYCOUNT(g_MpFeaturesUnlocked); j++) { flag = 0; for (challengeindex = 0; challengeindex < 30; challengeindex++) { - if (mpIsChallengeAvailable(challengeindex)) { + if (mpIsChallengeAvailableToAnyPlayer(challengeindex)) { for (i = 0; i < 16; i++) { - if (g_MpChallenges[challengeindex].unk09[i] == j) { + if (g_MpChallenges[challengeindex].unlockfeatures[i] == j) { flag |= 1; } } } } - for (i = 0; i < 40; i++) { - if (var800acca0[i] == j) { + for (i = 0; i < ARRAYCOUNT(g_MpFeaturesForceUnlocked); i++) { + if (g_MpFeaturesForceUnlocked[i] == j) { flag |= 1; } } for (challengeindex = 0; challengeindex < 30; challengeindex++) { for (prev = 0; prev < 4; prev++) { - if (func0f19af3c(prev, challengeindex)) { + if (mpIsChallengeAvailableToPlayer(prev, challengeindex)) { for (i = 0; i < 16; i++) { - if (g_MpChallenges[challengeindex].unk09[i] == j) { + if (g_MpChallenges[challengeindex].unlockfeatures[i] == j) { flag |= 2 << prev; } } @@ -519,21 +519,21 @@ void mpDetermineUnlockedFeatures(void) } } - g_MpChallengesCompleted[j] = flag; + g_MpFeaturesUnlocked[j] = flag; } for (j = 0; j < func0f188bcc(); j++) { struct mpweapon *weapon = &g_MpWeapons[j]; - if (weapon->unlock > 0 && func0f19cbcc(weapon->weaponnum)) { - g_MpChallengesCompleted[weapon->unlock] |= 1; + if (weapon->unlockfeature > 0 && func0f19cbcc(weapon->weaponnum)) { + g_MpFeaturesUnlocked[weapon->unlockfeature] |= 1; } } func0f1895e8(); // If the ability to have 8 simulants hasn't been unlocked, limit them to 4 - if (!mpIsChallengeComplete(0x40)) { + if (!mpIsFeatureUnlocked(MPFEATURE_8BOTS)) { for (k = 4; k < 8; k++) { if (g_MpSetup.chrslots & (1 << (4 + k))) { mpRemoveSimulant(k); @@ -575,7 +575,7 @@ void mpPerformSanityChecks(void) if (g_MpSetup.scenario == MPSCENARIO_KINGOFTHEHILL) { g_Vars.mphilltime = 10; } - } else if (!mpIsChallengeComplete(CHALLENGE_UNK64)) { + } else if (!mpIsFeatureUnlocked(MPFEATURE_8BOTS)) { // Limit to 4 players and 4 simulants g_MpSetup.chrslots &= 0x00ff; } @@ -587,7 +587,7 @@ s32 mpGetNumAvailableChallenges(void) s32 count = 0; for (challengeindex = 0; challengeindex != NUM_CHALLENGES; challengeindex++) { - if (mpIsChallengeAvailable(challengeindex)) { + if (mpIsChallengeAvailableToAnyPlayer(challengeindex)) { count++; } } @@ -606,7 +606,7 @@ char *mpGetChallengeNameBySlot(s32 slot) s32 i; for (i = 0; i < 30; i++) { - if (mpIsChallengeAvailable(i)) { + if (mpIsChallengeAvailableToAnyPlayer(i)) { if (index == slot) { return mpChallengeGetName(i); } @@ -624,7 +624,7 @@ void mpSetCurrentChallenge(s32 slotnum) g_MpChallengeIndex = 0; for (challengeindex = 0; challengeindex != NUM_CHALLENGES; challengeindex++) { - if (mpIsChallengeAvailable(challengeindex)) { + if (mpIsChallengeAvailableToAnyPlayer(challengeindex)) { if (slotnum == 0) { g_MpChallengeIndex = challengeindex; break; @@ -648,9 +648,9 @@ bool mpIsChallengeCompletedByAnyChrWithNumPlayersBySlot(s32 slot, s32 numplayers s32 i; for (i = 0; i < 30; i++) { - if (mpIsChallengeAvailable(i)) { + if (mpIsChallengeAvailableToAnyPlayer(i)) { if (availableindex == slot) { - return mpIsChallengeCompletedByAnyChrWithNumPlayers(i, numplayers); + return mpIsChallengeCompletedByAnyPlayerWithNumPlayers(i, numplayers); } availableindex++; @@ -666,9 +666,9 @@ bool mpIsChallengeCompletedByChrWithNumPlayersBySlot(s32 mpchrnum, s32 slot, s32 s32 i; for (i = 0; i < 30; i++) { - if (mpIsChallengeAvailable(i)) { + if (mpIsChallengeAvailableToAnyPlayer(i)) { if (availableindex == slot) { - return mpIsChallengeCompletedByChrWithNumPlayers(mpchrnum, i, numplayers); + return mpIsChallengeCompletedByPlayerWithNumPlayers(mpchrnum, i, numplayers); } availableindex++; @@ -853,7 +853,7 @@ struct mpconfigfull *mpGetNthAvailableChallengeSomething(s32 n, u8 *buffer, s32 s32 challengeindex; for (challengeindex = 0; challengeindex != NUM_CHALLENGES; challengeindex++) { - if (mpIsChallengeAvailable(challengeindex)) { + if (mpIsChallengeAvailableToAnyPlayer(challengeindex)) { if (numavailable == n) { return mpLoadChallenge(challengeindex, buffer, len); } @@ -871,24 +871,24 @@ struct mpconfigfull *mpLoadCurrentChallenge(u8 *buffer, s32 len) } /** - * This is adding unlockvalue to the array, provided it's unique. + * This is adding featurenum to the array, provided it's unique. */ -s32 func0f19bb50(s32 unlockvalue, u8 *array, s32 index, s32 len) +s32 mpForceUnlockFeature(s32 featurenum, u8 *array, s32 tail, s32 len) { s32 i; - for (i = 0; i < index; i++) { - if (array[i] == unlockvalue) { + for (i = 0; i < tail; i++) { + if (array[i] == featurenum) { break; } } - if (i >= index && index < len) { - array[index] = unlockvalue; - index++; + if (i >= tail && tail < len) { + array[tail] = featurenum; + tail++; } - return index; + return tail; } GLOBAL_ASM( @@ -923,7 +923,7 @@ glabel func0f19bb98 /* f19bc00: 3099007f */ andi $t9,$a0,0x7f /* f19bc04: 13200004 */ beqz $t9,.L0f19bc18 /* f19bc08: 03202025 */ or $a0,$t9,$zero -/* f19bc0c: 0fc66ed4 */ jal func0f19bb50 +/* f19bc0c: 0fc66ed4 */ jal mpForceUnlockFeature /* f19bc10: 02c03825 */ or $a3,$s6,$zero /* f19bc14: 00409025 */ or $s2,$v0,$zero .L0f19bc18: @@ -950,7 +950,7 @@ glabel func0f19bb98 /* f19bc64: 02403025 */ or $a2,$s2,$zero /* f19bc68: 50800005 */ beqzl $a0,.L0f19bc80 /* f19bc6c: 26310001 */ addiu $s1,$s1,0x1 -/* f19bc70: 0fc66ed4 */ jal func0f19bb50 +/* f19bc70: 0fc66ed4 */ jal mpForceUnlockFeature /* f19bc74: 02c03825 */ or $a3,$s6,$zero /* f19bc78: 00409025 */ or $s2,$v0,$zero /* f19bc7c: 26310001 */ addiu $s1,$s1,0x1 @@ -974,7 +974,7 @@ glabel func0f19bb98 /* f19bcbc: 02403025 */ or $a2,$s2,$zero /* f19bcc0: 50800005 */ beqzl $a0,.L0f19bcd8 /* f19bcc4: 8ee3000c */ lw $v1,0xc($s7) -/* f19bcc8: 0fc66ed4 */ jal func0f19bb50 +/* f19bcc8: 0fc66ed4 */ jal mpForceUnlockFeature /* f19bccc: 02c03825 */ or $a3,$s6,$zero /* f19bcd0: 00409025 */ or $s2,$v0,$zero .L0f19bcd4: @@ -985,7 +985,7 @@ glabel func0f19bb98 /* f19bce0: 306d0001 */ andi $t5,$v1,0x1 /* f19bce4: 11a00005 */ beqz $t5,.L0f19bcfc /* f19bce8: 02403025 */ or $a2,$s2,$zero -/* f19bcec: 0fc66ed4 */ jal func0f19bb50 +/* f19bcec: 0fc66ed4 */ jal mpForceUnlockFeature /* f19bcf0: 02c03825 */ or $a3,$s6,$zero /* f19bcf4: 00409025 */ or $s2,$v0,$zero /* f19bcf8: 8ee3000c */ lw $v1,0xc($s7) @@ -995,7 +995,7 @@ glabel func0f19bb98 /* f19bd04: 2404001d */ addiu $a0,$zero,0x1d /* f19bd08: 02a02825 */ or $a1,$s5,$zero /* f19bd0c: 02403025 */ or $a2,$s2,$zero -/* f19bd10: 0fc66ed4 */ jal func0f19bb50 +/* f19bd10: 0fc66ed4 */ jal mpForceUnlockFeature /* f19bd14: 02c03825 */ or $a3,$s6,$zero /* f19bd18: 00409025 */ or $s2,$v0,$zero .L0f19bd1c: @@ -1050,7 +1050,7 @@ glabel func0f19bd4c /* f19bdc8: 02403025 */ or $a2,$s2,$zero /* f19bdcc: 50800005 */ beqzl $a0,.L0f19bde4 /* f19bdd0: 00008025 */ or $s0,$zero,$zero -/* f19bdd4: 0fc66ed4 */ jal func0f19bb50 +/* f19bdd4: 0fc66ed4 */ jal mpForceUnlockFeature /* f19bdd8: 02603825 */ or $a3,$s3,$zero /* f19bddc: 00409025 */ or $s2,$v0,$zero .L0f19bde0: @@ -1069,7 +1069,7 @@ glabel func0f19bd4c /* f19be08: 02403025 */ or $a2,$s2,$zero /* f19be0c: 50800005 */ beqzl $a0,.L0f19be24 /* f19be10: 26100001 */ addiu $s0,$s0,0x1 -/* f19be14: 0fc66ed4 */ jal func0f19bb50 +/* f19be14: 0fc66ed4 */ jal mpForceUnlockFeature /* f19be18: 02603825 */ or $a3,$s3,$zero /* f19be1c: 00409025 */ or $s2,$v0,$zero .L0f19be20: @@ -1088,7 +1088,7 @@ glabel func0f19bd4c /* f19be4c: 02403025 */ or $a2,$s2,$zero /* f19be50: 50800005 */ beqzl $a0,.L0f19be68 /* f19be54: 92e20029 */ lbu $v0,0x29($s7) -/* f19be58: 0fc66ed4 */ jal func0f19bb50 +/* f19be58: 0fc66ed4 */ jal mpForceUnlockFeature /* f19be5c: 02603825 */ or $a3,$s3,$zero /* f19be60: 00409025 */ or $s2,$v0,$zero .L0f19be64: @@ -1104,7 +1104,7 @@ glabel func0f19bd4c /* f19be84: 02403025 */ or $a2,$s2,$zero /* f19be88: 50800005 */ beqzl $a0,.L0f19bea0 /* f19be8c: 8faa0040 */ lw $t2,0x40($sp) -/* f19be90: 0fc66ed4 */ jal func0f19bb50 +/* f19be90: 0fc66ed4 */ jal mpForceUnlockFeature /* f19be94: 02603825 */ or $a3,$s3,$zero /* f19be98: 00409025 */ or $s2,$v0,$zero .L0f19be9c: @@ -1122,7 +1122,7 @@ glabel func0f19bd4c /* f19bec4: 28410019 */ slti $at,$v0,0x19 /* f19bec8: 14200006 */ bnez $at,.L0f19bee4 /* f19becc: 02403025 */ or $a2,$s2,$zero -/* f19bed0: 0fc66ed4 */ jal func0f19bb50 +/* f19bed0: 0fc66ed4 */ jal mpForceUnlockFeature /* f19bed4: 02603825 */ or $a3,$s3,$zero /* f19bed8: 00409025 */ or $s2,$v0,$zero /* f19bedc: 10000014 */ b .L0f19bf30 @@ -1133,7 +1133,7 @@ glabel func0f19bd4c /* f19beec: 24040023 */ addiu $a0,$zero,0x23 /* f19bef0: 02802825 */ or $a1,$s4,$zero /* f19bef4: 02403025 */ or $a2,$s2,$zero -/* f19bef8: 0fc66ed4 */ jal func0f19bb50 +/* f19bef8: 0fc66ed4 */ jal mpForceUnlockFeature /* f19befc: 02603825 */ or $a3,$s3,$zero /* f19bf00: 00409025 */ or $s2,$v0,$zero /* f19bf04: 1000000a */ b .L0f19bf30 @@ -1144,7 +1144,7 @@ glabel func0f19bd4c /* f19bf14: 2404004d */ addiu $a0,$zero,0x4d /* f19bf18: 02802825 */ or $a1,$s4,$zero /* f19bf1c: 02403025 */ or $a2,$s2,$zero -/* f19bf20: 0fc66ed4 */ jal func0f19bb50 +/* f19bf20: 0fc66ed4 */ jal mpForceUnlockFeature /* f19bf24: 02603825 */ or $a3,$s3,$zero /* f19bf28: 00409025 */ or $s2,$v0,$zero /* f19bf2c: 8fa2006c */ lw $v0,0x6c($sp) @@ -1154,7 +1154,7 @@ glabel func0f19bd4c /* f19bf38: 24040040 */ addiu $a0,$zero,0x40 /* f19bf3c: 02802825 */ or $a1,$s4,$zero /* f19bf40: 02403025 */ or $a2,$s2,$zero -/* f19bf44: 0fc66ed4 */ jal func0f19bb50 +/* f19bf44: 0fc66ed4 */ jal mpForceUnlockFeature /* f19bf48: 02603825 */ or $a3,$s3,$zero /* f19bf4c: 00409025 */ or $s2,$v0,$zero .L0f19bf50: @@ -1182,30 +1182,32 @@ glabel func0f19bd4c /* f19bf9c: 27bd0060 */ addiu $sp,$sp,0x60 ); -void func0f19bfa0(void) +void mpForceUnlockSimulantFeatures(void) { s32 numsims = 0; - s32 index = func0f19bb98(&g_MpSetup, var800acca0, 40); + s32 index = func0f19bb98(&g_MpSetup, g_MpFeaturesForceUnlocked, ARRAYCOUNT(g_MpFeaturesForceUnlocked)); s32 i; for (i = 0; i < 8; i++) { + // Force unlock the simulant type s32 simtypeindex = mpGetSimTypeIndex(g_MpSimulants[i].base.simtype, SIMSKILL_NORMAL); if (simtypeindex >= 0) { - s32 unlockvalue = g_MpSimulantTypes[simtypeindex].unlockvalue; + s32 featurenum = g_MpSimulantTypes[simtypeindex].requirefeature; - if (unlockvalue) { - index = func0f19bb50(unlockvalue, var800acca0, index, 40); + if (featurenum) { + index = mpForceUnlockFeature(featurenum, g_MpFeaturesForceUnlocked, index, ARRAYCOUNT(g_MpFeaturesForceUnlocked)); } } + // Force unlock the simulant skill simtypeindex = mpGetSimTypeIndex(SIMTYPE_GENERAL, g_MpSimulants[i].skill); if (simtypeindex >= 0) { - s32 unlockvalue = g_MpSimulantTypes[simtypeindex].unlockvalue; + s32 featurenum = g_MpSimulantTypes[simtypeindex].requirefeature; - if (unlockvalue) { - index = func0f19bb50(unlockvalue, var800acca0, index, 40); + if (featurenum) { + index = mpForceUnlockFeature(featurenum, g_MpFeaturesForceUnlocked, index, ARRAYCOUNT(g_MpFeaturesForceUnlocked)); } } @@ -1213,29 +1215,33 @@ void func0f19bfa0(void) numsims++; } + // Force unlock the simulant's body if (g_MpSimulants[i].base.bodynum < ARRAYCOUNT(g_MpBodies)) { - s32 unlockvalue = g_MpBodies[g_MpSimulants[i].base.bodynum].unlockvalue; + s32 featurenum = g_MpBodies[g_MpSimulants[i].base.bodynum].requirefeature; - if (unlockvalue) { - index = func0f19bb50(unlockvalue, var800acca0, index, 40); + if (featurenum) { + index = mpForceUnlockFeature(featurenum, g_MpFeaturesForceUnlocked, index, ARRAYCOUNT(g_MpFeaturesForceUnlocked)); } } + // Force unlock the simulant's head if (g_MpSimulants[i].base.headnum < ARRAYCOUNT(g_MpHeads)) { - s32 unlockvalue = g_MpHeads[g_MpSimulants[i].base.headnum].unlockvalue; + s32 featurenum = g_MpHeads[g_MpSimulants[i].base.headnum].requirefeature; - if (unlockvalue) { - index = func0f19bb50(unlockvalue, var800acca0, index, 40); + if (featurenum) { + index = mpForceUnlockFeature(featurenum, g_MpFeaturesForceUnlocked, index, ARRAYCOUNT(g_MpFeaturesForceUnlocked)); } } } + // Force unlock 8 simulants if (numsims > 4) { - index = func0f19bb50(64, var800acca0, index, 40); + index = mpForceUnlockFeature(MPFEATURE_8BOTS, g_MpFeaturesForceUnlocked, index, ARRAYCOUNT(g_MpFeaturesForceUnlocked)); } - for (i = index; i < 40; i++) { - var800acca0[i] = 0; + // Clear the remainder of the array + for (i = index; i < ARRAYCOUNT(g_MpFeaturesForceUnlocked); i++) { + g_MpFeaturesForceUnlocked[i] = 0; } mpDetermineUnlockedFeatures(); @@ -1244,8 +1250,9 @@ void func0f19bfa0(void) void func0f19c190(void) { s32 i; - for (i = 0; i < 40; i++) { - var800acca0[i] = 0; + + for (i = 0; i < ARRAYCOUNT(g_MpFeaturesForceUnlocked); i++) { + g_MpFeaturesForceUnlocked[i] = 0; } mpDetermineUnlockedFeatures(); @@ -1302,26 +1309,30 @@ char *mpconfigGetDescription(struct mpconfigfull *mpconfig) return ""; } -s32 mpGetNumChallengesAvailable(s32 mpchrnum) +/** + * Return the index of the first incomplete challenge, but if it's in the first + * 4 then return index 4 because the first 4 are always shown. + */ +s32 mpGetAutoFocusedChallengeIndex(s32 mpchrnum) { s32 challengeindex; - s32 numavail = 0; + s32 index = 0; for (challengeindex = 29; challengeindex >= 0; challengeindex--) { - if (mpIsChallengeCompletedByChrWithNumPlayers(mpchrnum, challengeindex, 1) || - mpIsChallengeCompletedByChrWithNumPlayers(mpchrnum, challengeindex, 2) || - mpIsChallengeCompletedByChrWithNumPlayers(mpchrnum, challengeindex, 3) || - mpIsChallengeCompletedByChrWithNumPlayers(mpchrnum, challengeindex, 4)) { - numavail = challengeindex + 1; + if (mpIsChallengeCompletedByPlayerWithNumPlayers(mpchrnum, challengeindex, 1) || + mpIsChallengeCompletedByPlayerWithNumPlayers(mpchrnum, challengeindex, 2) || + mpIsChallengeCompletedByPlayerWithNumPlayers(mpchrnum, challengeindex, 3) || + mpIsChallengeCompletedByPlayerWithNumPlayers(mpchrnum, challengeindex, 4)) { + index = challengeindex + 1; break; } } - if (numavail < 4) { - numavail = 4; + if (index < 4) { + index = 4; } - return numavail; + return index; } char *mpChallengeGetNameWithArg(s32 arg0, s32 challengeindex) @@ -1329,39 +1340,39 @@ char *mpChallengeGetNameWithArg(s32 arg0, s32 challengeindex) return langGet(g_MpChallenges[challengeindex].name); } -bool func0f19c3bc(s32 mpchrnum, s32 index, s32 numplayers) +bool mpIsChallengeCompletedByPlayerWithNumPlayers2(s32 mpchrnum, s32 index, s32 numplayers) { - return mpIsChallengeCompletedByChrWithNumPlayers(mpchrnum, index, numplayers); + return mpIsChallengeCompletedByPlayerWithNumPlayers(mpchrnum, index, numplayers); } -bool mpIsChallengeCompletedByAnyChrWithNumPlayers(s32 index, s32 numplayers) +bool mpIsChallengeCompletedByAnyPlayerWithNumPlayers(s32 index, s32 numplayers) { - return (g_MpChallenges[index].completions[numplayers] & 1) != 0; + return (g_MpChallenges[index].completions[numplayers - 1] & 1) != 0; } -void mpSetChallengeCompletedByAnyChrWithNumPlayers(s32 index, s32 numplayers, bool completed) +void mpSetChallengeCompletedByAnyPlayerWithNumPlayers(s32 index, s32 numplayers, bool completed) { if (completed) { - g_MpChallenges[index].completions[numplayers] |= 1; + g_MpChallenges[index].completions[numplayers - 1] |= 1; return; } - g_MpChallenges[index].completions[numplayers] &= ~1; + g_MpChallenges[index].completions[numplayers - 1] &= ~1; } -bool mpIsChallengeCompletedByChrWithNumPlayers(s32 mpchrnum, s32 index, s32 numplayers) +bool mpIsChallengeCompletedByPlayerWithNumPlayers(s32 mpchrnum, s32 index, s32 numplayers) { - return (g_MpChallenges[index].completions[numplayers] & (2 << mpchrnum)) != 0; + return (g_MpChallenges[index].completions[numplayers - 1] & (2 << mpchrnum)) != 0; } -void mpSetChallengeCompletedByChrWithNumPlayers(u32 mpchrnum, s32 index, s32 numplayers, bool completed) +void mpSetChallengeCompletedByPlayerWithNumPlayers(u32 mpchrnum, s32 index, s32 numplayers, bool completed) { if (completed) { - g_MpChallenges[index].completions[numplayers] |= 2 << mpchrnum; + g_MpChallenges[index].completions[numplayers - 1] |= 2 << mpchrnum; return; } - g_MpChallenges[index].completions[numplayers] &= ~(2 << mpchrnum); + g_MpChallenges[index].completions[numplayers - 1] &= ~(2 << mpchrnum); } bool mpIsChallengeCompleteForEndscreen(void) @@ -1402,12 +1413,12 @@ void mpConsiderMarkingCurrentChallengeComplete(void) u32 prevplayernum; s32 i; - mpSetChallengeCompletedByAnyChrWithNumPlayers(g_MpChallengeIndex, PLAYERCOUNT(), 1); + mpSetChallengeCompletedByAnyPlayerWithNumPlayers(g_MpChallengeIndex, PLAYERCOUNT(), 1); prevplayernum = g_Vars.currentplayernum; for (i = 0; i < PLAYERCOUNT(); i++) { setCurrentPlayerNum(i); - mpSetChallengeCompletedByChrWithNumPlayers(g_Vars.currentplayerstats->mpindex, g_MpChallengeIndex, PLAYERCOUNT(), true); + mpSetChallengeCompletedByPlayerWithNumPlayers(g_Vars.currentplayerstats->mpindex, g_MpChallengeIndex, PLAYERCOUNT(), true); } setCurrentPlayerNum(prevplayernum); @@ -1415,27 +1426,27 @@ void mpConsiderMarkingCurrentChallengeComplete(void) } } -bool mpIsChallengeComplete(s32 challenge) +bool mpIsFeatureUnlocked(s32 featurenum) { - if (challenge == 0) { + if (featurenum == 0) { return true; } - return (g_MpChallengesCompleted[challenge] & 1) != 0; + return (g_MpFeaturesUnlocked[featurenum] & 1) != 0; } -bool mpIsChallengeCompleteWithNumPlayers(u32 numplayers, s32 challenge) +bool mpIsFeatureUnlockedByPlayer(u32 numplayers, s32 featurenum) { - if (challenge == 0) { + if (featurenum == 0) { return true; } - return (g_MpChallengesCompleted[challenge] & (2 << numplayers)) != 0; + return (g_MpFeaturesUnlocked[featurenum] & (2 << numplayers)) != 0; } -bool func0f19c96c(s32 challenge) +bool func0f19c96c(s32 featurenum) { - if (challenge) { + if (featurenum) { return false; } diff --git a/src/game/gamefile.c b/src/game/gamefile.c index 714da7c9a..4a8601687 100644 --- a/src/game/gamefile.c +++ b/src/game/gamefile.c @@ -214,7 +214,7 @@ void savefileLoadDefaults(struct savefile_solo *file) for (i = 0; i < 30; i++) { for (j = 1; j != 5; j++) { - mpSetChallengeCompletedByAnyChrWithNumPlayers(i, j, false); + mpSetChallengeCompletedByAnyPlayerWithNumPlayers(i, j, false); } } @@ -434,7 +434,7 @@ glabel func0f10fac8 /* f10fd40: 24050001 */ addiu $a1,$zero,0x1 /* f10fd44: 02202025 */ or $a0,$s1,$zero /* f10fd48: 02002825 */ or $a1,$s0,$zero -/* f10fd4c: 0fc67103 */ jal mpSetChallengeCompletedByAnyChrWithNumPlayers +/* f10fd4c: 0fc67103 */ jal mpSetChallengeCompletedByAnyPlayerWithNumPlayers /* f10fd50: 00403025 */ or $a2,$v0,$zero /* f10fd54: 26100001 */ addiu $s0,$s0,0x1 /* f10fd58: 5612fff8 */ bnel $s0,$s2,.L0f10fd3c @@ -928,7 +928,7 @@ glabel func0f10feac .L0f1104a0: /* f1104a0: 02202025 */ or $a0,$s1,$zero .L0f1104a4: -/* f1104a4: 0fc670f7 */ jal mpIsChallengeCompletedByAnyChrWithNumPlayers +/* f1104a4: 0fc670f7 */ jal mpIsChallengeCompletedByAnyPlayerWithNumPlayers /* f1104a8: 02002825 */ or $a1,$s0,$zero /* f1104ac: 02802025 */ or $a0,$s4,$zero /* f1104b0: 00402825 */ or $a1,$v0,$zero diff --git a/src/game/mplayer.c b/src/game/mplayer.c index ba97a2e72..d5cad358b 100644 --- a/src/game/mplayer.c +++ b/src/game/mplayer.c @@ -93,11 +93,11 @@ void mpStartMatch(void) func0f17f260(); - if (!mpIsChallengeComplete(30)) { + if (!mpIsFeatureUnlocked(MPFEATURE_ONEHITKILLS)) { g_MpSetup.options &= ~MPOPTION_ONEHITKILLS; } - if (!mpIsChallengeComplete(29)) { + if (!mpIsFeatureUnlocked(MPFEATURE_SLOWMOTION)) { g_MpSetup.options &= ~(MPOPTION_SLOWMOTION_ON | MPOPTION_SLOWMOTION_SMART); } @@ -707,7 +707,7 @@ glabel func0f18800c .L0f188154: /* f188154: 02202825 */ or $a1,$s1,$zero /* f188158: 02003025 */ or $a2,$s0,$zero -/* f18815c: 0fc6712e */ jal mpSetChallengeCompletedByChrWithNumPlayers +/* f18815c: 0fc6712e */ jal mpSetChallengeCompletedByPlayerWithNumPlayers /* f188160: 00003825 */ or $a3,$zero,$zero /* f188164: 26100001 */ addiu $s0,$s0,0x1 /* f188168: 5612fffa */ bnel $s0,$s2,.L0f188154 @@ -821,7 +821,7 @@ glabel func0f188210 /* f188308: a0430001 */ sb $v1,0x1($v0) /* f18830c: a0430002 */ sb $v1,0x2($v0) /* f188310: a0430003 */ sb $v1,0x3($v0) -/* f188314: 0fc66fe8 */ jal func0f19bfa0 +/* f188314: 0fc66fe8 */ jal mpForceUnlockSimulantFeatures /* f188318: ac430004 */ sw $v1,0x4($v0) /* f18831c: 3c05800b */ lui $a1,%hi(g_MpPlayers) /* f188320: 3c06800b */ lui $a2,%hi(g_ActiveMenuMpBotCommands) @@ -1477,7 +1477,7 @@ glabel mpGetNumWeaponOptions /* f188bfc: 96040004 */ lhu $a0,0x4($s0) .L0f188c00: /* f188c00: 308e007f */ andi $t6,$a0,0x7f -/* f188c04: 0fc67244 */ jal mpIsChallengeComplete +/* f188c04: 0fc67244 */ jal mpIsFeatureUnlocked /* f188c08: 01c02025 */ or $a0,$t6,$zero /* f188c0c: 10400002 */ beqz $v0,.L0f188c18 /* f188c10: 2610000a */ addiu $s0,$s0,0xa @@ -1509,7 +1509,7 @@ glabel mpGetWeaponLabel /* f188c64: 96040004 */ lhu $a0,0x4($s0) .L0f188c68: /* f188c68: 308e007f */ andi $t6,$a0,0x7f -/* f188c6c: 0fc67244 */ jal mpIsChallengeComplete +/* f188c6c: 0fc67244 */ jal mpIsFeatureUnlocked /* f188c70: 01c02025 */ or $a0,$t6,$zero /* f188c74: 5040001e */ beqzl $v0,.L0f188cf0 /* f188c78: 2610000a */ addiu $s0,$s0,0xa @@ -1566,7 +1566,7 @@ void mpSetWeaponSlot(s32 slot, s32 mpweaponnum) s32 i; for (i = 0; i <= mpweaponnum; i++) { - if (mpIsChallengeComplete(g_MpWeapons[i].unlock) == 0) { + if (mpIsFeatureUnlocked(g_MpWeapons[i].unlockfeature) == 0) { mpweaponnum++; } @@ -1582,7 +1582,7 @@ s32 mpGetWeaponSlot(s32 slot) s32 i; for (i = 0; i < g_MpSetup.weapons[slot]; i++) { - if (mpIsChallengeComplete(g_MpWeapons[i].unlock)) { + if (mpIsFeatureUnlocked(g_MpWeapons[i].unlockfeature)) { count++; } } @@ -1654,10 +1654,10 @@ s32 mpCountWeaponSetThing(s32 weaponsetindex) } for (i = 0; i < weaponsetindex; i++) { - if ((mpIsChallengeComplete(g_MpWeaponSets[i].unlocks[0]) - && mpIsChallengeComplete(g_MpWeaponSets[i].unlocks[1]) - && mpIsChallengeComplete(g_MpWeaponSets[i].unlocks[2]) - && mpIsChallengeComplete(g_MpWeaponSets[i].unlocks[3])) || g_MpWeaponSets[i].unk0c != 0x5c) { + if ((mpIsFeatureUnlocked(g_MpWeaponSets[i].requirefeatures[0]) + && mpIsFeatureUnlocked(g_MpWeaponSets[i].requirefeatures[1]) + && mpIsFeatureUnlocked(g_MpWeaponSets[i].requirefeatures[2]) + && mpIsFeatureUnlocked(g_MpWeaponSets[i].requirefeatures[3])) || g_MpWeaponSets[i].unk0c != 0x5c) { count++; } } @@ -1671,10 +1671,10 @@ s32 func0f188f9c(s32 arg0) for (i = 0; i < ARRAYCOUNT(g_MpWeaponSets); i++) { // @bug? Shouldn't the disabled check be == WEAPON_DISABLED? - if ((mpIsChallengeComplete(g_MpWeaponSets[i].unlocks[0]) - && mpIsChallengeComplete(g_MpWeaponSets[i].unlocks[1]) - && mpIsChallengeComplete(g_MpWeaponSets[i].unlocks[2]) - && mpIsChallengeComplete(g_MpWeaponSets[i].unlocks[3])) + if ((mpIsFeatureUnlocked(g_MpWeaponSets[i].requirefeatures[0]) + && mpIsFeatureUnlocked(g_MpWeaponSets[i].requirefeatures[1]) + && mpIsFeatureUnlocked(g_MpWeaponSets[i].requirefeatures[2]) + && mpIsFeatureUnlocked(g_MpWeaponSets[i].requirefeatures[3])) || g_MpWeaponSets[i].unk0c != WEAPON_DISABLED) { if (arg0 == 0) { break; @@ -1796,19 +1796,19 @@ glabel func0f18913c /* f189190: 2416000a */ addiu $s6,$zero,0xa /* f189194: afa00044 */ sw $zero,0x44($sp) .L0f189198: -/* f189198: 0fc67244 */ jal mpIsChallengeComplete +/* f189198: 0fc67244 */ jal mpIsFeatureUnlocked /* f18919c: 93c40008 */ lbu $a0,0x8($s8) /* f1891a0: 50400010 */ beqzl $v0,.L0f1891e4 /* f1891a4: 93d8000c */ lbu $t8,0xc($s8) -/* f1891a8: 0fc67244 */ jal mpIsChallengeComplete +/* f1891a8: 0fc67244 */ jal mpIsFeatureUnlocked /* f1891ac: 93c40009 */ lbu $a0,0x9($s8) /* f1891b0: 5040000c */ beqzl $v0,.L0f1891e4 /* f1891b4: 93d8000c */ lbu $t8,0xc($s8) -/* f1891b8: 0fc67244 */ jal mpIsChallengeComplete +/* f1891b8: 0fc67244 */ jal mpIsFeatureUnlocked /* f1891bc: 93c4000a */ lbu $a0,0xa($s8) /* f1891c0: 50400008 */ beqzl $v0,.L0f1891e4 /* f1891c4: 93d8000c */ lbu $t8,0xc($s8) -/* f1891c8: 0fc67244 */ jal mpIsChallengeComplete +/* f1891c8: 0fc67244 */ jal mpIsFeatureUnlocked /* f1891cc: 93c4000b */ lbu $a0,0xb($s8) /* f1891d0: 50400004 */ beqzl $v0,.L0f1891e4 /* f1891d4: 93d8000c */ lbu $t8,0xc($s8) @@ -1832,7 +1832,7 @@ glabel func0f18913c /* f189210: 92500000 */ lbu $s0,0x0($s2) /* f189214: 56140007 */ bnel $s0,$s4,.L0f189234 /* f189218: 92390018 */ lbu $t9,0x18($s1) -/* f18921c: 0fc67244 */ jal mpIsChallengeComplete +/* f18921c: 0fc67244 */ jal mpIsFeatureUnlocked /* f189220: 24040016 */ addiu $a0,$zero,0x16 /* f189224: 54400003 */ bnezl $v0,.L0f189234 /* f189228: 92390018 */ lbu $t9,0x18($s1) @@ -1903,7 +1903,7 @@ glabel func0f1892dc /* f189308: 000e7040 */ sll $t6,$t6,0x1 /* f18930c: 3c048008 */ lui $a0,%hi(g_MpWeaponSets+0x8) /* f189310: 008e2021 */ addu $a0,$a0,$t6 -/* f189314: 0fc67244 */ jal mpIsChallengeComplete +/* f189314: 0fc67244 */ jal mpIsFeatureUnlocked /* f189318: 908473f8 */ lbu $a0,%lo(g_MpWeaponSets+0x8)($a0) /* f18931c: 50400029 */ beqzl $v0,.L0f1893c4 /* f189320: 8e0d0000 */ lw $t5,0x0($s0) @@ -1913,7 +1913,7 @@ glabel func0f1892dc /* f189330: 030fc021 */ addu $t8,$t8,$t7 /* f189334: 0018c040 */ sll $t8,$t8,0x1 /* f189338: 00982021 */ addu $a0,$a0,$t8 -/* f18933c: 0fc67244 */ jal mpIsChallengeComplete +/* f18933c: 0fc67244 */ jal mpIsFeatureUnlocked /* f189340: 908473f9 */ lbu $a0,%lo(g_MpWeaponSets+0x9)($a0) /* f189344: 5040001f */ beqzl $v0,.L0f1893c4 /* f189348: 8e0d0000 */ lw $t5,0x0($s0) @@ -1923,7 +1923,7 @@ glabel func0f1892dc /* f189358: 01996021 */ addu $t4,$t4,$t9 /* f18935c: 000c6040 */ sll $t4,$t4,0x1 /* f189360: 008c2021 */ addu $a0,$a0,$t4 -/* f189364: 0fc67244 */ jal mpIsChallengeComplete +/* f189364: 0fc67244 */ jal mpIsFeatureUnlocked /* f189368: 908473fa */ lbu $a0,%lo(g_MpWeaponSets+0xa)($a0) /* f18936c: 50400015 */ beqzl $v0,.L0f1893c4 /* f189370: 8e0d0000 */ lw $t5,0x0($s0) @@ -1933,7 +1933,7 @@ glabel func0f1892dc /* f189380: 01cd7021 */ addu $t6,$t6,$t5 /* f189384: 000e7040 */ sll $t6,$t6,0x1 /* f189388: 008e2021 */ addu $a0,$a0,$t6 -/* f18938c: 0fc67244 */ jal mpIsChallengeComplete +/* f18938c: 0fc67244 */ jal mpIsFeatureUnlocked /* f189390: 908473fb */ lbu $a0,%lo(g_MpWeaponSets+0xb)($a0) /* f189394: 5040000b */ beqzl $v0,.L0f1893c4 /* f189398: 8e0d0000 */ lw $t5,0x0($s0) @@ -1982,7 +1982,7 @@ glabel func0f1892dc /* f189438: afa60038 */ sw $a2,0x38($sp) /* f18943c: afa0003c */ sw $zero,0x3c($sp) /* f189440: afaa0024 */ sw $t2,0x24($sp) -/* f189444: 0fc67244 */ jal mpIsChallengeComplete +/* f189444: 0fc67244 */ jal mpIsFeatureUnlocked /* f189448: afab0028 */ sw $t3,0x28($sp) /* f18944c: 3c088008 */ lui $t0,%hi(g_MpWeapons) /* f189450: 25087268 */ addiu $t0,$t0,%lo(g_MpWeapons) @@ -2872,18 +2872,18 @@ glabel func0f18a030 ); struct mpweaponset g_MpWeaponSets[] = { - { /*0x00*/ L_MPWEAPONS(55), { WEAPON_FALCON2, WEAPON_MAGSEC4, WEAPON_PHOENIX, WEAPON_MAULER, WEAPON_MPSHIELD, WEAPON_DISABLED }, { 0x08, 0x07, 0x00, 0x00 }, 0x02, 0x05, 0x02, 0x08, 0x5b, 0x5c }, // Pistols - { /*0x01*/ L_MPWEAPONS(54), { WEAPON_FALCON2, WEAPON_CMP150, WEAPON_LAPTOPGUN, WEAPON_AR34, WEAPON_MPSHIELD, WEAPON_DISABLED }, { 0x0b, 0x00, 0x00, 0x00 }, 0x02, 0x0a, 0x0f, 0x11, 0x5b, 0x5c }, // Automatics - { /*0x02*/ L_MPWEAPONS(53), { WEAPON_MAGSEC4, WEAPON_DY357MAGNUM, WEAPON_SHOTGUN, WEAPON_RCP120, WEAPON_MPSHIELD, WEAPON_DISABLED }, { 0x0e, 0x0d, 0x00, 0x00 }, 0x05, 0x08, 0x0f, 0x11, 0x5b, 0x5c }, // Power - { /*0x03*/ L_MPWEAPONS(52), { WEAPON_PHOENIX, WEAPON_CYCLONE, WEAPON_CALLISTONTG, WEAPON_FARSIGHTXR20, WEAPON_MPSHIELD, WEAPON_DISABLED }, { 0x01, 0x0a, 0x00, 0x00 }, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c }, // FarSight - { /*0x04*/ L_MPWEAPONS(51), { WEAPON_FALCON2, WEAPON_CMP150, WEAPON_DRAGON, WEAPON_TRANQUILIZER, WEAPON_MPSHIELD, WEAPON_DISABLED }, { 0x02, 0x00, 0x00, 0x00 }, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c }, // Tranquilizer - { /*0x05*/ L_MPWEAPONS(50), { WEAPON_MAULER, WEAPON_K7AVENGER, WEAPON_REAPER, WEAPON_SUPERDRAGON, WEAPON_MPSHIELD, WEAPON_DISABLED }, { 0x03, 0x07, 0x0c, 0x0f }, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c }, // Heavy - { /*0x06*/ L_MPWEAPONS(49), { WEAPON_FALCON2_SILENCER, WEAPON_GRENADE, WEAPON_CMP150, WEAPON_DY357LX, WEAPON_MPSHIELD, WEAPON_DISABLED }, { 0x05, 0x09, 0x00, 0x00 }, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c }, // Golden Magnum - { /*0x07*/ L_MPWEAPONS(48), { WEAPON_DEVASTATOR, WEAPON_DEVASTATOR, WEAPON_SUPERDRAGON, WEAPON_SUPERDRAGON, WEAPON_MPSHIELD, WEAPON_DISABLED }, { 0x03, 0x10, 0x00, 0x00 }, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c }, // Explosive - { /*0x08*/ L_MPWEAPONS(47), { WEAPON_MAGSEC4, WEAPON_CMP150, WEAPON_AR34, WEAPON_DEVASTATOR, WEAPON_MPSHIELD, WEAPON_DISABLED }, { 0x10, 0x00, 0x00, 0x00 }, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c }, // Grenade Launcher - { /*0x09*/ L_MPWEAPONS(46), { WEAPON_MAULER, WEAPON_CYCLONE, WEAPON_DRAGON, WEAPON_ROCKETLAUNCHER, WEAPON_MPSHIELD, WEAPON_DISABLED }, { 0x07, 0x00, 0x00, 0x00 }, 0x02, 0x0b, 0x0f, 0x18, 0x5b, 0x5c }, // Rocket Launcher - { /*0x0a*/ L_MPWEAPONS(45), { WEAPON_MAGSEC4, WEAPON_LAPTOPGUN, WEAPON_K7AVENGER, WEAPON_PROXIMITYMINE, WEAPON_MPSHIELD, WEAPON_DISABLED }, { 0x0b, 0x0c, 0x13, 0x00 }, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c }, // Proximity Mine - { /*0x0b*/ L_MPWEAPONS(44), { WEAPON_COMBATKNIFE, WEAPON_COMBATKNIFE, WEAPON_TIMEDMINE, WEAPON_CROSSBOW, WEAPON_MPSHIELD, WEAPON_DISABLED }, { 0x11, 0x00, 0x00, 0x00 }, 0x1a, 0x1a, 0x20, 0x20, 0x5b, 0x5c }, // Close Combat + { /*0x00*/ L_MPWEAPONS(55), { WEAPON_FALCON2, WEAPON_MAGSEC4, WEAPON_PHOENIX, WEAPON_MAULER, WEAPON_MPSHIELD, WEAPON_DISABLED }, { MPFEATURE_WEAPON_PHOENIX, MPFEATURE_WEAPON_MAULER, 0, 0 }, 0x02, 0x05, 0x02, 0x08, 0x5b, 0x5c }, // Pistols + { /*0x01*/ L_MPWEAPONS(54), { WEAPON_FALCON2, WEAPON_CMP150, WEAPON_LAPTOPGUN, WEAPON_AR34, WEAPON_MPSHIELD, WEAPON_DISABLED }, { MPFEATURE_WEAPON_LAPTOPGUN, 0, 0, 0 }, 0x02, 0x0a, 0x0f, 0x11, 0x5b, 0x5c }, // Automatics + { /*0x02*/ L_MPWEAPONS(53), { WEAPON_MAGSEC4, WEAPON_DY357MAGNUM, WEAPON_SHOTGUN, WEAPON_RCP120, WEAPON_MPSHIELD, WEAPON_DISABLED }, { MPFEATURE_WEAPON_SHOTGUN, MPFEATURE_WEAPON_RCP120, 0, 0 }, 0x05, 0x08, 0x0f, 0x11, 0x5b, 0x5c }, // Power + { /*0x03*/ L_MPWEAPONS(52), { WEAPON_PHOENIX, WEAPON_CYCLONE, WEAPON_CALLISTONTG, WEAPON_FARSIGHTXR20, WEAPON_MPSHIELD, WEAPON_DISABLED }, { MPFEATURE_WEAPON_FARSIGHT, MPFEATURE_WEAPON_CALLISTO, 0, 0 }, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c }, // FarSight + { /*0x04*/ L_MPWEAPONS(51), { WEAPON_FALCON2, WEAPON_CMP150, WEAPON_DRAGON, WEAPON_TRANQUILIZER, WEAPON_MPSHIELD, WEAPON_DISABLED }, { MPFEATURE_WEAPON_TRANQUILIZER, 0, 0, 0 }, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c }, // Tranquilizer + { /*0x05*/ L_MPWEAPONS(50), { WEAPON_MAULER, WEAPON_K7AVENGER, WEAPON_REAPER, WEAPON_SUPERDRAGON, WEAPON_MPSHIELD, WEAPON_DISABLED }, { MPFEATURE_WEAPON_SUPERDRAGON, MPFEATURE_WEAPON_MAULER, MPFEATURE_WEAPON_K7AVENGER, MPFEATURE_WEAPON_REAPER }, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c }, // Heavy + { /*0x06*/ L_MPWEAPONS(49), { WEAPON_FALCON2_SILENCER, WEAPON_GRENADE, WEAPON_CMP150, WEAPON_DY357LX, WEAPON_MPSHIELD, WEAPON_DISABLED }, { MPFEATURE_WEAPON_FALCON2SILENCED, MPFEATURE_WEAPON_DY357LX, 0, 0 }, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c }, // Golden Magnum + { /*0x07*/ L_MPWEAPONS(48), { WEAPON_DEVASTATOR, WEAPON_DEVASTATOR, WEAPON_SUPERDRAGON, WEAPON_SUPERDRAGON, WEAPON_MPSHIELD, WEAPON_DISABLED }, { MPFEATURE_WEAPON_SUPERDRAGON, MPFEATURE_WEAPON_DEVASTATOR, 0, 0 }, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c }, // Explosive + { /*0x08*/ L_MPWEAPONS(47), { WEAPON_MAGSEC4, WEAPON_CMP150, WEAPON_AR34, WEAPON_DEVASTATOR, WEAPON_MPSHIELD, WEAPON_DISABLED }, { MPFEATURE_WEAPON_DEVASTATOR, 0, 0, 0 }, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c }, // Grenade Launcher + { /*0x09*/ L_MPWEAPONS(46), { WEAPON_MAULER, WEAPON_CYCLONE, WEAPON_DRAGON, WEAPON_ROCKETLAUNCHER, WEAPON_MPSHIELD, WEAPON_DISABLED }, { MPFEATURE_WEAPON_MAULER, 0, 0, 0 }, 0x02, 0x0b, 0x0f, 0x18, 0x5b, 0x5c }, // Rocket Launcher + { /*0x0a*/ L_MPWEAPONS(45), { WEAPON_MAGSEC4, WEAPON_LAPTOPGUN, WEAPON_K7AVENGER, WEAPON_PROXIMITYMINE, WEAPON_MPSHIELD, WEAPON_DISABLED }, { MPFEATURE_WEAPON_LAPTOPGUN, MPFEATURE_WEAPON_K7AVENGER, MPFEATURE_WEAPON_PROXIMITYMINE, 0 }, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c }, // Proximity Mine + { /*0x0b*/ L_MPWEAPONS(44), { WEAPON_COMBATKNIFE, WEAPON_COMBATKNIFE, WEAPON_TIMEDMINE, WEAPON_CROSSBOW, WEAPON_MPSHIELD, WEAPON_DISABLED }, { MPFEATURE_WEAPON_CROSSBOW, 0, 0, 0 }, 0x1a, 0x1a, 0x20, 0x20, 0x5b, 0x5c }, // Close Combat }; u32 var800874c8 = 0x00000000; @@ -3019,91 +3019,91 @@ const char var7f1b8c04[] = "PakId for player %d: %d\n"; const char var7f1b8c20[] = "Load Player - Result: %d\n"; struct mphead g_MpBeauHeads[NUM_MPBEAUHEADS] = { - // head, unlock value - { HEAD_BEAU2, 0x00 }, - { HEAD_BEAU3, 0x00 }, - { HEAD_BEAU4, 0x00 }, - { HEAD_BEAU5, 0x00 }, - { HEAD_BEAU6, 0x00 }, + // head, require feature + { HEAD_BEAU2, 0 }, + { HEAD_BEAU3, 0 }, + { HEAD_BEAU4, 0 }, + { HEAD_BEAU5, 0 }, + { HEAD_BEAU6, 0 }, }; struct mphead g_MpHeads[75] = { - // head, unlock value - { /*0x00*/ HEAD_DARK_COMBAT, 0x00 }, - { /*0x01*/ HEAD_DARK_FROCK, 0x41 }, - { /*0x02*/ HEAD_DARKAQUA, 0x45 }, - { /*0x03*/ HEAD_DARK_SNOW, 0x4a }, - { /*0x04*/ HEAD_ELVIS, 0x3d }, - { /*0x05*/ HEAD_ELVIS_GOGS, 0x3d }, - { /*0x06*/ HEAD_CARRINGTON, 0x00 }, - { /*0x07*/ HEAD_MRBLONDE, 0x38 }, - { /*0x08*/ HEAD_CASSANDRA, 0x00 }, - { /*0x09*/ HEAD_TRENT, 0x35 }, - { /*0x0a*/ HEAD_JONATHAN, 0x3a }, - { /*0x0b*/ HEAD_VD, 0x00 }, - { /*0x0c*/ HEAD_PRESIDENT, 0x41 }, - { /*0x0d*/ HEAD_DDSHOCK, 0x00 }, - { /*0x0e*/ HEAD_BIOTECH, 0x3c }, - { /*0x0f*/ HEAD_DDSNIPER, 0x34 }, - { /*0x10*/ HEAD_A51FACEPLATE, 0x3a }, - { /*0x11*/ HEAD_SECRETARY, 0x00 }, - { /*0x12*/ HEAD_FEM_GUARD, 0x32 }, - { /*0x13*/ HEAD_FEM_GUARD2, 0x32 }, - { /*0x14*/ HEAD_MAIAN_S, 0x3d }, - { /*0x15*/ HEAD_JON, 0x00 }, - { /*0x16*/ HEAD_BEAU1, 0x00 }, - { /*0x17*/ HEAD_ROSS, 0x00 }, - { /*0x18*/ HEAD_MARK2, 0x00 }, - { /*0x19*/ HEAD_CHRIST, 0x00 }, - { /*0x1a*/ HEAD_RUSS, 0x00 }, - { /*0x1b*/ HEAD_DARLING, 0x00 }, - { /*0x1c*/ HEAD_BRIAN, 0x00 }, - { /*0x1d*/ HEAD_JAMIE, 0x00 }, - { /*0x1e*/ HEAD_DUNCAN2, 0x00 }, - { /*0x1f*/ HEAD_KEITH, 0x00 }, - { /*0x20*/ HEAD_STEVEM, 0x00 }, - { /*0x21*/ HEAD_GRANT, 0x00 }, - { /*0x22*/ HEAD_PENNY, 0x00 }, - { /*0x23*/ HEAD_DAVEC, 0x00 }, - { /*0x24*/ HEAD_JONES, 0x00 }, - { /*0x25*/ HEAD_GRAHAM, 0x00 }, - { /*0x26*/ HEAD_ROBERT, 0x00 }, - { /*0x27*/ HEAD_NEIL2, 0x00 }, - { /*0x28*/ HEAD_SHAUN, 0x00 }, - { /*0x29*/ HEAD_ROBIN, 0x00 }, - { /*0x2a*/ HEAD_COOK, 0x00 }, - { /*0x2b*/ HEAD_PRYCE, 0x00 }, - { /*0x2c*/ HEAD_SILKE, 0x00 }, - { /*0x2d*/ HEAD_SMITH, 0x00 }, - { /*0x2e*/ HEAD_GARETH, 0x00 }, - { /*0x2f*/ HEAD_MURCHIE, 0x00 }, - { /*0x30*/ HEAD_WONG, 0x00 }, - { /*0x31*/ HEAD_CARTER, 0x00 }, - { /*0x32*/ HEAD_TINTIN, 0x00 }, - { /*0x33*/ HEAD_MUNTON, 0x00 }, - { /*0x34*/ HEAD_STAMPER, 0x00 }, - { /*0x35*/ HEAD_PHELPS, 0x00 }, - { /*0x36*/ HEAD_ALEX, 0x00 }, - { /*0x37*/ HEAD_JULIANNE, 0x00 }, - { /*0x38*/ HEAD_LAURA, 0x00 }, - { /*0x39*/ HEAD_EDMCG, 0x00 }, - { /*0x3a*/ HEAD_ANKA, 0x00 }, - { /*0x3b*/ HEAD_LESLIE_S, 0x00 }, - { /*0x3c*/ HEAD_MATT_C, 0x00 }, - { /*0x3d*/ HEAD_PEER_S, 0x00 }, - { /*0x3e*/ HEAD_EILEEN_T, 0x00 }, - { /*0x3f*/ HEAD_ANDY_R, 0x00 }, - { /*0x40*/ HEAD_BEN_R, 0x00 }, - { /*0x41*/ HEAD_STEVE_K, 0x00 }, - { /*0x42*/ HEAD_SANCHEZ, 0x00 }, - { /*0x43*/ HEAD_TIM, 0x00 }, - { /*0x44*/ HEAD_KEN, 0x00 }, - { /*0x45*/ HEAD_EILEEN_H, 0x00 }, - { /*0x46*/ HEAD_SCOTT_H, 0x00 }, - { /*0x47*/ HEAD_JOEL, 0x00 }, - { /*0x48*/ HEAD_GRIFFEY, 0x00 }, - { /*0x49*/ HEAD_MOTO, 0x00 }, - { /*0x4a*/ HEAD_WINNER, 0x00 }, + // head, require feature + { /*0x00*/ HEAD_DARK_COMBAT, 0 }, + { /*0x01*/ HEAD_DARK_FROCK, MPFEATURE_41 }, + { /*0x02*/ HEAD_DARKAQUA, MPFEATURE_45 }, + { /*0x03*/ HEAD_DARK_SNOW, MPFEATURE_4A }, + { /*0x04*/ HEAD_ELVIS, MPFEATURE_3D }, + { /*0x05*/ HEAD_ELVIS_GOGS, MPFEATURE_3D }, + { /*0x06*/ HEAD_CARRINGTON, 0 }, + { /*0x07*/ HEAD_MRBLONDE, MPFEATURE_38 }, + { /*0x08*/ HEAD_CASSANDRA, 0 }, + { /*0x09*/ HEAD_TRENT, MPFEATURE_35 }, + { /*0x0a*/ HEAD_JONATHAN, MPFEATURE_3A }, + { /*0x0b*/ HEAD_VD, 0 }, + { /*0x0c*/ HEAD_PRESIDENT, MPFEATURE_41 }, + { /*0x0d*/ HEAD_DDSHOCK, 0 }, + { /*0x0e*/ HEAD_BIOTECH, MPFEATURE_3C }, + { /*0x0f*/ HEAD_DDSNIPER, MPFEATURE_34 }, + { /*0x10*/ HEAD_A51FACEPLATE, MPFEATURE_3A }, + { /*0x11*/ HEAD_SECRETARY, 0 }, + { /*0x12*/ HEAD_FEM_GUARD, MPFEATURE_32 }, + { /*0x13*/ HEAD_FEM_GUARD2, MPFEATURE_32 }, + { /*0x14*/ HEAD_MAIAN_S, MPFEATURE_3D }, + { /*0x15*/ HEAD_JON, 0 }, + { /*0x16*/ HEAD_BEAU1, 0 }, + { /*0x17*/ HEAD_ROSS, 0 }, + { /*0x18*/ HEAD_MARK2, 0 }, + { /*0x19*/ HEAD_CHRIST, 0 }, + { /*0x1a*/ HEAD_RUSS, 0 }, + { /*0x1b*/ HEAD_DARLING, 0 }, + { /*0x1c*/ HEAD_BRIAN, 0 }, + { /*0x1d*/ HEAD_JAMIE, 0 }, + { /*0x1e*/ HEAD_DUNCAN2, 0 }, + { /*0x1f*/ HEAD_KEITH, 0 }, + { /*0x20*/ HEAD_STEVEM, 0 }, + { /*0x21*/ HEAD_GRANT, 0 }, + { /*0x22*/ HEAD_PENNY, 0 }, + { /*0x23*/ HEAD_DAVEC, 0 }, + { /*0x24*/ HEAD_JONES, 0 }, + { /*0x25*/ HEAD_GRAHAM, 0 }, + { /*0x26*/ HEAD_ROBERT, 0 }, + { /*0x27*/ HEAD_NEIL2, 0 }, + { /*0x28*/ HEAD_SHAUN, 0 }, + { /*0x29*/ HEAD_ROBIN, 0 }, + { /*0x2a*/ HEAD_COOK, 0 }, + { /*0x2b*/ HEAD_PRYCE, 0 }, + { /*0x2c*/ HEAD_SILKE, 0 }, + { /*0x2d*/ HEAD_SMITH, 0 }, + { /*0x2e*/ HEAD_GARETH, 0 }, + { /*0x2f*/ HEAD_MURCHIE, 0 }, + { /*0x30*/ HEAD_WONG, 0 }, + { /*0x31*/ HEAD_CARTER, 0 }, + { /*0x32*/ HEAD_TINTIN, 0 }, + { /*0x33*/ HEAD_MUNTON, 0 }, + { /*0x34*/ HEAD_STAMPER, 0 }, + { /*0x35*/ HEAD_PHELPS, 0 }, + { /*0x36*/ HEAD_ALEX, 0 }, + { /*0x37*/ HEAD_JULIANNE, 0 }, + { /*0x38*/ HEAD_LAURA, 0 }, + { /*0x39*/ HEAD_EDMCG, 0 }, + { /*0x3a*/ HEAD_ANKA, 0 }, + { /*0x3b*/ HEAD_LESLIE_S, 0 }, + { /*0x3c*/ HEAD_MATT_C, 0 }, + { /*0x3d*/ HEAD_PEER_S, 0 }, + { /*0x3e*/ HEAD_EILEEN_T, 0 }, + { /*0x3f*/ HEAD_ANDY_R, 0 }, + { /*0x40*/ HEAD_BEN_R, 0 }, + { /*0x41*/ HEAD_STEVE_K, 0 }, + { /*0x42*/ HEAD_SANCHEZ, 0 }, + { /*0x43*/ HEAD_TIM, 0 }, + { /*0x44*/ HEAD_KEN, 0 }, + { /*0x45*/ HEAD_EILEEN_H, 0 }, + { /*0x46*/ HEAD_SCOTT_H, 0 }, + { /*0x47*/ HEAD_JOEL, 0 }, + { /*0x48*/ HEAD_GRIFFEY, 0 }, + { /*0x49*/ HEAD_MOTO, 0 }, + { /*0x4a*/ HEAD_WINNER, 0 }, }; // 2d678 @@ -3118,91 +3118,91 @@ u32 table_0x2d678[] = { // 2d74c struct mpsimulanttype g_MpSimulantTypes[] = { - // type, skill, name, body, unlock value - { SIMTYPE_GENERAL, SIMSKILL_MEAT, L_MISC(88), MPBODY_DD_GUARD, 0x00 }, - { SIMTYPE_GENERAL, SIMSKILL_EASY, L_MISC(89), MPBODY_DD_SECGUARD, 0x00 }, - { SIMTYPE_GENERAL, SIMSKILL_NORMAL, L_MISC(90), MPBODY_DD_SHOCK_INF, 0x00 }, - { SIMTYPE_GENERAL, SIMSKILL_HARD, L_MISC(91), MPBODY_DDSHOCK, 0x19 }, - { SIMTYPE_GENERAL, SIMSKILL_PERFECT, L_MISC(92), MPBODY_STRIPES, 0x1a }, - { SIMTYPE_GENERAL, SIMSKILL_DARK, L_MISC(93), MPBODY_MOORE, 0x1c }, - { SIMTYPE_PEACE, SIMSKILL_NORMAL, L_MISC(94), MPBODY_DD_LABTECH, 0x00 }, - { SIMTYPE_SHIELD, SIMSKILL_NORMAL, L_MISC(95), MPBODY_G5_SWAT_GUARD, 0x00 }, - { SIMTYPE_ROCKET, SIMSKILL_NORMAL, L_MISC(96), MPBODY_G5_GUARD, 0x00 }, - { SIMTYPE_KAZE, SIMSKILL_NORMAL, L_MISC(97), MPBODY_PRES_SECURITY, 0x00 }, - { SIMTYPE_FIST, SIMSKILL_NORMAL, L_MISC(98), MPBODY_PELAGIC_GUARD, 0x00 }, - { SIMTYPE_PREY, SIMSKILL_NORMAL, L_MISC(99), MPBODY_DDSHOCK, 0x00 }, - { SIMTYPE_COWARD, SIMSKILL_NORMAL, L_MISC(100), MPBODY_PRESIDENT, 0x00 }, - { SIMTYPE_JUDGE, SIMSKILL_NORMAL, L_MISC(101), MPBODY_STEWARD, 0x00 }, - { SIMTYPE_FEUD, SIMSKILL_NORMAL, L_MISC(102), MPBODY_NSA_LACKEY, 0x00 }, - { SIMTYPE_SPEED, SIMSKILL_NORMAL, L_MISC(103), MPBODY_MRBLONDE, 0x00 }, - { SIMTYPE_TURTLE, SIMSKILL_NORMAL, L_MISC(104), MPBODY_CARRINGTON, 0x00 }, - { SIMTYPE_VENGE, SIMSKILL_NORMAL, L_MISC(105), MPBODY_ALASKAN_GUARD, 0x00 }, + // type, skill, name, body, require feature + { SIMTYPE_GENERAL, SIMSKILL_MEAT, L_MISC(88), MPBODY_DD_GUARD, 0 }, + { SIMTYPE_GENERAL, SIMSKILL_EASY, L_MISC(89), MPBODY_DD_SECGUARD, 0 }, + { SIMTYPE_GENERAL, SIMSKILL_NORMAL, L_MISC(90), MPBODY_DD_SHOCK_INF, 0 }, + { SIMTYPE_GENERAL, SIMSKILL_HARD, L_MISC(91), MPBODY_DDSHOCK, MPFEATURE_SIMSKILL_HARD }, + { SIMTYPE_GENERAL, SIMSKILL_PERFECT, L_MISC(92), MPBODY_STRIPES, MPFEATURE_SIMSKILL_PERFECT }, + { SIMTYPE_GENERAL, SIMSKILL_DARK, L_MISC(93), MPBODY_MOORE, MPFEATURE_SIMSKILL_DARK }, + { SIMTYPE_PEACE, SIMSKILL_NORMAL, L_MISC(94), MPBODY_DD_LABTECH, 0 }, + { SIMTYPE_SHIELD, SIMSKILL_NORMAL, L_MISC(95), MPBODY_G5_SWAT_GUARD, 0 }, + { SIMTYPE_ROCKET, SIMSKILL_NORMAL, L_MISC(96), MPBODY_G5_GUARD, 0 }, + { SIMTYPE_KAZE, SIMSKILL_NORMAL, L_MISC(97), MPBODY_PRES_SECURITY, 0 }, + { SIMTYPE_FIST, SIMSKILL_NORMAL, L_MISC(98), MPBODY_PELAGIC_GUARD, 0 }, + { SIMTYPE_PREY, SIMSKILL_NORMAL, L_MISC(99), MPBODY_DDSHOCK, 0 }, + { SIMTYPE_COWARD, SIMSKILL_NORMAL, L_MISC(100), MPBODY_PRESIDENT, 0 }, + { SIMTYPE_JUDGE, SIMSKILL_NORMAL, L_MISC(101), MPBODY_STEWARD, 0 }, + { SIMTYPE_FEUD, SIMSKILL_NORMAL, L_MISC(102), MPBODY_NSA_LACKEY, 0 }, + { SIMTYPE_SPEED, SIMSKILL_NORMAL, L_MISC(103), MPBODY_MRBLONDE, 0 }, + { SIMTYPE_TURTLE, SIMSKILL_NORMAL, L_MISC(104), MPBODY_CARRINGTON, 0 }, + { SIMTYPE_VENGE, SIMSKILL_NORMAL, L_MISC(105), MPBODY_ALASKAN_GUARD, 0 }, }; // 2d7dc struct mpbody g_MpBodies[NUM_MPBODIES] = { - // global body ID, name, head, unk06 - /*0x00*/ { BODY_DARK_COMBAT, L_OPTIONS(16), HEAD_DARK_COMBAT, 0x00 }, - /*0x01*/ { BODY_DARK_TRENCH, L_OPTIONS(17), HEAD_DARK_COMBAT, 0x46 }, - /*0x02*/ { BODY_DARK_FROCK, L_OPTIONS(18), HEAD_DARK_FROCK, 0x41 }, - /*0x03*/ { BODY_DARK_RIPPED, L_OPTIONS(19), HEAD_DARK_FROCK, 0x41 }, - /*0x04*/ { BODY_DARK_AF1, L_OPTIONS(20), HEAD_DARK_COMBAT, 0x3f }, - /*0x05*/ { BODY_DARK_LEATHER, L_MPWEAPONS(156), HEAD_DARK_COMBAT, 0x37 }, - /*0x06*/ { BODY_DARK_NEGOTIATOR, L_MPWEAPONS(157), HEAD_DARK_COMBAT, 0x34 }, - /*0x07*/ { BODY_DARKWET, L_OPTIONS(21), HEAD_DARKAQUA, 0x45 }, - /*0x08*/ { BODY_DARKAQUALUNG, L_OPTIONS(22), HEAD_DARKAQUA, 0x45 }, - /*0x09*/ { BODY_DARKSNOW, L_OPTIONS(23), HEAD_DARK_SNOW, 0x4a }, - /*0x0a*/ { BODY_DARKLAB, L_OPTIONS(24), HEAD_DARK_COMBAT, 0x3a }, - /*0x0b*/ { BODY_THEKING, L_OPTIONS(25), HEAD_ELVIS, 0x3d }, - /*0x0c*/ { BODY_ELVIS1, L_OPTIONS(26), HEAD_ELVIS, 0x3d }, - /*0x0d*/ { BODY_ELVISWAISTCOAT, L_MPWEAPONS(158), HEAD_ELVIS, 0x3d }, - /*0x0e*/ { BODY_CARRINGTON, L_OPTIONS(27), HEAD_CARRINGTON, 0x00 }, - /*0x0f*/ { BODY_CARREVENINGSUIT, L_OPTIONS(28), HEAD_CARRINGTON, 0x41 }, - /*0x10*/ { BODY_MRBLONDE, L_OPTIONS(29), HEAD_MRBLONDE, 0x38 }, - /*0x11*/ { BODY_CASSANDRA, L_OPTIONS(30), HEAD_CASSANDRA, 0x00 }, - /*0x12*/ { BODY_TRENT, L_OPTIONS(31), HEAD_TRENT, 0x35 }, - /*0x13*/ { BODY_JONATHAN, L_OPTIONS(32), HEAD_JONATHAN, 0x4c }, - /*0x14*/ { BODY_CILABTECH, L_OPTIONS(33), 1000, 0x00 }, - /*0x15*/ { BODY_CIFEMTECH, L_OPTIONS(34), 1000, 0x00 }, - /*0x16*/ { BODY_CISOLDIER, L_OPTIONS(35), 1000, 0x00 }, - /*0x17*/ { BODY_DDSHOCK, L_OPTIONS(36), HEAD_DDSHOCK, 0x00 }, - /*0x18*/ { BODY_FEM_GUARD, L_OPTIONS(37), 1000, 0x32 }, - /*0x19*/ { BODY_DD_SECGUARD, L_OPTIONS(38), 1000, 0x00 }, - /*0x1a*/ { BODY_DD_GUARD, L_OPTIONS(39), 1000, 0x00 }, - /*0x1b*/ { BODY_DD_SHOCK_INF, L_OPTIONS(40), 1000, 0x00 }, - /*0x1c*/ { BODY_SECRETARY, L_OPTIONS(41), 1000, 0x00 }, - /*0x1d*/ { BODY_OFFICEWORKER, L_OPTIONS(42), 1000, 0x33 }, - /*0x1e*/ { BODY_OFFICEWORKER2, L_OPTIONS(43), 1000, 0x33 }, - /*0x1f*/ { BODY_NEGOTIATOR, L_OPTIONS(44), 1000, 0x34 }, - /*0x20*/ { BODY_DDSNIPER, L_OPTIONS(45), HEAD_DDSNIPER, 0x34 }, - /*0x21*/ { BODY_G5_GUARD, L_OPTIONS(46), 1000, 0x37 }, - /*0x22*/ { BODY_G5_SWAT_GUARD, L_OPTIONS(47), 1000, 0x37 }, - /*0x23*/ { BODY_CIAGUY, L_OPTIONS(48), 1000, 0x39 }, - /*0x24*/ { BODY_FBIGUY, L_OPTIONS(49), 1000, 0x39 }, - /*0x25*/ { BODY_AREA51GUARD, L_OPTIONS(50), 1000, 0x3a }, - /*0x26*/ { BODY_A51TROOPER, L_OPTIONS(51), 1000, 0x3a }, - /*0x27*/ { BODY_A51AIRMAN, L_OPTIONS(52), 1000, 0x3a }, - /*0x28*/ { BODY_OVERALL, L_OPTIONS(53), 1000, 0x3a }, - /*0x29*/ { BODY_STRIPES, L_OPTIONS(54), 1000, 0x44 }, - /*0x2a*/ { BODY_LABTECH, L_OPTIONS(55), 1000, 0x3b }, - /*0x2b*/ { BODY_FEMLABTECH, L_OPTIONS(56), 1000, 0x3b }, - /*0x2c*/ { BODY_DD_LABTECH, L_OPTIONS(57), 1000, 0x3b }, - /*0x2d*/ { BODY_BIOTECH, L_OPTIONS(58), HEAD_BIOTECH, 0x3c }, - /*0x2e*/ { BODY_ALASKAN_GUARD, L_OPTIONS(59), 1000, 0x3e }, - /*0x2f*/ { BODY_PILOTAF1, L_OPTIONS(60), 1000, 0x3f }, - /*0x30*/ { BODY_STEWARD, L_OPTIONS(61), 1000, 0x3f }, - /*0x31*/ { BODY_STEWARDESS, L_OPTIONS(62), 1000, 0x3f }, - /*0x32*/ { BODY_STEWARDESS_COAT, L_OPTIONS(63), 1000, 0x3f }, - /*0x33*/ { BODY_PRESIDENT, L_OPTIONS(64), HEAD_PRESIDENT, 0x41 }, - /*0x34*/ { BODY_NSA_LACKEY, L_OPTIONS(65), 1000, 0x36 }, - /*0x35*/ { BODY_PRES_SECURITY, L_OPTIONS(66), 1000, 0x43 }, - /*0x36*/ { BODY_PRESIDENT_CLONE2, L_OPTIONS(67), HEAD_PRESIDENT, 0x42 }, - /*0x37*/ { BODY_PELAGIC_GUARD, L_OPTIONS(68), 1000, 0x45 }, - /*0x38*/ { BODY_MAIAN_SOLDIER, L_OPTIONS(69), HEAD_MAIAN_S, 0x3d }, - /*0x39*/ { BODY_CONNERY, L_OPTIONS(70), 1000, 0x40 }, - /*0x3a*/ { BODY_MOORE, L_OPTIONS(70), 1000, 0x40 }, - /*0x3b*/ { BODY_DALTON, L_OPTIONS(70), 1000, 0x40 }, - /*0x3c*/ { BODY_DJBOND, L_OPTIONS(70), 1000, 0x40 }, + // global body ID, name, head, require feature + /*0x00*/ { BODY_DARK_COMBAT, L_OPTIONS(16), HEAD_DARK_COMBAT, 0 }, + /*0x01*/ { BODY_DARK_TRENCH, L_OPTIONS(17), HEAD_DARK_COMBAT, MPFEATURE_46 }, + /*0x02*/ { BODY_DARK_FROCK, L_OPTIONS(18), HEAD_DARK_FROCK, MPFEATURE_41 }, + /*0x03*/ { BODY_DARK_RIPPED, L_OPTIONS(19), HEAD_DARK_FROCK, MPFEATURE_41 }, + /*0x04*/ { BODY_DARK_AF1, L_OPTIONS(20), HEAD_DARK_COMBAT, MPFEATURE_3F }, + /*0x05*/ { BODY_DARK_LEATHER, L_MPWEAPONS(156), HEAD_DARK_COMBAT, MPFEATURE_37 }, + /*0x06*/ { BODY_DARK_NEGOTIATOR, L_MPWEAPONS(157), HEAD_DARK_COMBAT, MPFEATURE_34 }, + /*0x07*/ { BODY_DARKWET, L_OPTIONS(21), HEAD_DARKAQUA, MPFEATURE_45 }, + /*0x08*/ { BODY_DARKAQUALUNG, L_OPTIONS(22), HEAD_DARKAQUA, MPFEATURE_45 }, + /*0x09*/ { BODY_DARKSNOW, L_OPTIONS(23), HEAD_DARK_SNOW, MPFEATURE_4A }, + /*0x0a*/ { BODY_DARKLAB, L_OPTIONS(24), HEAD_DARK_COMBAT, MPFEATURE_3A }, + /*0x0b*/ { BODY_THEKING, L_OPTIONS(25), HEAD_ELVIS, MPFEATURE_3D }, + /*0x0c*/ { BODY_ELVIS1, L_OPTIONS(26), HEAD_ELVIS, MPFEATURE_3D }, + /*0x0d*/ { BODY_ELVISWAISTCOAT, L_MPWEAPONS(158), HEAD_ELVIS, MPFEATURE_3D }, + /*0x0e*/ { BODY_CARRINGTON, L_OPTIONS(27), HEAD_CARRINGTON, 0 }, + /*0x0f*/ { BODY_CARREVENINGSUIT, L_OPTIONS(28), HEAD_CARRINGTON, MPFEATURE_41 }, + /*0x10*/ { BODY_MRBLONDE, L_OPTIONS(29), HEAD_MRBLONDE, MPFEATURE_38 }, + /*0x11*/ { BODY_CASSANDRA, L_OPTIONS(30), HEAD_CASSANDRA, 0 }, + /*0x12*/ { BODY_TRENT, L_OPTIONS(31), HEAD_TRENT, MPFEATURE_35 }, + /*0x13*/ { BODY_JONATHAN, L_OPTIONS(32), HEAD_JONATHAN, MPFEATURE_4C }, + /*0x14*/ { BODY_CILABTECH, L_OPTIONS(33), 1000, 0 }, + /*0x15*/ { BODY_CIFEMTECH, L_OPTIONS(34), 1000, 0 }, + /*0x16*/ { BODY_CISOLDIER, L_OPTIONS(35), 1000, 0 }, + /*0x17*/ { BODY_DDSHOCK, L_OPTIONS(36), HEAD_DDSHOCK, 0 }, + /*0x18*/ { BODY_FEM_GUARD, L_OPTIONS(37), 1000, MPFEATURE_32 }, + /*0x19*/ { BODY_DD_SECGUARD, L_OPTIONS(38), 1000, 0 }, + /*0x1a*/ { BODY_DD_GUARD, L_OPTIONS(39), 1000, 0 }, + /*0x1b*/ { BODY_DD_SHOCK_INF, L_OPTIONS(40), 1000, 0 }, + /*0x1c*/ { BODY_SECRETARY, L_OPTIONS(41), 1000, 0 }, + /*0x1d*/ { BODY_OFFICEWORKER, L_OPTIONS(42), 1000, MPFEATURE_33 }, + /*0x1e*/ { BODY_OFFICEWORKER2, L_OPTIONS(43), 1000, MPFEATURE_33 }, + /*0x1f*/ { BODY_NEGOTIATOR, L_OPTIONS(44), 1000, MPFEATURE_34 }, + /*0x20*/ { BODY_DDSNIPER, L_OPTIONS(45), HEAD_DDSNIPER, MPFEATURE_34 }, + /*0x21*/ { BODY_G5_GUARD, L_OPTIONS(46), 1000, MPFEATURE_37 }, + /*0x22*/ { BODY_G5_SWAT_GUARD, L_OPTIONS(47), 1000, MPFEATURE_37 }, + /*0x23*/ { BODY_CIAGUY, L_OPTIONS(48), 1000, MPFEATURE_39 }, + /*0x24*/ { BODY_FBIGUY, L_OPTIONS(49), 1000, MPFEATURE_39 }, + /*0x25*/ { BODY_AREA51GUARD, L_OPTIONS(50), 1000, MPFEATURE_3A }, + /*0x26*/ { BODY_A51TROOPER, L_OPTIONS(51), 1000, MPFEATURE_3A }, + /*0x27*/ { BODY_A51AIRMAN, L_OPTIONS(52), 1000, MPFEATURE_3A }, + /*0x28*/ { BODY_OVERALL, L_OPTIONS(53), 1000, MPFEATURE_3A }, + /*0x29*/ { BODY_STRIPES, L_OPTIONS(54), 1000, MPFEATURE_44 }, + /*0x2a*/ { BODY_LABTECH, L_OPTIONS(55), 1000, MPFEATURE_3B }, + /*0x2b*/ { BODY_FEMLABTECH, L_OPTIONS(56), 1000, MPFEATURE_3B }, + /*0x2c*/ { BODY_DD_LABTECH, L_OPTIONS(57), 1000, MPFEATURE_3B }, + /*0x2d*/ { BODY_BIOTECH, L_OPTIONS(58), HEAD_BIOTECH, MPFEATURE_3C }, + /*0x2e*/ { BODY_ALASKAN_GUARD, L_OPTIONS(59), 1000, MPFEATURE_3E }, + /*0x2f*/ { BODY_PILOTAF1, L_OPTIONS(60), 1000, MPFEATURE_3F }, + /*0x30*/ { BODY_STEWARD, L_OPTIONS(61), 1000, MPFEATURE_3F }, + /*0x31*/ { BODY_STEWARDESS, L_OPTIONS(62), 1000, MPFEATURE_3F }, + /*0x32*/ { BODY_STEWARDESS_COAT, L_OPTIONS(63), 1000, MPFEATURE_3F }, + /*0x33*/ { BODY_PRESIDENT, L_OPTIONS(64), HEAD_PRESIDENT, MPFEATURE_41 }, + /*0x34*/ { BODY_NSA_LACKEY, L_OPTIONS(65), 1000, MPFEATURE_36 }, + /*0x35*/ { BODY_PRES_SECURITY, L_OPTIONS(66), 1000, MPFEATURE_43 }, + /*0x36*/ { BODY_PRESIDENT_CLONE2, L_OPTIONS(67), HEAD_PRESIDENT, MPFEATURE_42 }, + /*0x37*/ { BODY_PELAGIC_GUARD, L_OPTIONS(68), 1000, MPFEATURE_45 }, + /*0x38*/ { BODY_MAIAN_SOLDIER, L_OPTIONS(69), HEAD_MAIAN_S, MPFEATURE_3D }, + /*0x39*/ { BODY_CONNERY, L_OPTIONS(70), 1000, MPFEATURE_8BOTS }, + /*0x3a*/ { BODY_MOORE, L_OPTIONS(70), 1000, MPFEATURE_8BOTS }, + /*0x3b*/ { BODY_DALTON, L_OPTIONS(70), 1000, MPFEATURE_8BOTS }, + /*0x3c*/ { BODY_DJBOND, L_OPTIONS(70), 1000, MPFEATURE_8BOTS }, }; u32 g_MpMaleHeads[] = { @@ -4828,9 +4828,9 @@ s32 mpGetHeadId(u8 headnum) return g_MpHeads[headnum].headnum; } -s32 mpGetHeadUnlockValue(u8 headnum) +s32 mpGetHeadRequiredFeature(u8 headnum) { - return g_MpHeads[headnum].unlockvalue; + return g_MpHeads[headnum].requirefeature; } s32 mpGetBeauHeadId(u8 headnum) @@ -4889,14 +4889,14 @@ char *mpGetBodyName(u8 bodynum) return langGet(g_MpBodies[bodynum].name); } -u8 mpGetBodyUnk06(u8 bodynum) +u8 mpGetBodyRequiredFeature(u8 bodynum) { // Possible @bug: This should probably be >= if (bodynum > NUM_MPBODIES) { bodynum = 0; } - return g_MpBodies[bodynum].unlockvalue; + return g_MpBodies[bodynum].requirefeature; } s32 mpGetMpheadnumByMpbodynum(s32 mpbodynum) @@ -5825,7 +5825,7 @@ GLOBAL_ASM( glabel func0f18cc8c /* f18cc8c: 27bdffe8 */ addiu $sp,$sp,-24 /* f18cc90: afbf0014 */ sw $ra,0x14($sp) -/* f18cc94: 0fc67244 */ jal mpIsChallengeComplete +/* f18cc94: 0fc67244 */ jal mpIsFeatureUnlocked /* f18cc98: 24040040 */ addiu $a0,$zero,0x40 /* f18cc9c: 10400003 */ beqz $v0,.L0f18ccac /* f18cca0: 3c04800b */ lui $a0,%hi(g_MpSetup+0x16) @@ -6412,7 +6412,7 @@ glabel func0f18d2b8 /* f18d554: 02802025 */ or $a0,$s4,$zero /* f18d558: 02202825 */ or $a1,$s1,$zero /* f18d55c: 02003025 */ or $a2,$s0,$zero -/* f18d560: 0fc6712e */ jal mpSetChallengeCompletedByChrWithNumPlayers +/* f18d560: 0fc6712e */ jal mpSetChallengeCompletedByPlayerWithNumPlayers /* f18d564: 00403825 */ or $a3,$v0,$zero /* f18d568: 26100001 */ addiu $s0,$s0,0x1 /* f18d56c: 5612fff7 */ bnel $s0,$s2,.L0f18d54c @@ -6685,7 +6685,7 @@ glabel func0f18d5c4 /* f18d93c: 02802025 */ or $a0,$s4,$zero .L0f18d940: /* f18d940: 02202825 */ or $a1,$s1,$zero -/* f18d944: 0fc6711f */ jal mpIsChallengeCompletedByChrWithNumPlayers +/* f18d944: 0fc6711f */ jal mpIsChallengeCompletedByPlayerWithNumPlayers /* f18d948: 02003025 */ or $a2,$s0,$zero /* f18d94c: 02602025 */ or $a0,$s3,$zero /* f18d950: 00402825 */ or $a1,$v0,$zero @@ -6857,8 +6857,8 @@ bool mpIsPresetUnlocked(s32 presetnum) s32 i; for (i = 0; i != 16; i++) { - if (!mpIsChallengeComplete(g_MpPresets[presetnum].challenges[i]) && - g_MpPresets[presetnum].challenges[i] != 22) { + if (!mpIsFeatureUnlocked(g_MpPresets[presetnum].requirefeatures[i]) && + g_MpPresets[presetnum].requirefeatures[i] != MPFEATURE_WEAPON_SHIELD) { return false; } } @@ -7002,7 +7002,7 @@ glabel func0f18dcec /* f18de3c: 26f70004 */ addiu $s7,$s7,0x4 /* f18de40: 1420ffd2 */ bnez $at,.L0f18dd8c /* f18de44: a239ffc5 */ sb $t9,-0x3b($s1) -/* f18de48: 0fc67244 */ jal mpIsChallengeComplete +/* f18de48: 0fc67244 */ jal mpIsFeatureUnlocked /* f18de4c: 24040016 */ addiu $a0,$zero,0x16 /* f18de50: 1440000c */ bnez $v0,.L0f18de84 /* f18de54: 3c04800b */ lui $a0,%hi(g_MpSetup+0x6) @@ -7211,7 +7211,7 @@ glabel func0f18df5c /* f18e130: 261000a0 */ addiu $s0,$s0,0xa0 /* f18e134: 1611fffb */ bne $s0,$s1,.L0f18e124 /* f18e138: a202ff71 */ sb $v0,-0x8f($s0) -/* f18e13c: 0fc66fe8 */ jal func0f19bfa0 +/* f18e13c: 0fc66fe8 */ jal mpForceUnlockSimulantFeatures /* f18e140: 00000000 */ nop /* f18e144: 8fbf0034 */ lw $ra,0x34($sp) /* f18e148: 8fb00018 */ lw $s0,0x18($sp) diff --git a/src/gvars/gvars.c b/src/gvars/gvars.c index df6919464..1e1296473 100644 --- a/src/gvars/gvars.c +++ b/src/gvars/gvars.c @@ -17140,8 +17140,10 @@ u32 var800acc74 = 0; u32 var800acc78 = 0; u32 var800acc7c = 0; struct chrdata *g_MpSimulantChrs[MAX_SIMULANTS] = {NULL}; -u8 var800acca0[40] = {0}; -u8 g_MpChallengesCompleted[88] = {0}; // This is one *byte* per challenge, and length is at least 64 +u8 g_MpFeaturesForceUnlocked[40] = {0}; +u8 g_MpFeaturesUnlocked[80] = {0}; +u32 var800acd18 = 0; +u32 var800acd1c = 0; struct frdata g_FrData = {0}; struct trainingdata g_DtData = {0}; struct trainingdata g_HoloTrainingData = {0}; diff --git a/src/include/constants.h b/src/include/constants.h index 02bc3909d..9a7d61844 100644 --- a/src/include/constants.h +++ b/src/include/constants.h @@ -246,10 +246,6 @@ #define CASING_RIFLE 2 #define CASING_SHOTGUN 3 -// Challenge numbers don't appear to be a 1:1 mapping :( -#define CHALLENGE_7 30 -#define CHALLENGE_UNK64 64 - #define CHANNEL_0 0 #define CHANNEL_1 1 #define CHANNEL_2 2 @@ -1767,6 +1763,87 @@ #define MPCONFIG_CHALLENGE29 0x2a #define MPCONFIG_CHALLENGE30 0x2b +// Features are things that can be unlocked +#define MPFEATURE_WEAPON_FARSIGHT 0x01 +#define MPFEATURE_WEAPON_TRANQUILIZER 0x02 +#define MPFEATURE_WEAPON_SUPERDRAGON 0x03 +#define MPFEATURE_WEAPON_SLAYER 0x04 +#define MPFEATURE_WEAPON_FALCON2SILENCED 0x05 +#define MPFEATURE_WEAPON_FALCON2SCOPE 0x06 +#define MPFEATURE_WEAPON_MAULER 0x07 +#define MPFEATURE_WEAPON_PHOENIX 0x08 +#define MPFEATURE_WEAPON_DY357LX 0x09 +#define MPFEATURE_WEAPON_CALLISTO 0x0a +#define MPFEATURE_WEAPON_LAPTOPGUN 0x0b +#define MPFEATURE_WEAPON_K7AVENGER 0x0c +#define MPFEATURE_WEAPON_RCP120 0x0d +#define MPFEATURE_WEAPON_SHOTGUN 0x0e +#define MPFEATURE_WEAPON_REAPER 0x0f +#define MPFEATURE_WEAPON_DEVASTATOR 0x10 +#define MPFEATURE_WEAPON_CROSSBOW 0x11 +#define MPFEATURE_WEAPON_NBOMB 0x12 +#define MPFEATURE_WEAPON_PROXIMITYMINE 0x13 +#define MPFEATURE_WEAPON_REMOTEMINE 0x14 +#define MPFEATURE_WEAPON_XRAYSCANNER 0x15 +#define MPFEATURE_WEAPON_SHIELD 0x16 +#define MPFEATURE_WEAPON_CLOAKINGDEVICE 0x17 +#define MPFEATURE_WEAPON_COMBATBOOST 0x18 +#define MPFEATURE_SIMSKILL_HARD 0x19 +#define MPFEATURE_SIMSKILL_PERFECT 0x1a +#define MPFEATURE_1B 0x1b +#define MPFEATURE_SIMSKILL_DARK 0x1c +#define MPFEATURE_SLOWMOTION 0x1d +#define MPFEATURE_ONEHITKILLS 0x1e +#define MPFEATURE_1F 0x1f +#define MPFEATURE_20 0x20 +#define MPFEATURE_21 0x21 +#define MPFEATURE_22 0x22 +#define MPFEATURE_STAGE_CARPARK 0x23 +#define MPFEATURE_STAGE_COMPLEX 0x24 +#define MPFEATURE_STAGE_WAREHOUSE 0x25 +#define MPFEATURE_STAGE_RAVINE 0x26 +#define MPFEATURE_STAGE_TEMPLE 0x27 +#define MPFEATURE_STAGE_G5BUILDING 0x28 +#define MPFEATURE_STAGE_GRID 0x29 +#define MPFEATURE_STAGE_FELICITY 0x2a +#define MPFEATURE_STAGE_VILLA 0x2b +#define MPFEATURE_STAGE_SEWERS 0x2c +#define MPFEATURE_STAGE_RUINS 0x2d +#define MPFEATURE_STAGE_BASE 0x2e +#define MPFEATURE_2F 0x2f +#define MPFEATURE_STAGE_FORTRESS 0x30 +#define MPFEATURE_31 0x31 +#define MPFEATURE_32 0x32 +#define MPFEATURE_33 0x33 +#define MPFEATURE_34 0x34 +#define MPFEATURE_35 0x35 +#define MPFEATURE_36 0x36 +#define MPFEATURE_37 0x37 +#define MPFEATURE_38 0x38 +#define MPFEATURE_39 0x39 +#define MPFEATURE_3A 0x3a +#define MPFEATURE_3B 0x3b +#define MPFEATURE_3C 0x3c +#define MPFEATURE_3D 0x3d +#define MPFEATURE_3E 0x3e +#define MPFEATURE_3F 0x3f +#define MPFEATURE_8BOTS 0x40 // also unlocks the 4 Bonds +#define MPFEATURE_41 0x41 +#define MPFEATURE_42 0x42 +#define MPFEATURE_43 0x43 +#define MPFEATURE_44 0x44 +#define MPFEATURE_45 0x45 +#define MPFEATURE_46 0x46 +#define MPFEATURE_47 0x47 +#define MPFEATURE_48 0x48 +#define MPFEATURE_49 0x49 +#define MPFEATURE_4A 0x4a +#define MPFEATURE_4B 0x4b +#define MPFEATURE_4C 0x4c +#define MPFEATURE_4D 0x4d +#define MPFEATURE_4E 0x4e +#define MPFEATURE_WEAPON_LASER 0x4f + #define MPHEAD_DARK_COMBAT 0x00 #define MPHEAD_DARK_FROCK 0x01 #define MPHEAD_DARKAQUA 0x02 diff --git a/src/include/game/game_19aa80.h b/src/include/game/game_19aa80.h index 5d4271f98..2af3393fd 100644 --- a/src/include/game/game_19aa80.h +++ b/src/include/game/game_19aa80.h @@ -14,18 +14,18 @@ void mpPerformSanityChecks(void); char *mpGetChallengeNameBySlot(s32 slot); bool mpIsChallengeCompletedByAnyChrWithNumPlayersBySlot(s32 slot, s32 numplayers); struct mpconfigfull *mpLoadConfig(s32 confignum, u8 *buffer, s32 len); -s32 func0f19bb50(s32 unlockvalue, u8 *array, s32 index, s32 len); +s32 mpForceUnlockFeature(s32 featurenum, u8 *array, s32 tail, s32 len); s32 func0f19bb98(struct mpsetup *mpsetup, u8 *array, s32 len); u32 func0f19bd4c(void); -void func0f19bfa0(void); +void mpForceUnlockSimulantFeatures(void); void func0f19c1cc(void); char *mpGetCurrentChallengeDescription(void); char *mpconfigGetDescription(struct mpconfigfull *mpconfig); bool mpIsChallengeCompleteForEndscreen(void); bool aiMpInitSimulants(void); void func0f19ab40(void); -bool func0f19af3c(s32 chrnum, s32 challengeindex); -bool mpIsChallengeAvailable(s32 challengeindex); +bool mpIsChallengeAvailableToPlayer(s32 chrnum, s32 challengeindex); +bool mpIsChallengeAvailableToAnyPlayer(s32 challengeindex); s32 mpGetNumAvailableChallenges(void); char *mpChallengeGetName(s32 challengeindex); void mpSetCurrentChallenge(s32 slotnum); @@ -38,14 +38,14 @@ s32 mpRemoveLock(void); void mpLoadAndStoreCurrentChallenge(u8 *buffer, s32 len); void mpClearCurrentChallenge(void); bool mpIsChallengeLoaded(void); -s32 mpGetNumChallengesAvailable(s32 mpchrnum); +s32 mpGetAutoFocusedChallengeIndex(s32 mpchrnum); char *mpChallengeGetNameWithArg(s32 arg0, s32 challengeindex); -bool func0f19c3bc(s32 mpchrnum, s32 index, s32 numplayers); -bool mpIsChallengeCompletedByAnyChrWithNumPlayers(s32 index, s32 numplayers); -void mpSetChallengeCompletedByAnyChrWithNumPlayers(s32 index, s32 numplayers, bool completed); -bool mpIsChallengeCompletedByChrWithNumPlayers(s32 mpchrnum, s32 index, s32 numplayers); -void mpSetChallengeCompletedByChrWithNumPlayers(u32 mpchrnum, s32 index, s32 numplayers, bool completed); +bool mpIsChallengeCompletedByPlayerWithNumPlayers2(s32 mpchrnum, s32 index, s32 numplayers); +bool mpIsChallengeCompletedByAnyPlayerWithNumPlayers(s32 index, s32 numplayers); +void mpSetChallengeCompletedByAnyPlayerWithNumPlayers(s32 index, s32 numplayers, bool completed); +bool mpIsChallengeCompletedByPlayerWithNumPlayers(s32 mpchrnum, s32 index, s32 numplayers); +void mpSetChallengeCompletedByPlayerWithNumPlayers(u32 mpchrnum, s32 index, s32 numplayers, bool completed); void mpConsiderMarkingCurrentChallengeComplete(void); -bool mpIsChallengeComplete(s32 challenge); +bool mpIsFeatureUnlocked(s32 feature); #endif diff --git a/src/include/game/mplayer.h b/src/include/game/mplayer.h index df65db564..5861f8994 100644 --- a/src/include/game/mplayer.h +++ b/src/include/game/mplayer.h @@ -48,13 +48,13 @@ void func0f18b9e4(void); u32 func0f18bb1c(void); s32 mpGetNumHeads(void); s32 mpGetHeadId(u8 headnum); -s32 mpGetHeadUnlockValue(u8 headnum); +s32 mpGetHeadRequiredFeature(u8 headnum); s32 mpGetBeauHeadId(u8 headnum); u32 mpGetNumBodies(void); s32 mpGetBodyId(u8 bodynum); s32 mpGetMpbodynumByBodynum(u16 bodynum); char *mpGetBodyName(u8 bodynum); -u8 mpGetBodyUnk06(u8 bodynum); +u8 mpGetBodyRequiredFeature(u8 bodynum); s32 mpGetMpheadnumByMpbodynum(s32 bodynum); u32 mpChooseRandomLockPlayer(void); bool mpSetLock(s32 locktype, s32 playernum); diff --git a/src/include/gvars/gvars.h b/src/include/gvars/gvars.h index 0c45f321a..5a10a7415 100644 --- a/src/include/gvars/gvars.h +++ b/src/include/gvars/gvars.h @@ -833,8 +833,8 @@ extern u32 var800acc28[18]; extern u32 var800acc70; extern u32 var800acc74; extern struct chrdata *g_MpSimulantChrs[MAX_SIMULANTS]; -extern u8 var800acca0[40]; -extern u8 g_MpChallengesCompleted[]; +extern u8 g_MpFeaturesForceUnlocked[40]; +extern u8 g_MpFeaturesUnlocked[80]; extern struct frdata g_FrData; extern struct trainingdata g_DtData; extern struct trainingdata g_HoloTrainingData; diff --git a/src/include/types.h b/src/include/types.h index cddde52a0..f017b1882 100644 --- a/src/include/types.h +++ b/src/include/types.h @@ -3070,7 +3070,7 @@ struct stagetableentry { struct mpweaponset { /*0x00*/ u16 name; /*0x02*/ u8 slots[6]; - /*0x08*/ u8 unlocks[4]; + /*0x08*/ u8 requirefeatures[4]; /*0x0c*/ u8 unk0c; /*0x0d*/ u8 unk0d; /*0x0e*/ u8 unk0e; @@ -3081,7 +3081,7 @@ struct mpweaponset { struct mphead { s16 headnum; - u8 unlockvalue; + u8 requirefeature; }; struct mpsimulanttype { @@ -3089,14 +3089,14 @@ struct mpsimulanttype { /*0x01*/ u8 skill; /*0x02*/ u16 name; /*0x04*/ u16 body; - /*0x06*/ u8 unlockvalue; + /*0x06*/ u8 requirefeature; }; struct mpbody { s16 bodynum; s16 name; s16 headnum; - u8 unlockvalue; + u8 requirefeature; }; struct mptrack { @@ -4484,7 +4484,7 @@ struct mpscenariooverview { struct mparena { s16 stagenum; - u8 unlock; + u8 requirefeature; u16 name; }; @@ -4521,11 +4521,20 @@ struct challenge { /*0x00*/ u16 name; /*0x02*/ s16 confignum; - // One byte for each number of players, - // and 4 bits in each to mark which players completed it - /*0x04*/ u8 completions[5]; + // Bitfield xxx4 321a + // The number denotes if that player has the challenge available, + // and `a` denotes if any other has the challenge available. + /*0x04*/ u8 availability; - /*0x09*/ u8 unk09[16]; + // Same structure as availability, however each byte determines how many + // players it was completed with. So completions[0] is for completions with + // a single player and completions[3] is for completions with 4 players. + /*0x05*/ u8 completions[4]; + + // Array of features which will become unlocked once the challenge is + // available. Seems to be unused though, as all arrays are empty. + // Maybe it's populated at runtime? + /*0x09*/ u8 unlockfeatures[16]; }; struct scenariodata_cbt { @@ -4777,7 +4786,7 @@ struct criteria_holograph { struct mppreset { u16 name; u32 confignum; - u8 challenges[16]; + u8 requirefeatures[16]; // Doesn't seem to be used? All values are zero }; struct explosiontype { @@ -5816,7 +5825,7 @@ struct mpweapon { /*0x03*/ s8 weapon2ammotypeminusone; /*0x04*/ u8 weapon2ammoqty; /*0x05*/ u8 giveweapon : 1; - /*0x05*/ u8 unlock : 7; + /*0x05*/ u8 unlockfeature : 7; /*0x06*/ s16 model; /*0x08*/ s16 extrascale; };