00001
00002
00003
00004
00005
00006
00007 #include <string.h>
00008 #include <math.h>
00009
00010 #include "config.h"
00011 #include "externs.h"
00012 #include "interface.h"
00013
00014 #include "muxevent.h"
00015 #include "mech.h"
00016 #include "map.h"
00017 #include "map.los.h"
00018 #include "p.mech.utils.h"
00019 #include "p.mech.contacts.h"
00020 #include "failures.h"
00021 #include "p.mech.build.h"
00022 #include "p.mech.notify.h"
00023 #include "p.mech.update.h"
00024 #include "p.mech.move.h"
00025 #include "p.mech.los.h"
00026 #include "p.mech.status.h"
00027
00028 extern void auto_reply(MECH * mech, char *buf);
00029
00030 #ifdef HUDINFO_SUPPORT
00031
00032 #include "hudinfo.h"
00033
00034 void fake_hudinfo(dbref player, dbref cause, int key, char *arg)
00035 {
00036 notify(player, "HUDINFO does not work from scode or macros.");
00037 }
00038
00039 HASHTAB hudinfo_cmdtab;
00040
00041 void init_hudinfo(void)
00042 {
00043 HUDCMD *cmd;
00044
00045 hashinit(&hudinfo_cmdtab, 20 * HASH_FACTOR);
00046
00047 for(cmd = hudinfo_cmds; cmd->cmd; cmd++)
00048 hashadd(cmd->cmd, (int *) cmd, &hudinfo_cmdtab);
00049 }
00050
00051 static MECH *getMech_forPlayer(dbref player)
00052 {
00053 dbref inv, tmp;
00054 MECH *mech = NULL;
00055
00056 if(Hardcode(player) && !Zombie(player))
00057 mech = getMech(player);
00058
00059 if(!mech) {
00060 tmp = Location(player);
00061 if(Hardcode(tmp) && !Zombie(tmp))
00062 mech = getMech(tmp);
00063 }
00064
00065 if(!mech) {
00066 SAFE_DOLIST(inv, tmp, Contents(player)) {
00067 if(Hardcode(inv) && !Zombie(inv))
00068 mech = getMech(inv);
00069 if(mech)
00070 break;
00071 }
00072 }
00073 return mech;
00074 }
00075
00076 void do_hudinfo(DESC * d, char *arg)
00077 {
00078 char *subcmd;
00079 HUDCMD *cmd;
00080 MECH *mech = NULL;
00081
00082 while (*arg && isspace(*arg))
00083 arg++;
00084
00085 if(!*arg) {
00086 hudinfo_notify(d, NULL, NULL, "#HUD hudinfo version "
00087 HUD_PROTO_VERSION);
00088 return;
00089 }
00090
00091 if(strncmp(arg, "key=", 4) == 0) {
00092 arg += 4;
00093 if(!arg || strlen(arg) > 20) {
00094 hudinfo_notify(d, "KEY", "E", "Invalid key");
00095 return;
00096 }
00097 for(subcmd = arg; *subcmd; subcmd++) {
00098 if(!isalnum(*subcmd)) {
00099 hudinfo_notify(d, "KEY", "E", "Invalid key");
00100 return;
00101 }
00102 }
00103 strcpy(d->hudkey, arg);
00104 hudinfo_notify(d, "KEY", "R", "Key set");
00105 return;
00106 }
00107
00108 if(!d->hudkey[0]) {
00109 hudinfo_notify(d, "???", "E", "No session key set");
00110 return;
00111 }
00112
00113 subcmd = arg;
00114
00115 while (*arg && !isspace(*arg)) {
00116 if(!isalnum(*arg)) {
00117 hudinfo_notify(d, "???", "E", "Invalid subcommand");
00118 return;
00119 }
00120 arg++;
00121 }
00122
00123 if(*arg) {
00124 *arg++ = '\0';
00125 }
00126
00127 while (*arg && isspace(*arg))
00128 arg++;
00129
00130 cmd = (HUDCMD *) hashfind(subcmd, &hudinfo_cmdtab);
00131 if(!cmd) {
00132 hudinfo_notify(d, "???", "E",
00133 tprintf("%s: subcommand not found", subcmd));
00134 return;
00135 }
00136
00137 if(cmd->flag & HUDCMD_HASARG) {
00138 if(!*arg) {
00139 hudinfo_notify(d, cmd->msgclass, "E", "Not enough arguments");
00140 return;
00141 }
00142 } else if(*arg) {
00143 hudinfo_notify(d, cmd->msgclass, "E", "Command takes no arguments");
00144 return;
00145 }
00146
00147 if(cmd->flag & HUDCMD_NEEDMECH) {
00148 mech = getMech_forPlayer(d->player);
00149 if(!mech) {
00150 hudinfo_notify(d, cmd->msgclass, "E", "Not in a BattleTech unit");
00151 return;
00152 }
00153 if((cmd->flag & HUDCMD_NONDEST) && Destroyed(mech)) {
00154 hudinfo_notify(d, cmd->msgclass, "E", "You are destroyed!");
00155 return;
00156 }
00157 if((cmd->flag & HUDCMD_STARTED) && !Started(mech)) {
00158 hudinfo_notify(d, cmd->msgclass, "E", "Reactor is not online");
00159 return;
00160 }
00161 if((cmd->flag & HUDCMD_AWAKE) &&
00162 (MechStatus(mech) & (BLINDED | UNCONSCIOUS))) {
00163 hudinfo_notify(d, cmd->msgclass, "E",
00164 "You are unconscious....zzzzzzz");
00165 return;
00166 }
00167 }
00168
00169 cmd->handler(d, mech, cmd->msgclass, arg);
00170 return;
00171 }
00172
00173 static void FindRangeAndBearingToCenter(MECH * mech, float *rtc, int *btc)
00174 {
00175 float fx, fy;
00176
00177 MapCoordToRealCoord(MechX(mech), MechY(mech), &fx, &fy);
00178 *rtc = FindHexRange(fx, fy, MechFX(mech), MechFY(mech));
00179 *btc = FindBearing(MechFX(mech), MechFY(mech), fx, fy);
00180 }
00181
00182 static void hud_generalstatus(DESC * d, MECH * mech, char *msgclass,
00183 char *args)
00184 {
00185 static char response[LBUF_SIZE];
00186 char fuel[15];
00187 char tstat[5];
00188 char jumpx[8], jumpy[8];
00189 int btc;
00190 float rtc;
00191
00192 if(FlyingT(mech) && !AeroFreeFuel(mech))
00193 sprintf(fuel, "%d", AeroFuel(mech));
00194 else
00195 strcpy(fuel, "-");
00196
00197 if(MechHasTurret(mech))
00198 sprintf(tstat, "%d", AcceptableDegree(MechTurretFacing(mech)) - 180);
00199 else if((MechType(mech) == CLASS_MECH && !MechIsQuad(mech)) ||
00200 MechType(mech) == CLASS_MW)
00201 sprintf(tstat, "%d",
00202 MechStatus(mech) & TORSO_LEFT ? -60 : MechStatus(mech) &
00203 TORSO_RIGHT ? 60 : 0);
00204 else
00205 strcpy(tstat, "-");
00206
00207 if(Jumping(mech)) {
00208 snprintf(jumpx, 8, "%d", MechGoingX(mech));
00209 snprintf(jumpy, 8, "%d", MechGoingY(mech));
00210 } else {
00211 strcpy(jumpx, "-");
00212 strcpy(jumpy, "-");
00213 };
00214
00215 FindRangeAndBearingToCenter(mech, &rtc, &btc);
00216
00217 sprintf(response,
00218 "%s,%d,%d,%d,%d,%d,%.2f,%.2f,%d,%d,%s,%.2f,%.2f,%.3f,%d,%s,%s,%s,%s",
00219 MechIDS(mech, 0), MechX(mech), MechY(mech), MechZ(mech),
00220 MechFacing(mech), MechDesiredFacing(mech),
00221 MechSpeed(mech), MechDesiredSpeed(mech),
00222 (int) (10 * MechPlusHeat(mech)),
00223 (int) (10 * MechMinusHeat(mech)),
00224 fuel, MechVerticalSpeed(mech), MechVerticalSpeed(mech),
00225 rtc, btc, tstat, getStatusString(mech, 2), jumpx, jumpy);
00226
00227 hudinfo_notify(d, msgclass, "R", response);
00228 }
00229
00230 static char *hud_getweaponstatus(MECH * mech, int sect, int crit, int data)
00231 {
00232 static char wstatus[12];
00233
00234 if(PartIsBroken(mech, sect, crit))
00235 return "*";
00236 if(PartIsDisabled(mech, sect, crit))
00237 return "D";
00238 switch (PartTempNuke(mech, sect, crit)) {
00239 case FAIL_JAMMED:
00240 return "J";
00241 case FAIL_SHORTED:
00242 return "S";
00243 case FAIL_DUD:
00244 return "d";
00245 case FAIL_EMPTY:
00246 return "E";
00247 case FAIL_AMMOJAMMED:
00248 return "A";
00249 case FAIL_DESTROYED:
00250 return "*";
00251 }
00252 if(GetPartFireMode(mech, sect, crit) & IS_JETTISONED_MODE)
00253 return "j";
00254 if(data) {
00255 sprintf(wstatus, "%d", data / WEAPON_TICK);
00256 return wstatus;
00257 }
00258 return "R";
00259 }
00260
00261 static char *hud_getfiremode(MECH * mech, int sect, int crit, int type)
00262 {
00263 int mode = GetPartFireMode(mech, sect, crit);
00264 static char wmode[30];
00265 char *p = wmode;
00266
00267 if(mode & RAC_TWOSHOT_MODE)
00268 *p++ = '2';
00269 if(mode & RAC_FOURSHOT_MODE)
00270 *p++ = '4';
00271 if(mode & RAC_SIXSHOT_MODE)
00272 *p++ = '6';
00273 if(mode & WILL_JETTISON_MODE)
00274 *p++ = 'B';
00275 if(mode & GATTLING_MODE)
00276 *p++ = 'G';
00277 if(mode & HOTLOAD_MODE)
00278 *p++ = 'H';
00279 if(mode & RFAC_MODE)
00280 *p++ = 'R';
00281 if((mode & ON_TC) && !(MechCritStatus(mech) & TC_DESTROYED))
00282 *p++ = 'T';
00283 if(mode & ULTRA_MODE)
00284 *p++ = 'U';
00285 if(mode & HEAT_MODE)
00286 *p++ = 'h';
00287
00288 if(mode & (OS_USED | ROCKET_FIRED))
00289 *p++ = 'o';
00290 else if((mode & OS_MODE) || (MechWeapons[type].special & ROCKET))
00291 *p++ = 'O';
00292
00293 if(MechWeapons[type].special & INARC)
00294 *p++ = 'I';
00295 if(MechWeapons[type].special & NARC)
00296 *p++ = 'N';
00297 if(MechWeapons[type].special & STREAK)
00298 *p++ = 'S';
00299
00300 if(MechWeapons[type].special & AMS) {
00301 if(MechStatus(mech) & AMS_ENABLED)
00302 *p++ = 'A';
00303 else
00304 *p++ = 'a';
00305 }
00306
00307
00308
00309 if(p == wmode)
00310 *p++ = '-';
00311
00312 *p = '\0';
00313 return wmode;
00314 }
00315
00316 static char *hud_getammomode(MECH * mech, int mode)
00317 {
00318 static char amode[20];
00319 char *p = amode;
00320
00321 if(mode & SGUIDED_MODE)
00322 *p++ = 'G';
00323 if(mode & SWARM1_MODE)
00324 *p++ = '1';
00325 if(mode & ARTEMIS_MODE)
00326 *p++ = 'A';
00327 if(mode & CLUSTER_MODE)
00328 *p++ = 'C';
00329 if(mode & INARC_ECM_MODE)
00330 *p++ = 'E';
00331 if(mode & AC_FLECHETTE_MODE)
00332 *p++ = 'F';
00333 if(mode & INARC_HAYWIRE_MODE)
00334 *p++ = 'H';
00335 if(mode & INFERNO_MODE)
00336 *p++ = 'I';
00337 if(mode & LBX_MODE)
00338 *p++ = 'L';
00339 if(mode & MINE_MODE)
00340 *p++ = 'M';
00341 if(mode & NARC_MODE)
00342 *p++ = 'N';
00343 if(mode & AC_PRECISION_MODE)
00344 *p++ = 'P';
00345 if(mode & SWARM_MODE)
00346 *p++ = 'S';
00347 if(mode & AC_AP_MODE)
00348 *p++ = 'a';
00349 if(mode & INARC_EXPLO_MODE)
00350 *p++ = 'X';
00351 if(mode & AC_INCENDIARY_MODE)
00352 *p++ = 'e';
00353 if(mode & SMOKE_MODE)
00354 *p++ = 's';
00355 if(mode & STINGER_MODE)
00356 *p++ = 'T';
00357 if(mode & AC_CASELESS_MODE)
00358 *p++ = 'U';
00359
00360 if(p == amode)
00361 *p++ = '-';
00362 *p = '\0';
00363 return amode;
00364 }
00365
00366 static void hud_weapons(DESC * d, MECH * mech, char *msgclass, char *args)
00367 {
00368 int sect, weapcount, i, weapnum = -1;
00369 unsigned char weaparray[MAX_WEAPS_SECTION];
00370 unsigned char weapdata[MAX_WEAPS_SECTION];
00371 int critical[MAX_WEAPS_SECTION];
00372 char response[LBUF_SIZE];
00373
00374 UpdateRecycling(mech);
00375
00376 for(sect = 0; sect < NUM_SECTIONS; sect++) {
00377 weapcount = FindWeapons(mech, sect, weaparray, weapdata, critical);
00378 if(weapcount <= 0)
00379 continue;
00380 for(i = 0; i < weapcount; i++) {
00381 weapnum++;
00382 sprintf(response, "%d,%d,%d,%s%s,%s,%s,%s",
00383 weapnum,
00384 weaparray[i],
00385 GetPartBrand(mech, sect, critical[i]),
00386 ShortArmorSectionString(MechType(mech), MechMove(mech),
00387 sect), GetPartFireMode(mech, sect,
00388 critical
00389 [i]) &
00390 REAR_MOUNT ? "r" : "", hud_getweaponstatus(mech, sect,
00391 critical[i],
00392 weapdata[i]),
00393 hud_getfiremode(mech, sect, critical[i], weaparray[i]),
00394 hud_getammomode(mech,
00395 GetPartAmmoMode(mech, sect,
00396 critical[i])));
00397 hudinfo_notify(d, msgclass, "L", response);
00398 }
00399 }
00400 hudinfo_notify(d, msgclass, "D", "Done");
00401 }
00402
00403 static int get_weaponmodes(int weapindx, char *firemodes, char *ammomodes,
00404 char *damagetype)
00405 {
00406 int spec = MechWeapons[weapindx].special;
00407
00408 if(spec & PCOMBAT)
00409 return 0;
00410
00411 switch (MechWeapons[weapindx].type) {
00412 case TMISSILE:
00413 strcat(damagetype, "M");
00414 if(spec & AMS) {
00415 strcat(damagetype, "d");
00416 strcat(firemodes, "Aa");
00417 break;
00418 }
00419 if(spec & INARC) {
00420 strcat(firemodes, "I");
00421 strcat(ammomodes, "EHe");
00422 break;
00423 }
00424 if(spec & NARC) {
00425 strcat(firemodes, "N");
00426 break;
00427 }
00428 if(spec & IDF) {
00429 strcat(ammomodes, "1ACMNSs");
00430 strcat(damagetype, "g");
00431 strcat(firemodes, "Hi");
00432 } else if(spec & MRM)
00433 strcat(damagetype, "g");
00434 else
00435 strcat(ammomodes, "AIN");
00436 if(spec & DFM)
00437 strcat(damagetype, "D");
00438 if(spec & ELRM)
00439 strcat(damagetype, "e");
00440 if(spec & STREAK)
00441 strcat(firemodes, "S");
00442 break;
00443 case TAMMO:
00444 if(spec & GAUSS) {
00445 strcat(damagetype, "G");
00446 if(spec & HVYGAUSS)
00447 strcat(damagetype, "H");
00448 break;
00449 }
00450 strcat(damagetype, "B");
00451
00452 if(spec & CASELESS)
00453 strcat(damagetype, "C");
00454 if(spec & HYPER)
00455 strcat(damagetype, "Y");
00456 if(spec & RAC)
00457 strcat(firemodes, "246");
00458 if(spec & GMG)
00459 strcat(firemodes, "G");
00460 if(spec & RFAC) {
00461 strcat(firemodes, "R");
00462 strcat(ammomodes, "FPai");
00463 }
00464 if(spec & LBX)
00465 strcat(ammomodes, "L");
00466 if(spec & ULTRA)
00467 strcat(firemodes, "U");
00468 break;
00469 case TARTILLERY:
00470 strcat(damagetype, "Ag");
00471 strcat(firemodes, "Hi");
00472 strcat(ammomodes, "CMs");
00473 break;
00474 case TBEAM:
00475 strcat(damagetype, "E");
00476 if(spec & HVYW)
00477 strcat(damagetype, "h");
00478 if(spec & PULSE)
00479 strcat(damagetype, "p");
00480 if(spec & CHEAT)
00481 strcat(firemodes, "h");
00482 if(spec & A_POD)
00483 strcat(damagetype, "a");
00484 break;
00485 }
00486 if(spec & NOSPA)
00487 ammomodes[0] = '\0';
00488 return 1;
00489 }
00490
00491 static void hud_weaponlist(DESC * d, MECH * mech, char *msgclass, char *args)
00492 {
00493 int i;
00494 char firemodes[30] = "";
00495 char ammomodes[20] = "";
00496 char damagetype[10] = "";
00497 char response[LBUF_SIZE];
00498 struct weapon_struct *w;
00499
00500 for(i = 0; i < num_def_weapons; i++) {
00501 firemodes[0] = ammomodes[0] = damagetype[0] = '\0';
00502 if(!get_weaponmodes(i, firemodes, ammomodes, damagetype))
00503 continue;
00504
00505 if(strlen(firemodes) == 0)
00506 strcat(firemodes, "-");
00507 if(strlen(ammomodes) == 0)
00508 strcat(ammomodes, "-");
00509
00510 w = &MechWeapons[i];
00511 sprintf(response,
00512 "%d,%s,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s,%d", i,
00513 w->name, w->min, w->shortrange, w->medrange, w->longrange,
00514 w->min_water, w->shortrange_water, w->medrange_water,
00515 w->longrange_water, w->criticals, w->weight, w->damage,
00516 w->vrt, firemodes, ammomodes, damagetype, w->heat * 10);
00517 hudinfo_notify(d, msgclass, "L", response);
00518 }
00519
00520 hudinfo_notify(d, msgclass, "D", "Done");
00521 }
00522
00523 static void hud_limbstatus(DESC * d, MECH * mech, char *msgclass, char *args)
00524 {
00525
00526 int locs[] = { RLEG, LLEG, RARM, LARM };
00527 int todo = 3;
00528
00529 UpdateRecycling(mech);
00530
00531 if(MechType(mech) == CLASS_MECH) {
00532 for(; todo >= 0; todo--) {
00533 char *sect = ShortArmorSectionString(MechType(mech),
00534 MechMove(mech), locs[todo]);
00535 char status[10];
00536
00537 if(SectIsDestroyed(mech, locs[todo]))
00538 strcpy(status, "*");
00539 else if(MechSections(mech)[locs[todo]].recycle > 0)
00540 sprintf(status, "%d",
00541 MechSections(mech)[locs[todo]].recycle / WEAPON_TICK);
00542 else
00543 strcpy(status, "R");
00544
00545 hudinfo_notify(d, msgclass, "L", tprintf("%s,%s", sect, status));
00546 }
00547 }
00548 hudinfo_notify(d, msgclass, "D", "Done");
00549 }
00550
00551 static void hud_ammostatus(DESC * d, MECH * mech, char *msgclass, char *args)
00552 {
00553 unsigned char weapnums[8 * MAX_WEAPS_SECTION];
00554 unsigned short curamm[8 * MAX_WEAPS_SECTION];
00555 unsigned short maxamm[8 * MAX_WEAPS_SECTION];
00556 unsigned int ammomode[8 * MAX_WEAPS_SECTION];
00557 int i, ammonum;
00558 char response[LBUF_SIZE];
00559
00560 ammonum = FindAmmunition(mech, weapnums, curamm, maxamm, ammomode, 1);
00561
00562 for(i = 0; i < ammonum; i++) {
00563 sprintf(response, "%d,%d,%s,%d,%d", i, weapnums[i],
00564 hud_getammomode(mech, ammomode[i]), curamm[i], maxamm[i]);
00565 hudinfo_notify(d, msgclass, "L", response);
00566 }
00567 hudinfo_notify(d, msgclass, "D", "Done");
00568 }
00569
00570 static char hud_typechar(MECH * mech)
00571 {
00572
00573 if(MechMove(mech) == MOVE_NONE)
00574 return 'i';
00575
00576 switch (MechType(mech)) {
00577 case CLASS_MECH:
00578 if(MechMove(mech) == MOVE_QUAD)
00579 return 'Q';
00580 return 'B';
00581 case CLASS_VEH_GROUND:
00582 case CLASS_VEH_NAVAL:
00583 switch (MechMove(mech)) {
00584 case MOVE_TRACK:
00585 return 'T';
00586 case MOVE_WHEEL:
00587 return 'W';
00588 case MOVE_HOVER:
00589 return 'H';
00590 case MOVE_HULL:
00591 return 'N';
00592 case MOVE_FOIL:
00593 return 'Y';
00594 case MOVE_SUB:
00595 return 'U';
00596 default:
00597 SendError(tprintf("Unknown movement type on vehicle #%d: %d",
00598 mech->mynum, MechMove(mech)));
00599 return '?';
00600 }
00601 case CLASS_VTOL:
00602 return 'V';
00603 case CLASS_AERO:
00604 return 'F';
00605 case CLASS_DS:
00606 return 'A';
00607 case CLASS_SPHEROID_DS:
00608 return 'D';
00609 case CLASS_MW:
00610 return 'I';
00611 case CLASS_BSUIT:
00612 return 'S';
00613 }
00614 SendError(tprintf("Unknown unit type on unit #%d: %d (move %d)",
00615 mech->mynum, MechType(mech), MechMove(mech)));
00616 return '?';
00617 }
00618
00619 static float MaxSettableSpeed(MECH * mech)
00620 {
00621 int maxspeed = MMaxSpeed(mech);
00622
00623 if(MechMove(mech) == MOVE_VTOL)
00624 maxspeed = sqrt((float) maxspeed * maxspeed -
00625 MechVerticalSpeed(mech) * MechVerticalSpeed(mech));
00626
00627 maxspeed = maxspeed > 0.0 ? maxspeed : 0.0;
00628
00629 if((MechSpecials(mech) & TRIPLE_MYOMER_TECH) && MechHeat(mech) >= 9.)
00630 maxspeed = ceil((rint((maxspeed / 1.5) / MP1) + 1) * 1.5) * MP1;
00631 return maxspeed;
00632 }
00633
00634 static float MaxVerticalSpeed(MECH * mech)
00635 {
00636 int maxspeed = MMaxSpeed(mech);
00637
00638 if(MechMove(mech) != MOVE_VTOL)
00639 return 0.0;
00640
00641 maxspeed = sqrt((float) maxspeed * maxspeed -
00642 MechDesiredSpeed(mech) * MechDesiredSpeed(mech));
00643 return maxspeed;
00644 }
00645
00646 static char *hud_advtech(MECH * mech)
00647 {
00648 static char advtech[30];
00649 char *p = advtech;
00650 int spec = MechSpecials(mech);
00651
00652 if(spec & ECM_TECH)
00653 *p++ = 'E';
00654 if(spec & BEAGLE_PROBE_TECH)
00655 *p++ = 'B';
00656 if(spec & MASC_TECH)
00657 *p++ = 'M';
00658 if(spec & AA_TECH)
00659 *p++ = 'R';
00660 if(spec & SLITE_TECH)
00661 *p++ = 'S';
00662 if(spec & TRIPLE_MYOMER_TECH)
00663 *p++ = 't';
00664
00665 spec = MechSpecials2(mech);
00666 if(spec & ANGEL_ECM_TECH)
00667 *p++ = 'A';
00668 if(spec & NULLSIGSYS_TECH)
00669 *p++ = 'N';
00670 if(spec & BLOODHOUND_PROBE_TECH)
00671 *p++ = 'b';
00672 if(spec & STEALTH_ARMOR_TECH)
00673 *p++ = 's';
00674
00675 spec = MechInfantrySpecials(mech);
00676 if(spec & FC_INFILTRATORII_STEALTH_TECH) {
00677 *p++ = 'I';
00678 *p++ = 'P';
00679 }
00680 if(spec & CAN_JETTISON_TECH)
00681 *p++ = 'J';
00682 if(spec & DC_KAGE_STEALTH_TECH)
00683 *p++ = 'K';
00684 if(spec & INF_ANTILEG_TECH)
00685 *p++ = 'L';
00686 if(spec & INF_SWARM_TECH)
00687 *p++ = 'W';
00688 if(spec & FWL_ACHILEUS_STEALTH_TECH)
00689 *p++ = 'a';
00690 if(spec & INF_MOUNT_TECH)
00691 *p++ = 'f';
00692 if(spec & FC_INFILTRATOR_STEALTH_TECH)
00693 *p++ = 'i';
00694 if(spec & MUST_JETTISON_TECH)
00695 *p++ = 'j';
00696 if(spec & CS_PURIFIER_STEALTH_TECH)
00697 *p++ = 'p';
00698
00699 if(HasC3i(mech))
00700 *p++ = 'C';
00701 if(HasTAG(mech))
00702 *p++ = 'T';
00703 if(HasC3s(mech))
00704 *p++ = 'c';
00705 if(HasC3m(mech))
00706 *p++ = 'm';
00707
00708 if(p == advtech)
00709 *p++ = '-';
00710
00711 *p = '\0';
00712 return advtech;
00713 }
00714
00715 static void hud_templateinfo(DESC * d, MECH * mech, char *msgclass,
00716 char *args)
00717 {
00718 char response[LBUF_SIZE];
00719 char fuel[20];
00720
00721 if(FlyingT(mech) && AeroFuelOrig(mech))
00722 sprintf(fuel, "%d", AeroFuelOrig(mech));
00723 else
00724 strcpy(fuel, "-");
00725
00726 sprintf(response, "%c,%s,%s,%.3f,%.3f,%.3f,%.3f,%s,%d,%s",
00727 hud_typechar(mech), MechType_Ref(mech), MechType_Name(mech),
00728 WalkingSpeed(MaxSettableSpeed(mech)), MaxSettableSpeed(mech),
00729 -WalkingSpeed(MaxSettableSpeed(mech)),
00730 MaxVerticalSpeed(mech), fuel, MechRealNumsinks(mech),
00731 hud_advtech(mech));
00732 hudinfo_notify(d, msgclass, "R", response);
00733 }
00734
00735 static void hud_templatearmor(DESC * d, MECH * mech, char *msgclass,
00736 char *args)
00737 {
00738 char response[LBUF_SIZE];
00739 int sect;
00740
00741 for(sect = 0; sect < NUM_SECTIONS; sect++) {
00742 if(GetSectOInt(mech, sect)) {
00743 sprintf(response, "%s,%d,%d,%d",
00744 ShortArmorSectionString(MechType(mech), MechMove(mech),
00745 sect), GetSectOArmor(mech, sect),
00746 GetSectORArmor(mech, sect), GetSectOInt(mech, sect));
00747 hudinfo_notify(d, msgclass, "L", response);
00748 }
00749 }
00750 hudinfo_notify(d, msgclass, "D", "Done");
00751 }
00752
00753 static void hud_armorstatus(DESC * d, MECH * mech, char *msgclass, char *args)
00754 {
00755 char response[LBUF_SIZE];
00756 int sect;
00757
00758 for(sect = 0; sect < NUM_SECTIONS; sect++) {
00759 if(GetSectOInt(mech, sect)) {
00760 sprintf(response, "%s,%d,%d,%d",
00761 ShortArmorSectionString(MechType(mech), MechMove(mech),
00762 sect), GetSectArmor(mech, sect),
00763 GetSectRArmor(mech, sect), GetSectInt(mech, sect));
00764 hudinfo_notify(d, msgclass, "L", response);
00765 }
00766 }
00767 hudinfo_notify(d, msgclass, "D", "Done");
00768 }
00769
00770 static char *hud_arcstring(int arc)
00771 {
00772 static char arcstr[5];
00773 char *p = arcstr;
00774
00775 if(arc & FORWARDARC)
00776 *p++ = '*';
00777 if(arc & LSIDEARC)
00778 *p++ = 'l';
00779 if(arc & RSIDEARC)
00780 *p++ = 'r';
00781 if(arc & REARARC)
00782 *p++ = 'v';
00783 if(arc & TURRETARC)
00784 *p++ = 't';
00785
00786 if(p == arcstr)
00787 *p++ = '-';
00788
00789 *p = '\0';
00790 return arcstr;
00791 }
00792
00793 static char *hud_sensorstring(MECH * mech, int losflag)
00794 {
00795 if((losflag & MECHLOSFLAG_SEESP) && (losflag & MECHLOSFLAG_SEESS))
00796 return "PS";
00797 if(losflag & MECHLOSFLAG_SEESP)
00798 return "P";
00799 if(losflag & MECHLOSFLAG_SEESS)
00800 return "S";
00801 return "-";
00802 }
00803
00804 static void hud_contacts(DESC * d, MECH * mech, char *msgclass, char *args)
00805 {
00806 char response[LBUF_SIZE];
00807 MECH *other;
00808 MAP *map = getMap(mech->mapindex);
00809 int i, losflag, bearing, btc, weaponarc, x, y;
00810 float range, rtc;
00811 char jumph[12];
00812 char *mechname, *constat;
00813
00814 if(!map) {
00815 hudinfo_notify(d, msgclass, "E", "You are on no map");
00816 return;
00817 }
00818
00819 for(i = 0; i < map->first_free; i++) {
00820 if(map->mechsOnMap[i] == mech->mynum || map->mechsOnMap[i] == -1)
00821 continue;
00822
00823 other = (MECH *) FindObjectsData(map->mechsOnMap[i]);
00824 if(!other || !Good_obj(other->mynum))
00825 continue;
00826
00827 range = FlMechRange(map, mech, other);
00828 x = MechX(other);
00829 y = MechY(other);
00830 losflag = InLineOfSight(mech, other, x, y, range);
00831 if(!losflag)
00832 continue;
00833 bearing = FindBearing(MechFX(mech), MechFY(mech), MechFX(other),
00834 MechFY(other));
00835 weaponarc = InWeaponArc(mech, MechFX(other), MechFY(other));
00836
00837 if(Jumping(other))
00838 sprintf(jumph, "%d", MechJumpHeading(other));
00839 else
00840 strcpy(jumph, "-");
00841
00842 FindRangeAndBearingToCenter(other, &rtc, &btc);
00843
00844 if(!InLineOfSight_NB(mech, other, MechX(other), MechY(other), 0.0))
00845 mechname = "something";
00846 else
00847 mechname = silly_atr_get(other->mynum, A_MECHNAME);
00848
00849 if(!mechname || !*mechname)
00850 mechname = "-";
00851
00852 constat = getStatusString(other, !MechSeemsFriend(mech, other));
00853 if(strlen(constat) == 0)
00854 constat = "-";
00855
00856 sprintf(response,
00857 "%s,%s,%s,%c,%s,%d,%d,%d,%.3f,%d,%.3f,%.3f,%d,%s,%.3f,%d,%d,%.0f,%s",
00858 MechIDS(other, MechSeemsFriend(mech, other)),
00859 hud_arcstring(weaponarc), hud_sensorstring(mech, losflag),
00860 hud_typechar(other), mechname, MechX(other),
00861 MechY(other), MechZ(other), range, bearing, MechSpeed(other),
00862 MechVerticalSpeed(other), MechVFacing(other), jumph, rtc, btc,
00863 MechTons(other), MechHeat(other), constat);
00864 hudinfo_notify(d, msgclass, "L", response);
00865 }
00866 hudinfo_notify(d, msgclass, "D", "Done");
00867 }
00868
00869 static char *building_status(MAP * map, int locked)
00870 {
00871 static char buildingstatus[7];
00872 char *p = buildingstatus;
00873
00874 if(BuildIsCS(map))
00875 *p++ = 'C';
00876
00877 if(locked)
00878 *p++ = 'E';
00879 else
00880 *p++ = 'F';
00881
00882 if(BuildIsHidden(map))
00883 *p++ = 'H';
00884
00885 if(BuildIsSafe(map) || (locked && BuildIsCS(map)))
00886 *p++ = 'X';
00887 else if(locked)
00888 *p++ = 'x';
00889
00890 if(p == buildingstatus)
00891 *p++ = '-';
00892
00893 *p = '\0';
00894
00895 return buildingstatus;
00896 }
00897
00898 static void hud_building_contacts(DESC * d, MECH * mech, char *msgclass,
00899 char *args)
00900 {
00901 char response[LBUF_SIZE];
00902 MAP *map = getMap(mech->mapindex);
00903 MAP *building_map;
00904 char *building_name;
00905 mapobj *building;
00906 float fx, fy, range;
00907 int z, losflag, locked, bearing, weaponarc;
00908 char new[LBUF_SIZE];
00909
00910 if(!map) {
00911 hudinfo_notify(d, msgclass, "E", "You are on no map");
00912 return;
00913 }
00914
00915 for(building = first_mapobj(map, TYPE_BUILD); building;
00916 building = next_mapobj(building)) {
00917
00918 MapCoordToRealCoord(building->x, building->y, &fx, &fy);
00919 z = Elevation(map, building->x, building->y) + 1;
00920 range = FindRange(MechFX(mech), MechFY(mech), MechFZ(mech), fx, fy,
00921 ZSCALE * z);
00922
00923 if(!building->obj)
00924 continue;
00925
00926 building_map = getMap(building->obj);
00927 if(!building_map)
00928 continue;
00929
00930 losflag = InLineOfSight(mech, NULL, building->x, building->y, range);
00931 if(!losflag || (losflag & MECHLOSFLAG_BLOCK))
00932 continue;
00933
00934 if(BuildIsInvis(building_map))
00935 continue;
00936
00937 locked = !can_pass_lock(mech->mynum, building->obj, A_LENTER);
00938 if(locked && BuildIsHidden(building_map))
00939 continue;
00940
00941 bearing = FindBearing(MechFX(mech), MechFY(mech), fx, fy);
00942 weaponarc = InWeaponArc(mech, fx, fy);
00943 building_name = silly_atr_get(building->obj, A_MECHNAME);
00944 if(!building_name || !*building_name) {
00945 strncpy(new, Name(building->obj), LBUF_SIZE-1);
00946 building_name = strip_ansi_r(new,Name(building->obj),strlen(Name(building->obj)));
00947 }
00948
00949 if(!building_name || !*building_name)
00950 building_name = "-";
00951
00952 sprintf(response, "%s,%s,%d,%d,%d,%f,%d,%d,%d,%s",
00953 hud_arcstring(weaponarc), building_name, building->x,
00954 building->y, z, range, bearing, building_map->cf,
00955 building_map->cfmax, building_status(building_map, locked));
00956 hudinfo_notify(d, msgclass, "L", response);
00957 }
00958 hudinfo_notify(d, msgclass, "D", "Done");
00959
00960 };
00961
00962 static char hud_damstr[] = "OoxX*?";
00963 static char hud_damagechar(MECH * mech, int sect, int type)
00964 {
00965 int dummy;
00966
00967 switch (type) {
00968 case 1:
00969 if(GetSectOArmor(mech, sect))
00970 return hud_damstr[ArmorEvaluateSerious(mech, sect, 1, &dummy)];
00971 return '-';
00972 case 2:
00973 if(GetSectOInt(mech, sect))
00974 return hud_damstr[ArmorEvaluateSerious(mech, sect, 2, &dummy)];
00975 return '-';
00976 case 4:
00977 if(GetSectORArmor(mech, sect))
00978 return hud_damstr[ArmorEvaluateSerious(mech, sect, 4, &dummy)];
00979 return '-';
00980 }
00981 return '?';
00982 }
00983
00984 static MECH *hud_scantarget(DESC * d, MECH * mech, char *msgclass, char *args)
00985 {
00986 MECH *targ;
00987 float range;
00988
00989 if(!MechScanRange(mech)) {
00990 hudinfo_notify(d, msgclass, "E",
00991 "Your system seems to be inoperational");
00992 return NULL;
00993 }
00994
00995 if(strlen(args) != 2 ||
00996 !(targ = getMech(FindTargetDBREFFromMapNumber(mech, args)))) {
00997 hudinfo_notify(d, msgclass, "E", "No such target");
00998 return NULL;
00999 }
01000
01001 range = FaMechRange(mech, targ);
01002
01003 if(!InLineOfSight(mech, targ, MechX(targ), MechY(targ), range)) {
01004 hudinfo_notify(d, msgclass, "E", "No such target");
01005 return NULL;
01006 }
01007
01008 if(!MechIsObservator(mech) && (int) range > MechScanRange(mech)) {
01009 hudinfo_notify(d, msgclass, "E", "Out of range");
01010 return NULL;
01011 }
01012
01013 if(MechType(targ) == CLASS_MW ||
01014 !InLineOfSight_NB(mech, targ, MechX(targ), MechY(targ), range)) {
01015 hudinfo_notify(d, msgclass, "E", "Unable to scan target");
01016 return NULL;
01017 }
01018
01019 if(!MechIsObservator(mech)) {
01020 mech_notify(targ, MECHSTARTED,
01021 tprintf("You are being scanned by %s",
01022 GetMechToMechID(targ, mech)));
01023 auto_reply(targ, tprintf("%s just scanned me.",
01024 GetMechToMechID(targ, mech)));
01025 }
01026 return targ;
01027 }
01028
01029 static void hud_armorscan(DESC * d, MECH * mech, char *msgclass, char *args)
01030 {
01031 char response[LBUF_SIZE];
01032 int sect;
01033 MECH *targ;
01034
01035 targ = hud_scantarget(d, mech, msgclass, args);
01036 if(!targ)
01037 return;
01038
01039 for(sect = 0; sect < NUM_SECTIONS; sect++) {
01040 if(GetSectOInt(targ, sect)) {
01041 sprintf(response, "%s,%c,%c,%c",
01042 ShortArmorSectionString(MechType(targ), MechMove(targ),
01043 sect), hud_damagechar(targ, sect,
01044 1),
01045 hud_damagechar(targ, sect, 4), hud_damagechar(targ, sect,
01046 2));
01047 hudinfo_notify(d, msgclass, "L", response);
01048 }
01049 }
01050 hudinfo_notify(d, msgclass, "D", "Done");
01051 }
01052
01053 static char *hud_getweapscanstatus(MECH * mech, int sect, int crit, int data)
01054 {
01055 if(PartIsNonfunctional(mech, sect, crit))
01056 return "*";
01057 if(data)
01058 return "-";
01059 return "R";
01060 }
01061
01062 static void hud_weapscan(DESC * d, MECH * mech, char *msgclass, char *args)
01063 {
01064 int sect, weapcount, i, weapnum = -1;
01065 unsigned char weaparray[MAX_WEAPS_SECTION];
01066 unsigned char weapdata[MAX_WEAPS_SECTION];
01067 int critical[MAX_WEAPS_SECTION];
01068 char response[LBUF_SIZE];
01069 MECH *targ;
01070
01071 targ = hud_scantarget(d, mech, msgclass, args);
01072 if(!targ)
01073 return;
01074
01075 UpdateRecycling(targ);
01076
01077 for(sect = 0; sect < NUM_SECTIONS; sect++) {
01078 if(SectIsDestroyed(targ, sect))
01079 continue;
01080 weapcount = FindWeapons(targ, sect, weaparray, weapdata, critical);
01081 if(weapcount <= 0)
01082 continue;
01083 for(i = 0; i < weapcount; i++) {
01084 weapnum++;
01085 sprintf(response, "%d,%d,%s,%s", weapnum, weaparray[i],
01086 ShortArmorSectionString(MechType(targ), MechMove(targ),
01087 sect), hud_getweapscanstatus(targ,
01088 sect,
01089 critical
01090 [i],
01091 weapdata
01092 [i] /
01093 WEAPON_TICK));
01094 hudinfo_notify(d, msgclass, "L", response);
01095 }
01096 }
01097 hudinfo_notify(d, msgclass, "D", "Done");
01098 }
01099
01100 static void hud_tactical(DESC * d, MECH * mech, char *msgclass, char *args)
01101 {
01102 MAP *map = getMap(mech->mapindex);
01103 char *argv[5], result[LBUF_SIZE], *p;
01104 char mapid[21], mapname[MBUF_SIZE];
01105 int argc;
01106 int height = 24;
01107 short cx = MechX(mech), cy = MechY(mech);
01108 int sx, sy, ex, ey, x, y, losflag, lostactical = 0;
01109 hexlosmap_info *losmap = NULL;
01110
01111 if(!MechLRSRange(mech)) {
01112 hudinfo_notify(d, msgclass, "E",
01113 "Your system seems to be inoperational");
01114 return;
01115 }
01116
01117 if(!map) {
01118 hudinfo_notify(d, msgclass, "E", "You are on no map");
01119 return;
01120 }
01121
01122 argc = mech_parseattributes(args, argv, 4);
01123
01124 switch (argc) {
01125 case 4:
01126 if(strcmp("l", argv[3])) {
01127 hudinfo_notify(d, msgclass, "E", "Invalid fourth argument");
01128 return;
01129 }
01130 lostactical = 1;
01131
01132 case 3:{
01133 float fx, fy;
01134 int bearing = atoi(argv[1]);
01135 float range = atof(argv[2]);
01136
01137 if(!MechIsObservator(mech) &&
01138 abs((int) range) > MechLRSRange(mech)) {
01139 hudinfo_notify(d, msgclass, "E", "Out of range");
01140 return;
01141 }
01142 FindXY(MechFX(mech), MechFY(mech), bearing, range, &fx, &fy);
01143 RealCoordToMapCoord(&cx, &cy, fx, fy);
01144 }
01145
01146 case 1:
01147 height = atoi(argv[0]);
01148 if(!height || height < 0 || height > 40) {
01149 hudinfo_notify(d, msgclass, "E", "Invalid 1st argument");
01150 return;
01151 }
01152 break;
01153 default:
01154 hudinfo_notify(d, msgclass, "E", "Invalid arguments");
01155 return;
01156 }
01157
01158 if( (cx < 0) || (cx > map->map_width) || (cy > map->map_height) || (cy < 0)) {
01159 hudinfo_notify(d, msgclass, "E", "Out of range");
01160 return;
01161 }
01162
01163 height = MIN(height, 2 * MechLRSRange(mech));
01164 height = MIN(height, map->map_height);
01165
01166 sy = MAX(0, cy - height / 2);
01167 ey = MIN(map->map_height, cy + height / 2);
01168
01169 sx = MAX(0, cx - LRS_DISPLAY_WIDTH / 2);
01170 ex = MIN(map->map_width, cx + LRS_DISPLAY_WIDTH / 2);
01171
01172 if(lostactical || MapIsDark(map) || (MechType(mech) == CLASS_MW &&
01173 mudconf.btech_mw_losmap)) {
01174
01175
01176
01177
01178
01179
01180
01181 if (height > 1) {
01182 losmap = CalculateLOSMap(map, mech, sx, sy, ex - sx, ey - sy);
01183 }
01184 }
01185
01186 if(!mudconf.hudinfo_show_mapinfo ||
01187 (mudconf.hudinfo_show_mapinfo == 1 && In_Character(map->mynum))) {
01188 strcpy(mapid, "-1");
01189 strcpy(mapname, "-1");
01190 } else {
01191 sprintf(mapid, "%d", map->mynum);
01192 sprintf(mapname, "%s", map->mapname);
01193 };
01194
01195 sprintf(result, "%d,%d,%d,%d,%s,%s,-1,%d,%d", sx, sy, ex - 1, ey - 1,
01196 mapid, mapname, map->map_width, map->map_height);
01197 hudinfo_notify(d, msgclass, "S", result);
01198
01199 for(y = sy; y < ey; y++) {
01200 sprintf(result, "%d,", y);
01201 p = result + strlen(result);
01202
01203 for(x = sx; x < ex; x++) {
01204 if(losmap)
01205 losflag = LOSMap_GetFlag(losmap, x, y);
01206 else
01207 losflag = MAPLOSHEX_SEE;
01208
01209 if(losflag & MAPLOSHEX_SEETERRAIN) {
01210 *p = GetTerrain(map, x, y);
01211 if(*p == ' ')
01212 *p = '.';
01213 *p++;
01214 } else
01215 *p++ = '?';
01216
01217 if(losflag & MAPLOSHEX_SEEELEV)
01218 *p++ = GetElev(map, x, y) + '0';
01219 else
01220 *p++ = '?';
01221 }
01222 *p = '\0';
01223 hudinfo_notify(d, msgclass, "L", result);
01224 }
01225
01226 hudinfo_notify(d, msgclass, "D", "Done");
01227 }
01228
01229 static char *hud_getmapflags(MAP * map)
01230 {
01231 static char res[5];
01232 char *p = res;
01233
01234 if(map->flags & MAPFLAG_VACUUM)
01235 *p++ = 'V';
01236 if(map->flags & MAPFLAG_UNDERGROUND)
01237 *p++ = 'U';
01238 if(map->flags & MAPFLAG_DARK)
01239 *p++ = 'D';
01240
01241 if(p == res)
01242 *p++ = '-';
01243
01244 *p = '\0';
01245 return res;
01246 }
01247
01248 static void hud_conditions(DESC * d, MECH * mech, char *msgclass, char *args)
01249 {
01250 MAP *map = getMap(mech->mapindex);
01251 char res[200];
01252 char lt;
01253
01254 switch (map->maplight) {
01255 case 0:
01256 lt = 'N';
01257 break;
01258 case 1:
01259 lt = 'T';
01260 break;
01261 case 2:
01262 lt = 'D';
01263 break;
01264 default:
01265 lt = '?';
01266 SendError(tprintf("Unknown light type %d on map #%d",
01267 map->maplight, map->mynum));
01268 break;
01269 }
01270
01271 sprintf(res, "%c,%d,%d,%d,%s", lt, map->mapvis, map->grav,
01272 map->temp, hud_getmapflags(map));
01273 hudinfo_notify(d, msgclass, "R", res);
01274 }
01275
01276 #endif