1 /* 2 * Copyright (C) 2000-2013 The Exult Team 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 */ 18 19 #ifndef SHAPEID_H 20 #define SHAPEID_H 1 21 22 #include "exult_constants.h" 23 #include "shapevga.h" 24 #include "fontvga.h" 25 #include "singles.h" 26 #include <vector> 27 #include <memory> 28 29 30 class Shape_frame; 31 class Shape_info; 32 class Font; 33 class Image_buffer8; 34 struct Cursor_info; 35 36 enum ShapeFile { 37 SF_SHAPES_VGA = 0, // <STATIC>/shapes.vga. MUST be first. 38 SF_GUMPS_VGA, // <STATIC>/gumps.vga 39 SF_PAPERDOL_VGA, // <STATIC>/paperdol.vga 40 SF_SPRITES_VGA, // <STATIC>/sprites.vga 41 SF_FACES_VGA, // <STATIC>/faces.vga 42 SF_EXULT_FLX, // <DATA>/exult.flx 43 SF_GAME_FLX, // <DATA>/bg_data.flx or <DATA>/si_data.flx 44 // Not yet 45 //SF_FONTS_VGA, // <STATIC>/fonts.vga 46 SF_OTHER, // Other unknown FLX 47 SF_COUNT // # of preceding entries. 48 }; 49 50 // Special pixels. 51 enum Pixel_colors {POISON_PIXEL = 0, PROTECT_PIXEL, CURSED_PIXEL, 52 CHARMED_PIXEL, HIT_PIXEL, PARALYZE_PIXEL, BLACK_PIXEL, NPIXCOLORS 53 }; 54 55 /* 56 * Manage the set of shape files. 57 */ 58 class Shape_manager : public Game_singletons { 59 static Shape_manager *instance; // There shall be only one. 60 Shapes_vga_file shapes; // Main 'shapes.vga' file. 61 Vga_file files[static_cast<int>(SF_COUNT)]; // The files we manage. 62 std::unique_ptr<Fonts_vga_file> fonts = nullptr; // "fonts.vga" file. 63 std::vector<Xform_palette> xforms; // Transforms translucent colors 64 // 0xf4 through 0xfe. 65 Xform_palette *invis_xform; // For showing invisible NPC's. 66 unsigned char special_pixels[NPIXCOLORS]; // Special colors. 67 bool can_have_paperdolls = false; // Set true if the SI paperdoll file 68 // is found when playing BG 69 bool paperdolls_enabled = false; // True if paperdolls are on. 70 bool got_si_shapes = false; // Set true if the SI shapes file 71 // is found when playing BG 72 void read_shape_info(); 73 74 public: 75 friend class ShapeID; 76 Shape_manager(); 77 ~Shape_manager(); get_instance()78 static Shape_manager *get_instance() { 79 return instance; 80 } 81 void load(); // Read in files. 82 bool load_gumps_minimal(); // Read in files needed to display gumps. 83 void reload_shapes(int dragtype); // Reload a shape file. 84 void reload_shape_info(); get_file(ShapeFile f)85 Vga_file &get_file(ShapeFile f) { 86 return files[static_cast<int>(f)]; 87 } get_shapes()88 Shapes_vga_file &get_shapes() { 89 return shapes; 90 } get_xform(int i)91 inline Xform_palette &get_xform(int i) { 92 return xforms[i]; 93 } 94 // BG Only can_use_paperdolls()95 inline bool can_use_paperdolls() const { 96 return can_have_paperdolls; 97 } 98 are_paperdolls_enabled()99 inline bool are_paperdolls_enabled() const { 100 return paperdolls_enabled; 101 } 102 set_paperdoll_status(bool p)103 inline void set_paperdoll_status(bool p) { 104 paperdolls_enabled = p; 105 } 106 have_si_shapes()107 inline bool have_si_shapes() const { 108 return got_si_shapes; 109 } 110 111 // Paint shape in window. 112 void paint_shape(int xoff, int yoff, Shape_frame *shape, 113 bool translucent = false, unsigned char *trans = nullptr) { 114 if (!shape || !shape->get_data()) 115 CERR("nullptr SHAPE!!!"); 116 else if (!shape->is_rle()) 117 shape->paint(xoff, yoff); 118 else if (trans) 119 shape->paint_rle_remapped(xoff, yoff, trans); 120 else if (!translucent) 121 shape->paint_rle(xoff, yoff); 122 else 123 shape->paint_rle_translucent(xoff, yoff, &xforms[0], xforms.size()); 124 } 125 paint_invisible(int xoff,int yoff,Shape_frame * shape)126 inline void paint_invisible(int xoff, int yoff, Shape_frame *shape) { 127 if (shape) shape->paint_rle_transformed( 128 xoff, yoff, *invis_xform); 129 } 130 // Paint outline around a shape. paint_outline(int xoff,int yoff,Shape_frame * shape,Pixel_colors pix)131 inline void paint_outline(int xoff, int yoff, Shape_frame *shape, 132 Pixel_colors pix) { 133 if (shape) shape->paint_rle_outline( 134 xoff, yoff, special_pixels[static_cast<int>(pix)]); 135 } get_special_pixel(Pixel_colors pix)136 unsigned char get_special_pixel(Pixel_colors pix) { 137 return special_pixels[static_cast<int>(pix)]; 138 } 139 140 // Paint text using "fonts.vga". 141 int paint_text_box(int fontnum, const char *text, int x, int y, int w, 142 int h, int vert_lead = 0, bool pbreak = false, 143 bool center = false, int shading = -1, Cursor_info *cursor = nullptr); 144 int paint_text(int fontnum, const char *text, int xoff, int yoff); 145 int paint_text(int fontnum, const char *text, int textlen, 146 int xoff, int yoff); 147 // Get text width. 148 int get_text_width(int fontnum, const char *text); 149 int get_text_width(int fontnum, const char *text, int textlen); 150 // Get text height, baseline. 151 int get_text_height(int fontnum); 152 int get_text_baseline(int fontnum); 153 int find_cursor(int fontnum, const char *text, int x, int y, 154 int w, int h, int cx, int cy, int vert_lead); 155 Font *get_font(int fontnum); get_xforms_cnt()156 size_t get_xforms_cnt() const { 157 return xforms.size(); 158 } 159 }; 160 161 /* 162 * A shape ID contains a shape # and a frame # within the shape encoded 163 * as a 2-byte quantity. 164 */ 165 class ShapeID : public Game_singletons { 166 short shapenum = -1; // Shape #. 167 signed char framenum = -1; // Frame # within shape. 168 mutable bool has_trans = false; 169 ShapeFile shapefile = SF_SHAPES_VGA; 170 mutable Shape_frame *shape = nullptr; 171 mutable Shape_info *info = nullptr; 172 173 Shape_frame *cache_shape() const; 174 175 public: 176 // Read from buffer & incr. ptr. ShapeID(unsigned char * & data)177 ShapeID(unsigned char *&data) { 178 unsigned char l = *data++; 179 unsigned char h = *data++; 180 shapenum = l + 256 * (h & 0x3); 181 framenum = h >> 2; 182 } 183 // Create "end-of-list"/invalid entry. 184 ShapeID() = default; 185 186 ShapeID(const ShapeID&) = default; 187 ShapeID& operator=(const ShapeID&) = default; 188 ShapeID(ShapeID&&) noexcept = default; 189 ShapeID& operator=(ShapeID&&) noexcept = default; 190 virtual ~ShapeID() = default; 191 // End-of-list or invalid? is_invalid()192 bool is_invalid() const { 193 return shapenum == -1; 194 } is_eol()195 bool is_eol() const { 196 return is_invalid(); 197 } 198 get_shapenum()199 inline int get_shapenum() const { 200 return shapenum; 201 } get_framenum()202 inline int get_framenum() const { 203 return framenum; 204 } get_shapefile()205 inline ShapeFile get_shapefile() const { 206 return shapefile; 207 } get_shape()208 inline Shape_frame *get_shape() const { 209 if (shape == nullptr) { 210 cache_shape(); 211 } 212 return shape; 213 } set_translucent(bool trans)214 inline void set_translucent(bool trans) { 215 has_trans = trans; 216 } is_translucent()217 inline bool is_translucent() const { 218 if (shape == nullptr) { 219 cache_shape(); 220 } 221 return has_trans; 222 } 223 // Set to given shape. set_shape(int shnum,int frnum)224 void set_shape(int shnum, int frnum) { 225 shapenum = shnum; 226 framenum = frnum; 227 shape = nullptr; 228 info = nullptr; 229 } 230 ShapeID(int shnum, int frnum, ShapeFile shfile = SF_SHAPES_VGA) : shapenum(shnum)231 shapenum(shnum), framenum(frnum), shapefile(shfile) 232 { } 233 set_shape(int shnum)234 void set_shape(int shnum) { // Set shape, but keep old frame #. 235 shapenum = shnum; 236 shape = nullptr; 237 info = nullptr; 238 } set_frame(int frnum)239 void set_frame(int frnum) { // Set to new frame. 240 framenum = frnum; 241 shape = nullptr; 242 } set_file(ShapeFile shfile)243 void set_file(ShapeFile shfile) { // Set to new flex 244 shapefile = shfile; 245 shape = nullptr; 246 } 247 248 void paint_shape(int xoff, int yoff, bool force_trans = false) { 249 sman->paint_shape(xoff, yoff, get_shape(), 250 has_trans || force_trans); 251 } paint_invisible(int xoff,int yoff)252 void paint_invisible(int xoff, int yoff) { 253 sman->paint_invisible(xoff, yoff, get_shape()); 254 } 255 // Paint outline around a shape. paint_outline(int xoff,int yoff,Pixel_colors pix)256 inline void paint_outline(int xoff, int yoff, Pixel_colors pix) { 257 sman->paint_outline(xoff, yoff, get_shape(), pix); 258 } 259 int get_num_frames() const; 260 bool is_frame_empty() const; get_info()261 const Shape_info &get_info() const { // Get info. about shape. 262 return *(info ? info : info = 263 &Shape_manager::instance->shapes.get_info(shapenum)); 264 } get_info()265 Shape_info &get_info() { // Get info. about shape. 266 return *(info ? info : info = 267 &Shape_manager::instance->shapes.get_info(shapenum)); 268 } get_info(int shnum)269 static Shape_info &get_info(int shnum) { // Get info. about shape. 270 return Shape_manager::instance->shapes.get_info(shnum); 271 } 272 }; 273 274 /* 275 * An interface used in Get_click(): 276 */ 277 class Paintable { 278 public: 279 virtual void paint() = 0; 280 virtual ~Paintable() = default; 281 }; 282 283 #endif 284