server-1.12/include/map.h

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 */