diff --git a/game/builder.c b/game/builder.c index 6d34914..e100514 100644 --- a/game/builder.c +++ b/game/builder.c @@ -327,11 +327,14 @@ static const void *bott_draw_normal(const void *pp, int32_t *s) { char c[]=" ";int z,lv,llv; put_picture(x,0,ablock(H_OKNO));lv=p->lives;llv=p->vlastnosti[VLS_MAXHIT]; - if (lv || p->used & 0x80) + if (lv || p->used & 0x80 || p->kondice > 0) { z=3-((lv-1)*4/llv);if (lv==llv) z=0; z*=75; if (p->xicht>=0)put_8bit_clipped(ablock(H_XICHTY+i),bott_scr+PIC_X+x+PIC_Y*scr_linelen2,z,54,75); + if (!lv && !(p->used & 0x80) && p->kondice>0) { + greyscale_rectangle(PIC_X+x,PIC_Y, 54, 75); + } if (p->bonus) draw_small_icone(0,PIC_X+x+1,PIC_Y+1); if (p->spell) draw_small_icone(1,PIC_X+x+1,PIC_Y+1); if (!p->voda) draw_small_icone(2,PIC_X+x+1,PIC_Y+1); diff --git a/game/clk_map.c b/game/clk_map.c index 14e7fff..8de93e1 100644 --- a/game/clk_map.c +++ b/game/clk_map.c @@ -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|MS_EVENT_MOUSE_LDBLCLK)) + if (ms_last_event.event_type & (0x2)) { - if (get_control_key_state() || (ms_last_event.event_type & MS_EVENT_MOUSE_LDBLCLK)) + if (get_control_key_state() ) { if (p->sektor==viewsector) { @@ -465,7 +465,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+MS_EVENT_MOUSE_LDBLCLK,-1}, + {-1,54,378,497,479,start_invetory,2+8,-1}, {-1,315,0,335,14,spell_casting,2,-1}, }; diff --git a/game/dialogy.c b/game/dialogy.c index ebc34db..ead61d0 100644 --- a/game/dialogy.c +++ b/game/dialogy.c @@ -1037,11 +1037,13 @@ char drop_character() static char dead_players=0; - char is_player_near(int sector, THUMAN *p, int exclude_dir) { + char is_player_near(int sector, THUMAN *p) { + if (mob_map[sector]) return 0; if (sector == p->sektor) return 1; - for (int i = 0; i < 4; ++i) if (i != exclude_dir) { - if (map_sectors[sector].step_next[i] == p->sektor - && (map_sides[sector * 4 + i].flags & SD_PLAY_IMPS) == 0) return 1; + for (int i = 0; i < 4; ++i) { + int s = map_sectors[sector].step_next[i]; + if (mob_map[s]) continue; + if (s == p->sektor && (map_sides[sector * 4 + i].flags & SD_PLAY_IMPS) == 0) return 1; } return 0; } @@ -1052,10 +1054,10 @@ char can_select_player(THUMAN *p, char select_dead, char select_far) { p->sektor == 0 || p->sektor == viewsector)) return 1; } else { int side = (viewsector << 2) + viewdir; - if (p->used && p->lives != 0 && (select_far || + if (p->used && !(p->lives == 0 && p->kondice == 0) && (select_far || (p->sektor == viewsector || ((map_sides[side].flags & SD_PLAY_IMPS) == 0 - && is_player_near(map_sectors[viewsector].step_next[viewdir], p, viewdir) + && is_player_near(map_sectors[viewsector].step_next[viewdir], p) )))) return 1; diff --git a/game/enemy.c b/game/enemy.c index 17f71b4..7a5811c 100644 --- a/game/enemy.c +++ b/game/enemy.c @@ -487,21 +487,21 @@ char je_mozne_videt(int sector1, int sector2, int flag) { for (x = 0; x <= xs; x++) { y = (x + 1) * ys / (xs + 1); while (y > ly) { - if ((map_sides[(s << 2)].flags & flag) != (unsigned) flag) { + if ((map_sides[(s << 2)].flags & flag) == 0) { s = map_sectors[s].step_next[0]; ly++; } else return 0; } while (y < ly) { - if ((map_sides[(s << 2) + 2].flags & flag) != (unsigned) flag) { + if ((map_sides[(s << 2) + 2].flags & flag) == 0) { s = map_sectors[s].step_next[2]; ly--; } else return 0; } if (x != xs) { - if ((map_sides[(s << 2) + 3].flags & flag) != (unsigned) flag) { + if ((map_sides[(s << 2) + 3].flags & flag) == 0) { s = map_sectors[s].step_next[3]; } else { return 0; @@ -512,19 +512,19 @@ char je_mozne_videt(int sector1, int sector2, int flag) { for (x = 0; x >= xs; x--) { y = (x - 1) * ys / (xs - 1); while (y > ly) - if ((map_sides[(s << 2)].flags & flag) != (unsigned) flag) { + if ((map_sides[(s << 2)].flags & flag) == 0) { s = map_sectors[s].step_next[0]; ly++; } else return 0; while (y < ly) - if ((map_sides[( s << 2) + 2].flags & flag) != (unsigned) flag) { + if ((map_sides[( s << 2) + 2].flags & flag) == 0) { s = map_sectors[s].step_next[2]; ly--; } else return 0; if (x != xs) { - if ((map_sides[(s << 2) + 1].flags & flag) != (unsigned) flag) { + if ((map_sides[(s << 2) + 1].flags & flag) == 0) { s = map_sectors[s].step_next[1]; } else { return 0; @@ -559,8 +559,10 @@ int q_vidis_postavu(int sector,int dir,TMOB *p,int *otocit_se,char ret) case 2:ok=ys<=0;break; case 3:ok=xs>=0;break; } - if (ok) - if (je_mozne_videt(sector,postavy[i].sektor,SD_MONST_IMPS | SD_PLAY_IMPS)) + if (ok) { + char shoots = p->stay_strategy & MOB_ROGUE; + int block_flag = shoots && MIN(abs(xs),abs(ys)) == 0?(SD_THING_IMPS):(SD_MONST_IMPS|SD_PLAY_IMPS); + if (je_mozne_videt(sector,postavy[i].sektor,block_flag)) { int alt = 0; if (ys>=abs(xs)) {nd=0;alt=xs>0?3:1;} @@ -580,8 +582,8 @@ int q_vidis_postavu(int sector,int dir,TMOB *p,int *otocit_se,char ret) } } } - else d=255; - else d=255; + else d=255; + } else d=255; if (d!=255) { d*=2; diff --git a/game/globals.h b/game/globals.h index 5255c2b..ec3fe1d 100644 --- a/game/globals.h +++ b/game/globals.h @@ -939,6 +939,7 @@ typedef struct thuman uint8_t groupnum; //cislo skupiny 0-6 int8_t xicht; //cislo obliceje 0-5 uint8_t direction; //smer otoceni + uint8_t downpoints; //pokud mrtva postava ma nejake body, tak ji lze ozivit lecenim short sektor; //sektor postaveni short vlastnosti[VLS_MAX]; //mapa aktualnich vlastnosti po korekcich short bonus_zbrani[TPW_MAX]; //bonusy za zbrane @@ -1592,6 +1593,7 @@ int vypocet_zasahu(const short *utocnik,const short *obrance, int chaos,int zbr void rozhodni_o_smeru(TMOB *p); void krok_moba(TMOB *p); void pomala_regenerace_postavy(THUMAN *p); +void umirani_postavy(THUMAN *p); char zasah_veci(int sector,TFLY *fl); void vymaz_zasahy(THE_TIMER *q); char check_end_game(void); diff --git a/game/inv.c b/game/inv.c index b7d6bed..e3ef8f8 100644 --- a/game/inv.c +++ b/game/inv.c @@ -1078,6 +1078,7 @@ char check_jidlo_voda(THUMAN *p) char check_map_specials(THUMAN *p) { char c=0; + if (p->inmaphash != current_map_hash) return; switch(mglob.map_effector) { case ME_NORMAL:break; @@ -1088,6 +1089,10 @@ char check_map_specials(THUMAN *p) return c; } +void umirani_postavy(THUMAN *p) { + p->kondice = MAX(0, p->kondice - p->vlastnosti[VLS_KONDIC]/4); +} + void pomala_regenerace_postavy(THUMAN *p) { int mreg,mmax; @@ -1111,6 +1116,13 @@ void pomala_regenerace_postavy(THUMAN *p) char sleep_regenerace(THUMAN *p) { int mreg,mmax; + if (p->used && (!p->lives) && p->kondice>0) { + if (p->inmaphash == current_map_hash) { + p->lives = 1; + } else { + p->kondice = 0; + } + } if (p->used && p->lives && p->inmaphash == current_map_hash) { if (check_jidlo_voda(p)) return 1; @@ -1135,8 +1147,12 @@ void real_regeneration(THE_TIMER *t) for(i=0;iused && p->lives) - pomala_regenerace_postavy(p); + if (p->used) + if (p->lives) { + pomala_regenerace_postavy(p); + } else { + umirani_postavy(p); + } } send_message(E_KOUZLO_KOLO); sleep_ticks+=MAX_SLEEP/30; @@ -2479,10 +2495,10 @@ T_CLK_MAP clk_shop[]= { {-1,54,378,497,479,shop_change_player,2+8,-1}, {-1,0,0,639,479,_exit_shop,8,-1}, - {-1,INV_X,INV_Y,INV_X+INV_XS*6,INV_Y+INV_YS*5,shop_bag_click,MS_EVENT_MOUSE_LDBLCLK|MS_EVENT_MOUSE_LPRESS,-1}, + {-1,INV_X,INV_Y,INV_X+INV_XS*6,INV_Y+INV_YS*5,shop_bag_click,MS_EVENT_MOUSE_LPRESS,-1}, {1,2+BUYBOX_X,39+BUYBOX_Y,22+BUYBOX_X,76+BUYBOX_Y,shop_block_click,2,H_MS_DEFAULT}, {2,246+BUYBOX_X,39+BUYBOX_Y,266+BUYBOX_X,76+BUYBOX_Y,shop_block_click,2,H_MS_DEFAULT}, - {-1,BUYBOX_X+SHP_ICPLCX,17,BUYBOX_X+SHP_ICPLCX+4*SHP_ICSIZX,BUYBOX_Y+SHP_ICPLCY+2*SHP_ICSIZY,shop_keeper_click,MS_EVENT_MOUSE_LDBLCLK|MS_EVENT_MOUSE_LPRESS,-1}, + {-1,BUYBOX_X+SHP_ICPLCX,17,BUYBOX_X+SHP_ICPLCX+4*SHP_ICSIZX,BUYBOX_Y+SHP_ICPLCY+2*SHP_ICSIZY,shop_keeper_click,MS_EVENT_MOUSE_LPRESS,-1}, {-1,0,17,BUYBOX_X+SHP_ICPLCX,BUYBOX_Y,shop_keeper_click,2,-1}, {-1,337,0,357,14,go_map,2,H_MS_DEFAULT}, {-1,87,0,142,14,game_setup,2,H_MS_DEFAULT}, diff --git a/game/kouzla.c b/game/kouzla.c index a2f34b4..e50fc9e 100644 --- a/game/kouzla.c +++ b/game/kouzla.c @@ -143,8 +143,10 @@ typedef struct tkouzlo short cil; //2 //kladna cisla jsou postavy zaporna potvory (0 je bez urceni postavy) char povaha; char traceon; //jinak noanim - neprehravaji se animace a zvuky - //paddding 1 byte - word backfire; //backfire / 1 = demon , 0 = bez demona + union { + word backfire; //backfire + word demon; // 1 = demon , 0 = bez demona + } bkdm; word wait; //wait - cekani pocet animaci word delay; //delay - cekani pocet kol char spellname[28]; @@ -694,7 +696,7 @@ static void unaffect_after_demon(int cil) a=0; for(i=0;icil==cil && spl->backfire==1) + if (spl!=NULL && spl->cil==cil && spl->bkdm.demon==1) { if (spl->wait) { @@ -763,6 +765,7 @@ static void spell_demon(int num,TKOUZLO *spl,int cil,int demon) cil--; if (postavy[cil].stare_vls[VLS_KOUZLA] & SPL_DEMON) return; spl->owner=demon; + spl->bkdm.demon = 1; zmena_demona(cil,demon,1); postavy[cil].stare_vls[VLS_KOUZLA]|=SPL_DEMON; _flag_map[num]|=SPL_DEMON; @@ -1476,10 +1479,9 @@ void call_spell(int i) if (cil>0) { cil--; - if (postavy[cil].stare_vls[VLS_KOUZLA] & SPL_DEMON && ~_flag_map[i] & SPL_DEMON && p->backfire==0) + if (postavy[cil].vlastnosti[VLS_KOUZLA] & SPL_DEMON && !p->bkdm.demon && !p->delay) { - p->wait=1; - return; + p->delay=1; } } if (p->delay) return; @@ -1742,7 +1744,7 @@ int add_spell(int num,int cil,int owner,char noanim) p->owner=owner; p->traceon=noanim; p->teleport_target=teleport_target; - if (cil>0) p->backfire=(postavy[cil-1].stare_vls[VLS_KOUZLA] & SPL_DEMON)!=0; + if (cil>0) p->bkdm.demon=(postavy[cil-1].stare_vls[VLS_KOUZLA] & SPL_DEMON)!=0; aunlock(H_KOUZLA); spell_table[i]=p; if (cil>0 && owner>=0) postavy[cil-1].spell=1; @@ -1888,7 +1890,7 @@ void cast(int num,THUMAN *p,int owner, char backfire) if (um*2um) return; per1=(um-k->um/2)*128/k->um; per2=rnd(64); - if ((per1/2+32)backfire || (game_extras & EX_RANDOM_BACKFIRES)!=0)) + if ((per1/2+32)bkdm.backfire || (game_extras & EX_RANDOM_BACKFIRES)!=0)) { p->mana-=k->mge; if ((game_extras & EX_RANDOM_BACKFIRES)!=0) @@ -1899,7 +1901,7 @@ void cast(int num,THUMAN *p,int owner, char backfire) cast(rand()*105/RAND_MAX+(cil*512),p,p-postavy,1); return; } - cast(k->backfire+(cil<<9),p,owner,1); + cast(k->bkdm.backfire+(cil<<9),p,owner,1); return; } if(per1cil==cil) + for(i=0;spl=spell_table[i],icil==cil && spl->bkdm.demon) { while (spell_table[i]!=NULL) { diff --git a/game/souboje.c b/game/souboje.c index cc29b5f..a9370a9 100644 --- a/game/souboje.c +++ b/game/souboje.c @@ -736,6 +736,7 @@ void konec_kola() if (jprogramovano=(char)p->actions; } + } else if (p->used && !p->lives) { + umirani_postavy(p); } } rozhodni_o_poradi(); unwire_proc(); wire_jadro_souboje(); - send_message(E_KOUZLO_KOLO); + } static char add_pc_action(int d) { @@ -2684,7 +2687,7 @@ char player_check_death(THUMAN *p, char afterround) } p->groupnum=0; p->lives=0; - p->kondice=0; +// p->kondice=0; p->mana=0; SEND_LOG("(GAME) Character '%s' died. R.I.P.",p->jmeno); if (numplayers(p->sektor,0)==0) map_coord[p->sektor].flags &=~MC_PLAYER; diff --git a/libs/bgraph.h b/libs/bgraph.h index bc926bb..c459242 100644 --- a/libs/bgraph.h +++ b/libs/bgraph.h @@ -148,5 +148,7 @@ void put_picture2picture(const word *source,word *target,int xp,int yp); void draw_rounded_rectangle(int x, int y, int xs, int ys, int radius, int stroke_color, int fill_color); +void greyscale_rectangle_ex(int x, int y, int xs, int ys, uint16_t *screen_address, size_t line_width); +void greyscale_rectangle(int x, int y, int xs, int ys); #define swap_int(a,b) do {int c=a;a=b;b=c;} while (0); diff --git a/libs/bgraph2.c b/libs/bgraph2.c index 1ca90c5..d1c6532 100644 --- a/libs/bgraph2.c +++ b/libs/bgraph2.c @@ -789,3 +789,27 @@ void draw_rounded_rectangle(int x, int y, int xs, int ys, int radius, } } } + +void greyscale_rectangle_ex(int x, int y, int xs, int ys, uint16_t *screen_address, size_t line_width) { + for (int j = y; j < y + ys; j++) { + for (int i = x; i < x + xs; i++) { + uint16_t *pixel = screen_address + j * line_width + i; + uint16_t color = *pixel; + + // Extract RGB components (5 bits each) + int r = (color >> 10) & 0x1F; + int g = (color >> 5) & 0x1F; + int b = color & 0x1F; + + // Calculate greyscale value (average of RGB) + int grey = (r + g + b) / 3; + + // Reconstruct the pixel with the MSB intact + *pixel = (color & 0x8000) | (grey << 10) | (grey << 5) | grey; + } + } +} + +void greyscale_rectangle(int x, int y, int xs, int ys) { + greyscale_rectangle_ex(x,y,xs,ys,GetScreenAdr(),GetScreenPitch()); +} diff --git a/libs/mouse.h b/libs/mouse.h index daaab03..a447c62 100644 --- a/libs/mouse.h +++ b/libs/mouse.h @@ -14,7 +14,7 @@ extern "C" { #define MS_EVENT_MOUSE_RRELEASE 16 #define MS_EVENT_MOUSE_MPRESS 32 #define MS_EVENT_MOUSE_MRELEASE 64 -#define MS_EVENT_MOUSE_LDBLCLK 128 + typedef struct ms_event { diff --git a/platform/sdl/sdl_context.cpp b/platform/sdl/sdl_context.cpp index aedbbe0..d3928b0 100644 --- a/platform/sdl/sdl_context.cpp +++ b/platform/sdl/sdl_context.cpp @@ -552,9 +552,6 @@ void SDLContext::event_loop(std::stop_token stp) { case 3: ms_event.tl2 = !up; shift = 3; break; } ms_event.event_type |= (1<<(shift+up)); - 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;