File: chunks.h

package info (click to toggle)
exult 0.98rc1-2
  • links: PTS
  • area: contrib
  • in suites: woody
  • size: 6,924 kB
  • ctags: 8,928
  • sloc: cpp: 83,768; sh: 7,643; ansic: 4,328; makefile: 890; yacc: 618; lex: 255; xml: 19
file content (266 lines) | stat: -rw-r--r-- 9,327 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
/**
 **	Chunks.h - Chunks (16x16 tiles) on the map.
 **
 **	Written: 10/1/98 - JSF
 **/

/*
Copyright (C) 2001 The Exult Team

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 2
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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

#ifndef CHUNKS_H
#define CHUNKS_H

#include "objlist.h"


#include "exult_constants.h"
#include "rect.h"
#include "shapeid.h"
#include "tiles.h"
#include "vec.h"
#include "chunkter.h"

class Map_chunk;
class Egg_object;
class Game_object;
class Npc_actor;
class Image_buffer8;
class Chunk_terrain;

/*
 *	Data cached for a chunk to speed up processing, but which doesn't need
 *	to be saved to disk:
 */
class Chunk_cache
	{
	Map_chunk *obj_list;
	unsigned char setup_done;	// Already setup.
	unsigned short blocked[256];	// For each tile, a bit for each lift
					//   level if it's blocked by an obj.
	Egg_vector egg_objects;		// ->eggs which influence this chunk.
	unsigned short eggs[256];	// Bit #i (0-14) set means that the
					//   tile is within egg_object[i]'s
					//   influence.  Bit 15 means it's 1 or
					//   more of 
					//   egg_objects[15-(num_eggs-1)].
	friend class Map_chunk;
	Chunk_cache();			// Create empty one.
	~Chunk_cache();
	int get_num_eggs()
		{ return egg_objects.size(); }
					// Set/unset blocked region.
	void set_blocked(int startx, int starty, int endx, int endy,
						int lift, int ztiles, bool set);
					// Add/remove object.
	void update_object(Map_chunk *chunk,
						Game_object *obj, bool add);
					// Set area within egg's influence.
	void set_egged(Egg_object *egg, Rectangle& tiles, bool add);
					// Add egg.
	void update_egg(Map_chunk *chunk, Egg_object *egg, bool add);
					// Set up with chunk's data.
	void setup(Map_chunk *chunk);
					// Set blocked tile's bits.
	void set_blocked_tile(int tx, int ty, int lift, int ztiles)
		{
		blocked[ty*c_tiles_per_chunk + tx] |= 
						(((1 << ztiles) - 1) << lift);
		}
					// Clear blocked tile's bits.
	void clear_blocked_tile(int tx, int ty, int lift, int ztiles)
		{
		blocked[ty*c_tiles_per_chunk + tx] &= 
					~(((1 << ztiles) - 1) << lift);
		}
					// Get highest lift blocked below a
					//   given level for a desired tile.
	int get_highest_blocked(int lift, unsigned short tflags);
	int get_highest_blocked(int lift, int tx, int ty);
	int get_lowest_blocked(int lift, unsigned short tflags);
	int get_lowest_blocked(int lift, int tx, int ty);
					// Is a spot occupied?
	int is_blocked(int height, int lift, int tx, int ty, int& new_lift,
				const int move_flags, int max_drop = 1);
					// Activate eggs nearby.
	void activate_eggs(Game_object *obj, Map_chunk *chunk, 
			int tx, int ty, int tz,
			int from_tx, int from_ty, unsigned short eggbits);
	void activate_eggs(Game_object *obj, Map_chunk *chunk, 
			int tx, int ty, int tz, int from_tx, int from_ty)
		{
		unsigned short eggbits = eggs[
			(ty%c_tiles_per_chunk)*c_tiles_per_chunk + 
							(tx%c_tiles_per_chunk)];
		if (eggbits)
			activate_eggs(obj, chunk, tx, ty, tz,
						from_tx, from_ty,  eggbits);
		}

public:
					// Quick is blocked
	inline int is_blocked_fast(int tx, int ty, int lift)
		{
		return blocked[ty*c_tiles_per_chunk + tx] & (1 << lift);
		}
	};

/*
 *	Game objects are stored in a list for each chunk, sorted from top-to-
 *	bottom, left-to-right.
 */
class Map_chunk
	{
	Chunk_terrain *terrain;		// Flat landscape tiles.
	Object_list objects;		// ->first in list of all objs.  'Flat'
					//   obs. (lift=0,ht=0) stored 1st.
	Game_object *first_nonflat;	// ->first nonflat in 'objects'.
					// Counts of overlapping objects from
					//    chunks below, to right.
	unsigned char from_below, from_right, from_below_right;
	unsigned char ice_dungeon;	// For SI, chunk split into 4 quadrants
	unsigned char *dungeon_levels;	// A 'dungeon' level value for each tile (4 bit).
	Npc_actor *npcs;		// List of NPC's in this chunk.
					//   (Managed by Npc_actor class.)
	Chunk_cache *cache;		// Data for chunks near player.
	unsigned char roof;		// 1 if a roof present.
	unsigned char light_sources;	// # light sources in chunk.
	unsigned char cx, cy;		// Absolute chunk coords. of this.
	void add_dungeon_levels(Rectangle& tiles, unsigned int lift);
	void add_dependencies(Game_object *newobj,
					class Ordering_info& newinfo);
	static Map_chunk *add_outside_dependencies(int cx,
		int cy, Game_object *newobj, class Ordering_info& newinfo);
public:
	friend class Npc_actor;
	Map_chunk(int chunkx, int chunky);
	~Map_chunk();			// Delete everything in chunk.
	Chunk_terrain *get_terrain() const
		{ return terrain; }
	void set_terrain(Chunk_terrain *ter);
	void add(Game_object *obj);	// Add an object.
	void add_egg(Egg_object *egg);	// Add/remove an egg.
	void remove_egg(Egg_object *egg);
	void remove(Game_object *obj);	// Remove an object.
					// Apply gravity over given area.
	static void gravity(Rectangle area, int lift);
					// Is there a roof? Returns height
	int is_roof(int tx, int ty, int lift);

	Object_list& get_objects()
		{ return objects; }
	Game_object* get_first_nonflat() const
		{ return first_nonflat; }

	int get_cx() const
		{ return cx; }
	int get_cy() const
		{ return cy; }
	Npc_actor *get_npcs()		// Get ->first npc in chunk.
		{ return npcs; }
	int get_light_sources() const	// Get #lights.
		{ return light_sources; }
	ShapeID get_flat(int tilex, int tiley) const
		{ return terrain ? terrain->get_flat(tilex, tiley)
					: ShapeID(); }
	Image_buffer8 *get_rendered_flats()
		{ return terrain ? terrain->get_rendered_flats() : 0; }
					// Get/create cache.
	Chunk_cache *need_cache()
		{ 
		return cache ? cache 
				: (cache = new Chunk_cache()); 
		}
	void setup_cache()
		{ 
		if (!cache || !cache->setup_done)
			need_cache()->setup(this);
		}
					// Set/unset blocked region.
	void set_blocked(int startx, int starty, int endx, int endy,
						int lift, int ztiles, bool set)
		{ need_cache()->set_blocked(startx, starty, endx, endy,
							lift, ztiles, set); }
					// Get highest lift blocked.
	int get_highest_blocked(int lift, int tx, int ty)
		{ return need_cache()->get_highest_blocked(lift, tx, ty); }
	int get_lowest_blocked(int lift, int tx, int ty)
		{ return need_cache()->get_lowest_blocked(lift, tx, ty); }
					// Is a spot occupied?
	int is_blocked(int height, int lift, int tx, int ty, int& new_lift,
					const int move_flags, int max_drop = 1)
		{ return cache->is_blocked(height, lift, tx, ty, new_lift,
						move_flags, max_drop); }
					// Check range.
	static int is_blocked(int height, int lift, int startx, int starty,
		int xtiles, int ytiles, int& new_lift, const int move_flags, 
							int max_drop = 1);
					// Check absolute tile.
	static int is_blocked(Tile_coord& tile, int height = 1,
		const int move_flags = MOVE_ALL_TERRAIN, int max_drop = 1);
					// Check for > 1x1 object.
	static int is_blocked(int xtiles, int ytiles, int ztiles,
			Tile_coord from, Tile_coord& to, const int move_flags,
							int max_drop = 1);
	enum Find_spot_where		// For find_spot() below.
		{
		anywhere = 0,
		inside,			// Must be inside.
		outside			// Must be outside,
		};
					// Find spot for an object.
	static Tile_coord find_spot(Tile_coord pos, int dist,
		int shapenum, int framenum, int max_drop = 0,int dir = -1,
				Find_spot_where where = anywhere);
					// For approaching 'pos' by an object:
	static Tile_coord find_spot(Tile_coord pos, int dist,
				Game_object *obj, int max_drop = 0,
					Find_spot_where where = anywhere);
					// Set area within egg's influence.
	void set_egged(Egg_object *egg, Rectangle& tiles, bool add)
		{ need_cache()->set_egged(egg, tiles, add); }
	void activate_eggs(Game_object *obj, int tx, int ty, int tz,
						int from_tx, int from_ty)
		{ need_cache()->activate_eggs(obj, 
					this, tx, ty, tz, from_tx, from_ty);}
	static int find_in_area(Game_object_vector& vec, Rectangle area,
					int shapenum, int framenum);
					// Use this when teleported in.
	static void try_all_eggs(Game_object *obj, int tx, int ty, int tz,
						int from_tx, int from_ty);
	void setup_dungeon_levels();	// Set up after IFIX objs. read.
	inline int has_dungeon()		// Any tiles within dungeon?
		{ return dungeon_levels != 0; }

					// NOTE:  The following should only be
					//   called if has_dungeon()==1.
	inline int is_dungeon(int tx, int ty)	// Is object within dungeon? (returns height)
		{
		int tnum = ty*c_tiles_per_chunk + tx;
		return tnum%2? dungeon_levels[tnum/2] >> 4: dungeon_levels[tnum/2] & 0xF;
		}
					// Is the dungeon an ICE dungeon.NOTE: This is a
					// Hack and splits the chunk into 4 parts. Only if
	inline bool is_ice_dungeon(int tx, int ty) // all 4 are ice, will we have an ice dungeon
		{
		return ice_dungeon == 0x0F;//0 != ((ice_dungeon >> ( (tx>>3) + 2*(ty>>3) ) )&1);
		}


	};

#endif