From c5888aff50482c8761134c9e27dbbcb8adeec92d Mon Sep 17 00:00:00 2001 From: MysterD Date: Sun, 20 Sep 2020 17:28:24 -0700 Subject: [PATCH] Synchronized mips --- src/game/behaviors/cannon.inc.c | 4 +-- src/game/behaviors/mips.inc.c | 42 +++++++++++++++++++++++--- src/game/mario.c | 2 +- src/pc/network/network.h | 3 +- src/pc/network/packets/packet_object.c | 16 ++++++++-- 5 files changed, 55 insertions(+), 12 deletions(-) diff --git a/src/game/behaviors/cannon.inc.c b/src/game/behaviors/cannon.inc.c index d4113680..e0a07264 100644 --- a/src/game/behaviors/cannon.inc.c +++ b/src/game/behaviors/cannon.inc.c @@ -151,7 +151,7 @@ u8 cannon_ignore_remote_updates(void) { return ((gNetworkType == NT_SERVER) && o->oCannonIsLocal); } -static void cannon_on_received(void) { +static void cannon_on_received_pos(void) { // check if we're on in the cannon too struct MarioState* m = &gMarioStates[0]; if (m->action != ACT_IN_CANNON) { return; } @@ -179,7 +179,7 @@ void bhv_cannon_base_loop(void) { if (!network_sync_object_initialized(o)) { struct SyncObject* so = network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS); so->ignore_if_true = cannon_ignore_remote_updates; - so->on_received = cannon_on_received; + so->on_received_post = cannon_on_received_pos; network_init_object_field(o, &o->oAction); network_init_object_field(o, &o->oPrevAction); network_init_object_field(o, &o->oTimer); diff --git a/src/game/behaviors/mips.inc.c b/src/game/behaviors/mips.inc.c index eb590a24..ac64c89a 100644 --- a/src/game/behaviors/mips.inc.c +++ b/src/game/behaviors/mips.inc.c @@ -2,6 +2,18 @@ * Behavior for MIPS (everyone's favorite yellow rabbit). */ +static u32 mipsPrevHeldState = 0; + +static void bhv_mips_on_received_pre(void) { + mipsPrevHeldState = o->oHeldState; +} + +static void bhv_mips_on_received_post(void) { + if (mipsPrevHeldState == HELD_HELD && o->oHeldState == HELD_FREE) { + cur_obj_init_animation(0); + } +} + /** * Initializes MIPS' physics parameters and checks if he should be active, * hiding him if necessary. @@ -41,6 +53,17 @@ void bhv_mips_init(void) { o->oBuoyancy = 1.2f; cur_obj_init_animation(0); + + struct SyncObject* so = network_init_object(o, 4000.0f); + network_init_object_field(o, &o->oMipsStartWaypointIndex); + network_init_object_field(o, &o->oForwardVel); + network_init_object_field(o, &o->oMipsStarStatus); + network_init_object_field(o, &o->oBehParams2ndByte); + network_init_object_field(o, &o->oHeldState); + network_init_object_field(o, &o->oFlags); + network_init_object_field(o, &o->oIntangibleTimer); + so->on_received_pre = bhv_mips_on_received_pre; + so->on_received_post = bhv_mips_on_received_post; } /** @@ -58,6 +81,8 @@ s16 bhv_mips_find_furthest_waypoint_to_mario(void) { pathBase = segmented_to_virtual(&inside_castle_seg7_trajectory_mips); + struct Object* player = nearest_player_to_object(o); + // For each waypoint in MIPS path... for (i = 0; i < 10; i++) { waypoint = segmented_to_virtual(*(pathBase + i)); @@ -68,8 +93,7 @@ s16 bhv_mips_find_furthest_waypoint_to_mario(void) { // Is the waypoint within 800 units of MIPS? if (is_point_close_to_object(o, x, y, z, 800)) { // Is this further from Mario than the last waypoint? - distanceToMario = - sqr(x - gMarioObject->header.gfx.pos[0]) + sqr(z - gMarioObject->header.gfx.pos[2]); + distanceToMario = sqr(x - player->header.gfx.pos[0]) + sqr(z - player->header.gfx.pos[2]); if (furthestWaypointDistance < distanceToMario) { furthestWaypointIndex = i; furthestWaypointDistance = distanceToMario; @@ -221,7 +245,7 @@ void bhv_mips_free(void) { } static u8 bhv_mips_held_continue_dialog(void) { - return (o->oHeldState == HELD_HELD && o->oMipsStarStatus == MIPS_STAR_STATUS_HAVENT_SPAWNED_STAR); + return (o->heldByPlayerIndex == 0 && o->oHeldState == HELD_HELD && o->oMipsStarStatus == MIPS_STAR_STATUS_HAVENT_SPAWNED_STAR); } /** @@ -230,9 +254,11 @@ static u8 bhv_mips_held_continue_dialog(void) { void bhv_mips_held(void) { s16 dialogID; + struct Object* player = gMarioStates[o->heldByPlayerIndex].marioObj; + o->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE; cur_obj_init_animation(4); // Held animation. - cur_obj_set_pos_relative(gMarioObject, 0, 60.0f, 100.0f); + cur_obj_set_pos_relative(player, 0, 60.0f, 100.0f); cur_obj_become_intangible(); // If MIPS hasn't spawned his star yet... @@ -243,7 +269,7 @@ void bhv_mips_held(void) { else dialogID = DIALOG_162; - if (set_mario_npc_dialog(&gMarioStates[0], 1, bhv_mips_held_continue_dialog) == 2) { + if (o->heldByPlayerIndex == 0 && set_mario_npc_dialog(&gMarioStates[0], 1, bhv_mips_held_continue_dialog) == 2) { //o->activeFlags |= ACTIVE_FLAG_INITIATED_TIME_STOP; if (cutscene_object_with_dialog(CUTSCENE_DIALOG, o, dialogID)) { o->oInteractionSubtype |= INT_SUBTYPE_DROP_IMMEDIATELY; @@ -266,6 +292,9 @@ void bhv_mips_dropped(void) { cur_obj_become_tangible(); o->oForwardVel = 3.0f; o->oAction = MIPS_ACT_IDLE; + if (network_owns_object(o)) { + network_send_object(o); + } } /** @@ -281,6 +310,9 @@ void bhv_mips_thrown(void) { o->oForwardVel = 25.0f; o->oVelY = 20.0f; o->oAction = MIPS_ACT_FALL_DOWN; + if (network_owns_object(o)) { + network_send_object(o); + } } /** diff --git a/src/game/mario.c b/src/game/mario.c index 126882c1..1bbfb38c 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -1904,7 +1904,7 @@ s32 execute_mario_action(UNUSED struct Object *o) { // two-player hack: drop held object if server is holding it if (gNetworkType == NT_CLIENT && gMarioState->playerIndex == 0 && gMarioState->heldObj != NULL) { u8 inCutscene = ((gMarioState->action & ACT_GROUP_MASK) != ACT_GROUP_CUTSCENE); - if (!inCutscene && gMarioState->heldObj == gMarioStates[0].heldObj) { + if (!inCutscene && gMarioState->heldObj->heldByPlayerIndex != 0) { drop_and_set_mario_action(gMarioState, ACT_IDLE, 0); } } diff --git a/src/pc/network/network.h b/src/pc/network/network.h index 151b3caf..12c6ea1c 100644 --- a/src/pc/network/network.h +++ b/src/pc/network/network.h @@ -52,7 +52,8 @@ struct SyncObject { bool hasStandardFields; float maxUpdateRate; u8 (*ignore_if_true)(void); - void (*on_received)(void); + void (*on_received_pre)(void); + void (*on_received_post)(void); void* extraFields[MAX_SYNC_OBJECT_FIELDS]; }; diff --git a/src/pc/network/packets/packet_object.c b/src/pc/network/packets/packet_object.c index 237f0e63..8be668c1 100644 --- a/src/pc/network/packets/packet_object.c +++ b/src/pc/network/packets/packet_object.c @@ -55,7 +55,8 @@ struct SyncObject* network_init_object(struct Object *o, float maxSyncDistance) so->hasStandardFields = (maxSyncDistance >= 0); so->maxUpdateRate = 0; so->ignore_if_true = NULL; - so->on_received = NULL; + so->on_received_pre = NULL; + so->on_received_post = NULL; so->syncDeathEvent = true; memset(so->extraFields, 0, sizeof(void*) * MAX_SYNC_OBJECT_FIELDS); @@ -370,6 +371,15 @@ void network_receive_object(struct Packet* p) { if (gMarioStates[0].heldObj == o) { return; } } + // trigger on-received callback + if (so->on_received_pre != NULL) { + extern struct Object* gCurrentObject; + struct Object* tmp = gCurrentObject; + gCurrentObject = so->o; + (*so->on_received_pre)(); + gCurrentObject = tmp; + } + // read the rest of the packet data packet_read_object_full_sync(p, o); packet_read_object_standard_fields(p, o); @@ -382,11 +392,11 @@ void network_receive_object(struct Packet* p) { } // trigger on-received callback - if (so->on_received != NULL) { + if (so->on_received_post != NULL) { extern struct Object* gCurrentObject; struct Object* tmp = gCurrentObject; gCurrentObject = so->o; - (*so->on_received)(); + (*so->on_received_post)(); gCurrentObject = tmp; } }