mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-22 03:55:11 +00:00
Improve lag compensation
This commit is contained in:
parent
3d13b893aa
commit
fce88728d2
15 changed files with 282 additions and 219 deletions
|
@ -37,6 +37,7 @@ in_files = [
|
||||||
"src/game/sound_init.h",
|
"src/game/sound_init.h",
|
||||||
"src/pc/djui/djui_hud_utils.h",
|
"src/pc/djui/djui_hud_utils.h",
|
||||||
"src/pc/network/network_player.h",
|
"src/pc/network/network_player.h",
|
||||||
|
"src/pc/network/lag_compensation.h",
|
||||||
"include/behavior_table.h",
|
"include/behavior_table.h",
|
||||||
"src/pc/lua/utils/smlua_obj_utils.h",
|
"src/pc/lua/utils/smlua_obj_utils.h",
|
||||||
"src/pc/lua/utils/smlua_misc_utils.h",
|
"src/pc/lua/utils/smlua_misc_utils.h",
|
||||||
|
|
|
@ -4010,6 +4010,22 @@ function take_damage_and_knock_back(m, o)
|
||||||
-- ...
|
-- ...
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- @return nil
|
||||||
|
function lag_compensation_clear()
|
||||||
|
-- ...
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @param otherNp NetworkPlayer
|
||||||
|
--- @return MarioState
|
||||||
|
function lag_compensation_get_local_state(otherNp)
|
||||||
|
-- ...
|
||||||
|
end
|
||||||
|
|
||||||
|
--- @return nil
|
||||||
|
function lag_compensation_store()
|
||||||
|
-- ...
|
||||||
|
end
|
||||||
|
|
||||||
--- @param courseNum integer
|
--- @param courseNum integer
|
||||||
--- @param levelNum integer
|
--- @param levelNum integer
|
||||||
--- @param areaIndex integer
|
--- @param areaIndex integer
|
||||||
|
@ -5614,17 +5630,6 @@ function network_player_from_global_index(globalIndex)
|
||||||
-- ...
|
-- ...
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @return nil
|
|
||||||
function network_player_local_restore_lag_state()
|
|
||||||
-- ...
|
|
||||||
end
|
|
||||||
|
|
||||||
--- @param otherNp NetworkPlayer
|
|
||||||
--- @return nil
|
|
||||||
function network_player_local_set_lag_state(otherNp)
|
|
||||||
-- ...
|
|
||||||
end
|
|
||||||
|
|
||||||
--- @param np NetworkPlayer
|
--- @param np NetworkPlayer
|
||||||
--- @param part PlayerParts
|
--- @param part PlayerParts
|
||||||
--- @param out Color
|
--- @param out Color
|
||||||
|
|
|
@ -21,7 +21,7 @@ const f32 font_normal_widths[] = {
|
||||||
/* a b c d e f g h i j k l m n o p q r s t u v w x y z */
|
/* a b c d e f g h i j k l m n o p q r s t u v w x y z */
|
||||||
0.3000f, 0.3125f, 0.3125f, 0.3125f, 0.3125f, 0.3000f, 0.3750f, 0.3125f, 0.2200f, 0.3125f, 0.3125f, 0.1700f, 0.4350f, 0.3125f, 0.3000f, 0.3000f, 0.3125f, 0.2700f, 0.3125f, 0.3125f, 0.3125f, 0.2750f, 0.4375f, 0.3750f, 0.3125f, 0.3125f,
|
0.3000f, 0.3125f, 0.3125f, 0.3125f, 0.3125f, 0.3000f, 0.3750f, 0.3125f, 0.2200f, 0.3125f, 0.3125f, 0.1700f, 0.4350f, 0.3125f, 0.3000f, 0.3000f, 0.3125f, 0.2700f, 0.3125f, 0.3125f, 0.3125f, 0.2750f, 0.4375f, 0.3750f, 0.3125f, 0.3125f,
|
||||||
/* { | } ~ DEL */
|
/* { | } ~ DEL */
|
||||||
0.3125f, 0.2500f, 0.3125f, 0.5000f, 0.2000f,
|
0.3125f, 0.2500f, 0.3125f, 0.5000f, 0.3125f,
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -3299,6 +3299,68 @@
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
|
---
|
||||||
|
# functions from lag_compensation.h
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
|
||||||
|
## [lag_compensation_clear](#lag_compensation_clear)
|
||||||
|
|
||||||
|
### Lua Example
|
||||||
|
`lag_compensation_clear()`
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
- None
|
||||||
|
|
||||||
|
### Returns
|
||||||
|
- None
|
||||||
|
|
||||||
|
### C Prototype
|
||||||
|
`void lag_compensation_clear(void);`
|
||||||
|
|
||||||
|
[:arrow_up_small:](#)
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## [lag_compensation_get_local_state](#lag_compensation_get_local_state)
|
||||||
|
|
||||||
|
### Lua Example
|
||||||
|
`local MarioStateValue = lag_compensation_get_local_state(otherNp)`
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
| Field | Type |
|
||||||
|
| ----- | ---- |
|
||||||
|
| otherNp | [NetworkPlayer](structs.md#NetworkPlayer) |
|
||||||
|
|
||||||
|
### Returns
|
||||||
|
[MarioState](structs.md#MarioState)
|
||||||
|
|
||||||
|
### C Prototype
|
||||||
|
`struct MarioState* lag_compensation_get_local_state(struct NetworkPlayer* otherNp);`
|
||||||
|
|
||||||
|
[:arrow_up_small:](#)
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
## [lag_compensation_store](#lag_compensation_store)
|
||||||
|
|
||||||
|
### Lua Example
|
||||||
|
`lag_compensation_store()`
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
- None
|
||||||
|
|
||||||
|
### Returns
|
||||||
|
- None
|
||||||
|
|
||||||
|
### C Prototype
|
||||||
|
`void lag_compensation_store(void);`
|
||||||
|
|
||||||
|
[:arrow_up_small:](#)
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
---
|
---
|
||||||
# functions from level_info.h
|
# functions from level_info.h
|
||||||
|
|
||||||
|
@ -8186,44 +8248,6 @@
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
## [network_player_local_restore_lag_state](#network_player_local_restore_lag_state)
|
|
||||||
|
|
||||||
### Lua Example
|
|
||||||
`network_player_local_restore_lag_state()`
|
|
||||||
|
|
||||||
### Parameters
|
|
||||||
- None
|
|
||||||
|
|
||||||
### Returns
|
|
||||||
- None
|
|
||||||
|
|
||||||
### C Prototype
|
|
||||||
`void network_player_local_restore_lag_state(void);`
|
|
||||||
|
|
||||||
[:arrow_up_small:](#)
|
|
||||||
|
|
||||||
<br />
|
|
||||||
|
|
||||||
## [network_player_local_set_lag_state](#network_player_local_set_lag_state)
|
|
||||||
|
|
||||||
### Lua Example
|
|
||||||
`network_player_local_set_lag_state(otherNp)`
|
|
||||||
|
|
||||||
### Parameters
|
|
||||||
| Field | Type |
|
|
||||||
| ----- | ---- |
|
|
||||||
| otherNp | [NetworkPlayer](structs.md#NetworkPlayer) |
|
|
||||||
|
|
||||||
### Returns
|
|
||||||
- None
|
|
||||||
|
|
||||||
### C Prototype
|
|
||||||
`void network_player_local_set_lag_state(struct NetworkPlayer* otherNp);`
|
|
||||||
|
|
||||||
[:arrow_up_small:](#)
|
|
||||||
|
|
||||||
<br />
|
|
||||||
|
|
||||||
## [network_player_palette_to_color](#network_player_palette_to_color)
|
## [network_player_palette_to_color](#network_player_palette_to_color)
|
||||||
|
|
||||||
### Lua Example
|
### Lua Example
|
||||||
|
|
|
@ -792,6 +792,13 @@
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
|
- lag_compensation.h
|
||||||
|
- [lag_compensation_clear](functions-3.md#lag_compensation_clear)
|
||||||
|
- [lag_compensation_get_local_state](functions-3.md#lag_compensation_get_local_state)
|
||||||
|
- [lag_compensation_store](functions-3.md#lag_compensation_store)
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
- level_info.h
|
- level_info.h
|
||||||
- [get_level_name](functions-3.md#get_level_name)
|
- [get_level_name](functions-3.md#get_level_name)
|
||||||
- [get_level_name_ascii](functions-3.md#get_level_name_ascii)
|
- [get_level_name_ascii](functions-3.md#get_level_name_ascii)
|
||||||
|
@ -1085,8 +1092,6 @@
|
||||||
- [network_player_color_to_palette](functions-3.md#network_player_color_to_palette)
|
- [network_player_color_to_palette](functions-3.md#network_player_color_to_palette)
|
||||||
- [network_player_connected_count](functions-3.md#network_player_connected_count)
|
- [network_player_connected_count](functions-3.md#network_player_connected_count)
|
||||||
- [network_player_from_global_index](functions-3.md#network_player_from_global_index)
|
- [network_player_from_global_index](functions-3.md#network_player_from_global_index)
|
||||||
- [network_player_local_restore_lag_state](functions-3.md#network_player_local_restore_lag_state)
|
|
||||||
- [network_player_local_set_lag_state](functions-3.md#network_player_local_set_lag_state)
|
|
||||||
- [network_player_palette_to_color](functions-3.md#network_player_palette_to_color)
|
- [network_player_palette_to_color](functions-3.md#network_player_palette_to_color)
|
||||||
- [network_player_set_description](functions-3.md#network_player_set_description)
|
- [network_player_set_description](functions-3.md#network_player_set_description)
|
||||||
|
|
||||||
|
|
|
@ -105,29 +105,28 @@ function mario_local_hammer_check(m)
|
||||||
|
|
||||||
-- check for hammer attacks
|
-- check for hammer attacks
|
||||||
for i = 1, (MAX_PLAYERS - 1) do
|
for i = 1, (MAX_PLAYERS - 1) do
|
||||||
local m2 = gMarioStates[i]
|
local mattacker = gMarioStates[i]
|
||||||
local np2 = gNetworkPlayers[i]
|
local npattacker = gNetworkPlayers[i]
|
||||||
local s2 = gPlayerSyncTable[i]
|
local sattacker = gPlayerSyncTable[i]
|
||||||
if passes_pvp_interaction_checks(m2, m) ~= 0 then
|
local cmvictim = lag_compensation_get_local_state(npattacker)
|
||||||
network_player_local_set_lag_state(np2)
|
|
||||||
if s2.item == ITEM_HAMMER and mario_hammer_is_attack(m2.action) and passes_pvp_interaction_checks(m2, m) ~= 0 and global_index_hurts_mario_state(np2.globalIndex, m) then
|
if sattacker.item == ITEM_HAMMER and mario_hammer_is_attack(mattacker.action) and passes_pvp_interaction_checks(mattacker, cmvictim) ~= 0 and passes_pvp_interaction_checks(mattacker, m) ~= 0 and global_index_hurts_mario_state(npattacker.globalIndex, m) then
|
||||||
local pos = mario_hammer_position(m2)
|
local pos = mario_hammer_position(mattacker)
|
||||||
local dist = vec3f_dist(pos, m.pos)
|
local dist = vec3f_dist(pos, cmvictim.pos)
|
||||||
if dist <= 165 then
|
if dist <= 165 then
|
||||||
local yOffset = 100
|
local yOffset = 100
|
||||||
if m2.action == ACT_JUMP_KICK then
|
if mattacker.action == ACT_JUMP_KICK then
|
||||||
yOffset = yOffset + 100
|
yOffset = yOffset + 100
|
||||||
end
|
end
|
||||||
|
|
||||||
local vel = {
|
local vel = {
|
||||||
x = m.pos.x - m2.pos.x,
|
x = cmvictim.pos.x - mattacker.pos.x,
|
||||||
y = (m.pos.y + yOffset) - m2.pos.y,
|
y = (cmvictim.pos.y + yOffset) - mattacker.pos.y,
|
||||||
z = m.pos.z - m2.pos.z,
|
z = cmvictim.pos.z - mattacker.pos.z,
|
||||||
}
|
}
|
||||||
vec3f_normalize(vel)
|
vec3f_normalize(vel)
|
||||||
vec3f_mul(vel, 75 + 70 * (1 - mario_health_float(m)))
|
vec3f_mul(vel, 75 + 70 * (1 - mario_health_float(cmvictim)))
|
||||||
|
|
||||||
network_player_local_restore_lag_state()
|
|
||||||
set_mario_action(m, ACT_BACKWARD_AIR_KB, 0)
|
set_mario_action(m, ACT_BACKWARD_AIR_KB, 0)
|
||||||
m.invincTimer = 30
|
m.invincTimer = 30
|
||||||
m.knockbackTimer = 10
|
m.knockbackTimer = 10
|
||||||
|
@ -135,20 +134,18 @@ function mario_local_hammer_check(m)
|
||||||
m.vel.y = vel.y
|
m.vel.y = vel.y
|
||||||
m.vel.z = vel.z
|
m.vel.z = vel.z
|
||||||
m.faceAngle.y = atan2s(vel.z, vel.x) + 0x8000
|
m.faceAngle.y = atan2s(vel.z, vel.x) + 0x8000
|
||||||
s2.ammo = s2.ammo - 1
|
sattacker.ammo = sattacker.ammo - 1
|
||||||
|
|
||||||
send_arena_hammer_hit(np.globalIndex, np2.globalIndex)
|
send_arena_hammer_hit(np.globalIndex, npattacker.globalIndex)
|
||||||
e.lastDamagedByGlobal = np2.globalIndex
|
e.lastDamagedByGlobal = npattacker.globalIndex
|
||||||
|
|
||||||
if m2.action == ACT_PUNCHING or m2.action == ACT_MOVE_PUNCHING or m2.action == ACT_GROUND_POUND then
|
if mattacker.action == ACT_PUNCHING or mattacker.action == ACT_MOVE_PUNCHING or mattacker.action == ACT_GROUND_POUND then
|
||||||
m.hurtCounter = 12
|
m.hurtCounter = 12
|
||||||
else
|
else
|
||||||
m.hurtCounter = 8
|
m.hurtCounter = 8
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
network_player_local_restore_lag_state()
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
m.knockbackTimer = savedKb
|
m.knockbackTimer = savedKb
|
||||||
|
|
|
@ -17,13 +17,15 @@ end
|
||||||
|
|
||||||
function bhv_arena_bobomb_intersects_player(obj, m, pos, radius)
|
function bhv_arena_bobomb_intersects_player(obj, m, pos, radius)
|
||||||
local ownerNp = network_player_from_global_index(obj.oArenaBobombGlobalOwner)
|
local ownerNp = network_player_from_global_index(obj.oArenaBobombGlobalOwner)
|
||||||
network_player_local_set_lag_state(ownerNp)
|
local cm = m
|
||||||
|
if m.playerIndex == 0 then
|
||||||
|
cm = lag_compensation_get_local_state(ownerNp)
|
||||||
|
end
|
||||||
|
|
||||||
local mPos1 = { x = m.pos.x, y = m.pos.y + 50, z = m.pos.z }
|
local mPos1 = { x = cm.pos.x, y = cm.pos.y + 50, z = cm.pos.z }
|
||||||
local mPos2 = { x = m.pos.x, y = m.pos.y + 150, z = m.pos.z }
|
local mPos2 = { x = cm.pos.x, y = cm.pos.y + 150, z = cm.pos.z }
|
||||||
local ret = (vec3f_dist(pos, mPos1) < radius or vec3f_dist(pos, mPos2) < radius)
|
local ret = (vec3f_dist(pos, mPos1) < radius or vec3f_dist(pos, mPos2) < radius)
|
||||||
|
|
||||||
network_player_local_restore_lag_state()
|
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -18,17 +18,17 @@ function bhv_arena_cannon_ball_init(obj)
|
||||||
end
|
end
|
||||||
|
|
||||||
function bhv_arena_cannon_ball_intersects_local(obj, pos)
|
function bhv_arena_cannon_ball_intersects_local(obj, pos)
|
||||||
|
|
||||||
local ownerNp = network_player_from_global_index(obj.oArenaBobombGlobalOwner)
|
local ownerNp = network_player_from_global_index(obj.oArenaBobombGlobalOwner)
|
||||||
network_player_local_set_lag_state(ownerNp)
|
local cm = gMarioStates[0]
|
||||||
|
if gMarioStates[0].playerIndex == 0 then
|
||||||
|
cm = lag_compensation_get_local_state(ownerNp)
|
||||||
|
end
|
||||||
|
|
||||||
local m = gMarioStates[0]
|
local mPos1 = { x = cm.pos.x, y = cm.pos.y + 50, z = cm.pos.z }
|
||||||
local mPos1 = { x = m.pos.x, y = m.pos.y + 50, z = m.pos.z }
|
local mPos2 = { x = cm.pos.x, y = cm.pos.y + 150, z = cm.pos.z }
|
||||||
local mPos2 = { x = m.pos.x, y = m.pos.y + 150, z = m.pos.z }
|
|
||||||
local radius = clamp(obj.oArenaCannonBallSize * 250, 75, 250)
|
local radius = clamp(obj.oArenaCannonBallSize * 250, 75, 250)
|
||||||
local ret = (vec3f_dist(pos, mPos1) < radius or vec3f_dist(pos, mPos2) < radius)
|
local ret = (vec3f_dist(pos, mPos1) < radius or vec3f_dist(pos, mPos2) < radius)
|
||||||
|
|
||||||
network_player_local_restore_lag_state()
|
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -389,6 +389,14 @@ void adjust_analog_stick(struct Controller *controller) {
|
||||||
controller->stickY *= 64 / controller->stickMag;
|
controller->stickY *= 64 / controller->stickMag;
|
||||||
controller->stickMag = 64;
|
controller->stickMag = 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*extern bool gDebugToggle;
|
||||||
|
if (gDebugToggle) {
|
||||||
|
controller->stickX = 64;
|
||||||
|
controller->stickY = 0;
|
||||||
|
controller->stickMag = 64;
|
||||||
|
}*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if a demo sequence exists, this will run the demo
|
// if a demo sequence exists, this will run the demo
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
|
|
||||||
#include "pc/configfile.h"
|
#include "pc/configfile.h"
|
||||||
#include "pc/network/network.h"
|
#include "pc/network/network.h"
|
||||||
|
#include "pc/network/lag_compensation.h"
|
||||||
#include "pc/lua/smlua_hooks.h"
|
#include "pc/lua/smlua_hooks.h"
|
||||||
#include "pc/cheats.h"
|
#include "pc/cheats.h"
|
||||||
|
|
||||||
|
@ -1412,39 +1413,38 @@ u32 interact_player_pvp(struct MarioState* attacker, struct MarioState* victim)
|
||||||
// make sure it passes pvp checks before rollback
|
// make sure it passes pvp checks before rollback
|
||||||
if (!passes_pvp_interaction_checks(attacker, victim)) { return FALSE; }
|
if (!passes_pvp_interaction_checks(attacker, victim)) { return FALSE; }
|
||||||
|
|
||||||
// set my local player to the state I was in when they attacked
|
// grab the lag compensation version of the victim
|
||||||
|
struct MarioState* cVictim = NULL;
|
||||||
if (victim->playerIndex == 0) {
|
if (victim->playerIndex == 0) {
|
||||||
network_player_local_set_lag_state(&gNetworkPlayers[victim->playerIndex]);
|
cVictim = lag_compensation_get_local_state(&gNetworkPlayers[attacker->playerIndex]);
|
||||||
}
|
}
|
||||||
|
if (cVictim == NULL) { cVictim = victim; }
|
||||||
|
|
||||||
// make sure we overlap
|
// make sure we overlap
|
||||||
f32 overlapScale = (attacker->playerIndex == 0) ? 0.6f : 1.0f;
|
f32 overlapScale = (attacker->playerIndex == 0) ? 0.6f : 1.0f;
|
||||||
if (!detect_player_hitbox_overlap(attacker, victim, overlapScale)) {
|
if (!detect_player_hitbox_overlap(attacker, cVictim, overlapScale)) {
|
||||||
network_player_local_restore_lag_state();
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// see if it was an attack
|
// see if it was an attack
|
||||||
u32 interaction = determine_interaction(attacker, victim->marioObj);
|
u32 interaction = determine_interaction(attacker, cVictim->marioObj);
|
||||||
if (!(interaction & INT_ANY_ATTACK) || (interaction & INT_HIT_FROM_ABOVE) || !passes_pvp_interaction_checks(attacker, victim)) {
|
if (!(interaction & INT_ANY_ATTACK) || (interaction & INT_HIT_FROM_ABOVE) || !passes_pvp_interaction_checks(attacker, cVictim)) {
|
||||||
network_player_local_restore_lag_state();
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// call the lua hook
|
// call the lua hook
|
||||||
bool allow = true;
|
bool allow = true;
|
||||||
smlua_call_event_hooks_mario_params_ret_bool(HOOK_ALLOW_PVP_ATTACK, attacker, victim, &allow);
|
smlua_call_event_hooks_mario_params_ret_bool(HOOK_ALLOW_PVP_ATTACK, attacker, cVictim, &allow);
|
||||||
if (!allow) {
|
if (!allow) {
|
||||||
// Lua blocked the interaction
|
// Lua blocked the interaction
|
||||||
network_player_local_restore_lag_state();
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine if slide attack should be ignored
|
// determine if slide attack should be ignored
|
||||||
if ((interaction & INT_ATTACK_SLIDE) || player_is_sliding(victim)) {
|
if ((interaction & INT_ATTACK_SLIDE) || player_is_sliding(cVictim)) {
|
||||||
// determine the difference in velocities
|
// determine the difference in velocities
|
||||||
Vec3f velDiff;
|
Vec3f velDiff;
|
||||||
vec3f_dif(velDiff, attacker->vel, victim->vel);
|
vec3f_dif(velDiff, attacker->vel, cVictim->vel);
|
||||||
|
|
||||||
if (attacker->action == ACT_SLIDE_KICK_SLIDE || attacker->action == ACT_SLIDE_KICK) {
|
if (attacker->action == ACT_SLIDE_KICK_SLIDE || attacker->action == ACT_SLIDE_KICK) {
|
||||||
// if the difference vectors are not different enough, do not attack
|
// if the difference vectors are not different enough, do not attack
|
||||||
|
@ -1455,14 +1455,9 @@ u32 interact_player_pvp(struct MarioState* attacker, struct MarioState* victim)
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the victim is going faster, do not attack
|
// if the victim is going faster, do not attack
|
||||||
if (vec3f_length(victim->vel) > vec3f_length(attacker->vel)) { return FALSE; }
|
if (vec3f_length(cVictim->vel) > vec3f_length(attacker->vel)) { return FALSE; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// restore to current state
|
|
||||||
u32 victimAction = victim->action;
|
|
||||||
u32 victimFlags = victim->flags;
|
|
||||||
network_player_local_restore_lag_state();
|
|
||||||
|
|
||||||
// determine if ground pound should be ignored
|
// determine if ground pound should be ignored
|
||||||
if (attacker->action == ACT_GROUND_POUND) {
|
if (attacker->action == ACT_GROUND_POUND) {
|
||||||
// not moving down yet?
|
// not moving down yet?
|
||||||
|
@ -1473,7 +1468,7 @@ u32 interact_player_pvp(struct MarioState* attacker, struct MarioState* victim)
|
||||||
if (victim->playerIndex == 0) {
|
if (victim->playerIndex == 0) {
|
||||||
victim->interactObj = attacker->marioObj;
|
victim->interactObj = attacker->marioObj;
|
||||||
if (interaction & INT_KICK) {
|
if (interaction & INT_KICK) {
|
||||||
if (victimAction == ACT_FIRST_PERSON) {
|
if (victim->action == ACT_FIRST_PERSON) {
|
||||||
// without this branch, the player will be stuck in first person
|
// without this branch, the player will be stuck in first person
|
||||||
raise_background_noise(2);
|
raise_background_noise(2);
|
||||||
set_camera_mode(victim->area->camera, -1, 1);
|
set_camera_mode(victim->area->camera, -1, 1);
|
||||||
|
@ -1481,7 +1476,7 @@ u32 interact_player_pvp(struct MarioState* attacker, struct MarioState* victim)
|
||||||
}
|
}
|
||||||
set_mario_action(victim, ACT_FREEFALL, 0);
|
set_mario_action(victim, ACT_FREEFALL, 0);
|
||||||
}
|
}
|
||||||
if (!(victimFlags & MARIO_METAL_CAP)) {
|
if (!(victim->flags & MARIO_METAL_CAP)) {
|
||||||
attacker->marioObj->oDamageOrCoinValue = determine_player_damage_value(interaction);
|
attacker->marioObj->oDamageOrCoinValue = determine_player_damage_value(interaction);
|
||||||
if (attacker->flags & MARIO_METAL_CAP) { attacker->marioObj->oDamageOrCoinValue *= 2; }
|
if (attacker->flags & MARIO_METAL_CAP) { attacker->marioObj->oDamageOrCoinValue *= 2; }
|
||||||
}
|
}
|
||||||
|
@ -2250,7 +2245,6 @@ void mario_process_interactions(struct MarioState *m) {
|
||||||
if (&gMarioStates[i] == m) { continue; }
|
if (&gMarioStates[i] == m) { continue; }
|
||||||
interact_player_pvp(m, &gMarioStates[i]);
|
interact_player_pvp(m, &gMarioStates[i]);
|
||||||
}
|
}
|
||||||
network_player_local_restore_lag_state();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m->invincTimer > 0 && !sDelayInvincTimer) {
|
if (m->invincTimer > 0 && !sDelayInvincTimer) {
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "src/game/sound_init.h"
|
#include "src/game/sound_init.h"
|
||||||
#include "src/pc/djui/djui_hud_utils.h"
|
#include "src/pc/djui/djui_hud_utils.h"
|
||||||
#include "src/pc/network/network_player.h"
|
#include "src/pc/network/network_player.h"
|
||||||
|
#include "src/pc/network/lag_compensation.h"
|
||||||
#include "include/behavior_table.h"
|
#include "include/behavior_table.h"
|
||||||
#include "src/pc/lua/utils/smlua_obj_utils.h"
|
#include "src/pc/lua/utils/smlua_obj_utils.h"
|
||||||
#include "src/pc/lua/utils/smlua_misc_utils.h"
|
#include "src/pc/lua/utils/smlua_misc_utils.h"
|
||||||
|
@ -12643,6 +12644,57 @@ int smlua_func_take_damage_and_knock_back(lua_State* L) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////
|
||||||
|
// lag_compensation.h //
|
||||||
|
////////////////////////
|
||||||
|
|
||||||
|
int smlua_func_lag_compensation_clear(UNUSED lua_State* L) {
|
||||||
|
if (L == NULL) { return 0; }
|
||||||
|
|
||||||
|
int top = lua_gettop(L);
|
||||||
|
if (top != 0) {
|
||||||
|
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "lag_compensation_clear", 0, top);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
lag_compensation_clear();
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int smlua_func_lag_compensation_get_local_state(lua_State* L) {
|
||||||
|
if (L == NULL) { return 0; }
|
||||||
|
|
||||||
|
int top = lua_gettop(L);
|
||||||
|
if (top != 1) {
|
||||||
|
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "lag_compensation_get_local_state", 1, top);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NetworkPlayer* otherNp = (struct NetworkPlayer*)smlua_to_cobject(L, 1, LOT_NETWORKPLAYER);
|
||||||
|
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "lag_compensation_get_local_state"); return 0; }
|
||||||
|
|
||||||
|
smlua_push_object(L, LOT_MARIOSTATE, lag_compensation_get_local_state(otherNp));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int smlua_func_lag_compensation_store(UNUSED lua_State* L) {
|
||||||
|
if (L == NULL) { return 0; }
|
||||||
|
|
||||||
|
int top = lua_gettop(L);
|
||||||
|
if (top != 0) {
|
||||||
|
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "lag_compensation_store", 0, top);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
lag_compensation_store();
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////
|
//////////////////
|
||||||
// level_info.h //
|
// level_info.h //
|
||||||
//////////////////
|
//////////////////
|
||||||
|
@ -18659,38 +18711,6 @@ int smlua_func_network_player_from_global_index(lua_State* L) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int smlua_func_network_player_local_restore_lag_state(UNUSED lua_State* L) {
|
|
||||||
if (L == NULL) { return 0; }
|
|
||||||
|
|
||||||
int top = lua_gettop(L);
|
|
||||||
if (top != 0) {
|
|
||||||
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "network_player_local_restore_lag_state", 0, top);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
network_player_local_restore_lag_state();
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int smlua_func_network_player_local_set_lag_state(lua_State* L) {
|
|
||||||
if (L == NULL) { return 0; }
|
|
||||||
|
|
||||||
int top = lua_gettop(L);
|
|
||||||
if (top != 1) {
|
|
||||||
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "network_player_local_set_lag_state", 1, top);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct NetworkPlayer* otherNp = (struct NetworkPlayer*)smlua_to_cobject(L, 1, LOT_NETWORKPLAYER);
|
|
||||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "network_player_local_set_lag_state"); return 0; }
|
|
||||||
|
|
||||||
network_player_local_set_lag_state(otherNp);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int smlua_func_network_player_palette_to_color(lua_State* L) {
|
int smlua_func_network_player_palette_to_color(lua_State* L) {
|
||||||
if (L == NULL) { return 0; }
|
if (L == NULL) { return 0; }
|
||||||
|
|
||||||
|
@ -29910,6 +29930,11 @@ void smlua_bind_functions_autogen(void) {
|
||||||
smlua_bind_function(L, "passes_pvp_interaction_checks", smlua_func_passes_pvp_interaction_checks);
|
smlua_bind_function(L, "passes_pvp_interaction_checks", smlua_func_passes_pvp_interaction_checks);
|
||||||
smlua_bind_function(L, "take_damage_and_knock_back", smlua_func_take_damage_and_knock_back);
|
smlua_bind_function(L, "take_damage_and_knock_back", smlua_func_take_damage_and_knock_back);
|
||||||
|
|
||||||
|
// lag_compensation.h
|
||||||
|
smlua_bind_function(L, "lag_compensation_clear", smlua_func_lag_compensation_clear);
|
||||||
|
smlua_bind_function(L, "lag_compensation_get_local_state", smlua_func_lag_compensation_get_local_state);
|
||||||
|
smlua_bind_function(L, "lag_compensation_store", smlua_func_lag_compensation_store);
|
||||||
|
|
||||||
// level_info.h
|
// level_info.h
|
||||||
smlua_bind_function(L, "get_level_name", smlua_func_get_level_name);
|
smlua_bind_function(L, "get_level_name", smlua_func_get_level_name);
|
||||||
smlua_bind_function(L, "get_level_name_ascii", smlua_func_get_level_name_ascii);
|
smlua_bind_function(L, "get_level_name_ascii", smlua_func_get_level_name_ascii);
|
||||||
|
@ -30174,8 +30199,6 @@ void smlua_bind_functions_autogen(void) {
|
||||||
smlua_bind_function(L, "network_player_color_to_palette", smlua_func_network_player_color_to_palette);
|
smlua_bind_function(L, "network_player_color_to_palette", smlua_func_network_player_color_to_palette);
|
||||||
smlua_bind_function(L, "network_player_connected_count", smlua_func_network_player_connected_count);
|
smlua_bind_function(L, "network_player_connected_count", smlua_func_network_player_connected_count);
|
||||||
smlua_bind_function(L, "network_player_from_global_index", smlua_func_network_player_from_global_index);
|
smlua_bind_function(L, "network_player_from_global_index", smlua_func_network_player_from_global_index);
|
||||||
smlua_bind_function(L, "network_player_local_restore_lag_state", smlua_func_network_player_local_restore_lag_state);
|
|
||||||
smlua_bind_function(L, "network_player_local_set_lag_state", smlua_func_network_player_local_set_lag_state);
|
|
||||||
smlua_bind_function(L, "network_player_palette_to_color", smlua_func_network_player_palette_to_color);
|
smlua_bind_function(L, "network_player_palette_to_color", smlua_func_network_player_palette_to_color);
|
||||||
smlua_bind_function(L, "network_player_set_description", smlua_func_network_player_set_description);
|
smlua_bind_function(L, "network_player_set_description", smlua_func_network_player_set_description);
|
||||||
|
|
||||||
|
|
59
src/pc/network/lag_compensation.c
Normal file
59
src/pc/network/lag_compensation.c
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#include "types.h"
|
||||||
|
#include "network_player.h"
|
||||||
|
#include "lag_compensation.h"
|
||||||
|
#include "pc/debuglog.h"
|
||||||
|
#include "game/object_helpers.h"
|
||||||
|
#include "behavior_table.h"
|
||||||
|
#include "model_ids.h"
|
||||||
|
|
||||||
|
#define MAX_LOCAL_STATE_HISTORY 20
|
||||||
|
struct StateHistory {
|
||||||
|
struct MarioState m;
|
||||||
|
struct Object marioObj;
|
||||||
|
struct MarioBodyState bodyState;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct StateHistory sLocalStateHistory[MAX_LOCAL_STATE_HISTORY] = { 0 };
|
||||||
|
static bool sLocalStateHistoryReady = false;
|
||||||
|
static u32 sLocalStateHistoryIndex = 0;
|
||||||
|
|
||||||
|
void lag_compensation_clear(void) {
|
||||||
|
sLocalStateHistoryReady = false;
|
||||||
|
sLocalStateHistoryIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lag_compensation_store(void) {
|
||||||
|
if (!gMarioStates[0].marioBodyState) { return; }
|
||||||
|
if (!gMarioStates[0].marioObj) { return; }
|
||||||
|
|
||||||
|
struct StateHistory* sh = &sLocalStateHistory[sLocalStateHistoryIndex];
|
||||||
|
memcpy(&sh->m, &gMarioStates[0], sizeof(struct MarioState));
|
||||||
|
memcpy(&sh->marioObj, gMarioStates[0].marioObj, sizeof(struct Object));
|
||||||
|
memcpy(&sh->bodyState, gMarioStates[0].marioBodyState, sizeof(struct MarioBodyState));
|
||||||
|
sh->m.marioObj = &sh->marioObj;
|
||||||
|
sh->m.marioBodyState = &sh->bodyState;
|
||||||
|
|
||||||
|
if (sLocalStateHistoryIndex + 1 >= MAX_LOCAL_STATE_HISTORY) {
|
||||||
|
sLocalStateHistoryReady = true;
|
||||||
|
}
|
||||||
|
sLocalStateHistoryIndex = (sLocalStateHistoryIndex + 1) % MAX_LOCAL_STATE_HISTORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MarioState* lag_compensation_get_local_state(struct NetworkPlayer* otherNp) {
|
||||||
|
if (!otherNp) { return NULL; }
|
||||||
|
if (gNetworkType == NT_NONE) { return NULL; }
|
||||||
|
if (!sLocalStateHistoryReady) { return NULL; }
|
||||||
|
|
||||||
|
s32 pingToTicks = (otherNp->ping / 1000.0f) * 30;
|
||||||
|
if (pingToTicks > (MAX_LOCAL_STATE_HISTORY-1)) {
|
||||||
|
pingToTicks = (MAX_LOCAL_STATE_HISTORY-1);
|
||||||
|
}
|
||||||
|
//LOG_INFO("Ping: %s :: %u :: %d", otherNp->name, otherNp->ping, pingToTicks);
|
||||||
|
if (pingToTicks == 0) { return NULL; }
|
||||||
|
|
||||||
|
s32 index = (s32)sLocalStateHistoryIndex - pingToTicks;
|
||||||
|
while (index < 0) { index += MAX_LOCAL_STATE_HISTORY; }
|
||||||
|
index = index % MAX_LOCAL_STATE_HISTORY;
|
||||||
|
|
||||||
|
return &sLocalStateHistory[index].m;
|
||||||
|
}
|
8
src/pc/network/lag_compensation.h
Normal file
8
src/pc/network/lag_compensation.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef NETWORK_LAG_COMPENSATION_H
|
||||||
|
#define NETWORK_LAG_COMPENSATION_H
|
||||||
|
|
||||||
|
void lag_compensation_clear(void);
|
||||||
|
void lag_compensation_store(void);
|
||||||
|
struct MarioState* lag_compensation_get_local_state(struct NetworkPlayer* otherNp);
|
||||||
|
|
||||||
|
#endif
|
|
@ -10,32 +10,19 @@
|
||||||
#include "game/hardcoded.h"
|
#include "game/hardcoded.h"
|
||||||
#include "game/object_helpers.h"
|
#include "game/object_helpers.h"
|
||||||
#include "pc/lua/smlua_hooks.h"
|
#include "pc/lua/smlua_hooks.h"
|
||||||
|
#include "lag_compensation.h"
|
||||||
|
|
||||||
struct NetworkPlayer gNetworkPlayers[MAX_PLAYERS] = { 0 };
|
struct NetworkPlayer gNetworkPlayers[MAX_PLAYERS] = { 0 };
|
||||||
struct NetworkPlayer *gNetworkPlayerLocal = NULL;
|
struct NetworkPlayer *gNetworkPlayerLocal = NULL;
|
||||||
struct NetworkPlayer *gNetworkPlayerServer = NULL;
|
struct NetworkPlayer *gNetworkPlayerServer = NULL;
|
||||||
static char sDefaultPlayerName[] = "Player";
|
static char sDefaultPlayerName[] = "Player";
|
||||||
|
|
||||||
#define MAX_LOCAL_PLAYER_STATES 20
|
|
||||||
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) {
|
void network_player_init(void) {
|
||||||
gNetworkPlayers[0].modelIndex = (configPlayerModel < CT_MAX) ? configPlayerModel : 0;
|
gNetworkPlayers[0].modelIndex = (configPlayerModel < CT_MAX) ? configPlayerModel : 0;
|
||||||
gNetworkPlayers[0].palette = configPlayerPalette;
|
gNetworkPlayers[0].palette = configPlayerPalette;
|
||||||
gNetworkPlayers[0].overrideModelIndex = gNetworkPlayers[0].modelIndex;
|
gNetworkPlayers[0].overrideModelIndex = gNetworkPlayers[0].modelIndex;
|
||||||
gNetworkPlayers[0].overridePalette = gNetworkPlayers[0].palette;
|
gNetworkPlayers[0].overridePalette = gNetworkPlayers[0].palette;
|
||||||
sLocalPlayerTmpStateSet = false;
|
lag_compensation_clear();
|
||||||
sLocalPlayerStatesReady = false;
|
|
||||||
sLocalPlayerStateIndex = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void network_player_update_model(u8 localIndex) {
|
void network_player_update_model(u8 localIndex) {
|
||||||
|
@ -160,55 +147,8 @@ void network_player_palette_to_color(struct NetworkPlayer *np, enum PlayerParts
|
||||||
out[2] = np->palette.parts[part][2];
|
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;
|
|
||||||
pingToTicks += 2;
|
|
||||||
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) {
|
void network_player_update(void) {
|
||||||
network_player_local_save_state();
|
lag_compensation_store();
|
||||||
network_player_local_restore_lag_state();
|
|
||||||
|
|
||||||
for (s32 i = 0; i < MAX_PLAYERS; i++) {
|
for (s32 i = 0; i < MAX_PLAYERS; i++) {
|
||||||
struct NetworkPlayer *np = &gNetworkPlayers[i];
|
struct NetworkPlayer *np = &gNetworkPlayers[i];
|
||||||
|
|
|
@ -79,9 +79,6 @@ 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_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_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);
|
void network_player_update(void);
|
||||||
|
|
||||||
u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex, u8 modelIndex, const struct PlayerPalette* playerPalette, char* name);
|
u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex, u8 modelIndex, const struct PlayerPalette* playerPalette, char* name);
|
||||||
|
|
Loading…
Reference in a new issue