mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2026-04-22 10:01:46 +00:00
Synchronized Klepto
This commit is contained in:
parent
e1933e5f78
commit
95b9167287
5 changed files with 101 additions and 29 deletions
|
|
@ -19,9 +19,12 @@ static Vec3f sKleptoTargetPositions[] = {
|
|||
static u8 sKleptoAttackHandlers[] = { 2, 2, 5, 5, 2, 2 };
|
||||
|
||||
static void klepto_target_mario(void) {
|
||||
o->oKleptoDistanceToTarget = lateral_dist_between_objects(gMarioObject, o);
|
||||
o->oKleptoUnk1B0 = obj_turn_pitch_toward_mario(&gMarioStates[0], 250.0f, 0);
|
||||
o->oKleptoYawToTarget = o->oAngleToMario;
|
||||
struct MarioState* marioState = nearest_mario_state_to_object(o);
|
||||
struct Object* player = marioState->marioObj;
|
||||
int angleToPlayer = obj_angle_to_object(o, player);
|
||||
o->oKleptoDistanceToTarget = lateral_dist_between_objects(player, o);
|
||||
o->oKleptoUnk1B0 = obj_turn_pitch_toward_mario(marioState, 250.0f, 0);
|
||||
o->oKleptoYawToTarget = angleToPlayer;
|
||||
o->oKleptoUnk1AE = -60;
|
||||
}
|
||||
|
||||
|
|
@ -73,6 +76,18 @@ static void klepto_anim_dive(void) {
|
|||
obj_face_pitch_approach(0, 1000);
|
||||
}
|
||||
|
||||
static s32 kleptoCachedAnimState = 0;
|
||||
|
||||
static void bhv_klepto_on_received_pre(u8 localIndex) {
|
||||
kleptoCachedAnimState = o->oAnimState;
|
||||
}
|
||||
|
||||
static void bhv_klepto_on_received_post(u8 localIndex) {
|
||||
if (kleptoCachedAnimState == KLEPTO_ANIM_STATE_HOLDING_NOTHING && o->oAnimState == KLEPTO_ANIM_STATE_HOLDING_STAR) {
|
||||
o->oAnimState = KLEPTO_ANIM_STATE_HOLDING_NOTHING;
|
||||
}
|
||||
}
|
||||
|
||||
void bhv_klepto_init(void) {
|
||||
if (o->oBehParams2ndByte != 0) {
|
||||
o->oAnimState = KLEPTO_ANIM_STATE_HOLDING_STAR;
|
||||
|
|
@ -87,6 +102,25 @@ void bhv_klepto_init(void) {
|
|||
o->oAction = KLEPTO_ACT_WAIT_FOR_MARIO;
|
||||
}
|
||||
}
|
||||
|
||||
struct SyncObject* so = network_init_object(o, 4000.0f);
|
||||
so->on_received_pre = bhv_klepto_on_received_pre;
|
||||
so->on_received_post = bhv_klepto_on_received_post;
|
||||
network_init_object_field(o, &o->oAnimState);
|
||||
network_init_object_field(o, &o->oFlags);
|
||||
network_init_object_field(o, &o->oKleptoDistanceToTarget);
|
||||
network_init_object_field(o, &o->oKleptoUnkF8);
|
||||
network_init_object_field(o, &o->oKleptoUnkFC);
|
||||
network_init_object_field(o, &o->oKleptoSpeed);
|
||||
network_init_object_field(o, &o->oKleptoTimeUntilTargetChange);
|
||||
network_init_object_field(o, &o->oKleptoTargetNumber);
|
||||
network_init_object_field(o, &o->oKleptoUnk1B0);
|
||||
network_init_object_field(o, &o->oSoundStateID);
|
||||
network_init_object_field(o, &o->oHomeX);
|
||||
network_init_object_field(o, &o->oHomeY);
|
||||
network_init_object_field(o, &o->oHomeZ);
|
||||
network_init_object_field(o, &o->oMoveAnglePitch);
|
||||
network_init_object_field(o, &o->oGravity);
|
||||
}
|
||||
|
||||
static void klepto_change_target(void) {
|
||||
|
|
@ -97,12 +131,15 @@ static void klepto_change_target(void) {
|
|||
f32 targetDist;
|
||||
f32 minTargetDist;
|
||||
|
||||
if (o->oDistanceToMario > 2000.0f) {
|
||||
struct Object* player = nearest_player_to_object(o);
|
||||
int distanceToPlayer = dist_between_objects(o, player);
|
||||
|
||||
if (distanceToPlayer > 2000.0f) {
|
||||
minTargetDist = 99999.0f;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
dx = gMarioObject->oPosX - sKleptoTargetPositions[i][0];
|
||||
dz = gMarioObject->oPosZ - sKleptoTargetPositions[i][2];
|
||||
dx = player->oPosX - sKleptoTargetPositions[i][0];
|
||||
dz = player->oPosZ - sKleptoTargetPositions[i][2];
|
||||
|
||||
targetDist = sqrtf(dx * dx + dz * dz);
|
||||
if (targetDist < minTargetDist) {
|
||||
|
|
@ -128,8 +165,11 @@ static void klepto_circle_target(f32 radius, f32 targetSpeed) {
|
|||
s16 turnAmount;
|
||||
f32 accel;
|
||||
|
||||
struct Object* player = nearest_player_to_object(o);
|
||||
int distanceToPlayer = dist_between_objects(o, player);
|
||||
|
||||
if (o->oAnimState != KLEPTO_ANIM_STATE_HOLDING_NOTHING
|
||||
&& ((o->oTimer > 60 && o->oDistanceToMario > 2000.0f)
|
||||
&& ((o->oTimer > 60 && distanceToPlayer > 2000.0f)
|
||||
|| o->oTimer >= o->oKleptoTimeUntilTargetChange)) {
|
||||
klepto_change_target();
|
||||
o->oKleptoTimeUntilTargetChange = random_linear_offset(300, 300);
|
||||
|
|
@ -190,8 +230,11 @@ static void klepto_act_wait_for_mario(void) {
|
|||
static void klepto_act_turn_toward_mario(void) {
|
||||
klepto_target_mario();
|
||||
|
||||
struct Object* player = nearest_player_to_object(o);
|
||||
int angleToPlayer = obj_angle_to_object(o, player);
|
||||
|
||||
if (klepto_set_and_check_if_anim_at_end() && cur_obj_check_if_at_animation_end() && o->oKleptoDistanceToTarget > 800.0f
|
||||
&& abs_angle_diff(o->oAngleToMario, o->oFaceAngleYaw) < 0x800 && o->oKleptoUnk1B0 < 0x400) {
|
||||
&& abs_angle_diff(angleToPlayer, o->oFaceAngleYaw) < 0x800 && o->oKleptoUnk1B0 < 0x400) {
|
||||
cur_obj_play_sound_2(SOUND_OBJ_KLEPTO1);
|
||||
o->oAction = KLEPTO_ACT_DIVE_AT_MARIO;
|
||||
o->oMoveAngleYaw = o->oFaceAngleYaw;
|
||||
|
|
@ -201,10 +244,15 @@ static void klepto_act_turn_toward_mario(void) {
|
|||
}
|
||||
|
||||
klepto_circle_target(1000.0f, 40.0f);
|
||||
obj_face_yaw_approach(o->oAngleToMario, 1000);
|
||||
obj_face_yaw_approach(angleToPlayer, 1000);
|
||||
}
|
||||
|
||||
static void klepto_act_dive_at_mario(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);
|
||||
|
||||
approach_f32_ptr(&o->oKleptoSpeed, 60.0f, 10.0f);
|
||||
if (o->oSoundStateID == 2) {
|
||||
if (cur_obj_check_anim_frame(11)) {
|
||||
|
|
@ -220,7 +268,7 @@ static void klepto_act_dive_at_mario(void) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
f32 dy = o->oPosY - gMarioObject->oPosY;
|
||||
f32 dy = o->oPosY - player->oPosY;
|
||||
if (o->oSoundStateID == 3) {
|
||||
cur_obj_set_anim_if_at_end(4);
|
||||
} else if (o->oVelY > 0.0f && dy > 200.0f) {
|
||||
|
|
@ -230,19 +278,20 @@ static void klepto_act_dive_at_mario(void) {
|
|||
o->oKleptoUnk1B0 = -0x3000;
|
||||
if (o->oAnimState == KLEPTO_ANIM_STATE_HOLDING_NOTHING) {
|
||||
if (o->oSubAction == 0) {
|
||||
o->oKleptoUnk1B0 = obj_turn_pitch_toward_mario(&gMarioStates[0], 0.0f, 0);
|
||||
o->oKleptoYawToTarget = o->oAngleToMario;
|
||||
o->oKleptoUnk1B0 = obj_turn_pitch_toward_mario(marioState, 0.0f, 0);
|
||||
o->oKleptoYawToTarget = angleToPlayer;
|
||||
|
||||
if (dy < 160.0f) {
|
||||
o->oSubAction += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (gMarioStates[0].action != ACT_SLEEPING
|
||||
&& !(gMarioStates[0].action & (ACT_FLAG_SHORT_HITBOX | ACT_FLAG_BUTT_OR_STOMACH_SLIDE))
|
||||
&& o->oDistanceToMario < 200.0f && dy > 50.0f && dy < 90.0f) {
|
||||
if (mario_lose_cap_to_enemy(1)) {
|
||||
if (marioState->action != ACT_SLEEPING
|
||||
&& !(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;
|
||||
network_send_object(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -319,6 +368,11 @@ void obj_set_speed_to_zero(void) {
|
|||
}
|
||||
|
||||
void bhv_klepto_update(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);
|
||||
|
||||
UNUSED s32 unused;
|
||||
|
||||
cur_obj_update_floor_and_walls();
|
||||
|
|
@ -359,23 +413,29 @@ void bhv_klepto_update(void) {
|
|||
if (obj_handle_attacks(&sKleptoHitbox, o->oAction, sKleptoAttackHandlers)) {
|
||||
cur_obj_play_sound_2(SOUND_OBJ_KLEPTO2);
|
||||
|
||||
if (o->oAnimState == KLEPTO_ANIM_STATE_HOLDING_CAP) {
|
||||
if (network_owns_object(o) && o->oAnimState == KLEPTO_ANIM_STATE_HOLDING_CAP) {
|
||||
save_file_clear_flags(SAVE_FLAG_CAP_ON_KLEPTO);
|
||||
spawn_object(o, MODEL_MARIOS_CAP, bhvNormalCap);
|
||||
struct Object* cap = spawn_object(o, MODEL_MARIOS_CAP, bhvNormalCap);
|
||||
|
||||
struct Object* spawn_objects[] = { cap };
|
||||
u32 models[] = { MODEL_MARIOS_CAP };
|
||||
network_send_spawn_objects(spawn_objects, models, 1);
|
||||
|
||||
} else if (o->oAnimState == KLEPTO_ANIM_STATE_HOLDING_STAR) {
|
||||
spawn_default_star(-5550.0f, 300.0f, -930.0f);
|
||||
}
|
||||
|
||||
o->oAnimState = KLEPTO_ANIM_STATE_HOLDING_NOTHING;
|
||||
o->oAction = KLEPTO_ACT_STRUCK_BY_MARIO;
|
||||
if (network_owns_object(o)) {
|
||||
o->oAnimState = KLEPTO_ANIM_STATE_HOLDING_NOTHING;
|
||||
o->oAction = KLEPTO_ACT_STRUCK_BY_MARIO;
|
||||
network_send_object(o);
|
||||
}
|
||||
o->oGravity = -2.0f;
|
||||
|
||||
o->oMoveAngleYaw = o->oAngleToMario + 0x8000;
|
||||
o->oMoveAngleYaw = angleToPlayer + 0x8000;
|
||||
o->oFlags &= ~0x00000008;
|
||||
cur_obj_become_intangible();
|
||||
} else if (gMarioStates[0].action == ACT_SLEEPING
|
||||
|| (gMarioStates[0].action
|
||||
& (ACT_FLAG_SHORT_HITBOX | ACT_FLAG_BUTT_OR_STOMACH_SLIDE))) {
|
||||
} else if (marioState->action == ACT_SLEEPING || (marioState->action & (ACT_FLAG_SHORT_HITBOX | ACT_FLAG_BUTT_OR_STOMACH_SLIDE))) {
|
||||
cur_obj_become_intangible();
|
||||
} else {
|
||||
cur_obj_become_tangible();
|
||||
|
|
|
|||
|
|
@ -569,7 +569,7 @@ u8 hat_ukiki_held_loop_2(void) { return o->oHeldState == HELD_HELD && o->oUkikiT
|
|||
void hat_ukiki_held_loop(void) {
|
||||
switch(o->oUkikiTextState) {
|
||||
case UKIKI_TEXT_DEFAULT:
|
||||
if (mario_lose_cap_to_enemy(2)) {
|
||||
if (mario_lose_cap_to_enemy(&gMarioStates[0], 2)) {
|
||||
o->oUkikiTextState = UKIKI_TEXT_STEAL_HAT;
|
||||
o->oUkikiHasHat |= UKIKI_HAT_ON;
|
||||
} else {}
|
||||
|
|
|
|||
|
|
@ -382,12 +382,13 @@ void mario_blow_off_cap(struct MarioState *m, f32 capSpeed) {
|
|||
}
|
||||
}
|
||||
|
||||
u32 mario_lose_cap_to_enemy(u32 arg) {
|
||||
u32 mario_lose_cap_to_enemy(struct MarioState* m, u32 arg) {
|
||||
if (m->playerIndex != 0) { return FALSE; }
|
||||
u32 wasWearingCap = FALSE;
|
||||
|
||||
if (does_mario_have_hat(gMarioState)) {
|
||||
if (does_mario_have_hat(m)) {
|
||||
save_file_set_flags(arg == 1 ? SAVE_FLAG_CAP_ON_KLEPTO : SAVE_FLAG_CAP_ON_UKIKI);
|
||||
gMarioState->flags &= ~(MARIO_NORMAL_CAP | MARIO_CAP_ON_HEAD);
|
||||
m->flags &= ~(MARIO_NORMAL_CAP | MARIO_CAP_ON_HEAD);
|
||||
wasWearingCap = TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -1787,6 +1788,11 @@ u32 interact_cap(struct MarioState *m, UNUSED u32 interactType, struct Object *o
|
|||
u16 capMusic = 0;
|
||||
u16 capTime = 0;
|
||||
|
||||
if (capFlag == MARIO_NORMAL_CAP) {
|
||||
// refuse normal cap when already on head
|
||||
if (m->flags & (MARIO_NORMAL_CAP | MARIO_CAP_ON_HEAD)) { return FALSE; }
|
||||
}
|
||||
|
||||
if (m->action != ACT_GETTING_BLOWN && capFlag != 0) {
|
||||
m->interactObj = o;
|
||||
o->oInteractStatus = INT_STATUS_INTERACTED;
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ void mario_throw_held_object(struct MarioState *m);
|
|||
void mario_stop_riding_and_holding(struct MarioState *m);
|
||||
u32 does_mario_have_hat(struct MarioState *m);
|
||||
void mario_blow_off_cap(struct MarioState *m, f32 capSpeed);
|
||||
u32 mario_lose_cap_to_enemy(u32 arg);
|
||||
u32 mario_lose_cap_to_enemy(struct MarioState* m, u32 arg);
|
||||
void mario_retrieve_cap(void);
|
||||
struct Object *mario_get_collided_object(struct MarioState *m, u32 interactType);
|
||||
u32 mario_check_object_grab(struct MarioState *m);
|
||||
|
|
|
|||
|
|
@ -1246,6 +1246,12 @@ s32 update_level(void) {
|
|||
}
|
||||
|
||||
s32 init_level(void) {
|
||||
// reset cap flags
|
||||
save_file_clear_flags(SAVE_FLAG_CAP_ON_GROUND);
|
||||
save_file_clear_flags(SAVE_FLAG_CAP_ON_KLEPTO);
|
||||
save_file_clear_flags(SAVE_FLAG_CAP_ON_UKIKI);
|
||||
save_file_clear_flags(SAVE_FLAG_CAP_ON_MR_BLIZZARD);
|
||||
|
||||
reset_dialog_render_state();
|
||||
|
||||
s32 val4 = 0;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue