btmux-0.6-rc4/doc/
btmux-0.6-rc4/event/
btmux-0.6-rc4/game/
btmux-0.6-rc4/game/maps/
btmux-0.6-rc4/game/mechs/
btmux-0.6-rc4/game/text/help/
btmux-0.6-rc4/game/text/help/cat_faction/
btmux-0.6-rc4/game/text/help/cat_inform/
btmux-0.6-rc4/game/text/help/cat_misc/
btmux-0.6-rc4/game/text/help/cat_mux/
btmux-0.6-rc4/game/text/help/cat_mux/cat_commands/
btmux-0.6-rc4/game/text/help/cat_mux/cat_functions/
btmux-0.6-rc4/game/text/help/cat_templates/
btmux-0.6-rc4/game/text/wizhelp/
btmux-0.6-rc4/include/
btmux-0.6-rc4/misc/
btmux-0.6-rc4/python/
btmux-0.6-rc4/src/hcode/btech/
btmux-0.6-rc4/tree/
/*
 * Author: Markus Stenberg <fingon@iki.fi>
 *
 *  Copyright (c) 1996 Markus Stenberg
 *  Copyright (c) 1998-2002 Thomas Wouters
 *  Copyright (c) 2000-2002 Cord Awtry
 *       All rights reserved
 */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/file.h>

#include "mech.h"
#include "mech.events.h"
#include "map.h"
#include "p.mech.utils.h"
#include "p.mech.los.h"

char *default_contactoptions = "!db";

static char *ac_desc[] = {
	"0 - See enemies and friends, long text, color",
	"1 - See enemies and friends, short text, color",
	"2 - See enemies only, long text, color",
	"3 - See enemies only, short text, color",
	"4 - See enemies and friends, short text, no color",
	"5 - See enemies only, short text, no color",

	"6 - Disabled"
};

static char *c_desc[] = {
	"0 - Very verbose",
	"1 - Short form, the usual one",
	"2 - Short form, the usual one, but do not see buildings",
	"3 - Shorter form"
};

void show_brief_flags(dbref player, MECH * mech)
{
	notify_printf(player, "Brief status for %s:", GetMechToMechID(mech,
																  mech));
#ifdef ADVANCED_LOS
	notify_printf(player, "    (A)utocontacts: %s", ac_desc[mech->brief / 4]);
#endif
	notify_printf(player, "    (C)ontacts:     %s", c_desc[mech->brief % 4]);
}

void mech_brief(dbref player, void *data, char *buffer)
{
	MECH *mech = (MECH *) data;
	char c;
	int v;

	cch(MECH_USUALSM);
	skipws(buffer);
	if(!*buffer) {
		show_brief_flags(player, mech);
		return;
	}
	c = *buffer;
	buffer++;
	skipws(buffer);
	DOCHECK(!*buffer, "Argument missing!");
	DOCHECK(Readnum(v, buffer), "Invalid number!");
	switch (toupper(c)) {
#ifdef ADVANCED_LOS
	case 'A':
		DOCHECK(v < 0 || v > 6, "Number out of range!");
		v = BOUNDED(0, v, 6);
		mech->brief = mech->brief % 4;
		mech->brief += v * 4;
		mech_printf(mech, MECHALL,
					"Autocontact brevity set to %s.", ac_desc[v]);
		return;
#endif
	case 'C':
		DOCHECK(v < 0 || v > 3, "Number out of range!");
		v = BOUNDED(0, v, 3);
		mech->brief = ((mech->brief / 4) * 4) + v;
		mech_printf(mech, MECHALL, "Contact brevity set to %s.", c_desc[v]);
		return;
	}
}

#define SEE_DEAD	0x01
#define SEE_SHUTDOWN	0x02
#define SEE_ALLY	0x04
#define SEE_ENEMA	0x08
#define SEE_TARGET	0x10
#define SEE_BUILDINGS	0x20
#define SEE_NEGNEXT	0x80

char getWeaponArc(MECH * mech, int arc)
{
	if(arc & FORWARDARC)
		return '*';
	else if(arc & TURRETARC)
		return 't';
	else if(arc & RSIDEARC)
		return 'r';
	else if(arc & LSIDEARC)
		return 'l';
	else if(arc & REARARC)
		return 'v';
	else
		return '?';
}

/* who: 0 for friend, 1 for enemy, 2 for 'self' */
char *getStatusString(MECH * target, int who)
{
	static char statusstr[20];
	int sptr = 0;

	if(Destroyed(target))
		statusstr[sptr++] = 'D';

	if(Starting(target))
		statusstr[sptr++] = 's';
	else if(!Started(target))
		statusstr[sptr++] = 'S';

	if(Standing(target))
		statusstr[sptr++] = 'f';
	else if(Fallen(target))
		statusstr[sptr++] = 'F';

	if(ChangingHulldown(target))
		statusstr[sptr++] = 'h';
	else if(IsHulldown(target))
		statusstr[sptr++] = 'H';

	if(Towed(target))
		statusstr[sptr++] = 'T';
	else if(MechCarrying(target) > 0)
		statusstr[sptr++] = 't';

	if(Jumping(target))
		statusstr[sptr++] = 'J';

	if(OODing(target))
		statusstr[sptr++] = 'O';

	if(MechHeat(target))
		statusstr[sptr++] = '+';

	if(Jellied(target))
		statusstr[sptr++] = 'I';

	if(Burning(target))
		statusstr[sptr++] = 'B';

	if(MechLites(target))
		statusstr[sptr++] = 'L';

	if(MechLit(target))
		statusstr[sptr++] = 'l';

	if(MechSwarmTarget(target) > 0)
		statusstr[sptr++] = 'W';

	if(CarryingClub(target))
		statusstr[sptr++] = 'C';

	if(checkAllSections(target, NARC_ATTACHED) ||
	   checkAllSections(target, INARC_HOMING_ATTACHED)) {
		if(who == 1)
			statusstr[sptr++] = 'N';
		else
			statusstr[sptr++] = 'n';
	}
#ifndef ECM_ON_CONTACTS
	if(who > 1) {
#endif
		if(AnyECCMActive(target))
			statusstr[sptr++] = 'P';

		if(AnyECMActive(target))
			statusstr[sptr++] = 'E';

		if(AnyECMProtected(target))
			statusstr[sptr++] = 'p';

		if(AnyECMDisturbed(target))
			statusstr[sptr++] = 'e';
#ifndef ECM_ON_CONTACTS
	}
#endif

	if(Spinning(target))
		statusstr[sptr++] = 'X';

#ifdef BT_MOVEMENT_MODES
	if(Sprinting(target))
		statusstr[sptr++] = 'M';
	if(Evading(target))
		statusstr[sptr++] = 'm';
#endif

	statusstr[sptr] = '\0';
	return statusstr;
}

char getStatusChar(MECH * mech, MECH * mechTarget, int wCharNum)
{
	char cRet = ' ';

	switch (wCharNum) {
	case 1:
		cRet = MechSwarmTarget(mechTarget) > 0 ? 'W' :
			Towed(mechTarget) ? 'T' : MechCarrying(mechTarget) >
			0 ? 't' : CarryingClub(mechTarget) ? 'C' :
#ifdef BT_MOVEMENT_MODES
			Sprinting(mechTarget) ? 'M' : Evading(mechTarget) ? 'm' :
#endif
			' ';
		break;
	case 2:
		cRet = Destroyed(mechTarget) ? 'D' :
			MechLites(mechTarget) ? 'L' : MechLit(mechTarget) ? 'l' : ' ';
		break;
	case 3:
		cRet = Jumping(mechTarget) ? 'J' : OODing(mechTarget) ? 'O' :
			Fallen(mechTarget) ? 'F' : Standing(mechTarget) ? 'f' :
			ChangingHulldown(mechTarget) ? 'h' : IsHulldown(mechTarget) ?
			'H' : Spinning(mech) ? 'X' : ' ';
		break;
	case 4:
		cRet = Started(mechTarget) ?
			(MechHeat(mechTarget) ? '+' :
			 Jellied(mechTarget) ? 'I' :
			 Burning(mechTarget) ? 'B' : ' ') :
			Staggering(mechTarget) ? 'G' : Starting(mechTarget) ? 's' : 'S';
		break;
	case 5:
		cRet = (checkAllSections(mechTarget, NARC_ATTACHED) ||
				checkAllSections(mechTarget, INARC_HOMING_ATTACHED)) ?
			(MechTeam(mechTarget) == MechTeam(mech) ? 'n' : 'N') :
#ifdef ECM_ON_CONTACTS
			AnyECCMActive(mechTarget) ? 'P' :
			AnyECMActive(mechTarget) ? 'E' :
			AnyECMProtected(mechTarget) ? 'p' :
			AnyECMDisturbed(mechTarget) ? 'e' :
#endif
			' ';
		break;
	}

	return cRet;
}

void mech_contacts(dbref player, void *data, char *buffer)
{
	MECH *mech = (MECH *) data, *tempMech;
	MAP *mech_map = getMap(mech->mapindex), *tmp_map;
	mapobj *building;
	int loop, i, j, argc, bearing, buffindex = 0;
	char *args[1], bufflist[MAX_MECHS_PER_MAP][120], buff[100];
	int sbuff[MAX_MECHS_PER_MAP];
	float range, rangelist[MAX_MECHS_PER_MAP], fx, fy;
	int mechfound;
	char weaponarc;
	char *mech_name;
	char see_what;
	char *str;
	char move_type[30];
	char cStatus1, cStatus2, cStatus3, cStatus4, cStatus5;
	int losflag;
	int isvb;
	int inlos;
	int IsUsingHUD = 0;

	cch(MECH_USUAL);
	mechfound = 0;
	argc = mech_parseattributes(buffer, args, 1);

	isvb = (mech->brief % 4);
	if(argc > 0) {
		if(args[0][0] == 'h') {
			IsUsingHUD = 1;
			see_what =
				(SEE_DEAD | SEE_SHUTDOWN | SEE_ENEMA | SEE_ALLY | SEE_TARGET);
		} else {
			if(args[0][0] == '+') {
				str = silly_atr_get(player, A_CONTACTOPT);
				if(!*str)
					strcpy(buff, default_contactoptions);
				else {
					strncpy(buff, str, 50);
					buff[49] = 0;

					if(strlen(buff) == 0)
						strcpy(buff, default_contactoptions);
				}
			} else {
				strncpy(buff, args[0], 50);
				buff[49] = 0;
			}

			if(isvb == 1)
				see_what = SEE_BUILDINGS;
			else
				see_what = 0x0;

			for(loop = 0; loop < 50 && buff[loop]; loop++) {
				char c;

				c = buff[loop];

				if(c == 'd')

					(see_what & SEE_NEGNEXT) ? (see_what &=
												~SEE_DEAD) : (see_what |=
															  SEE_DEAD);
				else if(c == 's')
					(see_what & SEE_NEGNEXT) ? (see_what &=
												~SEE_SHUTDOWN) : (see_what |=
																  SEE_SHUTDOWN);
				else if(c == 'b')
					(see_what & SEE_NEGNEXT) ? (see_what &=
												~SEE_BUILDINGS) : (see_what |=
																   SEE_BUILDINGS);
				else if(c == 'e')
					(see_what & SEE_NEGNEXT) ? (see_what &=
												~SEE_ENEMA) : (see_what |=
															   SEE_ENEMA);
				else if(c == 'a')
					(see_what & SEE_NEGNEXT) ? (see_what &=
												~SEE_ALLY) : (see_what |=
															  SEE_ALLY);
				else if(c == 't')
					(see_what & SEE_NEGNEXT) ? (see_what &=
												~SEE_TARGET) : (see_what |=
																SEE_TARGET);
				else if(c == '!') {
					see_what =
						(SEE_NEGNEXT | SEE_DEAD | SEE_SHUTDOWN | SEE_ENEMA
						 | SEE_ALLY | SEE_TARGET);
				} else
					notify_printf(player,
								  "Ignoring %c as contact option.", c);
			}
		}
	} else {
		see_what =
			(SEE_DEAD | SEE_SHUTDOWN | SEE_ENEMA | SEE_ALLY | SEE_TARGET);
		if(isvb == 1)
			see_what |= SEE_BUILDINGS;
	}

	if(IsUsingHUD)
		notify(player, "#HUDINFO:CON#Line of Sight Contacts:");
	else if(isvb <= 2)
		notify(player, "Line of Sight Contacts:");

	for(loop = 0; loop < mech_map->first_free; loop++) {
		if(!(mech_map->mechsOnMap[loop] != mech->mynum &&
			 mech_map->mechsOnMap[loop] != -1))
			continue;

		tempMech = (MECH *) FindObjectsData(mech_map->mechsOnMap[loop]);

		if(!tempMech)
			continue;
		if(argc) {
			if(!((MechSeemsFriend(mech, tempMech) ? (see_what & SEE_ALLY)
				  : (see_what & SEE_ENEMA)) ||
				 ((see_what & SEE_TARGET) &&
				  (tempMech->mynum == MechTarget(mech)))))
				continue;
			if(!(((see_what & SEE_SHUTDOWN) || Started(tempMech)) ||
				 Destroyed(tempMech) || ((see_what & SEE_TARGET) &&
										 (tempMech->mynum ==
										  MechTarget(mech)))))
				continue;
			if(!(((see_what & SEE_DEAD) || !Destroyed(tempMech)) ||
				 ((see_what & SEE_TARGET) &&
				  (tempMech->mynum == MechTarget(mech)))))
				continue;
		}
		range = FlMechRange(mech_map, mech, tempMech);
		if(!(losflag =
			 InLineOfSight(mech, tempMech, MechX(tempMech),
						   MechY(tempMech), range)))
			continue;
		if(Good_obj(tempMech->mynum)) {
			if(!InLineOfSight_NB(mech, tempMech, MechX(tempMech),
								 MechY(tempMech), 0.0)) {
				mech_name = "something";
				inlos = 0;
			} else {
				mech_name = silly_atr_get(tempMech->mynum, A_MECHNAME);
				inlos = 1;
			}
		} else
			continue;
		bearing =
			FindBearing(MechFX(mech), MechFY(mech), MechFX(tempMech),
						MechFY(tempMech));
		weaponarc = getWeaponArc(mech, InWeaponArc(mech, MechFX(tempMech),
												   MechFY(tempMech)));

		strcpy(move_type, GetMoveTypeID(MechMove(tempMech)));

		if(isvb) {
			if(!inlos) {
				cStatus1 = ' ';
				cStatus2 = ' ';
				cStatus3 = ' ';
				cStatus4 = ' ';
				cStatus5 = ' ';
			} else {
				cStatus1 = getStatusChar(mech, tempMech, 1);
				cStatus2 = getStatusChar(mech, tempMech, 2);
				cStatus3 = getStatusChar(mech, tempMech, 3);
				cStatus4 = getStatusChar(mech, tempMech, 4);
				cStatus5 = getStatusChar(mech, tempMech, 5);
			}

			if(!IsUsingHUD) {
#ifdef SIMPLE_SENSORS
				sprintf(buff,
						"%s%c[%s]%c %-12.12s x:%3d y:%3d z:%3d r:%4.1f b:%3d s:%5.1f h:%3d S:%c%c%c%c%c%s",
#else
				sprintf(buff,
						"%s%c%c%c[%s]%c %-12.12s x:%3d y:%3d z:%3d r:%4.1f b:%3d s:%5.1f h:%3d S:%c%c%c%c%c%s",
#endif
						tempMech->mynum == MechTarget(mech) ? "%ch%cr" :
						!MechSeemsFriend(mech, tempMech) ? "%ch%cy" : "",
#ifndef SIMPLE_SENSORS
						(losflag & MECHLOSFLAG_SEESP) ? 'P' : ' ',
						(losflag & MECHLOSFLAG_SEESS) ? 'S' : ' ',
#endif
						weaponarc, MechIDS(tempMech,
										   MechSeemsFriend(mech, tempMech)),
						move_type[0], mech_name, MechX(tempMech),
						MechY(tempMech), MechZ(tempMech), range, bearing,
						MechSpeed(tempMech), MechVFacing(tempMech),
						cStatus1,
						cStatus2,
						cStatus3,
						cStatus4,
						cStatus5,
						(tempMech->mynum == MechTarget(mech) ||
						 !MechSeemsFriend(mech, tempMech)) ? "%c" : "");
			} else {
#ifdef SIMPLE_SENSORS
				sprintf(buff, "#HUDINFO:CON#%c,%c,%s,%c,%-12.12s,%3d,%3d,%3d,%4.1f,%3d,%4.1f,%3d,%c%c%c%c%c",	/* ) <- balance */
#else
				sprintf(buff,
						"#HUDINFO:CON#%c,%c,%c,%c,%s,%c,%-12.12s,%3d,%3d,%3d,%4.1f,%3d,%4.1f,%3d,%c%c%c%c%c",
#endif
						(tempMech->mynum == MechTarget(mech)) ? 'T' :
						!MechSeemsFriend(mech, tempMech) ? 'E' : 'F',
#ifndef SIMPLE_SENSORS
						(losflag & MECHLOSFLAG_SEESP) ? 'P' : ' ',
						(losflag & MECHLOSFLAG_SEESS) ? 'S' : ' ',
#endif
						weaponarc, MechIDS(tempMech,
										   MechSeemsFriend(mech, tempMech)),
						move_type[0], mech_name, MechX(tempMech),
						MechY(tempMech), MechZ(tempMech), range, bearing,
						MechSpeed(tempMech), MechVFacing(tempMech),
						cStatus1, cStatus2, cStatus3, cStatus4, cStatus5);
			}

			rangelist[buffindex] = range;
			rangelist[buffindex] +=
				(MechStatus(tempMech) & DESTROYED) ? 10000 : 0;
			strcpy(bufflist[buffindex++], buff);
		} else {
			sprintf(buff, "[%s] %-17s  Tonnage: %d", MechIDS(tempMech,
															 MechSeemsFriend
															 (mech,
															  tempMech)),
					mech_name, MechTons(tempMech));
			notify(player, buff);
			sprintf(buff, "      Range: %.1f hex\tBearing: %d degrees",
					range, bearing);
			notify(player, buff);
			sprintf(buff, "      Speed: %.1f KPH\tHeading: %d degrees",
					MechSpeed(tempMech), MechVFacing(tempMech));
			notify(player, buff);
			sprintf(buff, "      X, Y: %3d, %3d \tHeat: %.0f deg C.",
					MechX(tempMech), MechY(tempMech), MechHeat(tempMech));
			notify(player, buff);
			sprintf(buff, "      Movement Type: %s", move_type);
			notify(player, buff);
			notify_printf(player, "      Mech is in %s Arc",
						  GetArcID(mech, InWeaponArc(mech, MechFX(tempMech),
													 MechFY(tempMech))));
			if(MechStatus(tempMech) & DESTROYED)
				notify(player, "      Mech Destroyed");
			if(!(MechStatus(tempMech) & STARTED))
				notify(player, "      Mech Shutdown");
			if(Fallen(tempMech))
				notify(player, "      Mech has Fallen!");
			if(Jumping(tempMech))
				notify_printf(player,
							  "      Mech is Jumping!\tJump Heading: %d",
							  MechJumpHeading(tempMech));
			notify(player, " ");
		}
	}

	if(see_what & SEE_BUILDINGS) {
		for(building = first_mapobj(mech_map, TYPE_BUILD); building;
			building = next_mapobj(building)) {

			MapCoordToRealCoord(building->x, building->y, &fx, &fy);
			range =
				FindRange(MechFX(mech), MechFY(mech), MechFZ(mech), fx, fy,
						  ZSCALE * ((i =
									 Elevation(mech_map, building->x,
											   building->y)) + 1));

			losflag =
				InLineOfSight(mech, NULL, building->x, building->y, range);
			if(!losflag || (losflag & MECHLOSFLAG_BLOCK))
				continue;

			if(!(building->obj && (tmp_map = getMap(building->obj))))
				continue;
			if(BuildIsInvis(tmp_map))
				continue;
			if((j = !can_pass_lock(mech->mynum, tmp_map->mynum, A_LENTER))
			   && BuildIsHidden(tmp_map))
				continue;
			bearing = FindBearing(MechFX(mech), MechFY(mech), fx, fy);
			weaponarc = getWeaponArc(mech, InWeaponArc(mech, fx, fy));

			mech_name = silly_atr_get(building->obj, A_MECHNAME);
			if(!mech_name || !*mech_name)
				mech_name = strip_ansi(Name(building->obj));

			if(!IsUsingHUD) {
#ifdef SIMPLE_SENSORS
				sprintf(buff,
						"%s%c %-23.23s x:%3d y:%3d z:%2d r:%4.1f b:%3d CF:%4d /%4d S:%c%c%s",
#else
				sprintf(buff,
						"%s%c%c%c %-23.23s x:%3d y:%3d z:%2d r:%4.1f b:%3d CF:%4d /%4d S:%c%c%s",
#endif
						j ? "%ch%cy" : "",
#ifndef SIMPLE_SENSORS
						(losflag & MECHLOSFLAG_SEESP) ? 'P' : ' ',
						(losflag & MECHLOSFLAG_SEESS) ? 'S' : ' ',
#endif
						weaponarc, mech_name, building->x, building->y, i,
						range, bearing, tmp_map->cf, tmp_map->cfmax,
						(BuildIsSafe(tmp_map) || (j &&
												  BuildIsCS(tmp_map))) ? 'X' :
						j ? 'x' : BuildIsCS(tmp_map) ? 'C' : ' ',
						BuildIsHidden(tmp_map) ? 'H' : ' ', j ? "%c" : "");
			} else {
#ifdef SIMPLE_SENSORS
				sprintf(buff, "#HUDINFO:CON#%c,%c,%-21.21s,%3d,%3d,%3d,%4.1f,%3d,%4d,%4d,%c%c",	/* ) <- balance */
#else
				sprintf(buff,
						"#HUDINFO:CON#%c,%c,%c,%c,%-21.21s,%3d,%3d,%3d,%4.1f,%3d,%4d,%4d,%c%c",
#endif
						j ? 'E' : 'F',
#ifndef SIMPLE_SENSORS
						(losflag & MECHLOSFLAG_SEESP) ? 'P' : ' ',
						(losflag & MECHLOSFLAG_SEESS) ? 'S' : ' ',
#endif
						weaponarc, mech_name, building->x, building->y, i,
						range, bearing, tmp_map->cf, tmp_map->cfmax,
						(BuildIsSafe(tmp_map) || (j &&
												  BuildIsCS(tmp_map))) ? 'X' :
						j ? 'x' : BuildIsCS(tmp_map) ? 'C' : ' ',
						BuildIsHidden(tmp_map) ? 'H' : ' ');
			}
			rangelist[buffindex] = range + 20000;
			strcpy(bufflist[buffindex++], buff);
		}
	}

	if(isvb) {
		for(i = 0; i < buffindex; i++)
			sbuff[i] = i;
		/* print a sorted list of detected mechs */
		/* use the ever-popular bubble sort */
		for(i = 0; i < (buffindex - 1); i++)
			for(j = (i + 1); j < buffindex; j++)
				if(rangelist[sbuff[j]] > rangelist[sbuff[i]]) {
					loop = sbuff[i];
					sbuff[i] = sbuff[j];
					sbuff[j] = loop;
				}
		for(loop = 0; loop < buffindex; loop++)
			notify(player, bufflist[sbuff[loop]]);
	}

	if(IsUsingHUD)
		notify(player, "#HUDINFO:CON#End Contact List");
	else if(isvb <= 2)
		notify(player, "End Contact List");
}

#undef SEE_DEAD
#undef SEE_SHUTDOWN
#undef SEE_ALLY
#undef SEE_ENEMA
#undef SEE_TARGET
#undef SEE_BUILDINGS
#undef SEE_NEGNEXT