#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/file.h>
#include "mech.h"
#include "p.map.obj.h"
#include "p.mech.sensor.h"
#include "p.mech.los.h"
#include "p.mech.utils.h"
Include dependency graph for mech.los.c:
Go to the source code of this file.
Functions | |
float | ActualElevation (MAP *map, int x, int y, MECH *mech) |
int | TraceLOS (MAP *map, int ax, int ay, int bx, int by, lostrace_info **result) |
int | CalculateLOSFlag (MECH *mech, MECH *target, MAP *map, int x, int y, int ff, float hexRange) |
int | AddTerrainMod (MECH *mech, MECH *target, MAP *map, float hexRange, int wAmmoMode) |
int | InLineOfSight_NB (MECH *mech, MECH *target, int x, int y, float hexRange) |
int | InLineOfSight (MECH *mech, MECH *target, int x, int y, float hexRange) |
void | mech_losemit (dbref player, MECH *mech, char *buffer) |
Definition at line 35 of file mech.los.c.
References CLASS_DS, CLASS_MECH, Elevation, Fallen, IsDS, MechDugIn, MechMove, MechType, MechZ, and MOVE_NONE.
Referenced by CalculateLOSFlag().
00036 { 00037 00038 if(!map) 00039 return 0.0; 00040 if(!mech) 00041 return (float) (Elevation(map, x, y) + 0.1); 00042 if(MechType(mech) == CLASS_MECH && !Fallen(mech)) 00043 return (float) MechZ(mech) + 1.5; 00044 else if(MechMove(mech) == MOVE_NONE) 00045 return (float) MechZ(mech) + 1.5; 00046 else if(IsDS(mech)) 00047 return (float) MechZ(mech) + 2.5 + (MechType(mech) == 00048 CLASS_DS ? 0 : 2); 00049 if(MechDugIn(mech)) 00050 return (float) MechZ(mech) + 0.1; 00051 return (float) MechZ(mech) + 0.5; 00052 }
Definition at line 282 of file mech.los.c.
References MECHLOSFLAG_PARTIAL, MechStatus, MechToMech_LOSFlag, PARTIAL_COVER, and Sensor_ToHitBonus().
Referenced by FindNormalBTH(), and FireSpot().
00284 { 00285 /* Possibly do a quickie check only */ 00286 if(mech && target) { 00287 if(MechToMech_LOSFlag(map, mech, target) & MECHLOSFLAG_PARTIAL) 00288 MechStatus(target) |= PARTIAL_COVER; 00289 else 00290 MechStatus(target) &= ~PARTIAL_COVER; 00291 00292 return Sensor_ToHitBonus(mech, target, 00293 MechToMech_LOSFlag(map, mech, target), 00294 map->maplight, hexRange, wAmmoMode); 00295 } 00296 return 0; 00297 }
int CalculateLOSFlag | ( | MECH * | mech, | |
MECH * | target, | |||
MAP * | map, | |||
int | x, | |||
int | y, | |||
int | ff, | |||
float | hexRange | |||
) |
Definition at line 60 of file mech.los.c.
References AA_TECH, ActualElevation(), BOUNDED(), BRIDGE, CLASS_MECH, Elevation, Fallen, FIRE, GetRTerrain, GetTerrain, HEAVY_FOREST, HIGHWATER, ICE, InWater, IsWater, LIGHT_FOREST, MAP::map_height, MAP::map_width, MAP::maxvis, MECHLOSFLAG_BLOCK, MECHLOSFLAG_FIRE, MECHLOSFLAG_MNTN, MECHLOSFLAG_PARTIAL, MECHLOSFLAG_SEEC2, MECHLOSFLAG_SEEN, MECHLOSFLAG_SMOKE, MECHLOSFLAG_WATER, MECHLOSFLAG_WOOD, MECHLOSMAX_WATER, MECHLOSMAX_WOOD, MechMove, MechRTerrain, MechSpecials, MechType, MechX, MechY, MechZ, MOUNTAINS, MOVE_HOVER, SMOKE, TraceLOS(), WATER, WaterBeast, and lostrace_info::y.
Referenced by InLineOfSight(), and update_LOSinfo().
00062 { 00063 int new_flag = (ff & (MECHLOSFLAG_SEEN)) + MECHLOSFLAG_SEEC2; 00064 int woods_count = 0; 00065 int water_count = 0; 00066 int height, i; 00067 int pos_x, pos_y; 00068 float pos_z, z_inc, end_z; 00069 int terrain; 00070 int dopartials = 0; 00071 int underwater, bothworlds, t_underwater, t_bothworlds; 00072 int uwatercount = 0, coordcount; 00073 lostrace_info *coords; 00074 00075 #ifndef BT_PARTIAL 00076 float partial_z, p_z_inc; 00077 #endif 00078 00079 /* A Hex target off the map? Don't bother */ 00080 if(!target && ((x < 0 || y < 0 || x >= map->map_width || 00081 y >= map->map_height))) 00082 return new_flag + MECHLOSFLAG_BLOCK; 00083 00084 /* Outside max sensor range in the worst case? Don't bother. */ 00085 if(hexRange > (((MechSpecials(mech) & AA_TECH) || (target && 00086 (MechSpecials(target) & 00087 AA_TECH))) ? 180 : 00088 map->maxvis)) 00089 return new_flag + MECHLOSFLAG_BLOCK; 00090 00091 /* We start at (MechX(mech), MechY(mech)) and wind up at (x,y) */ 00092 pos_x = MechX(mech); 00093 pos_y = MechY(mech); 00094 pos_z = ActualElevation(map, pos_x, pos_y, mech); 00095 end_z = ActualElevation(map, x, y, target); 00096 00097 /* Definition of 'both worlds': According to FASA, if a mech is half 00098 submerged, or a sub is surfaced, or any naval or hover is on top 00099 of the water, it can see in both the underwater and overwater 'worlds'. 00100 In other words, it'll never get a block from the water/air interface. 00101 Neither will anything get such a block against it. That's what the 00102 'both worlds' variables test for. */ 00103 00104 if(end_z > 10 && pos_z > 10) 00105 return new_flag; 00106 bothworlds = IsWater(MechRTerrain(mech)) && /* Can we be in both worlds? */ 00107 (((MechType(mech) == CLASS_MECH) && (MechZ(mech) == -1)) || 00108 ((WaterBeast(mech)) && (MechZ(mech) == 0)) || 00109 ((MechMove(mech) == MOVE_HOVER) && (MechZ(mech) == 0))); 00110 underwater = InWater(mech) && (pos_z < 0.0); 00111 00112 /* Ice hex targeting special case */ 00113 if(!target && !underwater && GetRTerrain(map, x, y) == ICE) 00114 end_z = 0.0; 00115 00116 if(target) { 00117 /* What about him? Both worlds? Or flat out underwater? */ 00118 t_bothworlds = IsWater(MechRTerrain(target)) && 00119 (((MechType(target) == CLASS_MECH) && (MechZ(target) == -1)) || 00120 ((WaterBeast(target)) && (MechZ(target) == 0)) || 00121 ((MechMove(target) == MOVE_HOVER) && (MechZ(target) == 0))); 00122 00123 t_underwater = InWater(target) && (end_z < 0.0); 00124 } else { 00125 if(GetRTerrain(map, x, y) == ICE) 00126 t_bothworlds = 1; 00127 else 00128 t_bothworlds = 0; 00129 t_underwater = (end_z < 0.0); /* Is the hex underwater? */ 00130 } 00131 00132 /* And now we look once more to make sure we aren't wasting our time */ 00133 if(((underwater) && !(t_underwater)) || 00134 ((t_underwater) && !(underwater))) { 00135 return new_flag + MECHLOSFLAG_BLOCK; 00136 } 00137 00138 /* Worth our time to mess with figuring partial cover? */ 00139 if(target && mech) 00140 dopartials = (MechType(target) == CLASS_MECH) && (!Fallen(target)); 00141 00142 /*Same hex is always LoS */ 00143 if((x == pos_x) && (y == pos_y)) 00144 return new_flag; 00145 00146 /* Special cases are out of the way, looks like we have to do actual work. */ 00147 coordcount = TraceLOS(map, pos_x, pos_y, x, y, &coords); 00148 if(coordcount > 0) { 00149 z_inc = (float) (end_z - pos_z) / coordcount; 00150 } else { 00151 z_inc = 0; /* In theory, this should never happen. */ 00152 } 00153 00154 #ifndef BT_PARTIAL 00155 partial_z = 0; 00156 p_z_inc = (float) 1 / coordcount; 00157 #endif 00158 00159 if(coordcount > 0) { /* not in same hex ; in same hex, you see always */ 00160 for(i = 0; i < coordcount; i++) { 00161 pos_z += z_inc; 00162 #ifndef BT_PARTIAL 00163 partial_z += p_z_inc; 00164 #endif 00165 if(coords[i].x < 0 || coords[i].x >= map->map_width || 00166 coords[i].y < 0 || coords[i].y >= map->map_height) 00167 continue; 00168 /* Should be possible to see into water.. perhaps. But not 00169 on vislight */ 00170 terrain = GetRTerrain(map, coords[i].x, coords[i].y); 00171 /* get the current height */ 00172 height = Elevation(map, coords[i].x, coords[i].y); 00173 00174 /* If you, persoanlly, are underwater, the only way you can see someone 00175 if if they are underwater or in both worlds AND your LoS passes thru 00176 nothing but water hexes AND your LoS doesn't go thru the sea floor */ 00177 if(underwater) { 00178 00179 /* LoS hits sea floor */ 00180 if(!(IsWater(terrain)) || (terrain != BRIDGE && 00181 height >= pos_z)) { 00182 new_flag |= MECHLOSFLAG_BLOCK; 00183 return new_flag; 00184 } 00185 00186 /* LoS pops out of water, AND we're not tracing to half-submerged mech's head */ 00187 if(!t_bothworlds && pos_z > 0.0) { 00188 new_flag |= MECHLOSFLAG_BLOCK; 00189 return new_flag; 00190 } 00191 00192 /* uwatercount = # hexes LoS travel UNDERWATER */ 00193 if(pos_z <= 0.0) 00194 uwatercount++; 00195 water_count++; 00196 } else { /* Viewer is not underwater */ 00197 /* keep track of how many wooded hexes we cross */ 00198 if(pos_z < (height + 2)) { 00199 switch (GetTerrain(map, coords[i].x, coords[i].y)) { 00200 case SMOKE: 00201 if(i < coordcount - 1) 00202 new_flag |= MECHLOSFLAG_SMOKE; 00203 break; 00204 case FIRE: 00205 if(i < coordcount - 1) 00206 new_flag |= MECHLOSFLAG_FIRE; 00207 break; 00208 } 00209 switch (terrain) { 00210 case LIGHT_FOREST: 00211 case HEAVY_FOREST: 00212 if(i < coordcount - 1) 00213 woods_count += (terrain == LIGHT_FOREST) ? 1 : 2; 00214 break; 00215 case HIGHWATER: 00216 water_count++; 00217 break; 00218 case ICE: 00219 if(pos_z < -0.0) { 00220 new_flag |= MECHLOSFLAG_BLOCK; 00221 return new_flag; 00222 } 00223 water_count++; 00224 break; 00225 case WATER: 00226 00227 /* LoS goes INTO water and we're not tracing to a target in both worlds */ 00228 if(!bothworlds && (pos_z < 0.0)) { 00229 new_flag |= MECHLOSFLAG_BLOCK; 00230 return new_flag; 00231 } 00232 00233 /* Hexes in LoS that are phsyically underwater */ 00234 if(pos_z < 0.0) 00235 uwatercount++; 00236 water_count++; 00237 break; 00238 case MOUNTAINS: 00239 if(i < coordcount - 1) 00240 new_flag |= MECHLOSFLAG_MNTN; 00241 break; 00242 } 00243 } 00244 /* make this the new 'current hex' */ 00245 if(height >= pos_z && terrain != BRIDGE) { 00246 new_flag |= MECHLOSFLAG_BLOCK; 00247 return new_flag; 00248 } 00249 #ifndef BT_PARTIAL 00250 else if(dopartials && height >= (pos_z - partial_z)) 00251 new_flag |= MECHLOSFLAG_PARTIAL; 00252 #endif 00253 } 00254 } 00255 } 00256 /* Then, we check the hex before target hex */ 00257 #ifdef BT_PARTIAL 00258 if(coordcount >= 2) 00259 if(dopartials) { 00260 if(MechZ(target) >= MechZ(mech) && 00261 (Elevation(map, coords[coordcount - 2].x, 00262 coords[coordcount - 2].y) == (MechZ(target) + 1))) 00263 new_flag |= MECHLOSFLAG_PARTIAL; 00264 if(MechZ(target) == -1 && MechRTerrain(target) == WATER) 00265 new_flag |= MECHLOSFLAG_PARTIAL; 00266 } 00267 #endif 00268 00269 water_count = BOUNDED(0, water_count, MECHLOSMAX_WATER - 1); 00270 woods_count = BOUNDED(0, woods_count, MECHLOSMAX_WOOD - 1); 00271 new_flag += MECHLOSFLAG_WOOD * woods_count; 00272 new_flag += MECHLOSFLAG_WATER * water_count; 00273 00274 /* Block EM after 2, Vis/IR after 6 */ 00275 if(uwatercount > 2) 00276 new_flag |= MECHLOSFLAG_MNTN; 00277 if(uwatercount > 6) 00278 new_flag |= MECHLOSFLAG_FIRE; 00279 return new_flag; 00280 }
Definition at line 312 of file mech.los.c.
References CalculateLOSFlag(), CLAIRVOYANT, MAP::cloudbase, getMap(), InWeaponArc(), MAP::LOSinfo, MAP::map_height, MAP::map_width, MapCoordToRealCoord(), MECH::mapindex, MAP::maplight, MECH::mapnumber, MAP::mapvis, mech_notify(), MechCritStatus, MechFX, MechFY, MECHLOSFLAG_BLOCK, MECHLOSFLAG_SEEN, MECHLOSFLAG_SEESP, MECHLOSFLAG_SEESS, MECHPILOT, MechToMech_LOSFlag, MECH::mynum, SendError, Sensor_CanSee(), and tprintf().
Referenced by auto_radio_command_report(), DisplayTarget(), find_mech_in_hex(), findC3RangeWithNetwork(), FireSpot(), fun_btlosm2m(), InLineOfSight_NB(), mech_attachcables(), mech_bearing(), mech_c3_join_leave(), mech_c3i_join_leave(), mech_contacts(), mech_detachcables(), mech_embark(), mech_hide_event(), mech_jump(), mech_lock_event(), mech_pickup(), mech_radio(), mech_range(), mech_report(), mech_scan(), mech_settarget(), mech_spot(), mech_vector(), mech_view(), MechFireBroadcast(), MechLOSBroadcast(), MechLOSBroadcasti(), mechSeenByNetwork(), MechSeesHexF(), navigate_sketch_mechs(), parse_tacargs(), ScrambleInfraAndLiteAmp(), show_lrs_map(), showNetworkTargets(), and sketch_tac_mechs().
00313 { 00314 MAP *map; 00315 float x1, y1; 00316 int arc; 00317 int losflag; 00318 00319 map = getMap(mech->mapindex); 00320 if(!map) { 00321 mech_notify(mech, MECHPILOT, 00322 "You are on an invalid map! Map index reset!"); 00323 SendError(tprintf("InLineOfSight:invalid map:Mech %d Index %d", 00324 mech->mynum, mech->mapindex)); 00325 mech->mapindex = -1; 00326 return 0; 00327 } 00328 if(x < 0 || y < 0 || y >= map->map_height || x >= map->map_width) { 00329 SendError(tprintf("x:%d y:%d out of bounds for #%d (LOS check)", x, 00330 y, mech ? mech->mynum : -1)); 00331 } 00332 00333 /* Possibly do a quickie check only */ 00334 if(MechCritStatus(mech) & CLAIRVOYANT) 00335 return 1; 00336 00337 if(target) { 00338 x1 = MechFX(target); 00339 y1 = MechFY(target); 00340 } else 00341 MapCoordToRealCoord(x, y, &x1, &y1); 00342 arc = InWeaponArc(mech, x1, y1); 00343 00344 if(mech && target) { 00345 #ifndef ADVANCED_LOS 00346 losflag = MechToMech_LOSFlag(map, mech, target); 00347 if(Sensor_CanSee(mech, target, &losflag, arc, hexRange, map->mapvis, 00348 map->maplight, map->cloudbase)) { 00349 map->LOSinfo[mech->mapnumber][target->mapnumber] |= 00350 (MECHLOSFLAG_SEEN | MECHLOSFLAG_SEESP | MECHLOSFLAG_SEESS); 00351 return 1; 00352 } else { 00353 map->LOSinfo[mech->mapnumber][target->mapnumber] &= 00354 ~(MECHLOSFLAG_SEEN | MECHLOSFLAG_SEESP | MECHLOSFLAG_SEESS); 00355 return 0; 00356 } 00357 #else 00358 if(MechToMech_LOSFlag(map, mech, target) & (MECHLOSFLAG_SEESP | 00359 MECHLOSFLAG_SEESS)) 00360 return MechToMech_LOSFlag(map, mech, target) & 00361 (MECHLOSFLAG_SEESP | MECHLOSFLAG_SEESS | MECHLOSFLAG_BLOCK); 00362 #endif 00363 return 0; 00364 } 00365 losflag = CalculateLOSFlag(mech, NULL, map, x, y, 0, hexRange); 00366 return Sensor_CanSee(mech, NULL, &losflag, arc, hexRange, map->mapvis, 00367 map->maplight, map->cloudbase); 00368 }
Definition at line 299 of file mech.los.c.
References InLineOfSight(), and MECHLOSFLAG_BLOCK.
Referenced by checkTAG(), FindBSuitTarget(), fun_bthexlos(), fun_btid2db(), fun_btlosm2m(), GetMechToMechID(), mech_charge(), mech_contacts(), mech_report(), mech_scan(), mech_tag(), mech_view(), mechSeenByNetwork(), PhysicalAttack(), showNetworkTargets(), and SwarmHitTarget().
00300 { 00301 int i; 00302 00303 if(mech == target) 00304 return 1; 00305 00306 i = InLineOfSight(mech, target, x, y, hexRange); 00307 if(i & MECHLOSFLAG_BLOCK) 00308 return 0; 00309 return i; 00310 }
Definition at line 370 of file mech.los.c.
References cch, MECH_USUALSP, MechLOSBroadcast(), and notify.
00371 { 00372 cch(MECH_USUALSP); 00373 MechLOSBroadcast(mech, buffer); 00374 notify(player, "Broadcast done."); 00375 }
int TraceLOS | ( | MAP * | map, | |
int | ax, | |||
int | ay, | |||
int | bx, | |||
int | by, | |||
lostrace_info ** | result | |||
) |
Definition at line 208 of file mech.lostracer.c.
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 }