Synchronized teleports (e.g. flowerbed) and star collection

Fixed infinite packet_level_warp sending
This commit is contained in:
MysterD 2020-08-06 20:28:21 -07:00
parent b1651e96b6
commit a55f050051
8 changed files with 79 additions and 14 deletions

View File

@ -812,10 +812,17 @@ u32 interact_star_or_key(struct MarioState *m, UNUSED u32 interactType, struct O
m->usedObj = o; m->usedObj = o;
starIndex = (o->oBehParams >> 24) & 0x1F; starIndex = (o->oBehParams >> 24) & 0x1F;
if (m == &gMarioStates[0]) {
// sync the star collection
network_send_collect_star(m->numCoins, starIndex);
}
save_file_collect_star_or_key(m->numCoins, starIndex); save_file_collect_star_or_key(m->numCoins, starIndex);
m->numStars = s32 numStars = save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1);
save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1); for (int i = 0; i < 2; i++) {
gMarioStates[i].numStars = numStars;
}
if (!noExit) { if (!noExit) {
drop_queued_background_music(); drop_queued_background_music();
@ -859,6 +866,11 @@ u32 interact_bbh_entrance(struct MarioState *m, UNUSED u32 interactType, struct
u32 interact_warp(struct MarioState *m, UNUSED u32 interactType, struct Object *o) { u32 interact_warp(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
u32 action; u32 action;
if (m != &gMarioStates[0]) {
// don't do for remote players
return FALSE;
}
if (o->oInteractionSubtype & INT_SUBTYPE_FADING_WARP) { if (o->oInteractionSubtype & INT_SUBTYPE_FADING_WARP) {
action = m->action; action = m->action;
@ -1792,9 +1804,12 @@ void mario_process_interactions(struct MarioState *m) {
sDisplayingDoorText = FALSE; sDisplayingDoorText = FALSE;
} }
if (!(m->marioObj->collidedObjInteractTypes & INTERACT_WARP)) { if (!(m->marioObj->collidedObjInteractTypes & INTERACT_WARP)) {
if (m == &gMarioStates[0]) {
// limit to only local mario
sJustTeleported = FALSE; sJustTeleported = FALSE;
} }
} }
}
void check_death_barrier(struct MarioState *m) { void check_death_barrier(struct MarioState *m) {
if (m->pos[1] < m->floorHeight + 2048.0f) { if (m->pos[1] < m->floorHeight + 2048.0f) {

View File

@ -884,7 +884,6 @@ void initiate_delayed_warp(void) {
default: default:
warpNode = area_get_warp_node(sSourceWarpNodeId); warpNode = area_get_warp_node(sSourceWarpNodeId);
initiate_warp(warpNode->node.destLevel & 0x7F, warpNode->node.destArea, initiate_warp(warpNode->node.destLevel & 0x7F, warpNode->node.destArea,
warpNode->node.destNode, sDelayedWarpArg); warpNode->node.destNode, sDelayedWarpArg);

View File

@ -1436,8 +1436,11 @@ s32 act_teleport_fade_out(struct MarioState *m) {
} }
if (m->actionTimer++ == 20) { if (m->actionTimer++ == 20) {
if (m == &gMarioStates[0]) {
// only do for local player
level_trigger_warp(m, WARP_OP_TELEPORT); level_trigger_warp(m, WARP_OP_TELEPORT);
} }
}
stop_and_set_height_to_floor(m); stop_and_set_height_to_floor(m);

View File

@ -474,6 +474,7 @@ void save_file_reload(void) {
* If coin score is greater than the current high score, update it. * If coin score is greater than the current high score, update it.
*/ */
void save_file_collect_star_or_key(s16 coinScore, s16 starIndex) { void save_file_collect_star_or_key(s16 coinScore, s16 starIndex) {
s32 fileIndex = gCurrSaveFileNum - 1; s32 fileIndex = gCurrSaveFileNum - 1;
s32 courseIndex = gCurrCourseNum - 1; s32 courseIndex = gCurrCourseNum - 1;

View File

@ -110,6 +110,7 @@ void network_update(void) {
case PACKET_OBJECT: network_receive_object(&p); break; case PACKET_OBJECT: network_receive_object(&p); break;
case PACKET_LEVEL_WARP: network_receive_level_warp(&p); break; case PACKET_LEVEL_WARP: network_receive_level_warp(&p); break;
case PACKET_INSIDE_PAINTING: network_receive_inside_painting(&p); break; case PACKET_INSIDE_PAINTING: network_receive_inside_painting(&p); break;
case PACKET_COLLECT_STAR: network_receive_collect_star(&p); break;
default: printf("%s received unknown packet: %d\n", NETWORKTYPESTR, p.buffer[0]); default: printf("%s received unknown packet: %d\n", NETWORKTYPESTR, p.buffer[0]);
} }

View File

@ -20,6 +20,7 @@ enum PacketType {
PACKET_OBJECT, PACKET_OBJECT,
PACKET_LEVEL_WARP, PACKET_LEVEL_WARP,
PACKET_INSIDE_PAINTING, PACKET_INSIDE_PAINTING,
PACKET_COLLECT_STAR,
}; };
struct Packet { struct Packet {
@ -78,4 +79,6 @@ void network_receive_level_warp(struct Packet* p);
void network_update_inside_painting(void); void network_update_inside_painting(void);
void network_receive_inside_painting(struct Packet* p); void network_receive_inside_painting(struct Packet* p);
void network_send_collect_star(s16 coinScore, s16 starIndex);
void network_receive_collect_star(struct Packet* p);
#endif #endif

View File

@ -0,0 +1,39 @@
#include <stdio.h>
#include "../network.h"
#include "course_table.h"
extern s16 gCurrSaveFileNum;
extern s16 gCurrCourseNum;
void network_send_collect_star(s16 coinScore, s16 starIndex) {
struct Packet p;
packet_init(&p, PACKET_COLLECT_STAR, true);
packet_write(&p, &gCurrSaveFileNum, sizeof(s16));
packet_write(&p, &gCurrCourseNum, sizeof(s16));
packet_write(&p, &coinScore, sizeof(s16));
packet_write(&p, &starIndex, sizeof(s16));
network_send(&p);
}
void network_receive_collect_star(struct Packet* p) {
s16 coinScore, starIndex;
s16 lastSaveFileNum = gCurrSaveFileNum;
s16 lastCourseNum = gCurrCourseNum;
packet_read(p, &gCurrSaveFileNum, sizeof(s16));
packet_read(p, &gCurrCourseNum, sizeof(s16));
packet_read(p, &coinScore, sizeof(s16));
packet_read(p, &starIndex, sizeof(s16));
save_file_collect_star_or_key(coinScore, starIndex);
s32 numStars = save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1);
for (int i = 0; i < 2; i++) {
gMarioStates[i].numStars = numStars;
}
gCurrSaveFileNum = lastSaveFileNum;
gCurrCourseNum = lastCourseNum;
}

View File

@ -3,7 +3,7 @@
#include "src/game/level_update.h" #include "src/game/level_update.h"
#include "src/game/area.h" #include "src/game/area.h"
int warpTimeout = 0; int matchCount = 0;
void network_send_level_warp(void) { void network_send_level_warp(void) {
struct Packet p; struct Packet p;
@ -17,7 +17,6 @@ void network_send_level_warp(void) {
} }
void network_receive_level_warp(struct Packet* p) { void network_receive_level_warp(struct Packet* p) {
if (warpTimeout != 0) { return; }
s16 remotePlayMode; s16 remotePlayMode;
s16 remoteLevelNum; s16 remoteLevelNum;
s32 remoteWarpArg; s32 remoteWarpArg;
@ -28,16 +27,25 @@ void network_receive_level_warp(struct Packet* p) {
packet_read(p, &remoteWarpArg, 4); packet_read(p, &remoteWarpArg, 4);
packet_read(p, &remoteWarpNodeId, 2); packet_read(p, &remoteWarpNodeId, 2);
if (gCurrLevelNum == remoteLevelNum) { bool matching = (remoteLevelNum == gCurrLevelNum)
&& (remoteWarpArg == sDelayedWarpArg)
&& (remoteWarpNodeId == sSourceWarpNodeId);
if (matching) {
if (sCurrPlayMode == PLAY_MODE_SYNC_LEVEL) { if (sCurrPlayMode == PLAY_MODE_SYNC_LEVEL) {
// our levels match now, lets play! // our levels match now, lets play!
set_play_mode(PLAY_MODE_NORMAL); set_play_mode(PLAY_MODE_NORMAL);
set_menu_mode((s16)-1); set_menu_mode((s16)-1);
} }
// our levels match, make sure the other player knows that // our levels match, make sure the other player knows that
if (matchCount++ < 3) {
network_send_level_warp(); network_send_level_warp();
} else {
matchCount = 0;
}
return; return;
} }
matchCount = 0;
// remote isn't trying to sync, don't warp // remote isn't trying to sync, don't warp
if (remotePlayMode != PLAY_MODE_SYNC_LEVEL) { return; } if (remotePlayMode != PLAY_MODE_SYNC_LEVEL) { return; }
@ -50,12 +58,8 @@ void network_receive_level_warp(struct Packet* p) {
sDelayedWarpArg = remoteWarpArg; sDelayedWarpArg = remoteWarpArg;
sSourceWarpNodeId = remoteWarpNodeId; sSourceWarpNodeId = remoteWarpNodeId;
sDelayedWarpOp = WARP_OP_FORCE_SYNC; sDelayedWarpOp = WARP_OP_FORCE_SYNC;
// don't repeat the warp too quickly
warpTimeout = 2;
} }
void network_update_level_warp(void) { void network_update_level_warp(void) {
network_send_level_warp(); network_send_level_warp();
if (warpTimeout > 0) { warpTimeout--; }
} }