gates_of_skeldal/game/inv.c
2025-01-31 18:54:59 +01:00

3061 lines
76 KiB
C

#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 <libs/devices.h>
#include <libs/bmouse.h>
#include <libs/bgraph.h>
#include <libs/zvuk.h>
#include <libs/gui.h>
#include <libs/basicobj.h>
#include "engine1.h"
#include <libs/pcx.h>
#include "globals.h"
#include <assert.h>
#include <stddef.h>
#include <string.h>
#define neprezbrojit() (battle && (battle_mode!=MD_PREZBROJIT || select_player!=human_selected-postavy))
#define _SHOP_ST "_SHOPS.TMP"
#define SV_ITLIST 0x8001
#define SV_SNDLIST 0x8002
#define SV_END 0x8000
#define IT_LIBS 27
#define IT_LIB_NAME "IKONY%02d.LIB"
#define IT_LIB_SIZE 18
#define SHOP_NAME "SHOPS.DAT"
#define BUYBOX_X 0
#define BUYBOX_Y 197
#define IMAP_SIZE 8
#define SHP_ICSIZX 54
#define SHP_ICSIZY 60
#define SHP_ICPLCX 30
#define SHP_ICPLCY 29
THUMAN postavy_2[20];
int face_arr[IT_FACES];
static int sound_handle;
int ikon_libs;
int item_count,it_count_orgn;
LETICI_VEC *letici_veci=NULL;
short *picked_item=NULL;
short water_breath=-1; //vec pro dychani pod vodou
short flute_item=-1;
int item_in_cursor=0;
void (*inv_redraw)();
TSHOP *cur_shop;
TSHOP **shop_list=NULL;
int max_shops=0; //shop_list=prima spojeni s obchody
void *shop_hacek=NULL; //hacek za ktery visi cely shop strom (free(shop_hacek) - odalokuje shopy)
//hacek lze ulozit do savegame -> ulozi se cely stav obchodu
int32_t shop_hacek_size=0; //toto je jeho delka
static TSHOP_ALL_STATE shop_all_state;
#define ico_extract(icnnum) (((char*)ablock(ikon_libs+(icnnum)/IT_LIB_SIZE))+IT_ICONE_SIZE*((icnnum)%IT_LIB_SIZE))
#define TOP_OFS 17
#define HUMAN_X 35
#define HUMAN_Y 348
#define INV_X 285
#define INV_Y (TOP_OFS+29)
#define INV_DESC_X 325
#define INV_DESC_Y (TOP_OFS+50)
#define INV_XS 55
#define INV_YS 60
#define INV_NAME_X 129
#define INV_NAME_Y 349
#define INV_NAME_COL (RGB555(10,31,31))
#define INV_DESK 266
#define INV_INFO_X 298
#define INV_INFO_Y 343
#define INV_INFO_XS 300
#define INV_INFO_YS 20
#define INV_INFO_XP 12
#define INV_INFO_YC (INV_INFO_YS+INV_INFO_XP)
#define INV_BRIEF_COL1 (NOSHADOW(0))
#define INV_BRIEF_COL2 (NOSHADOW(0))
#define INV_LEVEL_COL1 (NOSHADOW(RGB555(0,0,15)))
#define INV_LEVEL_COL2 (RGB555(31,24,0))
unsigned short butt_plus[7]={0x0,(RGB555(25,23,16)),(RGB555(18,17,14)),(RGB555(10,10,5)),(RGB555(31,27,14))};
#define PO_XS 194
#define PO_YS 340
#define PO_XSS (PO_XS>>1)
#define PO_YSS (PO_YS>>1)
TITEM *glob_items=NULL;
char inv_view_mode=0;
void redraw_inventory();
void zkontroluj_postavu();
void place_human_item(word *obrazek,int x,int y,int item)
{
const word *p;
p=ablock(item);
put_picture2picture(p,obrazek,PO_XSS-p[0]/2+x,PO_YS-p[1]-y-20);
}
/*
void init_item_sounds(int *ptr)
{
int i;
char *c;
for(i=0;i<item_count;i++)
if (glob_items[i].sound)
{
c=(char *)ablock(H_SOUND_DAT)+sound_table[glob_items[i].sound-1];
if (c==NULL || c[0]==0)
{
closemode();
puts("Invalid Sound Table integrity - rebuild SOUND.DAT using MapEdit");
exit(1);
}
def_handle(glob_items[i].sound_handle=ptr[0]++,c,wav_load,SR_ZVUKY);
}
}
*/
void item_sound_event(int item,int sector)
{
if (!item) return;
item--;
if (!glob_items[item].sound) return;
play_sample_at_sector(glob_items[item].sound+sound_handle,viewsector,sector,0,0);
}
static const void *items_15to16_correct(const void *p,int32_t *s)
{
int i,j;
void *np = getmem(*s);
memcpy(np, p, *s);
char *cur=(char *)(np);
for (i=0;i<IT_LIB_SIZE;i++)
{
int pos=IT_ICONE_SIZE*i;
word *pal;
if (pos>=*s) return np;
pal=((word *)(cur+pos))+3;
for (j=0;j<256;j++,pal++)
{
*pal=RGB555(*pal>>10,(*pal>>5)& 0x1F,(*pal & 0x1F));
}
}
return np;
}
void load_items()
{
const char *name;
FILE *f;
int sect,i,hs;
int32_t size;
void *p;
f=NULL;i=0;
ikon_libs=hl_ptr;
free(glob_items);
do {
char name[200];
sprintf(name, IT_LIB_NAME, i++);
if (test_file_exist(SR_ITEMS, name)) {
def_handle(hl_ptr++, name, items_15to16_correct, SR_ITEMS);
} else {
break;
}
} while (1);
name=build_pathname(2, gpathtable[SR_MAP],ITEM_FILE);
f=fopen_icase(name,"rb");
if (f==NULL)
{
closemode();
display_error("Selhalo otevreni souboru ITEMS.DAT. Zkotroluj zda vubec existuje.");
exit(0);
}
do
{
load_section(f,&p,&sect,&size);
switch (sect)
{
case 1:
case 4:
face_arr[sect-1]=hl_ptr-1;
prepare_graphics(&hl_ptr,(char *)p,size,pcx_fade_decomp,SR_ITEMS);
free(p);
break;
case 2:
case 3:
face_arr[sect-1]=hl_ptr-1;
prepare_graphics(&hl_ptr,(char *)p,size,pcx_fade_decomp,SR_ITEMS);
free(p);
break;
case 5:
face_arr[sect-1]=hl_ptr-1;
prepare_graphics(&hl_ptr,(char *)p,size,NULL,SR_ITEMS);
free(p);
break;
case SV_ITLIST:
glob_items=p;
it_count_orgn=item_count=size/sizeof(TITEM);
for (int i = 0; i < it_count_orgn; ++i) {
if (glob_items[i].cena_high != 0) {
SEND_LOG("(ITEMS) Over-priced item %i %s %d > 65535", i, glob_items[i].jmeno, glob_items[i].cena + 65536*glob_items[i].cena_high);
}
}
break;
case SV_SNDLIST:
hs=hl_ptr;
prepare_graphics(&hl_ptr,(char *)p,size,wav_load,SR_ZVUKY);
sound_handle=hs-1;
break;
default:
free(p);
break;
}
}
while (sect!=SV_END);
fclose(f);
{
TITEM *t;
for(i=0,t=glob_items;i<it_count_orgn;i++,t++) if (t->druh==TYP_SPECIALNI)
{
if (t->user_value==TSP_WATER_BREATH) water_breath=i;
else if (t->user_value==TSP_FLUTE) flute_item=i;
}
}
}
void init_items()
{
map_items=(short **)getmem(mapsize*4*sizeof(short **));
memset(map_items,0,mapsize*4*sizeof(short **));
}
static short expand_itemlist(void)
{
int nwit=item_count;
if (item_count>32766)
{
int i,j;
for(i=it_count_orgn;i<item_count;i++)
{
for(j=0;j<POCET_POSTAV;j++) if (postavy[j].used && q_item_one(j,i+1)!=NULL) break;
if (j==POCET_POSTAV) break;
}
glob_items[i].flags|=ITF_FREE;
nwit=j;
}
else
{
TITEM *it;
item_count++;
it=(TITEM *)getmem(sizeof(TITEM)*item_count);
memcpy(it,glob_items,sizeof(TITEM)*nwit);
free(glob_items);
glob_items=it;
}
return nwit;
}
/*static short add_dupl_item(short item)
{
TITEM *it;
int nwit;
if (!item) return item;
if (glob_items[item-1].flags & ITF_DUPLIC) return item;
item--;
nwit=item_count;
item_count++;
if (item_count>32766)
{
nwit=32766;
memmove(glob_items+it_count_orgn,glob_items+it_count_orgn,(item_count-it_count_orgn-1)*sizeof(TITEM));
item_count=32766;
memcpy(&it[nwit],&glob_items[item],sizeof(TITEM));
}
else
{
it=(TITEM *)getmem(sizeof(TITEM)*item_count);
memcpy(it,glob_items,sizeof(TITEM)*nwit);
memcpy(&it[nwit],&glob_items[item],sizeof(TITEM));
free(glob_items);
}
it[nwit].flags|=ITF_DUPLIC;
glob_items=it;
return nwit+1;
}*/
short duplic_item(short item)
{
int i;
if (!item) return item;
item--;
for(i=0;i<item_count;i++) if (glob_items[i].flags & ITF_FREE) break;
if (i==item_count) i=expand_itemlist();
memcpy(glob_items+i,glob_items+item,sizeof(TITEM));
glob_items[i].flags|=ITF_DUPLIC;
glob_items[i].flags&=~ITF_FREE;
return i+1;
}
short create_unique_item(const TITEM *it)
{
int i;
if (it==NULL) return 0;
for(i=0;i<item_count;i++) if (glob_items[i].flags & ITF_FREE) break;
if (i==item_count) i=expand_itemlist();
memcpy(glob_items+i,it,sizeof(TITEM));
glob_items[i].flags|=ITF_DUPLIC;
glob_items[i].flags&=~ITF_FREE;
return i+1;
}
void destroy_items(short *items)
{
if (items==NULL) return;
while (*items)
{
if (glob_items[*items-1].flags & ITF_DUPLIC)
glob_items[*items-1].flags|=ITF_FREE;
items++;
}
}
short create_item_money(int obnos)
{
int i,ls,max=99999,z;
ls=-1;
for(i=0;i<item_count;i++) if (glob_items[i].druh==TYP_PENIZE && (z=abs(glob_items[i].cena-obnos))<max) ls=i,max=z;
if (ls==-1) return 0;
i=duplic_item(ls+1)-1;
glob_items[i].cena=obnos;
return i+1;
}
void load_item_map(void *p,int32_t s)
{
word itmc;
int sect;
short *c,*d;
c=(short *)p;
while (s>0)
{
sect=*(int *)c;
c+=sizeof(sect)/sizeof(short);s-=sizeof(sect);
d=c;itmc=1;
while (*d++) itmc++;
map_items[sect]=(short *)getmem(itmc*sizeof(short));
d=c;
itmc=0;
do
{
map_items[sect][itmc++]=*d;
s-=sizeof(short);
}
while (*d++);
c=d;
}
}
char possx[]={0,1,1,0};
char possy[]={1,1,0,0};
void draw_placed_items_normal(int celx,int cely,int sect,int side)
{
int i,j,k;
short *c;
short nl=0,vzh;
short cnt;
sect<<=2;
cnt=(cely==0)?2:4;
for(i=0;i<cnt;i++)
{
j=(i+side)&3;
if (map_items[sect+j]!=NULL) c=map_items[sect+j];else c=&nl;
k=0;
while (*c)
{
if (*c>0)
{
vzh=glob_items[(*c)-1].vzhled;
if (vzh) draw_item(celx,cely,possx[i],possy[i],ablock(vzh+face_arr[0]),k);
}
c++;k++;
}
}
}
int count_items_total(short *place)
{
int c=0;
if (place==NULL) return 0;
while (*place++) c++;
return c;
}
int count_items_visible(short *place)
{
int c=0;
if (place==NULL) return 0;
while (*place)
{
if (*place>0) c++;
place++;
}
return c;
}
int count_items_inside(short *place)
{
int c=1;
if (place==NULL) return 0;
place++;
while (*place++<0) c++;
return c;
}
int find_item(short *place,int mask)
{
int lastitem=-1;
int i=0;
if (place==NULL) return -1;
while (*place)
{
if ((*place & 0xC000)==mask) lastitem=i;
i++;place++;
}
return lastitem;
}
static int lastsector;
static char ValidateSector(word sector)
{
int pp=map_sectors[sector].sector_type;
if (pp==S_NORMAL || pp==S_SMER || pp==S_LEAVE || pp==S_FLT_SMER)
{
lastsector=sector;
return 1;
}
return 0;
}
void push_item(int sect,int pos,short *picked_item)
{
int bc;
int pc;
int tc;
short *p;
if (map_sectors[sect].sector_type==S_DIRA || ISTELEPORTSECT(sect))
sect=map_sectors[sect].sector_tag;
if (sect==0 || map_sectors[sect].sector_type==S_VODA)
{
if (game_extras & EX_RECOVER_DESTROYED_ITEMS)
{
labyrinth_find_path(viewsector,65535,SD_PLAY_IMPS,ValidateSector,NULL);
push_item(lastsector,viewdir,picked_item);
return;
}
else
{
free(picked_item);
picked_item=NULL;
return;
}
}
sect=(sect<<2)+pos;
bc=count_items_total(map_items[sect]);
pc=count_items_total(picked_item);
tc=bc+pc;
if (tc==0) return;
tc++;
p=(short *)grealloc(map_items[sect],tc*sizeof(short));
if (pc) memcpy(p+bc,picked_item,pc*sizeof(short));
p[tc-1]=0;
map_items[sect]=p;
recheck_button(sect>>2,1);
}
void pop_item(int sect,int pos,int mask,short **picked_item)
{
int picked;
int bc,tc,pc;
short *s,*t,*b;
*picked_item=NULL;
sect=(sect<<2)+pos;
picked=find_item(map_items[sect],mask);
if (picked==-1) return;
s=map_items[sect]+picked;
pc=count_items_inside(s);
bc=count_items_total(map_items[sect]);
tc=bc-pc;
*picked_item=(short *)getmem((pc+1)*sizeof(short));
memcpy(*picked_item,s,pc*sizeof(short));(*picked_item)[pc]=0;
if (tc) b=NewArr(short,tc+1);else b=NULL;
if (picked) memcpy(b,map_items[sect],picked*sizeof(short));
t=b+picked;
s=s+pc;
while (*s) *t++=*s++;
if (b!=NULL) b[tc]=0;
free(map_items[sect]);
map_items[sect]=b;
recheck_button(sect>>2,1);
}
void pick_set_cursor(void)
{
if (picked_item==NULL)
item_in_cursor=H_MS_DEFAULT;
else
item_in_cursor=-(glob_items[*picked_item-1].ikona);
mouse_set_default(item_in_cursor);
}
void do_items_specs(void)
{
int xa,ya;
char destroy=0;
TITEM *p;
GlobEvent(MAGLOB_ONPICKITEM,viewsector,viewdir);
if (picked_item==0) return;
p=&glob_items[*picked_item-1];
switch(p->druh)
{
case TYP_RUNA:xa=p->user_value/10;ya=1<<(p->user_value%10);
runes[xa]|=ya;
destroy=1;
play_fx_at(FX_MAGIC);
if (game_extras & EX_AUTOSHOWRUNE) bott_disp_rune(p->user_value,*picked_item-1);
break;
case TYP_PENIZE:
{
//char c[150];
money+=p->cena;
destroy=1;
//sprintf(c,texty[cislovka(p->cena)+131],p->cena);
//bott_disp_text(c);
play_fx_at(FX_MONEY);
break;
}
case TYP_PRACH:
destroy=1;
bott_disp_text(texty[134]);
break;
case TYP_SVITXT:
destroy=1;
cur_page=count_pages();
cur_page&=~0x1;
cur_page++;
if (p->popis[0]==0) add_to_book(p->user_value);
else
{
const char *s = build_pathname(2, gpathtable[SR_MAP], p->popis);
add_text_to_book(s,p->user_value);
}
play_fx_at(FX_BOOK);
if (game_extras & EX_AUTOOPENBOOK) autoopenaction=1;
break;
}
if (destroy)
{
destroy_items(picked_item);
free(picked_item);
picked_item=NULL;
}
}
static char check_pick(int sect,int id,int idd,int y)
{
short c;
int min=480,d;
short *place=map_items[(sect<<2)+idd];
int vzl;
if (place==NULL) return 0;
while (*place)
{
c=*place;
if (c>0)
{
vzl=glob_items[c-1].vzhled;
if (vzl) d=get_item_top(0,id>1,possx[id],possy[id],ablock(vzl+face_arr[0]),count_items_visible(place)-1);
else d=get_item_top(0,id>1,possx[id],possy[id],NULL,count_items_visible(place))-32;
if (d<min) min=d;
}
place++;
}
return y>min;
}
static int get_top_of_next(int sect,int id) //vraci souradnici predmetu na nasledujicim sektoru
{
int cnt,idd;
sect=map_sectors[sect].step_next[viewdir];
if (sect==0) return 0;
id=3-id;
idd=(id+viewdir) & 3;
sect<<=2;
cnt=count_items_visible(map_items[sect+idd])-1;
if (cnt<0) cnt=0;
return get_item_top(0,1,possx[id],possy[id],NULL,cnt);
}
char pick_item_(int id,int xa,int ya,int xr,int yr)
{
int sect;
int idd;
xa,ya,xr,yr;
if (id>1)
{
(sect=map_sectors[viewsector].step_next[viewdir]);
if ((map_sides[(viewsector<<2)+viewdir].flags & SD_THING_IMPS) && !(map_sides[(viewsector<<2)+viewdir].oblouk & SD_ITPUSH)) return 0;
}
else sect=viewsector;
idd=(id+viewdir)&0x3;
if (picked_item!=NULL)
{
if (map_sectors[sect].sector_type==S_DIRA)
{
throw_fly(xa,ya,0);
letici_veci->speed=0;
letici_veci->sector=sect;
letici_veci->xpos=-32;
letici_veci->velocity=0;
letici_veci->flags &= ~FLY_NEHMOTNA;
}
else
if (id>1 || ya>=get_top_of_next(sect,id))
{
if ((game_extras & EX_BAG_EXTENDED) && (get_control_key_state()) &&
(glob_items[*picked_item-1].nosnost>0))
{
int curinside=count_items_inside(picked_item);
int nosnost=(glob_items[*picked_item-1].nosnost);
short *batoh=(short *)getmem(nosnost*2+20);
short *cur=batoh;
memcpy(cur,picked_item,(curinside+1)*2);
cur+=curinside;
free(picked_item);
picked_item=NULL;
nosnost-=curinside-1;
while (1)
{
pop_item(sect,idd,0,&picked_item);
if (picked_item!=NULL) do_items_specs(); else break;
if (picked_item!=NULL)
{
short *p=picked_item;
int cnt=count_items_total(picked_item);
if (cnt>nosnost)
{
push_item(sect,idd,picked_item);
free(picked_item);
picked_item=NULL;
break;
}
while (*p)
{
*cur++=-abs(*p++);
nosnost--;
}
free(picked_item);
picked_item=NULL;
}
}
*cur=0;
picked_item=batoh;
pick_set_cursor();
return 1;
}
push_item(sect,idd,picked_item);
free(picked_item);
picked_item=NULL;
pick_set_cursor();
return 1;
}
return 0;
}
else
{
if (id>1 || check_pick(sect,id,idd,ya))
{
pop_item(sect,idd,0,&picked_item);
if (picked_item!=NULL) do_items_specs();
pick_set_cursor();
}
return (picked_item!=NULL);
}
}
int celkova_vaha(short *p)
{
int suma=0;
while (*p) suma+=glob_items[abs(*p++)-1].hmotnost;
return suma;
}
char put_item_to_inv(THUMAN *p,short *picked_items)
{
int i,pos=0;
int it;
if (p->inv_size>MAX_INV) p->inv_size=MAX_INV;
if (picked_items==NULL) return 0;
if (isdemon(p)) return 0;
it=*picked_items;
if (it && glob_items[it-1].umisteni==PL_SIP && !neprezbrojit())
{
int u;
u=glob_items[it-1].user_value;if (!u) u=1;
if (p->sipy+u<100)
{
p->sipy+=u;
return 1;
}
}
for(i=0;picked_items[i];i++);
while (i)
{
for(;pos<p->inv_size && p->inv[pos];pos++);
if (pos>=p->inv_size) break;
i--;
it=abs(picked_items[i]);
p->inv[pos]=it;
picked_items[i]=0;
}
return (i==0);
}
//-----------------------------------Inventory viewer-------------------
THUMAN *human_selected=postavy;
short vls_min[24]=
{0,0,0,0,1,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0};
short vls_max[]=
{200,200,200,200,32767,32767,32767,190,199,190,199,99,99,99,99,99,90,90,90,90,99,4};
char bag_click(int id,int xa,int ya,int xr,int yr);
char human_click(int id,int xa,int ya,int xr,int yr);
char inv_swap_desk(int id,int xa,int ya,int xr,int yr);
char exit_inv(int id,int xa,int ya,int xr,int yr);
char ring_place(int id,int xa,int ya,int xr,int yr);
char uloz_sip(int id,int xa,int ya,int xr,int yr);
char info_box_drawed=0;
void *info_box_below=NULL;
void *inv_keyboard(EVENT_MSG *msg,void **usr);
T_CLK_MAP clk_inv_view[]=
{
{-1,INV_X,INV_Y,INV_X+INV_XS*6,INV_Y+INV_YS*5,bag_click,2,-1},
{0,236,185,255,204,ring_place,2,-1},
{1,236,220,255,239,ring_place,2,-1},
{2,236,255,255,274,ring_place,2,-1},
{3,236,290,255,309,ring_place,2,-1},
{0,0,200,29,309,uloz_sip,2,-1},
{-1,37,34,225,336,human_click,2,-1},
{-1,45,339,212,358,inv_swap_desk,2,H_MS_DEFAULT},
{-1,54,378,497,479,start_invetory,2+8,-1},
{-1,337,0,357,14,go_map,2,H_MS_DEFAULT},
{-1,87,0,142,14,game_setup,2,H_MS_DEFAULT},
{-1,30,0,85,14,konec,2,H_MS_DEFAULT},
{-1,0,0,639,479,exit_inv,8,-1},
};
#define CLK_INV_VIEW 13
void prepocitat_postavu(THUMAN *human_selected)
{
short *sr1,*p,*q,i,j,c;
int v;
if (human_selected->inv_size>MAX_INV) human_selected->inv_size=MAX_INV;
sr1=human_selected->vlastnosti;
p=human_selected->stare_vls;
memcpy(sr1,p,sizeof(human_selected->stare_vls));
for(i=0;i<HUMAN_PLACES+4;i++)
{
if (i<HUMAN_PLACES) c=human_selected->wearing[i];else c=human_selected->prsteny[i-HUMAN_PLACES];
if (c)
{
p=sr1;
q=glob_items[c-1].zmeny;
for(j=0;j<VLS_MGSIL_L;j++)
{
if (glob_items[c-1].druh!=TYP_VRHACI || (j!=VLS_UTOK_L && j!=VLS_UTOK_H))
{
if (j>=VLS_OHEN && j<=VLS_MYSL)
p[0]=(int)floor(((float)p[0]+(float)q[0])/(1.0f+(float)p[0]*(float)q[0]/(90.0*90.0))+0.5);
else
(*p)+=(*q);
}
p++,q++;
}
p=sr1+VLS_DAMAGE; //vypocet damage (bez omezeni)
q=&glob_items[c-1].zmeny[VLS_DAMAGE];
*(p++)+=*q++;
p=sr1+VLS_KOUZLA; //aplikace kouzel
q=&glob_items[c-1].zmeny[VLS_KOUZLA];
(*p++)|=*q++;
}
}
p=sr1;
for(j=0;j<VLS_MGSIL_L;j++)
{
if (*p<vls_min[j]) *p=vls_min[j];
if (*p>vls_max[j]) *p=vls_max[j];
p++;
}
if (human_selected->lives>human_selected->vlastnosti[VLS_MAXHIT]) human_selected->lives=human_selected->vlastnosti[VLS_MAXHIT];
//if (human_selected->mana>human_selected->vlastnosti[VLS_MAXMANA]) human_selected->mana=human_selected->vlastnosti[VLS_MAXMANA];
if (human_selected->kondice>human_selected->vlastnosti[VLS_KONDIC]) human_selected->kondice=human_selected->vlastnosti[VLS_KONDIC];
v=MAX_HLAD(human_selected);human_selected->jidlo=MIN(human_selected->jidlo,v);
v=MAX_ZIZEN(human_selected);human_selected->voda=MIN(human_selected->voda,v);
}
char exit_inv(int id,int xa,int ya,int xr,int yr)
{
inv_view_mode=0;
if (!battle || battle_mode!=MD_PREZBROJIT || picked_item==NULL) return_game(id,xa,ya,xr,yr);
return 1;
}
void definuj_postavy()
{
int i,num1,r,inv=0,z;
const char *c,*end;
char cc;
int tmp;
c=ablock(H_POSTAVY_DAT);
end=c+get_handle(H_POSTAVY_DAT)->size;
for(i=0;c<end && i<20;i++)
{
THUMAN *p=&postavy_2[i];
inv=0;
memset(p,0,sizeof(*p));r=1;
p->inv_size=6;
while (c<end && *c!='\n' && *c!='\r' && r==1)
{
r=sscanf(c,"%d",&num1);c=strchr(c,'\n')+1;
switch(num1)
{
case 64:
case 65:
case 66:
case 67:
case 68:r=sscanf(c,"%d",&z);
while(r==1 && z!=-1)
{
runes[num1-64]|=1<<(z-1);
c=strchr(c,'\n')+1;
r=sscanf(c,"%d",&z);
}
break;
case 128:r=sscanf(c,"%c%14[^\r]",&cc,p->jmeno);r--;break;
case 129:r=sscanf(c,"%d",&tmp);p->female = (char)tmp;break;
case 130:r=sscanf(c,"%d",&tmp);p->xicht = (char)tmp;break;
case 131:r=sscanf(c,"%d",&tmp);p->level = (short)tmp;break;
case 132:r=sscanf(c,"%d",&tmp);p->exp = tmp;break;
case 133:r=sscanf(c,"%d",&num1);
while(r==1 && num1!=-1)
{
p->inv[inv++]=num1+1;
c=strchr(c,'\n')+1;
r=sscanf(c,"%d",&num1);
}
break;
case 134:r=sscanf(c,"%hd",&p->wearing[PO_BATOH]);
p->inv_size=6+glob_items[p->wearing[PO_BATOH]].nosnost;
p->wearing[PO_BATOH]++;
break;
case 135:r=sscanf(c,"%d",&num1);if (r!=1) break;
c=strchr(c,'\n')+1;
r=sscanf(c,"%hd",&p->wearing[num1]);
p->wearing[num1]++;
break;
case 136:r=sscanf(c,"%d",&num1);if (r!=1) break;
p->sipy=num1;
break;
default:r=sscanf(c,"%hd",&p->stare_vls[num1]);break;
}
if (c>=end) break;
c=strchr(c,'\n')+1;
}
if (r!=1)
{
closemode();
display_error("Error in file POSTAVY.DAT. May be missing a parameter in some definition.");
exit(0);
}
c=strchr(c,'\n')+1;
prepocitat_postavu(p);
p->lives=p->vlastnosti[VLS_MAXHIT];
p->kondice=p->vlastnosti[VLS_KONDIC];
p->mana=p->vlastnosti[VLS_MAXMANA];
p->used=1;
p->groupnum=1;
p->jidlo=MAX_HLAD(p);
p->voda=MAX_ZIZEN(p);
p->bonus=0;
p->mana_battery=32767;
}
}
static void inv_najist(short item)
{
TITEM *it;
int mhlad;
if (!item) return;
it=glob_items+item-1;
if (it->druh!=TYP_JIDLO) return;
human_selected->jidlo+=it->user_value*HODINA;
mhlad=MAX_HLAD(human_selected);
play_sample_at_channel(H_SND_EAT,1,100);
if (human_selected->jidlo>mhlad) human_selected->jidlo=mhlad;
if (it->magie>0)
thing_cast(it->spell,human_selected-postavy,human_selected->sektor,NULL,1);
bott_draw(1);
redraw_inventory();
}
static void inv_napit(short item)
{
TITEM *it;
int mvoda;
if (!item) return;
it=glob_items+item-1;
if (it->druh!=TYP_VODA) return;
human_selected->voda+=it->user_value*HODINA;
mvoda=MAX_ZIZEN(human_selected);
play_sample_at_channel(H_SND_LEKTVAR,1,100);
if (human_selected->voda>mvoda) human_selected->voda=mvoda;
if (it->magie>0)
thing_cast(it->spell,human_selected-postavy,human_selected->sektor,NULL,1);
bott_draw(1);
redraw_inventory();
}
static void inv_quaf(short item)
{
TITEM *it;
if (!item) return;
it=glob_items+item-1;
if (it->druh!=TYP_LEKTVAR) return;
thing_cast(it->spell,human_selected-postavy,human_selected->sektor,NULL,1);
bott_draw(1);
play_sample_at_channel(H_SND_LEKTVAR,1,100);
redraw_inventory();
}
static void inv_use_spec(short **items)
{
short *pp;
short it;
pp=*items;
if (pp==NULL) return;
it=*pp;
if (!it) return;
it--;
if (it==flute_item)
{
unwire_proc();
wire_proc();
bott_draw_fletna();
if (put_item_to_inv(human_selected,pp))
{
free(pp);
*items=NULL;
}
poloz_vsechny_predmety();
pick_set_cursor();
}
}
char check_jidlo_voda(THUMAN *p)
{
if (game_extras & EX_NOHUNGRY) return 0;
if (p->used && p->lives)
{
p->jidlo--;
p->voda--;
if (p->jidlo<0)
{
p->jidlo=0;
return 1;
}
if (p->voda<0)
{
p->voda=0;
player_hit(p,1,0);
return 1;
}
}
return 0;
}
char check_map_specials(THUMAN *p)
{
char c=0;
switch(mglob.map_effector)
{
case ME_NORMAL:break;
case ME_SOPKA:if (~p->vlastnosti[VLS_KOUZLA] & SPL_FIRE_RES) player_hit(p,10,0),c=1;break;
case ME_LEDOV:if (~p->vlastnosti[VLS_KOUZLA] & SPL_ICE_RES) player_hit(p,10,0),c=1;break;
}
if (c) bott_draw(0);
return c;
}
void pomala_regenerace_postavy(THUMAN *p)
{
int mreg,mmax;
check_map_specials(p);
if (check_jidlo_voda(p)) return;
if (p->utek)
{
p->utek=0;
if (p->kondice>0) p->kondice-=1;
return;
}
p->kondice+=(p->vlastnosti[VLS_VPREG]+9)/10;
if (p->kondice>p->vlastnosti[VLS_KONDIC]) p->kondice=p->vlastnosti[VLS_KONDIC];
mreg=(p->vlastnosti[VLS_MPREG]+9)/10;
mmax=p->vlastnosti[VLS_MAXMANA];
if (p->mana+mreg>mmax) mreg=mmax-p->mana;
if (mreg>0) p->mana+=mreg;
}
char sleep_regenerace(THUMAN *p)
{
int mreg,mmax;
if (p->used && p->lives)
{
if (check_jidlo_voda(p)) return 1;
p->kondice+=p->vlastnosti[VLS_VPREG];
p->lives+=p->vlastnosti[VLS_HPREG];
if (p->kondice>p->vlastnosti[VLS_KONDIC]) p->kondice=p->vlastnosti[VLS_KONDIC];
if (p->lives>p->vlastnosti[VLS_MAXHIT]) p->lives=p->vlastnosti[VLS_MAXHIT];
mreg=p->vlastnosti[VLS_MPREG];
mmax=p->vlastnosti[VLS_MAXMANA];
if (p->mana+mreg>mmax) mreg=mmax-p->mana;
if (mreg>0) p->mana+=mreg;
}
return 0;
}
void real_regeneration()
{
int i;
THUMAN *p;
for(i=0;i<POCET_POSTAV;i++)
{
p=&postavy[i];
if (p->used && p->lives)
pomala_regenerace_postavy(p);
}
send_message(E_KOUZLO_KOLO);
sleep_ticks+=MAX_SLEEP/30;
if (sleep_ticks>MAX_SLEEP) sleep_ticks=MAX_SLEEP;
tick_tack(1);
TimerEvents(viewsector,viewdir,game_time);
SEND_LOG("(GAME) Tick Tack, Game time: %d",game_time);
GlobEvent(MAGLOB_ONROUND,viewsector,viewdir);
bott_draw(0);
}
void init_inventory(void)
{
definuj_postavy();
}
void display_items_in_inv(THUMAN *h)
{
int i,x,xr,yr,it;
short *p;
put_picture(266,TOP_OFS,ablock(H_IDESKA));
p=ablock_copy(H_IMRIZ1);
p[1]=INV_YS*((h->inv_size-1)/6)+58;
put_picture(INV_X,INV_Y,p);
xr=INV_X;x=0;
yr=INV_Y;
for(i=0;i<h->inv_size;i++)
{
if ((it=h->inv[i])!=0)
{
int ikn;
ikn=glob_items[it-1].ikona;
put_picture(xr,yr,ico_extract(ikn));
}
xr+=INV_XS;
x++;if (x>=6)
{
xr=INV_X;yr+=INV_YS;x=0;
}
}
}
void display_rings()
{
word pozice[][2]=
{
{245,194},{245,229},{245,264},{245,299}
};
int i;
for(i=0;i<4;i++)
{
int ikn;
ikn=human_selected->prsteny[i];
if (ikn)
{
word *w;
ikn=glob_items[ikn-1].ikona;
w=(word *)ico_extract(ikn);
put_picture(pozice[i][0]-w[0]/2,pozice[i][1]-w[1]/2,w);
}
}
}
void *build_items_wearing(THUMAN *h, int32_t *s)
{
int i,vzhled,it;
const word *p;
word hx,hy;
word *ob;
size_t siz;
char *pp;
p=ablock(H_CHARS+h-postavy);
hx=p[0];
hy=p[1];
ob=getmem(siz=(PO_XS*PO_YS+PIC_FADE_PAL_SIZE));
memset(ob,0,siz);
memcpy(ob,p,PIC_FADE_PAL_SIZE);
*s = siz;
ob[0]=PO_XS;
ob[1]=PO_YS;
put_picture2picture(p,ob,PO_XSS-(hx/2),PO_YS-hy-20);
for(i=1;i<HUMAN_PLACES;i++)
if ((it=h->wearing[i])!=0)
{
TITEM *itt;
itt=&glob_items[it-1];
vzhled=itt->vzhled;
if (h->female==1) vzhled+=face_arr[2];else vzhled+=face_arr[1];
if (i==PO_RUKA_L) place_human_item(ob,itt->polohy[1][0],itt->polohy[1][1],vzhled);
else place_human_item(ob,itt->polohy[0][0],itt->polohy[0][1],vzhled);
}
pp=(char *)ob;
if (h->vlastnosti[VLS_KOUZLA] & SPL_STONED)
{
int i;
for (i=0;i<(PIC_FADE_PAL_SIZE>>1);++i) if (i>3)
{
unsigned short col=ob[i];
int bw=(GET_R_COLOR(col)+GET_G_COLOR(col)+GET_B_COLOR(col))/3;
if (bw>255) bw=255;
ob[i]=RGB(bw,bw,bw);
}
}
else
{
pp+=PIC_FADE_PAL_SIZE;
if (h->vlastnosti[VLS_KOUZLA] & SPL_INVIS)
for(i=0;i<PO_XS*PO_YS;i++,pp++) if (*pp!=0) *pp=1;
}
return ob;
}
const void *build_items_called(const void *p, int32_t *s)
{
return build_items_wearing(&postavy[memman_handle-H_POSTAVY], s);
}
void display_items_wearing(THUMAN *h)
{
int it;
int32_t scr_linelen2 = GetScreenPitch();
put_picture(4,TOP_OFS,ablock(H_IOBLOUK));
zneplatnit_block(h-postavy+H_POSTAVY);
enemy_draw(ablock(h-postavy+H_POSTAVY),GetScreenAdr()+HUMAN_X+HUMAN_Y*scr_linelen2,6,320,HUMAN_Y,640*65536);
it=h->wearing[PO_BATOH];
if (it)
{
TITEM *itt;
const word *w;int vzhled;
itt=&glob_items[it-1];
vzhled=itt->vzhled;
if (h->female==1) vzhled+=face_arr[2];else vzhled+=face_arr[1];
w=ablock(vzhled);
enemy_draw(w,GetScreenAdr()+itt->polohy[0][0]+HUMAN_X+PO_XSS-w[0]/2+scr_linelen2*(HUMAN_Y-itt->polohy[0][1]-20),6,320,HUMAN_Y,640*65536);
}
}
void write_human_big_name(char *c)
{
int xs,ys;
set_font(H_FBOLD,INV_NAME_COL);
xs=text_width(c)>>1;
ys=text_height(c)>>1;
position(INV_NAME_X-xs,INV_NAME_Y-ys);
outtext(c);
}
#define pvls(x) (offsetof(struct thuman,vlastnosti[x]))
#define ptpw(x) (offsetof(struct thuman,bonus_zbrani[x]))
static void percent_bar(int x,int y,int xs,int ys,int val,int max,char *popis)
{
CTL3D clt;
char s[25];
memcpy(&clt,def_border(3,0),sizeof(clt));
bar32(x,y,x+xs*val/max,ys+y);
show_textured_button(x-2,y-2,xs+5,ys+5,0,&clt);
set_aligned_position(x,y-5,0,2,popis);
outtext(popis);
sprintf(s,"%d/%d",val/360,max/360);
set_aligned_position(x+xs/2,y+ys/2,1,1,s);
outtext(s);
}
typedef struct t_inv_script
{
short col,line;
char *text;
short parm1,parm2;
char lenght;
char align;
} T_INV_SCRIPT;
#define INFO_AP -1
#define INFO_EXP -2
#define LINE_STEP 6
#define COL_STEP 8
static T_INV_SCRIPT script[]=
{
{15,12,"%d",pvls(VLS_SILA),0,2+128,2},
{15,14,"%d",pvls(VLS_SMAGIE),0,2+128,2},
{15,16,"%d",pvls(VLS_POHYB),0,2+128,2},
{15,18,"%d",pvls(VLS_OBRAT),0,2+128,2},
{15,5,"%d/%d",offsetof(THUMAN,lives),pvls(VLS_MAXHIT),2,2},
{15,7,"%d/%d",offsetof(THUMAN,mana),pvls(VLS_MAXMANA),2,2},
{15,9,"%d/%d",offsetof(THUMAN,kondice),pvls(VLS_KONDIC),2,2},
{15,20,"%d",offsetof(THUMAN,bonus),0,2,2},
{15,25,"%d",ptpw(TPW_MEC),0,2,2},
{15,27,"%d",ptpw(TPW_SEKERA),0,2,2},
{15,29,"%d",ptpw(TPW_KLADIVO),0,2,2},
{15,31,"%d",ptpw(TPW_HUL),0,2,2},
{15,33,"%d",ptpw(TPW_DYKA),0,2,2},
{15,35,"%d",ptpw(TPW_STRELNA),0,2,2},
{15,37,"%d",ptpw(TPW_OST),0,2,2},
{0,0,NULL,0,31,1,0},
{0,2,NULL,0,30,1,0},
{15,0,"%d",offsetof(THUMAN,level),0,2,2},
{30,2,"%d [%d]",offsetof(THUMAN,exp),INFO_EXP,4,2},
{0,5,NULL,0,14,1,0},
{0,7,NULL,0,16,1,0},
{0,9,NULL,0,15,1,0},
{0,12,NULL,0,10,128,0},
{0,14,NULL,0,11,128,0},
{0,16,NULL,0,12,128,0},
{0,18,NULL,0,13,128,0},
{0,20,NULL,0,19,0,0},
{0,23,NULL,0,90,1,0},
{0,25,NULL,0,91,1,0},
{0,27,NULL,0,92,1,0},
{0,29,NULL,0,93,1,0},
{0,31,NULL,0,94,1,0},
{0,33,NULL,0,95,1,0},
{0,35,NULL,0,96,1,0},
{0,37,NULL,0,97,1,0},
{30,5,"%d-%d",pvls(VLS_UTOK_L),pvls(VLS_UTOK_H),2,2},
{30,7,"%d-%d",pvls(VLS_OBRAN_L),pvls(VLS_OBRAN_H),2,2},
{30,9,"%d",INFO_AP,0,2,2},
{17,5,NULL,0,18,1,0},
{17,7,NULL,0,17,1,0},
{17,9,NULL,0,20,1,0},
{30,14,"%d",pvls(VLS_OHEN),0,2,2},
{30,16,"%d",pvls(VLS_VODA),0,2,2},
{30,18,"%d",pvls(VLS_ZEME),0,2,2},
{30,20,"%d",pvls(VLS_VZDUCH),0,2,2},
{30,22,"%d",pvls(VLS_MYSL),0,2,2},
{17,12,NULL,0,21,1,0},
{17,14,NULL,0,22,1,0},
{17,16,NULL,0,23,1,0},
{17,18,NULL,0,24,1,0},
{17,20,NULL,0,25,1,0},
{17,22,NULL,0,26,1,0},
};
static int calc_value(int parm,int lenght)
{
int32_t l;
if (parm>=0) l=*(int32_t *)(((char *)human_selected)+parm);
else
switch (parm)
{
case INFO_EXP:
l=(human_selected->level<PLAYER_MAX_LEVEL?(level_map[human_selected->level-1]-human_selected->exp):0);
break;
case INFO_AP:
l=get_ap(human_selected->vlastnosti);
break;
}
switch(lenght)
{
case 1:l=(int32_t)((signed char)l);break;
default:
case 2:l=(int32_t)((short)l);break;
case 4:l=(int32_t)l;break;
}
return l;
}
void inv_display_vlastnosti()
{
unsigned int i;
put_picture(INV_DESK,TOP_OFS,ablock(H_SVITEK));
for(i=0;i<sizeof(script)/sizeof(struct t_inv_script);i++)
{
struct t_inv_script *scr=script+i;
int x,y,p1,p2;
char *s;
char buffer[80];
x=INV_DESC_X+scr->col*COL_STEP;y=INV_DESC_Y+scr->line*LINE_STEP;
s=scr->text;
p1=scr->parm1;
p2=scr->parm2;
p1=calc_value(p1,scr->lenght & 0x7f);
if (s==NULL) s=texty[scr->parm2];else p2=calc_value(p2,scr->lenght);
sprintf(buffer,s,p1,p2);
if (scr->lenght & 0x80 && human_selected->bonus)
set_font(H_FONT7,scr->text==NULL?INV_LEVEL_COL1:INV_LEVEL_COL2);
else set_font(H_FONT7,NOSHADOW(0));
set_aligned_position(x,y,scr->align,0,buffer);
outtext(buffer);
}
set_font(H_FONT7,NOSHADOW(0));
curcolor=(RGB555(18,17,14));
percent_bar(INV_DESC_X+140,INV_DESC_Y+170,90,10,human_selected->jidlo,MAX_HLAD(human_selected),texty[69]);
curcolor=(RGB555(14,17,18));
percent_bar(INV_DESC_X+140,INV_DESC_Y+210,90,10,human_selected->voda,MAX_ZIZEN(human_selected),texty[70]);
if (human_selected->bonus)
for(i=0;i<4;i++) if (calc_value(script[i].parm1,2)<100)
{
int x,y;
x=INV_DESC_X+script[i].col*COL_STEP;y=INV_DESC_Y+script[i].line*LINE_STEP;
set_font(H_FSYMB,RGB555(31,31,31));
memcpy(charcolors,butt_plus,sizeof(charcolors));
position(x+1,y);outtext("+");
}
}
typedef struct t_info
{
short line,col;
char *format;
short parm1,parm2;
char bonus;
}T_INFO;
char muze_nosit(short item)
{
short *p,i,*q,*z;
p=human_selected->vlastnosti;
q=glob_items[item-1].podminky;
z=glob_items[item-1].zmeny;
for(i=0;i<4;i++)
{
if (*p<*q) return 0;
if (*p+*z<*q) return 0;
q++;z++;p++;
}
return 1;
}
void hide_inv_info_box()
{
info_box_drawed=0;
if (info_box_below!=NULL)
{
schovej_mysku();
put_picture(INV_INFO_X-12,INV_INFO_Y-12,info_box_below);
free(info_box_below);
info_box_below=NULL;
ukaz_mysku();
showview(INV_INFO_X-VEL_RAMEC,INV_INFO_Y-VEL_RAMEC,INV_INFO_XS+2*VEL_RAMEC+2,INV_INFO_YC+2*VEL_RAMEC+2);
}
}
void inv_info_box(char *text1,char *text2,char *text3,char asterix)
{
int x,y,ys;
static int last_info_ys=0;
ys=INV_INFO_YS;
if (text3!=NULL) ys+=INV_INFO_XP;
if (info_box_below!=NULL && last_info_ys!=ys)
{
put_picture(INV_INFO_X-12,INV_INFO_Y-12,info_box_below);
free(info_box_below);
info_box_below=NULL;
}
last_info_ys=ys;
info_box_drawed=1;
if (info_box_below==NULL)
{
info_box_below=getmem((INV_INFO_XS+28)*(ys+28)*2+6);
get_picture(INV_INFO_X-12,INV_INFO_Y-12,INV_INFO_XS+28,ys+28,info_box_below);
}
x=INV_INFO_X;
y=INV_INFO_Y;
create_frame(x,y,INV_INFO_XS,ys,1);
set_font(H_FBOLD,asterix?(NOSHADOW(RGB555(31,0,0))):NOSHADOW(0));
position(x,y);
outtext(text1);
position(x,y+12);
outtext(text2);
position(x,y+24);
if (text3!=NULL) outtext(text3);
}
static char *get_item_req(char *s,int itn)
{
TITEM *it;
int i;
char *c=s;
s[0]=0;
itn--;if (itn<0) return NULL;
it=glob_items+itn;
for(i=0;i<4;i++)
if (it->podminky[i])
{
sprintf(c,texty[200+i],it->podminky[i]);
c=strchr(c,0);
if (i!=3)*c++=32;
}
*c=0;
if (s[0]) return s;else return NULL;
}
void inv_informuj()
{
int i;
char s[80];
if (picked_item==NULL) return;
i=*picked_item;
inv_info_box(glob_items[i-1].jmeno,glob_items[i-1].popis,get_item_req(s,i),!muze_nosit(i));
}
void write_pocet_sipu()
{
char s[10];
if (human_selected->sipy)
{
set_font(H_FBOLD,RGB555(31,31,31));
sprintf(s,"%d",human_selected->sipy);
set_aligned_position(19,301,1,1,s);
outtext(s);
}
}
void redraw_inventory()
{
update_mysky();
schovej_mysku();
curcolor=0;
bar32(0,16,30,16+360);
bar32(620,16,640,16+360);
if (inv_view_mode==0 && ~human_selected->stare_vls[VLS_KOUZLA] & SPL_DEMON && ~human_selected->vlastnosti[VLS_KOUZLA] & SPL_STONED) display_items_in_inv(human_selected);
else inv_display_vlastnosti();
display_items_wearing(human_selected);
write_human_big_name(human_selected->jmeno);
write_pocet_sipu();
display_rings();
other_draw();
info_box_drawed=0;
free(info_box_below);
info_box_below=NULL;
ms_last_event.event_type=0x1;send_message(E_MOUSE,&ms_last_event);
ukaz_mysku();
showview(0,0,0,0);
}
static void add_vls(int plus,int vls,short *change1,short *change2,float factor)
{
int oldv,newv;
oldv=(int)(vls*factor);
vls+=plus;
newv=(int)(vls*factor);
if (change1!=NULL)
{
change1[0]+=newv-oldv;
if (change2!=NULL) change2[0]+=newv-oldv;
}
return;
}
int advance_vls(int id)
{
int i=0;
short *vls=human_selected->stare_vls;
switch (id)
{
case 0:if (vls[VLS_SILA]<100) //max 100
{
add_vls(1,vls[VLS_SILA],vls+VLS_MAXHIT,&human_selected->lives,1.5f);
add_vls(1,vls[VLS_SILA],vls+VLS_HPREG,NULL,0.08f);
vls[VLS_SILA]++;
i=1;
}
break;
case 1:if (vls[VLS_SMAGIE]<100) //max 100
{
add_vls(1,vls[VLS_SMAGIE],vls+VLS_MAXMANA,&human_selected->mana,2);
add_vls(1,vls[VLS_SMAGIE],vls+VLS_MPREG,NULL,0.1f);
vls[VLS_SMAGIE]++;
i=1;
}
break;
case 2:if (vls[VLS_POHYB]<100) //max 100
{
add_vls(1,vls[VLS_POHYB],vls+VLS_MAXHIT,&human_selected->lives,0.5);
add_vls(1,vls[VLS_POHYB],vls+VLS_KONDIC,&human_selected->kondice,0.25);
vls[VLS_POHYB]++;
i=1;
}
break;
case 3:if (vls[VLS_OBRAT]<100) //max 100
{
add_vls(1,vls[VLS_OBRAT],vls+VLS_KONDIC,&human_selected->kondice,0.5);
add_vls(1,vls[VLS_OBRAT],vls+VLS_VPREG,NULL,0.1f);
vls[VLS_OBRAT]++;
i=1;
}
break;
}
return i;
}
static void timed_redraw(THE_TIMER *t)
{
t;
bott_draw(1);
inv_redraw();
}
char vls_click(int id,int xa,int ya,int xr,int yr)
{
int xs,ys,i;
if (!human_selected->bonus) return 0;
set_font(H_FSYMB,0);
xs=text_width("+");
ys=text_height("+");
for(id=0;id<4;id++)
{
int xe,ye;
float mh,mv;
xr=INV_DESC_X+COL_STEP*script[id].col+1;
yr=INV_DESC_Y+LINE_STEP*script[id].line;
xe=xr+xs;ye=yr+ys;
if (xa>=xr && xa<xe && ya>=yr && ya<ye)
{
mh=(float)human_selected->jidlo/MAX_HLAD(human_selected);
mv=(float)human_selected->voda/MAX_ZIZEN(human_selected);
i=advance_vls(id);
if (i>0)
{
schovej_mysku();
set_font(H_FSYMB,0x0);
memcpy(charcolors,butt_plus,sizeof(butt_plus));
charcolors[1]=butt_plus[3];
charcolors[3]=butt_plus[1];
position(xr,yr);outtext("+");
ukaz_mysku();
showview(xr,yr,xs,ys);
}
human_selected->bonus-=i;
prepocitat_postavu(human_selected);
human_selected->jidlo=(int)(mh*MAX_HLAD(human_selected));
human_selected->voda=(int)(mv*MAX_ZIZEN(human_selected));
add_to_timer(-1,6,1,timed_redraw);
}
}
return 1;
}
void inv_item_info_box(EVENT_MSG *msg,void **data)
{
MS_EVENT *ms;
char podm;
int pos;
static int lastpos=-1;
int xr,yr;
data;
if (msg->msg==E_MOUSE)
{
ms=get_mouse(msg);
if (picked_item!=NULL)
{
if (ms->y>378 && info_box_drawed) hide_inv_info_box();
else if (ms->y<=378 && !info_box_drawed)
{
schovej_mysku();
inv_informuj();
ukaz_mysku();
showview(INV_INFO_X-VEL_RAMEC,INV_INFO_Y-VEL_RAMEC,INV_INFO_XS+2*VEL_RAMEC+2,INV_INFO_YC+2*VEL_RAMEC+2);
}
lastpos=-1;
}
else
{
if (inv_view_mode) return;
podm=(ms->x>=clk_inv_view[0].xlu &&
ms->x<=clk_inv_view[0].xrb &&
ms->y>=clk_inv_view[0].ylu &&
ms->y<=clk_inv_view[0].yrb);
xr=ms->x-clk_inv_view[0].xlu;
yr=ms->y-clk_inv_view[0].ylu;
if (podm) pos=(xr/INV_XS)+6*(yr/INV_YS);else pos=-1;
if (pos>=human_selected->inv_size) podm=0;
if (podm && (!info_box_drawed || pos!=lastpos))
{
int i=human_selected->inv[pos];
if (i)
{
char s[80];
schovej_mysku();
inv_info_box(glob_items[i-1].jmeno,glob_items[i-1].popis,get_item_req(s,i),!muze_nosit(i));
showview(INV_INFO_X-VEL_RAMEC,INV_INFO_Y-VEL_RAMEC,INV_INFO_XS+2*VEL_RAMEC+2,INV_INFO_YC+2*VEL_RAMEC+2);
ukaz_mysku();
}
else if (info_box_drawed) hide_inv_info_box();
}
else if (!podm && info_box_drawed) hide_inv_info_box();
lastpos=pos;
}
}
}
void unwire_inv_mode()
{
send_message(E_DONE,E_KEYBOARD,inv_keyboard);
send_message(E_DONE,E_MOUSE,inv_item_info_box);
build_all_players();
}
char vejdou_se(int pocet)
{
int i=human_selected->inv_size-1;
while (i>=0) if (!human_selected->inv[i--]) pocet--;
return pocet>0;
}
char uloz_sip(int id,int xa,int ya,int xr,int yr)
{
id;xa;ya;xr;yr;
if (isdemon(human_selected)) return 0;
if (neprezbrojit()) return 0;
if (picked_item!=NULL && picked_item[1]==0 && glob_items[picked_item[0]-1].umisteni==PL_SIP)
{
int pocet=glob_items[picked_item[0]-1].user_value;
if (pocet==0) pocet=1;
if (human_selected->sipy+pocet>99) return 1;
human_selected->sipy+=pocet;
free(picked_item);
picked_item=NULL;
}
else
if (picked_item==NULL && human_selected->sipy)
{
short x[2];
int i;
for(i=0;i<item_count;i++) if (glob_items[i].umisteni==PL_SIP && glob_items[i].user_value==0)
{
x[0]=i+1;
x[1]=0;
picked_item=(short *)getmem(2*sizeof(short));
memcpy(picked_item,x,sizeof(short)*2);
human_selected->sipy--;
break;
}
}
pick_set_cursor();
inv_redraw();
return 1;
}
static char MakeItemCombinations(short *itm1, short *itm2)
{
short i1=*itm1-1,i2=*itm2-1;
int src1;
int src2;
int trg1;
int trg2;
int cnt;
char succ=0;
FILE *table;
const char *fname = build_pathname(2,gpathtable[SR_MAP],"COMBITEM.DAT");
table=fopen_icase(fname,"r");
if (table==NULL) return 0;
cnt=fscanf(table,"%d %d -> %d %d",&src1,&src2,&trg1,&trg2);
while(cnt>=3)
{
if (src1==i1 && src2==i2)
{
if (cnt==3)
{
*itm2=trg1+1;
*itm1=0;
}
else
{
*itm1=trg1+1;
*itm2=trg2+1;
}
succ=1;
break;
}
if (src1==i2 && src2==i1)
{
if (cnt==3)
{
*itm2=trg1+1;
*itm1=0;
}
else
{
*itm2=trg1+1;
*itm1=trg2+1;
}
succ=1;
break;
}
if (fscanf(table," ;")==-1) break;
cnt=fscanf(table,"%d %d -> %d %d",&src1,&src2,&trg1,&trg2);
}
fclose(table);
return succ;
}
char bag_click(int id,int xa,int ya,int xr,int yr)
{
short p,*pk;
if (inv_view_mode || human_selected->stare_vls[VLS_KOUZLA] & SPL_DEMON || human_selected->vlastnosti[VLS_KOUZLA] & SPL_STONED) return vls_click(id,xa,ya,xr,yr);
xa;ya;
id=(xr/INV_XS)+6*(yr/INV_YS);
if (id>=human_selected->inv_size) return 0;
pk=picked_item;
if (pk!=NULL)
{
if (picked_item[1]!=0 && vejdou_se(count_items_total(picked_item))) return 0;
if (picked_item[1]!=0 || human_selected->inv[id]==0 || !MakeItemCombinations(picked_item,human_selected->inv+id))
while (*pk)
{
p=human_selected->inv[id];
human_selected->inv[id]=abs(*pk);
*pk=p;pk++;
if (*pk) while (human_selected->inv[id]) if ((++id)>=human_selected->inv_size) id=0;
}
}
else
{
picked_item=getmem(2*sizeof(short));
picked_item[0]=human_selected->inv[id];
picked_item[1]=0;
human_selected->inv[id]=0;
}
if (!picked_item[0])
{
free(picked_item);
picked_item=NULL;
}
pick_set_cursor();
play_sample_at_channel(H_SND_PUTINV,0,100);
inv_redraw();
return 1;
}
char item_pointed(int k,int x,int y,short item,short kind)
{
int x1,y1,x2,y2,xs,ys,xsiz,ysiz,i;
const short *p;
char *c,cc;
if (!item) return 0;
i=glob_items[item-1].vzhled;
p=ablock(i+face_arr[1+kind]);
xs=glob_items[item-1].polohy[k][0]+HUMAN_X+PO_XSS;
ys=HUMAN_Y-glob_items[item-1].polohy[k][1]-20;
xsiz=p[0]>>1;
ysiz=p[1];
x1=xs-xsiz;y1=ys-ysiz;
x2=xs+xsiz;y2=ys;
if (x>=x1 && x<=x2 && y>=y1 && y<=y2)
{
xs=x-x1;
ys=y-y1;
c=(char *)p;c+=PIC_FADE_PAL_SIZE+xs+ys*p[0];
cc=*c;
}
else cc=0;
return cc!=0;
}
char inv_swap_desk(int id,int xa,int ya,int xr,int yr)
{
id,xa,ya,xr,yr;
inv_view_mode=!inv_view_mode;
inv_redraw();
return 1;
}
char ring_place(int id,int xa,int ya,int xr,int yr)
{
short ring;
xa,ya,xr,yr;
if (neprezbrojit()) return 0;
if (isdemon(human_selected)) return 0;
if (human_selected->vlastnosti[VLS_KOUZLA] & SPL_STONED) return 0;
ring=human_selected->prsteny[id];
if (picked_item==NULL)
if (ring)
{
picked_item=(short *)getmem(2*sizeof(short));
picked_item[0]=ring;
picked_item[1]=0;
human_selected->prsteny[id]=0;
}
else return 0;
else
if (picked_item[1]==0)
{
int i;
i=picked_item[0]-1;
if (glob_items[i].umisteni!=PL_PRSTEN) return 1;
human_selected->prsteny[id]=picked_item[0];
*picked_item=ring;
if (!ring)
{
free(picked_item);picked_item=0;
}
}
prepocitat_postavu(human_selected);
zkontroluj_postavu();
pick_set_cursor();
inv_redraw();
return 1;
}
void vymen_batohy()
{
short *old,*c;
int i;
c=old=(short *)getmem(sizeof(short)*40);
memset(old,0,sizeof(short)*40);
*c++=human_selected->wearing[PO_BATOH];
for(i=6;i<human_selected->inv_size;i++)
{
*c=-human_selected->inv[i];
if (*c) c++;
}
for(i=6;i<MAX_INV;i++) human_selected->inv[i]=0;
if (picked_item!=NULL)
{
int it;
c=picked_item;
it=human_selected->wearing[PO_BATOH]=*c++;
i=6;
while (*c && i<MAX_INV) human_selected->inv[i++]=-*c++;
human_selected->inv_size=glob_items[it-1].nosnost+6;
}
else
{
human_selected->inv_size=6;
human_selected->wearing[PO_BATOH]=0;
}
if (old[0]) picked_item=old;
else
{
free(old);
picked_item=NULL;
}
prepocitat_postavu(human_selected);
zkontroluj_postavu();
pick_set_cursor();
play_sample_at_channel(H_SND_WEAR,1,100);
inv_redraw();
}
void remove_item(THUMAN *p,int what)
{
if (p->wearing[what])
{
int i;
short z[2];
z[0]=p->wearing[what];
z[1]=0;
if (glob_items[z[0]-1].flags & ITF_NOREMOVE) destroy_items(z);
else
{
for(i=0;i<p->inv_size && p->inv[i];i++);
if (i!=p->inv_size) p->inv[i]=p->wearing[what];
else push_item(p->sektor,p->direction,z);
}
p->wearing[what]=0;
}
}
int calculate_weight(THUMAN *p)
{
int suma=0;
int i;
for (i=0;i<p->inv_size;i++) if (p->inv[i])
suma+=glob_items[p->inv[i]-1].hmotnost;
suma=suma*3/2;
for (i=0;i<HUMAN_PLACES;i++) if (p->wearing[i])
suma+=glob_items[p->wearing[i]-1].hmotnost;
for (i=0;i<HUMAN_RINGS;i++) if (p->prsteny[i])
suma+=glob_items[p->prsteny[i]-1].hmotnost;
return suma;
}
int weigth_defect(THUMAN *p)
{
int wh,wf;
wh=calculate_weight(p);
if (wh>p->vlastnosti[VLS_SILA]*20)
wf=(wh-p->vlastnosti[VLS_SILA]*20)/200;
else
wf=0;
return wf;
}
static char check_double_wield(int newplace,short item)
{
short *p,i,*q1,*q2;
short *z1,*z2;
short opplace=newplace==PO_RUKA_L?PO_RUKA_R:PO_RUKA_L;
short item2=human_selected->wearing[opplace];
if (!item || !item2) return 0;
if (glob_items[item-1].druh!=TYP_UTOC || glob_items[item2-1].druh!=TYP_UTOC ) return 0;
p=human_selected->vlastnosti;
q1=glob_items[item-1].podminky;
q2=glob_items[item2-1].podminky;
z1=glob_items[item-1].zmeny;
z2=glob_items[item2-1].zmeny;
for(i=0;i<4;i++)
{
int chk=(*q1+*q2)*3/4;
if (*p<chk) return 1;
if (*p+*z1+*z2<chk) return 1;
q1++;p++;q2++;
z1++;z2++;
}
return 0;
}
void zkontroluj_postavu()
{
short *p,i;
p=human_selected->wearing;
for(i=0;i<HUMAN_PLACES;i++,p++)
if (*p && !muze_nosit(p[0])) remove_item(human_selected,i);
if (check_double_wield(PO_RUKA_R,human_selected->wearing[PO_RUKA_R]))
remove_item(human_selected,PO_RUKA_L);
}
char human_click(int id,int xa,int ya,int xr,int yr)
{
short itsave=0;
short place=-1;
short um=0;
xr;yr;id;
if ((battle && ((battle_mode!=MD_PREZBROJIT) || (select_player!=human_selected-postavy))) || (human_selected->vlastnosti[VLS_KOUZLA] & SPL_STONED)) return 0;
if (isdemon(human_selected)) return 0;
if (picked_item!=NULL)
if (muze_nosit(*picked_item))
if (glob_items[(*picked_item)-1].umisteni==PL_BATOH)
{
vymen_batohy();
return 0;
}
else if (picked_item[1]!=0) return 0;
else
{
um=place=glob_items[picked_item[0]-1].umisteni;
if (!place)
{
switch (glob_items[picked_item[0]-1].druh)
{
case TYP_LEKTVAR:inv_quaf(*picked_item);destroy_items(picked_item);free(picked_item);picked_item=NULL;pick_set_cursor();break;
case TYP_JIDLO:inv_najist(*picked_item);destroy_items(picked_item);free(picked_item);picked_item=NULL;pick_set_cursor();break;
case TYP_VODA:inv_napit(*picked_item);destroy_items(picked_item);free(picked_item);picked_item=NULL;pick_set_cursor();break;
case TYP_SPECIALNI:inv_use_spec(&picked_item);break;
}
inv_redraw();
return 1;
}
if (place==PL_RUKA)
if (xr<94) place=PO_RUKA_R;else place=PO_RUKA_L;
else if (place==PL_OBOUR) place=PO_RUKA_R;
else place--;
if (place>=HUMAN_PLACES) return 0;
itsave=human_selected->wearing[place];
}
else return 0;
else
{
int i=HUMAN_PLACES-1;
while (i>=0)
{
if (item_pointed(i==PO_RUKA_L,xa,ya,human_selected->wearing[i],human_selected->female)) break;
i--;
}
if (i<0) return 0;
if (i==PO_BATOH) vymen_batohy();
else
{
picked_item=getmem(2*sizeof(short));
picked_item[0]=human_selected->wearing[i];
picked_item[1]=0;
human_selected->wearing[i]=0;
}
}
if (um)
{
switch (um)
{
case PL_KUTNA:remove_item(human_selected,PO_HLAVA);
remove_item(human_selected,PO_TELO_D);
remove_item(human_selected,PO_TELO_H);
break;
case PL_OBOUR:remove_item(human_selected,PO_RUKA_L);
break;
case PL_TELO_H:
case PL_TELO_D:
case PL_HLAVA:remove_item(human_selected,PO_KUTNA);
break;
case PL_RUKA :if (place==PO_RUKA_L)
if (human_selected->wearing[PO_RUKA_R] && glob_items[human_selected->wearing[PO_RUKA_R]-1].umisteni==PL_OBOUR)
remove_item(human_selected,PO_RUKA_R);
if (check_double_wield(place,*picked_item))
remove_item(human_selected,place==PO_RUKA_L?PO_RUKA_R:PO_RUKA_L);
break;
}
human_selected->wearing[place]=*picked_item;
if (itsave) *picked_item=itsave;
else
{
free(picked_item);picked_item=NULL;
}
}
if (picked_item!=NULL && glob_items[*picked_item-1].flags & ITF_NOREMOVE)
{
destroy_items(picked_item);
free(picked_item);
picked_item=NULL;
}
play_sample_at_channel(H_SND_WEAR,1,100);
prepocitat_postavu(human_selected);
zkontroluj_postavu();
pick_set_cursor();
inv_redraw();
return 1;
}
void *inv_keyboard(EVENT_MSG *msg,void **usr)
{
char c;
usr;
if (msg->msg==E_KEYBOARD)
{
c=quit_request_as_escape(va_arg(msg->data, int))>>8;
switch (c)
{
case 0x17:
case 1:unwire_inv_mode();
wire_proc();
inv_view_mode=0;
break;
case 28:
case 15:
case 50:
if (GlobEvent(MAGLOB_BEFOREMAPOPEN,viewsector,viewdir))
{
unwire_inv_mode();
show_automap(1);
}
break;
}
}
return &inv_keyboard;
}
void wire_inv_mode(THUMAN *select)
{
mute_all_tracks(0);
send_message(E_ADD,E_KEYBOARD,inv_keyboard);
change_click_map(clk_inv_view,CLK_INV_VIEW);
send_message(E_ADD,E_MOUSE,inv_item_info_box);
human_selected=select;
if (human_selected->bonus!=0 && picked_item==NULL) inv_view_mode=1;
cur_mode=MD_INV;
build_all_players();
redraw_inventory();
unwire_proc=unwire_inv_mode;
inv_redraw=redraw_inventory;
}
static LETICI_VEC *fly_map=NULL;
static int fly_map_size=0; //velikost mapy
static int fly_count; //vyuziti mapy
void draw_fly_items(int celx,int cely,int sector,int side)
{
LETICI_VEC *p;
int xpos,ypos;
const short *pic;
short picnum;char turn,smr;
TITEM *it;
int i;
p=fly_map;
if (map_coord[sector].flags & 2)
{
i=fly_count;
while (i--)
if (p->sector==sector && (p->items!=NULL || p->item!=0))
{
switch(smr=(p->smer-side)&0x3)
{
case 0: xpos=p->ypos;ypos=p->xpos;turn=(celx*128+xpos)<0;break;
case 1: xpos=p->xpos;ypos=-p->ypos;turn=1;break;
case 2: xpos=-p->ypos;ypos=-p->xpos;turn=(celx*128+xpos)<0;break;
case 3: xpos=-p->xpos;ypos=p->ypos;turn=0;break;
}
xpos+=64;
ypos+=64;
if (p->items==NULL) it=glob_items+p->item-1;else it=&glob_items[*(p->items)-1];
if (p->flags & FLY_DESTROY_SEQ) smr=3;
else if (smr==3) smr=1;
picnum=it->v_letu[(smr<<2)+p->anim_pos];
if (!picnum)
if (it->vzhled)
picnum=it->vzhled+face_arr[0];
else
picnum=0;
else picnum+=face_arr[3];
if (picnum)
{
pic=ablock(picnum);
draw_placed_texture(pic,celx,cely,xpos,ypos,p->zpos,turn);
}
p++;
}
else p++;
}
}
void build_fly_map()
{
LETICI_VEC *p,*p2;
static int counter=0;
fly_count=0;
for(p=letici_veci;p!=NULL;p=p->next) if (!(p->flags & (FLY_BURNT|FLY_UNUSED))) fly_count++;
if (fly_count>fly_map_size || !counter)
{
free(fly_map);fly_map=NewArr(LETICI_VEC,fly_count);
if (!counter) {
SEND_LOG("(FLY) Fly_map was reduced - capacity: %d flies in game / was: %d",fly_count,fly_map_size);
} else {
SEND_LOG("(FLY) Fly_map was expanded - capacity: %d flies in game / was: %d",fly_count,fly_map_size);
}
counter=1000;
fly_map_size=fly_count;
}
else counter--;
for(p=letici_veci,p2=fly_map;p!=NULL;p=p->next) if (!(p->flags & (FLY_BURNT|FLY_UNUSED)))
{
map_coord[p->sector].flags|=2;
p->anim_pos++;p->anim_pos&=3;
memcpy(p2,p,sizeof(LETICI_VEC));
if (p->flags & FLY_DESTROY_SEQ && p->anim_pos==3)
{
stop_fly(p,1);
}
p2++;
}
else
p->flags|=FLY_UNUSED;
}
void destroy_fly_map()
{
int i;
LETICI_VEC *f;
for(i=0,f=fly_map;i<fly_count;i++,f++) map_coord[f->sector].flags &=~MC_FLY;
fly_count=0;
}
void add_fly(LETICI_VEC *p)
{
p->next=letici_veci;
letici_veci=p;
}
LETICI_VEC *throw_fly(int x,int y, char rovne)
{
LETICI_VEC *p;
int m;
p=create_fly();
p->zpos=128-y*128/360;
p->ypos=(x>320)?32:-32;
p->sector=viewsector;
p->smer=viewdir;
p->items=picked_item;
p->counter=0;
p->hit_bonus=0;
p->damage=0;
m=abs(celkova_vaha(picked_item));
if (mglob.map_effector==ME_PVODA) m+=50;
p->flags=(rovne?FLY_NEHMOTNA:0) | (glob_items[*picked_item-1].flags & ITF_DESTROY?FLY_DESTROY:0);
if (m) p->speed=1000/(m)+1;else p->speed=24;
if (p->speed>56) p->speed=56;
p->xpos=p->speed+1;
p->velocity=-(360-y)/72;
if (rovne) p->velocity=0;
if (select_player==-1 || !battle) p->owner=postavy-human_selected+1;
else p->owner=select_player+1;
p->hit_bonus=0;
add_fly(p);
picked_item=NULL;
if (!battle) pick_set_cursor();
return p;
}
void build_all_players()
{
int i;
for(i=0;i<POCET_POSTAV;i++) zneplatnit_block(i+H_POSTAVY);
}
//-------------------------- SHOP SYSTEM ---------------------------
#define CLK_SHOP 10
static short cur_owner=0; //1 hrac, -1 obchodnik, 0 Nikdo
char shop_bag_click(int id,int xa,int ya,int xr,int yr);
char shop_keeper_click(int id, int xa, int ya,int xr,int yr);
char shop_block_click(int id, int xa, int ya,int xr,int yr);
char shop_change_player(int id, int xa, int ya,int xr,int yr);
char _exit_shop(int id, int xa, int ya,int xr,int yr);
void unwire_shop();
void wire_shop();
static int top_item;
static short shp_item_map[IMAP_SIZE];
static short shp_item_pos[IMAP_SIZE];
static int shop_sector;
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,2,-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,2,-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},
{-1,30,0,85,14,konec,2,H_MS_DEFAULT},
};
static void shop_mouse_event(EVENT_MSG *msg,void **unused)
{
unused;
if (msg->msg==E_MOUSE)
{
MS_EVENT *ms;
int x,y;
char cc=1;
static int last_pos=-1;
EVENT_MSG msgc = clone_message(msg);
ms=get_mouse(msg);
x=ms->x-(BUYBOX_X+SHP_ICPLCX);
y=ms->y-(BUYBOX_Y+SHP_ICPLCY);
if (picked_item==NULL && x>0 && y>0 && x<(4*SHP_ICSIZX) && y<(2*SHP_ICSIZY))
{
int i,j;
x/=SHP_ICSIZX;
y/=SHP_ICSIZY;
i=4*y+x;
if (i<8 && (j=shp_item_map[i])!=0 && i!=last_pos)
{
char c[80];
char s[80];
int cena=cur_shop->list[shp_item_pos[i]].cena;
j--;
schovej_mysku();
sprintf(c,"%s (%d)",glob_items[j].jmeno,cena+cur_shop->koef*cena/100);
inv_info_box(c,glob_items[j].popis,get_item_req(s,j+1),!muze_nosit(j+1));
ukaz_mysku();
showview(INV_INFO_X-VEL_RAMEC,INV_INFO_Y-VEL_RAMEC,INV_INFO_XS+2*VEL_RAMEC+2,INV_INFO_YC+2*VEL_RAMEC+2);
last_pos=i;
cc=0;
}
else cc=i!=last_pos;
}
if (cc)
{
inv_item_info_box(&msgc,unused);
last_pos=-1;
}
destroy_message(&msgc);
}
}
static __inline void copy_data(char **src, void *target, int size) {
memcpy(target, *src, size);
(*src)+=size;
}
static char * load_TSHOP(char *binary, TSHOP *target) {
copy_data(&binary, target->keeper, 16);
copy_data(&binary, target->picture, 13);
copy_data(&binary, &target->koef, 4);
copy_data(&binary, &target->products, 4);
copy_data(&binary, &target->shop_id, 4);
copy_data(&binary, &target->list_size, 4);
copy_data(&binary, &target->spec_max, 2);
copy_data(&binary, &target->list, 4);
return binary;
}
static char * load_TPRODUCT(char *binary, TPRODUCT *target) {
copy_data(&binary, &target->item, 2);
copy_data(&binary, &target->cena, 4);
copy_data(&binary, &target->trade_flags, 2);
copy_data(&binary, &target->pocet, 4);
copy_data(&binary, &target->max_pocet, 4);
return binary;
}
static void rebuild_shops(void)
{
char *c=(char *)shop_hacek;
int i;
SEND_LOG("(SHOP) Rebuilding shops....");
if (shop_list!=NULL) free(shop_list);
shop_list=NewArr(TSHOP *,max_shops);
c+=4;
char *d = c;
size_t reqsize = 0;
size_t products = 0;
for(i=0;i<max_shops;i++) {
TSHOP s;
d = load_TSHOP(d, &s);
reqsize += sizeof(TSHOP)+sizeof(TSHOP *); //shop and its state + pointer to it
for (int j = 0; j < s.products; ++j) {
TPRODUCT p;
d = load_TPRODUCT(d, &p);
reqsize += sizeof(TPRODUCT) + sizeof(int32_t); //each product one state
++products;
}
}
SEND_LOG("(SHOP) Loaded total %d shops, %lu products, %lu bytes total memory", max_shops, products, reqsize);
void *newhacek = getmem(reqsize);
shop_list = (TSHOP **)newhacek;
TSHOP *shop_iter = (TSHOP *)(shop_list+max_shops);
TPRODUCT *prod_iter = (TPRODUCT *)(shop_iter+max_shops);
shop_all_state.first_product = prod_iter;
shop_all_state.count_states = products;
shop_all_state.first_state = (int32_t *)(prod_iter+products);
int32_t *state_iter = shop_all_state.first_state;
for(i=0;i<max_shops;i++) {
shop_list[i] = shop_iter;
c = load_TSHOP(c, shop_iter);
shop_iter->list = prod_iter;
for (int j = 0; j < shop_iter->products; ++j) {
c = load_TPRODUCT(c, prod_iter);
*state_iter += prod_iter->pocet;
++prod_iter;
++state_iter;
}
++shop_iter;
SEND_LOG("(SHOP) Shop found: '%s', products %d",shop_list[i]->keeper,shop_list[i]->products);
}
free(shop_hacek);
shop_hacek = newhacek;
}
void load_shops(void)
{
int *d;
if (!test_file_exist(SR_MAP,SHOP_NAME))
{
shop_hacek=NULL;
shop_list=NULL;
return;
}
shop_hacek=afile(SHOP_NAME,SR_MAP,&shop_hacek_size);
d=shop_hacek;
max_shops=*d;
if (!max_shops)
{
free(shop_hacek);
shop_hacek=NULL;
shop_list=NULL;
return;
}
rebuild_shops();
}
static int32_t *get_product_count(const TPRODUCT *p) {
int32_t index = p - shop_all_state.first_product;
assert(index >= 0 && index < (int32_t)shop_all_state.count_states);
return shop_all_state.first_state + index;
}
static void rebuild_keepers_items()
{
int i;
const TPRODUCT *p;
int remain;
char c;
memset(shp_item_map,0,sizeof(shp_item_map));
memset(shp_item_pos,0,sizeof(shp_item_map));
do
{
remain=cur_shop->list_size-top_item;
p=cur_shop->list+top_item;
for(i=0;i<8 && remain>0;remain--,p++)
if (p->trade_flags & SHP_SELL && *get_product_count(p))
{
shp_item_pos[i]=p-cur_shop->list;
shp_item_map[i++]=p->item+1;
}
c=(i<8 && top_item);
if (c) top_item--;
}
while (c);
}
static int make_offer(int i)
{
int j;
i--;
for(j=0;j<cur_shop->list_size;j++)
{
const TPRODUCT *p=cur_shop->list+j;
if (p->item==i && p->trade_flags & SHP_BUY) return p->cena-(p->cena*cur_shop->koef/100);
}
return 0;
}
static int get_sell_price(int i) //cislo predmetu
{
int j;
i--;
for(j=0;j<cur_shop->list_size;j++)
{
const TPRODUCT *p=cur_shop->list+j;
if (p->item==i && p->trade_flags & SHP_SELL && *get_product_count(p)>0) return p->cena+(p->cena*cur_shop->koef/100);
}
return 0;
}
static const TPRODUCT *find_sell_product(int i) //cislo predmetu
{
int j;
i--;
for(j=0;j<cur_shop->list_size;j++)
{
const TPRODUCT *p=cur_shop->list+j;
if (p->item==i) return p;
}
return NULL;
}
static void sell_item(int i)
{
int j;
i--;
for(j=0;j<cur_shop->list_size;j++)
{
const TPRODUCT *p=cur_shop->list+j;
if (p->item==i)
{
(*get_product_count(p))--;
return;
}
}
}
static void buy_item(int i)
{
int j;
i--;
for(j=0;j<cur_shop->list_size;j++)
{
const TPRODUCT *p=cur_shop->list+j;
if (p->item==i)
{
(*get_product_count(p))++;
return;
}
}
}
static void display_keepers_items()
{
int x,y,i;
put_picture(BUYBOX_X,BUYBOX_Y,ablock(H_SHOP_PIC));
i=0;
for(y=0;y<2*SHP_ICSIZY;y+=SHP_ICSIZY)
for(x=0;x<4*SHP_ICSIZX;x+=SHP_ICSIZX)
if (shp_item_map[i])
{
int ikn;
ikn=glob_items[shp_item_map[i++]-1].ikona;
put_picture(BUYBOX_X+SHP_ICPLCX+x,BUYBOX_Y+SHP_ICPLCY+y,ico_extract(ikn));
}
else
i++;
set_font(H_FBOLD,INV_NAME_COL);
set_aligned_position(135+BUYBOX_X,17+BUYBOX_Y,1,1,cur_shop->keeper);
outtext(cur_shop->keeper);
}
static void redraw_shop()
{
update_mysky();
schovej_mysku();
curcolor=0;
display_items_in_inv(human_selected);
display_keepers_items();
//write_shopkeeper_name(cur_shop->keeper);
other_draw();
info_box_drawed=0;
if (info_box_below!=NULL) free(info_box_below);
info_box_below=NULL;
ms_last_event.event_type=0x1;send_message(E_MOUSE,&ms_last_event);
ukaz_mysku();
showview(0,0,0,0);
}
static void block_next()
{
const TPRODUCT *p=cur_shop->list+top_item;
int remain=cur_shop->list_size-top_item;
int i,j;
if (remain<8) return;
j=top_item;
for(i=0;i<8 && remain>0;j++,remain--,p++) if (*get_product_count(p) && p->trade_flags & SHP_SELL) i++;
if (i!=8 || !remain) return;
top_item=j;
}
static void block_back()
{
const TPRODUCT *p=cur_shop->list+top_item;
int i,j;
if (top_item<8) top_item=0;
else
{
j=top_item;
for(i=0;i<8 && j>0;j--,p--) if (*get_product_count(p) && p->trade_flags & SHP_SELL) i++;
if (i==8) top_item=j; else top_item=0;
}
return;
}
static void redraw_keepers_items()
{
const word *w;
schovej_mysku();
w=ablock(H_SHOP_PIC);
display_keepers_items();
ukaz_mysku();
showview(BUYBOX_X,BUYBOX_Y,w[0],w[1]);
}
char shop_keeper_click(int id, int xa, int ya, int xr, int yr) {
id;
xa;
ya;
if (picked_item == NULL) {
int i, j;
xr = (xa - BUYBOX_X - SHP_ICPLCX);
yr = (ya - BUYBOX_Y - SHP_ICPLCY);
if (xr < 0 || yr < 0)
return 0;
xr /= SHP_ICSIZX;
yr /= SHP_ICSIZY;
i = yr * 4 + xr;
if (i < 8 && i >= 0 && (j = shp_item_map[i]) != 0) {
picked_item = NewArr(short, 2);
picked_item[0] = shp_item_map[i];
picked_item[1] = 0;
shp_item_map[i] = 0;
cur_owner = -1;
schovej_mysku();
pick_set_cursor();
redraw_keepers_items();
ukaz_mysku();
update_mysky();
if ((get_control_key_state()) && (game_extras & EX_FAST_TRADE)
&& get_sell_price(*picked_item) <= money) {
play_sample_at_channel(H_SND_OBCHOD, 1, 100);
money -= get_sell_price(*picked_item);
sell_item(*picked_item);
if (put_item_to_inv(human_selected, picked_item)) {
picked_item = NULL;
pick_set_cursor();
}
rebuild_keepers_items();
cur_owner = picked_item != NULL;
redraw_shop();
}
return 1;
}
} else if (cur_owner == -1) {
free(picked_item);
picked_item = NULL;
rebuild_keepers_items();
schovej_mysku();
pick_set_cursor();
redraw_keepers_items();
ukaz_mysku();
update_mysky();
cur_owner = 0;
return 1;
}
if (cur_owner != -1 && picked_item != NULL) {
int price, z;
char c[200];
mouse_set_cursor(H_MS_DEFAULT);
if (picked_item[1] != 0) {
message(1, 0, 0, "", texty[100], texty[80]);
wire_shop();
} else {
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]);
wire_shop();
} else {
int p;
const TPRODUCT *pp;
pp = find_sell_product(z);
sprintf(c, texty[102], price);
p = message(3, 0, 1, texty[118], c, texty[77], texty[230],
texty[78]);
if (p == 2)
price = -1;
if (p == 1)
price = smlouvat(price, pp->cena, *get_product_count(pp), money, 0);
if (price >= 0) {
play_sample_at_channel(H_SND_OBCHOD, 1, 100);
buy_item(z);
free(picked_item);
picked_item = NULL;
money += price;
rebuild_keepers_items();
}
wire_shop();
}
}
pick_set_cursor();
update_mysky();
return 1;
}
return 0;
}
char shop_bag_click(int id,int xa,int ya,int xr,int yr)
{
char s[200],p;
int price,z;
const TPRODUCT *pp;
if (cur_owner>-1)
{
id=bag_click(id,xa,ya,xr,yr);
cur_owner=picked_item!=NULL;
if (picked_item!=NULL && picked_item[1]==0 && (game_extras & EX_FAST_TRADE) && (get_control_key_state()))
{
short z;
price=make_offer(z=picked_item[0]);
if (price)
{
play_sample_at_channel(H_SND_OBCHOD,1,100);
buy_item(z);
free(picked_item);picked_item=NULL;
money+=price;
rebuild_keepers_items();
pick_set_cursor();
redraw_shop();
}
}
return id;
}
if (picked_item==NULL) return 0;
z=picked_item[0];
price=get_sell_price(z);
pp=find_sell_product(z);
if (pp==NULL) return 0;
mouse_set_cursor(H_MS_DEFAULT);
if (!price) return 0;
if (price>money)
{
p=message(2,0,0,"",texty[104],texty[230],texty[78]);
if (!p) price=smlouvat(price,pp->cena,*get_product_count(pp),money,1);else price=-1;
}
else
{
sprintf(s,texty[101],price);
p=message(3,0,1,texty[118],s,texty[77],texty[230],texty[78]);
if (p==1) price=smlouvat(price,pp->cena,*get_product_count(pp),money,1);else
if (p==2) price=-1;
}
if (price>=0)
{
play_sample_at_channel(H_SND_OBCHOD,1,100);
money-=price;
sell_item(z);
rebuild_keepers_items();
id=bag_click(id,xa,ya,xr,yr);
cur_owner=picked_item!=NULL;
}
else
{
shop_keeper_click(0,0,0,0,0);
}
wire_shop();
return 1;
}
char shop_block_click(int id, int xa, int ya,int xr,int yr)
{
xa,ya,xr,yr;
if (id==1) block_back();else block_next();
rebuild_keepers_items();
redraw_keepers_items();
return 1;
}
static int old_inv_view_mode;
void unwire_shop()
{
send_message(E_DONE,E_MOUSE,shop_mouse_event);
norefresh=0;
wire_proc=wire_shop;
inv_view_mode=old_inv_view_mode;
}
void wire_shop()
{
int32_t size;
static TSHOP *last_shop=NULL;
static void *pic=NULL;
mute_all_tracks(0);
old_inv_view_mode=inv_view_mode;
inv_view_mode=0;
inv_redraw=redraw_shop;
schovej_mysku();
if (last_shop!=cur_shop)
{
free(pic);pic=afile(cur_shop->picture,SR_DIALOGS,&size);
last_shop=cur_shop;
}
if (cur_shop->picture[0]) put_picture(5,SCREEN_OFFLINE,pic);
send_message(E_ADD,E_MOUSE,shop_mouse_event);
unwire_proc=unwire_shop;
change_click_map(clk_shop,CLK_SHOP);
if (shop_sector==viewsector) redraw_shop();else _exit_shop(0,0,0,0,0);
ukaz_mysku();
update_mysky();
}
void enter_shop(int shopid)
{
int i;
SEND_LOG("(SHOP) Entering shop...");
for(i=0;i<POCET_POSTAV;i++) if (isdemon(postavy+i)) unaffect_demon(i);
for(i=0;i<POCET_POSTAV && postavy[i].sektor!=viewsector;i++);
if (i==POCET_POSTAV) return; //nesmysl, nemelo by nikdy nastat.
if (battle) return;
select_player=i;
inv_view_mode=0;
human_selected=postavy+i;
top_item=0;cur_owner=(picked_item!=NULL);
for(i=0;i<max_shops;i++) if (shop_list[i]->shop_id==shopid) break;
if (i==max_shops) return;
unwire_proc();
cur_shop=shop_list[i];
curcolor=0;
bar32(0,0,639,479);
rebuild_keepers_items();
bott_draw(1);
shop_sector=viewsector;
wire_shop();
cancel_render=1;
cancel_pass=1;
norefresh=1;
cur_mode=MD_SHOP;
}
word *xs;
char shop_change_player(int id, int xa, int ya,int xr,int yr)
{
const word *xs;
int i;
id;xa;ya;yr;
xs=ablock(H_OKNO);
i=xr/xs[0];
if (i<POCET_POSTAV)
{
THUMAN *p;
i=group_sort[i];
p=&postavy[i];
if (p->used && p->sektor==viewsector) {
if (ms_last_event.event_type & 0x2)
{
int j=select_player;
select_player=i;
human_selected=p;
if (i==j && cur_owner>-1)
{
unwire_proc();
wire_inv_mode(p);
}
else
{
bott_draw(1);
redraw_shop();
}
}
else if (picked_item!=NULL && cur_owner>-1)
{
if (put_item_to_inv(p,picked_item))
{
free(picked_item);picked_item=NULL;
pick_set_cursor();
redraw_shop();
}
}
else if (picked_item==NULL) _exit_shop(id,xa,ya,xr,yr);
}
return 1;
}
return 0;
}
char _exit_shop(int id, int xa, int ya,int xr,int yr)
{
xr,yr,xa,ya,id;
SEND_LOG("(SHOP) Exiting shop...");
if (cur_owner==-1)
{
free(picked_item);
picked_item=NULL;
pick_set_cursor();
}
unwire_proc();
wire_main_functs();
return 1;
}
static void reroll_shop(TSHOP *p)
{
int i,j,r;
int poc_spec=0;
const TPRODUCT *pr;
SEND_LOG("(SHOP) Shops reroll: '%s' ",p->keeper);
pr=p->list;
for(i=0;i<p->list_size;i++,pr++)
{
if (pr->trade_flags & SHP_AUTOADD && *get_product_count(pr)<pr->max_pocet) (*get_product_count(pr))++;
if (pr->trade_flags & SHP_SPECIAL)
{
poc_spec++;if (*get_product_count(pr)>0) *get_product_count(pr)=0;
}
}
pr=p->list;
for(i=0;i<p->spec_max;i++)
{
int i=0;
r=rnd(poc_spec)+1;
for(j=0;i<r;j++) if (pr[j].trade_flags & SHP_SPECIAL) i++;
j--;
const TPRODUCT *sel = pr+j;
int maxp = MAX(sel->max_pocet,1);
*get_product_count(pr+j)=rnd(maxp)+1;
}
}
void reroll_all_shops()
{
int i;
for(i=0;i<max_shops;i++) reroll_shop(shop_list[i]);
}
char save_shops()
{
SEND_LOG("(SHOP) Saving shops...");
if (shop_all_state.count_states == 0) {
temp_storage_delete(_SHOP_ST);
return 0;
}
temp_storage_store(_SHOP_ST, shop_all_state.first_state, shop_all_state.count_states*sizeof(*shop_all_state.first_state));
return 0;
}
char load_saved_shops()
{
SEND_LOG("(SHOP) Loading saved shops...");
int32_t sz = temp_storage_find(_SHOP_ST);
int32_t needsz = shop_all_state.count_states*(sizeof(*shop_all_state.first_state));
if (sz != needsz) return 0;
temp_storage_retrieve(_SHOP_ST, shop_all_state.first_state, sz);
return 0;
}