File: map.h

package info (click to toggle)
crossfire 1.75.0-9
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 24,168 kB
  • sloc: ansic: 83,169; sh: 4,659; perl: 1,736; lex: 1,443; makefile: 1,199; python: 43
file content (388 lines) | stat: -rw-r--r-- 18,707 bytes parent folder | download | duplicates (4)
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
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
/**
 * @file
 * This file contains basic map-related structures and macros.
 */

/*
 * The mapstruct is allocated each time a new map is opened.
 * It contains pointers (very indirectly) to all objects on the map.
 */

#ifndef MAP_H
#define MAP_H

/* We set this size - this is to make magic map work properly on
 * tiled maps.  There is no requirement that this matches the
 * tiled maps size - it just seemed like a reasonable value.
 * Magic map code now always starts out putting the player in the
 * center of the map - this makes the most sense when dealing
 * with tiled maps.
 * We also figure out the magicmap color to use as we process the
 * spaces - this is more efficient as we already have up to date
 * map pointers.
 */
#define MAGIC_MAP_SIZE 50
#define MAGIC_MAP_HALF MAGIC_MAP_SIZE/2

/* This correspondes to the map layers in the map2 protocol.
 * The MAP_LAYER_... correspond to what goes on what layer -
 * this removes the need for hardcoding, and also makes sure
 * we don't overstep the number of layers.
 */
#define MAP_LAYERS 10

extern const char *const map_layer_name[MAP_LAYERS];

/**
 * @defgroup MAP_LAYER_xxx Map layers
 */
/*@{*/
#define MAP_LAYER_FLOOR         0
#define MAP_LAYER_NO_PICK1      1   /**< Non pickable ground objects */
#define MAP_LAYER_NO_PICK2      2   /**< Non pickable ground objects */
#define MAP_LAYER_ITEM1         3   /**< Items that can be picked up */
#define MAP_LAYER_ITEM2         4
#define MAP_LAYER_ITEM3         5
#define MAP_LAYER_LIVING1       6   /**< Living creatures */
#define MAP_LAYER_LIVING2       7
#define MAP_LAYER_FLY1          8   /**< Flying objects - creatures, spells */
#define MAP_LAYER_FLY2          9   /**< Arrows, etc */
/*@}*/

/**
 * These are map subtypes.  With new character
 * creation code, additional types are needed.
 */

#define MAP_TYPE_LEGACY         1   /**< For old character creation method */
#define MAP_TYPE_DEFAULT        2   /**< If no map is specified, where character starts */
#define MAP_TYPE_CHOICE         3   /**< Choice of maps presented to player */

/** This is when the map will reset */
#define MAP_WHEN_RESET(m)       ((m)->reset_time)

#define MAP_RESET_TIMEOUT(m)    ((m)->reset_timeout)
#define MAP_DIFFICULTY(m)       ((m)->difficulty)
#define MAP_TIMEOUT(m)          ((m)->timeout)
#define MAP_SWAP_TIME(m)        ((m)->swap_time)
#define MAP_OUTDOORS(m)         ((m)->outdoor)

/**
 * Map darkness used to enforce the MAX_DARKNESS value.
 * but IMO, if it is beyond max value, that should be fixed
 * on the map or in the code.
 */
#define MAP_DARKNESS(m)         (m)->darkness

/** Map width. */
#define MAP_WIDTH(m)            (m)->width
/** Map height. */
#define MAP_HEIGHT(m)           (m)->height
/** Convenient function - total number of spaces is used in many places. */
#define MAP_SIZE(m)             map_size(m)

/** Default X coordinate for map enter. */
#define MAP_ENTER_X(m)          (m)->enter_x
/** Default Y coordinate for map enter. */
#define MAP_ENTER_Y(m)          (m)->enter_y

#define MAP_NOSMOOTH(m)         (m)->nosmooth

/**
 * @defgroup MAP_xxx Map loading flags
 * Options passed to ready_map_name() and load_original_map().
 */
/*@{*/
#define MAP_FLUSH           0x1     /**< Always load map from the map directory, and don't do unique items or the like. */
#define MAP_PLAYER_UNIQUE   0x2     /**< This map is player-specific. Don't do any more name translation on it. */
#define MAP_STYLE           0x8     /**< Active objects shouldn't be put on active list. */
#define MAP_OVERLAY         0x10    /**< Map to load is an overlay. Always put items above floor. */
/*@}*/

/**
 * @defgroup SAVE_FLAG_xxx Save object flags
 *
 * Flags for save_object() and save_objects().
 * Can be combined for various effects.
 *
 */
/*@{*/
#define SAVE_FLAG_SAVE_UNPAID   1   /**< If set, unpaid items will be saved. */
#define SAVE_FLAG_NO_REMOVE     2   /**< If set, objects are not removed while saving. */
/*@}*/

/**
 * @defgroup SAVE_MODE_xxx Save map flags
 *
 * How save_map() should save the map. Can't be combined.
 */
/*@{*/
#define SAVE_MODE_NORMAL    0   /**< No special handling. */
#define SAVE_MODE_INPLACE   1   /**< Map is saved from where it was loaded.*/
#define SAVE_MODE_OVERLAY   2   /**< Map is persisted as an overlay. */
/*@}*/

/**
 * @defgroup IN_MEMORY_xxx Values for mapdef->in_memory field.
 * @todo rename to IM_xxx ?
 */
/*@{*/
#define MAP_IN_MEMORY   1   /**< Map is fully loaded. */
#define MAP_SWAPPED     2   /**< Map spaces have been saved to disk. */
#define MAP_LOADING     3   /**< This map is being loaded. */
#define MAP_SAVING      4   /**< Map being saved. Will stop object_remove() from some processing. */
/*@}*/

/**
 * @defgroup SAVE_ERROR_xxx Save error values
 * Those values are returned by save_map(), save_object() and save_objects().
 *
 * Values under -10 are returned by swap_map() only.
 */
/*@{*/
#define SAVE_ERROR_OK                0   /**< No error. */
#define SAVE_ERROR_RCREATION        -1  /**< Couldn't create the regular save file. */
#define SAVE_ERROR_UCREATION        -2  /**< Couldn't create the file for unique objects. */
#define SAVE_ERROR_WRITE            -3  /**< Write error. */
#define SAVE_ERROR_NO_PATH          -4  /**< Map had no path set. */
#define SAVE_ERROR_URENAME          -5  /**< Couldn't rename unique temporary file. */
#define SAVE_ERROR_CLOSE            -6  /**< Close error for regular file. */
#define SAVE_ERROR_RRENAME          -7  /**< Couldn't rename regular temporary file. */
#define SAVE_ERROR_NOT_IN_MEMORY    -10 /**< Map to swap isn't in memory. */
#define SAVE_ERROR_PLAYER           -11 /**< Player on map to save. */
/*@}*/

/* GET_MAP_FLAGS really shouldn't be used very often - get_map_flags should
 * really be used, as it is multi tile aware.  However, there are some cases
 * where it is known the map is not tiled or the values are known
 * consistent (eg, op->map, op->x, op->y)
 */
/** Gets map flags. Not multitile aware. */
#define GET_MAP_FLAGS(M, X, Y)  ((M)->spaces[(X)+(M)->width*(Y)].flags)
/** Sets map flags. Not multitile aware. */
#define SET_MAP_FLAGS(M, X, Y, C) ((M)->spaces[(X)+(M)->width*(Y)].flags = C)
/** Gets map light. Not multitile aware. */
#define GET_MAP_LIGHT(M, X, Y)  ((M)->spaces[(X)+(M)->width*(Y)].light)
/** Sets map light. Not multitile aware. */
#define SET_MAP_LIGHT(M, X, Y, L) ((M)->spaces[(X)+(M)->width*(Y)].light = L)
#define GET_MAP_PLAYER(M, X, Y) ((M)->spaces[(X)+(M)->width*(Y)].pl)
#define SET_MAP_PLAYER(M, X, Y, C) ((M)->spaces[(X)+(M)->width*(Y)].pl = C)

/** Gets the bottom object on a map. Not multitile aware. */
#define GET_MAP_OB(M, X, Y)     ((M)->spaces[(X)+(M)->width*(Y)].bottom)
/** Gets the top object on a map. Not multitile aware. */
#define GET_MAP_TOP(M, X, Y)    ((M)->spaces[(X)+(M)->width*(Y)].top)

/** Sets the bottom object on a map. Not multitile aware. */
#define SET_MAP_OB(M, X, Y, tmp) ((M)->spaces[(X)+(M)->width*(Y)].bottom = (tmp))
/** Sets the top object on a map. Not multitile aware. */
#define SET_MAP_TOP(M, X, Y, tmp) ((M)->spaces[(X)+(M)->width*(Y)].top = (tmp))

/** Sets the layer face of specified square. Not multitile aware. */
#define SET_MAP_FACE_OBJ(M, X, Y, C, L) ((M)->spaces[(X)+(M)->width*(Y)].faces_obj[L] = C)
/** Gets the layer face of specified square. Not multitile aware. */
#define GET_MAP_FACE_OBJ(M, X, Y, L) ((M)->spaces[(X)+(M)->width*(Y)].faces_obj[L])
/**
 * Returns the layers array so update_position can just copy
 * the entire array over.
 */
#define GET_MAP_FACE_OBJS(M, X, Y) ((M)->spaces[(X)+(M)->width*(Y)].faces_obj)

/** Gets the blocking state of a square. Not multitile aware. */
#define GET_MAP_MOVE_BLOCK(M, X, Y) ((M)->spaces[(X)+(M)->width*(Y)].move_block)
/** Sets the blocking state of a square. Not multitile aware. */
#define SET_MAP_MOVE_BLOCK(M, X, Y, C) ((M)->spaces[(X)+(M)->width*(Y)].move_block = C)

/** Gets the slowing state of a square. Not multitile aware. */
#define GET_MAP_MOVE_SLOW(M, X, Y)  ((M)->spaces[(X)+(M)->width*(Y)].move_slow)
/** Sets the slowing state of a square. Not multitile aware. */
#define SET_MAP_MOVE_SLOW(M, X, Y, C) ((M)->spaces[(X)+(M)->width*(Y)].move_slow = C)

/** Gets the move_on state of a square. Not multitile aware. */
#define GET_MAP_MOVE_ON(M, X, Y)    ((M)->spaces[(X)+(M)->width*(Y)].move_on)
/** Sets the move_on state of a square. Not multitile aware. */
#define SET_MAP_MOVE_ON(M, X, Y, C) ((M)->spaces[(X)+(M)->width*(Y)].move_on = C)

/** Gets the move_off state of a square. Not multitile aware. */
#define GET_MAP_MOVE_OFF(M, X, Y)    ((M)->spaces[(X)+(M)->width*(Y)].move_off)
/** Sets the move_off state of a square. Not multitile aware. */
#define SET_MAP_MOVE_OFF(M, X, Y, C) ((M)->spaces[(X)+(M)->width*(Y)].move_off = C)

/**
 * Checks if a square is out of the map.
 * You should really know what you are doing before using this - you
 * should almost always be using out_of_map() instead, which takes into account
 * map tiling.
 */
#define OUT_OF_REAL_MAP(M, X, Y) ((X) < 0 || (Y) < 0 || (X) >= (M)->width || (Y) >= (M)->height)

/**
 * @defgroup P_xxx Square flags.
 *
 * These are used in the MapLook flags element.  They are not used in
 * in the object flags structure.
 */
/*@{*/
#define P_BLOCKSVIEW    0x01    /**< This spot blocks the player's view. */
#define P_NO_MAGIC      0x02    /**< Spells (some) can't pass this object */

/* AB_NO_PASS is used for arch_blocked() return value.  It needs
 * to be here to make sure the bits don't match with anything.
 * Changed name to have AB_ prefix just to make sure no one
 * is using the P_NO_PASS.  AB_.. should only be used for
 * arch_blocked and functions that examine the return value.
 */
#define AB_NO_PASS      0x04
#define P_PLAYER        0x08    /**< There is a player on this space */
#define P_IS_ALIVE      0x10    /**< Something alive is on this space. */
#define P_NO_CLERIC     0x20    /**< No clerical spells cast here. */
#define P_NEED_UPDATE   0x40    /**< This space is out of date. */
#define P_NO_ERROR      0x80    /**< Purely temporary - if set, update_position
                                 * does not complain if the flags are different.
                                 */
/* The following two values are not stored in the MapLook flags, but instead
 * used in the get_map_flags value - that function is used to return
 * the flag value, as well as other conditions - using a more general
 * function that does more of the work can hopefully be used to replace
 * lots of duplicate checks currently in the code.
 */
#define P_OUT_OF_MAP    0x100   /**< This space is outside the map. */
#define P_NEW_MAP       0x200   /**< Coordinates passed result in a new tiled map.  */
/*@}*/

/**
 * This structure contains all information related to one map square.
 */
typedef struct MapSpace {
    object      *bottom;        /**< Lowest object on this space. */
    object      *top;           /**< Highest object on this space. */
    object      *faces_obj[MAP_LAYERS]; /**< Face objects for the layers. */
    uint8_t       flags;          /**< Flags about this space (see the P_ values above). */
    int8_t       light;          /**< How much light this space provides. */
    MoveType    move_block;     /**< What movement types this space blocks. */
    MoveType    move_slow;      /**< What movement types this space slows. */
    MoveType    move_on;        /**< What movement types are activated. */
    MoveType    move_off;       /**< What movement types are activated. */
    object      *pl;            /**< Player who is on this space, may be NULL. */
} MapSpace;

/**
 * This is a game region.
 * Each map is in a given region of the game world and links to a region definiton, so
 * they have to appear here in the headers, before the mapdef
 */
typedef struct regiondef {
    struct regiondef *next;      /**< Pointer to next region, NULL for the last one */
    char  *name;                 /**< Shortend name of the region as maps refer to it */
    char  *parent_name;          /**<
                                  * So that parent and child regions can be defined in
                                  * any order, we keep hold of the parent_name during
                                  * initialisation, and the children get assigned to their
                                  * parents later. (before runtime on the server though)
                                  * nothing outside the init code should ever use this value.
                                  */
    struct regiondef *parent;   /**<
                                  * Pointer to the region that is a parent of the current
                                  * region, if a value isn't defined in the current region
                                  * we traverse this series of pointers until it is.
                                  */
    char  *longname;             /**< Official title of the region, this might be defined
                                  * to be the same as name*/
    char  *msg;                  /**< The description of the region */
    uint32_t      counter;         /**< A generic counter for holding temporary data. */
    int8_t       fallback;        /**< Whether, in the event of a region not existing,
                                  * this should be the one we fall back on as the default. */
    char        *jailmap;        /**< Where a player that is arrested in this region should be imprisoned. */
    int16_t      jailx, jaily;    /**< The coodinates in jailmap to which the player should be sent. */
} region;

/**
 * Shop-related information for a map. This is one item type the shop will deal in, and
 * the price-chance.
 */
typedef struct shopitem {
    const char *name;     /**< Name of the item in question, null if it is the default item. */
    const char *name_pl;  /**< Plural name. */
    int typenum;    /**< Itemtype number we need to match, -1 if it is the default price. */
    int8_t strength; /**< The degree of specialisation the shop has in this item,
                     * as a percentage from -100 to 100. */
    int index;      /**< Being the size of the shopitems array.*/
} shopitems;

/**
 * This is a game-map.
 *
 * In general, code should always use the macros
 * above (or functions in map.c) to access many of the
 * values in the map structure.  Failure to do this will
 * almost certainly break various features.  You may think
 * it is safe to look at width and height values directly
 * (or even through the macros), but doing so will completely
 * break map tiling.
 */
typedef struct mapdef {
    struct mapdef *next;        /**< Next map, linked list. */
    char    *tmpname;           /**< Name of temporary file. */
    char    *name;              /**< Name of map as given by its creator. */
    struct regiondef *region;   /**< What jurisdiction in the game world this map is ruled by
                                 * points to the struct containing all the properties of
                                 * the region. */
    uint32_t  reset_time;         /**< When this map should reset. */
    uint32_t  reset_timeout;      /**< How many seconds must elapse before this map
                                 * should be reset. */
    uint32_t  fixed_resettime:1;  /**< If true, reset time is not affected by
                                 * players entering/exiting map. */
    uint32_t  unique:1;           /**< If set, this is a per player unique map. */
    uint32_t  is_template:1;         /**< If set, this is a template map. */
    uint32_t  nosmooth:1;         /**< If set the content of this map has smoothlevel=0 forced. */
    uint32_t  outdoor:1;          /**< True if an outdoor map. */
    int32_t  timeout;            /**< Swapout is set to this. */
    int32_t  swap_time;          /**< When it reaches 0, the map will be swapped out. */
    uint16_t  difficulty;         /**< What level the player should be to play here. */
    int16_t  players;            /**< How many players are on this level right now. Automatically updated by the object handling functions. */
    uint32_t  in_memory;          /**< Combination of @ref IN_MEMORY_xxx "IN_MEMORY_xxx" flags. */
    uint8_t   darkness;           /**< Indicates level of darkness of map. */
    uint16_t  width, height;      /**< Width and height of map. */
    int16_t  enter_x, enter_y;   /**< Enter_x and enter_y are default entrance
                                 *   coordinates to use for a map such that
                                 *   when an exit specifies hp,sp of -1,-1 for
                                 *   an exit pointing to the map, when the
                                 *   exit is applied, the character is placed
                                 *   at enter_x,enter_y when they arrive.    */
    oblinkpt *buttons;          /**< Linked list of linked lists of buttons. */
    MapSpace *spaces;           /**< Array of spaces on this map. */
    struct shopitem *shopitems;     /**< List of item-types the map's shop will trade in. */
    char    *shoprace;          /**< The preffered race of the local shopkeeper. */
    double  shopgreed;          /**< How much our shopkeeper overcharges. */
    uint64_t  shopmin;            /**< Minimum price a shop will trade for. */
    uint64_t  shopmax;            /**< MMaximum price a shop will offer. */
    char    *msg;               /**< Message map creator may have left. */
    char    *maplore;           /**< Map lore information. */
    char    *tile_path[4];      /**< Path to adjoining maps. */
    struct mapdef *tile_map[4]; /**< Adjoining maps. */
    char    path[HUGE_BUF];     /**< Filename of the map. */
    long last_reset_time;       /**< A timestamp of the last original map loading. */
    char    *background_music;  /**< Background music to use for this map. */
} mapstruct;

/**
 * This is used by get_rangevector to determine where the other
 * creature is.  get_rangevector takes into account map tiling,
 * so you just can not look the the map coordinates and get the
 * righte value.  distance_x/y are distance away, which
 * can be negative.  direction is the crossfire direction scheme
 * that the creature should head.  part is the part of the
 * monster that is closest.
 * Note: distance should be always >=0. I changed it to UINT. MT
 */
typedef struct rv_vector {
    unsigned int distance;  /**< Distance, in squares. */
    int     distance_x;     /**< X delta. */
    int     distance_y;     /**< Y delta. */
    int     direction;      /**< General direction to the targer. */
    object  *part;          /**< Part we found. */
} rv_vector;

uint32_t map_size(mapstruct *m);

#endif /* MAP_H */