Synchronized teleports (e.g. flowerbed) and star collection
Fixed infinite packet_level_warp sending
This commit is contained in:
parent
b1651e96b6
commit
a55f050051
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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--; }
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue