diff --git a/game/discord.cpp b/game/discord.cpp index 627714487c..131df52887 100644 --- a/game/discord.cpp +++ b/game/discord.cpp @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include "discord.h" @@ -62,6 +64,38 @@ const char* jak1_get_full_level_name(const char* level_name) { return "Unknown"; }; +// time of day string to append to level name for icons +const char* time_of_day_str(float time) { + int hour = static_cast(time); + + if (hour >= 0 && hour <= 9) + return "green-sun"; + else if (hour >= 10 && hour <= 21) + return "day"; + else if (hour >= 22 && hour <= 24) + return "evening"; + else + return ""; +} + +// convert time of day float to a 24-hour hh:mm format string +std::string get_time_of_day(float time) { + int hour = static_cast(time); + int minutes = static_cast((time - hour) * 60); + std::stringstream ss; + ss << hour << ':' << std::setw(2) << std::setfill('0') << minutes; + return ss.str(); +} + +// are we in an area that's indoors, i.e. not affected by time of day? +int indoors(const char* level_name) { + return !strcmp(level_name, "intro") || !strcmp(level_name, "title") || + !strcmp(level_name, "jungleb") || !strcmp(level_name, "sunken") || + !strcmp(level_name, "sunkenb") || !strcmp(level_name, "maincave") || + !strcmp(level_name, "robocave") || !strcmp(level_name, "darkcave") || + !strcmp(level_name, "lavatube") || !strcmp(level_name, "citadel"); +} + void handleDiscordReady(const DiscordUser* user) { printf("\nDiscord: connected to user %s#%s - %s\n", user->username, user->discriminator, user->userId); diff --git a/game/discord.h b/game/discord.h index 7d5eed58ac..ea879c807a 100644 --- a/game/discord.h +++ b/game/discord.h @@ -5,6 +5,9 @@ void init_discord_rpc(); void set_discord_rpc(int state); const char* jak1_get_full_level_name(const char* level_name); +const char* time_of_day_str(float time); +std::string get_time_of_day(float time); +int indoors(const char* level_name); void handleDiscordReady(const DiscordUser* user); void handleDiscordDisconnected(int errcode, const char* message); diff --git a/game/kernel/kmachine.cpp b/game/kernel/kmachine.cpp index 7b63edce85..a949e97cf7 100644 --- a/game/kernel/kmachine.cpp +++ b/game/kernel/kmachine.cpp @@ -827,13 +827,17 @@ void update_discord_rpc(u32 discord_info) { if (gDiscordRpcEnabled) { DiscordRichPresence rpc; char state[128]; + char large_image_key[128]; char large_image_text[128]; + char small_image_key[128]; + char small_image_text[128]; auto info = discord_info ? Ptr(discord_info).c() : NULL; if (info) { int cells = (int)*Ptr(info->fuel).c(); int orbs = (int)*Ptr(info->money_total).c(); int scout_flies = (int)*Ptr(info->buzzer_total).c(); int deaths = *Ptr(info->deaths).c(); + float time = *Ptr(info->time_of_day).c(); auto cutscene = Ptr(info->cutscene)->value; auto ogreboss = Ptr(info->ogreboss)->value; auto plantboss = Ptr(info->plantboss)->value; @@ -843,7 +847,16 @@ void update_discord_rpc(u32 discord_info) { char* level = Ptr(info->level).c()->data(); const char* full_level_name = jak1_get_full_level_name(Ptr(info->level).c()->data()); memset(&rpc, 0, sizeof(rpc)); - rpc.largeImageKey = level; + if (!indoors(level)) { + char level_with_tod[128]; + strcpy(level_with_tod, level); + strcat(level_with_tod, "-"); + strcat(level_with_tod, time_of_day_str(time)); + strcpy(large_image_key, level_with_tod); + } else { + strcpy(large_image_key, level); + } + rpc.largeImageKey = large_image_key; strcpy(large_image_text, full_level_name); if (!strcmp(level, "finalboss")) { strcpy(state, "Fighting Final Boss"); @@ -883,15 +896,20 @@ void update_discord_rpc(u32 discord_info) { rpc.largeImageText = large_image_text; rpc.state = state; if (racer != offset_of_s7()) { - rpc.smallImageKey = "target-racer"; - rpc.smallImageText = "Driving A-Grav Zoomer"; + strcpy(small_image_key, "target-racer"); + strcpy(small_image_text, "Driving A-Grav Zoomer"); } else if (flutflut != offset_of_s7()) { - rpc.smallImageKey = "flutflut"; - rpc.smallImageText = "Riding on Flut Flut"; + strcpy(small_image_key, "flutflut"); + strcpy(small_image_text, "Riding on Flut Flut"); } else { - rpc.smallImageKey = 0; - rpc.smallImageText = 0; + if (!indoors(level)) { + strcpy(small_image_key, time_of_day_str(time)); + strcpy(small_image_text, "Time of day: "); + strcat(small_image_text, get_time_of_day(time).c_str()); + } } + rpc.smallImageKey = small_image_key; + rpc.smallImageText = small_image_text; rpc.startTimestamp = gStartTime; rpc.details = status; rpc.partySize = 0; diff --git a/game/kernel/kmachine.h b/game/kernel/kmachine.h index 6d74ca89bf..24e40b04c3 100644 --- a/game/kernel/kmachine.h +++ b/game/kernel/kmachine.h @@ -146,6 +146,7 @@ struct DiscordInfo { u32 plantboss; // are we fighting plant-boss? u32 racer; // are we driving the zoomer? u32 flutflut; // are we riding on flut flut? + u32 time_of_day; }; // static_assert(offsetof(CpadInfo, new_pad) == 76, "cpad type offset"); diff --git a/goal_src/pc/pckernel-h.gc b/goal_src/pc/pckernel-h.gc index 07a41670df..6ad7e72c52 100644 --- a/goal_src/pc/pckernel-h.gc +++ b/goal_src/pc/pckernel-h.gc @@ -343,6 +343,7 @@ (plant-boss? symbol) (racer? symbol) (flutflut? symbol) + (time-of-day (pointer float)) ) ) diff --git a/goal_src/pc/pckernel.gc b/goal_src/pc/pckernel.gc index c1c12c4d47..2974977431 100644 --- a/goal_src/pc/pckernel.gc +++ b/goal_src/pc/pckernel.gc @@ -234,6 +234,7 @@ 'target-flut-stance 'target-flut-start 'target-flut-walk) #t)))) + (set! (-> info time-of-day) (&-> *time-of-day-context* time)) (with-profiler "discord-update" (pc-discord-rpc-update info)) )