mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-25 13:35:12 +00:00
PVP improvements
Removed angle check for punch/kick Compensated for lag, so interactions favor the attacker now
This commit is contained in:
parent
8f2f46fbdc
commit
f593a263aa
7 changed files with 105 additions and 31 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 //
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue