/* * Copyright (c) 2002 Thomas Wouters <thomas@xs4all.net> * * HUDINFO support. */ #include <string.h> #include <math.h> #include "config.h" #include "externs.h" #include "interface.h" #include "muxevent.h" #include "mech.h" #include "map.h" #include "map.los.h" #include "p.mech.utils.h" #include "p.mech.contacts.h" #include "failures.h" #include "p.mech.build.h" #include "p.mech.notify.h" #include "p.mech.update.h" #include "p.mech.move.h" #include "p.mech.los.h" #include "p.mech.status.h" extern void auto_reply(MECH * mech, char *buf); #ifdef HUDINFO_SUPPORT #include "hudinfo.h" void fake_hudinfo(dbref player, dbref cause, int key, char *arg) { notify(player, "HUDINFO does not work from scode or macros."); } HASHTAB hudinfo_cmdtab; void init_hudinfo(void) { HUDCMD *cmd; hashinit(&hudinfo_cmdtab, 20 * HASH_FACTOR); for(cmd = hudinfo_cmds; cmd->cmd; cmd++) hashadd(cmd->cmd, (int *) cmd, &hudinfo_cmdtab); } static MECH *getMech_forPlayer(dbref player) { dbref inv, tmp; MECH *mech = NULL; if(Hardcode(player) && !Zombie(player)) mech = getMech(player); if(!mech) { tmp = Location(player); if(Hardcode(tmp) && !Zombie(tmp)) mech = getMech(tmp); } if(!mech) { SAFE_DOLIST(inv, tmp, Contents(player)) { if(Hardcode(inv) && !Zombie(inv)) mech = getMech(inv); if(mech) break; } } return mech; } void do_hudinfo(DESC * d, char *arg) { char *subcmd; HUDCMD *cmd; MECH *mech = NULL; while (*arg && isspace(*arg)) arg++; if(!*arg) { hudinfo_notify(d, NULL, NULL, "#HUD hudinfo version " HUD_PROTO_VERSION); return; } if(strncmp(arg, "key=", 4) == 0) { arg += 4; if(!arg || strlen(arg) > 20) { hudinfo_notify(d, "KEY", "E", "Invalid key"); return; } for(subcmd = arg; *subcmd; subcmd++) { if(!isalnum(*subcmd)) { hudinfo_notify(d, "KEY", "E", "Invalid key"); return; } } strcpy(d->hudkey, arg); hudinfo_notify(d, "KEY", "R", "Key set"); return; } if(!d->hudkey[0]) { hudinfo_notify(d, "???", "E", "No session key set"); return; } subcmd = arg; while (*arg && !isspace(*arg)) { if(!isalnum(*arg)) { hudinfo_notify(d, "???", "E", "Invalid subcommand"); return; } arg++; } if(*arg) { *arg++ = '\0'; } while (*arg && isspace(*arg)) arg++; cmd = (HUDCMD *) hashfind(subcmd, &hudinfo_cmdtab); if(!cmd) { hudinfo_notify(d, "???", "E", tprintf("%s: subcommand not found", subcmd)); return; } if(cmd->flag & HUDCMD_HASARG) { if(!*arg) { hudinfo_notify(d, cmd->msgclass, "E", "Not enough arguments"); return; } } else if(*arg) { hudinfo_notify(d, cmd->msgclass, "E", "Command takes no arguments"); return; } if(cmd->flag & HUDCMD_NEEDMECH) { mech = getMech_forPlayer(d->player); if(!mech) { hudinfo_notify(d, cmd->msgclass, "E", "Not in a BattleTech unit"); return; } if((cmd->flag & HUDCMD_NONDEST) && Destroyed(mech)) { hudinfo_notify(d, cmd->msgclass, "E", "You are destroyed!"); return; } if((cmd->flag & HUDCMD_STARTED) && !Started(mech)) { hudinfo_notify(d, cmd->msgclass, "E", "Reactor is not online"); return; } if((cmd->flag & HUDCMD_AWAKE) && (MechStatus(mech) & (BLINDED | UNCONSCIOUS))) { hudinfo_notify(d, cmd->msgclass, "E", "You are unconscious....zzzzzzz"); return; } } cmd->handler(d, mech, cmd->msgclass, arg); return; } static void FindRangeAndBearingToCenter(MECH * mech, float *rtc, int *btc) { float fx, fy; MapCoordToRealCoord(MechX(mech), MechY(mech), &fx, &fy); *rtc = FindHexRange(fx, fy, MechFX(mech), MechFY(mech)); *btc = FindBearing(MechFX(mech), MechFY(mech), fx, fy); } static void hud_generalstatus(DESC * d, MECH * mech, char *msgclass, char *args) { static char response[LBUF_SIZE]; char fuel[15]; char tstat[5]; char jumpx[8], jumpy[8]; int btc; float rtc; if(FlyingT(mech) && !AeroFreeFuel(mech)) sprintf(fuel, "%d", AeroFuel(mech)); else strcpy(fuel, "-"); if(MechHasTurret(mech)) sprintf(tstat, "%d", AcceptableDegree(MechTurretFacing(mech)) - 180); else if((MechType(mech) == CLASS_MECH && !MechIsQuad(mech)) || MechType(mech) == CLASS_MW) sprintf(tstat, "%d", MechStatus(mech) & TORSO_LEFT ? -60 : MechStatus(mech) & TORSO_RIGHT ? 60 : 0); else strcpy(tstat, "-"); if(Jumping(mech)) { snprintf(jumpx, 8, "%d", MechGoingX(mech)); snprintf(jumpy, 8, "%d", MechGoingY(mech)); } else { strcpy(jumpx, "-"); strcpy(jumpy, "-"); }; FindRangeAndBearingToCenter(mech, &rtc, &btc); sprintf(response, "%s,%d,%d,%d,%d,%d,%.2f,%.2f,%d,%d,%s,%.2f,%.2f,%.3f,%d,%s,%s,%s,%s", MechIDS(mech, 0), MechX(mech), MechY(mech), MechZ(mech), MechFacing(mech), MechDesiredFacing(mech), MechSpeed(mech), MechDesiredSpeed(mech), (int) (10 * MechPlusHeat(mech)), (int) (10. * MechActiveNumsinks(mech)), fuel, MechVerticalSpeed(mech), MechVerticalSpeed(mech), rtc, btc, tstat, getStatusString(mech, 2), jumpx, jumpy); hudinfo_notify(d, msgclass, "R", response); } static char *hud_getweaponstatus(MECH * mech, int sect, int crit, int data) { static char wstatus[12]; if(PartIsBroken(mech, sect, crit)) return "*"; if(PartIsDisabled(mech, sect, crit)) return "D"; switch (PartTempNuke(mech, sect, crit)) { case FAIL_JAMMED: return "J"; case FAIL_SHORTED: return "S"; case FAIL_DUD: return "d"; case FAIL_EMPTY: return "E"; case FAIL_AMMOJAMMED: return "A"; case FAIL_DESTROYED: return "*"; } if(GetPartFireMode(mech, sect, crit) & IS_JETTISONED_MODE) return "j"; if(data) { sprintf(wstatus, "%d", data / WEAPON_TICK); return wstatus; } return "R"; } static char *hud_getfiremode(MECH * mech, int sect, int crit, int type) { int mode = GetPartFireMode(mech, sect, crit); static char wmode[30]; char *p = wmode; if(mode & RAC_TWOSHOT_MODE) *p++ = '2'; if(mode & RAC_FOURSHOT_MODE) *p++ = '4'; if(mode & RAC_SIXSHOT_MODE) *p++ = '6'; if(mode & WILL_JETTISON_MODE) *p++ = 'B'; if(mode & GATTLING_MODE) *p++ = 'G'; if(mode & HOTLOAD_MODE) *p++ = 'H'; if(mode & RFAC_MODE) *p++ = 'R'; if((mode & ON_TC) && !(MechCritStatus(mech) & TC_DESTROYED)) *p++ = 'T'; if(mode & ULTRA_MODE) *p++ = 'U'; if(mode & HEAT_MODE) *p++ = 'h'; if(mode & (OS_USED | ROCKET_FIRED)) *p++ = 'o'; else if((mode & OS_MODE) || (MechWeapons[type].special & ROCKET)) *p++ = 'O'; if(MechWeapons[type].special & INARC) *p++ = 'I'; if(MechWeapons[type].special & NARC) *p++ = 'N'; if(MechWeapons[type].special & STREAK) *p++ = 'S'; if(MechWeapons[type].special & AMS) { if(MechStatus(mech) & AMS_ENABLED) *p++ = 'A'; else *p++ = 'a'; } /* XXX Do enhanced damage */ if(p == wmode) *p++ = '-'; *p = '\0'; return wmode; } static char *hud_getammomode(MECH * mech, int mode) { static char amode[20]; char *p = amode; if(mode & SWARM1_MODE) *p++ = '1'; if(mode & ARTEMIS_MODE) *p++ = 'A'; if(mode & CLUSTER_MODE) *p++ = 'C'; if(mode & INARC_ECM_MODE) *p++ = 'E'; if(mode & AC_FLECHETTE_MODE) *p++ = 'F'; if(mode & INARC_HAYWIRE_MODE) *p++ = 'H'; if(mode & INFERNO_MODE) *p++ = 'I'; if(mode & LBX_MODE) *p++ = 'L'; if(mode & MINE_MODE) *p++ = 'M'; if(mode & NARC_MODE) *p++ = 'N'; if(mode & AC_PRECISION_MODE) *p++ = 'P'; if(mode & SWARM_MODE) *p++ = 'S'; if(mode & AC_AP_MODE) *p++ = 'a'; if(mode & INARC_EXPLO_MODE) *p++ = 'X'; if(mode & AC_INCENDIARY_MODE) *p++ = 'e'; if(mode & SMOKE_MODE) *p++ = 's'; if(mode & STINGER_MODE) *p++ = 'T'; if(mode & AC_CASELESS_MODE) *p++ = 'U'; if(p == amode) *p++ = '-'; *p = '\0'; return amode; } static void hud_weapons(DESC * d, MECH * mech, char *msgclass, char *args) { int sect, weapcount, i, weapnum = -1; unsigned char weaparray[MAX_WEAPS_SECTION]; unsigned char weapdata[MAX_WEAPS_SECTION]; int critical[MAX_WEAPS_SECTION]; char response[LBUF_SIZE]; UpdateRecycling(mech); for(sect = 0; sect < NUM_SECTIONS; sect++) { weapcount = FindWeapons(mech, sect, weaparray, weapdata, critical); if(weapcount <= 0) continue; for(i = 0; i < weapcount; i++) { weapnum++; sprintf(response, "%d,%d,%d,%s%s,%s,%s,%s", weapnum, weaparray[i], GetPartBrand(mech, sect, critical[i]), ShortArmorSectionString(MechType(mech), MechMove(mech), sect), GetPartFireMode(mech, sect, critical [i]) & REAR_MOUNT ? "r" : "", hud_getweaponstatus(mech, sect, critical[i], weapdata[i]), hud_getfiremode(mech, sect, critical[i], weaparray[i]), hud_getammomode(mech, GetPartAmmoMode(mech, sect, critical[i]))); hudinfo_notify(d, msgclass, "L", response); } } hudinfo_notify(d, msgclass, "D", "Done"); } static int get_weaponmodes(int weapindx, char *firemodes, char *ammomodes, char *damagetype) { int spec = MechWeapons[weapindx].special; if(spec & PCOMBAT) return 0; switch (MechWeapons[weapindx].type) { case TMISSILE: strcat(damagetype, "M"); if(spec & AMS) { strcat(damagetype, "d"); strcat(firemodes, "Aa"); break; } if(spec & INARC) { strcat(firemodes, "I"); strcat(ammomodes, "EHe"); break; } if(spec & NARC) { strcat(firemodes, "N"); break; } if(spec & IDF) { /* LRM */ strcat(ammomodes, "1ACMNSs"); strcat(damagetype, "g"); strcat(firemodes, "Hi"); } else if(spec & MRM) /* MRM */ strcat(damagetype, "g"); else /* SRM/SR_DFM */ strcat(ammomodes, "AIN"); if(spec & DFM) strcat(damagetype, "D"); if(spec & ELRM) strcat(damagetype, "e"); if(spec & STREAK) strcat(firemodes, "S"); break; case TAMMO: if(spec & GAUSS) { strcat(damagetype, "G"); if(spec & HVYGAUSS) strcat(damagetype, "H"); break; } strcat(damagetype, "B"); if(spec & CASELESS) strcat(damagetype, "C"); if(spec & HYPER) strcat(damagetype, "Y"); if(spec & RAC) strcat(firemodes, "246"); if(spec & GMG) strcat(firemodes, "G"); if(spec & RFAC) { strcat(firemodes, "R"); strcat(ammomodes, "FPai"); } if(spec & LBX) strcat(ammomodes, "L"); if(spec & ULTRA) strcat(firemodes, "U"); break; case TARTILLERY: strcat(damagetype, "Ag"); strcat(firemodes, "Hi"); strcat(ammomodes, "CMs"); break; case TBEAM: strcat(damagetype, "E"); if(spec & HVYW) strcat(damagetype, "h"); if(spec & PULSE) strcat(damagetype, "p"); if(spec & CHEAT) strcat(firemodes, "h"); if(spec & A_POD) strcat(damagetype, "a"); break; } if(spec & NOSPA) ammomodes[0] = '\0'; return 1; } static void hud_weaponlist(DESC * d, MECH * mech, char *msgclass, char *args) { int i; char firemodes[30] = ""; char ammomodes[20] = ""; char damagetype[10] = ""; char response[LBUF_SIZE]; struct weapon_struct *w; for(i = 0; i < num_def_weapons; i++) { firemodes[0] = ammomodes[0] = damagetype[0] = '\0'; if(!get_weaponmodes(i, firemodes, ammomodes, damagetype)) continue; if(strlen(firemodes) == 0) strcat(firemodes, "-"); if(strlen(ammomodes) == 0) strcat(ammomodes, "-"); w = &MechWeapons[i]; sprintf(response, "%d,%s,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%s,%s,%s,%d", i, w->name, w->min, w->shortrange, w->medrange, w->longrange, w->min_water, w->shortrange_water, w->medrange_water, w->longrange_water, w->criticals, w->weight, w->damage, w->vrt, firemodes, ammomodes, damagetype, w->heat * 10); hudinfo_notify(d, msgclass, "L", response); } hudinfo_notify(d, msgclass, "D", "Done"); } static void hud_limbstatus(DESC * d, MECH * mech, char *msgclass, char *args) { int locs[] = { RLEG, LLEG, RARM, LARM }; int todo = 3; UpdateRecycling(mech); if(MechType(mech) == CLASS_MECH) { for(; todo >= 0; todo--) { char *sect = ShortArmorSectionString(MechType(mech), MechMove(mech), locs[todo]); char status[10]; if(SectIsDestroyed(mech, locs[todo])) strcpy(status, "*"); else if(MechSections(mech)[locs[todo]].recycle > 0) sprintf(status, "%d", MechSections(mech)[locs[todo]].recycle / WEAPON_TICK); else strcpy(status, "R"); hudinfo_notify(d, msgclass, "L", tprintf("%s,%s", sect, status)); } } hudinfo_notify(d, msgclass, "D", "Done"); } static void hud_ammostatus(DESC * d, MECH * mech, char *msgclass, char *args) { unsigned char weapnums[8 * MAX_WEAPS_SECTION]; unsigned short curamm[8 * MAX_WEAPS_SECTION]; unsigned short maxamm[8 * MAX_WEAPS_SECTION]; unsigned int ammomode[8 * MAX_WEAPS_SECTION]; int i, ammonum; char response[LBUF_SIZE]; ammonum = FindAmmunition(mech, weapnums, curamm, maxamm, ammomode, 1); for(i = 0; i < ammonum; i++) { sprintf(response, "%d,%d,%s,%d,%d", i, weapnums[i], hud_getammomode(mech, ammomode[i]), curamm[i], maxamm[i]); hudinfo_notify(d, msgclass, "L", response); } hudinfo_notify(d, msgclass, "D", "Done"); } static char hud_typechar(MECH * mech) { if(MechMove(mech) == MOVE_NONE) return 'i'; switch (MechType(mech)) { case CLASS_MECH: if(MechMove(mech) == MOVE_QUAD) return 'Q'; return 'B'; case CLASS_VEH_GROUND: case CLASS_VEH_NAVAL: switch (MechMove(mech)) { case MOVE_TRACK: return 'T'; case MOVE_WHEEL: return 'W'; case MOVE_HOVER: return 'H'; case MOVE_HULL: return 'N'; case MOVE_FOIL: return 'Y'; case MOVE_SUB: return 'U'; default: SendError(tprintf("Unknown movement type on vehicle #%d: %d", mech->mynum, MechMove(mech))); return '?'; } case CLASS_VTOL: return 'V'; case CLASS_AERO: return 'F'; case CLASS_DS: return 'A'; case CLASS_SPHEROID_DS: return 'D'; case CLASS_MW: return 'I'; case CLASS_BSUIT: return 'S'; } SendError(tprintf("Unknown unit type on unit #%d: %d (move %d)", mech->mynum, MechType(mech), MechMove(mech))); return '?'; } static float MaxSettableSpeed(MECH * mech) { int maxspeed = MMaxSpeed(mech); if(MechMove(mech) == MOVE_VTOL) maxspeed = sqrt((float) maxspeed * maxspeed - MechVerticalSpeed(mech) * MechVerticalSpeed(mech)); maxspeed = maxspeed > 0.0 ? maxspeed : 0.0; if((MechSpecials(mech) & TRIPLE_MYOMER_TECH) && MechHeat(mech) >= 9.) maxspeed = ceil((rint((maxspeed / 1.5) / MP1) + 1) * 1.5) * MP1; return maxspeed; } static float MaxVerticalSpeed(MECH * mech) { int maxspeed = MMaxSpeed(mech); if(MechMove(mech) != MOVE_VTOL) return 0.0; maxspeed = sqrt((float) maxspeed * maxspeed - MechDesiredSpeed(mech) * MechDesiredSpeed(mech)); return maxspeed; } static char *hud_advtech(MECH * mech) { static char advtech[30]; char *p = advtech; int spec = MechSpecials(mech); if(spec & ECM_TECH) *p++ = 'E'; if(spec & BEAGLE_PROBE_TECH) *p++ = 'B'; if(spec & MASC_TECH) *p++ = 'M'; if(spec & AA_TECH) *p++ = 'R'; if(spec & SLITE_TECH) *p++ = 'S'; if(spec & TRIPLE_MYOMER_TECH) *p++ = 't'; spec = MechSpecials2(mech); if(spec & ANGEL_ECM_TECH) *p++ = 'A'; if(spec & NULLSIGSYS_TECH) *p++ = 'N'; if(spec & BLOODHOUND_PROBE_TECH) *p++ = 'b'; if(spec & STEALTH_ARMOR_TECH) *p++ = 's'; spec = MechInfantrySpecials(mech); if(spec & FC_INFILTRATORII_STEALTH_TECH) { *p++ = 'I'; *p++ = 'P'; } if(spec & CAN_JETTISON_TECH) *p++ = 'J'; if(spec & DC_KAGE_STEALTH_TECH) *p++ = 'K'; if(spec & INF_ANTILEG_TECH) *p++ = 'L'; if(spec & INF_SWARM_TECH) *p++ = 'W'; if(spec & FWL_ACHILEUS_STEALTH_TECH) *p++ = 'a'; if(spec & INF_MOUNT_TECH) *p++ = 'f'; if(spec & FC_INFILTRATOR_STEALTH_TECH) *p++ = 'i'; if(spec & MUST_JETTISON_TECH) *p++ = 'j'; if(spec & CS_PURIFIER_STEALTH_TECH) *p++ = 'p'; if(HasC3i(mech)) *p++ = 'C'; if(HasTAG(mech)) *p++ = 'T'; if(HasC3s(mech)) *p++ = 'c'; if(HasC3m(mech)) *p++ = 'm'; if(p == advtech) *p++ = '-'; *p = '\0'; return advtech; } static void hud_templateinfo(DESC * d, MECH * mech, char *msgclass, char *args) { char response[LBUF_SIZE]; char fuel[20]; if(FlyingT(mech) && AeroFuelOrig(mech)) sprintf(fuel, "%d", AeroFuelOrig(mech)); else strcpy(fuel, "-"); sprintf(response, "%c,%s,%s,%.3f,%.3f,%.3f,%.3f,%s,%d,%s", hud_typechar(mech), MechType_Ref(mech), MechType_Name(mech), WalkingSpeed(MaxSettableSpeed(mech)), MaxSettableSpeed(mech), -WalkingSpeed(MaxSettableSpeed(mech)), MaxVerticalSpeed(mech), fuel, MechRealNumsinks(mech), hud_advtech(mech)); hudinfo_notify(d, msgclass, "R", response); } static void hud_templatearmor(DESC * d, MECH * mech, char *msgclass, char *args) { char response[LBUF_SIZE]; int sect; for(sect = 0; sect < NUM_SECTIONS; sect++) { if(GetSectOInt(mech, sect)) { sprintf(response, "%s,%d,%d,%d", ShortArmorSectionString(MechType(mech), MechMove(mech), sect), GetSectOArmor(mech, sect), GetSectORArmor(mech, sect), GetSectOInt(mech, sect)); hudinfo_notify(d, msgclass, "L", response); } } hudinfo_notify(d, msgclass, "D", "Done"); } static void hud_armorstatus(DESC * d, MECH * mech, char *msgclass, char *args) { char response[LBUF_SIZE]; int sect; for(sect = 0; sect < NUM_SECTIONS; sect++) { if(GetSectOInt(mech, sect)) { sprintf(response, "%s,%d,%d,%d", ShortArmorSectionString(MechType(mech), MechMove(mech), sect), GetSectArmor(mech, sect), GetSectRArmor(mech, sect), GetSectInt(mech, sect)); hudinfo_notify(d, msgclass, "L", response); } } hudinfo_notify(d, msgclass, "D", "Done"); } static char *hud_arcstring(int arc) { static char arcstr[5]; char *p = arcstr; if(arc & FORWARDARC) *p++ = '*'; if(arc & LSIDEARC) *p++ = 'l'; if(arc & RSIDEARC) *p++ = 'r'; if(arc & REARARC) *p++ = 'v'; if(arc & TURRETARC) *p++ = 't'; if(p == arcstr) *p++ = '-'; *p = '\0'; return arcstr; } static char *hud_sensorstring(MECH * mech, int losflag) { if((losflag & MECHLOSFLAG_SEESP) && (losflag & MECHLOSFLAG_SEESS)) return "PS"; if(losflag & MECHLOSFLAG_SEESP) return "P"; if(losflag & MECHLOSFLAG_SEESS) return "S"; return "-"; } static void hud_contacts(DESC * d, MECH * mech, char *msgclass, char *args) { char response[LBUF_SIZE]; MECH *other; MAP *map = getMap(mech->mapindex); int i, losflag, bearing, btc, weaponarc, x, y; float range, rtc; char jumph[12]; char *mechname, *constat; if(!map) { hudinfo_notify(d, msgclass, "E", "You are on no map"); return; } for(i = 0; i < map->first_free; i++) { if(map->mechsOnMap[i] == mech->mynum || map->mechsOnMap[i] == -1) continue; other = (MECH *) FindObjectsData(map->mechsOnMap[i]); if(!other || !Good_obj(other->mynum)) continue; range = FlMechRange(map, mech, other); x = MechX(other); y = MechY(other); losflag = InLineOfSight(mech, other, x, y, range); if(!losflag) continue; bearing = FindBearing(MechFX(mech), MechFY(mech), MechFX(other), MechFY(other)); weaponarc = InWeaponArc(mech, MechFX(other), MechFY(other)); if(Jumping(other)) sprintf(jumph, "%d", MechJumpHeading(other)); else strcpy(jumph, "-"); FindRangeAndBearingToCenter(other, &rtc, &btc); if(!InLineOfSight_NB(mech, other, MechX(other), MechY(other), 0.0)) mechname = "something"; else mechname = silly_atr_get(other->mynum, A_MECHNAME); if(!mechname || !*mechname) mechname = "-"; constat = getStatusString(other, !MechSeemsFriend(mech, other)); if(strlen(constat) == 0) constat = "-"; sprintf(response, "%s,%s,%s,%c,%s,%d,%d,%d,%.3f,%d,%.3f,%.3f,%d,%s,%.3f,%d,%d,%.0f,%s", MechIDS(other, MechSeemsFriend(mech, other)), hud_arcstring(weaponarc), hud_sensorstring(mech, losflag), hud_typechar(other), mechname, MechX(other), MechY(other), MechZ(other), range, bearing, MechSpeed(other), MechVerticalSpeed(other), MechVFacing(other), jumph, rtc, btc, MechTons(other), MechHeat(other), constat); hudinfo_notify(d, msgclass, "L", response); } hudinfo_notify(d, msgclass, "D", "Done"); } static char *building_status(MAP * map, int locked) { static char buildingstatus[7]; char *p = buildingstatus; if(BuildIsCS(map)) *p++ = 'C'; if(locked) *p++ = 'E'; else *p++ = 'F'; if(BuildIsHidden(map)) *p++ = 'H'; if(BuildIsSafe(map) || (locked && BuildIsCS(map))) *p++ = 'X'; else if(locked) *p++ = 'x'; if(p == buildingstatus) *p++ = '-'; *p = '\0'; return buildingstatus; } static void hud_building_contacts(DESC * d, MECH * mech, char *msgclass, char *args) { char response[LBUF_SIZE]; MAP *map = getMap(mech->mapindex); MAP *building_map; char *building_name; mapobj *building; float fx, fy, range; int z, losflag, locked, bearing, weaponarc; if(!map) { hudinfo_notify(d, msgclass, "E", "You are on no map"); return; } for(building = first_mapobj(map, TYPE_BUILD); building; building = next_mapobj(building)) { MapCoordToRealCoord(building->x, building->y, &fx, &fy); z = Elevation(map, building->x, building->y) + 1; range = FindRange(MechFX(mech), MechFY(mech), MechFZ(mech), fx, fy, ZSCALE * z); if(!building->obj) continue; building_map = getMap(building->obj); if(!building_map) continue; losflag = InLineOfSight(mech, NULL, building->x, building->y, range); if(!losflag || (losflag & MECHLOSFLAG_BLOCK)) continue; if(BuildIsInvis(building_map)) continue; locked = !can_pass_lock(mech->mynum, building->obj, A_LENTER); if(locked && BuildIsHidden(building_map)) continue; bearing = FindBearing(MechFX(mech), MechFY(mech), fx, fy); weaponarc = InWeaponArc(mech, fx, fy); building_name = silly_atr_get(building->obj, A_MECHNAME); if(!building_name || !*building_name) building_name = strip_ansi(Name(building->obj)); if(!building_name || !*building_name) building_name = "-"; sprintf(response, "%s,%s,%d,%d,%d,%f,%d,%d,%d,%s", hud_arcstring(weaponarc), building_name, building->x, building->y, z, range, bearing, building_map->cf, building_map->cfmax, building_status(building_map, locked)); hudinfo_notify(d, msgclass, "L", response); } hudinfo_notify(d, msgclass, "D", "Done"); }; static char hud_damstr[] = "OoxX*?"; static char hud_damagechar(MECH * mech, int sect, int type) { int dummy; switch (type) { case 1: if(GetSectOArmor(mech, sect)) return hud_damstr[ArmorEvaluateSerious(mech, sect, 1, &dummy)]; return '-'; case 2: if(GetSectOInt(mech, sect)) return hud_damstr[ArmorEvaluateSerious(mech, sect, 2, &dummy)]; return '-'; case 4: if(GetSectORArmor(mech, sect)) return hud_damstr[ArmorEvaluateSerious(mech, sect, 4, &dummy)]; return '-'; } return '?'; } static MECH *hud_scantarget(DESC * d, MECH * mech, char *msgclass, char *args) { MECH *targ; float range; if(!MechScanRange(mech)) { hudinfo_notify(d, msgclass, "E", "Your system seems to be inoperational"); return NULL; } if(strlen(args) != 2 || !(targ = getMech(FindTargetDBREFFromMapNumber(mech, args)))) { hudinfo_notify(d, msgclass, "E", "No such target"); return NULL; } range = FaMechRange(mech, targ); if(!InLineOfSight(mech, targ, MechX(targ), MechY(targ), range)) { hudinfo_notify(d, msgclass, "E", "No such target"); return NULL; } if(!MechIsObservator(mech) && (int) range > MechScanRange(mech)) { hudinfo_notify(d, msgclass, "E", "Out of range"); return NULL; } if(MechType(targ) == CLASS_MW || !InLineOfSight_NB(mech, targ, MechX(targ), MechY(targ), range)) { hudinfo_notify(d, msgclass, "E", "Unable to scan target"); return NULL; } if(!MechIsObservator(mech)) { mech_notify(targ, MECHSTARTED, tprintf("You are being scanned by %s", GetMechToMechID(targ, mech))); auto_reply(targ, tprintf("%s just scanned me.", GetMechToMechID(targ, mech))); } return targ; } static void hud_armorscan(DESC * d, MECH * mech, char *msgclass, char *args) { char response[LBUF_SIZE]; int sect; MECH *targ; targ = hud_scantarget(d, mech, msgclass, args); if(!targ) return; for(sect = 0; sect < NUM_SECTIONS; sect++) { if(GetSectOInt(targ, sect)) { sprintf(response, "%s,%c,%c,%c", ShortArmorSectionString(MechType(targ), MechMove(targ), sect), hud_damagechar(targ, sect, 1), hud_damagechar(targ, sect, 4), hud_damagechar(targ, sect, 2)); hudinfo_notify(d, msgclass, "L", response); } } hudinfo_notify(d, msgclass, "D", "Done"); } static char *hud_getweapscanstatus(MECH * mech, int sect, int crit, int data) { if(PartIsNonfunctional(mech, sect, crit)) return "*"; if(data) return "-"; return "R"; } static void hud_weapscan(DESC * d, MECH * mech, char *msgclass, char *args) { int sect, weapcount, i, weapnum = -1; unsigned char weaparray[MAX_WEAPS_SECTION]; unsigned char weapdata[MAX_WEAPS_SECTION]; int critical[MAX_WEAPS_SECTION]; char response[LBUF_SIZE]; MECH *targ; targ = hud_scantarget(d, mech, msgclass, args); if(!targ) return; UpdateRecycling(targ); for(sect = 0; sect < NUM_SECTIONS; sect++) { if(SectIsDestroyed(targ, sect)) continue; weapcount = FindWeapons(targ, sect, weaparray, weapdata, critical); if(weapcount <= 0) continue; for(i = 0; i < weapcount; i++) { weapnum++; sprintf(response, "%d,%d,%s,%s", weapnum, weaparray[i], ShortArmorSectionString(MechType(targ), MechMove(targ), sect), hud_getweapscanstatus(targ, sect, critical [i], weapdata [i] / WEAPON_TICK)); hudinfo_notify(d, msgclass, "L", response); } } hudinfo_notify(d, msgclass, "D", "Done"); } static void hud_tactical(DESC * d, MECH * mech, char *msgclass, char *args) { MAP *map = getMap(mech->mapindex); char *argv[5], result[LBUF_SIZE], *p; char mapid[21], mapname[MBUF_SIZE]; int argc; int height = 24; short cx = MechX(mech), cy = MechY(mech); int sx, sy, ex, ey, x, y, losflag, lostactical = 0; hexlosmap_info *losmap = NULL; if(!MechLRSRange(mech)) { hudinfo_notify(d, msgclass, "E", "Your system seems to be inoperational"); return; } if(!map) { hudinfo_notify(d, msgclass, "E", "You are on no map"); return; } argc = mech_parseattributes(args, argv, 4); switch (argc) { case 4: if(strcmp("l", argv[3])) { hudinfo_notify(d, msgclass, "E", "Invalid fourth argument"); return; } lostactical = 1; /* FALLTHROUGH */ case 3:{ float fx, fy; int bearing = atoi(argv[1]); float range = atof(argv[2]); if(!MechIsObservator(mech) && abs((int) range) > MechLRSRange(mech)) { hudinfo_notify(d, msgclass, "E", "Out of range"); return; } FindXY(MechFX(mech), MechFY(mech), bearing, range, &fx, &fy); RealCoordToMapCoord(&cx, &cy, fx, fy); } /* FALLTHROUGH */ case 1: height = atoi(argv[0]); if(!height || height < 0 || height > 40) { hudinfo_notify(d, msgclass, "E", "Invalid 1st argument"); return; } break; default: hudinfo_notify(d, msgclass, "E", "Invalid arguments"); return; } height = MIN(height, 2 * MechLRSRange(mech)); height = MIN(height, map->map_height); sy = MAX(0, cy - height / 2); ey = MIN(map->map_height, cy + height / 2); sx = MAX(0, cx - LRS_DISPLAY_WIDTH / 2); ex = MIN(map->map_width, cx + LRS_DISPLAY_WIDTH / 2); if(lostactical || MapIsDark(map) || (MechType(mech) == CLASS_MW && mudconf.btech_mw_losmap)) losmap = CalculateLOSMap(map, mech, sx, sy, ex - sx, ey - sy); if(!mudconf.hudinfo_show_mapinfo || (mudconf.hudinfo_show_mapinfo == 1 && In_Character(map->mynum))) { strcpy(mapid, "-1"); strcpy(mapname, "-1"); } else { sprintf(mapid, "%d", map->mynum); sprintf(mapname, "%s", map->mapname); }; sprintf(result, "%d,%d,%d,%d,%s,%s,-1,%d,%d", sx, sy, ex - 1, ey - 1, mapid, mapname, map->map_width, map->map_height); hudinfo_notify(d, msgclass, "S", result); for(y = sy; y < ey; y++) { sprintf(result, "%d,", y); p = result + strlen(result); for(x = sx; x < ex; x++) { if(losmap) losflag = LOSMap_GetFlag(losmap, x, y); else losflag = MAPLOSHEX_SEE; if(losflag & MAPLOSHEX_SEETERRAIN) { *p = GetTerrain(map, x, y); if(*p == ' ') *p = '.'; *p++; } else *p++ = '?'; if(losflag & MAPLOSHEX_SEEELEV) *p++ = GetElev(map, x, y) + '0'; else *p++ = '?'; } *p = '\0'; hudinfo_notify(d, msgclass, "L", result); } hudinfo_notify(d, msgclass, "D", "Done"); } static char *hud_getmapflags(MAP * map) { static char res[5]; char *p = res; if(map->flags & MAPFLAG_VACUUM) *p++ = 'V'; if(map->flags & MAPFLAG_UNDERGROUND) *p++ = 'U'; if(map->flags & MAPFLAG_DARK) *p++ = 'D'; if(p == res) *p++ = '-'; *p = '\0'; return res; } static void hud_conditions(DESC * d, MECH * mech, char *msgclass, char *args) { MAP *map = getMap(mech->mapindex); char res[200]; char lt; switch (map->maplight) { case 0: lt = 'N'; break; case 1: lt = 'T'; break; case 2: lt = 'D'; break; default: lt = '?'; SendError(tprintf("Unknown light type %d on map #%d", map->maplight, map->mynum)); break; } sprintf(res, "%c,%d,%d,%d,%s", lt, map->mapvis, map->grav, map->temp, hud_getmapflags(map)); hudinfo_notify(d, msgclass, "R", res); } #endif