Synchronized mips/toad star spawning

This commit is contained in:
MysterD 2020-10-02 21:05:02 -07:00
parent 525ef6db17
commit b673457a48
15 changed files with 108 additions and 11 deletions

View file

@ -56,6 +56,8 @@ s16 gCurrLevelNum = LEVEL_MIN;
u32 gSpawnedStarDefault[8] = { 0 };
u8 gSpawnedStarDefaultCount = 0;
u32 gSpawnedStarNLE[8] = { 0 };
u8 gSpawnedStarNLECount = 0;
u8 gSpawnedStarRedCoin = 0;
u8 gSpawnedStarHidden = 0;

View file

@ -140,6 +140,8 @@ extern s16 gCurrLevelNum;
extern u32 gSpawnedStarDefault[];
extern u8 gSpawnedStarDefaultCount;
extern u32 gSpawnedStarNLE[];
extern u8 gSpawnedStarNLECount;
extern u8 gSpawnedStarRedCoin;
extern u8 gSpawnedStarHidden;

View file

@ -44,6 +44,7 @@
#include "spawn_object.h"
#include "spawn_sound.h"
#include "thread6.h"
#include "area.h"
#define o gCurrentObject

View file

@ -2,7 +2,7 @@
#define BEHAVIOR_ACTIONS_H
void spawn_mist_particles_variable(s32 count, s32 offsetY, f32 size);
void bhv_spawn_star_no_level_exit(struct Object*,u32);
void bhv_spawn_star_no_level_exit(struct Object* object, u32 params, u8 networkSendEvent);
void bhv_star_door_loop_2(void);
void spawn_triangle_break_particles(s16 numTris, s16 triModel, f32 triSize, s16 triAnimState);

View file

@ -211,7 +211,7 @@ void bhv_mips_act_idle(void) {
// Spawn a star if he was just picked up for the first time.
if (o->oMipsStarStatus == MIPS_STAR_STATUS_SHOULD_SPAWN_STAR) {
bhv_spawn_star_no_level_exit(o, o->oBehParams2ndByte + 3);
bhv_spawn_star_no_level_exit(o, o->oBehParams2ndByte + 3, TRUE);
o->oMipsStarStatus = MIPS_STAR_STATUS_ALREADY_SPAWNED_STAR;
}
}

View file

@ -140,9 +140,20 @@ void bhv_spawned_star_loop(void) {
o->oInteractStatus = 0;
}
void bhv_spawn_star_no_level_exit(struct Object* object, u32 sp20) {
void bhv_spawn_star_no_level_exit(struct Object* object, u32 sp20, u8 networkSendEvent) {
// de-duplication checking
for (int i = 0; i < gSpawnedStarNLECount; i++) {
if (gSpawnedStarNLE[i] == sp20) { return; }
}
if (gSpawnedStarNLECount < 8) {
gSpawnedStarNLE[gSpawnedStarNLECount++] = sp20;
}
struct Object *sp1C = spawn_object(object, MODEL_STAR, bhvSpawnedStarNoLevelExit);
sp1C->oBehParams = sp20 << 24;
sp1C->oInteractionSubtype = INT_SUBTYPE_NO_EXIT;
obj_set_angle(sp1C, 0, 0, 0);
if (networkSendEvent) {
network_send_spawn_star_nle(object, sp20);
}
}

View file

@ -803,7 +803,7 @@ u32 interact_coin(struct MarioState *m, UNUSED u32 interactType, struct Object *
if (COURSE_IS_MAIN_COURSE(gCurrCourseNum) && m->numCoins - o->oDamageOrCoinValue < 100
&& m->numCoins >= 100) {
bhv_spawn_star_no_level_exit(m->marioObj, 6);
bhv_spawn_star_no_level_exit(m->marioObj, 6, FALSE);
}
if (o->oDamageOrCoinValue >= 2) {

View file

@ -1312,8 +1312,10 @@ s32 init_level(void) {
for (int i = 0; i < 8; i++) {
gSpawnedStarDefault[i] = 0;
gSpawnedStarNLE[i] = 0;
}
gSpawnedStarDefaultCount = 0;
gSpawnedStarNLECount = 0;
gSpawnedStarRedCoin = 0;
gSpawnedStarHidden = 0;

View file

@ -131,15 +131,15 @@ static void toad_message_talking(void) {
switch (gCurrentObject->oToadMessageDialogId) {
case TOAD_STAR_1_DIALOG:
gCurrentObject->oToadMessageDialogId = TOAD_STAR_1_DIALOG_AFTER;
bhv_spawn_star_no_level_exit(gMarioStates[0].marioObj, 0);
bhv_spawn_star_no_level_exit(gMarioStates[0].marioObj, 0, TRUE);
break;
case TOAD_STAR_2_DIALOG:
gCurrentObject->oToadMessageDialogId = TOAD_STAR_2_DIALOG_AFTER;
bhv_spawn_star_no_level_exit(gMarioStates[0].marioObj, 1);
bhv_spawn_star_no_level_exit(gMarioStates[0].marioObj, 1, TRUE);
break;
case TOAD_STAR_3_DIALOG:
gCurrentObject->oToadMessageDialogId = TOAD_STAR_3_DIALOG_AFTER;
bhv_spawn_star_no_level_exit(gMarioStates[0].marioObj, 2);
bhv_spawn_star_no_level_exit(gMarioStates[0].marioObj, 2, TRUE);
break;
}
}

View file

@ -22,6 +22,16 @@ u8 network_player_connected_count(void) {
return count;
}
struct NetworkPlayer* network_player_from_global_index(u8 globalIndex) {
for (int i = 1; i < MAX_PLAYERS; i++) {
if (!gNetworkPlayers[i].connected) { continue; }
if (gNetworkPlayers[i].globalIndex == globalIndex) {
return &gNetworkPlayers[i];
}
}
return NULL;
}
void network_player_update(void) {
float elapsed = (clock() - gLastNetworkSend) / (float)CLOCKS_PER_SEC;
if (elapsed > NETWORK_PLAYER_TIMEOUT / 3.0f) {

View file

@ -33,6 +33,7 @@ extern struct NetworkPlayer* gNetworkPlayerServer;
bool network_player_any_connected(void);
u8 network_player_connected_count(void);
struct NetworkPlayer* network_player_from_global_index(u8 globalIndex);
void network_player_update(void);
u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex);
u8 network_player_disconnected(u8 globalIndex);

View file

@ -23,6 +23,7 @@ void packet_receive(struct Packet* p) {
case PACKET_OBJECT: network_receive_object(p); break;
case PACKET_SPAWN_OBJECTS: network_receive_spawn_objects(p); break;
case PACKET_SPAWN_STAR: network_receive_spawn_star(p); break;
case PACKET_SPAWN_STAR_NLE: network_receive_spawn_star_nle(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;

View file

@ -15,6 +15,7 @@ enum PacketType {
PACKET_OBJECT,
PACKET_SPAWN_OBJECTS,
PACKET_SPAWN_STAR,
PACKET_SPAWN_STAR_NLE,
PACKET_LEVEL_WARP,
PACKET_INSIDE_PAINTING,
PACKET_COLLECT_STAR,
@ -93,6 +94,8 @@ void network_receive_spawn_objects(struct Packet* p);
// packet_spawn_star.c
void network_send_spawn_star(struct Object* o, u8 starType, f32 x, f32 y, f32 z, u32 behParams);
void network_receive_spawn_star(struct Packet* p);
void network_send_spawn_star_nle(struct Object* o, u32 params);
void network_receive_spawn_star_nle(struct Packet* p);
// packet_level_warp.c
void network_send_level_warp_begin(void);

View file

@ -10,7 +10,7 @@
#include "src/game/object_helpers.h"
// defined in sparkle_spawn_star.inc.c
void bhv_spawn_star_no_level_exit(struct Object* object, u32 sp20);
void bhv_spawn_star_no_level_exit(struct Object* object, u32 sp20, u8 networkSendEvent);
static u8 localCoinId = 1;
@ -111,7 +111,7 @@ void network_receive_collect_coin(struct Packet* p) {
if (COURSE_IS_MAIN_COURSE(gCurrCourseNum)
&& gMarioStates[0].numCoins - coin->oDamageOrCoinValue < 100
&& gMarioStates[0].numCoins >= 100) {
bhv_spawn_star_no_level_exit(gMarioStates[1].marioObj, 6);
bhv_spawn_star_no_level_exit(gMarioStates[1].marioObj, 6, FALSE);
}
return;
@ -125,6 +125,6 @@ SANITY_CHECK_COINS:;
if (COURSE_IS_MAIN_COURSE(gCurrCourseNum)
&& oldCoinCount < 100
&& gMarioStates[0].numCoins >= 100) {
bhv_spawn_star_no_level_exit(gMarioStates[1].marioObj, 6);
bhv_spawn_star_no_level_exit(gMarioStates[1].marioObj, 6, FALSE);
}
}

View file

@ -1,10 +1,15 @@
#include <stdio.h>
#include "../network.h"
#include "object_fields.h"
#include "behavior_data.h"
#include "src/game/behavior_actions.h"
#include "pc/debuglog.h"
extern struct Object* gCurrentObject;
static u8 txSeqId = 0;
static u8 rxLastSeqId = (u8)-1;
void network_send_spawn_star(struct Object* o, u8 starType, f32 x, f32 y, f32 z, u32 behParams) {
struct Packet p;
packet_init(&p, PACKET_SPAWN_STAR, true, true);
@ -38,7 +43,7 @@ void network_receive_spawn_star(struct Packet* p) {
case 0: o = spawn_default_star(x, y, z); break;
case 1: o = spawn_red_coin_cutscene_star(x, y, z); break;
case 2: o = spawn_no_exit_star(x, y, z); break;
default: printf("UNKNOWN SPAWN STAR %d\n", starType);
default: LOG_ERROR("UNKNOWN SPAWN STAR %d", starType);
}
gCurrentObject->oBehParams = oldBehParams;
@ -47,3 +52,62 @@ void network_receive_spawn_star(struct Packet* p) {
packet_read(p, &o->oHomeX, sizeof(u32) * 3);
}
}
void network_send_spawn_star_nle(struct Object* o, u32 params) {
u8 globalIndex = UNKNOWN_GLOBAL_INDEX;
if (o->behavior == bhvMario) {
u8 localIndex = o->oBehParams - 1;
globalIndex = gNetworkPlayers[localIndex].globalIndex;
}
struct Packet p;
packet_init(&p, PACKET_SPAWN_STAR_NLE, true, true);
packet_write(&p, &txSeqId, sizeof(u8));
packet_write(&p, &globalIndex, sizeof(u8));
packet_write(&p, &o->oSyncID, sizeof(u32));
packet_write(&p, &params, sizeof(u32));
network_send(&p);
txSeqId++;
}
void network_receive_spawn_star_nle(struct Packet* p) {
u8 seqId = 0;
u8 globalIndex = UNKNOWN_GLOBAL_INDEX;
u32 syncId = 0;
u32 params = 0;
packet_read(p, &seqId, sizeof(u8));
packet_read(p, &globalIndex, sizeof(u8));
packet_read(p, &syncId, sizeof(u32));
packet_read(p, &params, sizeof(u32));
// de-dup
if (seqId == rxLastSeqId) {
LOG_INFO("Already seen seqId %d", seqId);
return;
}
// grab network player first
struct Object* object = NULL;
if (globalIndex != UNKNOWN_GLOBAL_INDEX) {
struct NetworkPlayer* np = network_player_from_global_index(globalIndex);
if (np != NULL) {
object = gMarioStates[np->localIndex].marioObj;
}
}
// check for sync id
if (object == NULL) {
object = gSyncObjects[syncId].o;
}
// sanity check object
if (object == NULL) {
LOG_ERROR("Could not find object to attach to. %d %d", globalIndex, syncId);
return;
}
// spawn
bhv_spawn_star_no_level_exit(object, params, FALSE);
}