btmux/autom4te.cache/
btmux/doc/.svn/
btmux/event/.svn/
btmux/game/.svn/
btmux/game/bin/.svn/
btmux/game/data/.svn/
btmux/game/logs/.svn/
btmux/game/maps/
btmux/game/maps/.svn/
btmux/game/maps/.svn/prop-base/
btmux/game/maps/.svn/props/
btmux/game/maps/.svn/text-base/
btmux/game/maps/.svn/wcprops/
btmux/game/mechs/
btmux/game/mechs/.svn/
btmux/game/mechs/.svn/prop-base/
btmux/game/mechs/.svn/props/
btmux/game/mechs/.svn/text-base/
btmux/game/mechs/.svn/wcprops/
btmux/game/text/.svn/
btmux/include/.svn/
btmux/misc/
btmux/misc/.svn/
btmux/misc/.svn/prop-base/
btmux/misc/.svn/props/
btmux/misc/.svn/text-base/
btmux/misc/.svn/wcprops/
btmux/python/
btmux/python/.svn/
btmux/python/.svn/prop-base/
btmux/python/.svn/props/
btmux/python/.svn/text-base/
btmux/python/.svn/wcprops/
btmux/src/.svn/prop-base/
btmux/src/.svn/props/
btmux/src/.svn/text-base/
btmux/src/.svn/wcprops/
btmux/src/hcode/.svn/
btmux/src/hcode/btech/
btmux/src/hcode/btech/.svn/
btmux/src/hcode/btech/.svn/prop-base/
btmux/src/hcode/btech/.svn/props/
btmux/src/hcode/btech/.svn/text-base/
btmux/src/hcode/btech/.svn/wcprops/
btmux/src/hcode/include/.svn/
/*
 * $Id: mech.c3.misc.c,v 1.1.1.1 2005/01/11 21:18:12 kstevens Exp $
 *
 * Author: Cord Awtry <kipsta@mediaone.net>
 *  Copyright (c) 2000-2002 Cord Awtry
 *       All rights reserved
 *
 * Based on work that was:
 *  Copyright (c) 1997 Markus Stenberg
 *  Copyright (c) 1998-2000 Thomas Wouters
 */

#include "mech.h"
#include "p.mech.c3.misc.h"
#include "p.mech.c3.h"
#include "p.mech.c3i.h"
#include "p.mech.utils.h"
#include "p.mech.los.h"
#include "p.mech.contacts.h"

#define TARG_LOS_NONE 0
#define TARG_LOS_CLEAR 1
#define TARG_LOS_SOMETHING 2

#define DEBUG_C3 0

MECH *getMechInTempNetwork(int wIdx, dbref * myNetwork, int networkSize)
{
    MECH *tempMech;
    dbref refOtherMech;

    if ((wIdx > networkSize) || (wIdx < 0))
	return NULL;

    refOtherMech = myNetwork[wIdx];

    if (refOtherMech > 0) {
	tempMech = getMech(refOtherMech);

	if (!tempMech)
	    return NULL;

	if (Destroyed(tempMech))
	    return NULL;

	return tempMech;
    }

    return NULL;
}

MECH *getOtherMechInNetwork(MECH * mech, int wIdx, int tCheckECM,
    int tCheckStarted, int tCheckUncon, int tIsC3)
{
    MECH *tempMech;
    dbref refOtherMech;
    int networkSize;

    networkSize =
	(tIsC3 ? MechC3NetworkSize(mech) : MechC3iNetworkSize(mech));

    if ((wIdx >= networkSize) || (wIdx < 0))
	return NULL;

    refOtherMech =
	(tIsC3 ? MechC3NetworkElem(mech, wIdx) : MechC3iNetworkElem(mech,
	    wIdx));

    if (refOtherMech > 0) {
	tempMech = getMech(refOtherMech);

	if (!tempMech)
	    return NULL;

	if (MechTeam(tempMech) != MechTeam(mech))
	    return NULL;

	if (tempMech->mapindex != mech->mapindex)
	    return NULL;

	if (Destroyed(tempMech))
	    return NULL;

	if (tIsC3) {
	    if (!HasC3(tempMech))	/* Sanity check */
		return NULL;

	    if (C3Destroyed(tempMech))
		return NULL;
	} else {
	    if (!HasC3i(tempMech))	/* Sanity check */
		return NULL;

	    if (C3iDestroyed(tempMech))
		return NULL;
	}

	if (tCheckECM)
	    if (AnyECMDisturbed(tempMech))
		return NULL;

	if (tCheckStarted)
	    if (!Started(tempMech))
		return NULL;

	if (tCheckUncon)
	    if (Uncon(tempMech))
		return NULL;

	return tempMech;
    }

    return NULL;
}

void buildTempNetwork(MECH * mech, dbref * myNetwork, int *networkSize,
    int tCheckECM, int tCheckStarted, int tCheckUncon, int tIsC3)
{
    int tempNetworkSize = 0;
    int baseNetworkSize;
    MECH *otherMech;
    dbref myTempNetwork[C3_NETWORK_SIZE];
    int i;

    /* Re-init the network */
    for (i = 0; i < C3_NETWORK_SIZE; i++)
	myNetwork[i] = -1;

    *networkSize = 0;

    baseNetworkSize =
	(tIsC3 ? MechC3NetworkSize(mech) : MechC3iNetworkSize(mech));

    if (baseNetworkSize == 0)
	return;

    /*
     * Build the base netork of all the mechs that fit the criteria we passed in
     */
    for (i = 0; i < baseNetworkSize; i++) {
	otherMech =
	    getOtherMechInNetwork(mech, i, tCheckECM, tCheckStarted,
	    tCheckUncon, tIsC3);

	if (!otherMech)
	    continue;

	if (!Good_obj(otherMech->mynum))
	    continue;

	myTempNetwork[tempNetworkSize] = otherMech->mynum;
	tempNetworkSize++;
    }

    /*
     * Once we're here, we're done with the C3i stuff, but we need to make sure that this is a valid C3 network
     * still. For example, we may have lost a master due to death or something else, so we need to make sure we
     * have enough masters left to actually do something.
     *
     * A valid network is one where there are MIN((((NUM_MASTERS * 4) - NUM_MASTERS) + ((MY_MASTERS * 4) - MY_MASTERS), 11) units in the network
     */
    if (tIsC3) {
	if (tempNetworkSize > 0)
	    tempNetworkSize =
		trimC3Network(mech, myTempNetwork, tempNetworkSize);
    }

    for (i = 0; i < tempNetworkSize; i++)
	myNetwork[i] = myTempNetwork[i];

    *networkSize = tempNetworkSize;
}

void sendNetworkMessage(dbref player, MECH * mech, char *msg, int tIsC3)
{
    int i;
    MECH *otherMech;
    const char *c = GetMechID(mech);
    char buf[LBUF_SIZE];
    int networkSize;
    dbref myNetwork[C3_NETWORK_SIZE];

    buildTempNetwork(mech, myNetwork, &networkSize, 1, 1, 1, tIsC3);

    for (i = 0; i < networkSize; i++) {
	otherMech = getMechInTempNetwork(i, myNetwork, networkSize);

	if (!otherMech)
	    continue;

	if (!Good_obj(otherMech->mynum))
	    continue;

	sprintf(buf, "%%ch%s/%s: %s%%cn", (tIsC3 ? "C3" : "C3i"), c, msg);
	mech_notify(otherMech, MECHALL, buf);
    }

    sprintf(buf, "%%ch%s/You: %s%%cn", (tIsC3 ? "C3" : "C3i"), msg);
    mech_notify(mech, MECHALL, buf);
}

void showNetworkTargets(dbref player, MECH * mech, int tIsC3)
{
    MAP *objMap = getMap(mech->mapindex);
    int i, j, wTemp, bearing;
    MECH *otherMech;
    float realRange, c3Range;
    char buff[100];
    char *mech_name;
    char move_type[30];
    char cStatus1, cStatus2, cStatus3, cStatus4, cStatus5;
    char weaponarc;
    int losFlag;
    int arc;
    int wSeeTarget = TARG_LOS_NONE;
    int wC3SeeTarget = TARG_LOS_NONE;
    int tShowStatusInfo = 0;
    char bufflist[MAX_MECHS_PER_MAP][120];
    float rangelist[MAX_MECHS_PER_MAP];
    int buffindex = 0;
    int sbuff[MAX_MECHS_PER_MAP];
    int networkSize;
    dbref myNetwork[C3_NETWORK_SIZE];
    dbref c3Ref;

    buildTempNetwork(mech, myNetwork, &networkSize, 1, 1, 0, tIsC3);

    /*
     * Send then a 'contacts' style report. This is different from the
     * normal contacts since it has a 'physical' range in it too.
     */
    notify(player, tprintf("%s Contacts:", tIsC3 ? "C3" : "C3i"));

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

	otherMech = (MECH *) FindObjectsData(objMap->mechsOnMap[i]);

	if (!otherMech)
	    continue;

	if (!Good_obj(otherMech->mynum))
	    continue;

	tShowStatusInfo = 0;
	realRange = FlMechRange(objMap, mech, otherMech);
	losFlag =
	    InLineOfSight(mech, otherMech, MechX(otherMech),
	    MechY(otherMech), realRange);

	/*
	 * If we do see them, let's make sure it's not just a 'something'
	 */
	if (losFlag) {
	    if (InLineOfSight_NB(mech, otherMech, MechX(otherMech),
		    MechY(otherMech), 0.0))
		wSeeTarget = TARG_LOS_CLEAR;
	    else
		wSeeTarget = TARG_LOS_SOMETHING;
	} else
	    wSeeTarget = TARG_LOS_NONE;

	/*
	 * If I don't see it, let's see if someone else in the network does
	 */
	if (wSeeTarget != TARG_LOS_CLEAR)
	    wC3SeeTarget = mechSeenByNetwork(mech, otherMech, tIsC3);

	/* If noone sees it, we continue */
	if (!wSeeTarget && !wC3SeeTarget)
	    continue;

	/* Get our network range */
	c3Range =
	    findC3RangeWithNetwork(mech, otherMech, realRange, myNetwork,
	    networkSize, &c3Ref);

	/* Figure out if we show the info or not... ie, do we actually 'see' it */
	if ((wSeeTarget != TARG_LOS_CLEAR) &&
	    (wC3SeeTarget != TARG_LOS_CLEAR)) {
	    tShowStatusInfo = 0;
	    mech_name = "something";
	} else {
	    tShowStatusInfo = 1;
	    mech_name = silly_atr_get(otherMech->mynum, A_MECHNAME);
	}

	bearing =
	    FindBearing(MechFX(mech), MechFY(mech), MechFX(otherMech),
	    MechFY(otherMech));
	strcpy(move_type, GetMoveTypeID(MechMove(otherMech)));

	/* Get our weapon arc */
	arc = InWeaponArc(mech, MechFX(otherMech), MechFY(otherMech));
	weaponarc = getWeaponArc(mech, arc);

	/* Now get our status chars */
	if (!tShowStatusInfo) {
	    cStatus1 = ' ';
	    cStatus2 = ' ';
	    cStatus3 = ' ';
	    cStatus4 = ' ';
	    cStatus5 = ' ';
	} else {
	    cStatus1 = getStatusChar(mech, otherMech, 1);
	    cStatus2 = getStatusChar(mech, otherMech, 2);
	    cStatus3 = getStatusChar(mech, otherMech, 3);
	    cStatus4 = getStatusChar(mech, otherMech, 4);
	    cStatus5 = getStatusChar(mech, otherMech, 5);
	}

	/* Now, build the string */
	sprintf(buff,
	    "%s%c%c%c[%s]%c %-11.11s x:%3d y:%3d z:%3d r:%4.1f c:%4.1f b:%3d s:%5.1f h:%3d S:%c%c%c%c%c%s",
	    otherMech->mynum == MechTarget(mech) ? "%ch%cr" :
	    (tShowStatusInfo &&
	    	!MechSeemsFriend(mech, otherMech)) ? "%ch%cy" : "",
	    (losFlag & MECHLOSFLAG_SEESP) ? 'P' : ' ',
	    (losFlag & MECHLOSFLAG_SEESS) ? 'S' : ' ', weaponarc,
	    MechIDS(otherMech, MechSeemsFriend(mech, otherMech) ||
		!tShowStatusInfo), move_type[0], mech_name,
	    MechX(otherMech), MechY(otherMech), MechZ(otherMech),
	    realRange, c3Range, bearing, MechSpeed(otherMech),
	    MechVFacing(otherMech), cStatus1, cStatus2, cStatus3, cStatus4,
	    cStatus5, (otherMech->mynum == MechTarget(mech) ||
		!MechSeemsFriend(mech, otherMech)) ? "%c" : "");

	rangelist[buffindex] = realRange;
	rangelist[buffindex] +=
	    (MechStatus(otherMech) & DESTROYED) ? 10000 : 0;
	strcpy(bufflist[buffindex++], buff);
    }

    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]]) {
		wTemp = sbuff[i];
		sbuff[i] = sbuff[j];
		sbuff[j] = wTemp;
	    }

    for (i = 0; i < buffindex; i++)
	notify(player, bufflist[sbuff[i]]);

    notify(player, tprintf("End %s Contact List", tIsC3 ? "C3" : "C3i"));
}

void showNetworkData(dbref player, MECH * mech, int tIsC3)
{
    int i, bearing;
    MECH *otherMech;
    float range;
    char buff[100];
    char *mech_name;
    char move_type[30];
    int networkSize;
    dbref myNetwork[C3_NETWORK_SIZE];

    notify(player, tprintf("%s Network Status:", tIsC3 ? "C3" : "C3i"));

    buildTempNetwork(mech, myNetwork, &networkSize, 1, 1, 0, tIsC3);

    for (i = 0; i < networkSize; i++) {
	otherMech = getMechInTempNetwork(i, myNetwork, networkSize);

	if (!otherMech)
	    continue;

	if (!Good_obj(otherMech->mynum))
	    continue;

	range = FlMechRange(objMap, mech, otherMech);
	bearing =
	    FindBearing(MechFX(mech), MechFY(mech), MechFX(otherMech),
	    MechFY(otherMech));

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

	mech_name = silly_atr_get(otherMech->mynum, A_MECHNAME);

	sprintf(buff,
	    "%%ch%%cy[%s]%c %-12.12s x:%3d y:%3d z:%3d r:%4.1f b:%3d s:%5.1f h:%3d a: %3d i: %3d%%cn",
	    MechIDS(otherMech, 1), move_type[0], mech_name,
	    MechX(otherMech), MechY(otherMech), MechZ(otherMech), range,
	    bearing, MechSpeed(otherMech), MechVFacing(otherMech),
	    getRemainingArmorPercent(otherMech),
	    getRemainingInternalPercent(otherMech));

	notify(player, buff);

    }

    notify(player, tprintf("End %s Network Status", tIsC3 ? "C3" : "C3i"));
}

int mechSeenByNetwork(MECH * mech, MECH * mechTarget, int tIsC3)
{
    int los = TARG_LOS_NONE;
    float range = 0.0;
    int i;
    int networkSize;
    dbref myNetwork[C3_NETWORK_SIZE];
    MECH *otherMech;

    buildTempNetwork(mech, myNetwork, &networkSize, 1, 1, 0, tIsC3);

    if (networkSize == 0)
	return TARG_LOS_NONE;

    for (i = 0; i < networkSize; i++) {
	otherMech = getMechInTempNetwork(i, myNetwork, networkSize);

	if (!otherMech)
	    continue;

	if (!Good_obj(otherMech->mynum))
	    continue;

	if (otherMech == mechTarget)
	    continue;

	range = FaMechRange(otherMech, mechTarget);
	los =
	    InLineOfSight(otherMech, mechTarget, MechX(mechTarget),
	    MechY(mechTarget), range);

	if (los) {
	    if (!InLineOfSight_NB(otherMech, mechTarget, MechX(mechTarget),
		    MechY(mechTarget), range))
		los = TARG_LOS_SOMETHING;
	    else {
		los = TARG_LOS_CLEAR;
		break;
	    }
	}
    }

    return los;
}

float findC3Range(MECH * mech, MECH * mechTarget, float realRange,
    dbref * c3Ref, int tIsC3)
{
    int networkSize;
    dbref myNetwork[C3_NETWORK_SIZE];

    if (tIsC3) {
	if (C3Destroyed(mech)) {
	    return realRange;
	}
    } else {
	if (C3iDestroyed(mech)) {
	    validateC3iNetwork(mech);

	    return realRange;
	}
    }

    if (AnyECMDisturbed(mech))
	return realRange;

    buildTempNetwork(mech, myNetwork, &networkSize, 1, 1, 0, tIsC3);

    return findC3RangeWithNetwork(mech, mechTarget, realRange, myNetwork,
	networkSize, c3Ref);
}

float findC3RangeWithNetwork(MECH * mech, MECH * mechTarget,
    float realRange, dbref * myNetwork, int networkSize, dbref * c3Ref)
{
    float c3Range = 0.0;
    float bestRange = 0.0;
    int i;
    int inLOS = 0;
    int mapX, mapY;
    float hexX, hexY, hexZ;
    MECH *otherMech;
    MAP *map;

    bestRange = realRange;
    *c3Ref = 0;

    if (networkSize == 0)
	return realRange;

    for (i = 0; i < networkSize; i++) {
	otherMech = getMechInTempNetwork(i, myNetwork, networkSize);

	if (!otherMech)
	    continue;

	if (!Good_obj(otherMech->mynum))
	    continue;

	if (mechTarget) {
	    if (otherMech == mechTarget)
		continue;

	    debugC3(tprintf
		("C3RANGE-NETWORK (mech): Finding range from %d to %d.",
		    mech->mynum, mechTarget->mynum));

	    c3Range = FaMechRange(otherMech, mechTarget);
	    inLOS =
		InLineOfSight(otherMech, mechTarget, MechX(mechTarget),
		MechY(mechTarget), c3Range);
	} else if ((MechTargX(mech) > 0) && (MechTargY(mech) > 0)) {
	    mapX = MechTargX(mech);
	    mapY = MechTargY(mech);
	    map = getMap(mech->mapindex);

	    debugC3(tprintf
		("C3RANGE-NETWORK (hex): Finding range from %d to %d %d.",
		    mech->mynum, mapX, mapY));

	    MechTargZ(mech) = Elevation(map, mapX, mapY);
	    hexZ = ZSCALE * MechTargZ(mech);
	    MapCoordToRealCoord(mapX, mapY, &hexX, &hexY);

	    c3Range =
		FindRange(MechFX(otherMech), MechFY(otherMech),
		MechFZ(otherMech), hexX, hexY, hexZ);
	    inLOS = LOS_NB(otherMech, NULL, mapX, mapY, c3Range);
	} else {
	    continue;
	}

	if (inLOS && (c3Range < bestRange)) {
	    bestRange = c3Range;
	    *c3Ref = otherMech->mynum;
	}
    }

    return bestRange;
}

void debugC3(char *msg)
{
    if (DEBUG_C3)
	SendDebug(msg);
}