/* * $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, §ion, &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; }