00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef CHUNKS_H
00026 #define CHUNKS_H
00027
00028 #include "objlist.h"
00029
00030
00031 #include "exult_constants.h"
00032 #include "rect.h"
00033 #include "shapeid.h"
00034 #include "tiles.h"
00035 #include "vec.h"
00036 #include "chunkter.h"
00037
00038 class Map_chunk;
00039 class Egg_object;
00040 class Game_object;
00041 class Npc_actor;
00042 class Image_buffer8;
00043 class Chunk_terrain;
00044
00045
00046
00047
00048
00049 class Chunk_cache : public Game_singletons
00050 {
00051 Map_chunk *obj_list;
00052 unsigned long blocked[256];
00053
00054 Egg_vector egg_objects;
00055 unsigned short eggs[256];
00056
00057
00058
00059
00060 Game_object_vector doors;
00061 friend class Map_chunk;
00062 Chunk_cache();
00063 ~Chunk_cache();
00064 int get_num_eggs()
00065 { return egg_objects.size(); }
00066
00067 void set_blocked(int startx, int starty, int endx, int endy,
00068 int lift, int ztiles, bool set);
00069
00070 void update_object(Map_chunk *chunk,
00071 Game_object *obj, bool add);
00072
00073 void set_egged(Egg_object *egg, Rectangle& tiles, bool add);
00074
00075 void update_egg(Map_chunk *chunk, Egg_object *egg, bool add);
00076
00077 void setup(Map_chunk *chunk);
00078 #if 0
00079
00080 void set_blocked_tile(int tx, int ty, int lift, int ztiles)
00081 {
00082 unsigned short val = (((1 << ztiles) - 1) << lift);
00083 unsigned short inter = blocked[ty*c_tiles_per_chunk + tx]&val;
00084 if (inter)
00085 intersects(tx, ty, inter);
00086 blocked[ty*c_tiles_per_chunk + tx] |= val;
00087 }
00088
00089 void clear_blocked_tile(int tx, int ty, int lift, int ztiles)
00090 {
00091 blocked[ty*c_tiles_per_chunk + tx] &=
00092 ~(((1 << ztiles) - 1) << lift);
00093 }
00094 #endif
00095
00096
00097 int get_highest_blocked(int lift, unsigned long tflags);
00098 int get_highest_blocked(int lift, int tx, int ty);
00099 int get_lowest_blocked(int lift, unsigned long tflags);
00100 int get_lowest_blocked(int lift, int tx, int ty);
00101
00102 int is_blocked(int height, int lift, int tx, int ty, int& new_lift,
00103 const int move_flags, int max_drop = 1, int max_rise = -1);
00104
00105 void activate_eggs(Game_object *obj, Map_chunk *chunk,
00106 int tx, int ty, int tz, int from_tx, int from_ty,
00107 unsigned short eggbits, bool now);
00108 void activate_eggs(Game_object *obj, Map_chunk *chunk,
00109 int tx, int ty, int tz, int from_tx, int from_ty, bool now)
00110 {
00111 unsigned short eggbits = eggs[
00112 (ty%c_tiles_per_chunk)*c_tiles_per_chunk +
00113 (tx%c_tiles_per_chunk)];
00114 if (eggbits)
00115 activate_eggs(obj, chunk, tx, ty, tz,
00116 from_tx, from_ty, eggbits, now);
00117 }
00118
00119 Game_object *find_door(Tile_coord t);
00120 public:
00121
00122 inline int is_blocked_fast(int tx, int ty, int lift)
00123 {
00124 return blocked[ty*c_tiles_per_chunk + tx] & (3 << (2*lift));
00125 }
00126 };
00127
00128
00129
00130
00131
00132 class Map_chunk : public Game_singletons
00133 {
00134 Chunk_terrain *terrain;
00135 Object_list objects;
00136
00137 Game_object *first_nonflat;
00138
00139
00140 unsigned char from_below, from_right, from_below_right;
00141 unsigned char ice_dungeon;
00142 unsigned char *dungeon_levels;
00143 Chunk_cache *cache;
00144 unsigned char roof;
00145
00146 unsigned char dungeon_lights, non_dungeon_lights;
00147 unsigned char cx, cy;
00148 void add_dungeon_levels(Rectangle& tiles, unsigned int lift);
00149 void add_dependencies(Game_object *newobj,
00150 class Ordering_info& newinfo);
00151 static Map_chunk *add_outside_dependencies(int cx,
00152 int cy, Game_object *newobj, class Ordering_info& newinfo);
00153 public:
00154 friend class Npc_actor;
00155 Map_chunk(int chunkx, int chunky);
00156 ~Map_chunk();
00157 Chunk_terrain *get_terrain() const
00158 { return terrain; }
00159 void set_terrain(Chunk_terrain *ter);
00160 void add(Game_object *obj);
00161 void add_egg(Egg_object *egg);
00162 void remove_egg(Egg_object *egg);
00163 void remove(Game_object *obj);
00164
00165 static void gravity(Rectangle area, int lift);
00166
00167 int is_roof(int tx, int ty, int lift);
00168
00169 Object_list& get_objects()
00170 { return objects; }
00171 Game_object* get_first_nonflat() const
00172 { return first_nonflat; }
00173
00174 int get_cx() const
00175 { return cx; }
00176 int get_cy() const
00177 { return cy; }
00178 int get_dungeon_lights() const
00179 { return dungeon_lights; }
00180 int get_non_dungeon_lights() const
00181 { return non_dungeon_lights; }
00182 ShapeID get_flat(int tilex, int tiley) const
00183 { return terrain ? terrain->get_flat(tilex, tiley)
00184 : ShapeID(); }
00185 Image_buffer8 *get_rendered_flats()
00186 { return terrain ? terrain->get_rendered_flats() : 0; }
00187
00188 Chunk_cache *get_cache() const { return cache; }
00189 Chunk_cache *need_cache()
00190 {
00191 if (!cache)
00192 { cache = new Chunk_cache(); cache->setup(this); }
00193 return cache;
00194 }
00195 void setup_cache()
00196 { (void) need_cache(); }
00197
00198 void set_blocked(int startx, int starty, int endx, int endy,
00199 int lift, int ztiles, bool set)
00200 { need_cache()->set_blocked(startx, starty, endx, endy,
00201 lift, ztiles, set); }
00202
00203 int get_highest_blocked(int lift, int tx, int ty)
00204 { return need_cache()->get_highest_blocked(lift, tx, ty); }
00205 int get_lowest_blocked(int lift, int tx, int ty)
00206 { return need_cache()->get_lowest_blocked(lift, tx, ty); }
00207
00208 int is_blocked(int height, int lift, int tx, int ty, int& new_lift,
00209 const int move_flags, int max_drop = 1, int max_rise = -1)
00210 { return cache->is_blocked(height, lift, tx, ty, new_lift,
00211 move_flags, max_drop, max_rise); }
00212
00213 static int is_blocked(int height, int lift, int startx, int starty,
00214 int xtiles, int ytiles, int& new_lift, const int move_flags,
00215 int max_drop, int max_rise = -1);
00216
00217 static int is_blocked(Tile_coord& tile, int height = 1,
00218 const int move_flags = MOVE_ALL_TERRAIN,
00219 int max_drop = 1, int max_rise = -1);
00220
00221 static int is_blocked(int xtiles, int ytiles, int ztiles,
00222 Tile_coord from, Tile_coord& to, const int move_flags,
00223 int max_drop = 1, int max_rise = -1);
00224 enum Find_spot_where
00225 {
00226 anywhere = 0,
00227 inside,
00228 outside
00229 };
00230
00231 static Tile_coord find_spot(Tile_coord pos, int dist,
00232 int shapenum, int framenum, int max_drop = 0,int dir = -1,
00233 Find_spot_where where = anywhere);
00234
00235 static Tile_coord find_spot(Tile_coord pos, int dist,
00236 Game_object *obj, int max_drop = 0,
00237 Find_spot_where where = anywhere);
00238
00239 void set_egged(Egg_object *egg, Rectangle& tiles, bool add)
00240 { need_cache()->set_egged(egg, tiles, add); }
00241 void activate_eggs(Game_object *obj, int tx, int ty, int tz,
00242 int from_tx, int from_ty, bool now = false)
00243 { need_cache()->activate_eggs(obj,
00244 this, tx, ty, tz, from_tx, from_ty, now);}
00245
00246 Game_object *find_door(Tile_coord t)
00247 { return need_cache()->find_door(t); }
00248 static int find_in_area(Game_object_vector& vec, Rectangle area,
00249 int shapenum, int framenum);
00250
00251 static void try_all_eggs(Game_object *obj, int tx, int ty, int tz,
00252 int from_tx, int from_ty);
00253 void setup_dungeon_levels();
00254 inline int has_dungeon()
00255 { return dungeon_levels != 0; }
00256
00257
00258
00259 inline int is_dungeon(int tx, int ty)
00260 {
00261 int tnum = ty*c_tiles_per_chunk + tx;
00262 return tnum%2? dungeon_levels[tnum/2] >> 4: dungeon_levels[tnum/2] & 0xF;
00263 }
00264
00265
00266 inline bool is_ice_dungeon(int tx, int ty)
00267 {
00268 return ice_dungeon == 0x0F;
00269 }
00270
00271
00272 void kill_cache();
00273
00274
00275 int get_obj_actors(Game_object_vector &removes, Actor_vector &actors);
00276
00277 };
00278
00279 #endif