Eject a player if more than one is in the cannon

Two players in the same cannon was causing softlocks and general
insanity. Now this should be fixed. Also prevented players from being
able to push or attack a player inside of a cannon.
This commit is contained in:
MysterD 2020-09-08 16:12:11 -07:00
parent 58a3156180
commit cf732c7beb
4 changed files with 46 additions and 1 deletions

View file

@ -146,14 +146,47 @@ u8 unused0EA1FC[] = { 2, 0, 0, 0, 0, 0, 0, 0, 63, 128, 0, 0, 2, 0, 0, 0
63, 128, 0, 0, 2, 0, 0, 0, 65, 160, 0, 0, 63, 128, 0, 0, 2, 0, 0, 0,
65, 160, 0, 0, 63, 128, 0, 0, 8, 0, 0, 0, 65, 32, 0, 0, 63, 128, 0, 0 };
u8 cannon_ignore_remote_updates(struct Object* object) { return object->oCannonIsLocal; }
u8 cannon_ignore_remote_updates(struct Object* object) {
// two-player hack
return ((gNetworkType == NT_SERVER) && object->oCannonIsLocal);
}
static void cannon_on_received(void) {
// check if we're on in the cannon too
struct MarioState* m = &gMarioStates[0];
if (m->action != ACT_IN_CANNON) { return; }
if (m->interactObj != o) { return; }
// two-player hack
if (gNetworkType == NT_SERVER) { return; }
// eject the player by shooting out of the cannon weakly
m->forwardVel = 10.0f * coss(m->faceAngle[0]);
m->vel[1] = 10.0f * sins(m->faceAngle[0]);
m->pos[0] += 120.0f * coss(m->faceAngle[0]) * sins(m->faceAngle[1]);
m->pos[1] += 120.0f * sins(m->faceAngle[0]);
m->pos[2] += 120.0f * coss(m->faceAngle[0]) * coss(m->faceAngle[1]);
set_mario_action(m, ACT_SHOT_FROM_CANNON, 0);
// reset things that got messed up
m->marioObj->header.gfx.node.flags |= GRAPH_RENDER_ACTIVE;
reset_camera(gCamera);
o->oCannonIsLocal = FALSE;
cur_obj_become_tangible();
cur_obj_enable_rendering();
}
void bhv_cannon_base_loop(void) {
if (!network_sync_object_initialized(o)) {
struct SyncObject* so = network_init_object(o, SYNC_DISTANCE_ONLY_EVENTS);
so->ignore_if_true = &cannon_ignore_remote_updates;
so->on_received = &cannon_on_received;
network_init_object_field(o, &o->oAction);
network_init_object_field(o, &o->oPrevAction);
network_init_object_field(o, &o->oTimer);
network_init_object_field(o, &o->oPosX);
network_init_object_field(o, &o->oPosY);
network_init_object_field(o, &o->oPosZ);
network_init_object_field(o, &o->oCannonUnk10C);
network_init_object_field(o, &o->oCannonUnk10C);
network_init_object_field(o, &o->oCannonUnkF8);
network_init_object_field(o, &o->oCannonUnkF4);

View file

@ -1233,6 +1233,7 @@ u32 interact_player(struct MarioState* m, UNUSED u32 interactType, struct Object
// attacked
u8 isInCutscene = ((m->action & ACT_GROUP_MASK) == ACT_GROUP_CUTSCENE) || ((m2->action & ACT_GROUP_MASK) == ACT_GROUP_CUTSCENE);
isInCutscene = isInCutscene || (m->action == ACT_IN_CANNON) || (m2->action == ACT_IN_CANNON);
u8 isInvulnerable = (m2->action & ACT_FLAG_INVULNERABLE) || m2->invincTimer != 0 || m2->hurtCounter != 0 || isInCutscene;
if ((interaction & INT_ANY_ATTACK) && !(interaction & INT_HIT_FROM_ABOVE) && !isInvulnerable) {

View file

@ -62,6 +62,7 @@ struct SyncObject {
bool hasStandardFields;
float maxUpdateRate;
u8 (*ignore_if_true)(struct Object*);
void (*on_received)(void);
void* extraFields[MAX_SYNC_OBJECT_FIELDS];
};

View file

@ -55,6 +55,7 @@ struct SyncObject* network_init_object(struct Object *o, float maxSyncDistance)
so->hasStandardFields = (maxSyncDistance >= 0);
so->maxUpdateRate = 0;
so->ignore_if_true = NULL;
so->on_received = NULL;
so->syncDeathEvent = true;
memset(so->extraFields, 0, sizeof(void*) * MAX_SYNC_OBJECT_FIELDS);
@ -372,6 +373,15 @@ void network_receive_object(struct Packet* p) {
if (o->activeFlags == ACTIVE_FLAG_DEACTIVATED) {
network_forget_sync_object(so);
}
// trigger on-received callback
if (so->on_received != NULL) {
extern struct Object* gCurrentObject;
struct Object* tmp = gCurrentObject;
gCurrentObject = so->o;
(*so->on_received)();
gCurrentObject = tmp;
}
}
void network_forget_sync_object(struct SyncObject* so) {