/* * $Id: mech.maps.c,v 1.7 2005/08/03 21:40:54 av1-op Exp $ * * Author: Markus Stenberg <fingon@iki.fi> * * Copyright (c) 1996 Markus Stenberg * Copyright (c) 1998-2002 Thomas Wouters * Copyright (c) 2000-2002 Cord Awtry * Copyright (c) 1999-2005 Kevin Stevens * All rights reserved * * Last modified: Fri Sep 18 13:09:09 1998 fingon * */ #include "config.h" #include <stdio.h> #include <stdlib.h> #include <math.h> #include <sys/file.h> #include "mech.h" #include "create.h" #include "mech.events.h" #include "map.los.h" #include "p.mech.utils.h" #include "p.mech.los.h" #include "p.eject.h" #include "p.mech.restrict.h" #include "p.mech.maps.h" #include "p.mech.notify.h" #include "p.ds.bay.h" #include "p.bsuit.h" #include "p.mech.utils.h" #include "autopilot.h" void mech_findcenter(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; float fx, fy; int x, y; cch(MECH_USUAL); x = MechX(mech); y = MechY(mech); MapCoordToRealCoord(x, y, &fx, &fy); notify(player, tprintf("Current hex: (%d,%d,%d)\tRange to center: %.2f\t" "Bearing to center: %d", x, y, MechZ(mech), FindHexRange(fx, fy, MechFX(mech), MechFY(mech)), FindBearing(MechFX(mech), MechFY(mech), fx, fy))); } static int parse_tacargs(dbref player, MECH *mech, char ** args, int argc, int maxrange, short * x, short * y) { int bearing; float range, fx, fy; MECH * tempMech; MAP * map; switch (argc) { case 2: bearing = atoi(args[0]); range = atof(args[1]); DOCHECK0(!MechIsObservator(mech) && abs((int) range) > maxrange, "Those coordinates are out of sensor range!"); FindXY(MechFX(mech), MechFY(mech), bearing, range, &fx, &fy); RealCoordToMapCoord(x, y, fx, fy); return 1; case 1: map = getMap(mech->mapindex); tempMech = getMech(FindMechOnMap(map, args[0])); DOCHECK0(!tempMech, "No such target."); range = FlMechRange(mech_map, mech, tempMech); DOCHECK0(!InLineOfSight(mech, tempMech, MechX(tempMech), MechY(tempMech), range), "No such target."); DOCHECK0(abs((int) range) > maxrange, "Target is out of scanner range."); *x = MechX(tempMech); *y = MechY(tempMech); return 1; case 0: *x = MechX(mech); *y = MechY(mech); return 1; default: notify(player, "Invalid number of parameters!"); return 0; } } const char *GetTerrainName_base(int t) { switch (t) { case GRASSLAND: case '_': return "Grassland"; case HEAVY_FOREST: return "Heavy Forest"; case LIGHT_FOREST: return "Light Forest"; case ICE: return "Ice"; case BRIDGE: return "Bridge"; case HIGHWATER: case WATER: return "Water"; case ROUGH: return "Rough"; case MOUNTAINS: return "Mountains"; case ROAD: return "Road"; case BUILDING: return "Building"; case FIRE: return "Fire"; case SMOKE: return "Smoke"; case WALL: return "Wall"; } return "Unknown"; } const char *GetTerrainName(MAP * map, int x, int y) { return GetTerrainName_base(GetTerrain(map, x, y)); } /* Player-customizable colors */ enum { SWATER_IDX, DWATER_IDX, BUILDING_IDX, ROAD_IDX, ROUGH_IDX, MOUNTAIN_IDX, FIRE_IDX, ICE_IDX, WALL_IDX, SNOW_IDX, SMOKE_IDX, LWOOD_IDX, HWOOD_IDX, UNKNOWN_IDX, CLIFF_IDX, SELF_IDX, FRIEND_IDX, ENEMY_IDX, DS_IDX, GOODLZ_IDX, BADLZ_IDX, NUM_COLOR_IDX }; /* Default colour string is "BbWnYyRWWWXGgbRHYRn" */ /* internal rep has H instead of h and \0 instead of n */ #define DEFAULT_COLOR_STRING "BbWXYyRWWWXGgbRhYRnGR" #define DEFAULT_COLOR_SCHEME "BbWXYyRWWWXGgbRHYR\0GR" static char custom_color_str[NUM_COLOR_IDX + 1] = DEFAULT_COLOR_SCHEME; static void set_colorscheme(dbref player) { char *str = silly_atr_get(player, A_MAPCOLOR); int i; if (*str && strlen(str) <= NUM_COLOR_IDX) { strncpy(custom_color_str, DEFAULT_COLOR_STRING, NUM_COLOR_IDX); strncpy(custom_color_str, str, strlen(str)); for (i = 0; i < NUM_COLOR_IDX; i++) { switch (custom_color_str[i]) { case 'f': case 'F': case 'I': case 'i': case 'H': case 'x': case 'X': case 'r': case 'R': case 'g': case 'G': case 'y': case 'Y': case 'b': case 'B': case 'm': case 'M': case 'c': case 'C': case 'w': case 'W': break; case 'h': custom_color_str[i] = 'H'; break; case 'n': custom_color_str[i] = '\0'; break; default: notify(player, tprintf("Invalid character '%c' in MAPCOLOR " "attribute!", custom_color_str[i])); notify(player, "Using default: " DEFAULT_COLOR_STRING); memcpy(custom_color_str, DEFAULT_COLOR_SCHEME, NUM_COLOR_IDX); return; } } return; } else if (*str) { notify(player, "Invalid MAPCOLOR attribute!"); notify(player, "Using default: " DEFAULT_COLOR_STRING); } memcpy(custom_color_str, DEFAULT_COLOR_SCHEME, NUM_COLOR_IDX); } void mech_navigate(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; char mybuff[NAVIGATE_LINES][MBUF_SIZE]; MAP *mech_map; char **maptext, *args[3]; int i, dolos, argc; short x, y; cch(MECH_USUAL); mech_map = getMap(mech->mapindex); dolos = MapIsDark(mech_map) || (MechType(mech) == CLASS_MW && mudconf.btech_mw_losmap); DOCHECK(mech_map->map_width <= 0 || mech_map->map_height <= 0, "Nothing to see on this map, move along."); argc = mech_parseattributes(buffer, args, 3); if (!parse_tacargs(player, mech, args, argc, MechTacRange(mech), &x, &y)) return; set_colorscheme(player); maptext = MakeMapText(player, mech, mech_map, x, y, 5, 5, 4, dolos); sprintf(mybuff[0], " 0 %.150s", maptext[0]); sprintf(mybuff[1], " ___________ %.150s", maptext[1]); sprintf(mybuff[2], " / \\ Location:%4d,%4d, %3d %.150s", MechX(mech), MechY(mech), MechZ(mech), maptext[2]); sprintf(mybuff[3], " 300 / \\ 60 Terrain: %14s %.150s", GetTerrainName(mech_map, MechX(mech), MechY(mech)), maptext[3]); sprintf(mybuff[4], " / \\ %.150s", maptext[4]); sprintf(mybuff[5], " / \\ %.150s", maptext[5]); sprintf(mybuff[6], "270 ( ) 90 Speed: %6.1f %.150s", MechSpeed(mech), maptext[6]); sprintf(mybuff[7], " \\ / Vertical Speed: %6.1f %.150s", MechVerticalSpeed(mech), maptext[7]); sprintf(mybuff[8], " \\ / Heading: %4d %.150s", MechFacing(mech), maptext[8]); sprintf(mybuff[9], " 240 \\ / 120 %.150s", maptext[9]); sprintf(mybuff[10], " \\___________/ %.150s", maptext[10]); sprintf(mybuff[11], " "); sprintf(mybuff[12], " 180"); navigate_sketch_mechs(mech, mech_map, x, y, mybuff); for (i = 0; i < NAVIGATE_LINES; i++) notify(player, mybuff[i]); } /* INDENT OFF */ /* 0 ___________ /``\][/""\][/""\ / \ HEX Location: 254, 122 \`1/``\""/``\""/ 300 / \ 60 Terrain: Light Forest /``\``/""\`3/""\ / \ Elevation: 0 \`2/``\"1/``\""/ / \ /""\``|**\`3/""\ 270 ( ) 90 Speed: 0.0 \"4/``\"4/``\""/ \ / Vertical Speed: 0.0 /""\`3/""\`3/""\ \ / Heading: 0 \"4/``\"4/``\""/ 240 \ / 120 /""\`3/""\`3/""\ \____*______/ \"4/][\"4/][\"4/ 180 */ /* INDENT ON */ char GetLRSMechChar(MECH * mech, MECH * other) { char c = 'u'; if (mech == other) return '*'; if (IsDS(other)) c = 'd'; switch (MechMove(other)) { case MOVE_FLY: c = 'a'; case MOVE_BIPED: c = 'b'; break; case MOVE_QUAD: c = 'q'; break; case MOVE_TRACK: c = 't'; break; case MOVE_WHEEL: c = 'w'; break; case MOVE_HOVER: c = 'h'; break; case MOVE_VTOL: c = 'v'; break; case MOVE_HULL: c = 'n'; break; case MOVE_SUB: c = 's'; break; case MOVE_FOIL: c = 'f'; break; } if (!MechSeemsFriend(mech, other)) c = toupper(c); return c; } static inline char TerrainColorChar(char terrain, int elev) { switch (terrain) { case HIGHWATER: return custom_color_str[DWATER_IDX]; case WATER: if (elev < 2 || elev == '0' || elev == '1' || elev == '~') return custom_color_str[SWATER_IDX]; return custom_color_str[DWATER_IDX]; case BUILDING: return custom_color_str[BUILDING_IDX]; case ROAD: return custom_color_str[ROAD_IDX]; case ROUGH: return custom_color_str[ROUGH_IDX]; case MOUNTAINS: return custom_color_str[MOUNTAIN_IDX]; case FIRE: return custom_color_str[FIRE_IDX]; case ICE: return custom_color_str[ICE_IDX]; case WALL: return custom_color_str[WALL_IDX]; case SNOW: return custom_color_str[SNOW_IDX]; case SMOKE: return custom_color_str[SMOKE_IDX]; case LIGHT_FOREST: return custom_color_str[LWOOD_IDX]; case HEAVY_FOREST: return custom_color_str[HWOOD_IDX]; case UNKNOWN_TERRAIN: return custom_color_str[UNKNOWN_IDX]; } return '\0'; } static char *add_color(char newc, char * prevc, char c) { static char buf[10]; /* won't be filled with more than 7 characters */ buf[0] = '\0'; if (newc == *prevc) { buf[0] = c; buf[1] = '\0'; return buf; } if (!newc || ((isupper(*prevc)) && !isupper(newc)) || (newc == 'H' && *prevc)) strcpy(buf, "%cn"); else if (isupper(newc) && !isupper(*prevc)) strcpy(buf, "%ch"); if (!newc) sprintf(buf + strlen(buf), "%c", c); else sprintf(buf + strlen(buf), "%%c%c%c", tolower(newc), c); *prevc = newc; return buf; } static char *GetLRSMech(MECH * mech, MECH * other, int docolor, char *prevc) { static char buf[2]; /* Won't be filled with more than 1 character */ char c = GetLRSMechChar(mech, other); char newc; if (!docolor) { sprintf(buf, "%c", c); return buf; } if (mech == other) newc = custom_color_str[SELF_IDX]; else if (!MechSeemsFriend(mech, other)) newc = custom_color_str[ENEMY_IDX]; else newc = custom_color_str[FRIEND_IDX]; return add_color(newc, prevc, c); } static char *LRSTerrain(MAP * map, int x, int y, int docolor, char *prevc) { static char buf[2]; /* Won't be filled with more than 1 character */ char c = GetTerrain(map, x, y); char newc; if (!c || !docolor || c == ' ') { buf[0] = c; buf[1] = '\0'; return buf; } else newc = TerrainColorChar(c, GetElev(map, x, y)); return add_color(newc, prevc, c); } static char *LRSElevation(MAP * map, int x, int y, int docolor, char *prevc) { static char buf[2]; /* Won't be filled with more than 1 character */ int e = GetElev(map, x, y); char c = (e || docolor) ? '0' + e : ' '; char newc; if (!docolor) { buf[0] = c; buf[1] = '\0'; return buf; } else newc = TerrainColorChar(GetTerrain(map, x, y), e); return add_color(newc, prevc, c); } #define LRS_TERRAINMODE 1 #define LRS_ELEVMODE 2 #define LRS_MECHMODE 4 #define LRS_LOSMODE 8 #define LRS_COLORMODE 16 #define LRS_ELEVCOLORMODE 32 static char *get_lrshexstr(MECH * mech, MAP *map, int x, int y, char * prevc, int mode, MECH ** mechs, int lm, hexlosmap_info * losmap) { int losflag = MAPLOSHEX_SEE | MAPLOSHEX_SEEN; if (mode & LRS_MECHMODE) { while (mechs[lm] && MechY(mechs[lm]) < y) lm++; while (mechs[lm] && MechY(mechs[lm]) == y && MechX(mechs[lm]) < x) lm++; if (mechs[lm] && MechY(mechs[lm]) == y && MechX(mechs[lm]) == x) return GetLRSMech(mech, mechs[lm], mode & LRS_COLORMODE, prevc); } if (losmap) losflag = LOSMap_GetFlag(losmap, x, y); /* If the losmap doesn't contain this hex, we return X in bold red * in both terrain and elevation mode. */ if (!(losflag & MAPLOSHEX_SEEN)) return add_color('R', prevc, 'X'); if (((mode & LRS_TERRAINMODE) && !(losflag & MAPLOSHEX_SEETERRAIN)) || ((mode & LRS_ELEVMODE) && !(losflag & MAPLOSHEX_SEEELEV))) return add_color(TerrainColorChar(UNKNOWN_TERRAIN, 0), prevc, '?'); if (mode & LRS_ELEVMODE) return LRSElevation(map, x, y, mode & LRS_ELEVCOLORMODE, prevc); if (mode & LRS_TERRAINMODE) return LRSTerrain(map, x, y, mode & LRS_COLORMODE, prevc); SendError(tprintf("Unknown LRS mode, mech #%d mode 0x%x.", mech->mynum, mode)); return add_color('R', prevc, 'Y'); } static void show_lrs_map(dbref player, MECH * mech, MAP * map, int x, int y, int displayHeight, int mode) { int loop, b_width, e_width, b_height, e_height, i; MECH *oMech; /* topbuff and botbuff must be capable of holding enough * characters to colorize all hexes in the most inefficient * way. This means 15 characters per 2 hexes, or 8 per * hex. topbuff and botbuff both hold half the hexes on the row, * so that ends up 4 * LRS_DISPLAY_WIDTH (plus some padding thrown * in for good measure.) * * midbuff is only used for the lables, and only needs a few * characters more than the display width. */ char topbuff[4 * LRS_DISPLAY_WIDTH + 30] = " "; char botbuff[4 * LRS_DISPLAY_WIDTH + 30] = " "; char midbuff[8 + LRS_DISPLAY_WIDTH] = " "; char trash1[5]; /* temp var to hold the max-three-digit number of map Y */ short oddcol = 0; MECH *mechs[MAX_MECHS_PER_MAP]; int last_mech = 0; char prevct = 0, prevcb = 0; hexlosmap_info * losmap = NULL; /* x and y hold the viewing center of the map */ b_width = x - LRS_DISPLAY_WIDTH / 2; b_width = MAX(b_width, 0); e_width = b_width + LRS_DISPLAY_WIDTH; if (e_width >= map->map_width) { e_width = map->map_width - 1; b_width = e_width - LRS_DISPLAY_WIDTH; b_width = MAX(b_width, 0); } if (b_width % 2) oddcol = 1; b_height = y - displayHeight / 2; b_height = MAX(b_height, 0); e_height = b_height + displayHeight; if (e_height > map->map_height) { e_height = map->map_height; b_height = e_height - displayHeight; b_height = MAX(b_height, 0); } /* Display the top labels */ for (i = b_width; i <= e_width; i++) { sprintf(trash1, "%3d", i); sprintf(topbuff + strlen(topbuff), "%c", trash1[0]); sprintf(midbuff + strlen(midbuff), "%c", trash1[1]); sprintf(botbuff + strlen(botbuff), "%c", trash1[2]); } notify(player, topbuff); notify(player, midbuff); notify(player, botbuff); if (mode & LRS_MECHMODE) { for (i = 0; i < map->first_free; i++) { if ((oMech = getMech(map->mechsOnMap[i]))) { if ((mech == oMech) || (MechY(oMech) >= b_height && MechY(oMech) <= e_height && MechX(oMech) >= b_width && MechX(oMech) <= e_width && InLineOfSight(mech, oMech, MechX(oMech), MechY(oMech), FlMechRange(map, mech, oMech)))) mechs[last_mech++] = oMech; } } for (i = 0; i < (last_mech - 1); i++) /* Bubble-sort the list * to y/x order */ for (loop = (i + 1); loop < last_mech; loop++) { if (MechY(mechs[i]) > MechY(mechs[loop])) { oMech = mechs[i]; mechs[i] = mechs[loop]; mechs[loop] = oMech; } else if (MechY(mechs[i]) == MechY(mechs[loop]) && MechX(mechs[i]) > MechX(mechs[loop])) { oMech = mechs[i]; mechs[i] = mechs[loop]; mechs[loop] = oMech; } } mechs[last_mech] = NULL; last_mech = 0; } if (mode & LRS_LOSMODE) losmap = CalculateLOSMap(map, mech, b_width, b_height, e_width - b_width, e_height - b_height); for (loop = b_height; loop < e_height; loop++) { sprintf(topbuff, "%3d ", loop); strcpy(botbuff, " "); if (mode & LRS_MECHMODE) while (mechs[last_mech] && MechY(mechs[last_mech]) < loop) last_mech++; for (i = b_width; i < e_width; i += 2) { sprintf(topbuff + strlen(topbuff), oddcol ? "%s " : " %s", get_lrshexstr(mech, map, i + !oddcol, loop, &prevct, mode, mechs, last_mech, losmap)); sprintf(botbuff + strlen(botbuff), oddcol ? " %s" : "%s ", get_lrshexstr(mech, map, i + oddcol, loop, &prevcb, mode, mechs, last_mech, losmap)); } if (i == e_width && !oddcol) { sprintf(botbuff + strlen(botbuff), "%s", get_lrshexstr(mech, map, i, loop, &prevcb, mode, mechs, last_mech, losmap)); } else if (i == e_width) { sprintf(topbuff + strlen(topbuff), "%s", get_lrshexstr(mech, map, i, loop, &prevct, mode, mechs, last_mech, losmap)); strcat(botbuff, " "); } if (mode & (LRS_COLORMODE|LRS_ELEVCOLORMODE)) { if (prevct) { strcat(topbuff, "%cn"); prevct = 0; } if (prevcb) { strcat(botbuff, "%cn"); prevcb = 0; } } sprintf(botbuff + strlen(botbuff), " %-3d", loop); notify(player, topbuff); notify(player, botbuff); } } void mech_lrsmap(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; MAP *map; int argc, mode = 0; short x, y; char *args[5], *str; int displayHeight = LRS_DISPLAY_HEIGHT; cch(MECH_USUAL); if (Ansimap(player)) mode |= LRS_COLORMODE; map = getMap(mech->mapindex); argc = mech_parseattributes(buffer, args, 4); DOCHECK(!MechLRSRange(mech), "Your system seems to be inoperational."); if (!parse_tacargs(player, mech, &args[1], argc - 1, MechLRSRange(mech), &x, &y)) return; switch(args[0][0]) { case 'M': case 'm': mode |= LRS_MECHMODE | LRS_TERRAINMODE; break; case 'E': case 'e': mode |= LRS_ELEVMODE; break; case 'C': case 'c': mode |= LRS_ELEVMODE | LRS_ELEVCOLORMODE; break; case 'T': case 't': mode |= LRS_TERRAINMODE; break; case 'L': case 'l': mode |= LRS_LOSMODE | LRS_TERRAINMODE; break; case 'H': case 'h': mode |= LRS_LOSMODE | LRS_ELEVMODE; break; case 'S': case 's': mode |= LRS_LOSMODE | LRS_MECHMODE | LRS_TERRAINMODE; break; default: notify(player, tprintf("Unknown LRS sensor type '%s'!", args[0])); return; } if (MapIsDark(map) || (MechType(mech) == CLASS_MW && mudconf.btech_mw_losmap)) mode |= LRS_LOSMODE; str = silly_atr_get(player, A_LRSHEIGHT); if (*str) { displayHeight = atoi(str); if (displayHeight < 10 || displayHeight > 40) { notify(player, "Illegal LRSHeight attribute. Must be between 10 and 40"); displayHeight = LRS_DISPLAY_HEIGHT; } } displayHeight = MIN(displayHeight, 2 * MechLRSRange(mech)); displayHeight = MIN(displayHeight, map->map_height); if (!(displayHeight % 2)) displayHeight++; set_colorscheme(player); show_lrs_map(player, mech, map, x, y, displayHeight, mode); } static inline int is_oddcol(int col) { /* * The only real trick here is to handle negative * numbers correctly. */ return (unsigned) col & 1; } static inline int tac_dispcols(int hexcols) { return hexcols * 3 + 1; } static inline int tac_hex_offset(int x, int y, int dispcols, int oddcol1) { int oddcolx = is_oddcol(x + oddcol1); return (y * 2 + 1 - oddcolx) * dispcols + x * 3 + 1; } static inline void sketch_tac_row(char *pos, int left_offset, char const *src, int len) { memset(pos, ' ', left_offset); memcpy(pos + left_offset, src, len); pos[left_offset + len] = '\0'; } static void sketch_tac_map(char *buf, MAP * map, MECH * mech, int sx, int sy, int wx, int wy, int dispcols, int top_offset, int left_offset, int docolour, int dohexlos) { #if 0 static char const hexrow[2][76] = { "\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/", "/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\" }; #else static char const hexrow[2][310] = { "\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][" "\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][" "\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][" "\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][" "\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/", "/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][" "/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][" "/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][" "/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][" "/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\][/][\\" }; #endif int x, y; int oddcol1 = is_oddcol(sx); /* One iff first hex col is odd */ char *pos; int mapcols = tac_dispcols(wx); hexlosmap_info * losmap = NULL; /* * First create a blank hex map. */ pos = buf; for (y = 0; y < top_offset; y++) { memset(pos, ' ', dispcols - 1); pos[dispcols - 1] = '\0'; pos += dispcols; } for (y = 0; y < wy; y++) { sketch_tac_row(pos, left_offset, hexrow[oddcol1], mapcols); pos += dispcols; sketch_tac_row(pos, left_offset, hexrow[!oddcol1], mapcols); pos += dispcols; } sketch_tac_row(pos, left_offset, hexrow[oddcol1], mapcols); /* * Now draw the terrain and elevation. */ pos = buf + top_offset * dispcols + left_offset; wx = MIN(wx, map->map_width - sx); wy = MIN(wy, map->map_height - sy); if (dohexlos) losmap = CalculateLOSMap(map, mech, MAX(0, sx), MAX(0, sy), wx, wy); for (y = MAX(0, -sy); y < wy; y++) { for (x = MAX(0, -sx); x < wx; x++) { int terr, elev, losflag = MAPLOSHEX_SEE | MAPLOSHEX_SEEN; char *base; char topchar, botchar; if (losmap) losflag = LOSMap_GetFlag(losmap, sx+x, sy+y); if (!(losflag & MAPLOSHEX_SEEN)) { terr = 'X'; elev = 40; /* 'X' */ } else { if (losflag & MAPLOSHEX_SEETERRAIN) terr = GetTerrain(map, sx + x, sy + y); else terr = UNKNOWN_TERRAIN; if (losflag & MAPLOSHEX_SEEELEV) elev = GetElev(map, sx + x, sy + y); else elev = 15; /* Ugly hack: '0' + 15 == '?' */ } base = pos + tac_hex_offset(x, y, dispcols, oddcol1); switch (terr) { case WATER: /* * Colour hack: Draw deep water with '\242' * if using colour so colourize_tac_map() * knows to use dark blue rather than light * blue */ if (docolour && elev >= 2) { topchar = '\242'; botchar = '\242'; } else { topchar = '~'; botchar = '~'; } break; case HIGHWATER: topchar = '~'; botchar = '+'; break; case BRIDGE: topchar = '#'; botchar = '+'; break; case ' ': /* GRASSLAND */ topchar = ' '; botchar = '_'; break; case UNKNOWN_TERRAIN: topchar = '?'; botchar = '?'; break; default: topchar = terr; botchar = terr; break; } base[0] = topchar; base[1] = topchar; base[dispcols + 0] = botchar; if (elev > 0) { botchar = '0' + elev; } base[dispcols + 1] = botchar; } } } /* * Draw one of the seven hexes that a Dropship takes up on a tac map. */ static void sketch_tac_ds(char *base, int dispcols, char terr) { /* * Becareful not to overlay a 'mech id or terrain elevation. */ if (!isalpha((unsigned char) base[0])) { base[0] = terr; base[1] = terr; } base[dispcols + 0] = terr; if (!isdigit((unsigned char) base[dispcols + 1])) { base[dispcols + 1] = terr; } } extern int dirs[6][2]; static void sketch_tac_ownmech(char *buf, MAP * map, MECH * mech, int sx, int sy, int wx, int wy, int dispcols, int top_offset, int left_offset) { int oddcol1 = is_oddcol(sx); char *pos = buf + top_offset * dispcols + left_offset; char *base; int x = MechX(mech) - sx; int y = MechY(mech) - sy; if (x < 0 || x >= wx || y < 0 || y >= wy) { return; } base = pos + tac_hex_offset(x, y, dispcols, oddcol1); base[0] = '*'; base[0] = '*'; } static void sketch_tac_mechs(char *buf, MAP * map, MECH * player_mech, int sx, int sy, int wx, int wy, int dispcols, int top_offset, int left_offset, int docolour, int labels) { int i; char *pos = buf + top_offset * dispcols + left_offset; int oddcol1 = is_oddcol(sx); /* * Draw all the 'mechs on the map. */ for (i = 0; i < map->first_free; i++) { int x, y; char *base; MECH *mech; if (map->mechsOnMap[i] == -1) { continue; } mech = getMech(map->mechsOnMap[i]); if (mech == NULL) { continue; } /* * Check to see if the 'mech is on the tac map and * that its in LOS of the player's 'mech. */ x = MechX(mech) - sx; y = MechY(mech) - sy; if (x < 0 || x >= wx || y < 0 || y >= wy) { continue; } if (mech != player_mech && !InLineOfSight(player_mech, mech, MechX(mech), MechY(mech), FlMechRange(map, player_mech, mech))) { continue; } base = pos + tac_hex_offset(x, y, dispcols, oddcol1); if (!(MechSpecials2(mech) & CARRIER_TECH) && IsDS(mech) && ((MechZ(mech) >= ORBIT_Z && mech != player_mech) || Landed(mech) || !Started(mech))) { int ts = DSBearMod(mech); int dir; /* * Dropships are a special case. They take up * seven hexes on a tac map. First draw the * center hex and then the six surronding hexes. */ if (docolour) { /* * Colour hack: 'X' would be confused with * any enemy con by colourize_tac_map() */ sketch_tac_ds(base, dispcols, '$'); } else { sketch_tac_ds(base, dispcols, 'X'); } for (dir = 0; dir < 6; dir++) { int tx = x + dirs[dir][0]; int ty = y + dirs[dir][1]; if ((tx + oddcol1) % 2 == 0 && dirs[dir][0] != 0) { ty--; } if (tx < 0 || tx >= wx || ty < 0 || ty >= wy) { continue; } base = pos + tac_hex_offset(tx, ty, dispcols, oddcol1); if (Find_DS_Bay_Number(mech, (dir - ts + 6) % 6) >= 0) { sketch_tac_ds(base, dispcols, '@'); } else { sketch_tac_ds(base, dispcols, '='); } } } else if (mech == player_mech) { base[0] = '*'; base[1] = '*'; } else { char *id = MechIDS(mech, MechSeemsFriend(player_mech, mech)); base[0] = id[0]; base[1] = id[1]; } } } static void sketch_tac_cliffs(char *buf, MAP * map, int sx, int sy, int wx, int wy, int dispcols, int top_offset, int left_offset, int cliff_size) { char *pos = buf + top_offset * dispcols + left_offset; int y, x; int oddcol1 = is_oddcol(sx); wx = MIN(wx, map->map_width - sx); wy = MIN(wy, map->map_height - sy); for (y = MAX(0, -sy); y < wy; y++) { int ty = sy + y; for (x = MAX(0, -sx); x < wx; x++) { int tx = sx + x; int oddcolx = is_oddcol(tx); int elev = Elevation(map, tx, ty); char *base = pos + tac_hex_offset(x, y, dispcols, oddcol1); char c; /* * Copy the elevation up to the top of the hex * so we can draw a bottom hex edge on every hex. */ c = base[dispcols + 1]; if (base[0] == '*') { base[0] = '*'; base[1] = '*'; } else if (isdigit((unsigned char) c)) { base[1] = c; } /* * For each hex on the map check to see if each * of it's 240, 180, and 120 hex sides is a cliff. * Don't check for cliffs between hexes that are on * the tac map and those that are off of it. */ if (x != 0 && (y < wy - 1 || oddcolx) && abs(Elevation(map, tx - 1, ty + 1 - oddcolx) - elev) >= cliff_size) { base[dispcols - 1] = '|'; } if (y < wy - 1 && abs(Elevation(map, tx, ty + 1) - elev) >= cliff_size) { base[dispcols] = ','; base[dispcols + 1] = ','; } else { base[dispcols] = '_'; base[dispcols + 1] = '_'; } if (x < wx - 1 && (y < wy - 1 || oddcolx) && abs(Elevation(map, tx + 1, ty + 1 - oddcolx) - elev) >= cliff_size) { base[dispcols + 2] = '!'; } } } } static void sketch_tac_dslz(char *buf, MAP * map, MECH * mech, int sx, int sy, int wx, int wy, int dispcols, int top_offset, int left_offset, int cliff_size, int docolour) { char *pos = buf + top_offset * dispcols + left_offset; int y, x; int oddcol1 = is_oddcol(sx); wx = MIN(wx, map->map_width - sx); wy = MIN(wy, map->map_height - sy); for (y = MAX(0, -sy); y < wy; y++) { int ty = sy + y; for (x = MAX(0, -sx); x < wx; x++) { int tx = sx + x; char *base = pos + tac_hex_offset(x, y, dispcols, oddcol1); if (ImproperLZ(mech, tx, ty)) base[dispcols] = docolour ? '\241' : 'X'; else base[dispcols] = docolour ? '\240' : 'O'; } } } /* * Colourize a sketch tac map. Uses dynmaically allocated buffers * which are overwritten on each call. */ static char **colourize_tac_map(char const *sketch, int dispcols, int disprows) { static char *buf = NULL; static int buf_len = 5000; static char **lines = NULL; static int lines_len = 100; int pos = 0; int line = 0; unsigned char cur_colour = '\0'; const char *line_start; char const *src = sketch; if (buf == NULL) { Create(buf, char, buf_len); } if (lines == NULL) { Create(lines, char *, lines_len); } line_start = (char *) src; lines[0] = buf; while (lines > 0) { unsigned char new_colour; unsigned char c = *src++; if (c == '\0') { /* * End of line. */ if (cur_colour != '\0') { buf[pos++] = '%'; buf[pos++] = 'c'; buf[pos++] = 'n'; } buf[pos++] = '\0'; line++; if (line >= disprows) { break; /* Done */ } if (line + 1 >= lines_len) { lines_len *= 2; ReCreate(lines, char *, lines_len); } line_start += dispcols; src = line_start; lines[line] = buf + pos; continue; } switch (c) { case (unsigned char) '\242': /* Colour Hack: Deep Water */ c = '~'; new_colour = custom_color_str[DWATER_IDX]; break; case (unsigned char) '\241': /* Colour Hack: improper LZ */ c = 'X'; new_colour = custom_color_str[BADLZ_IDX]; break; case (unsigned char) '\240': /* Colour Hack: proper LZ */ c = 'O'; new_colour = custom_color_str[GOODLZ_IDX]; break; case '?': c = '?'; new_colour = custom_color_str[UNKNOWN_IDX]; break; case '$': /* Colour Hack: Drop Ship */ c = 'X'; new_colour = custom_color_str[DS_IDX]; break; case '!': /* Cliff hex edge */ c = '/'; new_colour = custom_color_str[CLIFF_IDX]; break; case '|': /* Cliff hex edge */ c = '\\'; new_colour = custom_color_str[CLIFF_IDX]; break; case ',': /* Cliff hex edge */ c = '_'; new_colour = custom_color_str[CLIFF_IDX]; break; case '*': /* mech itself. */ new_colour = custom_color_str[SELF_IDX]; break; default: if (islower(c)) { /* Friendly con */ new_colour = custom_color_str[FRIEND_IDX]; } else if (isupper(c)) { /* Enemy con */ new_colour = custom_color_str[ENEMY_IDX]; } else if (isdigit(c)) { /* Elevation */ new_colour = cur_colour; } else { new_colour = TerrainColorChar(c, 0); } break; } if (isupper(new_colour) != isupper(cur_colour)) { if (isupper(new_colour)) { buf[pos++] = '%'; buf[pos++] = 'c'; buf[pos++] = 'h'; } else { buf[pos++] = '%'; buf[pos++] = 'c'; buf[pos++] = 'n'; cur_colour = '\0'; } } if (tolower(new_colour) != tolower(cur_colour)) { buf[pos++] = '%'; buf[pos++] = 'c'; if (new_colour == '\0') { buf[pos++] = 'n'; } else if (new_colour == 'H') { buf[pos++] = 'n'; buf[pos++] = '%'; buf[pos++] = 'c'; buf[pos++] = tolower(new_colour); } else { buf[pos++] = tolower(new_colour); } cur_colour = new_colour; } buf[pos++] = c; if (pos + 11 > buf_len) { /* * If we somehow run out of room then we don't * bother to reallocate 'buf' and potentially have * a bunch of invalid pointers in 'lines' to fix up. * We just restart from scratch with a bigger 'buf'. */ buf_len *= 2; free(buf); buf = NULL; return colourize_tac_map(sketch, dispcols, disprows); } } lines[line] = NULL; return lines; } /* * Draw a tac map for the TACTICAL and NAVIGATE commands. * * This used to be "one MOFO of a function" but has been simplified * in a number of ways. One is that it used to statically allocated * buffers which limit the map drawn to MAP_DISPLAY_WIDTH hexes across * and 24 hexes down in size. The return value should no longer be * freed with KillText(). * * player = dbref of player wanting map (mostly irrelevant) * mech = mech player's in (or NULL, if on map) * map = map obj itself * cx = middle of the map (x) * cy = middle of the map (y) * wx = width in x * wy = width in y * labels = bit array * 1 = the 'top numbers' * 2 = the 'side numbers' * 4 = navigate mode * 8 = show mech cliffs * 16 = show tank cliffs * 32 = show DS LZ's * * If navigate mode, wx and wy should be equal and odd. Navigate maps * cannot have top or side labels. * */ char **MakeMapText(dbref player, MECH * mech, MAP * map, int cx, int cy, int wx, int wy, int labels, int dohexlos) { int docolour = Ansimap(player); int dispcols; int disprows; int mapcols; int left_offset = 0; int top_offset = 0; int navigate = 0; int sx, sy; int i; char *base; int oddcol1; enum { MAX_WIDTH = 40, MAX_HEIGHT = 24, TOP_LABEL = 3, LEFT_LABEL = 4, RIGHT_LABEL = 3 }; static char sketch_buf[((LEFT_LABEL + 1 + MAX_WIDTH * 3 + RIGHT_LABEL + 1) * (TOP_LABEL + 1 + MAX_HEIGHT * 2) + 2) * 5]; static char *lines[(TOP_LABEL + 1 + MAX_HEIGHT * 2 + 1) * 5]; if (labels & 4) { navigate = 1; labels = 0; } /* * Figure out the extent of the tac map to draw. */ wx = MIN(MAX_WIDTH, wx); wy = MIN(MAX_HEIGHT, wy); sx = cx - wx / 2; sy = cy - wy / 2; if (!navigate) { /* * Only allow navigate maps to include off map hexes. */ sx = MAX(0, MIN(sx, map->map_width - wx)); sy = MAX(0, MIN(sy, map->map_height - wy)); wx = MIN(wx, map->map_width); wy = MIN(wy, map->map_height); } mapcols = tac_dispcols(wx); dispcols = mapcols + 1; disprows = wy * 2 + 1; oddcol1 = is_oddcol(sx); if (navigate) { if (oddcol1) { /* * Insert blank line at the top where we can put * a "__" to make the navigate map look pretty. */ top_offset = 1; disprows++; } } else { /* * Allow room for the labels. */ if (labels & 1) { left_offset = LEFT_LABEL; dispcols += LEFT_LABEL + RIGHT_LABEL; } if (labels & 2) { top_offset = TOP_LABEL; disprows += TOP_LABEL; } } /* * Create a sketch tac map including terrain and elevation. */ sketch_tac_map(sketch_buf, map, mech, sx, sy, wx, wy, dispcols, top_offset, left_offset, docolour, dohexlos); /* * Draw the top and side labels. */ if (labels & 1) { int x; for (x = 0; x < wx; x++) { char scratch[4]; int label = sx + x; if (label < 0 || label > 999) { continue; } sprintf(scratch, "%3d", label); base = sketch_buf + left_offset + 1 + x * 3; base[0] = scratch[0]; base[1 * dispcols] = scratch[1]; base[2 * dispcols] = scratch[2]; } } if (labels & 2) { int y; for (y = 0; y < wy; y++) { int label = sy + y; base = sketch_buf + (top_offset + 1 + y * 2) * dispcols; if (label < 0 || label > 999) { continue; } sprintf(base, "%3d", label); base[3] = ' '; sprintf(base + (dispcols - RIGHT_LABEL - 1), "%3d", label); } } if (labels & 8) { if (mech != NULL) { sketch_tac_ownmech(sketch_buf, map, mech, sx, sy, wx, wy, dispcols, top_offset, left_offset); } sketch_tac_cliffs(sketch_buf, map, sx, sy, wx, wy, dispcols, top_offset, left_offset, 3); } else if (labels & 16) { if (mech != NULL) { sketch_tac_ownmech(sketch_buf, map, mech, sx, sy, wx, wy, dispcols, top_offset, left_offset); } sketch_tac_cliffs(sketch_buf, map, sx, sy, wx, wy, dispcols, top_offset, left_offset, 2); } else if (labels & 32) { if (mech != NULL) { sketch_tac_ownmech(sketch_buf, map, mech, sx, sy, wx, wy, dispcols, top_offset, left_offset); } sketch_tac_dslz(sketch_buf, map, mech, sx, sy, wx, wy, dispcols, top_offset, left_offset, 2, docolour); } else if (mech != NULL) { sketch_tac_mechs(sketch_buf, map, mech, sx, sy, wx, wy, dispcols, top_offset, left_offset, docolour, labels); } if (navigate) { int n = wx / 2; /* Hexagon radius */ /* * Navigate hack: erase characters from the sketch map * to turn it into a pretty hexagonal shaped map. */ if (oddcol1) { /* * Don't need the last line in this case. */ disprows--; } for (i = 0; i < n; i++) { int len; base = sketch_buf + (i + 1) * dispcols + left_offset; len = (n - i - 1) * 3 + 1; memset(base, ' ', len); base[len] = '_'; base[len + 1] = '_'; base[mapcols - len - 2] = '_'; base[mapcols - len - 1] = '_'; base[mapcols - len] = '\0'; base = sketch_buf + (disprows - i - 1) * dispcols + left_offset; len = (n - i) * 3; memset(base, ' ', len); base[mapcols - len] = '\0'; } memset(sketch_buf + left_offset, ' ', n * 3 + 1); sketch_buf[left_offset + n * 3 + 1] = '_'; sketch_buf[left_offset + n * 3 + 2] = '_'; sketch_buf[left_offset + n * 3 + 3] = '\0'; } if (docolour) { /* * If using colour then colourize the sketch map and * return the result. */ return colourize_tac_map(sketch_buf, dispcols, disprows); } /* * If not using colour, the sketch map can be used as is. */ for (i = 0; i < disprows; i++) { lines[i] = sketch_buf + dispcols * i; } lines[i] = NULL; return lines; } /* Draws the map for the player when they use the * TACTICAL [C | T | L] [<BEARING> <RANGE> | <TARGET-ID>] * command inside a unit */ void mech_tacmap(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; int argc, i; short x, y; int mapx, mapy; char *args_vec[4]; char **args = args_vec; MAP *mech_map; int displayHeight = MAP_DISPLAY_HEIGHT, displayWidth = MAP_DISPLAY_WIDTH; char *str; char **maptext; int flags = 3, dohexlos = 0; /* Basic checks for pilot and mech */ cch(MECH_USUAL); /* Get the map info */ mech_map = getMap(mech->mapindex); mapx = MechX(mech); mapy = MechY(mech); /* Various checks for conditions and system of mech */ argc = mech_parseattributes(buffer, args, 4); DOCHECK(!MechTacRange(mech), "Your system seems to be inoperational."); if (MapIsDark(mech_map) || (MechType(mech) == CLASS_MW && mudconf.btech_mw_losmap)) dohexlos = 1; /* Check to see which type of tactical to display * if they specified a particular one */ if (argc > 0 && isalpha((unsigned char) args[0][0]) && args[0][1] == '\0') { switch (tolower((unsigned char) args[0][0])) { case 'c': flags |= 8; /* Show cliffs */ break; case 't': flags |= 16; /* Show tank cliffs */ break; case 'l': dohexlos = 1; break; case 'b': flags |= 32; break; default: notify(player, "Invalid tactical map flag."); return; } args++; argc--; } DOCHECK(dohexlos && (flags & (8|16|32)), "You can't see that much here!"); if (!parse_tacargs(player, mech, args, argc, MechTacRange(mech), &x, &y)) return; /* Get the Tacsize attribute from * the player, if doesn't exist set the height and width to * default params. If it does exist, check the values and * make sure they are legit. */ str = silly_atr_get(player, A_TACSIZE); if (!*str) { displayHeight = MAP_DISPLAY_HEIGHT; displayWidth = MAP_DISPLAY_WIDTH; } else if (sscanf(str, "%d %d", &displayHeight, &displayWidth) != 2 || displayHeight > 24 || displayHeight < 5 || displayWidth > 40 || displayWidth < 5) { notify(player, "Illegal Tacsize attribute. Must be in format " "'Height Width' . Height : 5-24 Width : 5-40"); displayHeight = MAP_DISPLAY_HEIGHT; displayWidth = MAP_DISPLAY_WIDTH; } /* Everything worked but lets check the mech's tac range * and the map size */ displayHeight = (displayHeight <= 2 * MechTacRange(mech) ? displayHeight : 2 * MechTacRange(mech)); displayWidth = (displayWidth <= 2 * MechTacRange(mech) ? displayWidth : 2 * MechTacRange(mech)); displayHeight = (displayHeight <= mech_map->map_height) ? displayHeight : mech_map->map_height; displayWidth = (displayWidth <= mech_map->map_width) ? displayWidth : mech_map->map_width; set_colorscheme(player); /* Get the data to draw the map */ maptext = MakeMapText(player, mech, mech_map, x, y, displayWidth, displayHeight, flags, dohexlos); /* Draw the map for the player */ for (i = 0; maptext[i]; i++) notify(player, maptext[i]); } /* XXX Fix 'enterbase <dir>' */ static void mech_enter_event(MUXEVENT * e) { MECH *mech = (MECH *) e->data, *tmpm = NULL; mapobj *mapo; MAP *map = getMap(mech->mapindex), *newmap; int target = (int) e->data2; int x, y; if (!(mapo = find_entrance_by_xy(map, MechX(mech), MechY(mech)))) return; if (!Started(mech) || Uncon(mech) || Jumping(mech) || (MechType(mech) == CLASS_MECH && (Fallen(mech) || Standing(mech))) || OODing(mech) || (fabs(MechSpeed(mech)) * 5 >= MMaxSpeed(mech) && fabs(MMaxSpeed(mech)) >= MP1) || (MechType(mech) == CLASS_VTOL && AeroFuel(mech) <= 0)) return; if (!(newmap = getMap(mapo->obj))) return; if (!find_entrance(newmap, target, &x, &y)) return; if (!can_pass_lock(mech->mynum, newmap->mynum, A_LENTER) && (BuildIsSafe(newmap) || newmap->cf >= (newmap->cfmax / 2))) { char *msg = silly_atr_get(newmap->mynum, A_FAIL); if (!msg || !*msg) msg = "The hangar is locked."; mech_notify(mech, MECHALL, msg); return; } StopBSuitSwarmers(FindObjectsData(mech->mapindex), mech, 1); mech_notify(mech, MECHALL, tprintf("You enter %s.", structure_name(mapo))); MechLOSBroadcast(mech, tprintf("has entered %s at %d,%d.", structure_name(mapo), MechX(mech), MechY(mech))); MarkForLOSUpdate(mech); if (MechType(mech) == CLASS_MW && !In_Character(mapo->obj)) { enter_mw_bay(mech, mapo->obj); return; } if (MechCarrying(mech) > 0) tmpm = getMech(MechCarrying(mech)); mech_Rsetmapindex(GOD, (void *) mech, tprintf("%d", (int) mapo->obj)); mech_Rsetxy(GOD, (void *) mech, tprintf("%d %d", x, y)); MechLOSBroadcast(mech, tprintf("has entered %s at %d,%d.", structure_name(mapo), MechX(mech), MechY(mech))); loud_teleport(mech->mynum, mapo->obj); if (tmpm) { mech_Rsetmapindex(GOD, (void *) tmpm, tprintf("%d", (int) mapo->obj)); mech_Rsetxy(GOD, (void *) tmpm, tprintf("%d %d", x, y)); loud_teleport(tmpm->mynum, mapo->obj); } auto_cal_mapindex(mech); } void mech_enterbase(dbref player, void *data, char *buffer) { MECH *mech = (MECH *) data; MAP *map, *newmap; int x, y; mapobj *mapo; char target, *tmpc; char *args[2]; int argc; char fail_mesg[SBUF_SIZE]; argc = mech_parseattributes(buffer, args, 2); DOCHECK(argc > 1, "Invalid arguments to command!"); tmpc = args[0]; if (argc > 0 && *tmpc && !(*(tmpc + 1))) target = tolower(*tmpc); else target = 0; cch(MECH_USUAL); map = getMap(mech->mapindex); /* For now, no dir checks */ DOCHECK(Jumping(mech), "While in mid-jump? No way."); DOCHECK(MechType(mech) == CLASS_MECH && (Fallen(mech) || Standing(mech)), "Crawl inside? I think not. Stand first."); DOCHECK(OODing(mech), "While in mid-flight? No way."); DOCHECK(MechType(mech) == CLASS_VTOL && AeroFuel(mech) <= 0, "You lack fuel to maneuver in!"); DOCHECK(FlyingT(mech) && !Landed(mech), "You need to land before you can enter the hangar."); DOCHECK(IsDS(mech), "Heh, you're trying to be funny, right, a DropShip entering hangar?"); DOCHECK(fabs(MechSpeed(mech)) * 5 >= MMaxSpeed(mech) && fabs(MMaxSpeed(mech)) >= MP1, "You are moving too fast to enter the hangar!"); DOCHECK(!(mapo = find_entrance_by_xy(map, MechX(mech), MechY(mech))), "You see nothing to enter here!"); /* Wow, *gasp*, we got something to enter */ if (!(newmap = FindObjectsData(mapo->obj))) { mech_notify(mech, MECHALL, "You sense wrongness in fabric of space.."); SendError(tprintf ("Error: No map existing for mapindex #%d (@ %d,%d of #%d)", (int) mapo->obj, mapo->x, mapo->y, mech->mapindex)); return; } if (!find_entrance(newmap, target, &x, &y)) { mech_notify(mech, MECHALL, "You sense wrongness in fabric of space.."); SendError(tprintf ("Error: No entrance existing for mapindex #%d (@ %d,%d of #%d)", (int) mapo->obj, mapo->x, mapo->y, mech->mapindex)); return; } if (!can_pass_lock(mech->mynum, newmap->mynum, A_LENTER) && (BuildIsSafe(newmap) || newmap->cf >= (newmap->cfmax / 2))) { /* Trigger FAIL & AFAIL */ memset(fail_mesg, 0, sizeof(fail_mesg)); snprintf(fail_mesg, LBUF_SIZE, "The hangar is locked."); did_it(player, newmap->mynum, A_FAIL, fail_mesg, 0, NULL, A_AFAIL, (char **) NULL, 0); return; } DOCHECK(EnteringHangar(mech), "You are already entering the hangar!"); /* XXX Check for other mechs in the hex possibly doing this as well (ick) */ HexLOSBroadcast(map, MechX(mech), MechY(mech), "The doors at $h start to open.."); MECHEVENT(mech, EVENT_ENTER_HANGAR, mech_enter_event, 18, (int) target); }