support for controllers, save effect, fix bugs

This commit is contained in:
Ondrej Novak 2025-03-02 20:36:41 +01:00
parent 9e5faf53de
commit 44e73566b1
16 changed files with 306 additions and 38 deletions

View file

@ -665,6 +665,7 @@ void map_keyboard(EVENT_MSG *msg,void **usr)
case 's':if (check_for_layer(cur_depth-1)) cur_depth--;break;
case 18:
case 'I':
case 'O':
case 't':if (check_for_layer(cur_depth+1)) cur_depth++;break;
case 15:
case 50:

View file

@ -1356,6 +1356,7 @@ void death_screen() {
}
void redraw_scene()
{
if (norefresh) return;
@ -1436,8 +1437,8 @@ void play_fx(int x,int y)
void play_fx_at(int where)
{
static word polex[]={313,290,362,336};
static word poley[]={1,1,1,1,1};
static word polex[]={313,290,362,336,165};
static word poley[]={1,1,1,1,1,1};
play_fx(polex[where],poley[where]);
}

View file

@ -258,9 +258,9 @@ char start_invetory(int id,int xa,int ya,int xr,int yr)
p=&postavy[i];
if (p->used && p->inmaphash == current_map_hash)
{
if (ms_last_event.event_type & 0x2)
if (ms_last_event.event_type & (0x2|MS_EVENT_MOUSE_LDBLCLK))
{
if (get_control_key_state())
if (get_control_key_state() || (ms_last_event.event_type & MS_EVENT_MOUSE_LDBLCLK))
{
if (p->sektor==viewsector)
{
@ -466,7 +466,7 @@ T_CLK_MAP clk_main_view[]=
{MS_GAME_WIN,0,17,639,377,clk_throw,2,-1},
{MS_GAME_WIN,0,17,639,250,clk_mob_alter,2,-1},
{-1,0,378,639,479,sing_song_clk,0xff,-1},
{-1,54,378,497,479,start_invetory,2+8,-1},
{-1,54,378,497,479,start_invetory,2+8+MS_EVENT_MOUSE_LDBLCLK,-1},
{-1,315,0,335,14,spell_casting,2,-1},
};

View file

@ -106,11 +106,45 @@ static char ask_who_proc(int id,int xa,int ya,int xr,int yr);
static TSTRINGTABLE *dialogy_strtable = NULL;
#define CLK_DIALOG 3
void wire_dialog_drw(void);
static void (*old_wire_proc)(void) = NULL;
void wire_dialog_drw_restore(void) {
wire_proc = old_wire_proc ;
wire_dialog_drw();
}
static char dlg_konec(int id,int xa,int ya,int xr,int yr) {
old_wire_proc = wire_proc;
wire_proc = wire_dialog_drw_restore;
konec(id,xa,ya,xr,yr);
return 1;
}
static char dlg_game_setup(int id,int xa,int ya,int xr,int yr) {
old_wire_proc = wire_proc;
wire_proc = wire_dialog_drw_restore;
game_setup(id,xa,ya,xr,yr);
return 1;
}
static char dlg_clk_saveload(int id,int xa,int ya,int xr,int yr) {
old_wire_proc = wire_proc;
wire_proc = wire_dialog_drw_restore;
clk_saveload(id,xa,ya,xr,yr);
return 1;
}
#define CLK_DIALOG 5
static T_CLK_MAP clk_dialog[CLK_DIALOG]=
{
{0,TEXT_X,TEXT_Y,TEXT_X+TEXT_XS,TEXT_Y+TEXT_YS,case_click,3,H_MS_DEFAULT},
{-1,30,0,85,14,konec,2,H_MS_DEFAULT},
{-1,30,0,85,14,dlg_konec,2,H_MS_DEFAULT},
{-1,87,0,142,14,dlg_game_setup,2,H_MS_DEFAULT},
{0,207,0,265,14,dlg_clk_saveload,2,H_MS_DEFAULT},
{0,0,0,639,479,empty_clk,0xff,H_MS_DEFAULT},
};
@ -699,26 +733,51 @@ static void key_check(EVENT_MSG *msg,void **unused)
unused;
if (msg->msg==E_KEYBOARD)
{
int c = va_arg(msg->data, int);
int c = va_arg(msg->data, int) >> 8;
char redraw = 0;
switch (c) {
case 1:dlg_konec(0,0,0,0,0);break;
case 17:
case 'H':if (vyb_volba==0) his_line-=(his_line>0);
else vyb_volba--;
redraw = 1;
break;
case 31:
case 'P':if (his_line<last_his_line) his_line++;
else if (vyb_volba+1<pocet_voleb) vyb_volba++;
redraw = 1;
break;
case 28:
case 57:dialog_cont();break;
}
if (redraw) {
schovej_mysku();
redraw_text();
ukaz_mysku();
showview(TEXT_X,TEXT_Y,TEXT_XS,TEXT_YS);
}
/*
d=c>>8;
if (c & 0xFF)
{
switch(d)
{
case 17:
case 'H':if (vyb_volba==0) his_line-=(his_line>0);else vyb_volba--;break;
case 31:
case 'P':if (his_line<last_his_line) his_line++;else if (vyb_volba+1<pocet_voleb) vyb_volba++;break;
}
schovej_mysku();
redraw_text();
ukaz_mysku();
showview(TEXT_X,TEXT_Y,TEXT_XS,TEXT_YS);
}
else if (c==13||c==32)
{
dialog_cont();
msg->msg=-1;
}
else if (c==27) konec(0,0,0,0,0);
else if (c==27) {
dlg_konec(0,0,0,0,0);
}*/
}
}
@ -729,7 +788,7 @@ void wire_dialog_drw()
wire_dialog();
draw_all();
ukaz_mysku();
showview(0,0,0,0);
effect_show(NULL);
}
void unwire_dialog(void)
{

View file

@ -773,7 +773,7 @@ int save_game(long game_time,char *gamename, char is_autosave)
fclose(svf);
}
SEND_LOG("(SAVELOAD) Game saved.... Result %d",r);
disable_intro();
play_fx_at(FX_SAVE);
return r;
}
@ -1099,7 +1099,10 @@ static void free_savegame_list(TSAVEGAME_LIST *lst) {
release_list(lst->names);
lst->files = 0;
lst->names = 0;
free(lst->autosave_flags);
if (lst->autosave_flags) {
free(lst->autosave_flags);
lst->autosave_flags = NULL;
}
}
static void place_name(int c,int i,char show, char sel)
@ -1245,7 +1248,7 @@ static void read_story(int slot)
static void read_story(const char *filename) {
void *text_data;
int32_t size;
int32_t size = 0;
TSTR_LIST ls;
char *c,*d;

View file

@ -733,6 +733,7 @@ void draw_blood(char mode,int mob_dostal,int mob_dostal_pocet);
#define FX_BOOK 1
#define FX_MONEY 2
#define FX_MAP 3
#define FX_SAVE 4
@ -1415,6 +1416,7 @@ char ask_save_dialog(char *name_buffer, size_t name_size);
void do_autosave();
#define autosave() if (autosave_enabled) do_autosave();
extern char autosave_enabled;
extern char autosave_on_enter;
int load_map_automap(char *mapfile);
/* ^^^ Tato funkce zmeni mapu, bez zmeny grafiky a stavu cele hry.
Jeji vyuziti je pro zobrazeni automapingu jineho levelu nez aktualniho

View file

@ -1487,7 +1487,7 @@ static void smlouvat_enter(EVENT_MSG *msg,OBJREC *o)
if (msg->msg==E_KEYBOARD)
{
int c = va_arg(msg->data, int);
switch(c)
switch(c & 0xFF)
{
case 13:goto_control(30);terminate_gui();break;
case 27:goto_control(20);terminate_gui();break;
@ -1507,7 +1507,7 @@ THAGGLERESULT smlouvat_dlg(int cena,int puvod,int pocet,int posledni, int money,
define(-1,150,15,100,13,0,label,int2ascii(cena,buffer,10));
set_font(H_FBOLD,MSG_COLOR1);
define(-1,10,30,1,1,0,label,texty[238]);
define(10,150,30,100,13,0,input_line,8);property(def_border(5,BAR_COLOR),NULL,NULL,0);set_default("");
define(10,150,30,100,13,0,input_line,8,0,0,"");property(def_border(5,BAR_COLOR),NULL,NULL,0);set_default("");
on_control_event(smlouvat_enter);
define(20,20,20,80,20,2,button,texty[239]);property(def_border(5,BAR_COLOR),NULL,NULL,BAR_COLOR);on_control_change(terminate_gui);
define(30,110,20,80,20,2,button,texty[230]);property(def_border(5,BAR_COLOR),NULL,NULL,BAR_COLOR);on_control_change(terminate_gui);
@ -1516,7 +1516,9 @@ THAGGLERESULT smlouvat_dlg(int cena,int puvod,int pocet,int posledni, int money,
schovej_mysku();set_font(H_FBOLD,RGB555(31,31,31));
ukaz_mysku();
goto_control(10);
send_message(E_ADD,E_KEYBOARD, smlouvat_enter);
escape();
send_message(E_DONE,E_KEYBOARD, smlouvat_enter);
res.message = 0;
res.hprice = posledni;
res.canceled = 1;

View file

@ -2845,7 +2845,7 @@ char shop_keeper_click(int id, int xa, int ya, int xr, int yr) {
price = make_offer(z = picked_item[0]);
if (!price) {
sprintf(c, texty[103], glob_items[z - 1].jmeno);
message(1, 0, 0, "", c, texty[80]);
message(1, 0, 1, "", c, texty[80]);
wire_shop();
} else {
int p;
@ -2853,7 +2853,7 @@ char shop_keeper_click(int id, int xa, int ya, int xr, int yr) {
pp = find_sell_product(z);
sprintf(c, texty[102], price);
p = message(3, 0, 1, texty[118], c, texty[77], texty[230],
p = message(3, 0, 2, texty[118], c, texty[77], texty[230],
texty[78]);
if (p == 2) {
price = -1;
@ -2928,10 +2928,10 @@ char shop_bag_click(int id, int xa, int ya, int xr, int yr) {
mouse_set_cursor(H_MS_DEFAULT);
if (!price) return 0;
if (price > money) {
p = message(2, 0, 0, "", texty[104], texty[230], texty[78]) + 1;
p = message(2, 0, 1, "", texty[104], texty[230], texty[78]) + 1;
} else {
sprintf(s, texty[101], price);
p = message(3, 0, 1, texty[118], s, texty[77], texty[230], texty[78]);
p = message(3, 0, 2, texty[118], s, texty[77], texty[230], texty[78]);
}
if (p == 1) {
redraw_shop();

View file

@ -199,6 +199,8 @@ void macro_send_act(const TMA_SEND_ACTION *p)
delay_action(p->s_action,p->sector,p->side,p->change_bits<<24,0,p->delay);
}
char autosave_on_enter = 0;
void macro_load_another_map(const TMA_LOADLEV *z)
{
// int i,j=0;
@ -221,6 +223,7 @@ void macro_load_another_map(const TMA_LOADLEV *z)
*/
loadlevel=*z;
save_map=1;
autosave_on_enter = 1;
send_message(E_CLOSE_MAP);
}

View file

@ -87,8 +87,8 @@ static char click(int id,int xa,int ya,int xr,int yr)
T_CLK_MAP clk_main_menu[]=
{
{-1,220,300,220+206,300+178,promacknuti,1,-1},
{-1,220,300,220+206,300+178,click,2,-1},
{-1,220,300,220+206,300+177,promacknuti,1,-1},
{-1,220,300,220+206,300+177,click,2,-1},
{-1,0,0,639,479,vymacknout,1,-1},
{-1,0,0,639,479,empty_clk,0xff,H_MS_DEFAULT},
};

View file

@ -1018,6 +1018,8 @@ void init_skeldal(const INI_CONFIG *cfg)
load_items();
load_shops();
memset(&loadlevel,0,sizeof(loadlevel));
loadlevel.eflags = 0xFF;
SetWheelMapping('H','P');
}
@ -1110,8 +1112,11 @@ void enter_game(void)
wire_main_functs();
add_to_timer(TM_FAST_TIMER,2,-1,objekty_mimo);
cancel_pass=0;
autosave();
set_game_click_map();
if (autosave_on_enter) {
autosave();
autosave_on_enter = 0;
}
send_message(E_ADD,E_RELOADMAP,reload_map_handler);
{
@ -1376,7 +1381,9 @@ static void game_big_circle(char enforced)
leave_current_map();
strcopy_n(s,loadlevel.name,sizeof(s));
if (s[0]!=0)err=load_map(s);
if (s[0]!=0) {
err=load_map(s);
}
memset(GlobEventList,0,sizeof(GlobEventList));
}

View file

@ -679,7 +679,7 @@ void input_line_init(OBJREC *o,va_list len)
st->minimum = va_arg(len, int);
st->maximum = va_arg(len, int);
st->format = va_arg(len, char * );
o->datasize=st->len;
o->datasize=st->len+1;
o->userptr = st;
}

View file

@ -801,11 +801,21 @@ void set_window_modal(void)
waktual->modal=1;
}
void set_object_value(char redraw,OBJREC *o,void *value)
static void set_object_value(char redraw,OBJREC *o,const char *value)
{
if (memcmp(o->data,value,o->datasize))
if (strncmp(o->data, value, o->datasize))
{
memcpy(o->data,value,o->datasize);
strcopy_n(o->data,value,o->datasize);
if (redraw) redraw_object(o);
}
}
static void set_object_value_bin(char redraw,OBJREC *o,const void *value, size_t sz)
{
size_t cpsz = MIN(o->datasize, sz);
if (memcmp(o->data,value,cpsz))
{
memcpy(o->data,value,cpsz);
if (redraw) redraw_object(o);
}
}
@ -843,11 +853,24 @@ void set_value(int win_id,int obj_id,void *value)
set_object_value((w==waktual),o,value);
}
void set_default(void *value)
void set_value_bin(int win_id,int obj_id,void *value, size_t value_size) {
OBJREC *o;
WINDOW *w;
if ((o=find_object_desktop(win_id,obj_id,&w))==NULL)return;
set_object_value_bin((w==waktual),o,value, value_size);
}
void set_default(const char *value)
{
set_object_value(0,o_end,value);
}
void set_default_bin(const void *value, size_t value_size) {
set_object_value_bin(0, o_end, value, value_size);
}
void goto_control(int obj_id)
{
EVENT_MSG msg;
@ -864,12 +887,12 @@ void c_set_value(int win_id,int obj_id,int cnst)
WINDOW *w;
if ((o=find_object_desktop(win_id,obj_id,&w))==NULL)return;
set_object_value((w==waktual),o,&cnst);
set_object_value_bin((w==waktual),o,&cnst,sizeof(cnst));
}
void c_default(int cnst)
{
set_object_value(0,o_end,&cnst);
set_object_value_bin(0,o_end,&cnst,sizeof(cnst));
}

View file

@ -153,7 +153,9 @@ void on_control_event(void (*proc)(EVENT_MSG *, struct objrec *));
void terminate_gui(void);
void set_change(void);
void set_value(int win_id,int obj_id,void *value);
void set_default(void *value);
void set_value_bin(int win_id,int obj_id,void *value, size_t value_size);
void set_default(const char *value);
void set_default_bin(const void *value, size_t value_size);
void c_set_value(int win_id,int obj_id,int cnst);
void c_default(int cnst);
int f_get_value(int win_id,int obj_id);

View file

@ -34,18 +34,27 @@ void SDLContext::SDL_Audio_Deleter::operator()(SDL_AudioDeviceID x) {
struct SDL_INIT_Context {
SDL_INIT_Context() {
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_AUDIO) < 0) {
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_AUDIO|SDL_INIT_JOYSTICK) < 0) {
SDL_Log("Unable to initialize SDL: %s", SDL_GetError());
exit(1);
}
if (SDL_NumJoysticks() > 0) {
if (SDL_IsGameController(0)) {
controller = SDL_JoystickOpen(0);
SDL_JoystickEventState(SDL_ENABLE);
}
}
inited = true;
}
~SDL_INIT_Context() {
if (controller) SDL_JoystickClose(controller);
SDL_Quit();
}
bool inited = false;
SDL_Joystick *controller = nullptr;
};
static SDL_INIT_Context init_context = {};
@ -148,7 +157,9 @@ void SDLContext::generateCRTTexture(SDL_Renderer* renderer, SDL_Texture** textur
void SDLContext::init_video(const VideoConfig &config, const char *title) {
char buff[256];
static Uint32 update_request_event = SDL_RegisterEvents(1);
static Uint32 refresh_request_event = SDL_RegisterEvents(1);
_update_request_event = update_request_event;
_refresh_request = refresh_request_event;
assert(!_render_thread.joinable());
@ -243,6 +254,91 @@ void SDLContext::close_video() {
_render_thread.join();
}
int SDLContext::check_axis_dir(int &cooldown, int value) {
if (cooldown>0) {
cooldown -= 0x400;
} else {
if (value > 0) {
cooldown = 0x5000-value;
return 1;
}
if (value < 0) {
cooldown = 0x5000+value;
return -1;
}
}
return 0;
}
static int adjust_deadzone(int v) {
if (v > 0x4000) return v - 0x4000;
if (v < -0x4000) return v + 0x4000;
return 0;
}
static int axis_dynamic(int c) {
double f = std::floor(std::pow(std::abs(c)*0.001,2)*0.02)+0.5;
if (c < 0) return static_cast<int>(-f);
else return static_cast<int>(f);
}
void SDLContext::joystick_handle() {
int a1 = SDL_JoystickGetAxis(init_context.controller, 0);
int a2 = SDL_JoystickGetAxis(init_context.controller, 1);
if (std::abs(a1) - std::abs(a2) > 0x1000) a2 = 0;
else if (std::abs(a2) - std::abs(a1) >0x1000) a1 = 0;
else {
a1 = 0;
a2 = 0;
}
int axis1 = check_axis_dir(axis1_cooldown,adjust_deadzone(a1));
int axis2 = check_axis_dir(axis2_cooldown,adjust_deadzone(a2));
int axis3 = axis_dynamic(SDL_JoystickGetAxis(init_context.controller,2));
int axis4 = axis_dynamic(SDL_JoystickGetAxis(init_context.controller,3));
int newx = this->ms_event.x + axis3;
int newy = this->ms_event.y + axis4;
if (newx <0) newx = 0;
if (newx > 639) newx = 639;
if (newy <0) newy = 0;
if (newy > 479) newy = 479;
if (axis3 || axis4) {
this->ms_event.x = (uint16_t)newx;
this->ms_event.y = (uint16_t)newy;
this->ms_event.event = 1;
this->ms_event.event_type = 1;
if (_mouse) {
SDL_Point pt(this->ms_event.x, this->ms_event.y);
SDL_Rect winrc = get_window_aspect_rect();
pt = to_window_point(winrc,pt);
_mouse_rect.x = pt.x;
_mouse_rect.y = pt.y;
SDL_Event event;
event.type = _refresh_request;
SDL_PushEvent(&event);
}
}
SDL_Scancode scn = {};
switch(axis2) {
case -1: scn = SDL_SCANCODE_UP;break;
case 1: scn = SDL_SCANCODE_DOWN;break;
default:break;
}
switch(axis1) {
case -1: scn = SDL_SCANCODE_LEFT;break;
case 1: scn = SDL_SCANCODE_RIGHT;break;
default:break;
}
if (scn != SDL_Scancode{}) {
std::lock_guard _(_mx);
_keyboard_queue.push(sdl_keycode_map.get_bios_code(scn,false, false));
}
}
void SDLContext::event_loop(std::stop_token stp) {
static Uint32 exit_loop_event = SDL_RegisterEvents(1);
@ -252,8 +348,17 @@ void SDLContext::event_loop(std::stop_token stp) {
SDL_PushEvent(&event);
});
if (init_context.controller) {
SDL_AddTimer(25,[](Uint32 tm, void *ptr){
SDLContext *me = reinterpret_cast<SDLContext *>(ptr);
me->joystick_handle();
return tm;
}, this);
}
SDL_Event e;
while (SDL_WaitEvent(&e)) {
SDL_Scancode kbdevent = {};
if (e.type == SDL_QUIT) {
_quit_requested = true;
if (_quit_callback) _quit_callback();
@ -261,6 +366,8 @@ void SDLContext::event_loop(std::stop_token stp) {
break;
} else if (e.type == _update_request_event) {
update_screen();
} else if (e.type == _refresh_request) {
update_screen(true);
} else if (e.type == SDL_WINDOWEVENT) {
if (e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
_crt_effect.reset();
@ -316,6 +423,54 @@ void SDLContext::event_loop(std::stop_token stp) {
if (e.type == SDL_MOUSEBUTTONDOWN && e.button.clicks == 2 && e.button.button == 1) {
ms_event.event_type |= MS_EVENT_MOUSE_LDBLCLK;
}
} else if (e.type == SDL_MOUSEWHEEL) {
if (e.wheel.y > 0) kbdevent =SDL_SCANCODE_UP;
else if (e.wheel.y < 0) kbdevent =SDL_SCANCODE_DOWN;
} else if (e.type == SDL_JOYBUTTONDOWN) {
switch (e.jbutton.button) {
case 3: kbdevent = SDL_SCANCODE_SPACE; break;
case 2: kbdevent = SDL_SCANCODE_RETURN; break;
case 9: kbdevent = SDL_SCANCODE_END;break;
case 7: kbdevent = SDL_SCANCODE_ESCAPE;break;
case 10:kbdevent = SDL_SCANCODE_PAGEDOWN;break;
case 11:kbdevent = SDL_SCANCODE_UP;break;
case 12:kbdevent = SDL_SCANCODE_DOWN;break;
case 13:kbdevent = SDL_SCANCODE_LEFT;break;
case 14:kbdevent = SDL_SCANCODE_RIGHT;break;
case 0: ms_event.event = 1;
ms_event.event_type |= MS_EVENT_MOUSE_LPRESS;
ms_event.tl1 = 1;
break;
case 8: ms_event.event = 1;
ms_event.event_type |= MS_EVENT_MOUSE_LPRESS|MS_EVENT_MOUSE_LDBLCLK;
ms_event.tl1 = 1;
break;
case 1: ms_event.event = 1;
ms_event.event_type |= MS_EVENT_MOUSE_RPRESS;
ms_event.tl1 = 1;
break;
default: break;
}
} else if (e.type == SDL_JOYBUTTONUP) {
switch (e.jbutton.button) {
case 0: ms_event.event = 1;
ms_event.event_type |= MS_EVENT_MOUSE_LRELEASE;
ms_event.tl1 = 0;
break;
case 8:
case 1: ms_event.event = 1;
ms_event.event_type |= MS_EVENT_MOUSE_RRELEASE;
ms_event.tl1 = 1;
break;
default: break;
}
}
if (kbdevent != SDL_Scancode{}) {
auto code =sdl_keycode_map.get_bios_code(kbdevent,false, false);
std::lock_guard _(_mx);
_keyboard_queue.push(code);
}
}

View file

@ -197,7 +197,15 @@ protected:
SDL_Point _mouse_finger;
SpriteList _sprites;
int axis1_cooldown = 0;
int axis2_cooldown = 0;
int axis3_cooldown = 0;
int axis4_cooldown = 0;
int check_axis_dir(int &cooldown, int value);
Uint32 _update_request_event;
Uint32 _refresh_request;
void event_loop(std::stop_token stp);
@ -233,4 +241,6 @@ protected:
void push_hi_image(const unsigned short *image);
void update_zindex();
void joystick_handle();
};