Players turn into bubbles when they die
Player life counters are separate. When one player dies they lose a life and are turned into a bubble. If the other player pops it, they are alive again. If all players are bubbled, they get kicked out of the level. If the bubbled player ran out of lives, they can not come back to life until the level is over. Whenever a level change happens, everyone's life count is set to a minimum of two. No game overs. Took heavy inspiration from Kaze Emanuar
This commit is contained in:
parent
9427afb14b
commit
906ea3345e
|
@ -556,6 +556,15 @@ const BehaviorScript bhvBubbleMaybe[] = {
|
|||
DEACTIVATE(),
|
||||
};
|
||||
|
||||
const BehaviorScript bhvBubblePlayer[] = {
|
||||
BEGIN(OBJ_LIST_DEFAULT),
|
||||
ID(id_bhvBubblePlayer),
|
||||
OR_INT(oFlags, OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE),
|
||||
BEGIN_LOOP(),
|
||||
CALL_NATIVE(bhv_bubble_player_loop),
|
||||
END_LOOP(),
|
||||
};
|
||||
|
||||
const BehaviorScript bhvSmallWaterWave[] = {
|
||||
BEGIN(OBJ_LIST_UNIMPORTANT),
|
||||
ID(id_bhvSmallWaterWave),
|
||||
|
@ -6657,3 +6666,4 @@ const BehaviorScript bhvIntroScene[] = {
|
|||
CALL_NATIVE(bhv_intro_scene_loop),
|
||||
END_LOOP(),
|
||||
};
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ const BehaviorScript* gBehaviorTable[id_bhv_max_count] = {
|
|||
[id_bhvBetaChestLid] = bhvBetaChestLid,
|
||||
[id_bhvBubbleParticleSpawner] = bhvBubbleParticleSpawner,
|
||||
[id_bhvBubbleMaybe] = bhvBubbleMaybe,
|
||||
[id_bhvBubblePlayer] = bhvBubblePlayer,
|
||||
[id_bhvSmallWaterWave] = bhvSmallWaterWave,
|
||||
[id_bhvWaterAirBubble] = bhvWaterAirBubble,
|
||||
[id_bhvSmallParticle] = bhvSmallParticle,
|
||||
|
|
|
@ -20,6 +20,7 @@ extern const BehaviorScript bhvBetaChestBottom[];
|
|||
extern const BehaviorScript bhvBetaChestLid[];
|
||||
extern const BehaviorScript bhvBubbleParticleSpawner[];
|
||||
extern const BehaviorScript bhvBubbleMaybe[];
|
||||
extern const BehaviorScript bhvBubblePlayer[];
|
||||
extern const BehaviorScript bhvSmallWaterWave[];
|
||||
extern const BehaviorScript bhvSmallWaterWave398[];
|
||||
extern const BehaviorScript bhvWaterAirBubble[];
|
||||
|
|
|
@ -23,6 +23,7 @@ enum BehaviorId {
|
|||
id_bhvBetaChestLid,
|
||||
id_bhvBubbleParticleSpawner,
|
||||
id_bhvBubbleMaybe,
|
||||
id_bhvBubblePlayer,
|
||||
id_bhvSmallWaterWave,
|
||||
id_bhvWaterAirBubble,
|
||||
id_bhvSmallParticle,
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#define MODEL_LUIGI 0xE2 // luigi_geo
|
||||
#define MODEL_LUIGI2 0xE3 // luigi2_geo
|
||||
|
||||
#define MODEL_BUBBLE_PLAYER 0xE4 // water_bomb_geo
|
||||
|
||||
/* Various static level geometry, the geo layout differs but terrain object presets treat them the same.*/
|
||||
|
||||
#define MODEL_LEVEL_GEOMETRY_03 0x03
|
||||
|
|
|
@ -402,6 +402,7 @@
|
|||
#define ACT_GRABBED 0x00020370 // (0x170 | ACT_FLAG_STATIONARY | ACT_FLAG_INVULNERABLE)
|
||||
#define ACT_IN_CANNON 0x00001371 // (0x171 | ACT_FLAG_STATIONARY | ACT_FLAG_INTANGIBLE)
|
||||
#define ACT_TORNADO_TWIRLING 0x10020372 // (0x172 | ACT_FLAG_STATIONARY | ACT_FLAG_INVULNERABLE | ACT_FLAG_SWIMMING_OR_FLYING)
|
||||
#define ACT_BUBBLED (0x173 | ACT_FLAG_MOVING)
|
||||
|
||||
// group 0x180: object actions
|
||||
#define ACT_PUNCHING 0x00800380 // (0x180 | ACT_FLAG_STATIONARY | ACT_FLAG_ATTACKING)
|
||||
|
|
|
@ -368,6 +368,7 @@ struct MarioState
|
|||
/*0xC8*/ s16 currentRoom;
|
||||
/*0xCA*/ struct Object* heldByObj;
|
||||
/*????*/ u8 isSnoring;
|
||||
/*????*/ struct Object* bubbleObj;
|
||||
};
|
||||
|
||||
#define PLAY_MODE_NORMAL 0
|
||||
|
|
|
@ -69,6 +69,7 @@ const LevelScript level_main_scripts_entry[] = {
|
|||
LOAD_MODEL_FROM_GEO(MODEL_MARIO2, mario2_geo),
|
||||
LOAD_MODEL_FROM_GEO(MODEL_LUIGI, luigi_geo),
|
||||
LOAD_MODEL_FROM_GEO(MODEL_LUIGI2, luigi2_geo),
|
||||
LOAD_MODEL_FROM_GEO(MODEL_BUBBLE_PLAYER, water_bomb_geo),
|
||||
LOAD_MODEL_FROM_GEO(MODEL_SMOKE, smoke_geo),
|
||||
LOAD_MODEL_FROM_GEO(MODEL_SPARKLES, sparkles_geo),
|
||||
LOAD_MODEL_FROM_GEO(MODEL_BUBBLE, bubble_geo),
|
||||
|
|
|
@ -40,6 +40,7 @@ void bhv_beta_chest_bottom_loop(void);
|
|||
void bhv_beta_chest_lid_loop(void);
|
||||
void bhv_bubble_wave_init(void);
|
||||
void bhv_bubble_maybe_loop(void);
|
||||
void bhv_bubble_player_loop(void);
|
||||
void bhv_small_water_loop(void);
|
||||
void bhv_water_air_bubble_init(void);
|
||||
void bhv_water_air_bubble_loop(void);
|
||||
|
|
|
@ -21,6 +21,7 @@ void bhv_bbh_tilting_trap_platform_loop(void) {
|
|||
f32 z = 0;
|
||||
u8 playersTouched = 0;
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
if (gMarioStates[i].marioObj->platform == o) {
|
||||
x += gMarioStates[i].marioObj->oPosX;
|
||||
y += gMarioStates[i].marioObj->oPosY;
|
||||
|
|
|
@ -51,6 +51,7 @@ void bhv_boo_init(void) {
|
|||
static s32 boo_should_be_stopped(void) {
|
||||
if (cur_obj_has_behavior(bhvMerryGoRoundBigBoo) || cur_obj_has_behavior(bhvMerryGoRoundBoo)) {
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
if (gMarioStates[i].currentRoom == BBH_DYNAMIC_SURFACE_ROOM || gMarioStates[i].currentRoom == BBH_NEAR_MERRY_GO_ROUND_ROOM) { return FALSE; }
|
||||
}
|
||||
return TRUE;
|
||||
|
@ -80,6 +81,7 @@ static s32 boo_should_be_active(void) {
|
|||
|
||||
u8 inRoom = FALSE;
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
if (gMarioStates[i].currentRoom == o->oRoom || gMarioStates[i].currentRoom == 0) { inRoom = TRUE; }
|
||||
}
|
||||
|
||||
|
@ -614,6 +616,7 @@ static void big_boo_act_1(void) {
|
|||
if (cur_obj_has_behavior(bhvMerryGoRoundBigBoo)) {
|
||||
u8 inRoom = FALSE;
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
if (gMarioStates[i].currentRoom == BBH_DYNAMIC_SURFACE_ROOM || gMarioStates[i].currentRoom == BBH_NEAR_MERRY_GO_ROUND_ROOM) { inRoom = TRUE; }
|
||||
}
|
||||
|
||||
|
@ -924,6 +927,7 @@ void bhv_boo_in_castle_loop(void) {
|
|||
|
||||
u8 inRoom = FALSE;
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
if (marioState->floor == NULL) { continue; }
|
||||
inRoom = inRoom || (marioState->floor->room == 1);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
void bhv_floor_trap_in_castle_loop(void) {
|
||||
u8 onPlatform = FALSE;
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
onPlatform = onPlatform || (gMarioStates[i].marioObj->platform == o);
|
||||
}
|
||||
if (onPlatform)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
void common_anchor_mario_behavior(f32 sp28, f32 sp2C, s32 sp30) {
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
struct MarioState* marioState = &gMarioStates[i];
|
||||
struct Object* player = gMarioStates[i].marioObj;
|
||||
if (marioState->heldByObj != o->parentObj && marioState->heldByObj != o) { continue; }
|
||||
|
|
|
@ -83,8 +83,16 @@ void bhv_door_loop(void) {
|
|||
play_warp_door_open_noise();
|
||||
break;
|
||||
}
|
||||
if (o->oAction == 0)
|
||||
load_object_collision_model();
|
||||
|
||||
// make doors intangible when you're bubbled
|
||||
if (o->oAction == 0) {
|
||||
if (gCurrCourseNum != COURSE_NONE && gMarioStates[0].action == ACT_BUBBLED) {
|
||||
o->oIntangibleTimer = -1;
|
||||
} else {
|
||||
load_object_collision_model();
|
||||
o->oIntangibleTimer = 0;
|
||||
}
|
||||
}
|
||||
bhv_star_door_loop_2();
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ void elevator_act_0(void) {
|
|||
|
||||
u8 onPlatform = FALSE;
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
onPlatform = onPlatform || gMarioStates[i].marioObj->platform == o;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ void floating_platform_act_0(void) {
|
|||
f32 z = 0;
|
||||
u8 playersTouched = 0;
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
if (gMarioStates[i].marioObj->platform == o) {
|
||||
x += gMarioStates[i].marioObj->oPosX;
|
||||
z += gMarioStates[i].marioObj->oPosZ;
|
||||
|
|
|
@ -3,16 +3,21 @@
|
|||
struct MarioState* king_bobomb_nearest_mario_state() {
|
||||
struct MarioState* nearest = NULL;
|
||||
f32 nearestDist = 0;
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
float ydiff = (o->oPosY - gMarioStates[i].marioObj->oPosY);
|
||||
if (ydiff >= 1200) { continue; }
|
||||
u8 checkActive = TRUE;
|
||||
do {
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (checkActive && !is_player_active(&gMarioStates[i])) { continue; }
|
||||
float ydiff = (o->oPosY - gMarioStates[i].marioObj->oPosY);
|
||||
if (ydiff >= 1200) { continue; }
|
||||
|
||||
float dist = dist_between_objects(o, gMarioStates[i].marioObj);
|
||||
if (nearest == NULL || dist < nearestDist) {
|
||||
nearest = &gMarioStates[i];
|
||||
nearestDist = dist;
|
||||
float dist = dist_between_objects(o, gMarioStates[i].marioObj);
|
||||
if (nearest == NULL || dist < nearestDist) {
|
||||
nearest = &gMarioStates[i];
|
||||
nearestDist = dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
checkActive = FALSE;
|
||||
} while (nearest == NULL);
|
||||
|
||||
return nearest;
|
||||
}
|
||||
|
@ -62,6 +67,7 @@ void king_bobomb_act_0(void) {
|
|||
|
||||
int mario_is_far_below_object(f32 arg0) {
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
if (arg0 >= o->oPosY - gMarioStates[i].marioObj->oPosY) { return FALSE; }
|
||||
}
|
||||
return TRUE;
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
void bhv_1up_interact(void) {
|
||||
UNUSED s32 sp1C;
|
||||
|
||||
struct Object* player = nearest_player_to_object(o);
|
||||
if (obj_check_if_collided_with_object(o, player) == 1) {
|
||||
struct MarioState* marioState = nearest_mario_state_to_object(o);
|
||||
if (marioState->playerIndex == 0 && obj_check_if_collided_with_object(o, marioState->marioObj) == 1) {
|
||||
play_sound(SOUND_GENERAL_COLLECT_1UP, gDefaultSoundArgs);
|
||||
gMarioState->numLives++;
|
||||
marioState->numLives++;
|
||||
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -219,6 +219,7 @@ static void platform_on_track_act_move_along_track(void) {
|
|||
|
||||
u8 anyMarioOnPlatform = FALSE;
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
if (gMarioStates[i].marioObj->platform == o) { anyMarioOnPlatform = TRUE; }
|
||||
}
|
||||
|
||||
|
@ -248,6 +249,7 @@ static void platform_on_track_act_fall(void) {
|
|||
|
||||
u8 anyMarioOnPlatform = FALSE;
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
if (gMarioStates[i].marioObj->platform == o) { anyMarioOnPlatform = TRUE; }
|
||||
}
|
||||
|
||||
|
@ -270,6 +272,7 @@ static void platform_on_track_rock_ski_lift(void) {
|
|||
|
||||
struct Object* player = NULL;
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
if (gMarioStates[i].marioObj->platform != o) { continue; }
|
||||
player = gMarioStates[i].marioObj;
|
||||
break;
|
||||
|
@ -317,6 +320,7 @@ void bhv_platform_on_track_update(void) {
|
|||
|
||||
u8 anyMarioOnPlatform = FALSE;
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
if (gMarioStates[i].marioObj->platform == o) { anyMarioOnPlatform = TRUE; }
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ void bhv_purple_switch_loop(void) {
|
|||
|
||||
u8 anyPlayerOnPlatform = FALSE;
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
if (gMarioStates[i].marioObj->platform == o) {
|
||||
anyPlayerOnPlatform = TRUE;
|
||||
break;
|
||||
|
|
|
@ -128,6 +128,7 @@ static void racing_penguin_act_race(void) {
|
|||
|
||||
u8 isInAir = FALSE;
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
isInAir = isInAir || mario_is_in_air_action(&gMarioStates[i]);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ void bhv_recovery_heart_loop(void) {
|
|||
obj_set_hitbox(o, &sRecoveryHeartHitbox);
|
||||
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
if (obj_check_if_collided_with_object(o, gMarioStates[i].marioObj)) { collided = TRUE; }
|
||||
}
|
||||
|
||||
|
@ -40,6 +41,7 @@ void bhv_recovery_heart_loop(void) {
|
|||
|
||||
struct MarioState* nearestState = nearest_mario_state_to_object(o);
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
if (&gMarioStates[i] == nearestState || dist_between_objects(o, gMarioStates[i].marioObj) < 1000) {
|
||||
gMarioStates[i].healCounter += 4;
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ void bhv_seesaw_platform_update(void) {
|
|||
f32 z = 0;
|
||||
u8 playersTouched = 0;
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
if (gMarioStates[i].marioObj->platform == o) {
|
||||
x += gMarioStates[i].marioObj->oPosX;
|
||||
y += gMarioStates[i].marioObj->oPosY;
|
||||
|
|
|
@ -132,6 +132,7 @@ void bhv_tower_platform_group_loop(void) {
|
|||
|
||||
u8 anyPlayerInRange = FALSE;
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
if (gMarioStates[i].marioObj->oPosY > o->oHomeY - 1000.0f) { anyPlayerInRange = TRUE; }
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ void bhv_water_bomb_spawner_update(void) {
|
|||
struct Object* player = NULL;
|
||||
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
f32 latDist = lateral_dist_between_objects(o, gMarioStates[i].marioObj);
|
||||
if (latDist < latDistToMario) {
|
||||
latDistToMario = latDist;
|
||||
|
|
|
@ -70,6 +70,44 @@ void bhv_small_water_wave_loop(void) {
|
|||
obj_mark_for_deletion(o);
|
||||
}
|
||||
|
||||
void bhv_bubble_player_loop(void) {
|
||||
struct MarioState* marioState = &gMarioStates[o->heldByPlayerIndex];
|
||||
|
||||
// grab positions to find the mid-point
|
||||
f32* torsoPos = marioState->marioBodyState->torsoPos;
|
||||
f32* pos = marioState->pos;
|
||||
|
||||
// sanity check torsoPos
|
||||
if (marioState->marioObj->header.gfx.node.flags & GRAPH_RENDER_INVISIBLE) {
|
||||
torsoPos = marioState->pos;
|
||||
}
|
||||
|
||||
// set the position + offset
|
||||
o->oPosX = (torsoPos[0] + pos[0]) / 2;
|
||||
o->oPosY = (torsoPos[1] + pos[1]) / 2 + 30.0f;
|
||||
o->oPosZ = (torsoPos[2] + pos[2]) / 2;
|
||||
|
||||
// slowly rotate the bubble
|
||||
o->oFaceAnglePitch += 300;
|
||||
o->oFaceAngleYaw += 230;
|
||||
o->oFaceAngleRoll += 170;
|
||||
|
||||
// scale the bubble
|
||||
extern u32 gGlobalTimer;
|
||||
f32 scale = sins(gGlobalTimer * 800) * 0.1f + 1.4f;
|
||||
o->header.gfx.scale[0] = scale;
|
||||
o->header.gfx.scale[1] = sins(gGlobalTimer * 1500) * 0.2f + scale;
|
||||
o->header.gfx.scale[2] = scale;
|
||||
|
||||
// check if the bubble popped
|
||||
if (marioState->action != ACT_BUBBLED) {
|
||||
spawn_mist_particles();
|
||||
create_sound_spawner(SOUND_OBJ_DIVING_IN_WATER);
|
||||
marioState->bubbleObj = NULL;
|
||||
obj_mark_for_deletion(o);
|
||||
}
|
||||
}
|
||||
|
||||
void scale_bubble_sin(void) {
|
||||
o->header.gfx.scale[0] = sins(o->oWaterObjUnkF4) * 0.5 + 2.0;
|
||||
o->oWaterObjUnkF4 += o->oWaterObjUnkFC;
|
||||
|
|
|
@ -187,6 +187,7 @@ void whomp_on_ground(void) {
|
|||
if (o->oSubAction == 0) {
|
||||
u8 anyMarioOnPlatform = FALSE;
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
if (gMarioStates[i].marioObj->platform == o) { anyMarioOnPlatform = TRUE; }
|
||||
}
|
||||
if (anyMarioOnPlatform) {
|
||||
|
|
|
@ -1908,6 +1908,12 @@ void mario_process_interactions(struct MarioState *m) {
|
|||
|
||||
void check_death_barrier(struct MarioState *m) {
|
||||
if (m->pos[1] < m->floorHeight + 2048.0f) {
|
||||
if (gCurrCourseNum != COURSE_TOTWC) {
|
||||
m->pos[1] = m->floorHeight + 2048.0f;
|
||||
if (m->vel[1] < 0) { m->vel[1] = 0; }
|
||||
mario_set_bubbled(m);
|
||||
return;
|
||||
}
|
||||
if (level_trigger_warp(m, WARP_OP_WARP_FLOOR) == 20 && !(m->flags & MARIO_UNKNOWN_18)) {
|
||||
play_sound(SOUND_MARIO_WAAAOOOW, m->marioObj->header.gfx.cameraToObject);
|
||||
}
|
||||
|
|
|
@ -379,6 +379,14 @@ void init_mario_after_warp(void) {
|
|||
init_door_warp(&gPlayerSpawnInfos[i], sWarpDest.arg);
|
||||
}
|
||||
|
||||
// set to a minimum of two lives on level change
|
||||
if (sWarpDest.type == WARP_TYPE_CHANGE_LEVEL) {
|
||||
gMarioStates[i].numLives = max(gMarioStates[i].numLives, 2);
|
||||
gMarioStates[i].health = 0x880;
|
||||
gMarioStates[i].healCounter = 0;
|
||||
gMarioStates[i].hurtCounter = 0;
|
||||
}
|
||||
|
||||
if (sWarpDest.type == WARP_TYPE_CHANGE_LEVEL || sWarpDest.type == WARP_TYPE_CHANGE_AREA) {
|
||||
gPlayerSpawnInfos[i].areaIndex = sWarpDest.areaIdx;
|
||||
if (i == 0) { load_mario_area(); }
|
||||
|
@ -388,6 +396,11 @@ void init_mario_after_warp(void) {
|
|||
init_mario();
|
||||
set_mario_initial_action(gMarioState, marioSpawnType, sWarpDest.arg);
|
||||
|
||||
// enforce bubble on area change
|
||||
if (gMarioState->playerIndex == 0 && gMarioState->numLives == -1) {
|
||||
mario_set_bubbled(gMarioState);
|
||||
}
|
||||
|
||||
gMarioState->interactObj = spawnNode->object;
|
||||
gMarioState->usedObj = spawnNode->object;
|
||||
}
|
||||
|
@ -745,9 +758,12 @@ s16 level_trigger_warp(struct MarioState *m, s32 warpOp) {
|
|||
break;
|
||||
|
||||
case WARP_OP_DEATH:
|
||||
if (m->numLives == 0) {
|
||||
sDelayedWarpOp = WARP_OP_GAME_OVER;
|
||||
if (m->numLives < 2) {
|
||||
m->numLives = 2;
|
||||
}
|
||||
/*if (m->numLives == 0) {
|
||||
sDelayedWarpOp = WARP_OP_GAME_OVER;
|
||||
}*/
|
||||
sDelayedWarpTimer = 48;
|
||||
sSourceWarpNodeId = WARP_NODE_DEATH;
|
||||
play_transition(WARP_TRANSITION_FADE_INTO_BOWSER, 0x30, 0x00, 0x00, 0x00);
|
||||
|
@ -757,11 +773,11 @@ s16 level_trigger_warp(struct MarioState *m, s32 warpOp) {
|
|||
case WARP_OP_WARP_FLOOR:
|
||||
sSourceWarpNodeId = WARP_NODE_WARP_FLOOR;
|
||||
if (area_get_warp_node(sSourceWarpNodeId) == NULL) {
|
||||
if (m->numLives == 0) {
|
||||
/*if (m->numLives == 0) {
|
||||
sDelayedWarpOp = WARP_OP_GAME_OVER;
|
||||
} else {
|
||||
} else {*/
|
||||
sSourceWarpNodeId = WARP_NODE_DEATH;
|
||||
}
|
||||
//}
|
||||
}
|
||||
sDelayedWarpTimer = 20;
|
||||
play_transition(WARP_TRANSITION_FADE_INTO_CIRCLE, 0x14, 0x00, 0x00, 0x00);
|
||||
|
@ -937,7 +953,7 @@ void update_hud_values(void) {
|
|||
}
|
||||
#else
|
||||
if (gMarioState->numCoins > 999) {
|
||||
gMarioState->numLives = (s8) 999; //! Wrong variable
|
||||
gMarioState->numCoins = (s16) 999;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -387,6 +387,22 @@ void play_mario_sound(struct MarioState *m, s32 actionSound, s32 marioSound) {
|
|||
* ACTIONS *
|
||||
**************************************************/
|
||||
|
||||
void mario_set_bubbled(struct MarioState* m) {
|
||||
if (m->playerIndex != 0) { return; }
|
||||
if (m->action == ACT_BUBBLED) { return; }
|
||||
set_mario_action(m, ACT_BUBBLED, 0);
|
||||
if (m->numLives != -1) {
|
||||
m->numLives--;
|
||||
}
|
||||
m->healCounter = 0;
|
||||
m->hurtCounter = 31;
|
||||
gCamera->cutscene = 0;
|
||||
m->statusForCamera->action = m->action;
|
||||
m->statusForCamera->cameraEvent = 0;
|
||||
extern s16 gCutsceneTimer;
|
||||
gCutsceneTimer = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets Mario's other velocities from his forward speed.
|
||||
*/
|
||||
|
@ -1204,6 +1220,8 @@ s32 transition_submerged_to_walking(struct MarioState *m) {
|
|||
* non-submerged action. This also applies the water surface camera preset.
|
||||
*/
|
||||
s32 set_water_plunge_action(struct MarioState *m) {
|
||||
if (m->action == ACT_BUBBLED) { return FALSE; }
|
||||
|
||||
m->forwardVel = m->forwardVel / 4.0f;
|
||||
m->vel[1] = m->vel[1] / 2.0f;
|
||||
|
||||
|
@ -1828,7 +1846,9 @@ s32 execute_mario_action(UNUSED struct Object *o) {
|
|||
* End of cheat stuff
|
||||
*/
|
||||
if (gMarioState->action) {
|
||||
gMarioState->marioObj->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE;
|
||||
if (gMarioState->action != ACT_BUBBLED) {
|
||||
gMarioState->marioObj->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE;
|
||||
}
|
||||
mario_reset_bodystate(gMarioState);
|
||||
update_mario_inputs(gMarioState);
|
||||
mario_handle_special_floors(gMarioState);
|
||||
|
@ -1989,8 +2009,10 @@ void init_mario(void) {
|
|||
gMarioState->quicksandDepth = 0.0f;
|
||||
|
||||
gMarioState->heldObj = NULL;
|
||||
gMarioState->heldByObj = NULL;
|
||||
gMarioState->riddenObj = NULL;
|
||||
gMarioState->usedObj = NULL;
|
||||
gMarioState->bubbleObj = NULL;
|
||||
|
||||
gMarioState->waterLevel =
|
||||
find_water_level(gMarioSpawnInfo->startPos[0], gMarioSpawnInfo->startPos[2]);
|
||||
|
@ -2085,7 +2107,7 @@ void init_mario_from_save_file(void) {
|
|||
save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1);
|
||||
gMarioState->numKeys = 0;
|
||||
|
||||
gMarioState->numLives = 4;
|
||||
gMarioState->numLives = 3;
|
||||
gMarioState->health = 0x880;
|
||||
|
||||
gMarioState->prevNumStarsForDialog = gMarioState->numStars;
|
||||
|
|
|
@ -25,6 +25,7 @@ void play_mario_landing_sound_once(struct MarioState *m, u32 soundBits);
|
|||
void play_mario_heavy_landing_sound(struct MarioState *m, u32 soundBits);
|
||||
void play_mario_heavy_landing_sound_once(struct MarioState *m, u32 soundBits);
|
||||
void play_mario_sound(struct MarioState *m, s32 primarySoundBits, s32 scondarySoundBits);
|
||||
void mario_set_bubbled(struct MarioState* m);
|
||||
void mario_set_forward_vel(struct MarioState *m, f32 speed);
|
||||
s32 mario_get_floor_class(struct MarioState *m);
|
||||
u32 mario_get_terrain_sound_addend(struct MarioState *m);
|
||||
|
|
|
@ -1556,7 +1556,13 @@ s32 act_lava_boost(struct MarioState *m) {
|
|||
}
|
||||
|
||||
if (m->health < 0x100) {
|
||||
level_trigger_warp(m, WARP_OP_DEATH);
|
||||
if (m != &gMarioStates[0]) {
|
||||
// never kill remote marios
|
||||
m->health = 0x100;
|
||||
} else {
|
||||
m->health = 0xFF;
|
||||
return drop_and_set_mario_action(m, ACT_DEATH_ON_BACK, 0);
|
||||
}
|
||||
}
|
||||
|
||||
m->marioBodyState->eyeState = MARIO_EYES_DEAD;
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#include "level_table.h"
|
||||
#include "thread6.h"
|
||||
#include "object_helpers.h"
|
||||
#include "obj_behaviors.h"
|
||||
#include "level_update.h"
|
||||
|
||||
#define POLE_NONE 0
|
||||
#define POLE_TOUCHED_FLOOR 1
|
||||
|
@ -850,6 +852,94 @@ s32 act_tornado_twirling(struct MarioState *m) {
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
s32 act_bubbled(struct MarioState* m) {
|
||||
struct MarioState* targetMarioState = nearest_mario_state_to_object(m->marioObj);
|
||||
struct Object* target = targetMarioState->marioObj;
|
||||
int angleToPlayer = obj_angle_to_object(m->marioObj, target);
|
||||
int distanceToPlayer = dist_between_objects(m->marioObj, target);
|
||||
|
||||
// trigger warp if all are bubbled
|
||||
if (m->playerIndex == 0) {
|
||||
u8 allInBubble = TRUE;
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (gMarioStates[i].action != ACT_BUBBLED) {
|
||||
allInBubble = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allInBubble) {
|
||||
level_trigger_warp(m, WARP_OP_DEATH);
|
||||
return set_mario_action(m, ACT_DEATH_ON_BACK, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// create bubble
|
||||
if (m->bubbleObj == NULL) {
|
||||
//m->bubbleObj = spawn_object(m->marioObj, MODEL_BUBBLE, bhvBubblePlayer);
|
||||
m->bubbleObj = spawn_object(m->marioObj, MODEL_BUBBLE_PLAYER, bhvBubblePlayer);
|
||||
m->bubbleObj->heldByPlayerIndex = m->playerIndex;
|
||||
}
|
||||
|
||||
// force inactive state
|
||||
if (m->heldObj != NULL) { mario_drop_held_object(m); }
|
||||
m->heldByObj = NULL;
|
||||
m->marioObj->oIntangibleTimer = -1;
|
||||
m->squishTimer = 0;
|
||||
set_mario_animation(m, MARIO_ANIM_SLEEP_IDLE);
|
||||
|
||||
// force inputs
|
||||
m->faceAngle[0] = 0;
|
||||
m->faceAngle[1] = m->intendedYaw;
|
||||
m->forwardVel = m->intendedMag;
|
||||
if (m->input & INPUT_A_DOWN) { m->vel[1] += 3.0f; }
|
||||
if (m->input & INPUT_Z_DOWN) { m->vel[1] -= 3.0f; }
|
||||
|
||||
// set and smooth velocity
|
||||
Vec3f oldVel = { m->vel[0], m->vel[1], m->vel[2] };
|
||||
set_vel_from_pitch_and_yaw(m);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
m->vel[i] = (oldVel[i] * 0.9f + m->vel[i] * 0.1f);
|
||||
}
|
||||
|
||||
// move player
|
||||
switch (perform_air_step(m, 0)) {
|
||||
case AIR_STEP_LANDED:
|
||||
m->vel[1] += 10.0f;
|
||||
break;
|
||||
|
||||
case AIR_STEP_HIT_WALL:
|
||||
case AIR_STEP_HIT_LAVA_WALL:
|
||||
m->vel[0] *= -0.99f;
|
||||
m->vel[2] *= -0.99f;
|
||||
break;
|
||||
}
|
||||
|
||||
// always look toward target
|
||||
m->faceAngle[1] = angleToPlayer;
|
||||
m->marioObj->header.gfx.angle[1] = angleToPlayer;
|
||||
|
||||
// make invisible on -1 lives
|
||||
if (m->numLives == -1) {
|
||||
m->marioObj->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE;
|
||||
}
|
||||
|
||||
// pop bubble
|
||||
if (m->playerIndex == 0 && distanceToPlayer < 200 && is_player_active(targetMarioState) && m->numLives != -1) {
|
||||
m->hurtCounter = 0;
|
||||
m->healCounter = 31;
|
||||
m->health = 0x100;
|
||||
m->marioObj->oIntangibleTimer = 0;
|
||||
m->peakHeight = m->pos[1];
|
||||
m->vel[0] = 0;
|
||||
m->vel[1] = 0;
|
||||
m->vel[2] = 0;
|
||||
m->marioObj->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE;
|
||||
return set_mario_action(m, ACT_IDLE, 0);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s32 check_common_automatic_cancels(struct MarioState *m) {
|
||||
if (m->pos[1] < m->waterLevel - 100) {
|
||||
return set_water_plunge_action(m);
|
||||
|
@ -886,6 +976,7 @@ s32 mario_execute_automatic_action(struct MarioState *m) {
|
|||
case ACT_GRABBED: cancel = act_grabbed(m); break;
|
||||
case ACT_IN_CANNON: cancel = act_in_cannon(m); break;
|
||||
case ACT_TORNADO_TWIRLING: cancel = act_tornado_twirling(m); break;
|
||||
case ACT_BUBBLED: cancel = act_bubbled(m); break;
|
||||
}
|
||||
/* clang-format on */
|
||||
|
||||
|
|
|
@ -730,7 +730,8 @@ s32 act_fall_after_star_grab(struct MarioState *m) {
|
|||
s32 common_death_handler(struct MarioState *m, s32 animation, s32 frameToDeathWarp) {
|
||||
s32 animFrame = set_mario_animation(m, animation);
|
||||
if (animFrame == frameToDeathWarp) {
|
||||
level_trigger_warp(m, WARP_OP_DEATH);
|
||||
//level_trigger_warp(m, WARP_OP_DEATH);
|
||||
mario_set_bubbled(m);
|
||||
}
|
||||
m->marioBodyState->eyeState = MARIO_EYES_DEAD;
|
||||
stop_and_set_height_to_floor(m);
|
||||
|
@ -810,7 +811,8 @@ s32 act_eaten_by_bubba(struct MarioState *m) {
|
|||
}
|
||||
|
||||
if (m->actionTimer++ == 60) {
|
||||
level_trigger_warp(m, WARP_OP_DEATH);
|
||||
//level_trigger_warp(m, WARP_OP_DEATH);
|
||||
mario_set_bubbled(m);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -1230,7 +1232,7 @@ s32 act_death_exit(struct MarioState *m) {
|
|||
play_sound(SOUND_MARIO_OOOF2, m->marioObj->header.gfx.cameraToObject);
|
||||
#endif
|
||||
queue_rumble_data_mario(m, 5, 80);
|
||||
m->numLives--;
|
||||
//m->numLives--;
|
||||
// restore 7.75 units of health
|
||||
m->healCounter = 31;
|
||||
}
|
||||
|
@ -1246,7 +1248,7 @@ s32 act_unused_death_exit(struct MarioState *m) {
|
|||
#else
|
||||
play_sound(SOUND_MARIO_OOOF2, m->marioObj->header.gfx.cameraToObject);
|
||||
#endif
|
||||
m->numLives--;
|
||||
//m->numLives--;
|
||||
// restore 7.75 units of health
|
||||
m->healCounter = 31;
|
||||
}
|
||||
|
@ -1263,7 +1265,7 @@ s32 act_falling_death_exit(struct MarioState *m) {
|
|||
play_sound(SOUND_MARIO_OOOF2, m->marioObj->header.gfx.cameraToObject);
|
||||
#endif
|
||||
queue_rumble_data_mario(m, 5, 80);
|
||||
m->numLives--;
|
||||
//m->numLives--;
|
||||
// restore 7.75 units of health
|
||||
m->healCounter = 31;
|
||||
}
|
||||
|
@ -1308,7 +1310,7 @@ s32 act_special_death_exit(struct MarioState *m) {
|
|||
|
||||
if (launch_mario_until_land(m, ACT_HARD_BACKWARD_GROUND_KB, MARIO_ANIM_BACKWARD_AIR_KB, -24.0f)) {
|
||||
queue_rumble_data_mario(m, 5, 80);
|
||||
m->numLives--;
|
||||
//m->numLives--;
|
||||
m->healCounter = 31;
|
||||
}
|
||||
// show Mario
|
||||
|
@ -1606,9 +1608,11 @@ s32 act_squished(struct MarioState *m) {
|
|||
if (m->actionTimer >= 15) {
|
||||
// 1 unit of health
|
||||
if (m->health < 0x0100) {
|
||||
level_trigger_warp(m, WARP_OP_DEATH);
|
||||
//level_trigger_warp(m, WARP_OP_DEATH);
|
||||
// woosh, he's gone!
|
||||
set_mario_action(m, ACT_DISAPPEARED, 0);
|
||||
//set_mario_action(m, ACT_DISAPPEARED, 0);
|
||||
drop_and_set_mario_action(m, ACT_DEATH_ON_BACK, 0);
|
||||
m->squishTimer = 0;
|
||||
} else if (m->hurtCounter == 0) {
|
||||
// un-squish animation
|
||||
m->squishTimer = 30;
|
||||
|
@ -1654,9 +1658,10 @@ s32 act_squished(struct MarioState *m) {
|
|||
}
|
||||
|
||||
m->hurtCounter = 0;
|
||||
level_trigger_warp(m, WARP_OP_DEATH);
|
||||
//level_trigger_warp(m, WARP_OP_DEATH);
|
||||
// woosh, he's gone!
|
||||
set_mario_action(m, ACT_DISAPPEARED, 0);
|
||||
//set_mario_action(m, ACT_DISAPPEARED, 0);
|
||||
mario_set_bubbled(m);
|
||||
}
|
||||
stop_and_set_height_to_floor(m);
|
||||
set_mario_animation(m, MARIO_ANIM_A_POSE);
|
||||
|
|
|
@ -922,7 +922,8 @@ static s32 act_drowning(struct MarioState *m) {
|
|||
set_mario_animation(m, MARIO_ANIM_DROWNING_PART2);
|
||||
m->marioBodyState->eyeState = MARIO_EYES_DEAD;
|
||||
if (m->marioObj->header.gfx.unk38.animFrame == 30) {
|
||||
level_trigger_warp(m, WARP_OP_DEATH);
|
||||
//level_trigger_warp(m, WARP_OP_DEATH);
|
||||
mario_set_bubbled(m);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -942,7 +943,8 @@ static s32 act_water_death(struct MarioState *m) {
|
|||
|
||||
set_mario_animation(m, MARIO_ANIM_WATER_DYING);
|
||||
if (set_mario_animation(m, MARIO_ANIM_WATER_DYING) == 35) {
|
||||
level_trigger_warp(m, WARP_OP_DEATH);
|
||||
//level_trigger_warp(m, WARP_OP_DEATH);
|
||||
mario_set_bubbled(m);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
@ -1049,7 +1051,8 @@ static s32 act_caught_in_whirlpool(struct MarioState *m) {
|
|||
if ((marioObj->oMarioWhirlpoolPosY += m->vel[1]) < 0.0f) {
|
||||
marioObj->oMarioWhirlpoolPosY = 0.0f;
|
||||
if (distance < 16.1f && m->actionTimer++ == 16) {
|
||||
level_trigger_warp(m, WARP_OP_DEATH);
|
||||
//level_trigger_warp(m, WARP_OP_DEATH);
|
||||
mario_set_bubbled(m);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -644,7 +644,7 @@ s32 perform_air_step(struct MarioState *m, u32 stepArg) {
|
|||
|
||||
m->terrainSoundAddend = mario_get_terrain_sound_addend(m);
|
||||
|
||||
if (m->action != ACT_FLYING) {
|
||||
if (m->action != ACT_FLYING && m->action != ACT_BUBBLED) {
|
||||
apply_gravity(m);
|
||||
}
|
||||
apply_vertical_wind(m);
|
||||
|
|
|
@ -498,6 +498,7 @@ void obj_move_xyz_using_fvel_and_yaw(struct Object *obj) {
|
|||
*/
|
||||
s32 is_point_within_radius_of_mario(f32 x, f32 y, f32 z, s32 dist) {
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
struct Object* player = gMarioStates[i].marioObj;
|
||||
f32 mGfxX = player->header.gfx.pos[0];
|
||||
f32 mGfxY = player->header.gfx.pos[1];
|
||||
|
@ -512,19 +513,30 @@ s32 is_point_within_radius_of_mario(f32 x, f32 y, f32 z, s32 dist) {
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
u8 is_player_active(struct MarioState* m) {
|
||||
if (m->action == ACT_BUBBLED) { return FALSE; }
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns closest MarioState
|
||||
*/
|
||||
struct MarioState* nearest_mario_state_to_object(struct Object *obj) {
|
||||
struct MarioState* nearest = NULL;
|
||||
f32 nearestDist = 0;
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
float dist = dist_between_objects(obj, gMarioStates[i].marioObj);
|
||||
if (nearest == NULL || dist < nearestDist) {
|
||||
nearest = &gMarioStates[i];
|
||||
nearestDist = dist;
|
||||
u8 checkActive = TRUE;
|
||||
do {
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (gMarioStates[i].marioObj == obj) { continue; }
|
||||
if (checkActive && !is_player_active(&gMarioStates[i])) { continue; }
|
||||
float dist = dist_between_objects(obj, gMarioStates[i].marioObj);
|
||||
if (nearest == NULL || dist < nearestDist) {
|
||||
nearest = &gMarioStates[i];
|
||||
nearestDist = dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
checkActive = FALSE;
|
||||
} while (nearest == NULL);
|
||||
|
||||
return nearest;
|
||||
}
|
||||
|
|
|
@ -161,6 +161,7 @@ void bhv_free_bowling_ball_loop(void); /* likely unused */
|
|||
void bhv_rr_cruiser_wing_init(void);
|
||||
void bhv_rr_cruiser_wing_loop(void);
|
||||
struct Object* spawn_default_star(f32 sp20, f32 sp24, f32 sp28);
|
||||
u8 is_player_active(struct MarioState* m);
|
||||
struct MarioState* nearest_mario_state_to_object(struct Object* obj);
|
||||
struct Object* nearest_player_to_object(struct Object* obj);
|
||||
#endif // OBJ_BEHAVIORS_H
|
||||
|
|
|
@ -2264,6 +2264,7 @@ s32 cur_obj_wait_then_blink(s32 timeUntilBlinking, s32 numBlinks) {
|
|||
|
||||
s32 cur_obj_is_mario_ground_pounding_platform(void) {
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
if (gMarioStates[i].marioObj->platform == o) {
|
||||
if (gMarioStates[i].action == ACT_GROUND_POUND_LAND) {
|
||||
return TRUE;
|
||||
|
@ -2401,6 +2402,7 @@ s32 cur_obj_is_mario_on_platform(void) {
|
|||
|
||||
s32 cur_obj_is_any_player_on_platform(void) {
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
if (gMarioStates[i].marioObj->platform == o) {
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -2457,6 +2459,7 @@ s32 bit_shift_left(s32 a0) {
|
|||
|
||||
s32 cur_obj_mario_far_away(void) {
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
struct Object* player = gMarioStates[i].marioObj;
|
||||
f32 dx = o->oHomeX - player->oPosX;
|
||||
f32 dy = o->oHomeY - player->oPosY;
|
||||
|
@ -2594,6 +2597,7 @@ void cur_obj_if_hit_wall_bounce_away(void) {
|
|||
|
||||
s32 cur_obj_hide_if_mario_far_away_y(f32 distY) {
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
if (absf(o->oPosY - gMarioStates[i].marioObj->oPosY) < distY) {
|
||||
cur_obj_unhide();
|
||||
return FALSE;
|
||||
|
|
Loading…
Reference in New Issue