gates_of_skeldal/game/globmap.c
2025-02-02 21:50:52 +01:00

665 lines
15 KiB
C
Raw Blame History

#include <platform/platform.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <math.h>
#include <libs/types.h>
#include <libs/event.h>
#include <libs/memman.h>
#include <ctype.h>
#include <libs/devices.h>
#include <libs/bmouse.h>
#include <libs/bgraph.h>
#include <platform/sound.h>
#include <libs/strlite.h>
#include "engine1.h"
#include <libs/pcx.h>
#include "globals.h"
#include <string.h>
#include <unistd.h>
#define GLOBMAP "GLOBMAP.DAT"
#define ODDELOVACE ";:=,\n\r{}"
#define OD_COMMAND oddelovace[0]
#define OD_CRIT oddelovace[1]
#define OD_SET oddelovace[2]
#define OD_COMMA oddelovace[3]
#define OD_NEWLINE oddelovace[4]
#define OD_CR oddelovace[5]
#define OD_IN oddelovace[6]
#define OD_OUT oddelovace[7]
#define OD_COMMENT '`'
#define INDEXU 256
typedef struct index_def
{
char mapname[13];
char *text;
char defined;
}INDEX_DEF;
static INDEX_DEF *index_tab=NULL;
static uint8_t last_index=1;
static int usemap;
static FILE *glbm;
static char oddelovace[]=ODDELOVACE;
static int last_oddelovac;
static int linecounter=0;
static int enter_sector=0;
static char *symbolmap[]=
{
"A !",
"B &&",
"D BREAK",
"O CURMAP", // krit
"E DRAW",
"F ESCAPE",
"G FLG", // krit
"P IFDEF", // krit
"I INDX",
"I INDEX",
"K MAP",
"Q SEKTOR", // krit
"Q SECTOR", // krit
"L TEXT",
"M UNDEF",
"N USEMAP",
"C ||",
};
#define OP_NOT 'A'
#define OP_AND 'B'
#define OP_OR 'C'
#define OP_INDX 'I'
#define OP_DRAW 'E'
#define OP_TEXT 'L'
#define OP_MAP 'K'
#define OP_UNDEF 'M'
#define OP_FLG 'G'
#define OP_USEMAP 'N'
#define OP_BREAK 'D'
#define OP_ESCAPE 'F'
#define OP_CURMAP 'O'
#define OP_ISDEF 'P'
#define OP_SEKTOR 'Q'
#define ODD last_oddelovac
static char cti_int_num(int *readed)
{
return !fscanf(glbm,"%d",readed);
}
static int find_symbol(char **symbolmap,int list_len,int offset,char *symbol)
{
int start_pos;
char chr=0;
start_pos=0;
while (start_pos<list_len && *symbol)
{
char *ss=symbolmap[start_pos];
if (ss[offset]==*symbol)
{
chr=*symbol;
symbol++;offset++;continue;
}
if (ss[offset]>*symbol) return -1;
if (chr && ss[offset-1]!=chr) return -1;
start_pos++;
}
if (*symbol) return -1;
return start_pos;
}
static char get_symbol(char *symb)
{
int i;
i=find_symbol(symbolmap,sizeof(symbolmap)/sizeof(char *),2,symb);
if (i==-1) return 0;else return symbolmap[i][0];
}
static int cti_oddelovac(void)//cte prvni oddelovac - preskakuje mezery
{
int c;
do
{
c=getc(glbm);
if (c==OD_COMMENT) while((c=getc(glbm))!='\n');
if (c=='\n') linecounter++;
if (strchr(oddelovace,c)!=NULL || c==EOF) return c;
}
while (c==' ' || c=='\x9');
ungetc(c,glbm);
return 0;
}
static int cti_retezec(int znaku,char *text,char mezera,char upcase)
{
int c;
znaku--;
if (mezera)
{
while((c=getc(glbm))==32 || c==9);
}
else c=getc(glbm);
while (strchr(oddelovace,c)==NULL && ((c!=32 && c!=9) || !mezera) && c!=EOF)
{
if (upcase) c=toupper(c);
if (znaku)
{
*text++=c;
znaku--;
}
c=getc(glbm);
}
if (c!=32 && c!=9) ungetc(c,glbm);
*text=0;
return 0;
}
static void error(const char *text)
{
char popis[300];
sprintf(popis,"Chyba v souboru "GLOBMAP" na radce %d.\r\n%s",linecounter,text);
SEND_LOG("(ERROR) %s : %s",popis,text);
closemode();
display_error(popis);
exit(0);
}
static void ex_error(char znak)
{
char ex_text[100];
sprintf(ex_text,"Ocekava se znak '%c'",znak);
error(ex_text);
}
static void ready_index_tab(void)
{
index_tab=NewArr(INDEX_DEF,INDEXU);
memset(index_tab,0,INDEXU*sizeof(INDEX_DEF));
}
static void purge_index_tab(void)
{
if (index_tab)
{
int i;
for(i=0;i<255;i++) if (index_tab[i].text!=NULL) free(index_tab[i].text);
free(index_tab);
index_tab=NULL;
}
}
static char test_kriterii(void)
{
char last_op=0;
char not_op=0;
char text[128];
char hodn;
char vysl=0;
char symb,*c;
while (ODD==0 || ODD==OD_NEWLINE)
{
cti_retezec(100,text,1,1);
c=text;if (*c=='!') not_op=1,c++;
symb=get_symbol(c);
switch (symb)
{
case OP_AND:last_op=1;break;
case OP_NOT:not_op=!not_op;break;
case OP_OR:last_op=0;break;
case OP_SEKTOR:
{
int c;
if (cti_int_num(&c)) error("O<EFBFBD>ek<EFBFBD>v<EFBFBD> se <20><>slo");
hodn=c==enter_sector;
}
break;
case OP_CURMAP:cti_retezec(100,text,1,1);
hodn=!strcmp(level_fname,text);
break;
case OP_ISDEF:{
int c;
if (cti_int_num(&c)) error("O<EFBFBD>ek<EFBFBD>v<EFBFBD> se <20><>slo");
hodn=index_tab[c].defined;
}
break;
case OP_FLG:
{
int flag_num;
if (cti_int_num(&flag_num)) error("Za FLG mus<75> b<>t <20><>slo!");
if (flag_num>255) error("<EFBFBD><EFBFBD>slo vlajky (FLG) mus<75> b<>t v rozsahu 0-255!");
hodn=(test_flag(flag_num)!=0);
}
break;
default:
{
hodn=temp_storage_find(text)>=0;
/* char c[200];
sprintf(c,"%s.TMP",text);
hodn=!check_file_exists(c);*/
}
break;
}
hodn^=not_op;not_op=0;
if (last_op) vysl&=hodn;else vysl|=hodn;
ODD=cti_oddelovac();
}
return vysl;
}
static char proved_prikaz()
{
char prikaz[20];
char text[128];
int c;
char op;
ODD=cti_oddelovac();
while (ODD==OD_NEWLINE || ODD==OD_CR) ODD=cti_oddelovac(); //preskoc prazdne radky
if (ODD==OD_IN) return 0; //cti znak {
do
{
while (ODD==OD_NEWLINE || ODD==OD_CR || ODD==OD_COMMAND) ODD=cti_oddelovac();
if (ODD!=0) error("O<EFBFBD>ek<EFBFBD>v<EFBFBD> se jm<6A>no definice (p<><70>klad: INDX=)");
cti_retezec(20,prikaz,1,1);
op=get_symbol(prikaz);
if (op==OP_BREAK) return 1;
ODD=cti_oddelovac();
if (ODD!=OD_SET) ex_error(OD_SET);
switch(op)
{
case OP_INDX:
if (cti_int_num(&c)) error("INDX=?");
if (c<0 || c>255) error("INDX=<0,255>");
index_tab[last_index=c].defined=1;
break;
case OP_TEXT:
cti_retezec(128,text,0,0);
index_tab[last_index].text=NewArr(char,strlen(text)+1);
strcpy(index_tab[last_index].text,text);
break;
case OP_MAP:
cti_retezec(13,index_tab[last_index].mapname,1,1);
break;
case OP_DRAW:
{
char file[20];
int xp,yp;
int h;
cti_retezec(20,file,1,1);
ODD=cti_oddelovac();if (ODD!=OD_COMMA)ex_error(OD_COMMA);
if (cti_int_num(&xp)) error("O<EFBFBD>ek<EFBFBD>v<EFBFBD> se <20><>slo xp");
ODD=cti_oddelovac();if (ODD!=OD_COMMA)ex_error(OD_COMMA);
if (cti_int_num(&yp)) error("O<EFBFBD>ek<EFBFBD>v<EFBFBD> se <20><>slo yp");
h=find_handle(file,pcx_8bit_decomp);
if (h==-1) def_handle(h=end_ptr++,file,pcx_8bit_decomp,SR_DIALOGS);
put_picture(xp,yp+SCREEN_OFFLINE,ablock(h));
}
break;
case OP_UNDEF:
if (cti_int_num(&c)) error("UNDEF=?");
if (c<0 || c>255) error("UNDEF=<0,255>");
index_tab[c].defined=0;
break;
case OP_USEMAP:
{
char file[20];
cti_retezec(20,file,1,1);
usemap=find_handle(file,pcx_8bit_nopal);
if (usemap==-1) def_handle(usemap=end_ptr++,file,pcx_8bit_nopal,SR_DIALOGS);
}
break;
case OP_ESCAPE:
{
cti_retezec(20,prikaz,1,1);
fclose(glbm);
const char *s = build_pathname(2, gpathtable[SR_MAP], prikaz);
if ((glbm=fopen_icase(s,"r"))==NULL) error(s);
return 0;
}
default:error(prikaz);
}
ODD=cti_oddelovac();
if (ODD!=OD_COMMAND && ODD!=OD_NEWLINE && ODD!=OD_CR && ODD!=EOF) ex_error(OD_COMMAND);
}
while (ODD!=OD_NEWLINE && ODD !=OD_CR && ODD!=EOF);
return 0;
}
static void preskoc_prikaz(void)
{
char ending=0;
int uroven=0;
char last;
char text;
do
{
last=ODD;
ODD=cti_oddelovac();
switch (ODD)
{
case 0:cti_retezec(1,&text,0,0);ending=1;break;
case '\n':if (ending && uroven==0) return;break;
case EOF: if (uroven!=0)ex_error(OD_OUT);return;break;
case '{': if (last==OD_CRIT || last==OD_NEWLINE) uroven++;break;
case '}': if (last==OD_NEWLINE) uroven--; if (uroven<0) ex_error(OD_IN);
else if (uroven==0)return;
break;
}
if (ODD!=0) ending=0;
}
while(1);
}
static void do_script(void)
{
char vysledek;
const char *s=build_pathname(2,gpathtable[SR_MAP], GLOBMAP);
linecounter=0;
glbm=fopen_icase(s,"r");
if (glbm==NULL) error("Chyb<EFBFBD> uveden<65> soubor...");
ODD=cti_oddelovac();
do
{
if (ODD==0) //existuji kriteria
{
vysledek=test_kriterii();
}
else vysledek=1;
if (ODD==OD_CRIT) //oddelovac kriterii
{
char c=0;
if (vysledek)c=proved_prikaz();else preskoc_prikaz();
if (c) break;
}
ODD=cti_oddelovac();
}
while(ODD!=EOF);
fclose(glbm);
}
static int found_place=0;
static char flp_validate2(word sector)
{
TMOB *m;
char c;
if (mob_map[sector])
{
m=mobs+mob_map[sector]-1;
if (m->vlajky & ~MOB_PASSABLE) return 0;
if (!m->next)
if (mobs[m->next-1].vlajky & ~MOB_PASSABLE) return 0;
}
c=map_sectors[sector].sector_type;
if (c==S_DIRA || ISTELEPORT(c) || c==S_LAVA || c==S_VODA ) return 0;
return 1;
}
static char flp_validate(word sector)
{
TMOB *m;
char c;
if (found_place) return 0;
if (mob_map[sector])
{
m=mobs+mob_map[sector]-1;
if (m->vlajky & ~MOB_PASSABLE) return 0;
if (!m->next)
if (mobs[m->next-1].vlajky & ~MOB_PASSABLE) return 0;
}
c=map_sectors[sector].sector_type;
if (~map_coord[sector].flags & 1) return 0;
if (c==S_DIRA || ISTELEPORT(c) || c==S_LAVA || c==S_VODA ) return 0;
if (c==S_LEAVE && !found_place) found_place=sector;
return 1;
}
static int find_leave_place(int sector)
{
found_place=0;
if (map_sectors[sector].sector_type==S_LEAVE) return sector;
labyrinth_find_path(sector,65535,(SD_PLAY_IMPS | SD_SECRET),flp_validate,NULL);
return found_place;
}
static int select_mode = 0;
static char load_index_map(int index)
{
TMA_LOADLEV x;
int lv,i;
THUMAN *h;
if (select_mode)
{
char *a;
a=alloca(strlen(index_tab[index].mapname)+1);strcpy(a,index_tab[index].mapname);
wire_automap_file(a);
return 1;
}
if (!strcmp(index_tab[last_index].mapname,level_fname)) return 0;
lv=find_leave_place(viewsector);
if (lv<1)
{
bott_disp_text(texty[121]);
return 0;
}
for(i=0,h=postavy;i<POCET_POSTAV;i++,h++)
if (h->used && h->lives)
if (h->sektor!=lv && !labyrinth_find_path(h->sektor,lv,(SD_PLAY_IMPS | SD_SECRET),flp_validate2,NULL))
{
char c[20];
bott_disp_text(int2ascii(i,c,10));
return 0;
}
if (!GlobEvent(MAGLOB_LEAVEMAP,viewsector,viewdir)) return 0;
for(i=0,h=postavy;i<POCET_POSTAV;i++,h++)
if (h->used && h->lives) h->sektor=lv;
viewsector=lv;
strncpy(x.name,index_tab[index].mapname,12);
x.start_pos=0;
x.dir=0;
macro_load_another_map(&x);
return 0;
}
static char *fly_text;
static int fly_x,fly_y,fly_xs,fly_ys;
static void *fly_background;
void global_map_point(EVENT_MSG *msg,void **_)
{
MS_EVENT *ms;
if(msg->msg == E_INIT)
{
fly_background=NULL;last_index=0;fly_text=NULL;
fly_x=0;fly_y=0;fly_xs=4;fly_ys=4;
}
if(msg->msg == E_MOUSE)
{
int x,y,i,xs,ys;
const char *ptr;
ms=get_mouse(msg);
if (ms->event_type & 0x1)
{
x=ms->x;y=ms->y-SCREEN_OFFLINE;
if (y<0 || y>359) return;
else
{
alock(usemap);
ptr=ablock(usemap);
ptr+=640*y+x+6;
i=*ptr;
}
y+=60;
schovej_mysku();
if (fly_background!=NULL)put_picture(fly_x,fly_y,fly_background);
set_font(H_FTINY,RGB555(31,31,0));
xs=fly_xs;ys=fly_ys;
if (i!=last_index)
{
free(fly_background);
last_index=i;
if (index_tab[i].defined)
{
fly_text=index_tab[i].text;
mouse_set_default(H_MS_ZARE);
set_ms_finger(5,5);
}
else
{
fly_text=NULL;
mouse_set_default(H_MS_DEFAULT);
}
if (fly_text!=NULL)
{
xs=text_width(fly_text)+4;
ys=text_height(fly_text)+4;
fly_background=NewArr(word,xs*ys*2+6);
}
else
{
fly_text=NULL;xs=4;ys=4;
fly_background=NULL;
}
}
if (fly_text!=NULL)
{
if ((x+xs)>639) x=639-xs;
get_picture(x,y,xs,ys,fly_background);
trans_bar(x,y,xs,ys,0);
position(x+2,y+2);outtext(fly_text);
}
send_message(E_MOUSE,ms);
ukaz_mysku();
showview(fly_x,fly_y,fly_xs+1,fly_ys);
showview(fly_x=x,fly_y=y,(fly_xs=xs)+1,fly_ys=ys);
aunlock(usemap);
}
if (ms->event_type & 0x2 && ms->y>SCREEN_OFFLINE && ms->y<378)
{
if (last_index && index_tab[last_index].defined) {
if (load_index_map(last_index)) {
return;
}
} else {
return;
}
unwire_proc();
wire_proc();
msg->msg=-1;
}
if (ms->event_type & 0x8)
{
unwire_proc();
wire_proc();
msg->msg=-1;
}
}
if (msg->msg == E_DONE)
{
free(fly_background);
}
}
void unwire_global_map()
{
purge_index_tab();
send_message(E_DONE,E_MOUSE,global_map_point);
set_select_mode(0);
pick_set_cursor();
}
void wire_global_map()
{
unwire_proc();
schovej_mysku();
ready_index_tab();
do_script();
ukaz_mysku();
showview(0,0,0,0);
send_message(E_ADD,E_MOUSE,global_map_point);
unwire_proc=unwire_global_map;
change_click_map(NULL,0);
}
static void *old_wire_save;
static int old_viewsector;
static void empty_unwire()
{
}
static void unwire_automap_file()
{
load_map_automap(level_fname);
wire_proc=old_wire_save;
viewsector=old_viewsector;
build_player_map();
bott_draw(0);
wire_proc();
}
void wire_automap_file(char *mapfile)
{
int c;
if ((c=get_leaving_place(mapfile))==0) return;
old_wire_save=wire_proc;
old_viewsector=viewsector;
viewsector=c;
unwire_proc();
unwire_proc=empty_unwire;
wire_proc=unwire_automap_file;
save_map_state();
load_map_automap(mapfile);
noarrows=1;
cur_mode=MD_ANOTHER_MAP;
show_automap(1);
cancel_render=1;
}
char set_select_mode(char mode)
{
char last=select_mode;
select_mode=mode;
return last;
}
void cestovat()
{
}