implement achievements, console supports copy to clipboard

This commit is contained in:
Ondrej Novak 2025-04-18 20:03:47 +02:00
parent f5450c0f92
commit 936bafca5a
12 changed files with 133 additions and 25 deletions

View file

@ -1,29 +1,66 @@
#include "ach_events.h"
#include <platform/achievements.h>
#include <stdint.h>
#include <stdlib.h>
#include <libs/event.h>
#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);
}

View file

@ -2,6 +2,7 @@
#include <libs/event.h>
#include <platform/achievements.h>
#include "globals.h"
#include "../platform/platform.h"
#include <ctype.h>
#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;

View file

@ -617,7 +617,6 @@ void konec_hry()
int task_id;
int timer;
ach_event_end_game();
schovej_mysku();
curcolor=0;
@ -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);

View file

@ -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();

View file

@ -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);
}

View file

@ -3,6 +3,7 @@
#include "error.h"
#include <string.h>
#include <sstream>
#include "platform.h"
extern "C" {
#include <libs/event.h>
@ -67,11 +68,20 @@ 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;
}
}
}
@ -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());

View file

@ -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);

View file

@ -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);
}

View file

@ -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);

View file

@ -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);
}

View file

@ -14,7 +14,7 @@
#include <steam/steam_api.h>
#include <stdbool.h>
#include <thread>
#include <mutex>.
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <string_view>
@ -673,7 +673,7 @@ void SDLContext::refresh_screen() {
recalc_rect.y = _mouse_rect.y - static_cast<int>(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;
}

View file

@ -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<void()> _quit_callback;
JoystickConfig _jcontrol_map;
bool _jcontrol_mod_key = false;