diff --git a/src/ailists/gailists.c b/src/ailists/gailists.c index b8e6fa627..564decca0 100644 --- a/src/ailists/gailists.c +++ b/src/ailists/gailists.c @@ -3628,31 +3628,20 @@ u8 func0000_idle_0009[] = { u8 func0016_show_objective_failed_msg[] = { // Wait until an objective has failed beginloop(0x0c) - if_timer_gt(0, /*goto*/ 0x13) - if_objective_failed(0, /*goto*/ 0x16) - if_objective_failed(1, /*goto*/ 0x16) - if_objective_failed(2, /*goto*/ 0x16) - if_objective_failed(3, /*goto*/ 0x16) - if_objective_failed(4, /*goto*/ 0x16) + if_any_objective_failed(/*goto*/ 0x16) endloop(0x0c) - // Wait 30 seconds. It iterates to the top loop here, which instantly jumps - // down to 0x13 because the timer is > 0. Seems a bit unnecessary... + // Wait 30 seconds label(0x16) restart_timer - yield - label(0x13) - if_timer_gt(1800, /*goto*/ 0x13) - goto_first(0x0c) + beginloop(0x0d) + if_timer_gt(1800, /*goto*/ 0x13) + endloop(0x0d) // Check objective is still failed label(0x13) - if_objective_failed(0, /*goto*/ 0x13) - if_objective_failed(1, /*goto*/ 0x13) - if_objective_failed(2, /*goto*/ 0x13) - if_objective_failed(3, /*goto*/ 0x13) - if_objective_failed(4, /*goto*/ 0x13) + if_any_objective_failed(/*goto*/ 0x13) set_ailist(CHR_SELF, GAILIST_IDLE) // Show message first time @@ -3668,11 +3657,7 @@ u8 func0016_show_objective_failed_msg[] = { // Check objective is still failed label(0x16) - if_objective_failed(0, /*goto*/ 0x13) - if_objective_failed(1, /*goto*/ 0x13) - if_objective_failed(2, /*goto*/ 0x13) - if_objective_failed(3, /*goto*/ 0x13) - if_objective_failed(4, /*goto*/ 0x13) + if_any_objective_failed(/*goto*/ 0x13) set_ailist(CHR_SELF, GAILIST_IDLE) // Show message second time @@ -3687,11 +3672,7 @@ u8 func0016_show_objective_failed_msg[] = { // Check objective is still failed label(0x06) - if_objective_failed(0, /*goto*/ 0x13) - if_objective_failed(1, /*goto*/ 0x13) - if_objective_failed(2, /*goto*/ 0x13) - if_objective_failed(3, /*goto*/ 0x13) - if_objective_failed(4, /*goto*/ 0x13) + if_any_objective_failed(/*goto*/ 0x13) set_ailist(CHR_SELF, GAILIST_IDLE) // Show message third time diff --git a/src/ailists/setupark.c b/src/ailists/setupark.c index 9f69b2afd..ef5bc3b4b 100644 --- a/src/ailists/setupark.c +++ b/src/ailists/setupark.c @@ -2790,11 +2790,7 @@ u8 func1014_msg_cantleaveany[] = { u8 func1015_msg_jumpshipwaiting[] = { beginloop(0x1f) - if_objective_failed(0, /*goto*/ 0x00) - if_objective_failed(1, /*goto*/ 0x00) - if_objective_failed(2, /*goto*/ 0x00) - if_objective_failed(3, /*goto*/ 0x00) - if_objective_failed(4, /*goto*/ 0x00) + if_any_objective_failed(/*goto*/ 0x00) if_chr_in_room(CHR_BOND, 0x00, 0x0002, /*goto*/ 0x20) endloop(0x1f) diff --git a/src/game/chraicommands.c b/src/game/chraicommands.c index 2468d93ac..9fde12c8c 100644 --- a/src/game/chraicommands.c +++ b/src/game/chraicommands.c @@ -1980,17 +1980,33 @@ bool aiIfNeverBeenOnScreen(void) bool aiIfObjectiveComplete(s32 index) { return index < objectiveGetCount() - && objectiveCheck(index) == OBJECTIVE_COMPLETE + && g_ObjectiveStatuses[index] == OBJECTIVE_COMPLETE && objectiveGetDifficultyBits(index) & (1 << lvGetDifficulty()); } bool aiIfObjectiveFailed(s32 index) { return index < objectiveGetCount() - && objectiveCheck(index) == OBJECTIVE_FAILED + && g_ObjectiveStatuses[index] == OBJECTIVE_FAILED && objectiveGetDifficultyBits(index) & (1 << lvGetDifficulty()); } +bool aiIfAnyObjectiveFailed(void) +{ + s32 numobjectives = objectiveGetCount(); + s32 mask = 1 << lvGetDifficulty(); + s32 i; + + for (i = 0; i < numobjectives; i++) { + if (g_ObjectiveStatuses[i] == OBJECTIVE_FAILED + && objectiveGetDifficultyBits(i) & mask) { + return true; + } + } + + return false; +} + bool aiIfObjectDistanceToPadLessThan(s32 tagnum, s32 padnum, f32 distance) { f32 xdiff; diff --git a/src/include/commands.h b/src/include/commands.h index 2b858d0a8..6af0902a9 100644 --- a/src/include/commands.h +++ b/src/include/commands.h @@ -941,6 +941,10 @@ objective, \ label, +#define if_any_objective_failed(label) \ + mkshort(0x0064), \ + label, + /** * This is only ever called in a sequence of 4, with u1 values 8, 2, 4, 8 in * that order. Believed to be a pad within specific distance of target chr, diff --git a/tools/ai2asm/ai2asm.py b/tools/ai2asm/ai2asm.py index c6376f142..859378a33 100755 --- a/tools/ai2asm/ai2asm.py +++ b/tools/ai2asm/ai2asm.py @@ -562,6 +562,10 @@ class App(): self.emit('jal', ['aiIfChrAmmoQuantityLessThan']) self.emit_bnez_label(params[3]) + def ai_if_any_objective_failed(self, params): + self.emit('jal', ['aiIfAnyObjectiveFailed']) + self.emit_bnez_label(params[0]) + def ai_if_calculated_safety2_lt(self, params): self.emit('li', ['$a0', params[0]]) self.emit('jal', ['aiIfSafety2LessThan']) diff --git a/tools/ai2asm/commands.py b/tools/ai2asm/commands.py index 66bef326c..d9effdaa1 100644 --- a/tools/ai2asm/commands.py +++ b/tools/ai2asm/commands.py @@ -84,6 +84,7 @@ def get_commands(): commands[0x0061] = {'macro': 'if_gun_unclaimed', 'len': 5} commands[0x0062] = {'macro': 'if_object_in_good_condition', 'len': 4} commands[0x0063] = {'macro': 'if_chr_activated_object', 'len': 5} + commands[0x0064] = {'macro': 'if_any_objective_failed', 'len': 3} commands[0x0066] = {'macro': 'destroy_object', 'len': 3} commands[0x0068] = {'macro': 'drop_concealed_items', 'len': 3} commands[0x0069] = {'macro': 'chr_drop_weapon', 'len': 3}