Enemy hat fixes (#83)

* Ukiki now steals Mario/Luigi hat correctly
* Klepto now steals Mario/Luigi hat correctly
* Mr. Blizzard now knocks off Mario/Luigi hat correctly
* Fwoosh now knocks off Mario/Luigi hat correctly

Co-authored-by: anzz1 <>
This commit is contained in:
anzz1 2020-10-16 13:03:25 +03:00 committed by GitHub
parent 7971dbfa3f
commit bc7ec31c02
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 93 additions and 24 deletions

View file

@ -54,6 +54,9 @@ UNUSED static const u64 binid_11 = 11;
#include "mario_cap/model.inc.c"
UNUSED static const u64 binid_12 = 12;
// luigi_cap
#include "luigi_cap/model.inc.c"
#include "power_meter/model.inc.c"
UNUSED static const u64 binid_13 = 13;
@ -82,4 +85,4 @@ UNUSED static const u64 binid_20 = 20;
UNUSED static const u64 binid_21 = 21;
#include "tree/model.inc.c"
UNUSED static const u64 binid_22 = 22;
UNUSED static const u64 binid_22 = 22;

View file

@ -172,6 +172,27 @@ extern const Gfx mario_cap_seg3_dl_03023108[];
extern const Gfx mario_cap_seg3_dl_03023160[];
extern const Gfx mario_cap_seg3_dl_03023298[];
// luigi_cap
extern const GeoLayout luigis_cap_geo[];
//extern const GeoLayout luigis_metal_cap_geo[];
//extern const GeoLayout luigis_wing_cap_geo[];
//extern const GeoLayout luigis_winged_metal_cap_geo[];
extern const Gfx luigi_cap_seg3_dl_03022B30[];
extern const Gfx luigi_cap_seg3_dl_03022B68[];
extern const Gfx luigi_cap_seg3_dl_03022CC8[];
extern const Gfx luigi_cap_seg3_dl_03022D10[];
extern const Gfx luigi_cap_seg3_dl_03022E78[];
extern const Gfx luigi_cap_seg3_dl_03022EA8[];
extern const Gfx luigi_cap_seg3_dl_03022ED8[];
extern const Gfx luigi_cap_seg3_dl_03022F20[];
extern const Gfx luigi_cap_seg3_dl_03022F48[];
extern const Gfx luigi_cap_seg3_dl_03022FF8[];
extern const Gfx luigi_cap_seg3_dl_030230B0[];
extern const Gfx luigi_cap_seg3_dl_03023108[];
extern const Gfx luigi_cap_seg3_dl_03023160[];
extern const Gfx luigi_cap_seg3_dl_03023298[];
// mist
extern const GeoLayout mist_geo[];
extern const GeoLayout white_puff_geo[];

View file

@ -17,6 +17,7 @@
#include "blue_fish/geo.inc.c"
#include "leaves/geo.inc.c"
#include "mario_cap/geo.inc.c"
#include "luigi_cap/geo.inc.c" // custom luigi_cap
#include "number/geo.inc.c"
#include "mushroom_1up/geo.inc.c"
#include "star/geo.inc.c"

View file

@ -24,7 +24,7 @@ const GeoLayout klepto_geo[] = {
GEO_ANIMATED_PART(LAYER_OPAQUE, 0, 0, 0, NULL),
GEO_ANIMATED_PART(LAYER_OPAQUE, 0, 0, 0, NULL),
GEO_OPEN_NODE(),
GEO_SWITCH_CASE(4, geo_switch_anim_state),
GEO_SWITCH_CASE(5, geo_switch_anim_state),
GEO_OPEN_NODE(),
GEO_NODE_START(),
GEO_NODE_START(),
@ -53,6 +53,14 @@ const GeoLayout klepto_geo[] = {
GEO_TRANSLATE_ROTATE_WITH_DL(LAYER_OPAQUE, 0, 100, 0, 180, 270, 0, transparent_star_seg3_dl_0302C620),
GEO_CLOSE_NODE(),
GEO_CLOSE_NODE(),
GEO_NODE_START(),
GEO_OPEN_NODE(),
GEO_SCALE(0x00, 16384),
GEO_OPEN_NODE(),
GEO_ASM(0, geo_offset_klepto_held_object),
GEO_TRANSLATE_ROTATE_WITH_DL(LAYER_OPAQUE, 0, 100, 0, 180, 270, 0, luigi_cap_seg3_dl_03022F48),
GEO_CLOSE_NODE(),
GEO_CLOSE_NODE(),
GEO_CLOSE_NODE(),
GEO_CLOSE_NODE(),
GEO_CLOSE_NODE(),

View file

@ -8,7 +8,7 @@ const GeoLayout ukiki_geo[] = {
GEO_OPEN_NODE(),
GEO_ANIMATED_PART(LAYER_OPAQUE, 0, 99, -11, NULL),
GEO_OPEN_NODE(),
GEO_SWITCH_CASE(4, geo_switch_anim_state),
GEO_SWITCH_CASE(5, geo_switch_anim_state),
GEO_OPEN_NODE(),
GEO_NODE_START(),
GEO_OPEN_NODE(),
@ -32,6 +32,13 @@ const GeoLayout ukiki_geo[] = {
GEO_TRANSLATE_ROTATE_WITH_DL(LAYER_OPAQUE, 100, 0, 0, -90, -90, 0, mario_cap_seg3_dl_03022F48),
GEO_CLOSE_NODE(),
GEO_CLOSE_NODE(),
GEO_NODE_START(),
GEO_OPEN_NODE(),
GEO_ANIMATED_PART(LAYER_OPAQUE, 0, 0, 0, ukiki_seg5_dl_0500B2E8),
GEO_OPEN_NODE(),
GEO_TRANSLATE_ROTATE_WITH_DL(LAYER_OPAQUE, 100, 0, 0, -90, -90, 0, luigi_cap_seg3_dl_03022F48),
GEO_CLOSE_NODE(),
GEO_CLOSE_NODE(),
GEO_CLOSE_NODE(),
GEO_CLOSE_NODE(),
GEO_ANIMATED_PART(LAYER_OPAQUE, 71, 69, -9, NULL),

View file

@ -25,7 +25,11 @@
#define MODEL_MARIO 0x01 // mario_geo
#define MODEL_LUIGI 0xE2 // luigi_geo
#define MODEL_BUBBLE_PLAYER 0xE4 // water_bomb_geo
#define MODEL_BUBBLE_PLAYER 0xE3 // water_bomb_geo
/* Additional custom models */
#define MODEL_LUIGIS_CAP 0xE4 // luigis_cap_geo
/* Various static level geometry, the geo layout differs but terrain object presets treat them the same.*/

View file

@ -660,9 +660,11 @@
#define UKIKI_ANIM_HELD 12
/* oAnimState */
#define UKIKI_ANIM_STATE_DEFAULT 0
#define UKIKI_ANIM_STATE_EYE_CLOSED 1
#define UKIKI_ANIM_STATE_HAT_ON 2
#define UKIKI_ANIM_STATE_DEFAULT 0
#define UKIKI_ANIM_STATE_EYE_CLOSED 1 // unused
#define UKIKI_ANIM_STATE_HAT_ON 2
#define UKIKI_ANIM_STATE_UNUSED 3 // unused, HAT_ON+EYE_CLOSED
#define UKIKI_ANIM_STATE_HAT_ON_LUIGI 4
/* oUkikiHasHat */
#define UKIKI_HAT_ON 1
@ -883,6 +885,7 @@
#define KLEPTO_ANIM_STATE_HOLDING_NOTHING 0
#define KLEPTO_ANIM_STATE_HOLDING_CAP 1
#define KLEPTO_ANIM_STATE_HOLDING_STAR 2
#define KLEPTO_ANIM_STATE_HOLDING_CAP_LUIGI 4
/* Bird */
/* oAction */

View file

@ -66,7 +66,7 @@ const LevelScript level_main_scripts_entry[] = {
LOAD_RAW( /*seg*/ 0x13, _behaviorSegmentRomStart, _behaviorSegmentRomEnd),
ALLOC_LEVEL_POOL(),
LOAD_MODEL_FROM_GEO(MODEL_MARIO, mario_geo),
LOAD_MODEL_FROM_GEO(MODEL_LUIGI, luigi_geo),
LOAD_MODEL_FROM_GEO(MODEL_LUIGI, luigi_geo), // custom luigi
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),
@ -104,6 +104,7 @@ const LevelScript level_main_scripts_entry[] = {
LOAD_MODEL_FROM_GEO(MODEL_MARIOS_WING_CAP, marios_wing_cap_geo),
LOAD_MODEL_FROM_GEO(MODEL_MARIOS_CAP, marios_cap_geo),
LOAD_MODEL_FROM_GEO(MODEL_MARIOS_CAP, marios_cap_geo), // repeated
LOAD_MODEL_FROM_GEO(MODEL_LUIGIS_CAP, luigis_cap_geo), // custom luigi_cap
LOAD_MODEL_FROM_GEO(MODEL_BOWSER_KEY_CUTSCENE, bowser_key_cutscene_geo),
LOAD_MODEL_FROM_GEO(MODEL_BOWSER_KEY, bowser_key_geo),
LOAD_MODEL_FROM_GEO(MODEL_RED_FLAME_SHADOW, red_flame_shadow_geo),

View file

@ -96,11 +96,12 @@ void bhv_klepto_init(void) {
o->oKleptoStartPosY = o->oPosY;
o->oKleptoStartPosZ = o->oPosZ;
if (save_file_get_flags() & SAVE_FLAG_CAP_ON_KLEPTO) {
o->oAnimState = KLEPTO_ANIM_STATE_HOLDING_CAP;
} else {
// skip hat save flags
//if (save_file_get_flags() & SAVE_FLAG_CAP_ON_KLEPTO) {
// o->oAnimState = KLEPTO_ANIM_STATE_HOLDING_CAP;
//} else {
o->oAction = KLEPTO_ACT_WAIT_FOR_MARIO;
}
//}
}
struct SyncObject* so = network_init_object(o, 4000.0f);
@ -290,7 +291,12 @@ static void klepto_act_dive_at_mario(void) {
&& !(marioState->action & (ACT_FLAG_SHORT_HITBOX | ACT_FLAG_BUTT_OR_STOMACH_SLIDE))
&& distanceToPlayer < 200.0f && dy > 50.0f && dy < 90.0f) {
if (network_owns_object(o) && mario_lose_cap_to_enemy(marioState, 1)) {
o->oAnimState = KLEPTO_ANIM_STATE_HOLDING_CAP;
u8 isLuigi = (gNetworkType == NT_SERVER) ? (marioState->playerIndex != 0) : (marioState->playerIndex == 0);
if (isLuigi) {
o->oAnimState = KLEPTO_ANIM_STATE_HOLDING_CAP_LUIGI;
} else {
o->oAnimState = KLEPTO_ANIM_STATE_HOLDING_CAP;
}
network_send_object(o);
}
}
@ -413,12 +419,14 @@ void bhv_klepto_update(void) {
if (obj_handle_attacks(&sKleptoHitbox, o->oAction, sKleptoAttackHandlers)) {
cur_obj_play_sound_2(SOUND_OBJ_KLEPTO2);
if (network_owns_object(o) && o->oAnimState == KLEPTO_ANIM_STATE_HOLDING_CAP) {
if (network_owns_object(o) && (o->oAnimState == KLEPTO_ANIM_STATE_HOLDING_CAP || o->oAnimState == KLEPTO_ANIM_STATE_HOLDING_CAP_LUIGI)) {
save_file_clear_flags(SAVE_FLAG_CAP_ON_KLEPTO);
struct Object* cap = spawn_object(o, MODEL_MARIOS_CAP, bhvNormalCap);
u8 capModel = (o->oAnimState == KLEPTO_ANIM_STATE_HOLDING_CAP) ? MODEL_MARIOS_CAP : MODEL_LUIGIS_CAP;
struct Object* cap = spawn_object(o, capModel, bhvNormalCap);
struct Object* spawn_objects[] = { cap };
u32 models[] = { MODEL_MARIOS_CAP };
u32 models[] = { capModel };
network_send_spawn_objects(spawn_objects, models, 1);
} else if (o->oAnimState == KLEPTO_ANIM_STATE_HOLDING_STAR) {

View file

@ -638,12 +638,13 @@ void hat_ukiki_held_loop(void) {
* Initializatation for ukiki, determines if it has Mario's hat.
*/
void bhv_ukiki_init(void) {
if (o->oBehParams2ndByte == UKIKI_HAT) {
if (save_file_get_flags() & SAVE_FLAG_CAP_ON_UKIKI) {
o->oUkikiTextState = UKIKI_TEXT_HAS_HAT;
o->oUkikiHasHat |= UKIKI_HAT_ON;
}
}
// skip hat save flags
//if (o->oBehParams2ndByte == UKIKI_HAT) {
// if (save_file_get_flags() & SAVE_FLAG_CAP_ON_UKIKI) {
// o->oUkikiTextState = UKIKI_TEXT_HAS_HAT;
// o->oUkikiHasHat |= UKIKI_HAT_ON;
// }
//}
network_init_object(o, 4000.0f);
network_init_object_field(o, &o->oUkikiTauntCounter);
@ -684,7 +685,18 @@ void bhv_ukiki_loop(void) {
}
if (o->oUkikiHasHat & UKIKI_HAT_ON) {
o->oAnimState = UKIKI_ANIM_STATE_HAT_ON;
for (int i = 0; i < MAX_PLAYERS; i++) {
if (!is_player_active(&gMarioStates[i])) { continue; }
if (!does_mario_have_hat(&gMarioStates[i])) {
u8 isLuigi = (gNetworkType == NT_SERVER) ? (gMarioStates[i].playerIndex != 0) : (gMarioStates[i].playerIndex == 0);
if(isLuigi) {
o->oAnimState = UKIKI_ANIM_STATE_HAT_ON_LUIGI;
} else {
o->oAnimState = UKIKI_ANIM_STATE_HAT_ON;
}
break;
}
}
} else {
o->oAnimState = UKIKI_ANIM_STATE_DEFAULT;
}

View file

@ -387,7 +387,8 @@ void mario_blow_off_cap(struct MarioState *m, f32 capSpeed) {
m->flags &= ~(MARIO_NORMAL_CAP | MARIO_CAP_ON_HEAD);
capObject = spawn_object(m->marioObj, MODEL_MARIOS_CAP, bhvNormalCap);
u8 isLuigi = (gNetworkType == NT_SERVER) ? (m->playerIndex != 0) : (m->playerIndex == 0);
capObject = spawn_object(m->marioObj, isLuigi ? MODEL_LUIGIS_CAP : MODEL_MARIOS_CAP, bhvNormalCap);
capObject->oPosY += (m->action & ACT_FLAG_SHORT_HITBOX) ? 120.0f : 180.0f;
capObject->oForwardVel = capSpeed;