406 lines
19 KiB
C
406 lines
19 KiB
C
/*
|
|
* static char *rcsid_define_h =
|
|
* "$Id: map.h 11578 2009-02-23 22:02:27Z lalo $";
|
|
*/
|
|
|
|
/*
|
|
CrossFire, A Multiplayer game for X-windows
|
|
|
|
Copyright (C) 2002-2005 Mark Wedel & Crossfire Development Team
|
|
Copyright (C) 1992 Frank Tore Johansen
|
|
|
|
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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
The authors can be reached via e-mail at crossfire-devel@real-time.com
|
|
*/
|
|
|
|
/**
|
|
* @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 *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 */
|
|
/*@}*/
|
|
|
|
/** 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) ((m)->width*(m)->height)
|
|
|
|
/** 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().
|
|
* @todo remove map_block
|
|
*/
|
|
/*@{*/
|
|
#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_BLOCK 0x4 /**< Unused. */
|
|
#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 remove_ob() 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 lighe. 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 flags; /**< Flags about this space (see the P_ values above). */
|
|
sint8 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 that is on this space */
|
|
} 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 */
|
|
const char *name; /**< Shortend name of the region as maps refer to it */
|
|
const 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.
|
|
*/
|
|
const char *longname; /**< Official title of the region, this might be defined
|
|
* to be the same as name*/
|
|
const char *msg; /**< The description of the region */
|
|
uint32 counter; /**< A generic counter for holding temporary data. */
|
|
sint8 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. */
|
|
sint16 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, 0 if it is the default price. */
|
|
sint8 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 reset_time; /**< When this map should reset. */
|
|
uint32 reset_timeout; /**< How many seconds must elapse before this map
|
|
* should be reset. */
|
|
uint32 fixed_resettime:1; /**< If true, reset time is not affected by
|
|
* players entering/exiting map. */
|
|
uint32 unique:1; /**< If set, this is a per player unique map. */
|
|
uint32 is_template:1; /**< If set, this is a template map. */
|
|
uint32 nosmooth:1; /**< If set the content of this map has smoothlevel=0 forced. */
|
|
uint32 outdoor:1; /**< True if an outdoor map. */
|
|
sint32 timeout; /**< Swapout is set to this. */
|
|
sint32 swap_time; /**< When it reaches 0, the map will be swapped out. */
|
|
uint16 difficulty; /**< What level the player should be to play here. */
|
|
sint16 players; /**< How many players are on this level right now. Automatically updated by the object handling functions. */
|
|
uint32 in_memory; /**< Combination of @ref IN_MEMORY_xxx "IN_MEMORY_xxx" flags. */
|
|
uint8 compressed; /**< Compression method used. */
|
|
|
|
uint8 darkness; /**< Indicates level of darkness of map. */
|
|
uint16 width, height; /**< Width and height of map. */
|
|
uint16 enter_x; /**< Enter_x and enter_y are default entrance location. */
|
|
uint16 enter_y; /**< on the map if none are set in the exit. */
|
|
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 shopmin; /**< Minimum price a shop will trade for. */
|
|
uint64 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. */
|
|
struct timeval 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 negativbe. 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;
|
|
|
|
#endif /* MAP_H */
|