Synchronized Monty Mole

This commit is contained in:
MysterD 2020-10-01 18:25:36 -07:00
parent 66356133db
commit f6bae3a619
2 changed files with 89 additions and 14 deletions

View File

@ -701,6 +701,9 @@
/* Monty Mole */ /* Monty Mole */
#define /*0x0F4*/ oMontyMoleCurrentHole OBJECT_FIELD_OBJ(0x1B) #define /*0x0F4*/ oMontyMoleCurrentHole OBJECT_FIELD_OBJ(0x1B)
#define /*0x0F8*/ oMontyMoleHeightRelativeToFloor OBJECT_FIELD_F32(0x1C) #define /*0x0F8*/ oMontyMoleHeightRelativeToFloor OBJECT_FIELD_F32(0x1C)
#define /*0x0FC*/ oMontyMoleHoleX OBJECT_FIELD_F32(0x1D)
#define /*0x100*/ oMontyMoleHoleY OBJECT_FIELD_F32(0x1E)
#define /*0x104*/ oMontyMoleHoleZ OBJECT_FIELD_F32(0x1F)
/* Monty Mole Hole */ /* Monty Mole Hole */
#define /*0x0F4*/ oMontyMoleHoleCooldown OBJECT_FIELD_S32(0x1B) #define /*0x0F4*/ oMontyMoleHoleCooldown OBJECT_FIELD_S32(0x1B)

View File

@ -58,12 +58,17 @@ static struct Object *link_objects_with_behavior(const BehaviorScript *behavior)
* whose cooldown is zero. Return NULL if no hole is available. * whose cooldown is zero. Return NULL if no hole is available.
*/ */
static struct Object *monty_mole_select_available_hole(f32 minDistToMario) { static struct Object *monty_mole_select_available_hole(f32 minDistToMario) {
struct Object* player;
int distanceToPlayer;
struct Object *hole = sMontyMoleHoleList; struct Object *hole = sMontyMoleHoleList;
s32 numAvailableHoles = 0; s32 numAvailableHoles = 0;
while (hole != NULL) { while (hole != NULL) {
player = nearest_player_to_object(hole);
distanceToPlayer = dist_between_objects(hole, player);
if (hole->oMontyMoleHoleCooldown == 0) { if (hole->oMontyMoleHoleCooldown == 0) {
if (hole->oDistanceToMario < 1500.0f && hole->oDistanceToMario > minDistToMario) { if (distanceToPlayer < 1500.0f && distanceToPlayer > minDistToMario) {
numAvailableHoles++; numAvailableHoles++;
} }
} }
@ -78,8 +83,10 @@ static struct Object *monty_mole_select_available_hole(f32 minDistToMario) {
numAvailableHoles = 0; numAvailableHoles = 0;
while (hole != NULL) { while (hole != NULL) {
player = nearest_player_to_object(hole);
distanceToPlayer = dist_between_objects(hole, player);
if (hole->oMontyMoleHoleCooldown == 0) { if (hole->oMontyMoleHoleCooldown == 0) {
if (hole->oDistanceToMario < 1500.0f && hole->oDistanceToMario > minDistToMario) { if (distanceToPlayer < 1500.0f && distanceToPlayer > minDistToMario) {
if (numAvailableHoles == selectedHole) { if (numAvailableHoles == selectedHole) {
return hole; return hole;
} }
@ -132,11 +139,46 @@ void monty_mole_spawn_dirt_particles(s8 offsetY, s8 velYBase) {
cur_obj_spawn_particles(&sMontyMoleRiseFromGroundParticles); cur_obj_spawn_particles(&sMontyMoleRiseFromGroundParticles);
} }
static void bhv_monty_mole_on_received_post(u8 fromLocalIndex) {
if (o->oMontyMoleHoleX == 0 && o->oMontyMoleHoleY == 0 && o->oMontyMoleHoleZ == 0) { return; }
o->oMontyMoleCurrentHole = NULL;
f32 savePosX = o->oPosX;
f32 savePosY = o->oPosY;
f32 savePosZ = o->oPosZ;
o->oPosX = o->oMontyMoleHoleX;
o->oPosY = o->oMontyMoleHoleY;
o->oPosZ = o->oMontyMoleHoleZ;
o->oMontyMoleCurrentHole = cur_obj_nearest_object_with_behavior(bhvMontyMoleHole);
o->oPosX = savePosX;
o->oPosY = savePosY;
o->oPosZ = savePosZ;
}
/** /**
* Init function for bhvMontyMole. * Init function for bhvMontyMole.
*/ */
void bhv_monty_mole_init(void) { void bhv_monty_mole_init(void) {
o->oMontyMoleCurrentHole = NULL; o->oMontyMoleCurrentHole = NULL;
o->oMontyMoleHoleX = 0;
o->oMontyMoleHoleY = 0;
o->oMontyMoleHoleZ = 0;
struct SyncObject* so = network_init_object(o, 4000.0f);
so->on_received_post = bhv_monty_mole_on_received_post;
network_init_object_field(o, &o->oMontyMoleHeightRelativeToFloor);
network_init_object_field(o, &o->oMontyMoleHoleX);
network_init_object_field(o, &o->oMontyMoleHoleY);
network_init_object_field(o, &o->oMontyMoleHoleZ);
network_init_object_field(o, &o->oFaceAnglePitch);
network_init_object_field(o, &o->oGravity);
network_init_object_field(o, &o->header.gfx.node.flags);
network_init_object_field(o, &o->oIntangibleTimer);
network_init_object_field(o, &o->oFaceAnglePitch);
} }
/** /**
@ -144,11 +186,14 @@ void bhv_monty_mole_init(void) {
* either the rise from hole or jump out of hole action. * either the rise from hole or jump out of hole action.
*/ */
static void monty_mole_act_select_hole(void) { static void monty_mole_act_select_hole(void) {
u8 networkOwns = network_owns_object(o);
struct MarioState* marioState = nearest_mario_state_to_object(o);
f32 minDistToMario; f32 minDistToMario;
if (o->oBehParams2ndByte != MONTY_MOLE_BP_NO_ROCK) { if (o->oBehParams2ndByte != MONTY_MOLE_BP_NO_ROCK) {
minDistToMario = 200.0f; minDistToMario = 200.0f;
} else if (gMarioStates[0].forwardVel < 8.0f) { } else if (marioState->forwardVel < 8.0f) {
minDistToMario = 100.0f; minDistToMario = 100.0f;
} else { } else {
minDistToMario = 500.0f; minDistToMario = 500.0f;
@ -156,6 +201,10 @@ static void monty_mole_act_select_hole(void) {
// Select a hole to pop out of // Select a hole to pop out of
if ((o->oMontyMoleCurrentHole = monty_mole_select_available_hole(minDistToMario)) != NULL) { if ((o->oMontyMoleCurrentHole = monty_mole_select_available_hole(minDistToMario)) != NULL) {
o->oMontyMoleHoleX = o->oMontyMoleCurrentHole->oPosX;
o->oMontyMoleHoleY = o->oMontyMoleCurrentHole->oPosY;
o->oMontyMoleHoleZ = o->oMontyMoleCurrentHole->oPosZ;
cur_obj_play_sound_2(SOUND_OBJ2_MONTY_MOLE_APPEAR); cur_obj_play_sound_2(SOUND_OBJ2_MONTY_MOLE_APPEAR);
// Mark hole as unavailable // Mark hole as unavailable
@ -169,7 +218,10 @@ static void monty_mole_act_select_hole(void) {
o->oFaceAnglePitch = 0; o->oFaceAnglePitch = 0;
o->oMoveAngleYaw = o->oMontyMoleCurrentHole->oAngleToMario; o->oMoveAngleYaw = o->oMontyMoleCurrentHole->oAngleToMario;
if (o->oDistanceToMario > 500.0f || minDistToMario > 100.0f || random_sign() < 0) { struct Object* player = nearest_player_to_object(o);
int distanceToPlayer = dist_between_objects(o, player);
if (distanceToPlayer > 500.0f || minDistToMario > 100.0f || random_sign() < 0) {
o->oAction = MONTY_MOLE_ACT_RISE_FROM_HOLE; o->oAction = MONTY_MOLE_ACT_RISE_FROM_HOLE;
o->oVelY = 3.0f; o->oVelY = 3.0f;
o->oGravity = 0.0f; o->oGravity = 0.0f;
@ -183,6 +235,8 @@ static void monty_mole_act_select_hole(void) {
cur_obj_unhide(); cur_obj_unhide();
cur_obj_become_tangible(); cur_obj_become_tangible();
if (networkOwns) { network_send_object(o); }
} }
} }
@ -207,12 +261,21 @@ static void monty_mole_act_rise_from_hole(void) {
* Otherwise, enter the begin jump into hole action. * Otherwise, enter the begin jump into hole action.
*/ */
static void monty_mole_act_spawn_rock(void) { static void monty_mole_act_spawn_rock(void) {
struct Object* player = nearest_player_to_object(o);
int angleToPlayer = obj_angle_to_object(o, player);
struct Object *rock; struct Object *rock;
if (cur_obj_init_anim_and_check_if_end(2)) { if (cur_obj_init_anim_and_check_if_end(2)) {
if (o->oBehParams2ndByte != MONTY_MOLE_BP_NO_ROCK if (o->oBehParams2ndByte != MONTY_MOLE_BP_NO_ROCK
&& abs_angle_diff(o->oAngleToMario, o->oMoveAngleYaw) < 0x4000 && abs_angle_diff(angleToPlayer, o->oMoveAngleYaw) < 0x4000
&& network_owns_object(o)
&& (rock = spawn_object(o, MODEL_PEBBLE, bhvMontyMoleRock)) != NULL) { && (rock = spawn_object(o, MODEL_PEBBLE, bhvMontyMoleRock)) != NULL) {
struct Object* spawn_objects[] = { rock };
u32 models[] = { MODEL_PEBBLE };
network_send_spawn_objects(spawn_objects, models, 1);
o->prevObj = rock; o->prevObj = rock;
o->oAction = MONTY_MOLE_ACT_THROW_ROCK; o->oAction = MONTY_MOLE_ACT_THROW_ROCK;
} else { } else {
@ -226,7 +289,8 @@ static void monty_mole_act_spawn_rock(void) {
* into hole action. * into hole action.
*/ */
static void monty_mole_act_begin_jump_into_hole(void) { static void monty_mole_act_begin_jump_into_hole(void) {
if (cur_obj_init_anim_and_check_if_end(3) || obj_is_near_to_and_facing_mario(&gMarioStates[0], 1000.0f, 0x4000)) { struct MarioState* marioState = nearest_mario_state_to_object(o);
if (cur_obj_init_anim_and_check_if_end(3) || obj_is_near_to_and_facing_mario(marioState, 1000.0f, 0x4000)) {
o->oAction = MONTY_MOLE_ACT_JUMP_INTO_HOLE; o->oAction = MONTY_MOLE_ACT_JUMP_INTO_HOLE;
o->oVelY = 40.0f; o->oVelY = 40.0f;
o->oGravity = -6.0f; o->oGravity = -6.0f;
@ -266,6 +330,7 @@ static void monty_mole_act_jump_into_hole(void) {
* Become intangible and enter the select hole action. * Become intangible and enter the select hole action.
*/ */
static void monty_mole_hide_in_hole(void) { static void monty_mole_hide_in_hole(void) {
if (o->oMontyMoleCurrentHole == NULL) { return; }
o->oMontyMoleCurrentHole->oMontyMoleHoleCooldown = 30; o->oMontyMoleCurrentHole->oMontyMoleHoleCooldown = 30;
o->oAction = MONTY_MOLE_ACT_SELECT_HOLE; o->oAction = MONTY_MOLE_ACT_SELECT_HOLE;
o->oVelY = 0.0f; o->oVelY = 0.0f;
@ -378,9 +443,13 @@ void bhv_monty_mole_update(void) {
// 1500 units away from each other, so the counter resets if you // 1500 units away from each other, so the counter resets if you
// attack moles in these holes consecutively. // attack moles in these holes consecutively.
if (distToLastKill < 1500.0f) { if (distToLastKill < 1500.0f) {
if (sMontyMoleKillStreak == 7) { if (sMontyMoleKillStreak == 7 && network_owns_object(o)) {
play_puzzle_jingle(); play_puzzle_jingle();
spawn_object(o, MODEL_1UP, bhv1upWalking); struct Object* oneUp = spawn_object(o, MODEL_1UP, bhv1upWalking);
struct Object* spawn_objects[] = { oneUp };
u32 models[] = { MODEL_1UP };
network_send_spawn_objects(spawn_objects, models, 1);
} }
} else { } else {
sMontyMoleKillStreak = 0; sMontyMoleKillStreak = 0;
@ -412,19 +481,22 @@ static void monty_mole_rock_act_held(void) {
o->oParentRelativePosY = -50.0f; o->oParentRelativePosY = -50.0f;
o->oParentRelativePosZ = 0.0f; o->oParentRelativePosZ = 0.0f;
if (o->parentObj->prevObj == NULL) { if (o->parentObj == NULL || o->parentObj->prevObj == NULL) {
f32 distToMario = o->oDistanceToMario; struct Object* player = nearest_player_to_object(o);
if (distToMario > 600.0f) { int distanceToPlayer = dist_between_objects(o, player);
distToMario = 600.0f; if (distanceToPlayer > 600.0f) {
distanceToPlayer = 600.0f;
} }
o->oAction = MONTY_MOLE_ROCK_ACT_MOVE; o->oAction = MONTY_MOLE_ROCK_ACT_MOVE;
// The angle is adjusted to compensate for the start position offset // The angle is adjusted to compensate for the start position offset
o->oMoveAngleYaw = (s32)(o->parentObj->oMoveAngleYaw + 0x1F4 - distToMario * 0.1f); if (o->parentObj != NULL) {
o->oMoveAngleYaw = (s32)(o->parentObj->oMoveAngleYaw + 0x1F4 - distanceToPlayer * 0.1f);
}
o->oForwardVel = 40.0f; o->oForwardVel = 40.0f;
o->oVelY = distToMario * 0.08f + 8.0f; o->oVelY = distanceToPlayer * 0.08f + 8.0f;
o->oMoveFlags = 0; o->oMoveFlags = 0;
} }