diff --git a/autogen/convert_functions.py b/autogen/convert_functions.py
index 8ab92a973..7426fcac9 100644
--- a/autogen/convert_functions.py
+++ b/autogen/convert_functions.py
@@ -33,6 +33,7 @@ in_files = [
"src/game/save_file.h",
"src/game/sound_init.h",
"src/pc/djui/djui_hud_utils.h",
+ "src/pc/network/network_player.h",
]
override_allowed_functions = {
@@ -59,6 +60,7 @@ override_disallowed_functions = {
"src/game/interaction.h": [ "process_interactions", "_handle_" ],
"src/game/sound_init.h": [ "_loop_", "thread4_", "set_sound_mode" ],
"src/pc/network/network_utils.h": [ "network_get_player_text_color[^_]" ],
+ "src/pc/network/network_player.h": [ "_init", "_connected[^_]", "_shutdown", "_disconnected", "_update" ],
}
###########################################################
diff --git a/credits.txt b/credits.txt
index e2d35f471..daac4bbd5 100644
--- a/credits.txt
+++ b/credits.txt
@@ -22,6 +22,7 @@ Contributors:
GammaTendonNine
gunvalk
IsaacBrumby
+ jkcoxson
Llennpie
LuigiNoodle
PeachyPeach
diff --git a/docs/lua/functions.md b/docs/lua/functions.md
index 0a61ff05c..40ae0e659 100644
--- a/docs/lua/functions.md
+++ b/docs/lua/functions.md
@@ -275,6 +275,15 @@
+- network_player.h
+ - [get_network_player_from_area](#get_network_player_from_area)
+ - [get_network_player_from_level](#get_network_player_from_level)
+ - [get_network_player_smallest_global](#get_network_player_smallest_global)
+ - [network_player_connected_count](#network_player_connected_count)
+ - [network_player_from_global_index](#network_player_from_global_index)
+
+
+
- network_utils.h
- [network_get_player_text_color_string](#network_get_player_text_color_string)
- [network_global_index_from_local](#network_global_index_from_local)
@@ -4699,6 +4708,113 @@
+---
+# functions from network_player.h
+
+
+
+
+## [get_network_player_from_area](#get_network_player_from_area)
+
+### Lua Example
+`local NetworkPlayerValue = get_network_player_from_area(courseNum, actNum, levelNum, areaIndex)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| courseNum | integer |
+| actNum | integer |
+| levelNum | integer |
+| areaIndex | integer |
+
+### Returns
+[NetworkPlayer](structs.md#NetworkPlayer)
+
+### C Prototype
+`struct NetworkPlayer* get_network_player_from_area(s16 courseNum, s16 actNum, s16 levelNum, s16 areaIndex);`
+
+[:arrow_up_small:](#)
+
+
+
+## [get_network_player_from_level](#get_network_player_from_level)
+
+### Lua Example
+`local NetworkPlayerValue = get_network_player_from_level(courseNum, actNum, levelNum)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| courseNum | integer |
+| actNum | integer |
+| levelNum | integer |
+
+### Returns
+[NetworkPlayer](structs.md#NetworkPlayer)
+
+### C Prototype
+`struct NetworkPlayer* get_network_player_from_level(s16 courseNum, s16 actNum, s16 levelNum);`
+
+[:arrow_up_small:](#)
+
+
+
+## [get_network_player_smallest_global](#get_network_player_smallest_global)
+
+### Lua Example
+`local NetworkPlayerValue = get_network_player_smallest_global()`
+
+### Parameters
+- None
+
+### Returns
+[NetworkPlayer](structs.md#NetworkPlayer)
+
+### C Prototype
+`struct NetworkPlayer* get_network_player_smallest_global(void);`
+
+[:arrow_up_small:](#)
+
+
+
+## [network_player_connected_count](#network_player_connected_count)
+
+### Lua Example
+`local integerValue = network_player_connected_count()`
+
+### Parameters
+- None
+
+### Returns
+- integer
+
+### C Prototype
+`u8 network_player_connected_count(void);`
+
+[:arrow_up_small:](#)
+
+
+
+## [network_player_from_global_index](#network_player_from_global_index)
+
+### Lua Example
+`local NetworkPlayerValue = network_player_from_global_index(globalIndex)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| globalIndex | integer |
+
+### Returns
+[NetworkPlayer](structs.md#NetworkPlayer)
+
+### C Prototype
+`struct NetworkPlayer* network_player_from_global_index(u8 globalIndex);`
+
+[:arrow_up_small:](#)
+
+
+
---
# functions from network_utils.h
diff --git a/mods/hide-and-seek.lua b/mods/hide-and-seek.lua
index 30e030178..f352b862d 100644
--- a/mods/hide-and-seek.lua
+++ b/mods/hide-and-seek.lua
@@ -13,7 +13,9 @@ gGlobalSyncTable.roundNumber = 0
gGlobalSyncTable.roundEnded = ROUND_END_UNKNOWN
sRoundEndedTimer = 0
-sRoundIntermissionTime = 5 * 30 -- five seconds
+sRoundEndedTimeout = 15 * 30 -- fifteen seconds
+sFlashingIndex = 0
+sDisplayCenterTimer = 0
-- server keeps track of last player turned seeker
sLastSeekerIndex = 0
@@ -29,6 +31,7 @@ sLastPos.y = 0
sLastPos.z = 0
sDistanceMoved = 0
sDistanceTimer = 0
+sDistanceTimeout = 10 * 30
function server_update(m)
-- figure out state of the game
@@ -72,8 +75,7 @@ function server_update(m)
end
-- if round was over for 5 seconds
- sRoundEndedTimer = sRoundEndedTimer + 1
- if sRoundEndedTimer >= sRoundIntermissionTime then
+ if sRoundEndedTimer >= sRoundEndedTimeout then
-- reset seekers
for i=0,(MAX_PLAYERS-1) do
gPlayerSyncTable[i].seeking = false
@@ -118,16 +120,19 @@ function camping_detection(m)
end
-- if the player has moved enough, reset the timer
- if sDistanceMoved > 20 then
+ if sDistanceMoved > 25 then
sDistanceTimer = 0
end
-- inform the player that they need to move, or make them a seeker
- if sDistanceTimer == 30 * 1 then
- djui_popup_create('\\#ff4040\\Keep moving!', 3)
- elseif sDistanceTimer > 30 * 6 then
+ if sDistanceTimer > sDistanceTimeout then
s.seeking = true
end
+
+ -- make sound
+ if sDistanceTimer > 0 and sDistanceTimer % 30 == 1 then
+ play_sound(SOUND_MENU_CAMERA_BUZZ, m.marioObj.header.gfx.cameraToObject)
+ end
end
function update()
@@ -148,18 +153,13 @@ function update()
sDistanceTimer = 0
end
- -- update sLastSeekerTimer
+ -- update sLastSeekerTimer and sRoundEndedTimer
if gGlobalSyncTable.roundEnded == 0 then
sLastSeekerTimer = sLastSeekerTimer + 1
- local timeLeft = sLastSeekerTimeout - sLastSeekerTimer
- if timeLeft == 60 * 30 then
- djui_popup_create('\\#ff4040\\Seekers have one minute to get someone!', 3)
- elseif timeLeft == 30 * 30 then
- djui_popup_create('\\#ff4040\\Seekers have 30 seconds to get someone!', 3)
- elseif timeLeft == 10 * 30 then
- djui_popup_create('\\#ff4040\\Seekers have 10 seconds to get someone!', 3)
- end
+ else
+ sRoundEndedTimer = sRoundEndedTimer + 1
end
+ sDisplayCenterTimer = sDisplayCenterTimer + 1
end
function mario_update(m)
@@ -249,6 +249,131 @@ function on_player_connected(m)
s.seeking = false
end
+function hud_top_render()
+ -- check gamemode enabled state
+ if not gGlobalSyncTable.hideAndSeek then
+ return
+ end
+
+ local seconds = 0
+ local text = ''
+
+ if network_player_connected_count() < 2 then
+ seconds = 60
+ text = 'waiting for players'
+ elseif gGlobalSyncTable.roundEnded == 0 then
+ seconds = math.floor((sLastSeekerTimeout - sLastSeekerTimer) / 30)
+ text = 'seekers have ' .. seconds .. ' seconds'
+ else
+ seconds = math.floor((sRoundEndedTimeout - sRoundEndedTimer) / 30)
+ text = 'next round in ' .. seconds .. ' seconds'
+ end
+
+ if seconds < 0 then seconds = 0 end
+ local scale = 0.50
+
+ -- get width of screen and text
+ local screenWidth = djui_hud_get_screen_width()
+ local width = djui_hud_measure_text(text) * scale
+
+ local x = (screenWidth - width) / 2.0
+ local y = 0
+
+ local background = 0.0
+ if seconds < 60 and gGlobalSyncTable.roundEnded == 0 then
+ background = (math.sin(sFlashingIndex / 10.0) * 0.5 + 0.5) * 1.0
+ background = background * background
+ background = background * background
+ end
+
+ -- render top
+ djui_hud_set_color(255 * background, 0, 0, 128);
+ djui_hud_render_rect(x - 6, y, width + 12, 16);
+
+ djui_hud_set_color(255, 255, 255, 255);
+ djui_hud_print_text(text, x, y, scale);
+end
+
+function hud_bottom_render()
+ local seconds = math.floor((sDistanceTimeout - sDistanceTimer) / 30)
+ if seconds < 0 then seconds = 0 end
+ if sDistanceTimer < 1 then return end
+
+ local text = 'Keep moving! (' .. seconds .. ')'
+ local scale = 0.50
+
+ -- get width of screen and text
+ local screenWidth = djui_hud_get_screen_width()
+ local screenHeight = djui_hud_get_screen_height()
+ local width = djui_hud_measure_text(text) * scale
+
+ local x = (screenWidth - width) / 2.0
+ local y = screenHeight - 16
+
+ local background = (math.sin(sFlashingIndex / 10.0) * 0.5 + 0.5) * 1.0
+ background = background * background
+ background = background * background
+
+ -- render top
+ djui_hud_set_color(255 * background, 0, 0, 128);
+ djui_hud_render_rect(x - 6, y, width + 12, 16);
+
+ djui_hud_set_color(255, 255, 255, 255);
+ djui_hud_print_text(text, x, y, scale);
+end
+
+function hud_center_render()
+ if sDisplayCenterTimer > 30 * 5 then return end
+
+ -- set text
+ local text = ''
+ if gGlobalSyncTable.roundEnded == ROUND_END_SEEKER_WIN then
+ text = 'Seekers Win!'
+ elseif gGlobalSyncTable.roundEnded == ROUND_END_HIDER_WIN then
+ text = 'Hiders Win!'
+ elseif gGlobalSyncTable.roundEnded == 0 then
+ text = 'Go!'
+ else
+ return
+ end
+
+ -- set scale
+ local scale = 1 - (sRoundEndedTimer / 30) + 4
+ if scale < 0 then scale = 0 end
+ if scale > 1 then scale = 1 end
+ scale = scale * scale
+ scale = scale * scale
+ scale = scale * scale
+
+ -- get width of screen and text
+ local screenWidth = djui_hud_get_screen_width()
+ local screenHeight = djui_hud_get_screen_height()
+ local width = djui_hud_measure_text(text) * scale
+ local height = 32 * scale
+
+ local x = (screenWidth - width) / 2.0
+ local y = (screenHeight - height) / 2.0
+
+ -- render
+ djui_hud_set_color(0, 0, 0, 128);
+ djui_hud_render_rect(x - 6 * scale, y, width + 12 * scale, height);
+
+ djui_hud_set_color(255, 255, 255, 255);
+ djui_hud_print_text(text, x, y, scale);
+end
+
+function on_hud_render()
+ -- render to N64 screen space, with the HUD font
+ djui_hud_set_resolution(RESOLUTION_N64)
+ djui_hud_set_font(FONT_NORMAL)
+
+ hud_top_render()
+ hud_bottom_render()
+ hud_center_render()
+
+ sFlashingIndex = sFlashingIndex + 1
+end
+
function on_hide_and_seek_command(msg)
if not network_is_server() then
djui_chat_message_create('Only the server can change this setting!')
@@ -271,33 +396,20 @@ end
-----------------------
function on_round_number_changed(tag, oldVal, newVal)
- -- inform players when a new round has begun
- if oldVal < newVal then
- djui_popup_create('\\#a0ffa0\\a new round has begun', 2)
- sDistanceMoved = 100
- sDistanceTimer = 0
- play_character_sound(gMarioStates[0], CHAR_SOUND_HERE_WE_GO)
- end
+ play_character_sound(gMarioStates[0], CHAR_SOUND_HERE_WE_GO)
+ sDisplayCenterTimer = 0
end
function on_round_ended_changed(tag, oldVal, newVal)
- -- inform players when a round has ended
- local tColor = '\\#ffa0a0\\'
- if newVal == ROUND_END_UNKNOWN then
- djui_popup_create(tColor .. 'the round has ended', 2)
- elseif newVal == ROUND_END_HIDER_WIN then
- if not gPlayerSyncTable[0].seeking then tColor = '\\#a0ffa0\\' end
- djui_popup_create(tColor .. 'Hiders win!', 2)
- elseif newVal == ROUND_END_SEEKER_WIN then
- if gPlayerSyncTable[0].seeking then tColor = '\\#a0ffa0\\' end
- djui_popup_create(tColor .. 'Seekers win!', 2)
- end
-
if oldVal == 0 and newVal ~= 0 then
sLastSeekerTimer = 0
+ play_sound(SOUND_MENU_CLICK_CHANGE_VIEW, gMarioStates[0].marioObj.header.gfx.cameraToObject)
+ sDisplayCenterTimer = 0
elseif newVal == 0 and oldVal ~= 0 then
sLastSeekerTimer = 0
end
+
+ sRoundEndedTimer = 0
end
function on_seeking_changed(tag, oldVal, newVal)
@@ -323,6 +435,7 @@ hook_event(HOOK_MARIO_UPDATE, mario_update)
hook_event(HOOK_BEFORE_PHYS_STEP, mario_before_phys_step)
hook_event(HOOK_ON_PVP_ATTACK, on_pvp_attack)
hook_event(HOOK_ON_PLAYER_CONNECTED, on_player_connected)
+hook_event(HOOK_ON_HUD_RENDER, on_hud_render)
hook_chat_command('hide-and-seek', "[on|off] turn hide-and-seek on or off", on_hide_and_seek_command)
@@ -330,6 +443,6 @@ hook_chat_command('hide-and-seek', "[on|off] turn hide-and-seek on or off", on_h
hook_on_sync_table_change(gGlobalSyncTable, 'roundNumber', 0, on_round_number_changed)
hook_on_sync_table_change(gGlobalSyncTable, 'roundEnded', 0, on_round_ended_changed)
for i=0,(MAX_PLAYERS-1) do
- gPlayerSyncTable[i].seeking = false
+ gPlayerSyncTable[i].seeking = true
hook_on_sync_table_change(gPlayerSyncTable[i], 'seeking', i, on_seeking_changed)
end
diff --git a/src/pc/djui/djui.c b/src/pc/djui/djui.c
index 5a396b305..3c8834c91 100644
--- a/src/pc/djui/djui.c
+++ b/src/pc/djui/djui.c
@@ -4,6 +4,7 @@
#include "game/level_update.h"
#include "pc/lua/smlua_hooks.h"
#include "djui_panel_playerlist.h"
+#include "djui_hud_utils.h"
static Gfx* sSavedDisplayListHead = NULL;
@@ -52,6 +53,8 @@ void djui_render_patch(void) {
void djui_render(void) {
if (gDjuiDisabled) { return; }
sSavedDisplayListHead = gDisplayListHead;
+ gDjuiHudUtilsZ = 0;
+
create_dl_ortho_matrix();
smlua_call_event_hooks(HOOK_ON_HUD_RENDER);
diff --git a/src/pc/djui/djui_hud_utils.c b/src/pc/djui/djui_hud_utils.c
index ef204ac7c..012cbc27c 100644
--- a/src/pc/djui/djui_hud_utils.c
+++ b/src/pc/djui/djui_hud_utils.c
@@ -16,6 +16,8 @@
static enum HudUtilsResolution sResolution = RESOLUTION_DJUI;
static enum DjuiFontType sFont = FONT_NORMAL;
+f32 gDjuiHudUtilsZ = 0;
+
extern ALIGNED8 const u8 texture_hud_char_camera[];
extern ALIGNED8 const u8 texture_hud_char_lakitu[];
extern ALIGNED8 const u8 texture_hud_char_no_camera[];
@@ -95,6 +97,8 @@ f32 djui_hud_measure_text(const char* message) {
void djui_hud_print_text(const char* message, float x, float y, float scale) {
if (message == NULL) { return; }
+ gDjuiHudUtilsZ += 0.01f;
+
const struct DjuiFont* font = gDjuiFonts[sFont];
f32 fontScale = font->defaultFontScale * scale;
@@ -107,7 +111,7 @@ void djui_hud_print_text(const char* message, float x, float y, float scale) {
f32 translatedX = x;
f32 translatedY = y;
djui_hud_position_translate(&translatedX, &translatedY);
- create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, 0);
+ create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, gDjuiHudUtilsZ);
// compute font size
f32 translatedFontSize = fontScale;
@@ -137,11 +141,13 @@ void djui_hud_print_text(const char* message, float x, float y, float scale) {
}
static void djui_hud_render_texture_raw(const u8* texture, u32 bitSize, u32 width, u32 height, f32 x, f32 y, f32 scaleW, f32 scaleH) {
+ gDjuiHudUtilsZ += 0.01f;
+
// translate position
f32 translatedX = x;
f32 translatedY = y;
djui_hud_position_translate(&translatedX, &translatedY);
- create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, 0);
+ create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, gDjuiHudUtilsZ);
// translate scale
f32 translatedW = scaleW;
@@ -162,11 +168,13 @@ void djui_hud_render_texture(struct TextureInfo* texInfo, f32 x, f32 y, f32 scal
}
void djui_hud_render_rect(f32 x, f32 y, f32 width, f32 height) {
+ gDjuiHudUtilsZ += 0.01f;
+
// translate position
f32 translatedX = x;
f32 translatedY = y;
djui_hud_position_translate(&translatedX, &translatedY);
- create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, 0);
+ create_dl_translation_matrix(DJUI_MTX_PUSH, translatedX, translatedY, gDjuiHudUtilsZ);
// translate scale
f32 translatedW = width;
diff --git a/src/pc/djui/djui_hud_utils.h b/src/pc/djui/djui_hud_utils.h
index 1d62ea2be..4c9bbec79 100644
--- a/src/pc/djui/djui_hud_utils.h
+++ b/src/pc/djui/djui_hud_utils.h
@@ -25,6 +25,7 @@ struct GlobalTextures {
};
extern struct GlobalTextures gGlobalTextures;
+extern f32 gDjuiHudUtilsZ;
void djui_hud_set_resolution(enum HudUtilsResolution resolutionType);
void djui_hud_set_font(enum DjuiFontType fontType);
diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c
index e89282aaf..4546e34e0 100644
--- a/src/pc/lua/smlua_functions_autogen.c
+++ b/src/pc/lua/smlua_functions_autogen.c
@@ -17,6 +17,7 @@
#include "src/game/save_file.h"
#include "src/game/sound_init.h"
#include "src/pc/djui/djui_hud_utils.h"
+#include "src/pc/network/network_player.h"
//////////////
@@ -2929,6 +2930,71 @@ int smlua_func_stop_and_set_height_to_floor(lua_State* L) {
return 1;
}
+ //////////////////////
+ // network_player.h //
+//////////////////////
+
+int smlua_func_get_network_player_from_area(lua_State* L) {
+ if(!smlua_functions_valid_param_count(L, 4)) { return 0; }
+
+ s16 courseNum = smlua_to_integer(L, 1);
+ if (!gSmLuaConvertSuccess) { return 0; }
+ s16 actNum = smlua_to_integer(L, 2);
+ if (!gSmLuaConvertSuccess) { return 0; }
+ s16 levelNum = smlua_to_integer(L, 3);
+ if (!gSmLuaConvertSuccess) { return 0; }
+ s16 areaIndex = smlua_to_integer(L, 4);
+ if (!gSmLuaConvertSuccess) { return 0; }
+
+ smlua_push_object(L, LOT_NETWORKPLAYER, get_network_player_from_area(courseNum, actNum, levelNum, areaIndex));
+
+ return 1;
+}
+
+int smlua_func_get_network_player_from_level(lua_State* L) {
+ if(!smlua_functions_valid_param_count(L, 3)) { return 0; }
+
+ s16 courseNum = smlua_to_integer(L, 1);
+ if (!gSmLuaConvertSuccess) { return 0; }
+ s16 actNum = smlua_to_integer(L, 2);
+ if (!gSmLuaConvertSuccess) { return 0; }
+ s16 levelNum = smlua_to_integer(L, 3);
+ if (!gSmLuaConvertSuccess) { return 0; }
+
+ smlua_push_object(L, LOT_NETWORKPLAYER, get_network_player_from_level(courseNum, actNum, levelNum));
+
+ return 1;
+}
+
+int smlua_func_get_network_player_smallest_global(UNUSED lua_State* L) {
+ if(!smlua_functions_valid_param_count(L, 0)) { return 0; }
+
+
+ smlua_push_object(L, LOT_NETWORKPLAYER, get_network_player_smallest_global());
+
+ return 1;
+}
+
+int smlua_func_network_player_connected_count(UNUSED lua_State* L) {
+ if(!smlua_functions_valid_param_count(L, 0)) { return 0; }
+
+
+ lua_pushinteger(L, network_player_connected_count());
+
+ return 1;
+}
+
+int smlua_func_network_player_from_global_index(lua_State* L) {
+ if(!smlua_functions_valid_param_count(L, 1)) { return 0; }
+
+ u8 globalIndex = smlua_to_integer(L, 1);
+ if (!gSmLuaConvertSuccess) { return 0; }
+
+ smlua_push_object(L, LOT_NETWORKPLAYER, network_player_from_global_index(globalIndex));
+
+ return 1;
+}
+
/////////////////////
// network_utils.h //
/////////////////////
@@ -3721,6 +3787,13 @@ void smlua_bind_functions_autogen(void) {
smlua_bind_function(L, "stationary_ground_step", smlua_func_stationary_ground_step);
smlua_bind_function(L, "stop_and_set_height_to_floor", smlua_func_stop_and_set_height_to_floor);
+ // network_player.h
+ smlua_bind_function(L, "get_network_player_from_area", smlua_func_get_network_player_from_area);
+ smlua_bind_function(L, "get_network_player_from_level", smlua_func_get_network_player_from_level);
+ smlua_bind_function(L, "get_network_player_smallest_global", smlua_func_get_network_player_smallest_global);
+ 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);
+
// network_utils.h
smlua_bind_function(L, "network_get_player_text_color_string", smlua_func_network_get_player_text_color_string);
smlua_bind_function(L, "network_global_index_from_local", smlua_func_network_global_index_from_local);