00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "mech.h"
00011 #include "map.h"
00012 #define _MECH_SENSOR_C
00013 #include "p.mech.ecm.h"
00014 #include "p.mech.tag.h"
00015 #include "mech.events.h"
00016 #include "mech.sensor.h"
00017 #include "autopilot.h"
00018 #include "p.mech.utils.h"
00019 #include "p.mech.lite.h"
00020 #include "p.mech.los.h"
00021 #include "p.btechstats.h"
00022
00023 #define SEE_SENSOR_PRIMARY 1
00024 #define SEE_SENSOR_SECONDARY 2
00025
00026 int Sensor_ToHitBonus(MECH * mech, MECH * target, int flag, int maplight,
00027 float range, int wAmmoMode)
00028 {
00029 int bth1, bth2;
00030 int wLightMod = (wAmmoMode & AC_INCENDIARY_MODE) ? 1 : 0;
00031 MAP *map = getMap(mech->mapindex);
00032
00033 maplight = maplight + wLightMod;
00034
00035 if(maplight < 0)
00036 maplight = 0;
00037
00038 if(maplight > 2)
00039 maplight = 2;
00040
00041 if(!(flag & (MECHLOSFLAG_SEESP | MECHLOSFLAG_SEESS)))
00042 return 10000;
00043 if(!(flag & MECHLOSFLAG_SEESP)) {
00044 bth2 = 1 + sensors[(int) MechSensor(mech)[1]].tohitbonus_func(mech,
00045 target,
00046 map,
00047 flag,
00048 maplight);
00049 #ifdef SENSOR_BTH_DEBUG
00050 SendDebug(tprintf("%d: BTH S+%d", mech->mynum, bth2));
00051 #endif
00052 return bth2;
00053 }
00054 if(!(flag & MECHLOSFLAG_SEESS) ||
00055 (MechSensor(mech)[0] == MechSensor(mech)[1])) {
00056 bth1 = sensors[(int) MechSensor(mech)[0]].tohitbonus_func(mech,
00057 target, map,
00058 flag,
00059 maplight);
00060 #ifdef SENSOR_BTH_DEBUG
00061 SendDebug(tprintf("%d: BTH P+%d", mech->mynum, bth1));
00062 #endif
00063 return bth1;
00064 }
00065 bth1 = sensors[(int) MechSensor(mech)[0]].tohitbonus_func(mech, target,
00066 map, flag,
00067 maplight);
00068 bth2 =
00069 1 + sensors[(int) MechSensor(mech)[1]].tohitbonus_func(mech, target,
00070 map, flag,
00071 maplight);
00072 #ifdef SENSOR_BTH_DEBUG
00073 SendDebug(tprintf("%d: BTH +%d/+%d", mech->mynum, bth1, bth2));
00074 #endif
00075 return MIN(bth1, bth2);
00076 }
00077
00078 int Sensor_CanSee(MECH * mech, MECH * target, int *flag, int arc,
00079 float range, int mapvis, int maplight, int cloudbase)
00080 {
00081 int i, j = 0, sn;
00082 MAP *map = getMap(mech->mapindex);
00083
00084 if(!(*flag & MECHLOSFLAG_SEEC2))
00085 return 0;
00086 if(target && (MechCritStatus(target) & INVISIBLE))
00087 return 0;
00088
00089 if(MechSensor(mech)[0] != MechSensor(mech)[1]) {
00090 #define MaxVis(mech,sensor) ((sensors[sensor].maxvis*(((sensor)>=2 && MechMove(mech)==MOVE_NONE)?140:100)) / 100)
00091 #define MaxVar(mech,sensor) sensors[sensor].maxvvar
00092 #define MAXVR(mech,sensor) MaxVis(mech,sensor) - MaxVar(mech, sensor)
00093
00094 for(i = 0; i < 2; i++) {
00095 sn = MechSensor(mech)[i];
00096
00097
00098 if(!sensors[sn].fullvision && !(arc & (FORWARDARC | TURRETARC)) &&
00099 !Sees360(mech))
00100 continue;
00101 if(MaxVis(mech, sn) < range)
00102 continue;
00103
00104
00105
00106
00107
00108 if(target) {
00109 if(cloudbase && sn < 3 && ((MechZ(mech) < cloudbase)
00110 ? (MechZ(target) >=
00111 cloudbase) : (MechZ(target)
00112 < cloudbase)))
00113 continue;
00114 } else {
00115 if(cloudbase && MechZ(mech) > cloudbase)
00116 continue;
00117 }
00118
00119 if(!sensors[sn].cansee_func(mech, target, map, range, *flag))
00120 continue;
00121
00122 if(!sensors[sn].seechance_func(target, map, sn, range, mapvis,
00123 maplight))
00124 continue;
00125
00126 if(MaxVar(mech, sn) && (MAXVR(mech, sn)) < range)
00127 if(((MAXVR(mech, sn)) + (MechVisMod(mech) * (MaxVar(mech,
00128 sn) +
00129 1)) / 100) <
00130 range)
00131 continue;
00132 j += (i + 1);
00133 }
00134 return j;
00135 }
00136 sn = MechSensor(mech)[0];
00137 if(MaxVis(mech, sn) < range)
00138 return 0;
00139 if(cloudbase && target && sn < 3 &&
00140 ((MechZ(mech) < cloudbase) ? (MechZ(target) >= cloudbase)
00141 : (MechZ(target) < cloudbase)))
00142 return 0;
00143 if(!sensors[sn].cansee_func(mech, target, map, range, *flag))
00144 return 0;
00145 if(!sensors[sn].seechance_func(target, map, sn, range, mapvis, maplight))
00146 return 0;
00147 if(MaxVar(mech, sn) && (MAXVR(mech, sn)) < range)
00148 if(((MAXVR(mech, sn)) + MechVisMod(mech) * (MaxVar(mech,
00149 sn) + 1) / 100) <
00150 range)
00151 return 0;
00152 return 3;
00153 }
00154
00155 int Sensor_ArcBaseChance(int type, int arc)
00156 {
00157 int base = 100;
00158
00159 switch (type) {
00160 case CLASS_MW:
00161 if(arc & (LSIDEARC | RSIDEARC | REARARC))
00162 return 0;
00163 break;
00164 case CLASS_BSUIT:
00165 case CLASS_MECH:
00166 if(arc & (LSIDEARC | RSIDEARC))
00167 base = 70;
00168 else if(arc & REARARC)
00169 base = 40;
00170 break;
00171 default:
00172 if(arc & (LSIDEARC | RSIDEARC))
00173 base = 80;
00174 else if(arc & REARARC)
00175 base = 50;
00176 if(arc & TURRETARC)
00177 base += 15;
00178 break;
00179 }
00180 return base;
00181 }
00182
00183 extern int bth_modifier[];
00184
00185
00186 int Sensor_DriverBaseChance(MECH * mech)
00187 {
00188 int i = 1;
00189
00190 if(MechPer(mech) <= 2)
00191 i = 36;
00192 else if(MechPer(mech) >= 12)
00193 i = 1;
00194 else
00195 i = (36 - bth_modifier[MechPer(mech) - 2]);
00196 return 64 + i;
00197 }
00198
00199 int Sensor_Sees(MECH * mech, MECH * target, int f, int arc, float range,
00200 int snum, int chance_divisor, int mapvis, int maplight)
00201 {
00202 MAP *map = getMap(mech->mapindex);
00203 int chance = (Sensor_ArcBaseChance(MechType(mech), arc) * ((target &&
00204 MechTeam(mech)
00205 !=
00206 MechTeam
00207 (target)) ?
00208 Sensor_DriverBaseChance
00209 (mech) : 100))
00210 / 100;
00211 int ch2 = sensors[snum].seechance_func(target, map, snum, range,
00212 mapvis, maplight);
00213
00214 if(!ch2 || !sensors[snum].cansee_func(mech, target, map, range, f))
00215 return 0;
00216 if(target && IsDS(target))
00217 chance = chance * 4;
00218 if(target && MechCritStatus(target) & HIDDEN &&
00219 MechTeam(mech) != MechTeam(target)) {
00220
00221 if(sensors[snum].matchletter[0] == 'B' &&
00222 (MechInfantrySpecials(target) & STEALTH_TECH) &&
00223 (!(MechInfantrySpecials(target) & CS_PURIFIER_STEALTH_TECH)))
00224 return 0;
00225
00226 if(ch2 <= 100) {
00227 if(range > 5)
00228 return 0;
00229 chance = chance / 4;
00230 }
00231 }
00232 if(range < 3 || Number(1, 10000) < ((chance * ch2) / chance_divisor)) {
00233 if(target && In_Character(mech->mynum) &&
00234 In_Character(target->mynum) && MechTeam(mech) != MechTeam(target))
00235 if(!Number(0, 5))
00236 MadePerceptionRoll(mech, -2);
00237 return 1;
00238 }
00239 return 0;
00240 }
00241
00242
00243
00244
00245
00246
00247
00248
00249 int Sensor_SeesNow(MECH * mech, MECH * target, int f, int arc, float range,
00250 int mapvis, int maplight)
00251 {
00252 int i, sn;
00253
00254 if(MechSensor(mech)[0] != MechSensor(mech)[1]) {
00255
00256 for(i = 0; i < 2; i++) {
00257 sn = MechSensor(mech)[i];
00258
00259 if(!sensors[sn].fullvision && !(arc & (FORWARDARC | TURRETARC)) &&
00260 !Sees360(mech))
00261 continue;
00262 if(MaxVis(mech, sn) < range)
00263 continue;
00264 if(Sensor_Sees(mech, target, f, arc, range, sn, i + 1, mapvis,
00265 maplight))
00266 return (i + 1);
00267 }
00268 return 0;
00269 }
00270 sn = MechSensor(mech)[0];
00271 if(MaxVis(mech, sn) < range)
00272 return 0;
00273 return (Sensor_Sees(mech, target, f, arc, range, sn, 1, mapvis,
00274 maplight));
00275 return 3;
00276 }
00277
00278 char *my_dump_flag(int i)
00279 {
00280 int j;
00281 static char buf[MBUF_SIZE];
00282
00283 strcpy(buf, "");
00284 for(j = 0; j < 32; j++)
00285 if(i & (1 << j)) {
00286 if(buf[0] == 0)
00287 sprintf(buf, "%d", j);
00288 else
00289 sprintf(buf + strlen(buf), ",%d", j);
00290 }
00291 return buf;
00292 }
00293
00294 #define AUTOCON_LONG 0x01
00295 #define AUTOCON_WARN 0x02
00296 #define AUTOCON_SHORT 0x04
00297
00298 static int valid_to_notice(MECH * mech, MECH * targ, int los)
00299 {
00300 int bf = (mech->brief / 4);
00301 int foe;
00302
00303 if((los < 0 && MechSeemsFriend(mech, targ)) ||
00304 (los > 0 && MechTeam(mech) == MechTeam(targ)))
00305 foe = 0;
00306 else
00307 foe = AUTOCON_WARN;
00308
00309 switch (bf) {
00310 case 0:
00311 return AUTOCON_LONG | foe;
00312 case 1:
00313 return AUTOCON_SHORT | foe;
00314 case 2:
00315 return foe ? (AUTOCON_LONG | foe) : 0;
00316 case 3:
00317 return foe ? (AUTOCON_SHORT | foe) : 0;
00318 case 4:
00319 return AUTOCON_SHORT;
00320 case 5:
00321 return foe ? AUTOCON_SHORT : 0;
00322 case 6:
00323 default:
00324 return 0;
00325 }
00326 }
00327
00328 void Sensor_DoWeSeeNow(MECH * mech, unsigned short *fl, float range, int x,
00329 int y, MECH * target, int mapvis, int maplight,
00330 int cloudbase, int seeanew, int wlf)
00331 {
00332 int arc;
00333 float x1, y1;
00334 int sc, sl, st;
00335 int f = *fl;
00336 char buf[MBUF_SIZE];
00337
00338 if(!Started(mech))
00339 return;
00340 if(target) {
00341 x1 = MechFX(target);
00342 y1 = MechFY(target);
00343 if(MechZ(mech) >= ATMO_Z && MechZ(target) >= ATMO_Z)
00344 range = range / 3;
00345 } else
00346 MapCoordToRealCoord(x, y, &x1, &y1);
00347 arc = InWeaponArc(mech, x1, y1);
00348 if(f & MECHLOSFLAG_SEEN) {
00349 if((sl =
00350 Sensor_CanSee(mech, target, &f, arc, range, mapvis,
00351 maplight, cloudbase))) {
00352 if(sl & 1)
00353 f |= MECHLOSFLAG_SEESP;
00354 if(sl & 2)
00355 f |= MECHLOSFLAG_SEESS;
00356 }
00357 if(!(f & (MECHLOSFLAG_SEESP | MECHLOSFLAG_SEESS))) {
00358 if(MechTeam(mech) != MechTeam(target))
00359 MechNumSeen(mech) = MAX(0, MechNumSeen(mech) - 1);
00360 f &= ~MECHLOSFLAG_SEEN;
00361 if(!MechIsObservator(mech)
00362 && (Started(target) || SeeWhenShutdown(target)
00363 || MechAutoconSD(mech))
00364 && (st = valid_to_notice(mech, target, wlf)) && seeanew < 3) {
00365 if(st & AUTOCON_WARN)
00366 strcpy(buf, "%cy");
00367 else
00368 buf[0] = 0;
00369 if(st & AUTOCON_SHORT)
00370 sprintf(buf + strlen(buf), "Lost: %s, %s arc.",
00371 GetMechToMechID_base(mech, target, wlf),
00372 GetArcID(mech, arc));
00373 else
00374 sprintf(buf,
00375 "You have lost %s from your scanners. It was last in your %s arc.",
00376 GetMechToMechID_base(mech, target, wlf),
00377 GetArcID(mech, arc));
00378 if(st & AUTOCON_WARN)
00379 strcat(buf, "%cn");
00380 mech_notify(mech, MECHALL, buf);
00381 }
00382 if((MechStatus(mech) & LOCK_TARGET) &&
00383 target->mynum == MechTarget(mech)) {
00384 mech_notify(mech, MECHALL,
00385 "Weapon system reports the lock has been lost.");
00386 LoseLock(mech);
00387 }
00388 #ifdef SENSOR_DEBUG
00389 sprintf(buf, "Notice: #%d lost #%d (Sensor: %d, Flag: %s)",
00390 mech->mynum, target->mynum,
00391 (f & (MECHLOSFLAG_SEESP | MECHLOSFLAG_SEESS)),
00392 my_dump_flag(f));
00393 SendSensor(buf);
00394 #endif
00395 MechPNumSeen(mech)++;
00396 }
00397 *fl = f;
00398 return;
00399 }
00400 if((sc =
00401 Sensor_CanSee(mech, target, &f, arc, range, mapvis, maplight,
00402 cloudbase))) {
00403 if(!seeanew) {
00404 MechPNumSeen(mech)++;
00405 *fl = f;
00406 return;
00407 }
00408 if((sl =
00409 Sensor_SeesNow(mech, target, f, arc, range, mapvis, maplight))) {
00410 if(sc & 1)
00411 f |= MECHLOSFLAG_SEESP;
00412 if(sc & 2)
00413 f |= MECHLOSFLAG_SEESS;
00414 }
00415 if((f & (MECHLOSFLAG_SEESP | MECHLOSFLAG_SEESS))) {
00416 if(MechTeam(mech) != MechTeam(target)) {
00417 MechNumSeen(mech)++;
00418 UnZombifyMech(mech);
00419 }
00420 f |= MECHLOSFLAG_SEEN;
00421 *fl = f;
00422 if(!MechIsObservator(mech)
00423 && (Started(target) || SeeWhenShutdown(target)
00424 || MechAutoconSD(mech))
00425 && (st = valid_to_notice(mech, target, -1)) && seeanew < 2) {
00426 if(st & AUTOCON_WARN)
00427 strcpy(buf, "%cr");
00428 else
00429 buf[0] = 0;
00430 if(st & AUTOCON_SHORT)
00431 sprintf(buf + strlen(buf), "Seen: %s, %s arc.",
00432 GetMechToMechID(mech, target), GetArcID(mech,
00433 arc));
00434 else
00435 sprintf(buf + strlen(buf),
00436 "You notice %s in your %s arc.",
00437 GetMechToMechID(mech, target), GetArcID(mech,
00438 arc));
00439 if(st & AUTOCON_WARN)
00440 strcat(buf, "%cn");
00441 mech_notify(mech, MECHALL, buf);
00442 }
00443 if(MechTeam(mech) != MechTeam(target))
00444 StopHiding(target);
00445 #ifdef SENSOR_DEBUG
00446 sprintf(buf, "Notice: #%d saw #%d (Sensor: %d, Flag: %s C:%d)",
00447 mech->mynum, target->mynum,
00448 (f & (MECHLOSFLAG_SEESP | MECHLOSFLAG_SEESS)),
00449 my_dump_flag(f), seeanew);
00450 SendSensor(buf);
00451 #endif
00452 } else
00453 MechPNumSeen(mech)++;
00454 }
00455 *fl = f;
00456 }
00457
00458 void update_LOSinfo(dbref obj, MAP * map)
00459 {
00460 int i, j, fl;
00461 int mapvis = map->mapvis;
00462 int maplight = map->maplight;
00463 MECH *mech, *target;
00464 float range;
00465 int wlf;
00466
00467
00468 for(i = 0; i < map->first_free; i++) {
00469 mech = getMech(map->mechsOnMap[i]);
00470 if(!mech)
00471 continue;
00472 if(!Started(mech))
00473 continue;
00474 for(j = i + 1; j < map->first_free; j++)
00475 if(1) {
00476 target = getMech(map->mechsOnMap[j]);
00477 if(!target)
00478 continue;
00479 range = FaMechRange(mech, target);
00480 if(ECMEnabled(mech) || ECCMEnabled(mech) ||
00481 AngelECMEnabled(mech) || AngelECCMEnabled(mech))
00482 if(range < ECM_RANGE)
00483 checkECM(target);
00484 if(TAGTarget(mech) > 0)
00485 checkTAG(mech);
00486 if(MechStatus2(mech) & SLITE_ON)
00487 if(range < LITE_RANGE)
00488 cause_lite(mech, target);
00489 if(range > map->maxvis && MechZ(target) < 11 &&
00490 MechZ(mech) < 11) {
00491 map->LOSinfo[i][j] = MECHLOSFLAG_BLOCK;
00492 continue;
00493 }
00494 wlf = !(map->LOSinfo[i][j] & MECHLOSFLAG_BLOCK) &&
00495 ((map->LOSinfo[i][j] & MECHLOSFLAG_SEESP) ||
00496 (map->LOSinfo[i][j] & MECHLOSFLAG_SEESS));
00497 map->LOSinfo[i][j] = fl =
00498 CalculateLOSFlag(mech, target, map, MechX(target),
00499 MechY(target), map->LOSinfo[i]
00500 [j], (float) range);
00501
00502 #ifdef ADVANCED_LOS
00503 Sensor_DoWeSeeNow(mech, &map->LOSinfo[i][j], range, -1, -1,
00504 target, mapvis, maplight, map->cloudbase, 0,
00505 wlf);
00506 #endif
00507 }
00508 }
00509 for(i = 1; i < map->first_free; i++) {
00510 if(map->mechsOnMap[i] > 0);
00511 mech = getMech(map->mechsOnMap[i]);
00512 if(!mech)
00513 continue;
00514 if(!Started(mech))
00515 continue;
00516 for(j = 0; j < i; j++)
00517 if(1) {
00518 target = getMech(map->mechsOnMap[j]);
00519 if(!target)
00520 continue;
00521 range = FaMechRange(mech, target);
00522 if(ECMEnabled(mech) || ECCMEnabled(mech) ||
00523 AngelECMEnabled(mech) || AngelECCMEnabled(mech))
00524 if(range < ECM_RANGE)
00525 checkECM(target);
00526 if(TAGTarget(mech) > 0)
00527 checkTAG(mech);
00528 if(MechStatus2(mech) & SLITE_ON)
00529 if(range < LITE_RANGE)
00530 cause_lite(mech, target);
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552 if(range > map->maxvis && MechZ(target) < 11 &&
00553 MechZ(mech) < 11) {
00554 map->LOSinfo[i][j] = MECHLOSFLAG_BLOCK;
00555 continue;
00556 }
00557
00558 wlf = !(map->LOSinfo[i][j] & MECHLOSFLAG_BLOCK) &&
00559 ((map->LOSinfo[i][j] & MECHLOSFLAG_SEESP) ||
00560 (map->LOSinfo[i][j] & MECHLOSFLAG_SEESS));
00561 map->LOSinfo[i][j] = fl =
00562 CalculateLOSFlag(mech, target, map, MechX(target),
00563 MechY(target), map->LOSinfo[i]
00564 [j], (float) range);
00565 Sensor_DoWeSeeNow(mech, &map->LOSinfo[i][j], range, -1, -1,
00566 target, mapvis, maplight, map->cloudbase, 0,
00567 wlf);
00568 }
00569 }
00570 for(i = 0; i < map->first_free; i++)
00571 map->mechflags[i] = 0;
00572 }
00573
00574 void add_sensor_info(char *buf, MECH * mech, int sn, int verbose)
00575 {
00576 if(!verbose)
00577 sprintf(buf + strlen(buf), "(R:%s)", sensors[sn].range_desc);
00578 else {
00579 sprintf(buf + strlen(buf), "\n\tRange: %s\n\tBlocked by: %s",
00580 sensors[sn].range_desc, sensors[sn].block_desc);
00581 if(sensors[sn].special_desc)
00582 sprintf(buf + strlen(buf), "\n\tNotes: %s",
00583 sensors[sn].special_desc);
00584 }
00585 }
00586
00587 static char *sensor_mode_name(MECH * mech, int sn, int full, int verbose)
00588 {
00589 static char buf[MBUF_SIZE];
00590
00591 if(sn < 0 || sn >= NUM_SENSORS)
00592 return "None";
00593
00594 if(sensors[sn].fullvision) {
00595 sprintf(buf, "%s ", sensors[sn].sensorname);
00596 add_sensor_info(buf, mech, sn, verbose);
00597 } else {
00598 if(full || Sees360(mech))
00599 sprintf(buf, "%s in 360 degree scanning mode ",
00600 sensors[sn].sensorname);
00601 else
00602 sprintf(buf, "%s in 120 degree scanning mode (Forward arc) ",
00603 sensors[sn].sensorname);
00604 add_sensor_info(buf, mech, sn, verbose);
00605 }
00606 return buf;
00607 }
00608
00609 static void sensor_mode(MECH * mech, char *msg, dbref player, int p, int s,
00610 int verbose)
00611 {
00612 char buf[MBUF_SIZE];
00613 int i;
00614
00615 if(p != s) {
00616 for(i = 0; i < strlen(msg); i++)
00617 buf[i] = '-';
00618 buf[strlen(msg)] = 0;
00619 notify(player, msg);
00620 notify(player, buf);
00621 notify_printf(player, "Primary: %s", sensor_mode_name(mech, p,
00622 0, verbose));
00623 notify_printf(player, "Secondary: %s", sensor_mode_name(mech, s,
00624 0, verbose));
00625 } else
00626 notify_printf(player, "%s: %s", msg, sensor_mode_name(mech, p, 1,
00627 verbose));
00628 }
00629
00630 static int tmp_prim;
00631 static int tmp_sec;
00632 static int tmp_found;
00633
00634 static void sensor_check(MUXEVENT * e)
00635 {
00636 int d = ((int) e->data2);
00637
00638 tmp_prim = d / NUM_SENSORS;
00639 tmp_sec = d % NUM_SENSORS;
00640 tmp_found = 1;
00641 }
00642
00643 static char SensorInf[] = "vliesrbVLIESRB";
00644
00645 char *mechSensorInfo(int mode, MECH * mech, char *arg)
00646 {
00647 static char buffer[5];
00648
00649 tmp_found = 0;
00650 buffer[0] = SensorInf[(short) MechSensor(mech)[0]];
00651 buffer[1] = SensorInf[(short) MechSensor(mech)[1]];
00652 if(SensorChange(mech)) {
00653 muxevent_gothru_type_data(EVENT_SCHANGE, (void *) mech, sensor_check);
00654 if(tmp_found) {
00655 buffer[2] = SensorInf[tmp_prim + NUM_SENSORS];
00656 buffer[3] = SensorInf[tmp_sec + NUM_SENSORS];
00657 buffer[4] = '\0';
00658 return buffer;
00659 }
00660 }
00661 buffer[2] = '\0';
00662 return buffer;
00663 }
00664
00665 static void show_sensor(dbref player, MECH * mech, int verbose)
00666 {
00667
00668 tmp_found = 0;
00669 sensor_mode(mech, "Sensors", player, MechSensor(mech)[0],
00670 MechSensor(mech)[1], verbose);
00671 if(SensorChange(mech)) {
00672 muxevent_gothru_type_data(EVENT_SCHANGE, (void *) mech, sensor_check);
00673 if(tmp_found)
00674 sensor_mode(mech, "Wanted", player, tmp_prim, tmp_sec, 0);
00675 }
00676 }
00677
00678 static void mech_sensorchange_event(MUXEVENT * e)
00679 {
00680 int d = (int) e->data2;
00681 MECH *mech = (MECH *) e->data;
00682 int prim = d / NUM_SENSORS;
00683 int sec = d % NUM_SENSORS;
00684
00685 if(!Started(mech))
00686 return;
00687 MechSensor(mech)[0] = prim;
00688 MechSensor(mech)[1] = sec;
00689 mech_notify(mech, MECHALL, "As your sensors change, your lock clears.");
00690 MechTarget(mech) = -1;
00691 MarkForLOSUpdate(mech);
00692 }
00693
00694 int CanChangeTo(MECH * mech, int s)
00695 {
00696 MAP *map;
00697 int i;
00698
00699 if(!(map = getMap(mech->mapindex))) {
00700 mech_notify(mech, MECHALL, "Where are you? ;-)");
00701 return 0;
00702 }
00703
00704
00705 if((i = sensors[s].required_special)) {
00706
00707 if(sensors[s].specials_set == 1) {
00708 if((i > 0) == ((!(MechSpecials(mech) & abs(i))) != 0)) {
00709 mech_printf(mech, MECHALL,
00710 "You lack the %s sensors!",
00711 sensors[s].sensorname);
00712 return 0;
00713 }
00714 } else {
00715 if((i > 0) == ((!(MechSpecials2(mech) & abs(i))) != 0)) {
00716 mech_printf(mech, MECHALL,
00717 "You lack the %s sensors!",
00718 sensors[s].sensorname);
00719 return 0;
00720 }
00721 }
00722 }
00723
00724 if(sensors[s].min_light >= 0 && sensors[s].min_light > map->maplight) {
00725 if(!Destroyed(mech) && Started(mech))
00726 mech_printf(mech, MECHALL,
00727 "It's now too dark to use %s!",
00728 sensors[s].sensorname);
00729 return 0;
00730 }
00731 if(sensors[s].max_light >= 0 && sensors[s].max_light < map->maplight) {
00732 if(!Destroyed(mech) && Started(mech))
00733 mech_printf(mech, MECHALL,
00734 "The light's kinda too bright now to use %s!",
00735 sensors[s].sensorname);
00736 return 0;
00737 }
00738
00739 switch (sensors[s].attributeCheck) {
00740 case SENSOR_ATTR_SEISMIC:
00741 if((MechType(mech) == CLASS_MW) ||
00742 (MechType(mech) == CLASS_BSUIT) ||
00743 (MechType(mech) == CLASS_VEH_NAVAL) ||
00744 (MechMove(mech) == MOVE_HOVER)) {
00745 mech_printf(mech, MECHALL,
00746 "You lack the %s sensors!", sensors[s].sensorname);
00747 return 0;
00748 }
00749
00750 break;
00751 }
00752
00753 return 1;
00754 }
00755
00756 void sensor_light_availability_check(MECH * mech)
00757 {
00758 int p = MechSensor(mech)[0], s = MechSensor(mech)[1];
00759 int same = (p == s);
00760
00761 if(sensors[p].min_light >= 0 || sensors[p].max_light >= 0)
00762 if(!CanChangeTo(mech, p))
00763 MechSensor(mech)[0] = 0;
00764
00765 if(!same && (sensors[s].min_light >= 0 || sensors[s].max_light >= 0))
00766 if(!CanChangeTo(mech, s))
00767 MechSensor(mech)[1] = 0;
00768 }
00769
00770 static int set_sensor(MECH * mech, char ps, char ss)
00771 {
00772 int prim = -1, sec = -1;
00773 int i;
00774
00775 if(!Started(mech))
00776 return 0;
00777 for(i = 0; i < NUM_SENSORS; i++) {
00778 if(sensors[i].matchletter[0] == ps)
00779 prim = i;
00780 if(sensors[i].matchletter[0] == ss)
00781 sec = i;
00782 }
00783 if(prim < 0 || sec < 0)
00784 return -1;
00785 if(prim != MechSensor(mech)[0] || sec != MechSensor(mech)[1]) {
00786 if(!CanChangeTo(mech, prim))
00787 return -1;
00788 if(!CanChangeTo(mech, sec))
00789 return -1;
00790 StopSensorChange(mech);
00791 MECHEVENT(mech, EVENT_SCHANGE, mech_sensorchange_event,
00792 SCHANGE_TICK, ((prim * NUM_SENSORS) + sec));
00793 }
00794 return 0;
00795 }
00796
00797 void mech_sensor(dbref player, void *data, char *buffer)
00798 {
00799 MECH *mech = (MECH *) data;
00800 char *args[3];
00801 int argc;
00802
00803 if(!mech)
00804 return;
00805 DOCHECK(MechType(mech) == CLASS_MW,
00806 "You're using your eyes, and nothing you can do changes that!");
00807 argc = mech_parseattributes(buffer, args, 2);
00808 DOCHECK(argc > 2, "Invalid number of arguments!");
00809 switch (argc) {
00810 case 0:
00811 show_sensor(player, mech, 0);
00812 break;
00813 case 1:
00814 show_sensor(player, mech, 1);
00815 break;
00816 case 2:
00817 DOCHECK(set_sensor(mech, toupper(args[0][0]), toupper(args[1][0]))
00818 < 0, "Invalid arguments!");
00819 show_sensor(player, mech, 0);
00820 break;
00821 }
00822 }
00823
00824 void possibly_see_mech(MECH * mech)
00825 {
00826 MAP *map = getMap(mech->mapindex);
00827 int i, j;
00828 MECH *seer;
00829 int mapvis;
00830 int maplight;
00831 float range;
00832 int num = mech->mapnumber;
00833
00834 if(!map)
00835 return;
00836 mapvis = map->mapvis;
00837 maplight = map->maplight;
00838
00839
00840
00841 for(i = 0; i < map->first_free; i++)
00842 if(i != num && (j = map->mechsOnMap[i]) >= 0) {
00843 if(!(seer = getMech(j)))
00844 continue;
00845 if(seer->mapindex != map->mynum) {
00846 SendError(tprintf("Mech #%d was on map #%d but with "
00847 "incorrect mapindex (%d)", seer->mynum,
00848 map->mynum, seer->mapindex));
00849 map->mechsOnMap[i] = -1;
00850 continue;
00851 }
00852 range = FaMechRange(seer, mech);
00853 map->LOSinfo[i][num] =
00854 CalculateLOSFlag(seer, mech, map, MechX(mech), MechY(mech),
00855 map->LOSinfo[i][num], (float) range);
00856
00857
00858
00859 #ifdef ADVANCED_LOS
00860 Sensor_DoWeSeeNow(seer, &map->LOSinfo[i][num], range, -1, -1,
00861 mech, mapvis, maplight, map->cloudbase, 2, 0);
00862 #endif
00863 }
00864 }
00865
00866 static void mech_unblind_event(MUXEVENT * e)
00867 {
00868 MECH *m = (MECH *) e->data;
00869
00870 MechStatus(m) &= ~BLINDED;
00871 if(!Uncon(m))
00872 mech_notify(m, MECHALL, "Your sight recovers.");
00873 }
00874
00875 void ScrambleInfraAndLiteAmp(MECH * mech, int time, int chance,
00876 char *inframsg, char *liteampmsg)
00877 {
00878 MAP *mech_map = getMap(mech->mapindex);
00879 int i;
00880 MECH *tempMech;
00881
00882 possibly_see_mech(mech);
00883 for(i = 0; i < mech_map->first_free; i++)
00884 if(mech_map->mechsOnMap[i] != -1 &&
00885 mech_map->mechsOnMap[i] != mech->mynum)
00886 if((tempMech = getMech(mech_map->mechsOnMap[i])))
00887 if(InLineOfSight(tempMech, mech, MechX(mech), MechY(mech),
00888 FaMechRange(tempMech, mech))) {
00889 if(Blinded(tempMech) || Uncon(tempMech))
00890 continue;
00891 if(sensors[(int)
00892 MechSensor(tempMech)[0]].matchletter[0] == 'I'
00893 || sensors[(int)
00894 MechSensor(tempMech)
00895 [0]].matchletter[1] == 'I') {
00896 if(chance)
00897 if(Number(1, 100) > chance)
00898 continue;
00899
00900 mech_notify(tempMech, MECHALL, inframsg);
00901 } else if(sensors[(int)
00902 MechSensor(tempMech)[0]].matchletter[0]
00903 == 'L' || sensors[(int)
00904 MechSensor(tempMech)
00905 [0]].matchletter[1]
00906 == 'L') {
00907 if(chance)
00908 if(Number(1, 100) > chance)
00909 continue;
00910
00911 mech_notify(tempMech, MECHALL, liteampmsg);
00912 } else
00913 continue;
00914 MechStatus(tempMech) |= BLINDED;
00915 MECHEVENT(tempMech, EVENT_BLINDREC, mech_unblind_event,
00916 time, 0);
00917 }
00918 }