/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #ifndef NUVIE_CORE_CONVERSE_H #define NUVIE_CORE_CONVERSE_H #include "ultima/shared/std/string.h" #include "ultima/shared/std/containers.h" #include "ultima/nuvie/actors/actor.h" #include "ultima/nuvie/gui/widgets/msg_scroll.h" #include "ultima/nuvie/files/u6_lib_n.h" #include "ultima/nuvie/views/view.h" namespace Ultima { namespace Nuvie { class Actor; class ActorManager; class Configuration; class MsgScroll; class GameClock; class ObjManager; class Player; class ViewManager; class U6Lib_n; class U6Lzw; class ConverseInterpret; class ConverseSpeech; class ConvScript; using Std::string; ConverseGumpType get_converse_gump_type_from_config(const Configuration *config); typedef uint32 converse_value; // any single value read from a script typedef unsigned char *convscript_buffer; typedef struct { uint8 type; converse_value val; } converse_typed_value; #define U6TALK_VAR_SEX 0x10 // sex of avatar: male=0 female=1 #define U6TALK_VAR_KARMA 0x14 // avatar's karma #define U6TALK_VAR_GARGF 0x15 // 1=player knows Gargish #define U6TALK_VAR_NPC_NAME 0x17 #define U6TALK_VAR_PARTYLIVE 0x17 // number of people (living) following avatar #define U6TALK_VAR_PARTYALL 0x18 // number of people (total) following avatar #define U6TALK_VAR_HP 0x19 // avatar's health #define U6TALK_VAR_PLAYER_NAME 0x19 #define U6TALK_VAR_QUESTF 0x1A // 0="Thou art not upon a sacred quest!" #define WOUTALK_VAR_ADD_TO_INVENTORY_FAILED 0x1D #define U6TALK_VAR_WORKTYPE 0x20 // current activity of npc, from schedule #define U6TALK_VAR_YSTRING 0x22 // value of $Y variable. #define U6TALK_VAR_INPUT 0x23 // previous input from player ($Z) #define U6TALK_VAR__LAST_ 0x25 // (all above 36 appear uninitialized) /* Conversation engine, apart from the interpreter. Loads converse files, * and reads script into buffer. Also manages input/output and has npc-related * support functions. This class handles all game types. */ class Converse { friend class ConverseInterpret; friend class SETalkInterpret; friend class MDTalkInterpret; friend class WOUConverseInterpret; friend class U6ConverseInterpret; // game system objects from nuvie const Configuration *config; GameClock *_clock; ActorManager *actors; ObjManager *objects; Player *player; ViewManager *views; MsgScroll *scroll; // i/o nuvie_game_t gametype; // what game is being played? U6Lib_n *src; uint8 src_num; // identify source file: 0=unset/unused const char *src_name(); ConverseInterpret *conv_i; // interpreter ConvScript *script; View *last_view; Actor *npc; uint8 npc_num; uint8 script_num; //this could differ from npc_num when talking to guards or wisps etc. Std::string _name, _desc; bool active; // running npc script? (either paused or unpaused) bool need_input; // waiting for text input bool party_all_the_time; // force NPCs to join player's party? string in_str; // last input from player string out_str; // text that is to be printed char *allowed_input; // characters requested for single-character input char aname[16]; // return from npc_name() struct converse_variables_s { converse_value cv; char *sv; } *variables; /* initialized for [U6TALK_VAR__LAST_+1] items */ ConverseSpeech *speech; bool using_fmtowns; void reset(); public: Converse(); ~Converse(); void init(const Configuration *cfg, nuvie_game_t t, MsgScroll *s, ActorManager *a, GameClock *c, Player *p, ViewManager *v, ObjManager *o); uint32 get_script_num(uint8 a); void load_conv(const Std::string &convfilename); uint32 load_conv(uint8 a); void unload_conv() { delete src; src = nullptr; } ConvScript *load_script(uint32 n); ConverseInterpret *new_interpreter(); bool start(Actor *a) { return start(a->get_actor_num()); } bool start(uint8 n); void continue_script(); void stop(); bool running() const { return active; } bool is_waiting_for_scroll() { return scroll->get_page_break(); } void unwait(); void poll_input(const char *allowed = nullptr, bool nonblock = true); bool override_input(); void collect_input(); bool input(); void print(const char *s = nullptr); const Std::string &get_input() const { return in_str; } const Std::string &get_output() const { return out_str; } void set_input(Std::string s) { in_str = s; } void set_output(Std::string s) { out_str = s; } void set_party_all_the_time(bool val) { party_all_the_time = val; } const char *npc_name(uint8 num); void show_portrait(uint8 n); converse_value get_var(uint8 varnum) const { return (varnum <= U6TALK_VAR__LAST_ ? variables[varnum].cv : 0x00); } const char *get_svar(uint8 varnum); void set_var(uint8 varnum, uint32 val) { if (varnum <= U6TALK_VAR__LAST_) variables[varnum].cv = val; } void set_svar(uint8 varnum, const char *set); void init_variables(); void delete_variables(); ConverseSpeech *get_speech() { return speech; }; bool conversations_stop_music; private: void print_prompt(); }; /* Conversation script container. Maintains current position in the script. The * object only exists if it has data loaded. Different classes with an identical * interface can be created to handle different games' file formats. */ class ConvScript { friend class Converse; convscript_buffer buf; uint32 buf_len; convscript_buffer buf_pt; // pointer into script (current location) U6Lib_n *src; uint32 src_index; bool compressed; // was the original file (LZW) compressed? uint8 ref; // Multiple objects can use the same buffer ConvScript *cpy; public: ConvScript(U6Lib_n *s, uint32 idx); ConvScript(ConvScript *orig); ~ConvScript(); void read_script(); bool loaded() const { return ((buf && buf_len)); // script is loaded? } /* Reading */ converse_value read(uint32 advance = 1); converse_value read2(); converse_value read4(); converse_value peek(uint32 displacement = 0) { return ((converse_value) * (buf_pt + displacement)); } /* Writing */ void write2(converse_value val); /* Seeking - update script pointer */ void rewind() { buf_pt = buf; } void skip(uint32 bytes = 1) { buf_pt += bytes; } void seek(uint32 offset = 0) { rewind(); skip(offset); } uint32 pos() const { return buf_pt - buf; } bool overflow(uint32 ptadd = 0) const { return (((pos() + ptadd) >= buf_len)); } convscript_buffer get_buffer(uint32 ptadd = 0) { return ((!ptadd || (ptadd < buf_len)) ? buf + ptadd : nullptr); } }; } // End of namespace Nuvie } // End of namespace Ultima #endif