#include #include #include #include "globals.h" #include "../platform/error.h" #include "../platform/platform.h" #include #define console_max_characters 120 #define console_max_lines 300 void macro_drop_item(int sector,int smer,short item); /****/ void wzprintf(const char *text,...) __attribute__((format(printf, 1, 2))); static void wzputs(const char *text); char *side_flags[]= { "AUTOMAP", "!PLR", "!MONST", "!THING", "!SOUND", "ALARM", "PASS", "TRANSPARENT", "P_ANIM", "P_VIS", "P_PING", "P_FORW", "S_ANIM", "S_VIS", "S_PING", "S_FORW", "LEFT_A", "RIGHT_A", "ALT_SIDES", "SPEC", "COPY", "SEND", "APLY2ND", "AUTOANIM", "", "", "", "", "", "SECRET", "TRUESEE", "INVIS" }; char *obl_flags[]= { "RECESS", "UP_SIDE", "DOWN_SIDE", "ITPUSH" }; char *mc_flags[]= { "MAPPED", "FLY_OBJECT", "PLAYER", "DEAD_PLAYER", "SPECTXTR", "SAFEPLACE", "UNUSED", "MARKED!", "SHADED", "STAIRS", "DOWN", "!AUTOMAP", "!SUMMON" }; void show_flags(int number,char **flags,char nums) { int i=0; while (nums--) { if (number & 1) wzprintf("%s ",flags[i]); i++; number>>=1; } } void spell_group_invis() { int i; char ok=1; for(i=0;iused) { wzprintf("%d.%-14s (%d) Sek:%5d Smr:%d HPReg:%d MPReg:%d VPReg:%d %04X%s\n",i+1,p->jmeno,p->groupnum,p->sektor,p->direction,p->vlastnosti[VLS_HPREG], p->vlastnosti[VLS_MPREG], p->vlastnosti[VLS_VPREG], p->vlastnosti[VLS_KOUZLA], p->lives?"":"(dead)"); } } wzprintf("Held items: "); v=picked_item; if (v==NULL) wzprintf("\n");else while(*v) wzprintf("%d \n",abs(*v++)-1); for(i=0,cn=0,astr=0;isector_type, ss->floor,ss->ceil,ss->sector_tag,ss->side_tag,ss->action); wzprintf(" Exits: North %d East %d South %d West %d\n",ss->step_next[0],ss->step_next[1],ss->step_next[2],ss->step_next[3]); wzprintf(" FLAGS: %02X %02X ",ss->flags,map_coord[viewsector].flags); show_flags(map_coord[viewsector].flags,mc_flags,12); wzprintf("\nSide: Prim %d Sec %d Arc %d Anim_prim %d/%d Anim_sec %d/%d\n", s->prim,s->sec,s->oblouk & 0xf,s->prim_anim>>4,s->prim_anim & 0xf,s->sec_anim>>4,s->sec_anim & 0xf); wzprintf(" Action target %d Action side %d Action %d\n",s->action,s->sector_tag,s->side_tag & 0x3); wzprintf(" Multiaction: %s\n",macros[viewsector*4+viewdir].action_list==NULL?"No":"Yes"); wzprintf(" Flags: %04X %02X %02X\n",s->flags,s->oblouk>>4,s->side_tag>>2); show_flags(s->flags,side_flags,32); show_flags(s->oblouk>>4,obl_flags,4); wzprintf("\n"); return 0; } /*****/ void unaffect(); extern char immortality; extern char nohassle; extern char dead_food; extern char pass_all_mobs; static char console_input_line[console_max_characters+1] = ""; static char *console_output_lines[console_max_lines] = {}; static int console_top_line = 0; static const char *console_command = NULL; static int copied_text = 0; static const int console_x = 0; static const int console_y = SCREEN_OFFLINE; static const int console_width = 640; static const int console_height = 165; static const int console_padding = 3; static int console_blink = 0; static char console_visible = 0; #define CONSOLE_FONT H_FLITT5 void draw_console_window() { if (!console_visible) return; trans_bar(console_x, console_y, console_width, console_height, 0); set_font(CONSOLE_FONT, RGB555(31,31,16)); int y = console_y+console_height-text_height("X")-console_padding; position(console_x+console_padding, y); outtext("$ "); outtext(console_input_line); if ((console_blink>>1) & 1) { outtext("_"); } ++console_blink; set_font(CONSOLE_FONT, RGB555(31,31,31)); y-=3*text_height("X")/2; for (int i = 0; i < console_max_lines;++i) { int p = i + console_top_line; if (p>=console_max_lines) break; position(console_x+console_padding,y); if (console_output_lines[p]) outtext(console_output_lines[p]); y-=text_height("X"); if (y < console_y+console_padding) break; } if (copied_text > 0) { const char *c = "Copied"; set_aligned_position(console_x+console_width, console_y, 2, 0, c); outtext(c); --copied_text; } else if (get_control_key_state()) { const char *c = "Press CTRL+C to copy content"; set_aligned_position(console_x+console_width, console_y, 2, 0, c); outtext(c); } } char console_is_visible() { return console_visible; } static void console_add_line(const char *line); static void flush_console_command() { if (console_command) { const char *cmd = concat2("> ", console_command); console_command = NULL; console_add_line(cmd); } } static void console_add_line_s(const char *line, size_t sz) { flush_console_command(); free(console_output_lines[console_max_lines-1]); memmove(console_output_lines+1,console_output_lines, (console_max_lines-1)*sizeof(char *)); console_output_lines[0] = malloc(sz+1); memcpy(console_output_lines[0], line, sz); console_output_lines[0][sz] = 0; } static void console_add_line(const char *line) { console_add_line_s(line, strlen(line)); } typedef struct { char *cmd_buffer; const char *command; const char *args; } PARSED_COMMAND; static PARSED_COMMAND parse_command(const char *cmd) { PARSED_COMMAND ret; ret.command = 0; ret.args = 0; ret.cmd_buffer = strdup(cmd); char *c =ret.cmd_buffer; while (*c && isspace(*c)) ++c; if (!*c) return ret; ret.command = c; ret.args = NULL; char *sep = strchr(c, ' '); if (sep!= NULL) { *sep = 0; ++sep; while (*sep && isspace(*sep)) ++sep; if (*sep) { ret.args = sep; char *end = strrchr(sep,0); end--; while (end > sep && isspace(*end)) end--; end++; *end = 0; } } return ret; } extern int ghost_walls; extern int nofloors; static int process_on_off_command(const char *cmd, char on) { if (istrcmp(cmd, "inner-eye") == 0) { log_combat = on; return 1; } if (istrcmp(cmd, "hunter-instinct") == 0) { show_lives = on; return 1; } if (istrcmp(cmd, "no-hassle") == 0) { nohassle=on; return 1; } if (istrcmp(cmd, "iron-skin") == 0) { immortality=on; return 1; } if (istrcmp(cmd, "spirit-wander") == 0) { cur_group=on?10:postavy[0].groupnum; return 1; } if (istrcmp(cmd, "ghost-walls") == 0) { ghost_walls = on; return 1; } if (istrcmp(cmd, "true-seeing") == 0) { true_seeing = on; return 1; } if (istrcmp(cmd, "walking-in-air") == 0) { nofloors = on; return 1; } if (istrcmp(cmd, "enemy-insight") == 0) { show_mob_info = on; return 1; } if (istrcmp(cmd, "enemy-walk-diagonal") == 0) { game_extras = on?(game_extras | EX_WALKDIAGONAL):(game_extras & ~EX_WALKDIAGONAL); return 1; } if (istrcmp(cmd, "ghost-form") == 0) { pass_all_mobs = on; return 1; } if (istrcmp(cmd, "dead-food") == 0) { dead_food = on; return 1; } if (istrcmp(cmd, "trace-dialogs") == 0) { trace_dialogs = on; return 1; } return 0; } void postavy_teleport_effect(int sector,int dir,int postava,char effect); static void command_ls_callback(const char *name, void* ctx) { wzprintf("%s\n", name); } static int process_actions(const char *command) { if (istrcmp(command, "flute") == 0) { bott_draw_fletna(); return 1; } if (istrcmp(command, "global-map") == 0) { wire_global_map(); return 1; } if (istrcmp(command, "status") == 0) { display_game_status(); return 1; } if (istrcmp(command, "offlers-blessing") == 0) { money=150000; play_fx_at(FX_MONEY); return 1; } if (istrcmp(command, "i-require-gold") == 0) { money+=1; play_fx_at(FX_MONEY); return 1; } if (istrcmp(command, "to-the-moon") == 0) { money+=100000; play_fx_at(FX_MONEY); return 1; } if (istrcmp(command, "echo-location") == 0) { for (int i = 1; i < mapsize; ++i) { map_coord[i].flags |= MC_AUTOMAP; } play_fx_at(FX_MAP); return 1; } if (istrcmp(command, "rise-and-shine") == 0) { int r = 0; for (int i = 0; i < POCET_POSTAV; ++i) { THUMAN *p = postavy+i; if (p->used && p->inmaphash == current_map_hash) { p->lives=p->vlastnosti[VLS_MAXHIT]; p->mana=p->vlastnosti[VLS_MAXMANA]; p->kondice=p->vlastnosti[VLS_KONDIC]; p->sektor = viewsector; r = 1; } } bott_draw(0); return r; } if (istrcmp(command, "save") == 0) { do_autosave(); return 1; } if (istrcmp(command, "ascent") == 0) { int lev = postavy[0].level; for (int i = 0; i < POCET_POSTAV; ++i) { THUMAN *p = postavy+i; if (p->used) lev = MAX(lev,p->level); } for (int i = 0; i < POCET_POSTAV; ++i) { THUMAN *p = postavy+i; if (p->used) { p->exp = level_map[lev-1]; check_player_new_level(p); } } return 1; } if (istrcmp(command, "by-the-power-of-grayskull") == 0) { memset(runes,0xFF, sizeof(runes)); play_fx_at(FX_MAGIC); return 1; } if (istrcmp(command, "beam-me-up") == 0) { for (int i = 1; i < mapsize; ++i) { map_coord[i].flags |= MC_AUTOMAP; } play_fx_at(FX_MAP); int kdo = 0; THUMAN *h = postavy; for(int i=0;i= 0) { const TMOB *t =(TMOB *)ablock(H_ENEMY); int sect = map_sectors[viewsector].step_next[viewdir]; if (sect) { load_enemy_to_map(choosen_id, sect, (viewdir+2) & 3, t+id); return 1; } } } } return 0; } return 0; } if (istrcmp(cmd, "say") == 0) { console_add_line(args); return 1; } if (istrcmp(cmd, "speed") == 0) { long v = strtol(args, NULL, 10); if (v > 0) timerspeed_val = v; return v > 0; } if (istrcmp(cmd, "portal-jump") == 0) { if (check_file_exists(build_pathname(2,gpathtable[SR_MAP], args))) { TMA_LOADLEV lev; strcopy_n(lev.name,args,sizeof(lev.name)); lev.start_pos = 0; macro_load_another_map(&lev); return 1; } return 0; } if (istrcmp(cmd, "unachieve") == 0) { return !clear_achievement(args); } if (istrcmp(cmd, "talk") == 0) { if (args[0] == 0) return 0; int id; char pgf = 0; if (args[0] == '/') { pgf = 1; args++; } id = atoi(args); if (!pgf) id = id * 128; if (dialog_is_paragraph(id)) { call_dialog(id, -1); return 1; } } if (istrcmp(cmd, "unvisit") == 0) { if (args[0] == 0) return 0; int id = atoi(args); return dialog_set_notvisited(id); } if (istrcmp(cmd, "cat") == 0) { int32_t sz =temp_storage_find(args); if (sz < 0) return 0; char *data = (char *)malloc(sz+1); temp_storage_retrieve(args,data,sz); data[sz] = 0; char *data2 = (char *)malloc(sz+10); int xs, ys; zalamovani(data, data2,600, &xs, &ys); char *iter = data2; while (iter < data2+sz) { wzputs(iter); iter = iter + strlen(iter)+1; } free(data); free(data2); return 1; } if (istrcmp(cmd, "hex") == 0) { int32_t sz =temp_storage_find(args); if (sz < 0) return 0; uint8_t *data = (uint8_t *)malloc(sz); temp_storage_retrieve(args,data,sz); char *data2 = (char *)malloc(sz*3+1); char *iter = data2; for (int32_t i = 0; i < sz; i++) { snprintf(iter,4, "%02X ", (int)data[i]); iter = iter+3; } char *data3 = (char *)malloc(sz*3+10); int xs, ys; zalamovani(data2, data3,600, &xs, &ys); iter = data3; while (*iter) { wzputs(iter); iter = iter + strlen(iter)+1; } free(data3); free(data2); free(data); return 1; } if (istrcmp(cmd, "rm") == 0) { if (strcmp(args, "*") == 0) { temp_storage_clear(); } else { int32_t sz =temp_storage_find(args); if (sz < 0) return 0; temp_storage_delete(args); } return 1; } if (istrcmp(cmd, "crash") == 0) { throw_exception(args); return 1; } return 0; } static int process_command(PARSED_COMMAND cmd) { if (cmd.command == NULL) { console_add_line(""); return 0; } int onoff = -1; if (cmd.args) { if (istrcmp(cmd.args, "on") == 0) onoff = 1; else if (istrcmp(cmd.args, "off") == 0) onoff = 0; } else { return process_actions(cmd.command); } if (onoff != -1) { return process_on_off_command(cmd.command, onoff); } else return process_with_params(cmd.command, cmd.args); return 0; } static void console_copy_to_clipboard() { size_t needsz = 0; for (unsigned int i = 0; i < console_max_lines; ++i) { if (console_output_lines[i]) needsz = needsz + strlen(console_output_lines[i]) + 2; } needsz+=1; char *text = (char *)malloc(needsz); char *iter = text; for (unsigned int i = console_max_lines; i > 0; ) { --i; if (console_output_lines[i]) { size_t len = strlen(console_output_lines[i]); memcpy(iter, console_output_lines[i], len); iter+=len; *iter = '\r'; ++iter; *iter = '\n'; ++iter; } } *iter = 0; if (copy_text_to_clipboard(text)) { copied_text = 20; } free(text); } static void console_keyboard(EVENT_MSG *msg, void **_) { if (msg->msg == E_KEYBOARD) { int code = va_arg(msg->data, int); int c = code & 0xFF; if (c == E_QUIT_GAME_KEY) return; if (c) { int len = strlen(console_input_line); if (c == 0x1B) { console_show(0); msg->msg = -1; return; } if (c == '\b') { if (len) { console_input_line[len-1] = 0; } msg->msg = -1; } else if (c == '\r') { console_command = console_input_line; PARSED_COMMAND cmd = parse_command(console_input_line); char ok = process_command(cmd); if (ok) { flush_console_command(); console_top_line = 0; console_input_line[0] = 0; } console_command = NULL; free(cmd.cmd_buffer); msg->msg = -1; } else if (c == 3 && !get_shift_key_state()) { console_copy_to_clipboard(); } else if (c >=32 && len < console_max_characters) { console_input_line[len] = c; console_input_line[len+1] = 0; msg->msg = -1; } } else { switch (code >> 8) { case 'I': console_top_line = MIN(console_max_lines-10, console_top_line+10);break; case 'Q': console_top_line = MAX(0, console_top_line-10);break; case 'H': console_top_line = MIN(console_max_lines-10, console_top_line+1);break; case 'P': console_top_line = MAX(0, console_top_line-1);break; case 'G': console_top_line = console_max_characters-10;break; case 'O': console_top_line = 0;break; default: return; } msg->msg = -1; } } } static void wire_console(void) { send_message(E_ADD,E_KEYBOARD, console_keyboard); } static void unwire_console(void) { send_message(E_DONE,E_KEYBOARD, console_keyboard); } void console_show(char show) { if (console_visible != show) { console_visible = show; if (show) wire_console(); else unwire_console(); } } void wzprintf(const char *text,...) { char buff[console_max_characters+1]; static char wzprint_line[console_max_characters+1]; va_list lst; va_start(lst, text); vsnprintf(buff,console_max_characters, text, lst); char *c = buff; char *d = strchr(c, '\n'); while (d != NULL) { *d = 0; strncat(wzprint_line,c, console_max_characters); wzprint_line[console_max_characters] = 0; console_add_line(wzprint_line); c = d+1; d = strchr(c, '\n'); wzprint_line[0] = 0; } strncat(wzprint_line, c, console_max_characters); wzprint_line[console_max_characters] = 0; } static void wzputs(const char *text) { const char *sep = strchr(text, '\n'); while (sep != NULL) { console_add_line_s(text, sep-text); text = sep+1; sep = strchr(text, '\n'); } if (text[0] != 0) console_add_line_s(text, strlen(text)); }