Synchronized wing cap and hidden trigger pickups

This commit is contained in:
MysterD 2020-08-10 23:38:58 -07:00
parent f1789d4e78
commit 2177094730
5 changed files with 107 additions and 2 deletions

View file

@ -35,7 +35,7 @@ void bhv_hidden_star_loop(void) {
/* TODO: this is likely not a checkpoint but a Secret */
void bhv_hidden_star_trigger_loop(void) {
struct Object *hiddenStar;
if (obj_check_if_collided_with_object(o, gMarioObject) == 1) {
if ((o->oInteractStatus & INT_STATUS_INTERACTED) || obj_check_if_collided_with_object(o, gMarioObject) == 1) {
hiddenStar = cur_obj_nearest_object_with_behavior(bhvHiddenStar);
if (hiddenStar != NULL) {
hiddenStar->oHiddenStarTriggerCounter++;
@ -53,6 +53,9 @@ void bhv_hidden_star_trigger_loop(void) {
}
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
if (!(o->oInteractStatus & INT_STATUS_INTERACTED)) {
network_send_collect_item(o);
}
}
}

View file

@ -1586,6 +1586,9 @@ u32 interact_hoot(struct MarioState *m, UNUSED u32 interactType, struct Object *
}
u32 interact_cap(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
// only allow for local
if (m != &gMarioStates[0]) { return; }
u32 capFlag = get_mario_cap_flag(o);
u16 capMusic = 0;
u16 capTime = 0;
@ -1631,7 +1634,7 @@ u32 interact_cap(struct MarioState *m, UNUSED u32 interactType, struct Object *o
if (capMusic != 0) {
play_cap_music(capMusic);
}
network_send_collect_item(o);
return TRUE;
}

View file

@ -78,6 +78,7 @@ void network_update(void) {
case PACKET_INSIDE_PAINTING: network_receive_inside_painting(&p); break;
case PACKET_COLLECT_STAR: network_receive_collect_star(&p); break;
case PACKET_COLLECT_COIN: network_receive_collect_coin(&p); break;
case PACKET_COLLECT_ITEM: network_receive_collect_item(&p); break;
default: printf("%s received unknown packet: %d\n", NETWORKTYPESTR, p.buffer[0]);
}

View file

@ -24,6 +24,7 @@ enum PacketType {
PACKET_INSIDE_PAINTING,
PACKET_COLLECT_STAR,
PACKET_COLLECT_COIN,
PACKET_COLLECT_ITEM,
};
struct Packet {
@ -102,4 +103,7 @@ void network_receive_collect_star(struct Packet* p);
void network_send_collect_coin(struct Object* o);
void network_receive_collect_coin(struct Packet* p);
void network_send_collect_item(struct Object* o);
void network_receive_collect_item(struct Packet* p);
#endif

View file

@ -0,0 +1,94 @@
#include <stdio.h>
#include "../network.h"
#include "object_fields.h"
#include "object_constants.h"
#include "behavior_table.h"
#include "course_table.h"
#include "src/game/interaction.h"
#include "src/engine/math_util.h"
static u8 localItemId = 1;
// two-player hack: the remoteItemId stuff is only valid for the one remote player
// will need to be extended if MAX_PLAYERS is ever increased
#define MAX_REMOTE_ITEM_IDS 16
static u8 remoteItemIds[MAX_REMOTE_ITEM_IDS] = { 0 };
static u8 onRemoteItemId = 0;
static f32 dist_to_pos(struct Object* o, f32* pos) {
f32 x = (f32)o->oPosX - pos[0]; x *= x;
f32 y = (f32)o->oPosY - pos[1]; y *= y;
f32 z = (f32)o->oPosZ - pos[2]; z *= z;
return (f32)sqrt(x + y + z);
}
static struct Object* find_nearest_item(const BehaviorScript *behavior, f32* pos, float minDist) {
uintptr_t *behaviorAddr = segmented_to_virtual(behavior);
struct Object *closestObj = NULL;
struct Object *obj;
struct ObjectNode *listHead;
extern struct ObjectNode *gObjectLists;
listHead = &gObjectLists[get_object_list_from_behavior(behaviorAddr)];
obj = (struct Object *) listHead->next;
while (obj != (struct Object *) listHead) {
if (obj->behavior == behaviorAddr && obj->activeFlags != ACTIVE_FLAG_DEACTIVATED) {
f32 objDist = dist_to_pos(obj, pos);
if (objDist < minDist) {
closestObj = obj;
minDist = objDist;
}
}
obj = (struct Object *) obj->header.next;
}
return closestObj;
}
void network_send_collect_item(struct Object* o) {
enum BehaviorId behaviorId = get_id_from_behavior(o->behavior);
struct Packet p;
packet_init(&p, PACKET_COLLECT_ITEM, true);
packet_write(&p, &localItemId, sizeof(u8));
packet_write(&p, &behaviorId, sizeof(enum BehaviorId));
packet_write(&p, &o->oPosX, sizeof(f32) * 3);
network_send(&p);
localItemId++;
}
void network_receive_collect_item(struct Packet* p) {
u8 remoteItemId = 0;
enum BehaviorId behaviorId;
void* behavior = NULL;
f32 pos[3] = { 0 };
packet_read(p, &remoteItemId, sizeof(u8));
packet_read(p, &behaviorId, sizeof(enum BehaviorId));
packet_read(p, &pos, sizeof(f32) * 3);
behavior = get_behavior_from_id(behaviorId);
// check if remote item id has already been seen
for (int i = 0; i < MAX_REMOTE_ITEM_IDS; i++) {
if (remoteItemIds[i] == remoteItemId) {
// we already saw this item!
return;
}
}
// cache the seen id
remoteItemIds[onRemoteItemId] = remoteItemId;
onRemoteItemId = (onRemoteItemId + 1) % MAX_REMOTE_ITEM_IDS;
// make sure it's valid
if (behavior == NULL) { return; }
// find the item
struct Object* item = find_nearest_item(behavior, pos, 1000);
if (item == NULL) { return; }
// destroy item
item->oInteractStatus = INT_STATUS_INTERACTED;
}