PVP improvements

Removed angle check for punch/kick
Compensated for lag, so interactions favor the attacker now
This commit is contained in:
MysterD 2023-04-02 18:26:00 -07:00
parent 8f2f46fbdc
commit f593a263aa
7 changed files with 105 additions and 31 deletions

View file

@ -491,6 +491,7 @@ void read_controller_inputs(void) {
controller->stickY = 0;
controller->stickMag = 0;
}
}
// For some reason, player 1's inputs are copied to player 3's port. This

View file

@ -202,10 +202,7 @@ u32 determine_interaction(struct MarioState *m, struct Object *o) {
// hack: make water punch actually do something
if (interaction == 0 && m->action == ACT_WATER_PUNCH && o->oInteractType & INTERACT_PLAYER) {
s16 dYawToObject = mario_obj_angle_to_object(m, o) - m->faceAngle[1];
if (-0x2AAA <= dYawToObject && dYawToObject <= 0x2AAA) {
interaction = INT_PUNCH;
}
interaction = INT_PUNCH;
}
if (interaction == 0 && action & ACT_FLAG_ATTACKING) {
@ -214,15 +211,11 @@ u32 determine_interaction(struct MarioState *m, struct Object *o) {
if (m->flags & MARIO_PUNCHING) {
// 120 degrees total, or 60 each way
if (-0x2AAA <= dYawToObject && dYawToObject <= 0x2AAA) {
interaction = INT_PUNCH;
}
interaction = INT_PUNCH;
}
if (m->flags & MARIO_KICKING) {
// 120 degrees total, or 60 each way
if (-0x2AAA <= dYawToObject && dYawToObject <= 0x2AAA) {
interaction = INT_KICK;
}
interaction = INT_KICK;
}
if (m->flags & MARIO_TRIPPING) {
// 180 degrees total, or 90 each way
@ -1289,6 +1282,7 @@ static u8 resolve_player_collision(struct MarioState* m, struct MarioState* m2)
f32 aboveFloor = m2->pos[1] - m2->floorHeight;
if ((interaction & INT_HIT_FROM_ABOVE) && (aboveFloor < 1)) {
if (m2->playerIndex == 0) {
network_player_local_restore_lag_state();
m2->squishTimer = max(m2->squishTimer, 4);
}
f32 velY;
@ -1380,22 +1374,31 @@ u32 interact_player(struct MarioState* m, UNUSED u32 interactType, struct Object
if (m2 == NULL) { return FALSE; }
if (m2->action == ACT_JUMBO_STAR_CUTSCENE) { return FALSE; }
// set my local player to the state I was in when they attacked
if (m2->playerIndex == 0) {
network_player_local_set_lag_state(&gNetworkPlayers[m->playerIndex]);
}
// vanish cap players can't interact
u32 vanishFlags = (MARIO_VANISH_CAP | MARIO_CAP_ON_HEAD);
if ((m->flags & vanishFlags) == vanishFlags) {
network_player_local_restore_lag_state();
return FALSE;
}
if ((m2->flags & vanishFlags) == vanishFlags) {
network_player_local_restore_lag_state();
return FALSE;
}
// don't do further interactions if we've hopped on top
if (resolve_player_collision(m, m2)) {
network_player_local_restore_lag_state();
return FALSE;
}
// don't attack each other on level load
if (gCurrentArea == NULL || gCurrentArea->localAreaTimer < 60) {
network_player_local_restore_lag_state();
return FALSE;
}
@ -1404,8 +1407,10 @@ u32 interact_player(struct MarioState* m, UNUSED u32 interactType, struct Object
if ((interaction & INT_ANY_ATTACK) && !(interaction & INT_HIT_FROM_ABOVE) && passes_pvp_interaction_checks(m, m2)) {
bool allow = true;
smlua_call_event_hooks_mario_params_ret_bool(HOOK_ALLOW_PVP_ATTACK, m, m2, &allow);
if (!allow) {
// Lua blocked the interaction
network_player_local_restore_lag_state();
return false;
}
@ -1431,17 +1436,24 @@ u32 interact_player(struct MarioState* m, UNUSED u32 interactType, struct Object
}
}
// restore to current state
u32 m2action = m2->action;
u32 m2flags = m2->flags;
network_player_local_restore_lag_state();
// determine if ground pound should be ignored
if (m->action == ACT_GROUND_POUND) {
// not moving down yet?
if (m->actionState == 0) { return FALSE; }
if (m->actionState == 0) {
return FALSE;
}
m2->squishTimer = max(m2->squishTimer, 20);
}
if (m2->playerIndex == 0) {
m2->interactObj = m->marioObj;
if (interaction & INT_KICK) {
if (m2->action == ACT_FIRST_PERSON) {
if (m2action == ACT_FIRST_PERSON) {
// without this branch, the player will be stuck in first person
raise_background_noise(2);
set_camera_mode(m2->area->camera, -1, 1);
@ -1449,7 +1461,7 @@ u32 interact_player(struct MarioState* m, UNUSED u32 interactType, struct Object
}
set_mario_action(m2, ACT_FREEFALL, 0);
}
if (!(m2->flags & MARIO_METAL_CAP)) {
if (!(m2flags & MARIO_METAL_CAP)) {
m->marioObj->oDamageOrCoinValue = determine_player_damage_value(interaction);
if (m->flags & MARIO_METAL_CAP) {
m->marioObj->oDamageOrCoinValue *= 2;
@ -1465,6 +1477,7 @@ u32 interact_player(struct MarioState* m, UNUSED u32 interactType, struct Object
return FALSE;
}
network_player_local_restore_lag_state();
return FALSE;
}

View file

@ -6,6 +6,7 @@
#include "mario.h"
#include "object_list_processor.h"
#include "spawn_object.h"
#include "pc/network/network_player.h"
struct Object *debug_print_obj_collision(struct Object *a) {
struct Object *sp24;
@ -24,6 +25,8 @@ int detect_player_hitbox_overlap(struct MarioState* local, struct MarioState* re
if (local->marioObj == NULL || local->marioObj->oIntangibleTimer != 0) { return FALSE; }
if (remote->marioObj == NULL || remote->marioObj->oIntangibleTimer != 0) { return FALSE; }
network_player_local_set_lag_state(&gNetworkPlayers[remote->playerIndex]);
struct Object* a = local->marioObj;
f32* aTorso = local->marioBodyState->torsoPos;
@ -43,15 +46,19 @@ int detect_player_hitbox_overlap(struct MarioState* local, struct MarioState* re
f32 sp1C = b->hitboxHeight + sp38;
if (sp3C > sp1C) {
network_player_local_restore_lag_state();
return FALSE;
}
if (sp20 < sp38) {
network_player_local_restore_lag_state();
return FALSE;
}
if (a->numCollidedObjs >= 4) {
network_player_local_restore_lag_state();
return FALSE;
}
if (b->numCollidedObjs >= 4) {
network_player_local_restore_lag_state();
return FALSE;
}
a->collidedObjs[a->numCollidedObjs] = b;
@ -60,10 +67,13 @@ int detect_player_hitbox_overlap(struct MarioState* local, struct MarioState* re
b->collidedObjInteractTypes |= a->oInteractType;
a->numCollidedObjs++;
b->numCollidedObjs++;
network_player_local_restore_lag_state();
return TRUE;
}
//! no return value
network_player_local_restore_lag_state();
return FALSE;
}

View file

@ -17,6 +17,7 @@
static bool sHoldingAlt = false;
static bool sHoldingShift = false;
bool gDebugToggle = false;
#define SCANCODE_0 0x0B
#define SCANCODE_1 0x02
@ -109,6 +110,7 @@ void debug_keyboard_on_key_down(int scancode) {
case SCANCODE_2: if (sHoldingAlt) { debug_warp_level2(); } break;
case SCANCODE_4: if (sHoldingAlt) { debug_warp_level3(); } break;
case SCANCODE_5: if (sHoldingAlt) { print_sync_object_table(); } break;
case SCANCODE_6: if (sHoldingAlt) { gDebugToggle = !gDebugToggle; } break;
case SCANCODE_8: if (sHoldingAlt) { debug_spawn_object(); } break;
case SCANCODE_9: if (sHoldingAlt) { debug_warp_to(); } break;
case SCANCODE_0: if (sHoldingAlt) { debug_suicide(); } break;

View file

@ -65,21 +65,3 @@
#define gDPSetTextureClippingDjui(pkt, x1, y1, x2, y2) gSetClippingDjui(pkt, G_TEXCLIP_DJUI, x1, y1, x2, y2)
#define gDPSetTextureOverrideDjui(pkt, texture, w, h, bitSize) gSetOverrideDjui(pkt, G_TEXOVERRIDE_DJUI, texture, w, h, bitSize)
// DO NOT COMMIT //
# define gsSPVertexDjui(v, n, v0) \
{{ \
(_SHIFTL(G_DJUI_SIMPLE_VERT,24,8)|_SHIFTL((n),12,8)|_SHIFTL((v0)+(n),1,7)), \
(uintptr_t)(v) \
}}
#define gsSP2TrianglesDjui(v00, v01, v02, flag0, v10, v11, v12, flag1) \
{{ \
(_SHIFTL(G_DJUI_SIMPLE_TRI2, 24, 8)| \
__gsSP1Triangle_w1f(v00, v01, v02, flag0)), \
__gsSP1Triangle_w1f(v10, v11, v12, flag1) \
}}
// DO NOT COMMIT //

View file

@ -16,11 +16,26 @@ struct NetworkPlayer *gNetworkPlayerLocal = NULL;
struct NetworkPlayer *gNetworkPlayerServer = NULL;
static char sDefaultPlayerName[] = "Player";
#define MAX_LOCAL_PLAYER_STATES 15
struct LagState {
struct MarioState m;
struct MarioBodyState bodyState;
};
static struct LagState sLocalPlayerStates[MAX_LOCAL_PLAYER_STATES] = { 0 };
static struct LagState sLocalPlayerTmpState = { 0 };
static bool sLocalPlayerTmpStateSet = false;
static bool sLocalPlayerStatesReady = false;
static u32 sLocalPlayerStateIndex = 0;
void network_player_init(void) {
gNetworkPlayers[0].modelIndex = (configPlayerModel < CT_MAX) ? configPlayerModel : 0;
gNetworkPlayers[0].palette = configPlayerPalette;
gNetworkPlayers[0].overrideModelIndex = gNetworkPlayers[0].modelIndex;
gNetworkPlayers[0].overridePalette = gNetworkPlayers[0].palette;
sLocalPlayerTmpStateSet = false;
sLocalPlayerStatesReady = false;
sLocalPlayerStateIndex = 0;
}
void network_player_update_model(u8 localIndex) {
@ -145,7 +160,55 @@ void network_player_palette_to_color(struct NetworkPlayer *np, enum PlayerParts
out[2] = np->palette.parts[part][2];
}
static void network_player_local_save_state(void) {
if (!gMarioStates[0].marioBodyState) { return; }
memcpy(&sLocalPlayerStates[sLocalPlayerStateIndex].m, &gMarioStates[0], sizeof(struct MarioState));
memcpy(&sLocalPlayerStates[sLocalPlayerStateIndex].bodyState, gMarioStates[0].marioBodyState, sizeof(struct MarioBodyState));
if (sLocalPlayerStateIndex + 1 >= MAX_LOCAL_PLAYER_STATES) {
sLocalPlayerStatesReady = true;
}
sLocalPlayerStateIndex = (sLocalPlayerStateIndex + 1) % MAX_LOCAL_PLAYER_STATES;
}
void network_player_local_set_lag_state(struct NetworkPlayer* otherNp) {
if (!otherNp) { return; }
if (gNetworkType == NT_NONE) { return; }
if (!sLocalPlayerStatesReady) { return; }
s32 pingToTicks = (otherNp->ping / 1000.0f) * 30;
if (pingToTicks > (MAX_LOCAL_PLAYER_STATES-1)) {
pingToTicks = (MAX_LOCAL_PLAYER_STATES-1);
}
if (pingToTicks == 0) { return; }
s32 index = (s32)sLocalPlayerStateIndex - pingToTicks;
while (index < 0) { index += MAX_LOCAL_PLAYER_STATES; }
index = index % MAX_LOCAL_PLAYER_STATES;
memcpy(&sLocalPlayerTmpState.m, &gMarioStates[0], sizeof(struct MarioState));
memcpy(&sLocalPlayerTmpState.bodyState, gMarioStates[0].marioBodyState, sizeof(struct MarioBodyState));
memcpy(&gMarioStates[0], &sLocalPlayerStates[index].m, sizeof(struct MarioState));
memcpy(gMarioStates[0].marioBodyState, &sLocalPlayerStates[index].bodyState, sizeof(struct MarioBodyState));
sLocalPlayerTmpStateSet = true;
}
void network_player_local_restore_lag_state(void) {
if (!sLocalPlayerTmpStateSet) { return; }
memcpy(&gMarioStates[0], &sLocalPlayerTmpState.m, sizeof(struct MarioState));
memcpy(gMarioStates[0].marioBodyState, &sLocalPlayerTmpState.bodyState, sizeof(struct MarioBodyState));
sLocalPlayerTmpStateSet = false;
}
void network_player_update(void) {
network_player_local_save_state();
network_player_local_restore_lag_state();
for (s32 i = 0; i < MAX_PLAYERS; i++) {
struct NetworkPlayer *np = &gNetworkPlayers[i];
if (!np->connected && i > 0) { continue; }

View file

@ -79,6 +79,9 @@ struct NetworkPlayer* get_network_player_smallest_global(void);
void network_player_color_to_palette(struct NetworkPlayer *np, enum PlayerParts part, Color color);
void network_player_palette_to_color(struct NetworkPlayer *np, enum PlayerParts part, Color out);
void network_player_local_set_lag_state(struct NetworkPlayer* otherNp);
void network_player_local_restore_lag_state(void);
void network_player_update(void);
u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex, u8 modelIndex, const struct PlayerPalette* playerPalette, char* name);