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.spot.c,v 1.1.1.1 2005/01/11 21:18:23 kstevens Exp $
 *
 * Author: Cord Awtry <kipsta@mediaone.net>
 *  Copyright (c) 2001-2002 Cord Awtry
 *  Copyright (c) 1999-2005 Kevin Stevens
 *       All rights reserved
 *
 * Based on work that was:
 *  Copyright (c) 1997 Markus Stenberg
 *  Copyright (c) 1998-2001 Thomas Wouters
 */

#include <stdio.h>
#include <stdlib.h>

#include "mech.h"
#include "create.h"
#include "btmacros.h"
#include "mech.events.h"
#include "p.btechstats.h"
#include "p.mech.bth.h"
#include "p.mech.combat.h"
#include "p.mech.combat.misc.h"
#include "p.mech.los.h"
#include "p.mech.utils.h"

int IsArtyMech(MECH * mech)
{
    int weapnum, section, critical, weaptype = -2;

    for (weapnum = 0; weaptype != -1; weapnum++) {
	weaptype =
	    FindWeaponNumberOnMech(mech, weapnum, &section, &critical);
	if (IsArtillery(weaptype))
	    return 1;
    }
    return 0;
}

static void mech_check_range(MUXEVENT * e)
{
    MECH *spotter = (MECH *) e->data2, *mech = (MECH *) e->data;
    float range;

    if (!mech)
	return;

    if (MechSpotter(mech) == -1)
	return;

    if (!spotter) {
	mech_notify(mech, MECHALL,
	    "You have lost link with your spotter!");
	MechSpotter(mech) = -1;
	return;
    }
    range = FlMechRange(fl, mech, spotter);
    if (range > 2 * MechRadioRange(spotter) || MechSpotter(spotter) == -1
	|| spotter->mapindex != mech->mapindex) {
	mech_notify(mech, MECHALL,
	    "You have lost link with your spotter!");
	MechSpotter(mech) = -1;
	return;
    }
    MECHEVENT(mech, EVENT_SPOT_CHECK, mech_check_range, SPOT_TICK,
	spotter);
}

static void mech_spot_event(MUXEVENT * e)
{
    MECH *target, *mech = (MECH *) e->data;
    struct spot_data *sd = (struct spot_data *) e->data2;

    target = (MECH *) sd->target;

    if (MechFX(mech) != sd->mechFX && MechFY(mech) != sd->mechFY &&
	MechFX(target) != sd->tarFX && MechFY(target) != sd->tarFY) {
	mech_notify(target, MECHALL,
	    "The data link was not established due to movement!");
	mech_notify(mech, MECHALL,
	    "The data link was not established due to movement!");
	free((void *) e->data2);
	return;
    }
    mech_notify(target, MECHALL, tprintf("Data link established with %s.",
	    GetMechToMechID(target, mech)));
    mech_notify(mech, MECHALL,
	tprintf
	("Data link established with %s, you now have a forward observer.",
	    GetMechToMechID(target, mech)));
    MechSpotter(mech) = target->mynum;
    MECHEVENT(mech, EVENT_SPOT_CHECK, mech_check_range, SPOT_TICK, target);
    free((void *) e->data2);
}

void ClearFireAdjustments(MAP * map, dbref mech)
{
    int i;
    MECH *m;

    for (i = 0; i < map->first_free; i++)
	if (map->mechsOnMap[i] >= 0) {
	    if (!(m = getMech(map->mechsOnMap[i])))
		continue;
	    if (m->mynum == mech)
		continue;
	    if (MechSpotter(m) == mech)
		MechFireAdjustment(m) = 0;
	}
}

void mech_spot(dbref player, void *data, char *buffer)
{
    MECH *mech = (MECH *) data, *target;
    char *args[5];
    char targetID[3];
    int argc;
    int LOS = 1;
    dbref targetref;
    float range;
    struct spot_data *dat;
    MAP *mech_map;

    cch(MECH_USUALO);
    mech_map = getMap(mech->mapindex);
    argc = mech_parseattributes(buffer, args, 5);
#ifdef BT_MOVEMENT_MODES
    DOCHECK(MoveModeLock(mech), "You cannot spot while using a special movement mode.");
#endif
    DOCHECK(argc != 1, "You may only use mech ID's to set spotter!");
    DOCHECK(MechType(mech) == CLASS_MW,
    	"Spot ? You ? What with, your pretty blue eyes ? Hah!");
    targetID[0] = args[0][0];
    targetID[1] = args[0][1];
    targetID[2] = 0;
    targetref = FindTargetDBREFFromMapNumber(mech, targetID);
    if (!strcmp(args[0], "-")) {
	if (MechSpotter(mech) == mech->mynum) {
	    mech_notify(mech, MECHALL, "You spot no longer.");
	    ClearFireAdjustments(mech_map, mech->mynum);
	} else
	    mech_notify(mech, MECHALL,
		"You disable the datalink to spotter.");
	MechSpotter(mech) = -1;
	return;
    }
    if (!strcasecmp(targetID, MechIDS(mech, 0))) {
	MechSpotter(mech) = mech->mynum;
	mech_notify(mech, MECHALL, "You are now set as a spotter.");
	return;
    }
    target = getMech(targetref);
    if (target)
	LOS =
	    InLineOfSight(mech, target, MechX(target), MechY(target),
	    FlMechRange(mech_map, mech, target));
    DOCHECK((targetref == -1) ||
	MechTeam(target) != MechTeam(mech), "That target does not exist!");

    DOCHECK(MechType(target) == CLASS_MW,
    	"Spot ? That puny being ?! What with, those clear brown eyes ? Hah!");
    DOCHECK(MechSpotter(target) != target->mynum,
	"That 'mech is not set up as spotter!");

    if (IsArtyMech(mech) && !LOS) {
	mech_notify(target, MECHALL,
	    "Someone is trying to establish a data link with you!");
	mech_notify(mech, MECHALL,
	    "You attempt to establish a data link..... please stand by.");
	range = FlMechRange(mech_map, mech, target);
	if (range > 2 * MechRadioRange(target)) {
	    mech_notify(mech, MECHALL,
		"That target is our of data link range!");
	    return;
	}
	Create(dat, struct spot_data, 1);
	dat->mechFY = MechFY(mech);
	dat->mechFX = MechFX(mech);
	dat->tarFX = MechFX(target);
	dat->tarFY = MechFY(target);
	dat->target = (MECH *) target;
	MECHEVENT(mech, EVENT_SPOT_LOCK, mech_spot_event,
	    WEAPON_TICK * ((int) range / 10 + 5), dat);
	return;
    } else
	DOCHECK(!LOS, "You do not have LOS to that target!")
	    MechSpotter(mech) = targetref;
    MechFireAdjustment(mech) = 0;
    mech_notify(mech, MECHALL, tprintf("%s set as spotter.",
	    GetMechToMechID(mech, target)));
}

int FireSpot(dbref player,
    MECH * mech,
    MAP * mech_map,
    int weaponnum, int weapontype, int sight, int section, int critical)
{
    /* Nim 9/11/96 */

    float spot_range, range;
    float enemyX, enemyY, enemyZ = 0;
    int LOS, mapx = 0, mapy = 0;
    MECH *target = NULL, *spotter;
    int spotTerrain;
    int found_target = 0;

    /* No spotter or not IDF weapon lets get outta here */
    if (MechSpotter(mech) == -1 ||
	!(MechWeapons[weapontype].special & IDF))
	return 0;

    spotter = getMech(MechSpotter(mech));
    DOCHECKMP1(!spotter, "There is no spotter avilable to IDF with!");

    if (!(MechSpotter(spotter) == spotter->mynum)) {
	mech_notify(mech, MECH_PILOT, "You do not have a spotter!");
	MechSpotter(mech) = -1;
	return 1;
    }
    DOCHECKMP1(Uncon(spotter), "Your spotter is unconscious!");
    DOCHECKMP1(Blinded(spotter), "Your spotter can't see a thing!");

    /* Is the spotter set to a Mech or to a Hex? */
    if (MechTarget(spotter) != -1) {
	target = getMech(MechTarget(spotter));
	DOCHECKMP1(!target, "Your spotter has invalid target!");
	mapx = MechX(target);
	mapy = MechY(target);
	spot_range = FaMechRange(spotter, target);
	LOS = InLineOfSight(spotter, target, mapx, mapy, spot_range);
	DOCHECKMP1(!LOS, "You spotter does not have a target in LOS!");
	range = FaMechRange(mech, target);
	spotTerrain =
	    IsArtillery(weapontype) ? 2 : 1 + AddTerrainMod(spotter,
	    target,
	    mech_map,
	    spot_range,
	    0) + AttackMovementMods(spotter) +
	    (Locking(spotter) && MechTargComp(spotter) != TARGCOMP_MULTI)
	    ? 2 : 0;
	DOCHECK1(IsArtillery(weapontype) &&
	    target,
	    "You can only target hexes with this kind of artillery.");
	if (!sight) {
	    AccumulateSpotXP(MechPilot(spotter), spotter, target);
	    AccumulateArtyXP(MechPilot(mech), mech, target);
	}
	FireWeapon(mech, mech_map, target, 0, weapontype, weaponnum,
	    section, critical, MechFX(target), MechFY(target), mapx,
	    mapy, range, spotTerrain, sight, 2);
	return 1;
    }
    if (!(MechTargX(spotter) >= 0 && MechTargY(spotter) >= 0)) {
	notify(player, "Your spotter has no target set!");
	return 1;
    }
    if (!IsArtillery(weapontype))
	if ((target =
		find_mech_in_hex(mech, mech_map, MechTargX(spotter),
		    MechTargY(spotter), 0))) {
	    enemyX = MechFX(target);
	    enemyY = MechFY(target);
	    enemyZ = MechFZ(target);
	    mapx = MechX(target);
	    mapy = MechY(target);
	    found_target = 1;
	}
    if (!found_target) {
	target = (MECH *) NULL;
	mapx = MechTargX(spotter);
	mapy = MechTargY(spotter);
	enemyZ = ZSCALE * MechTargZ(spotter);
	MapCoordToRealCoord(mapx, mapy, &enemyX, &enemyY);
    }
    spot_range =
	FindRange(MechFX(spotter), MechFY(spotter), MechFZ(spotter),
	enemyX, enemyY, enemyZ);
    LOS = InLineOfSight(spotter, target, mapx, mapy, spot_range);
    DOCHECK0(!LOS, "That target is not in your spotters line of sight!");
    range =
	FindRange(MechFX(mech), MechFY(mech), MechFZ(mech), enemyX, enemyY,
	enemyZ);
    spotTerrain =
	IsArtillery(weapontype) ? 2 : 1 + AttackMovementMods(spotter) +
	(Locking(spotter) && MechTargComp(spotter) != TARGCOMP_MULTI)
	? 2 : 0;
    FireWeapon(mech, mech_map, target, 0, weapontype, weaponnum, section,
	critical, enemyX, enemyY, mapx, mapy, range, spotTerrain,
	sight, 2);
    return 1;
}