Impl Triple Shells, fix CPU items (#597)
* Impl triple shell * CPUs can throw greenshells backwards --------- Authored-by: Luiz Henrique <luizlink64@gmail.com>
This commit is contained in:
parent
1a5c79b641
commit
99b5630055
|
|
@ -106,6 +106,8 @@ enum ShellState {
|
|||
BLUE_SHELL_TARGET_ELIMINATED // Mission completed, well done boss.
|
||||
};
|
||||
|
||||
#define THROW_SHELL_BACKWARDS -45 // Analogue stick Y value
|
||||
|
||||
// Actor banana->state
|
||||
enum BananaState {
|
||||
HELD_BANANA, // Single banana that has not been dropped.
|
||||
|
|
@ -305,7 +307,7 @@ typedef struct {
|
|||
/* 0x02 */ s16 flags;
|
||||
/* 0x04 */ s16 shellsAvailable;
|
||||
/* 0x06 */ s16 state;
|
||||
/* 0x08 */ f32 unk_08;
|
||||
/* 0x08 */ f32 firePressed; // Set to 1.0 when Z is pressed. Triggers if value higher than 0.0, acts like a boolean
|
||||
/* 0x0C */ f32 unk_0C;
|
||||
/* 0x10 */ s16 rotVelocity;
|
||||
/* 0x12 */ s16 rotAngle;
|
||||
|
|
|
|||
|
|
@ -512,6 +512,8 @@ player spins. Something with avoding rollover of aniamation frame data? */
|
|||
#define SPAWN_FIRST_SHELL 0
|
||||
#define SPAWN_SECOND_SHELL 1
|
||||
#define SPAWN_THIRD_SHELL 2
|
||||
#define SHELL_COLLISION 3 // Activated when triple shells have spawned
|
||||
#define ORBIT_PLAYER 4
|
||||
|
||||
#define GPACK_RGB888(r, g, b) (((r) << 16) | ((g) << 8) | (b))
|
||||
#define COLOR_LIGHT GPACK_RGB888(0x1C, 0x00, 0x00)
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@
|
|||
#define VER_PRODUCTVERSION 0, 1, 0, 0
|
||||
#define VER_PRODUCTVERSION_str "0.1.0\0"
|
||||
|
||||
#define VER_COMPANYNAME_STR "Spaghettikart Team - Harbourmasters\0"
|
||||
#define VER_PRODUCTNAME_STR "Spaghettikart\0"
|
||||
#define VER_COMPANYNAME_STR "SpaghettiKart Team - Harbourmasters\0"
|
||||
#define VER_PRODUCTNAME_STR "SpaghettiKart\0"
|
||||
|
||||
#define VER_INTERNALNAME_STR "Spaghettikart\0"
|
||||
#define VER_INTERNALNAME_STR "SpaghettiKart\0"
|
||||
#define VER_ORIGINALFILENAME_STR "Spaghettify.exe\0"
|
||||
|
||||
#define VER_FILEDESCRIPTION_STR "Spaghettikart - Alfredo Alfa\0"
|
||||
#define VER_FILEDESCRIPTION_STR "SpaghettiKart - Alfredo Alfa\0"
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ void update_actor_green_shell(struct ShellActor* shell) {
|
|||
controller = &gControllers[shell->playerId];
|
||||
if ((controller->buttonDepressed & Z_TRIG) != 0) {
|
||||
controller->buttonDepressed &= ~Z_TRIG;
|
||||
if (controller->rawStickY < -0x2D) {
|
||||
if (controller->rawStickY < THROW_SHELL_BACKWARDS) {
|
||||
var_f2 = 8.0f;
|
||||
if (player->speed > 8.0f) {
|
||||
var_f2 = player->speed * 1.2f;
|
||||
|
|
@ -71,14 +71,14 @@ void update_actor_green_shell(struct ShellActor* shell) {
|
|||
shell->velocity[0] = somePosVel[0];
|
||||
shell->velocity[1] = somePosVel[1];
|
||||
shell->velocity[2] = somePosVel[2];
|
||||
shell->state = 2;
|
||||
shell->state = MOVING_SHELL;
|
||||
func_800C9060(shell->playerId, SOUND_ARG_LOAD(0x19, 0x00, 0x80, 0x04));
|
||||
func_800C90F4(shell->playerId,
|
||||
(player->characterId * 0x10) + SOUND_ARG_LOAD(0x29, 0x00, 0x80, 0x00));
|
||||
add_green_shell_in_unexpired_actor_list(CM_FindActorIndex(shell));
|
||||
return;
|
||||
} else {
|
||||
shell->state = 1;
|
||||
shell->state = RELEASED_SHELL;
|
||||
if (player->unk_0C0 > 0) {
|
||||
shell->rotAngle = 0x78E3;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -7092,7 +7092,7 @@ void cpu_decisions_branch_item(UNUSED s32 playerId, s16* branch, s32 itemId) {
|
|||
break;
|
||||
}
|
||||
|
||||
if (CVarGetInteger("gHarderCPU", 0) == 1) {
|
||||
if (CVarGetInteger("gHarderCPU", false) == true) {
|
||||
switch (itemId) {
|
||||
case ITEM_NONE:
|
||||
value = -1;
|
||||
|
|
@ -7109,12 +7109,12 @@ void cpu_decisions_branch_item(UNUSED s32 playerId, s16* branch, s32 itemId) {
|
|||
case ITEM_RED_SHELL:
|
||||
value = CPU_STRATEGY_ITEM_RED_SHELL;
|
||||
break;
|
||||
// case ITEM_TRIPLE_GREEN_SHELL:
|
||||
// value = CPU_STRATEGY_ITEM_TRIPLE_GREEN_SHELL;
|
||||
// break;
|
||||
// case ITEM_TRIPLE_RED_SHELL:
|
||||
// value = CPU_STRATEGY_ITEM_TRIPLE_RED_SHELL;
|
||||
// break;
|
||||
case ITEM_TRIPLE_GREEN_SHELL:
|
||||
value = CPU_STRATEGY_ITEM_TRIPLE_GREEN_SHELL;
|
||||
break;
|
||||
case ITEM_TRIPLE_RED_SHELL:
|
||||
value = CPU_STRATEGY_ITEM_TRIPLE_RED_SHELL;
|
||||
break;
|
||||
case ITEM_DOUBLE_MUSHROOM:
|
||||
value = CPU_STRATEGY_ITEM_DOUBLE_MUSHROOM;
|
||||
break;
|
||||
|
|
@ -7222,7 +7222,7 @@ void cpu_use_item_strategy(s32 playerId) {
|
|||
}
|
||||
} else if (cpuStrategy->branch == CPU_STRATEGY_ITEM_BANANA) {
|
||||
cpuStrategy->actorIndex = use_banana_item(player);
|
||||
if ((cpuStrategy->actorIndex >= 0) && (cpuStrategy->actorIndex < 100)) {
|
||||
if (cpuStrategy->actorIndex >= 0) {
|
||||
player->triggers |= DRAG_ITEM_EFFECT;
|
||||
cpuStrategy->branch = CPU_STRATEGY_HOLD_BANANA;
|
||||
cpuStrategy->timer = 0;
|
||||
|
|
@ -7239,13 +7239,6 @@ void cpu_use_item_strategy(s32 playerId) {
|
|||
actor = GET_ACTOR(cpuStrategy->actorIndex);
|
||||
if ((!(BANANA_ACTOR(actor)->flags & 0x8000)) || (BANANA_ACTOR(actor)->type != ACTOR_BANANA) ||
|
||||
(BANANA_ACTOR(actor)->state != HELD_BANANA) || (playerId != BANANA_ACTOR(actor)->playerId)) {
|
||||
|
||||
// FAKE
|
||||
if (!(BANANA_ACTOR(actor)->flags & 0x8000)) {}
|
||||
if (BANANA_ACTOR(actor)->type != 6) {}
|
||||
if (BANANA_ACTOR(actor)->state != 0) {}
|
||||
if (BANANA_ACTOR(actor)->rot[0] != playerId) {}
|
||||
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
cpuStrategy->timer = 0;
|
||||
player->triggers &= ~DRAG_ITEM_EFFECT;
|
||||
|
|
@ -7259,13 +7252,6 @@ void cpu_use_item_strategy(s32 playerId) {
|
|||
if ((((!(BANANA_ACTOR(actor)->flags & 0x8000)) || (BANANA_ACTOR(actor)->type != ACTOR_BANANA)) ||
|
||||
(BANANA_ACTOR(actor)->state != HELD_BANANA)) ||
|
||||
(playerId != BANANA_ACTOR(actor)->playerId)) {
|
||||
|
||||
// FAKE
|
||||
if (!(BANANA_ACTOR(actor)->flags & 0x8000)) {}
|
||||
if (BANANA_ACTOR(actor)->type != 6) {}
|
||||
if (BANANA_ACTOR(actor)->state != 0) {}
|
||||
if (BANANA_ACTOR(actor)->rot[0] != playerId) {}
|
||||
|
||||
} else {
|
||||
BANANA_ACTOR(actor)->state = DROPPED_BANANA;
|
||||
BANANA_ACTOR(actor)->velocity[0] = 0.0f;
|
||||
|
|
@ -7284,7 +7270,7 @@ void cpu_use_item_strategy(s32 playerId) {
|
|||
|
||||
case CPU_STRATEGY_THROW_BANANA:
|
||||
cpuStrategy->actorIndex = use_banana_item(player);
|
||||
if ((cpuStrategy->actorIndex >= 0) && (cpuStrategy->actorIndex < 100)) {
|
||||
if (cpuStrategy->actorIndex >= 0) {
|
||||
actor = GET_ACTOR(cpuStrategy->actorIndex);
|
||||
BANANA_ACTOR(actor)->state = BANANA_ON_GROUND;
|
||||
player->triggers |= DRAG_ITEM_EFFECT;
|
||||
|
|
@ -7311,13 +7297,6 @@ void cpu_use_item_strategy(s32 playerId) {
|
|||
if ((((!(BANANA_ACTOR(actor)->flags & 0x8000)) || (BANANA_ACTOR(actor)->type != ACTOR_BANANA)) ||
|
||||
(BANANA_ACTOR(actor)->state != BANANA_ON_GROUND)) ||
|
||||
(playerId != BANANA_ACTOR(actor)->playerId)) {
|
||||
|
||||
// FAKE
|
||||
if (!(BANANA_ACTOR(actor)->flags & 0x8000)) {}
|
||||
if (BANANA_ACTOR(actor)->type != 6) {}
|
||||
if (BANANA_ACTOR(actor)->state != 0) {}
|
||||
if (BANANA_ACTOR(actor)->rot[0] != playerId) {}
|
||||
|
||||
cpuStrategy->timer = 0;
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
player->triggers &= ~DRAG_ITEM_EFFECT;
|
||||
|
|
@ -7337,13 +7316,6 @@ void cpu_use_item_strategy(s32 playerId) {
|
|||
if ((((!(BANANA_ACTOR(actor)->flags & 0x8000)) || (BANANA_ACTOR(actor)->type != ACTOR_BANANA)) ||
|
||||
(BANANA_ACTOR(actor)->state != BANANA_ON_GROUND)) ||
|
||||
(playerId != BANANA_ACTOR(actor)->playerId)) {
|
||||
|
||||
// FAKE
|
||||
if (!(BANANA_ACTOR(actor)->flags & 0x8000)) {}
|
||||
if (BANANA_ACTOR(actor)->type != 6) {}
|
||||
if (BANANA_ACTOR(actor)->state != 0) {}
|
||||
if (BANANA_ACTOR(actor)->rot[0] != playerId) {}
|
||||
|
||||
} else {
|
||||
BANANA_ACTOR(actor)->state = DROPPED_BANANA;
|
||||
BANANA_ACTOR(actor)->velocity[0] = 0.0f;
|
||||
|
|
@ -7360,16 +7332,12 @@ void cpu_use_item_strategy(s32 playerId) {
|
|||
break;
|
||||
|
||||
case CPU_STRATEGY_ITEM_GREEN_SHELL:
|
||||
if (gNumActors < 80) {
|
||||
cpuStrategy->actorIndex = use_green_shell_item(player);
|
||||
if ((cpuStrategy->actorIndex >= 0) && (cpuStrategy->actorIndex < 100)) {
|
||||
cpuStrategy->branch = CPU_STRATEGY_HOLD_GREEN_SHELL;
|
||||
cpuStrategy->timer = 0;
|
||||
cpuStrategy->numItemUse += 1;
|
||||
cpuStrategy->timeBeforeThrow = (random_int(3) * 20) + 10;
|
||||
} else {
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
}
|
||||
cpuStrategy->actorIndex = use_green_shell_item(player);
|
||||
if (cpuStrategy->actorIndex >= 0) {
|
||||
cpuStrategy->branch = CPU_STRATEGY_HOLD_GREEN_SHELL;
|
||||
cpuStrategy->timer = 0;
|
||||
cpuStrategy->numItemUse += 1;
|
||||
cpuStrategy->timeBeforeThrow = (random_int(3) * 20) + 10;
|
||||
} else {
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
}
|
||||
|
|
@ -7380,13 +7348,6 @@ void cpu_use_item_strategy(s32 playerId) {
|
|||
if ((((!(SHELL_ACTOR(actor)->flags & 0x8000)) || (actor->type != ACTOR_GREEN_SHELL)) ||
|
||||
(SHELL_ACTOR(actor)->state != HELD_SHELL)) ||
|
||||
(playerId != SHELL_ACTOR(actor)->playerId)) {
|
||||
|
||||
// FAKE
|
||||
if (!(SHELL_ACTOR(actor)->flags & 0x8000)) {}
|
||||
if (SHELL_ACTOR(actor)->type != 7) {}
|
||||
if (SHELL_ACTOR(actor)->state != 0) {}
|
||||
if (SHELL_ACTOR(actor)->rotVelocity != playerId) {}
|
||||
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
cpuStrategy->timer = 0;
|
||||
} else if (cpuStrategy->timeBeforeThrow < cpuStrategy->timer) {
|
||||
|
|
@ -7400,33 +7361,56 @@ void cpu_use_item_strategy(s32 playerId) {
|
|||
if ((((!(SHELL_ACTOR(actor)->flags & 0x8000)) || (actor->type != ACTOR_GREEN_SHELL)) ||
|
||||
(SHELL_ACTOR(actor)->state != HELD_SHELL)) ||
|
||||
(playerId != SHELL_ACTOR(actor)->playerId)) {
|
||||
|
||||
// FAKE
|
||||
if (!(actor->flags & 0x8000)) {}
|
||||
if (actor->type != 7) {}
|
||||
if (actor->state != 0) {}
|
||||
if (actor->rot[0] != playerId) {}
|
||||
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
cpuStrategy->timer = 0;
|
||||
} else {
|
||||
SHELL_ACTOR(actor)->state = RELEASED_SHELL;
|
||||
// Check for players behind the CPU and throw shell backwards
|
||||
s16 highestHumanRank = gPlayerOne->currentRank;
|
||||
// Handle two players
|
||||
//! @warning Likely needs an update to support more than two human players
|
||||
if ((gPlayerTwo->type & PLAYER_HUMAN) && gPlayerTwo->currentRank > highestHumanRank) {
|
||||
highestHumanRank = gPlayerTwo->currentRank;
|
||||
}
|
||||
|
||||
if (player->currentRank < highestHumanRank) {
|
||||
// Code for backwards firing is the same for CPUs and humans
|
||||
Vec3f somePos2;
|
||||
Vec3f somePosVel;
|
||||
f32 var_f2;
|
||||
|
||||
var_f2 = 8.0f;
|
||||
if (player->speed > 8.0f) {
|
||||
var_f2 = player->speed * 1.2f;
|
||||
}
|
||||
somePosVel[0] = 0.0f;
|
||||
somePosVel[1] = 0.0f;
|
||||
somePosVel[2] = -var_f2;
|
||||
func_802B64C4(somePosVel, player->rotation[1] + player->unk_0C0);
|
||||
SHELL_ACTOR(actor)->velocity[0] = somePosVel[0];
|
||||
SHELL_ACTOR(actor)->velocity[1] = somePosVel[1];
|
||||
SHELL_ACTOR(actor)->velocity[2] = somePosVel[2];
|
||||
SHELL_ACTOR(actor)->state = MOVING_SHELL;
|
||||
func_800C9060(SHELL_ACTOR(actor)->playerId, SOUND_ARG_LOAD(0x19, 0x00, 0x80, 0x04));
|
||||
func_800C90F4(SHELL_ACTOR(actor)->playerId,
|
||||
(player->characterId * 0x10) + SOUND_ARG_LOAD(0x29, 0x00, 0x80, 0x00));
|
||||
add_green_shell_in_unexpired_actor_list(CM_FindActorIndex(SHELL_ACTOR(actor)));
|
||||
}
|
||||
else
|
||||
{
|
||||
SHELL_ACTOR(actor)->state = RELEASED_SHELL;
|
||||
}
|
||||
cpuStrategy->timer = 0;
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
}
|
||||
break;
|
||||
|
||||
case CPU_STRATEGY_ITEM_RED_SHELL:
|
||||
if (gNumActors < 80) {
|
||||
cpuStrategy->actorIndex = use_red_shell_item(player);
|
||||
if ((cpuStrategy->actorIndex >= 0) && (cpuStrategy->actorIndex < 100)) {
|
||||
cpuStrategy->branch = CPU_STRATEGY_HOLD_RED_SHELL;
|
||||
cpuStrategy->timer = 0;
|
||||
cpuStrategy->numItemUse += 1;
|
||||
cpuStrategy->timeBeforeThrow = (random_int(3) * 20) + 10;
|
||||
} else {
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
}
|
||||
cpuStrategy->actorIndex = use_red_shell_item(player);
|
||||
if (cpuStrategy->actorIndex >= 0) {
|
||||
cpuStrategy->branch = CPU_STRATEGY_HOLD_RED_SHELL;
|
||||
cpuStrategy->timer = 0;
|
||||
cpuStrategy->numItemUse += 1;
|
||||
cpuStrategy->timeBeforeThrow = (random_int(3) * 20) + 10;
|
||||
} else {
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
}
|
||||
|
|
@ -7437,13 +7421,6 @@ void cpu_use_item_strategy(s32 playerId) {
|
|||
if ((((!(SHELL_ACTOR(actor)->flags & 0x8000)) || (SHELL_ACTOR(actor)->type != ACTOR_RED_SHELL)) ||
|
||||
(SHELL_ACTOR(actor)->state != HELD_SHELL)) ||
|
||||
(playerId != SHELL_ACTOR(actor)->playerId)) {
|
||||
|
||||
// FAKE
|
||||
if (!(actor->flags & 0x8000)) {}
|
||||
if (actor->type != 8) {}
|
||||
if (actor->state != 0) {}
|
||||
if (actor->rot[0] != playerId) {}
|
||||
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
cpuStrategy->timer = 0;
|
||||
} else if (cpuStrategy->timeBeforeThrow < cpuStrategy->timer) {
|
||||
|
|
@ -7457,13 +7434,6 @@ void cpu_use_item_strategy(s32 playerId) {
|
|||
if ((((!(SHELL_ACTOR(actor)->flags & 0x8000)) || (SHELL_ACTOR(actor)->type != ACTOR_RED_SHELL)) ||
|
||||
(SHELL_ACTOR(actor)->state != HELD_SHELL)) ||
|
||||
(playerId != SHELL_ACTOR(actor)->playerId)) {
|
||||
|
||||
// FAKE
|
||||
if (!(actor->flags & 0x8000)) {}
|
||||
if (actor->type != 8) {}
|
||||
if (actor->state != 0) {}
|
||||
if (actor->rot[0] != playerId) {}
|
||||
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
cpuStrategy->timer = 0;
|
||||
} else {
|
||||
|
|
@ -7474,16 +7444,12 @@ void cpu_use_item_strategy(s32 playerId) {
|
|||
break;
|
||||
|
||||
case CPU_STRATEGY_ITEM_BANANA_BUNCH:
|
||||
if (gNumActors < 80) {
|
||||
cpuStrategy->actorIndex = use_banana_bunch_item(player);
|
||||
if ((cpuStrategy->actorIndex >= 0) && (cpuStrategy->actorIndex < 100)) {
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_INIT_BANANA_BUNCH;
|
||||
cpuStrategy->timer = 0;
|
||||
cpuStrategy->numItemUse += 1;
|
||||
cpuStrategy->timeBeforeThrow = (random_int(3) * 20) + 60;
|
||||
} else {
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
}
|
||||
cpuStrategy->actorIndex = use_banana_bunch_item(player);
|
||||
if (cpuStrategy->actorIndex >= 0) {
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_INIT_BANANA_BUNCH;
|
||||
cpuStrategy->timer = 0;
|
||||
cpuStrategy->numItemUse += 1;
|
||||
cpuStrategy->timeBeforeThrow = (random_int(3) * 20) + 60;
|
||||
} else {
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
}
|
||||
|
|
@ -7493,10 +7459,6 @@ void cpu_use_item_strategy(s32 playerId) {
|
|||
actor = GET_ACTOR(cpuStrategy->actorIndex);
|
||||
if (BANANA_BUNCH_ACTOR(actor)->state == 6) {
|
||||
|
||||
// FAKE
|
||||
if (BANANA_BUNCH_ACTOR(actor)->state != -1) {}
|
||||
if (BANANA_BUNCH_ACTOR(actor)->state == 6) {}
|
||||
|
||||
isValidBanana2 = false;
|
||||
|
||||
if (BANANA_BUNCH_ACTOR(actor)->bananaIndices[4] != (-1)) {
|
||||
|
|
@ -7578,7 +7540,7 @@ void cpu_use_item_strategy(s32 playerId) {
|
|||
|
||||
case CPU_STRATEGY_ITEM_FAKE_ITEM_BOX:
|
||||
cpuStrategy->actorIndex = use_fake_itembox_item(player);
|
||||
if ((cpuStrategy->actorIndex >= 0) && (cpuStrategy->actorIndex < 100)) {
|
||||
if (cpuStrategy->actorIndex >= 0) {
|
||||
cpuStrategy->branch = CPU_STRATEGY_HOLD_FAKE_ITEM_BOX;
|
||||
cpuStrategy->timer = 0;
|
||||
cpuStrategy->numItemUse += 1;
|
||||
|
|
@ -7595,32 +7557,18 @@ void cpu_use_item_strategy(s32 playerId) {
|
|||
(FAKE_ITEMBOX_ACTOR(actor)->state != 0)) ||
|
||||
(playerId != ((s32) FAKE_ITEMBOX_ACTOR(actor)->playerId))) {
|
||||
|
||||
// FAKE
|
||||
if (!(actor->flags & 0x8000)) {}
|
||||
if (actor->type != 13) {}
|
||||
if (actor->state != 0) {}
|
||||
if (actor->rot[0] != playerId) {}
|
||||
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
cpuStrategy->timer = 0;
|
||||
} else if (cpuStrategy->timeBeforeThrow < cpuStrategy->timer) {
|
||||
cpuStrategy->branch = CPU_STRATEGY_THROW_FAKE_ITEM_BOX;
|
||||
}
|
||||
break;
|
||||
|
||||
case CPU_STRATEGY_THROW_FAKE_ITEM_BOX:
|
||||
actor = GET_ACTOR(cpuStrategy->actorIndex);
|
||||
if ((((!(FAKE_ITEMBOX_ACTOR(actor)->flags & 0x8000)) ||
|
||||
(FAKE_ITEMBOX_ACTOR(actor)->type != ACTOR_FAKE_ITEM_BOX)) ||
|
||||
(FAKE_ITEMBOX_ACTOR(actor)->state != 0)) ||
|
||||
(playerId != ((s32) FAKE_ITEMBOX_ACTOR(actor)->playerId))) {
|
||||
|
||||
// FAKE
|
||||
if (!(FAKE_ITEMBOX_ACTOR(actor)->flags & 0x8000)) {}
|
||||
if (FAKE_ITEMBOX_ACTOR(actor)->type != 13) {}
|
||||
if (FAKE_ITEMBOX_ACTOR(actor)->state != 0) {}
|
||||
if (FAKE_ITEMBOX_ACTOR(actor)->rot[0] != playerId) {}
|
||||
|
||||
} else {
|
||||
func_802A1064((struct FakeItemBox*) actor);
|
||||
if (D_801631E0[playerId] == true) {
|
||||
|
|
@ -7718,23 +7666,19 @@ void cpu_use_item_strategy(s32 playerId) {
|
|||
}
|
||||
break;
|
||||
case CPU_STRATEGY_ITEM_BLUE_SPINY_SHELL:
|
||||
if (((s32) gNumActors) < 80) {
|
||||
cpuStrategy->actorIndex = use_blue_shell_item(player);
|
||||
if ((cpuStrategy->actorIndex >= 0) && (cpuStrategy->actorIndex < 0x64)) {
|
||||
cpuStrategy->branch = CPU_STRATEGY_HOLD_BLUE_SPINY_SHELL;
|
||||
cpuStrategy->timer = 0;
|
||||
cpuStrategy->numItemUse += 1;
|
||||
cpuStrategy->timeBeforeThrow = (random_int(3U) * 0x14) + 0xA;
|
||||
} else {
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
}
|
||||
cpuStrategy->actorIndex = use_blue_shell_item(player);
|
||||
if (cpuStrategy->actorIndex >= 0) {
|
||||
cpuStrategy->branch = CPU_STRATEGY_HOLD_BLUE_SPINY_SHELL;
|
||||
cpuStrategy->timer = 0;
|
||||
cpuStrategy->numItemUse += 1;
|
||||
cpuStrategy->timeBeforeThrow = (random_int(3) * 20) + 10;
|
||||
} else {
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
}
|
||||
break;
|
||||
case CPU_STRATEGY_HOLD_BLUE_SPINY_SHELL:
|
||||
actor = GET_ACTOR(cpuStrategy->actorIndex);
|
||||
if ((((!(SHELL_ACTOR(actor)->flags & 0x8000)) || (actor->type != ACTOR_BLUE_SPINY_SHELL)) ||
|
||||
if ((((!(SHELL_ACTOR(actor)->flags & 0x8000)) || (SHELL_ACTOR(actor)->type != ACTOR_BLUE_SPINY_SHELL)) ||
|
||||
(SHELL_ACTOR(actor)->state != HELD_SHELL)) ||
|
||||
(playerId != SHELL_ACTOR(actor)->playerId)) {
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
|
|
@ -7757,6 +7701,103 @@ void cpu_use_item_strategy(s32 playerId) {
|
|||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
}
|
||||
break;
|
||||
case CPU_STRATEGY_ITEM_TRIPLE_GREEN_SHELL:
|
||||
cpuStrategy->actorIndex = use_triple_shell_item(player, ACTOR_TRIPLE_GREEN_SHELL);
|
||||
if (cpuStrategy->actorIndex >= 0) {
|
||||
cpuStrategy->branch = CPU_STRATEGY_ORBIT_TRIPLE_GREEN_SHELL;
|
||||
cpuStrategy->timer = 0;
|
||||
cpuStrategy->numItemUse += 1;
|
||||
cpuStrategy->timeBeforeThrow = (random_int(10) * 20) + 50; // Delays firing until the shells have spawned
|
||||
} else {
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
}
|
||||
break;
|
||||
case CPU_STRATEGY_ORBIT_TRIPLE_GREEN_SHELL:
|
||||
actor = GET_ACTOR(cpuStrategy->actorIndex);
|
||||
if ((((!(SHELL_ACTOR(actor)->flags & 0x8000)) || (SHELL_ACTOR(actor)->type != ACTOR_TRIPLE_GREEN_SHELL))) ||
|
||||
(playerId != SHELL_ACTOR(actor)->playerId)) {
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
cpuStrategy->timer = 0;
|
||||
} else if (cpuStrategy->timeBeforeThrow < cpuStrategy->timer) {
|
||||
|
||||
TripleShellParent* parent = (TripleShellParent*) actor;
|
||||
if (parent->state == ORBIT_PLAYER) {
|
||||
cpuStrategy->branch = CPU_STRATEGY_THROW_TRIPLE_GREEN_SHELL;
|
||||
} else {
|
||||
cpuStrategy->timer = 0;
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CPU_STRATEGY_THROW_TRIPLE_GREEN_SHELL:
|
||||
actor = GET_ACTOR(cpuStrategy->actorIndex);
|
||||
if ((((!(SHELL_ACTOR(actor)->flags & 0x8000)) || (SHELL_ACTOR(actor)->type != ACTOR_TRIPLE_GREEN_SHELL))) ||
|
||||
(playerId != SHELL_ACTOR(actor)->playerId)) {
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
cpuStrategy->timer = 0;
|
||||
} else {
|
||||
cpuStrategy->timer = 0;
|
||||
TripleShellParent* parent = (TripleShellParent*) actor;
|
||||
if (parent->state == ORBIT_PLAYER && 0 < parent->shellsAvailable) {
|
||||
cpuStrategy->branch = CPU_STRATEGY_ORBIT_TRIPLE_GREEN_SHELL;
|
||||
parent->firePressed += 1.0f;
|
||||
cpuStrategy->timeBeforeThrow = (random_int(2) * 20);
|
||||
} else {
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CPU_STRATEGY_ITEM_TRIPLE_RED_SHELL:
|
||||
cpuStrategy->actorIndex = use_triple_shell_item(player, ACTOR_TRIPLE_RED_SHELL);
|
||||
if (cpuStrategy->actorIndex >= 0) {
|
||||
cpuStrategy->branch = CPU_STRATEGY_ORBIT_TRIPLE_RED_SHELL;
|
||||
cpuStrategy->timer = 0;
|
||||
cpuStrategy->numItemUse += 1;
|
||||
cpuStrategy->timeBeforeThrow = (random_int(3) * 20) + 50; // Delays firing until the shells have spawned
|
||||
} else {
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
}
|
||||
break;
|
||||
|
||||
case CPU_STRATEGY_ORBIT_TRIPLE_RED_SHELL:
|
||||
actor = GET_ACTOR(cpuStrategy->actorIndex);
|
||||
if ((((!(SHELL_ACTOR(actor)->flags & 0x8000)) || (SHELL_ACTOR(actor)->type != ACTOR_TRIPLE_RED_SHELL))) ||
|
||||
(playerId != SHELL_ACTOR(actor)->playerId)) {
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
cpuStrategy->timer = 0;
|
||||
} else if (cpuStrategy->timeBeforeThrow < cpuStrategy->timer) {
|
||||
|
||||
TripleShellParent* parent = (TripleShellParent*) actor;
|
||||
if (parent->state == ORBIT_PLAYER) {
|
||||
cpuStrategy->branch = CPU_STRATEGY_THROW_TRIPLE_RED_SHELL;
|
||||
} else {
|
||||
cpuStrategy->timer = 0;
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CPU_STRATEGY_THROW_TRIPLE_RED_SHELL:
|
||||
actor = GET_ACTOR(cpuStrategy->actorIndex);
|
||||
if ((((!(SHELL_ACTOR(actor)->flags & 0x8000)) || (SHELL_ACTOR(actor)->type != ACTOR_TRIPLE_RED_SHELL))) ||
|
||||
(playerId != SHELL_ACTOR(actor)->playerId)) {
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
cpuStrategy->timer = 0;
|
||||
} else {
|
||||
|
||||
cpuStrategy->timer = 0;
|
||||
TripleShellParent* parent = (TripleShellParent*) actor;
|
||||
if (parent->state == ORBIT_PLAYER && 0 < parent->shellsAvailable) {
|
||||
cpuStrategy->branch = CPU_STRATEGY_ORBIT_TRIPLE_RED_SHELL;
|
||||
parent->firePressed += 1.0f;
|
||||
cpuStrategy->timeBeforeThrow = (random_int(3) * 20) + 90; // Delay so that the CPU fires the next shell after the player has finished tumbling
|
||||
} else {
|
||||
cpuStrategy->branch = CPU_STRATEGY_WAIT_NEXT_ITEM;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ typedef struct {
|
|||
/* 0x08 */ s16 numDroppedBananaBunch;
|
||||
/* 0x0A */ s16 unk_0A;
|
||||
/* 0x0C */ s16 unk_0C;
|
||||
/* 0x0E */ s16 timeBeforeThrow;
|
||||
/* 0x0E */ s16 timeBeforeThrow; // Allows time for spawning the shells before they can be spawned
|
||||
} CpuItemStrategyData; // size = 0x10
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -89,6 +89,14 @@ enum CpuItemStrategyEnum {
|
|||
CPU_STRATEGY_ITEM_BLUE_SPINY_SHELL,
|
||||
CPU_STRATEGY_THROW_BLUE_SPINY_SHELL,
|
||||
CPU_STRATEGY_HOLD_BLUE_SPINY_SHELL,
|
||||
|
||||
CPU_STRATEGY_ITEM_TRIPLE_GREEN_SHELL,
|
||||
CPU_STRATEGY_ORBIT_TRIPLE_GREEN_SHELL,
|
||||
CPU_STRATEGY_THROW_TRIPLE_GREEN_SHELL,
|
||||
|
||||
CPU_STRATEGY_ITEM_TRIPLE_RED_SHELL,
|
||||
CPU_STRATEGY_ORBIT_TRIPLE_RED_SHELL,
|
||||
CPU_STRATEGY_THROW_TRIPLE_RED_SHELL,
|
||||
};
|
||||
|
||||
/* Function Prototypes */
|
||||
|
|
|
|||
|
|
@ -391,8 +391,8 @@ void update_actor_triple_shell(TripleShellParent* parent, s16 shellType) {
|
|||
parent->state = 3;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
parent->state = 4;
|
||||
case SHELL_COLLISION:
|
||||
parent->state = ORBIT_PLAYER;
|
||||
shell = (struct ShellActor*) GET_ACTOR((s16) parent->shellIndices[0]);
|
||||
shell->flags |= 0x4000;
|
||||
shell = (struct ShellActor*) GET_ACTOR((s16) parent->shellIndices[1]);
|
||||
|
|
@ -400,7 +400,7 @@ void update_actor_triple_shell(TripleShellParent* parent, s16 shellType) {
|
|||
shell = (struct ShellActor*) GET_ACTOR((s16) parent->shellIndices[2]);
|
||||
shell->flags |= 0x4000;
|
||||
break;
|
||||
case 4:
|
||||
case ORBIT_PLAYER:
|
||||
shellCount = 0;
|
||||
if (is_shell_exist(parent->shellIndices[0]) == 1) {
|
||||
shellCount = 1;
|
||||
|
|
@ -422,10 +422,14 @@ void update_actor_triple_shell(TripleShellParent* parent, s16 shellType) {
|
|||
break;
|
||||
}
|
||||
if ((gControllers[parent->playerId].buttonPressed & Z_TRIG) != 0) {
|
||||
parent->unk_08 += 1.0f;
|
||||
/**
|
||||
* Fires shell. Uses += 1.0f because this code is ran multiple times per frame.
|
||||
* A bool would be turned on and off again resulting in no change
|
||||
*/
|
||||
parent->firePressed += 1.0f;
|
||||
gControllers[parent->playerId].buttonPressed &= ~Z_TRIG;
|
||||
}
|
||||
if (parent->unk_08 > 0.0f) {
|
||||
if (parent->firePressed > 0.0f) { // Fires a shell and resets firePressed to zero
|
||||
if (parent->shellIndices[0] > 0.0f) {
|
||||
shell = (struct ShellActor*) GET_ACTOR((s16) parent->shellIndices[0]);
|
||||
if ((shell->rotAngle < 0x38E) || (shell->rotAngle >= -0x38D)) {
|
||||
|
|
@ -448,7 +452,7 @@ void update_actor_triple_shell(TripleShellParent* parent, s16 shellType) {
|
|||
}
|
||||
parent->shellIndices[0] = -1.0f;
|
||||
parent->shellsAvailable -= 1;
|
||||
parent->unk_08 -= 1.0f;
|
||||
parent->firePressed -= 1.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -474,7 +478,7 @@ void update_actor_triple_shell(TripleShellParent* parent, s16 shellType) {
|
|||
}
|
||||
parent->shellIndices[1] = -1.0f;
|
||||
parent->shellsAvailable -= 1;
|
||||
parent->unk_08 -= 1.0f;
|
||||
parent->firePressed -= 1.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -500,7 +504,7 @@ void update_actor_triple_shell(TripleShellParent* parent, s16 shellType) {
|
|||
}
|
||||
parent->shellIndices[2] = -1.0f;
|
||||
parent->shellsAvailable -= 1;
|
||||
parent->unk_08 -= 1.0f;
|
||||
parent->firePressed -= 1.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -548,7 +552,7 @@ s32 use_triple_shell_item(Player* player, s16 tripleShellType) {
|
|||
parent->rotAngle = -0x8000;
|
||||
parent->playerId = player - gPlayerOne;
|
||||
parent->shellsAvailable = 0;
|
||||
parent->unk_08 = 0.0f;
|
||||
parent->firePressed = 0.0f;
|
||||
return actorIndex;
|
||||
}
|
||||
|
||||
|
|
@ -681,7 +685,14 @@ s32 use_red_shell_item(Player* player) {
|
|||
// Interestingly blue shells start their life as a red shell,
|
||||
// and then just change the type from red to blue shell
|
||||
s32 use_blue_shell_item(Player* player) {
|
||||
GET_ACTOR(use_red_shell_item(player))->type = ACTOR_BLUE_SPINY_SHELL;
|
||||
// GET_ACTOR(use_red_shell_item(player))->type = ACTOR_BLUE_SPINY_SHELL; // Original code was just this line, without return statement! So I commented out.
|
||||
|
||||
// Fix the CPU strategy not properly releasing the blue shell. This function originally doesnt have a return value, so it returns UB.
|
||||
// The actor index range check on the cpu strategy fails because the actual actor index of blue shell was never returned by this function!
|
||||
s16 actorIndex = use_red_shell_item(player);
|
||||
GET_ACTOR(actorIndex)->type = ACTOR_BLUE_SPINY_SHELL;
|
||||
|
||||
return actorIndex;
|
||||
}
|
||||
|
||||
#include "actors/banana/update.inc.c"
|
||||
|
|
|
|||
Loading…
Reference in New Issue