Synchronized enemy lakitu and spiny

This commit is contained in:
MysterD 2020-10-08 22:14:17 -07:00
parent 4c76dc065c
commit 74f027b3e6
2 changed files with 80 additions and 20 deletions

View File

@ -25,7 +25,9 @@ static struct ObjectHitbox sEnemyLakituHitbox = {
*/
static void enemy_lakitu_act_uninitialized(void) {
#ifndef NODRAWINGDISTANCE
if (o->oDistanceToMario < 2000.0f) {
struct Object* player = nearest_player_to_object(o);
int distanceToPlayer = dist_between_objects(o, player);
if (distanceToPlayer < 2000.0f) {
#endif
spawn_object_relative_with_scale(CLOUD_BP_LAKITU_CLOUD, 0, 0, 0, 2.0f, o, MODEL_MIST, bhvCloud);
@ -49,7 +51,8 @@ static void enemy_lakitu_update_vel_y(f32 offsetY) {
margin = 3.0f;
}
if (o->oPosY < gMarioObject->oPosY + offsetY + margin) {
struct Object* player = nearest_player_to_object(o);
if (o->oPosY < player->oPosY + offsetY + margin) {
obj_y_vel_approach(4.0f, 0.4f);
} else {
obj_y_vel_approach(-4.0f, 0.4f);
@ -61,16 +64,21 @@ static void enemy_lakitu_update_vel_y(f32 offsetY) {
* angle toward mario.
*/
static void enemy_lakitu_update_speed_and_angle(void) {
struct MarioState* marioState = nearest_mario_state_to_object(o);
struct Object* player = marioState->marioObj;
int distanceToPlayer = dist_between_objects(o, player);
int angleToPlayer = obj_angle_to_object(o, player);
f32 minSpeed;
s16 turnSpeed;
f32 distToMario = o->oDistanceToMario;
f32 distToMario = distanceToPlayer;
if (distToMario > 500.0f) {
distToMario = 500.0f;
}
// Move faster the farther away mario is and the faster mario is moving
if ((minSpeed = 1.2f * gMarioStates[0].forwardVel) < 8.0f) {
if ((minSpeed = 1.2f * marioState->forwardVel) < 8.0f) {
minSpeed = 8.0f;
}
o->oForwardVel = distToMario * 0.04f;
@ -83,13 +91,13 @@ static void enemy_lakitu_update_speed_and_angle(void) {
if (o->oEnemyLakituFaceForwardCountdown != 0) {
o->oEnemyLakituFaceForwardCountdown -= 1;
} else {
obj_face_yaw_approach(o->oAngleToMario, 0x600);
obj_face_yaw_approach(angleToPlayer, 0x600);
}
// Change move angle toward mario faster when farther from mario
turnSpeed = (s16)(distToMario * 2);
clamp_s16(&turnSpeed, 0xC8, 0xFA0);
cur_obj_rotate_yaw_toward(o->oAngleToMario, turnSpeed);
cur_obj_rotate_yaw_toward(angleToPlayer, turnSpeed);
}
/**
@ -97,21 +105,35 @@ static void enemy_lakitu_update_speed_and_angle(void) {
* hold it, then enter the hold spiny sub-action.
*/
static void enemy_lakitu_sub_act_no_spiny(void) {
struct MarioState* marioState = nearest_mario_state_to_object(o);
struct Object* player = marioState->marioObj;
int distanceToPlayer = dist_between_objects(o, player);
int angleToPlayer = obj_angle_to_object(o, player);
cur_obj_init_animation_with_sound(1);
if (o->oEnemyLakituSpinyCooldown != 0) {
o->oEnemyLakituSpinyCooldown -= 1;
} else if (o->oEnemyLakituNumSpinies < 3 && o->oDistanceToMario < 800.0f
&& abs_angle_diff(o->oAngleToMario, o->oFaceAngleYaw) < 0x4000) {
struct Object *spiny = spawn_object(o, MODEL_SPINY_BALL, bhvSpiny);
if (spiny != NULL) {
o->prevObj = spiny;
spiny->oAction = SPINY_ACT_HELD_BY_LAKITU;
obj_init_animation_with_sound(spiny, spiny_egg_seg5_anims_050157E4, 0);
} else if (o->oEnemyLakituNumSpinies < 3 && distanceToPlayer < 800.0f
&& abs_angle_diff(angleToPlayer, o->oFaceAngleYaw) < 0x4000) {
o->oEnemyLakituNumSpinies += 1;
o->oSubAction = ENEMY_LAKITU_SUB_ACT_HOLD_SPINY;
o->oEnemyLakituSpinyCooldown = 30;
if (marioState->playerIndex == 0) {
struct Object* spiny = spawn_object(o, MODEL_SPINY_BALL, bhvSpiny);
if (spiny != NULL) {
o->prevObj = spiny;
spiny->oAction = SPINY_ACT_HELD_BY_LAKITU;
obj_init_animation_with_sound(spiny, spiny_egg_seg5_anims_050157E4, 0);
o->oEnemyLakituNumSpinies += 1;
o->oSubAction = ENEMY_LAKITU_SUB_ACT_HOLD_SPINY;
o->oEnemyLakituSpinyCooldown = 30;
network_send_object(o);
network_set_sync_id(spiny);
struct Object* spawn_objects[] = { spiny };
u32 models[] = { MODEL_SPINY_BALL };
network_send_spawn_objects(spawn_objects, models, 1);
}
}
}
}
@ -121,15 +143,19 @@ static void enemy_lakitu_sub_act_no_spiny(void) {
* enter the throw spiny sub-action.
*/
static void enemy_lakitu_sub_act_hold_spiny(void) {
struct Object* player = nearest_player_to_object(o);
int distanceToPlayer = dist_between_objects(o, player);
int angleToPlayer = obj_angle_to_object(o, player);
cur_obj_init_anim_extend(3);
if (o->oEnemyLakituSpinyCooldown != 0) {
o->oEnemyLakituSpinyCooldown -= 1;
}
// TODO: Check if anything interesting happens if we bypass this with speed
else if (o->oDistanceToMario > o->oDrawingDistance - 100.0f
|| (o->oDistanceToMario < 500.0f
&& abs_angle_diff(o->oAngleToMario, o->oFaceAngleYaw) < 0x2000)) {
else if (distanceToPlayer > o->oDrawingDistance - 100.0f
|| (distanceToPlayer < 500.0f
&& abs_angle_diff(angleToPlayer, o->oFaceAngleYaw) < 0x2000)) {
o->oSubAction = ENEMY_LAKITU_SUB_ACT_THROW_SPINY;
o->oEnemyLakituFaceForwardCountdown = 20;
}
@ -191,6 +217,12 @@ static void enemy_lakitu_act_main(void) {
*/
void bhv_enemy_lakitu_update(void) {
// PARTIAL_UPDATE
if (!network_sync_object_initialized(o)) {
network_init_object(o, 4000.0f);
network_init_object_field(o, &o->oEnemyLakituBlinkTimer);
network_init_object_field(o, &o->oEnemyLakituSpinyCooldown);
network_init_object_field(o, &o->oEnemyLakituFaceForwardCountdown);
}
treat_far_home_as_mario(2000.0f);

View File

@ -37,8 +37,10 @@ static u8 sSpinyWalkAttackHandlers[] = {
* If the spiny was spawned by lakitu and mario is far away, despawn.
*/
static s32 spiny_check_active(void) {
struct Object* player = nearest_player_to_object(o);
int distanceToPlayer = dist_between_objects(o, player);
if (o->parentObj != o) {
if (o->oDistanceToMario > 2500.0f) {
if (distanceToPlayer > 2500.0f) {
//! It's possible for the lakitu to despawn while the spiny still
// references it. This line allows us to decrement the 0x1B field
// in an object that loads into the lakitu's former slot.
@ -177,11 +179,37 @@ static void spiny_act_thrown_by_lakitu(void) {
}
}
void bhv_spiny_override_ownership(u8* shouldOverride, u8* shouldOwn) {
*shouldOverride = (o->parentObj->behavior == bhvEnemyLakitu);
*shouldOwn = network_owns_object(o->parentObj);
}
/**
* Update function for bhvSpiny.
*/
void bhv_spiny_update(void) {
// PARTIAL_UPDATE
if (!network_sync_object_initialized(o)) {
struct SyncObject* so = network_init_object(o, 4000.0f);
so->syncDeathEvent = FALSE;
so->override_ownership = bhv_spiny_override_ownership;
network_init_object_field(o, &o->oGraphYOffset);
network_init_object_field(o, &o->oFaceAngleYaw);
network_init_object_field(o, &o->oSpinyTimeUntilTurn);
network_init_object_field(o, &o->oSpinyTargetYaw);
network_init_object_field(o, &o->oSpinyTurningAwayFromWall);
network_init_object_field(o, &o->oMoveFlags);
network_init_object_field(o, &o->oInteractType);
network_init_object_field(o, &o->oFaceAnglePitch);
struct Object* lakitu = cur_obj_nearest_object_with_behavior(bhvEnemyLakitu);
if (lakitu != NULL) {
lakitu->prevObj = o;
o->oAction = SPINY_ACT_HELD_BY_LAKITU;
obj_init_animation_with_sound(o, spiny_egg_seg5_anims_050157E4, 0);
}
}
switch (o->oAction) {
case SPINY_ACT_WALK: