#include "mech.h"
#include "btmacros.h"
#include "mech.sensor.h"
#include "map.los.h"
#include "p.mech.utils.h"
Include dependency graph for map.los.c:
Go to the source code of this file.
Defines | |
#define | INDEX2X(i) ((i%(losmap.xsize))+(losmap.startx)) |
#define | INDEX2Y(i) ((i/(losmap.xsize))+(losmap.starty)) |
#define | DEF_MINA(mech, sn) (MechSeesTerrain(mech, sn) ? -20 : 1000) |
Functions | |
int | TraceLOS (MAP *map, int ax, int ay, int bx, int by, lostrace_info **result) |
int | LOSMap_Hex2Index (hexlosmap_info *losmap, int x, int y) |
static float | MechHeight (MECH *mech) |
static void | set_hexlosinfo (int x, int y, int flag) |
static int | hexlit (int x, int y) |
static void | set_sliteinfo (int x, int y, int flag) |
static void | set_hexlosall (int flag) |
static int | MechSeesThroughWoods (MECH *mech, MAP *map, int nwoods, int sensor) |
static int | MechSeesOverMountain (MECH *mech, MAP *map, int sensor) |
static int | MechSeesThroughWater (MECH *mech, MAP *map, int nwater, int sensor) |
static int | MechSeesRange (MECH *mech, MAP *map, int x, int y, int z, int sensor) |
static int | MechSLitesRange (MECH *mech, int x, int y, int z) |
static int | MechSeesTerrain (MECH *mech, int sn) |
static void | trace_slitelos (MAP *map, MECH *mech, int index, float start_height) |
static void | litemark_callback (MAP *map, int x, int y) |
static void | litemark_map (MAP *map) |
static void | trace_maphexlos (MAP *map, MECH *mech, int index, int tracew, float start_height) |
hexlosmap_info * | CalculateLOSMap (MAP *map, MECH *mech, int sx, int sy, int xsz, int ysz) |
Variables | |
static hexlosmap_info | losmap |
#define DEF_MINA | ( | mech, | |||
sn | ) | (MechSeesTerrain(mech, sn) ? -20 : 1000) |
#define INDEX2X | ( | i | ) | ((i%(losmap.xsize))+(losmap.startx)) |
#define INDEX2Y | ( | i | ) | ((i/(losmap.xsize))+(losmap.starty)) |
hexlosmap_info* CalculateLOSMap | ( | MAP * | map, | |
MECH * | mech, | |||
int | sx, | |||
int | sy, | |||
int | xsz, | |||
int | ysz | |||
) |
Definition at line 433 of file map.los.c.
References CLAIRVOYANT, CLASS_MECH, hexlosmap_info::flags, IsWater, litemark_map(), losmap, hexlosmap_info::map, MAPLOS_MAXX, MAPLOS_MAXY, MAPLOSHEX_NOLOS, MAPLOSHEX_SEE, MAPLOSHEX_SEEN, MechCritStatus, MechHeight(), MechMove, MechRTerrain, MechSeesTerrain(), MechType, MechZ, MOVE_HOVER, MECH::mynum, SendError, set_hexlosall(), hexlosmap_info::startx, hexlosmap_info::starty, tprintf(), trace_maphexlos(), WaterBeast, hexlosmap_info::xsize, and hexlosmap_info::ysize.
Referenced by sketch_tac_map().
00435 { 00436 int index, underterrain, bothworlds; 00437 float start_height; 00438 00439 /* Some safeguarding on size */ 00440 00441 if(xsz > MAPLOS_MAXX || ysz > MAPLOS_MAXY) { 00442 SendError(tprintf("xsize (%d vs %d) or ysize (%d vs %d) " 00443 "to CalculateLOSMap too large, for mech #%d", 00444 xsz, MAPLOS_MAXX, ysz, MAPLOS_MAXY, mech->mynum)); 00445 return NULL; 00446 } 00447 00448 losmap.startx = sx; 00449 losmap.starty = sy; 00450 losmap.xsize = xsz; 00451 losmap.ysize = ysz; 00452 losmap.flags = 0; 00453 memset(losmap.map, 0, xsz * ysz); 00454 00455 underterrain = MechZ(mech) <= -1; 00456 if(IsWater(MechRTerrain(mech)) 00457 && ((MechType(mech) == CLASS_MECH && MechZ(mech) == -1) 00458 || ((WaterBeast(mech) || MechMove(mech) == MOVE_HOVER) 00459 && MechZ(mech) == 0))) { 00460 bothworlds = 1; 00461 } else 00462 bothworlds = 0; 00463 00464 start_height = MechZ(mech) + MechHeight(mech); 00465 00466 if(MechCritStatus(mech) & CLAIRVOYANT) { 00467 set_hexlosall(MAPLOSHEX_SEE); 00468 return &losmap; 00469 } 00470 00471 if(!MechSeesTerrain(mech, 0) && !MechSeesTerrain(mech, 1)) { 00472 set_hexlosall(MAPLOSHEX_NOLOS); 00473 return &losmap; 00474 } 00475 00476 /* In order for slites to properly light terrain, we have to mark the 00477 * losmap with all lit hexes first. Which means going over all 'mechs on 00478 * the map and tag all hexes that they light. 00479 */ 00480 00481 litemark_map(map); 00482 00483 /* In order to do the most efficient lostracing, we make losmaps by 00484 * first tracing from the 'mech hex to the upper Y-row, the lower Y-row, 00485 * the leftmost X-row, the rightmost X-row, and then all hexes starting 00486 * at the upper left corner to make sure we have seen all hexes. (It is 00487 * entirely possible for a hex not to be visited yet, even if we traced 00488 * to every other hex.) 00489 */ 00490 00491 for(index = 0; index < xsz; index++) { 00492 if(losmap.map[index] & MAPLOSHEX_SEEN) 00493 continue; 00494 trace_maphexlos(map, mech, index, underterrain || bothworlds, 00495 start_height); 00496 } 00497 for(index = (ysz - 1) * xsz; index < ysz * xsz; index++) { 00498 if(losmap.map[index] & MAPLOSHEX_SEEN) 00499 continue; 00500 trace_maphexlos(map, mech, index, underterrain || bothworlds, 00501 start_height); 00502 } 00503 for(index = xsz; index < ysz * xsz; index += xsz) { 00504 if(losmap.map[index] & MAPLOSHEX_SEEN) 00505 continue; 00506 trace_maphexlos(map, mech, index, underterrain || bothworlds, 00507 start_height); 00508 } 00509 for(index = 2 * xsz - 1; index < ysz * xsz; index += xsz) { 00510 if(losmap.map[index] & MAPLOSHEX_SEEN) 00511 continue; 00512 trace_maphexlos(map, mech, index, underterrain || bothworlds, 00513 start_height); 00514 } 00515 for(index = 0; index < xsz * ysz; index++) { 00516 if(losmap.map[index] & MAPLOSHEX_SEEN) 00517 continue; 00518 trace_maphexlos(map, mech, index, underterrain || bothworlds, 00519 start_height); 00520 } 00521 00522 return &losmap; 00523 }
static int hexlit | ( | int | x, | |
int | y | |||
) | [static] |
Definition at line 62 of file map.los.c.
References losmap, LOSMap_Hex2Index(), hexlosmap_info::map, MAPLOSHEX_LIT, hexlosmap_info::startx, hexlosmap_info::starty, hexlosmap_info::xsize, and hexlosmap_info::ysize.
Referenced by trace_maphexlos().
00063 { 00064 if(x < (losmap.startx) || x >= (losmap.startx) + (losmap.xsize) || 00065 y < (losmap.starty) || y >= (losmap.starty) + (losmap.ysize)) { 00066 return 0; 00067 } 00068 00069 return (losmap.map[LOSMap_Hex2Index(&losmap, x, y)] & MAPLOSHEX_LIT); 00070 }
static void litemark_callback | ( | MAP * | map, | |
int | x, | |||
int | y | |||
) | [static] |
Definition at line 260 of file map.los.c.
References MAPLOSHEX_LIT, and set_sliteinfo().
Referenced by litemark_map().
00261 { 00262 set_sliteinfo(x, y, MAPLOSHEX_LIT); 00263 }
static void litemark_map | ( | MAP * | map | ) | [static] |
Definition at line 265 of file map.los.c.
References FindObjectsData(), MAP::first_free, first_mapobj(), Jellied, litemark_callback(), losmap, MAPLOSHEX_LIT, MechHeight(), MechLites, MAP::mechsOnMap, MechX, MechY, MechZ, next_mapobj(), set_sliteinfo(), trace_slitelos(), TYPE_FIRE, visit_neighbor_hexes(), mapobj_struct::x, hexlosmap_info::xsize, mapobj_struct::y, and hexlosmap_info::ysize.
Referenced by CalculateLOSMap().
00266 { 00267 MECH *mech; 00268 int i; 00269 int index; 00270 mapobj *fire; 00271 00272 for(fire = first_mapobj(map, TYPE_FIRE); fire; fire = next_mapobj(fire)) { 00273 set_sliteinfo(fire->x, fire->y, MAPLOSHEX_LIT); 00274 visit_neighbor_hexes(map, fire->x, fire->y, litemark_callback); 00275 } 00276 00277 for(i = 0; i < map->first_free; i++) { 00278 if(map->mechsOnMap[i] < 0) 00279 continue; 00280 mech = FindObjectsData(map->mechsOnMap[i]); 00281 if(!mech) 00282 continue; 00283 00284 if(Jellied(mech)) { 00285 set_sliteinfo(MechX(mech), MechY(mech), MAPLOSHEX_LIT); 00286 visit_neighbor_hexes(map, MechX(mech), MechY(mech), 00287 litemark_callback); 00288 } 00289 00290 if(!MechLites(mech)) 00291 continue; 00292 00293 for(index = 0; index < losmap.xsize * losmap.ysize; index++) { 00294 trace_slitelos(map, mech, index, MechZ(mech) + MechHeight(mech)); 00295 } 00296 } 00297 }
int LOSMap_Hex2Index | ( | hexlosmap_info * | losmap, | |
int | x, | |||
int | y | |||
) |
Definition at line 26 of file map.los.c.
References losmap, SendError, hexlosmap_info::startx, hexlosmap_info::starty, tprintf(), hexlosmap_info::xsize, and hexlosmap_info::ysize.
Referenced by hexlit(), set_hexlosinfo(), and set_sliteinfo().
00027 { 00028 if(x < losmap->startx || x > losmap->startx + losmap->xsize || 00029 y < losmap->starty || y > losmap->starty + losmap->ysize) { 00030 SendError(tprintf("LOSMap request from out of bounds hex: %d,%d", 00031 x, y)); 00032 return 0; 00033 } 00034 return ((y - losmap->starty) * losmap->xsize) + (x - losmap->startx); 00035 }
static float MechHeight | ( | MECH * | mech | ) | [static] |
Definition at line 37 of file map.los.c.
References CLASS_DS, CLASS_MECH, CLASS_MW, CLASS_SPHEROID_DS, CLASS_VEH_NAVAL, Fallen, and MechType.
Referenced by CalculateLOSMap(), and litemark_map().
00038 { 00039 switch (MechType(mech)) { 00040 case CLASS_MECH: 00041 return 0.2 + !Fallen(mech); 00042 case CLASS_SPHEROID_DS: 00043 return 4.2; 00044 case CLASS_DS: 00045 return 2.2; 00046 case CLASS_MW: 00047 case CLASS_VEH_NAVAL: 00048 return 0.01; 00049 } 00050 return 0.2; 00051 }
Definition at line 106 of file map.los.c.
References SensorStruct::cansee_func, MECHLOSFLAG_MNTN, MechSensor, and sensors.
Referenced by trace_maphexlos().
00107 { 00108 int sn = MechSensor(mech)[sensor]; 00109 int fake_losflag = MECHLOSFLAG_MNTN; 00110 00111 return sensors[sn].cansee_func(mech, NULL, map, 1, fake_losflag); 00112 }
Definition at line 123 of file map.los.c.
References FindRange(), hexlosmap_info::flags, FORWARDARC, InWeaponArc(), losmap, MapCoordToRealCoord(), MAP::maplight, MAPLOS_FLAG_SLITE, MAP::mapvis, SensorStruct::maxvis, MechFX, MechFY, MechFZ, MechSensor, sensors, TURRETARC, and ZSCALE.
Referenced by trace_maphexlos().
00125 { 00126 int sn = MechSensor(mech)[sensor]; 00127 float fx, fy, range, maxvis = sensors[sn].maxvis; 00128 00129 MapCoordToRealCoord(x, y, &fx, &fy); 00130 range = FindRange(MechFX(mech), MechFY(mech), MechFZ(mech), 00131 fx, fy, ZSCALE * z); 00132 00133 /* XXX HACK: code duplication. this should be replaced with sensor 00134 * functions 00135 */ 00136 00137 if(sn < 2) /* V or L sensors */ 00138 maxvis = map->mapvis; 00139 if(sn == 1 && map->maplight == 0) /* L sensors in darkness */ 00140 maxvis *= 2; 00141 00142 if(!sensors[sn].fullvision) { 00143 int arc = InWeaponArc(mech, fx, fy); 00144 00145 if(!(arc & (FORWARDARC | TURRETARC))) { 00146 if(MechSensor(mech)[0] == MechSensor(mech)[1]) 00147 maxvis = (maxvis * 200 / 300); 00148 else 00149 maxvis = 0; 00150 } 00151 } 00152 00153 if(sn == 0 && maxvis && range >= maxvis && 00154 (losmap.flags & MAPLOS_FLAG_SLITE)) 00155 return -1; 00156 00157 return range < maxvis; 00158 }
static int MechSeesTerrain | ( | MECH * | mech, | |
int | sn | |||
) | [static] |
Definition at line 176 of file map.los.c.
References MechSensor.
Referenced by CalculateLOSMap().
00177 { 00178 return MechSensor(mech)[sn] < 4; 00179 }
Definition at line 114 of file map.los.c.
References SensorStruct::cansee_func, MECHLOSFLAG_WATER, MechSensor, and sensors.
Referenced by trace_maphexlos().
00116 { 00117 int sn = MechSensor(mech)[sensor]; 00118 int fake_losflag = nwater * MECHLOSFLAG_WATER; 00119 00120 return sensors[sn].cansee_func(mech, NULL, map, 1, fake_losflag); 00121 }
Definition at line 96 of file map.los.c.
References SensorStruct::cansee_func, MECHLOSFLAG_WOOD, MechSensor, and sensors.
Referenced by trace_maphexlos().
00098 { 00099 int sn = MechSensor(mech)[sensor]; 00100 int fake_losflag = nwoods * MECHLOSFLAG_WOOD; 00101 int res = sensors[sn].cansee_func(mech, NULL, map, 1, fake_losflag); 00102 00103 return res; 00104 }
static int MechSLitesRange | ( | MECH * | mech, | |
int | x, | |||
int | y, | |||
int | z | |||
) | [static] |
Definition at line 160 of file map.los.c.
References FindRange(), FORWARDARC, InWeaponArc(), MapCoordToRealCoord(), MechFX, MechFY, MechFZ, TURRETARC, and ZSCALE.
Referenced by trace_slitelos().
00161 { 00162 float fx, fy, range; 00163 int arc, maxvis = 60; 00164 00165 MapCoordToRealCoord(x, y, &fx, &fy); 00166 arc = InWeaponArc(mech, fx, fy); 00167 if(!(arc & (FORWARDARC | TURRETARC))) { 00168 return 0; 00169 } 00170 00171 range = FindRange(MechFX(mech), MechFY(mech), MechFZ(mech), 00172 fx, fy, ZSCALE * z); 00173 return range < maxvis; 00174 }
static void set_hexlosall | ( | int | flag | ) | [static] |
Definition at line 87 of file map.los.c.
References losmap, hexlosmap_info::map, MAPLOSHEX_SEEN, hexlosmap_info::xsize, and hexlosmap_info::ysize.
Referenced by CalculateLOSMap().
static void set_hexlosinfo | ( | int | x, | |
int | y, | |||
int | flag | |||
) | [static] |
Definition at line 53 of file map.los.c.
References losmap, LOSMap_Hex2Index(), hexlosmap_info::map, MAPLOSHEX_SEEN, hexlosmap_info::startx, hexlosmap_info::starty, hexlosmap_info::xsize, and hexlosmap_info::ysize.
Referenced by trace_maphexlos().
00054 { 00055 if(x < (losmap.startx) || x >= (losmap.startx) + (losmap.xsize) || 00056 y < (losmap.starty) || y >= (losmap.starty) + (losmap.ysize)) { 00057 return; 00058 } 00059 losmap.map[LOSMap_Hex2Index(&losmap, x, y)] |= (flag | MAPLOSHEX_SEEN); 00060 }
static void set_sliteinfo | ( | int | x, | |
int | y, | |||
int | flag | |||
) | [static] |
Definition at line 72 of file map.los.c.
References hexlosmap_info::flags, losmap, LOSMap_Hex2Index(), hexlosmap_info::map, MAPLOS_FLAG_SLITE, hexlosmap_info::startx, hexlosmap_info::starty, hexlosmap_info::xsize, and hexlosmap_info::ysize.
Referenced by litemark_callback(), litemark_map(), and trace_slitelos().
00073 { 00074 if(x < (losmap.startx) || x >= (losmap.startx) + (losmap.xsize) || 00075 y < (losmap.starty) || y >= (losmap.starty) + (losmap.ysize)) { 00076 return; 00077 } 00078 losmap.flags |= MAPLOS_FLAG_SLITE; 00079 losmap.map[LOSMap_Hex2Index(&losmap, x, y)] |= flag; 00080 }
static void trace_maphexlos | ( | MAP * | map, | |
MECH * | mech, | |||
int | index, | |||
int | tracew, | |||
float | start_height | |||
) | [static] |
Definition at line 301 of file map.los.c.
References DEF_MINA, Elevation, GetRTerrain, HEAVY_FOREST, hexlit(), INDEX2X, INDEX2Y, LIGHT_FOREST, MAPLOSHEX_NOLOS, MAPLOSHEX_SEE, MAPLOSHEX_SEETERRAIN, MAX_SENSORS, MechSeesOverMountain(), MechSeesRange(), MechSeesThroughWater(), MechSeesThroughWoods(), MechX, MechY, MOUNTAINS, NUMSENSORS, set_hexlosinfo(), TraceLOS(), WATER, watercount, lostrace_info::x, and lostrace_info::y.
Referenced by CalculateLOSMap().
00303 { 00304 int trace_water[MAX_SENSORS] = { tracew, tracew }; 00305 float minangle[MAX_SENSORS] = { DEF_MINA(mech, 0), DEF_MINA(mech, 1) }; 00306 float blockangle[MAX_SENSORS] = { DEF_MINA(mech, 0), DEF_MINA(mech, 1) }; 00307 int woodcount[MAX_SENSORS] = { 0, 0 }; 00308 int watercount[MAX_SENSORS] = { 0, 0 }; 00309 lostrace_info *trace_coords; 00310 int trace_range = 0; 00311 00312 int trace_coordnum = TraceLOS(map, MechX(mech), MechY(mech), 00313 INDEX2X(index), INDEX2Y(index), 00314 &trace_coords); 00315 00316 for(; trace_range < trace_coordnum; trace_range++) { 00317 int seestate; 00318 int trace_x = trace_coords[trace_range].x; 00319 int trace_y = trace_coords[trace_range].y; 00320 int trace_height = Elevation(map, trace_x, trace_y); 00321 00322 float trace_a = (trace_height - start_height) / (trace_range + 1); 00323 float trace_ba = 00324 ((trace_height + 2 - start_height)) / (trace_range + 1); 00325 int trace_terrain = GetRTerrain(map, trace_x, trace_y); 00326 int nsensor, newwoods; 00327 00328 for(nsensor = 0; nsensor < NUMSENSORS(mech); nsensor++) { 00329 00330 /* If the current hex and all its terrain ('blockangle') lies 00331 * below our minimum angle of sight, we won't see it at all; 00332 * jump straight ahead to the water/mountain checks. This check 00333 * is made first, because it is the cheapest check and the 00334 * general mechanism to signal 'no more visibility on this line 00335 * of sight' is to set trace_ba to an impossible angle. 00336 */ 00337 00338 if(trace_ba < minangle[nsensor]) { 00339 set_hexlosinfo(trace_x, trace_y, MAPLOSHEX_NOLOS); 00340 goto hexinfluence; 00341 00342 } 00343 00344 /* Then we check for range. */ 00345 seestate = MechSeesRange(mech, map, trace_x, trace_y, 00346 trace_height, nsensor); 00347 00348 if(seestate == 0) { 00349 set_hexlosinfo(trace_x, trace_y, MAPLOSHEX_NOLOS); 00350 minangle[nsensor] = blockangle[nsensor] = 1000; 00351 goto hexinfluence; 00352 } 00353 00354 /* Count the number of woods. */ 00355 newwoods = 0; 00356 switch (trace_terrain) { 00357 case HEAVY_FOREST: 00358 newwoods++; 00359 /* FALLTHROUGH */ 00360 case LIGHT_FOREST: 00361 newwoods++; 00362 /* Because we aren't in water, we stop tracing below water */ 00363 trace_water[nsensor] = 0; 00364 break; 00365 } 00366 00367 if(!newwoods) { 00368 00369 if(trace_a < minangle[nsensor] || (seestate < 0 && 00370 !hexlit(trace_x, 00371 trace_y))) { 00372 set_hexlosinfo(trace_x, trace_y, MAPLOSHEX_NOLOS); 00373 } else { 00374 set_hexlosinfo(trace_x, trace_y, MAPLOSHEX_SEE); 00375 blockangle[nsensor] = minangle[nsensor] = trace_a; 00376 woodcount[nsensor] = 0; 00377 } 00378 goto hexinfluence; 00379 } 00380 00381 if(blockangle[nsensor] < trace_a) { 00382 minangle[nsensor] = trace_a; 00383 blockangle[nsensor] = trace_ba; 00384 woodcount[nsensor] = newwoods; 00385 } else if(!MechSeesThroughWoods(mech, map, woodcount[nsensor] + 00386 newwoods, nsensor)) { 00387 if(trace_ba >= blockangle[nsensor]) { 00388 minangle[nsensor] = blockangle[nsensor]; 00389 blockangle[nsensor] = trace_ba; 00390 woodcount[nsensor] = newwoods; 00391 } else 00392 minangle[nsensor] = trace_ba; 00393 } else { 00394 minangle[nsensor] = trace_a; 00395 woodcount[nsensor] += newwoods; 00396 } 00397 00398 if(trace_terrain == WATER) { 00399 if(trace_water[nsensor]) 00400 watercount[nsensor]++; 00401 if(!trace_water[nsensor] || 00402 !MechSeesThroughWater(mech, map, watercount[nsensor], 00403 nsensor)) { 00404 if(seestate < 0 && !hexlit(trace_x, trace_y)) 00405 set_hexlosinfo(trace_x, trace_y, MAPLOSHEX_NOLOS); 00406 else 00407 set_hexlosinfo(trace_x, trace_y, 00408 MAPLOSHEX_SEETERRAIN); 00409 } 00410 } else if(seestate < 0 && !hexlit(trace_x, trace_y)) 00411 set_hexlosinfo(trace_x, trace_y, MAPLOSHEX_NOLOS); 00412 else 00413 set_hexlosinfo(trace_x, trace_y, MAPLOSHEX_SEE); 00414 00415 hexinfluence: 00416 if(trace_terrain == WATER && 00417 !MechSeesThroughWater(mech, map, 1, nsensor)) { 00418 set_hexlosinfo(trace_x, trace_y, MAPLOSHEX_NOLOS); 00419 minangle[nsensor] = blockangle[nsensor] = 1000; 00420 continue; 00421 } 00422 trace_water[nsensor] = 0; 00423 if(trace_terrain == MOUNTAINS && 00424 !MechSeesOverMountain(mech, map, nsensor)) { 00425 set_hexlosinfo(trace_x, trace_y, MAPLOSHEX_NOLOS); 00426 minangle[nsensor] = blockangle[nsensor] = 1000; 00427 continue; 00428 } 00429 } 00430 } 00431 }
Definition at line 223 of file map.los.c.
References Elevation, GetTerrain, HEAVY_FOREST, INDEX2X, INDEX2Y, LIGHT_FOREST, MAPLOSHEX_LIT, MAX, MechSLitesRange(), MechX, MechY, set_sliteinfo(), SMOKE, TraceLOS(), x, and lostrace_info::y.
Referenced by litemark_map().
00225 { 00226 float minangle = -20; 00227 lostrace_info *trace_coords; 00228 int trace_range = 0; 00229 int trace_x, trace_y, trace_height; 00230 float trace_a; 00231 int trace_coordnum = TraceLOS(map, MechX(mech), MechY(mech), 00232 INDEX2X(index), INDEX2Y(index), 00233 &trace_coords); 00234 00235 for(; trace_range < trace_coordnum; trace_range++) { 00236 trace_x = trace_coords[trace_range].x; 00237 trace_y = trace_coords[trace_range].y; 00238 00239 trace_height = MAX(0, Elevation(map, trace_x, trace_y)); 00240 00241 if(!MechSLitesRange(mech, trace_x, trace_y, trace_height)) 00242 return; 00243 00244 trace_a = (trace_height - start_height) / (trace_range + 1); 00245 switch (GetTerrain(map, trace_x, trace_y)) { 00246 case HEAVY_FOREST: 00247 case LIGHT_FOREST: 00248 case SMOKE: 00249 trace_a += 2; 00250 } 00251 00252 if(trace_a < minangle) 00253 continue; 00254 00255 set_sliteinfo(trace_x, trace_y, MAPLOSHEX_LIT); 00256 minangle = trace_a; 00257 } 00258 }
int TraceLOS | ( | MAP * | map, | |
int | ax, | |||
int | ay, | |||
int | bx, | |||
int | by, | |||
lostrace_info ** | result | |||
) |
Definition at line 208 of file mech.lostracer.c.
Referenced by CalculateLOSFlag(), trace_maphexlos(), and trace_slitelos().
00210 { 00211 00212 int i; /* Generic counter */ 00213 float acx, acy, bcx, bcy; /* endpoints CARTESIAN coords */ 00214 float currcx, currcy; /* current hex CARTESIAN coords */ 00215 int currx, curry; /* current hex being worked from */ 00216 int nextx, nexty; /* x & y coords of next hex */ 00217 int bestx = 0, besty = 0; /* best found so far */ 00218 int lastx, lasty; /* Holding place for final intervening hex */ 00219 int xmul, ymul; /* Used in 30/150/210/330 special case */ 00220 hexdir nexthex; /* potential next hex being examined */ 00221 float nextcx, nextcy; /* Next hex's CARTESIAN coords */ 00222 float slope; /* slope of line */ 00223 float uangle; /* angle of line (in STD CARTESIAN FORM!) */ 00224 float sinu; /* sin of -uangle */ 00225 float cosu; /* cos of same */ 00226 float liney; /* TRANSFORMED y coord of the line */ 00227 float tempangle; /* temporary uangle used for effrad calc */ 00228 float effrad; /* effective radius of hex */ 00229 float currdist; /* distance along line of current hex */ 00230 float nextdist; /* distance along the line of potential hex */ 00231 float bestdist; /* "best" (not furthest) distance tried */ 00232 float enddist; /* distance along at end of line */ 00233 static lostrace_info found_coords[4000]; 00234 int found_count = 0; 00235 00236 /* Before doing anything, let's check for special circumstances, this */ 00237 /* means vertical lines (which work using the current code, but depend */ 00238 /* on atan returning proper vaules for atan(-Inf) -- which is probably */ 00239 /* slow and may break on non-ANSI systems; and also lines at 30, 90 */ 00240 /* etc.. degrees which contain 'ties' between hexes. FASA rules here */ 00241 /* say that the 'best' hex for the defender (the one that breaks LOS, */ 00242 /* or gives a greater BTH penalty) should be used. */ 00243 00244 /* THE base case */ 00245 if((ax == bx) && (ay == by)) { 00246 Store_Hex(bx, by); 00247 *result = found_coords; 00248 return found_count; 00249 } 00250 /* Is it vertical? */ 00251 if(ax == bx) { 00252 if(ay > by) 00253 for(i = ay - 1; i > by; i--) 00254 Store_Hex(ax, i); 00255 else 00256 for(i = ay + 1; i < by; i++) 00257 Store_Hex(ax, i); 00258 Store_Hex(bx, by); 00259 *result = found_coords; 00260 return found_count; 00261 } 00262 00263 /* Does it lie along a 90 degree 'tie' direction? */ 00264 /* IF(even-number-of-cols apart AND same-y-coord) */ 00265 if(!((bx - ax) % 2) && ay == by) { 00266 currx = ax; 00267 i = bx > ax ? 1 : -1; 00268 while (currx != bx) { 00269 /* Do best of (currx+1,by-currx%2) */ 00270 /* or (currx+1,by-currx%2+1) */ 00271 Store_BestOf(currx + 1 * i, by - currx % 2, currx + 1 * i, 00272 by - currx % 2 + 1); 00273 00274 if(currx != bx) 00275 Store_Hex(currx + 2 * i, by); 00276 00277 currx += 2 * i; 00278 } 00279 00280 /* Store_Hex(bx,by); */ 00281 *result = found_coords; 00282 return found_count; 00283 } 00284 00285 /* Does it lie along a 30, 150, 210, 330 degree 'tie' direction? */ 00286 /* This expression is messy, but it just means that a hex is along */ 00287 /* 30 degrees if the y distance is (the integer part of) 3/2 */ 00288 /* times the x distance, plus 1 if the x difference is odd, AND */ 00289 /* the original hex was in an even column and heads in the +y */ 00290 /* direction, or odd and goes -y. It works, try it :) */ 00291 if(abs(by - ay) == 00292 (3 * abs(bx - ax) / 2) + abs((bx - ax) % 2) * abs((by < 00293 ay) ? (ax % 00294 2) : (1 - 00295 ax % 00296 2))) { 00297 00298 /* First get the x and y 'multipliers' -- either 1 or -1 */ 00299 /* they determine the direction of the movement */ 00300 if(bx > ax) 00301 if(by > ay) { 00302 xmul = 1; 00303 ymul = 1; 00304 } else { 00305 xmul = 1; 00306 ymul = -1; 00307 } else if(by > ay) { 00308 xmul = -1; 00309 ymul = 1; 00310 } else { 00311 xmul = -1; 00312 ymul = -1; 00313 } 00314 00315 currx = ax; 00316 curry = ay; 00317 while ((currx != bx) && (curry != by)) { 00318 00319 Store_BestOf(currx, curry + ymul, currx + xmul, 00320 ymul == 00321 1 ? curry + 1 - currx % 2 : curry - currx % 2); 00322 00323 curry += (ymul == 1) ? (2 - currx % 2) : (-1 - currx % 2); 00324 currx += xmul; 00325 00326 if(currx == bx && curry == by) 00327 continue; 00328 00329 Store_Hex(currx, curry); 00330 } 00331 Store_Hex(currx, curry); 00332 *result = found_coords; 00333 return found_count; 00334 } 00335 00336 /****************************************************************************/ 00337 00338 /**** OK, now we know it's not a special case ******************************/ 00339 00340 /****************************************************************************/ 00341 00342 /* First get the necessary constants set up */ 00343 00344 LOS_MapCoordToRealCoord(ax, ay, acx, acy); 00345 LOS_MapCoordToRealCoord(bx, by, bcx, bcy); 00346 00347 slope = (float) (acy - bcy) / (float) (acx - bcx); 00348 00349 uangle = -atan(slope); 00350 00351 sinu = sin(uangle); 00352 cosu = cos(uangle); 00353 00354 liney = acx * sinu + acy * cosu; /* we could just as */ 00355 /* correctly use bx, by */ 00356 00357 enddist = bcx * cosu - bcy * sinu; 00358 00359 tempangle = fabs(uangle); 00360 while (tempangle > DEG60) 00361 tempangle -= DEG60; 00362 effrad = cos(tempangle - DEG30) * TRACESCALEMAP / ROOT3; 00363 00364 /*****************************************************************/ 00365 00368 /*****************************************************************/ 00369 00370 currx = ax; 00371 curry = ay; 00372 LOS_MapCoordToRealCoord(currx, curry, currcx, currcy); 00373 currdist = currcx * cosu - currcy * sinu; 00374 bestdist = enddist; /* set this to the endpoint, the worst */ 00375 /* possible point to go to */ 00376 00377 while (!(currx == bx && curry == by)) { 00378 00379 for(nexthex = N; nexthex <= NW; nexthex++) { 00380 00381 GetAdjHex(currx, curry, nexthex, &nextx, &nexty); 00382 LOS_MapCoordToRealCoord(nextx, nexty, nextcx, nextcy); 00383 00384 /* Is it on the line? */ 00385 if(fabs((nextcx * sinu + nextcy * cosu) - liney) > effrad) 00386 continue; 00387 00388 /* Where is it? Find the transformed x coord */ 00389 nextdist = nextcx * cosu - nextcy * sinu; 00390 00391 /* is it forward of the current hex? */ 00392 if(fabs(enddist - nextdist) > fabs(enddist - currdist)) 00393 continue; 00394 00395 /* Is it better than what we have? */ 00396 if(fabs(enddist - nextdist) >= fabs(enddist - bestdist)) { 00397 bestdist = nextdist; 00398 bestx = nextx; 00399 besty = nexty; 00400 } 00401 } 00402 00403 if(bestx == bx && besty == by) { /* If we've found the last hex, record */ 00404 lastx = currx; /* the current hex as the last */ 00405 lasty = curry; /* intervening hex, save currx/y, */ 00406 currx = bestx; /* and jump to the end of the loop */ 00407 curry = besty; 00408 continue; 00409 } 00410 00411 /* ********************************************************* */ 00412 /* HERE is where you put the test code for intervening hexes */ 00413 /* ********************************************************* */ 00414 Store_Hex(bestx, besty); 00415 /* ********************************************************* */ 00416 00417 currx = bestx; /* Reset the curr hex for the next iteration */ 00418 curry = besty; 00419 currdist = bestdist; 00420 bestdist = enddist; /* reset to worst possible value */ 00421 00422 } 00423 00424 /* **************************************************** */ 00425 /* HERE is where you put the test code for the LAST hex */ 00426 /* **************************************************** */ 00427 Store_Hex(currx, curry); 00428 /* ********************************************************* */ 00429 *result = found_coords; 00430 return found_count; 00431 }
hexlosmap_info losmap [static] |
Definition at line 24 of file map.los.c.
Referenced by CalculateLOSMap(), get_lrshexstr(), hexlit(), litemark_map(), LOSMap_Hex2Index(), MechSeesRange(), set_hexlosall(), set_hexlosinfo(), set_sliteinfo(), show_lrs_map(), and sketch_tac_map().