/*
* 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