From 936bafca5afe24418aeacdb8d7e394c2f4def98f Mon Sep 17 00:00:00 2001 From: Ondrej Novak Date: Fri, 18 Apr 2025 20:03:47 +0200 Subject: [PATCH] implement achievements, console supports copy to clipboard --- game/ach_events.c | 51 +++++++++++++++++++++++++++++++----- game/console.c | 45 ++++++++++++++++++++++++++++++- game/menu.c | 6 +++-- game/skeldal.c | 7 ++++- libs/mgifmapmem.c | 2 ++ platform/achievements.cpp | 23 +++++++++------- platform/platform.h | 3 ++- platform/sdl/BGraph2.cpp | 7 ++++- platform/sdl/BGraph2.h | 1 + platform/sdl/input.cpp | 3 +++ platform/sdl/sdl_context.cpp | 8 ++++-- platform/sdl/sdl_context.h | 2 ++ 12 files changed, 133 insertions(+), 25 deletions(-) diff --git a/game/ach_events.c b/game/ach_events.c index 7fe5bc8..2fa240c 100644 --- a/game/ach_events.c +++ b/game/ach_events.c @@ -1,29 +1,66 @@ #include "ach_events.h" +#include #include #include #include #include "globals.h" +#define DEFACH(x) static const char * x = #x; static char reported_##x = 0 +#define IS_ACH_REPORTED(x) (reported_##x) + +DEFACH(ACH_ALL_PARTY); +DEFACH(ACH_END_GAME); +DEFACH(ACH_FIRE); +DEFACH(ACH_FIRST_KILL); +DEFACH(ACH_FOUNTAIN); +DEFACH(ACH_HAMMER); +DEFACH(ACH_HEART); +DEFACH(ACH_ORC_TREASURE); +DEFACH(ACH_SCROLL); + +#define item_orc_treasure 72 +#define item_scroll_victory 152 +#define item_hearth_earth 150 +#define item_wind_hammer 149 +#define item_mitchel_water 151 +#define item_eternal_fire 148 + + + +static char achievements_enabled = 0; + +#define UNLOCK_ACH(x) do {if (achievements_enabled && !reported_##x) set_achievement(x); reported_##x = 1;} while(0) void enable_achievements(char enable) { - + achievements_enabled = enable; } void ach_event_kill_monster(int id) { - wzprintf("(event) kill monster %d\n", id); + (void)id; + UNLOCK_ACH(ACH_FIRST_KILL); } void ach_event_pick_item(int id) { - wzprintf("(event) pick item %d\n", id); + switch (id) { + case item_orc_treasure: UNLOCK_ACH(ACH_ORC_TREASURE); break; + case item_eternal_fire: UNLOCK_ACH(ACH_FIRE); break; + case item_hearth_earth: UNLOCK_ACH(ACH_HEART);break; + case item_mitchel_water: UNLOCK_ACH(ACH_FOUNTAIN);break; + case item_scroll_victory: UNLOCK_ACH(ACH_SCROLL);break; + case item_wind_hammer: UNLOCK_ACH(ACH_HAMMER);break; + default:break; + } } void ach_event_end_game() { - wzprintf("(event) end_game\n"); + UNLOCK_ACH(ACH_END_GAME); } void ach_event_inv_add(int id) { - wzprintf("(event) inventory add %d\n", id); + (void)id; + //wzprintf("(event) inventory add %d\n", id); } void ach_event_dialog_paragraph(int pgf) { - wzprintf("(event) dialog paragraph %d\n", pgf); + (void)pgf; + //wzprintf("(event) dialog paragraph %d\n", pgf); } void ach_event_full_party() { - wzprintf("(event) full party\n"); + UNLOCK_ACH(ACH_ALL_PARTY); } diff --git a/game/console.c b/game/console.c index 9910218..9b10b89 100644 --- a/game/console.c +++ b/game/console.c @@ -2,6 +2,7 @@ #include #include #include "globals.h" +#include "../platform/platform.h" #include #define console_max_characters 120 @@ -166,6 +167,7 @@ static char console_input_line[console_max_characters+1] = ""; static char *console_output_lines[console_max_lines] = {}; static int console_top_line = 0; static const char *console_command = NULL; +static int copied_text = 0; static const int console_x = 0; static const int console_y = SCREEN_OFFLINE; @@ -203,6 +205,16 @@ void draw_console_window() { y-=text_height("X"); if (y < console_y+console_padding) break; } + if (copied_text > 0) { + const char *c = "Copied"; + set_aligned_position(console_x+console_width, console_y, 2, 0, c); + outtext(c); + --copied_text; + } else if (get_control_key_state()) { + const char *c = "Press CTRL+C to copy content"; + set_aligned_position(console_x+console_width, console_y, 2, 0, c); + outtext(c); + } } char console_is_visible() { @@ -570,9 +582,10 @@ static int process_with_params(const char *cmd, const char *args) { return 0; } - if (istrcmp(cmd, "achieve") == 0) { +/* if (istrcmp(cmd, "achieve") == 0) { return !set_achievement(args); } +*/ if (istrcmp(cmd, "unachieve") == 0) { return !clear_achievement(args); } @@ -619,12 +632,40 @@ static int process_command(PARSED_COMMAND cmd) { return 0; } +static void console_copy_to_clipboard() { + size_t needsz = 0; + for (unsigned int i = 0; i < console_max_lines; ++i) { + if (console_output_lines[i]) needsz = needsz + strlen(console_output_lines[i]) + 2; + } + needsz+=1; + char *text = (char *)malloc(needsz); + char *iter = text; + for (unsigned int i = console_max_lines; i > 0; ) { + --i; + if (console_output_lines[i]) { + size_t len = strlen(console_output_lines[i]); + memcpy(iter, console_output_lines[i], len); + iter+=len; + *iter = '\r'; + ++iter; + *iter = '\n'; + ++iter; + } + } + *iter = 0; + if (copy_text_to_clipboard(text)) { + copied_text = 20; + } + free(text); +} + static void console_keyboard(EVENT_MSG *msg, void **_) { if (msg->msg == E_KEYBOARD) { int code = va_arg(msg->data, int); int c = code & 0xFF; if (c == E_QUIT_GAME_KEY) return; if (c) { + int len = strlen(console_input_line); if (c == 0x1B) { console_show(0); @@ -648,6 +689,8 @@ static void console_keyboard(EVENT_MSG *msg, void **_) { console_command = NULL; free(cmd.cmd_buffer); msg->msg = -1; + } else if (c == 3 && !get_shift_key_state()) { + console_copy_to_clipboard(); } else if (c >=32 && len < console_max_characters) { console_input_line[len] = c; console_input_line[len+1] = 0; diff --git a/game/menu.c b/game/menu.c index 944e40b..4dc173c 100644 --- a/game/menu.c +++ b/game/menu.c @@ -617,8 +617,7 @@ void konec_hry() int task_id; int timer; - ach_event_end_game(); - + schovej_mysku(); curcolor=0; bar32(0,0,639,479); @@ -627,6 +626,9 @@ void konec_hry() change_music(get_next_music_from_playlist()); timer=get_timer_value(); while (get_timer_value()-timer<150) task_sleep(); + + ach_event_end_game(); + task_id=add_task(8196,titles,1,"ENDTEXT.TXT"); task_wait_event(E_KEYBOARD); if (is_running(task_id)) term_task(task_id); diff --git a/game/skeldal.c b/game/skeldal.c index 8958488..ee1b6ec 100644 --- a/game/skeldal.c +++ b/game/skeldal.c @@ -20,6 +20,7 @@ #include "resources.h" // #include "advconfig.h" +#include "ach_events.h" #include "skeldal.h" #include "lang.h" @@ -1067,7 +1068,7 @@ void init_skeldal(const INI_CONFIG *cfg) load_shops(); memset(&loadlevel,0,sizeof(loadlevel)); loadlevel.eflags = 0xFF; - SetWheelMapping('H','P'); + } void wire_main_functs(); @@ -1746,6 +1747,10 @@ int skeldal_entry_point(const SKELDAL_CONFIG *start_cfg) lang_set_folder(build_pathname(2, gpathtable[SR_LANG], start_cfg->lang_path)); } + if (!start_cfg->adventure_path) { + enable_achievements(1); + } + start_check(); purge_temps(1); clrscr(); diff --git a/libs/mgifmapmem.c b/libs/mgifmapmem.c index aff74cc..4fb8878 100644 --- a/libs/mgifmapmem.c +++ b/libs/mgifmapmem.c @@ -188,7 +188,9 @@ void play_animation(const char *filename,char mode,int posy,char sound) void *mgf=map_file_to_memory(file_icase_find(filename), &sz); change_music(NULL); if (mgf==NULL) return; + game_display_disable_crt_effect_temporary(1); PlayMGFFile(mgf,BigPlayProc,posy,mode & 0x80); + game_display_disable_crt_effect_temporary(0); unmap_file(mgf, sz); } diff --git a/platform/achievements.cpp b/platform/achievements.cpp index 466d9b8..fa0fc8d 100644 --- a/platform/achievements.cpp +++ b/platform/achievements.cpp @@ -3,6 +3,7 @@ #include "error.h" #include #include +#include "platform.h" extern "C" { #include @@ -67,12 +68,21 @@ int8_t clear_achievement(const char *id) return -1; } - if (SteamUserStats() && SteamUserStats()->ClearAchievement(id)) { + if (istrcmp(id, "all") == 0) { + unsigned int cnt = SteamUserStats()->GetNumAchievements(); + for (unsigned int i = 0; i < cnt; ++i) { + SteamUserStats()->ClearAchievement(SteamUserStats()->GetAchievementName(i)); + } SteamUserStats()->StoreStats(); return 0; } else { - return -1; - } + if (SteamUserStats() && SteamUserStats()->ClearAchievement(id)) { + SteamUserStats()->StoreStats(); + return 0; + } else { + return -1; + } + } } char is_steam_available() @@ -89,13 +99,6 @@ char *get_steam_status() oss << "Is Steam overlay enabled:" << (SteamUtils()->IsOverlayEnabled() ? "yes" : "no") << "\n"; oss << "AppID: "<< SteamUtils()->GetAppID() << "\n"; oss << "Num Achievements: " << num_achievements << "\n"; - for (int i = 0; i < num_achievements; ++i) { - const char* name = SteamUserStats()->GetAchievementName(i); - bool achieved = false; - SteamUserStats()->GetAchievement(name, &achieved); - - oss << "[" << i << "] " << name << " - " << (achieved ? "Yes" : "No") << "\n"; - } std::string str = oss.str(); char *out = strdup(str.c_str()); diff --git a/platform/platform.h b/platform/platform.h index 81182ec..63660d6 100644 --- a/platform/platform.h +++ b/platform/platform.h @@ -85,8 +85,9 @@ char change_current_directory(const char *path); void *map_file_to_memory(const char *name, size_t *sz); void unmap_file(void *ptr, size_t sz); +char copy_text_to_clipboard(const char *); + void ShareCPU(void); -void SetWheelMapping(char up, char down); char get_control_key_state(void); char get_shift_key_state(void); diff --git a/platform/sdl/BGraph2.cpp b/platform/sdl/BGraph2.cpp index 28509ac..e841088 100644 --- a/platform/sdl/BGraph2.cpp +++ b/platform/sdl/BGraph2.cpp @@ -32,7 +32,7 @@ char game_display_init(const INI_CONFIG_SECTION *display_section, const char *ti cfg.window_height = ini_get_int(display_section, "window_height", 480); cfg.window_width = ini_get_int(display_section, "window_width", 640); - const char *filter = ini_get_string(display_section, "crt_filter", "auto"); + const char *filter = ini_get_string(display_section, "crt_filter", "none"); if (istrcmp(filter,"none") == 0) cfg.crt_filter = SDLContext::CrtFilterType::none; else if (istrcmp(filter,"scanlines") == 0) cfg.crt_filter = SDLContext::CrtFilterType::scanlines; else if (istrcmp(filter,"scanlines_2") == 0) cfg.crt_filter = SDLContext::CrtFilterType::scanlines_2; @@ -276,3 +276,8 @@ void game_display_sprite_set_zindex(int sprite_id, int zindex) { auto &sdl = get_sdl_global_context(); sdl.sprite_set_zindex(sprite_id, zindex); } + +void game_display_disable_crt_effect_temporary(char disable) { + auto &sdl = get_sdl_global_context(); + sdl.disable_crt_effect_temprary(disable?true:false); +} diff --git a/platform/sdl/BGraph2.h b/platform/sdl/BGraph2.h index a060cad..aabdbb3 100644 --- a/platform/sdl/BGraph2.h +++ b/platform/sdl/BGraph2.h @@ -38,6 +38,7 @@ void game_display_sprite_set_zindex(int sprite_id, int zindex); void game_display_hide_sprite(int sprite_id); ///unload sprite and free index void game_display_unload_sprite(int sprite); +void game_display_disable_crt_effect_temporary(char disable); void *DxPrepareWalk(int ypos); void DxZoomWalk(void *handle, int ypos, int *points,float phase, void *lodka); diff --git a/platform/sdl/input.cpp b/platform/sdl/input.cpp index 6f019b4..e7e8f38 100644 --- a/platform/sdl/input.cpp +++ b/platform/sdl/input.cpp @@ -107,3 +107,6 @@ char is_joystick_used() { char is_joystick_enabled() { return get_sdl_global_context().is_joystick_enabled()?1:0; } +char copy_text_to_clipboard(const char *text) { + return !SDL_SetClipboardText(text); +} diff --git a/platform/sdl/sdl_context.cpp b/platform/sdl/sdl_context.cpp index cd243e7..aedbbe0 100644 --- a/platform/sdl/sdl_context.cpp +++ b/platform/sdl/sdl_context.cpp @@ -14,7 +14,7 @@ #include #include #include -#include . +#include #include #include #include @@ -673,7 +673,7 @@ void SDLContext::refresh_screen() { recalc_rect.y = _mouse_rect.y - static_cast(f.y * _mouse_size); SDL_RenderCopy(_renderer.get(), _mouse.get(), NULL, &recalc_rect); } - if (winrc.h >= 720 && _crt_filter != CrtFilterType::none && _enable_crt) { + if (winrc.h >= 720 && _crt_filter != CrtFilterType::none && _enable_crt && !_disable_crt_tmp) { if (!_crt_effect) { SDL_Texture *txt; generateCRTTexture(_renderer.get(), &txt, winrc.w, winrc.h, _crt_filter); @@ -1135,3 +1135,7 @@ SDLContext::JoystickButton SDLContext::button_from_string(std::string_view s) { return JoystickButton::disabled; } + +void SDLContext::disable_crt_effect_temprary(bool disable) { + _disable_crt_tmp = disable; +} diff --git a/platform/sdl/sdl_context.h b/platform/sdl/sdl_context.h index 09db4dc..0e11bda 100644 --- a/platform/sdl/sdl_context.h +++ b/platform/sdl/sdl_context.h @@ -162,6 +162,7 @@ public: bool is_joystick_used() const; bool is_joystick_enabled() const; + void disable_crt_effect_temprary(bool disable); protected: struct SDL_Deleter { @@ -224,6 +225,7 @@ protected: int aspect_y = 3; CrtFilterType _crt_filter= CrtFilterType::autoselect; bool _enable_crt = true; + bool _disable_crt_tmp = false; std::function _quit_callback; JoystickConfig _jcontrol_map; bool _jcontrol_mod_key = false;