From 3070d2bfdb49134acda474694934d1cc2c6c4f79 Mon Sep 17 00:00:00 2001 From: MysterD Date: Fri, 11 Sep 2020 22:14:42 -0700 Subject: [PATCH] Prevent two players from holding the same object Fixes #40 --- src/game/mario.c | 8 ++++++++ src/game/mario.h | 1 + src/game/mario_actions_automatic.c | 3 +-- src/pc/network/packets/packet_object.c | 8 +++++--- src/pc/network/packets/packet_player.c | 8 +++++++- 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/game/mario.c b/src/game/mario.c index cefef77b5..352bc6efd 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -1492,6 +1492,9 @@ void update_mario_inputs(struct MarioState *m) { & (INT_STATUS_HOOT_GRABBED_BY_MARIO | INT_STATUS_MARIO_UNK1 | INT_STATUS_MARIO_UNK4)) { m->input |= INPUT_UNKNOWN_10; } + if (m->heldObj != NULL) { + m->heldObj->heldByPlayerIndex = 0; + } } // This function is located near other unused trampoline functions, @@ -1973,6 +1976,11 @@ s32 execute_mario_action(UNUSED struct Object *o) { return 0; } +s32 force_idle_state(struct MarioState* m) { + u8 underWater = (m->pos[1] < ((f32)m->waterLevel)); + return set_mario_action(m, underWater ? ACT_WATER_IDLE : ACT_IDLE, 0); +} + /************************************************** * INITIALIZATION * **************************************************/ diff --git a/src/game/mario.h b/src/game/mario.h index 3d927d74d..1683ecda0 100644 --- a/src/game/mario.h +++ b/src/game/mario.h @@ -49,6 +49,7 @@ s32 check_common_hold_action_exits(struct MarioState *m); s32 transition_submerged_to_walking(struct MarioState *m); s32 set_water_plunge_action(struct MarioState *m); s32 execute_mario_action(UNUSED struct Object *o); +s32 force_idle_state(struct MarioState* m); void init_mario(void); void init_mario_from_save_file(void); diff --git a/src/game/mario_actions_automatic.c b/src/game/mario_actions_automatic.c index 2415c7e8f..77772d7e0 100644 --- a/src/game/mario_actions_automatic.c +++ b/src/game/mario_actions_automatic.c @@ -951,8 +951,7 @@ s32 act_bubbled(struct MarioState* m) { m->vel[1] = 0; m->vel[2] = 0; m->marioObj->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE; - u8 underWater = (m->pos[1] < ((f32)m->waterLevel)); - return set_mario_action(m, underWater ? ACT_WATER_IDLE : ACT_IDLE, 0); + return force_idle_state(m); } return FALSE; diff --git a/src/pc/network/packets/packet_object.c b/src/pc/network/packets/packet_object.c index 73b28f82c..97267aee3 100644 --- a/src/pc/network/packets/packet_object.c +++ b/src/pc/network/packets/packet_object.c @@ -364,10 +364,12 @@ void network_receive_object(struct Packet* p) { if (so == NULL) { return; } struct Object* o = so->o; if (!network_sync_object_initialized(o)) { return; } - if (gMarioStates[0].heldByObj == o) { return; } // make sure no one can update an object we're holding - if (gMarioStates[0].heldObj == o) { return; } + if (gNetworkType == NT_SERVER) { // two-player hack: needs priority + if (gMarioStates[0].heldObj == o) { return; } + if (gMarioStates[0].heldByObj == o) { return; } + } // read the rest of the packet data packet_read_object_full_sync(p, o); @@ -424,7 +426,7 @@ void network_update_objects(void) { float dist = player_distance(&gMarioStates[0], so->o); if (so->maxSyncDistance != SYNC_DISTANCE_INFINITE && dist > so->maxSyncDistance) { continue; } float updateRate = dist / 1000.0f; - if (gMarioStates[0].heldObj == so->o) { updateRate = 0; } + if (gMarioStates[0].heldObj == so->o) { updateRate = 0.33f; } // set max and min update rate if (so->maxUpdateRate > 0 && updateRate < so->maxUpdateRate) { updateRate = so->maxUpdateRate; } diff --git a/src/pc/network/packets/packet_player.c b/src/pc/network/packets/packet_player.c index 05d47fd6e..8e1641678 100644 --- a/src/pc/network/packets/packet_player.c +++ b/src/pc/network/packets/packet_player.c @@ -3,7 +3,9 @@ #include "object_fields.h" #include "object_constants.h" #include "sm64.h" -#include "src/audio/external.h" +#include "game/interaction.h" +#include "game/mario.h" +#include "audio/external.h" #define SET_BIT(val, num) ((((u8)(val)) & 0x01) << (num)); #define GET_BIT(val, num) (((val) >> (num)) & 0x01) @@ -81,6 +83,10 @@ void network_receive_player(struct Packet* p) { if (heldSyncID != 0 && gSyncObjects[heldSyncID].o != NULL) { // TODO: do we have to move graphics nodes around to make this visible? struct Object* heldObj = gSyncObjects[heldSyncID].o; + if (gMarioStates[0].heldObj == heldObj && gNetworkType == NT_CLIENT) { // two-player hack: needs priority + mario_drop_held_object(&gMarioStates[0]); + force_idle_state(&gMarioStates[0]); + } gMarioStates[1].heldObj = heldObj; heldObj->oHeldState = HELD_HELD; heldObj->heldByPlayerIndex = 1;