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;
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);
m->numStars =
save_file_get_total_star_count(gCurrSaveFileNum - 1, COURSE_MIN - 1, COURSE_MAX - 1);
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;
}
if (!noExit) {
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 action;
if (m != &gMarioStates[0]) {
// don't do for remote players
return FALSE;
}
if (o->oInteractionSubtype & INT_SUBTYPE_FADING_WARP) {
action = m->action;
@ -1792,7 +1804,10 @@ void mario_process_interactions(struct MarioState *m) {
sDisplayingDoorText = FALSE;
}
if (!(m->marioObj->collidedObjInteractTypes & INTERACT_WARP)) {
sJustTeleported = FALSE;
if (m == &gMarioStates[0]) {
// limit to only local mario
sJustTeleported = FALSE;
}
}
}

View File

@ -884,9 +884,8 @@ void initiate_delayed_warp(void) {
default:
warpNode = area_get_warp_node(sSourceWarpNodeId);
initiate_warp(warpNode->node.destLevel & 0x7F, warpNode->node.destArea,
warpNode->node.destNode, sDelayedWarpArg);
warpNode->node.destNode, sDelayedWarpArg);
check_if_should_set_warp_checkpoint(&warpNode->node);
if (sWarpDest.type != WARP_TYPE_CHANGE_LEVEL) {

View File

@ -1436,7 +1436,10 @@ s32 act_teleport_fade_out(struct MarioState *m) {
}
if (m->actionTimer++ == 20) {
level_trigger_warp(m, WARP_OP_TELEPORT);
if (m == &gMarioStates[0]) {
// only do for local player
level_trigger_warp(m, WARP_OP_TELEPORT);
}
}
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.
*/
void save_file_collect_star_or_key(s16 coinScore, s16 starIndex) {
s32 fileIndex = gCurrSaveFileNum - 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_LEVEL_WARP: network_receive_level_warp(&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]);
}

View File

@ -20,6 +20,7 @@ enum PacketType {
PACKET_OBJECT,
PACKET_LEVEL_WARP,
PACKET_INSIDE_PAINTING,
PACKET_COLLECT_STAR,
};
struct Packet {
@ -78,4 +79,6 @@ void network_receive_level_warp(struct Packet* p);
void network_update_inside_painting(void);
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

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