00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <stdio.h>
00013 #include <stdlib.h>
00014
00015 #include "mech.h"
00016 #include "create.h"
00017 #include "btmacros.h"
00018 #include "mech.events.h"
00019 #include "p.btechstats.h"
00020 #include "p.mech.bth.h"
00021 #include "p.mech.combat.h"
00022 #include "p.mech.combat.misc.h"
00023 #include "p.mech.los.h"
00024 #include "p.mech.utils.h"
00025
00026 int IsArtyMech(MECH * mech)
00027 {
00028 int weapnum, section, critical, weaptype = -2;
00029
00030 for(weapnum = 0; weaptype != -1; weapnum++) {
00031 weaptype = FindWeaponNumberOnMech(mech, weapnum, §ion, &critical);
00032 if(IsArtillery(weaptype))
00033 return 1;
00034 }
00035 return 0;
00036 }
00037
00038 static void mech_check_range(MUXEVENT * e)
00039 {
00040 MECH *spotter = (MECH *) e->data2, *mech = (MECH *) e->data;
00041 float range;
00042
00043 if(!mech)
00044 return;
00045
00046 if(MechSpotter(mech) == -1)
00047 return;
00048
00049 if(!spotter) {
00050 mech_notify(mech, MECHALL, "You have lost link with your spotter!");
00051 MechSpotter(mech) = -1;
00052 return;
00053 }
00054 range = FlMechRange(fl, mech, spotter);
00055 if(range > 2 * MechRadioRange(spotter) || MechSpotter(spotter) == -1
00056 || spotter->mapindex != mech->mapindex) {
00057 mech_notify(mech, MECHALL, "You have lost link with your spotter!");
00058 MechSpotter(mech) = -1;
00059 return;
00060 }
00061 MECHEVENT(mech, EVENT_SPOT_CHECK, mech_check_range, SPOT_TICK, spotter);
00062 }
00063
00064 static void mech_spot_event(MUXEVENT * e)
00065 {
00066 MECH *target, *mech = (MECH *) e->data;
00067 struct spot_data *sd = (struct spot_data *) e->data2;
00068
00069 target = (MECH *) sd->target;
00070
00071 if(MechFX(mech) != sd->mechFX && MechFY(mech) != sd->mechFY &&
00072 MechFX(target) != sd->tarFX && MechFY(target) != sd->tarFY) {
00073 mech_notify(target, MECHALL,
00074 "The data link was not established due to movement!");
00075 mech_notify(mech, MECHALL,
00076 "The data link was not established due to movement!");
00077 free((void *) e->data2);
00078 return;
00079 }
00080 mech_printf(target, MECHALL, "Data link established with %s.",
00081 GetMechToMechID(target, mech));
00082 mech_printf(mech, MECHALL,
00083 "Data link established with %s, you now have a forward observer.",
00084 GetMechToMechID(target, mech));
00085 MechSpotter(mech) = target->mynum;
00086 MECHEVENT(mech, EVENT_SPOT_CHECK, mech_check_range, SPOT_TICK, target);
00087 free((void *) e->data2);
00088 }
00089
00090 void ClearFireAdjustments(MAP * map, dbref mech)
00091 {
00092 int i;
00093 MECH *m;
00094
00095 for(i = 0; i < map->first_free; i++)
00096 if(map->mechsOnMap[i] >= 0) {
00097 if(!(m = getMech(map->mechsOnMap[i])))
00098 continue;
00099 if(m->mynum == mech)
00100 continue;
00101 if(MechSpotter(m) == mech)
00102 MechFireAdjustment(m) = 0;
00103 }
00104 }
00105
00106 void mech_spot(dbref player, void *data, char *buffer)
00107 {
00108 MECH *mech = (MECH *) data, *target;
00109 char *args[5];
00110 char targetID[3];
00111 int argc;
00112 int LOS = 1;
00113 dbref targetref;
00114 float range;
00115 struct spot_data *dat;
00116 MAP *mech_map;
00117
00118 cch(MECH_USUALO);
00119 mech_map = getMap(mech->mapindex);
00120 argc = mech_parseattributes(buffer, args, 5);
00121 #ifdef BT_MOVEMENT_MODES
00122 DOCHECK(MoveModeLock(mech),
00123 "You cannot spot while using a special movement mode.");
00124 #endif
00125 DOCHECK(argc != 1, "You may only use mech ID's to set spotter!");
00126 DOCHECK(MechType(mech) == CLASS_MW,
00127 "Spot ? You ? What with, your pretty blue eyes ? Hah!");
00128 targetID[0] = args[0][0];
00129 targetID[1] = args[0][1];
00130 targetID[2] = 0;
00131 targetref = FindTargetDBREFFromMapNumber(mech, targetID);
00132 if(!strcmp(args[0], "-")) {
00133 if(MechSpotter(mech) == mech->mynum) {
00134 mech_notify(mech, MECHALL, "You spot no longer.");
00135 ClearFireAdjustments(mech_map, mech->mynum);
00136 } else
00137 mech_notify(mech, MECHALL,
00138 "You disable the datalink to spotter.");
00139 MechSpotter(mech) = -1;
00140 return;
00141 }
00142 if(!strcasecmp(targetID, MechIDS(mech, 0))) {
00143 MechSpotter(mech) = mech->mynum;
00144 mech_notify(mech, MECHALL, "You are now set as a spotter.");
00145 return;
00146 }
00147 target = getMech(targetref);
00148 if(target)
00149 LOS =
00150 InLineOfSight(mech, target, MechX(target), MechY(target),
00151 FlMechRange(mech_map, mech, target));
00152 DOCHECK((targetref == -1) ||
00153 MechTeam(target) != MechTeam(mech),
00154 "That target does not exist!");
00155
00156 DOCHECK(MechType(target) == CLASS_MW,
00157 "Spot ? That puny being ?! What with, those clear brown eyes ? Hah!");
00158 DOCHECK(MechSpotter(target) != target->mynum,
00159 "That 'mech is not set up as spotter!");
00160
00161 if(IsArtyMech(mech) && !LOS) {
00162 mech_notify(target, MECHALL,
00163 "Someone is trying to establish a data link with you!");
00164 mech_notify(mech, MECHALL,
00165 "You attempt to establish a data link..... please stand by.");
00166 range = FlMechRange(mech_map, mech, target);
00167 if(range > 2 * MechRadioRange(target)) {
00168 mech_notify(mech, MECHALL,
00169 "That target is our of data link range!");
00170 return;
00171 }
00172 Create(dat, struct spot_data, 1);
00173 dat->mechFY = MechFY(mech);
00174 dat->mechFX = MechFX(mech);
00175 dat->tarFX = MechFX(target);
00176 dat->tarFY = MechFY(target);
00177 dat->target = (MECH *) target;
00178 MECHEVENT(mech, EVENT_SPOT_LOCK, mech_spot_event,
00179 WEAPON_TICK * ((int) range / 10 + 5), dat);
00180 return;
00181 } else
00182 DOCHECK(!LOS, "You do not have LOS to that target!")
00183 MechSpotter(mech) = targetref;
00184 MechFireAdjustment(mech) = 0;
00185 mech_printf(mech, MECHALL, "%s set as spotter.",
00186 GetMechToMechID(mech, target));
00187 }
00188
00189 int FireSpot(dbref player,
00190 MECH * mech,
00191 MAP * mech_map,
00192 int weaponnum, int weapontype, int sight, int section,
00193 int critical)
00194 {
00195
00196
00197 float spot_range, range;
00198 float enemyX, enemyY, enemyZ = 0;
00199 int LOS, mapx = 0, mapy = 0;
00200 MECH *target = NULL, *spotter;
00201 int spotTerrain;
00202 int found_target = 0;
00203
00204
00205 if(MechSpotter(mech) == -1 || !(MechWeapons[weapontype].special & IDF))
00206 return 0;
00207
00208 spotter = getMech(MechSpotter(mech));
00209 DOCHECKMP1(!spotter, "There is no spotter avilable to IDF with!");
00210
00211 if(!(MechSpotter(spotter) == spotter->mynum)) {
00212 mech_notify(mech, MECH_PILOT, "You do not have a spotter!");
00213 MechSpotter(mech) = -1;
00214 return 1;
00215 }
00216 DOCHECKMP1(Uncon(spotter), "Your spotter is unconscious!");
00217 DOCHECKMP1(Blinded(spotter), "Your spotter can't see a thing!");
00218
00219
00220 if(MechTarget(spotter) != -1) {
00221 target = getMech(MechTarget(spotter));
00222 DOCHECKMP1(!target, "Your spotter has invalid target!");
00223 mapx = MechX(target);
00224 mapy = MechY(target);
00225 spot_range = FaMechRange(spotter, target);
00226 LOS = InLineOfSight(spotter, target, mapx, mapy, spot_range);
00227 DOCHECKMP1(!LOS, "You spotter does not have a target in LOS!");
00228 range = FaMechRange(mech, target);
00229 spotTerrain =
00230 IsArtillery(weapontype) ? 2 : 1 + AddTerrainMod(spotter,
00231 target,
00232 mech_map,
00233 spot_range,
00234 0) +
00235 AttackMovementMods(spotter) + (Locking(spotter)
00236 && MechTargComp(spotter) !=
00237 TARGCOMP_MULTI)
00238 ? 2 : 0;
00239 DOCHECK1(IsArtillery(weapontype) &&
00240 target,
00241 "You can only target hexes with this kind of artillery.");
00242 if(!sight) {
00243 AccumulateSpotXP(MechPilot(spotter), spotter, target);
00244 AccumulateArtyXP(MechPilot(mech), mech, target);
00245 }
00246 FireWeapon(mech, mech_map, target, 0, weapontype, weaponnum,
00247 section, critical, MechFX(target), MechFY(target), mapx,
00248 mapy, range, spotTerrain, sight, 2);
00249 return 1;
00250 }
00251 if(!(MechTargX(spotter) >= 0 && MechTargY(spotter) >= 0)) {
00252 notify(player, "Your spotter has no target set!");
00253 return 1;
00254 }
00255 if(!IsArtillery(weapontype))
00256 if((target =
00257 find_mech_in_hex(mech, mech_map, MechTargX(spotter),
00258 MechTargY(spotter), 0))) {
00259 enemyX = MechFX(target);
00260 enemyY = MechFY(target);
00261 enemyZ = MechFZ(target);
00262 mapx = MechX(target);
00263 mapy = MechY(target);
00264 found_target = 1;
00265 }
00266 if(!found_target) {
00267 target = (MECH *) NULL;
00268 mapx = MechTargX(spotter);
00269 mapy = MechTargY(spotter);
00270 enemyZ = ZSCALE * MechTargZ(spotter);
00271 MapCoordToRealCoord(mapx, mapy, &enemyX, &enemyY);
00272 }
00273 spot_range =
00274 FindRange(MechFX(spotter), MechFY(spotter), MechFZ(spotter),
00275 enemyX, enemyY, enemyZ);
00276 LOS = InLineOfSight(spotter, target, mapx, mapy, spot_range);
00277 DOCHECK0(!LOS, "That target is not in your spotters line of sight!");
00278 range =
00279 FindRange(MechFX(mech), MechFY(mech), MechFZ(mech), enemyX, enemyY,
00280 enemyZ);
00281 spotTerrain =
00282 IsArtillery(weapontype) ? 2 : 1 + AttackMovementMods(spotter) +
00283 (Locking(spotter) && MechTargComp(spotter) != TARGCOMP_MULTI)
00284 ? 2 : 0;
00285 FireWeapon(mech, mech_map, target, 0, weapontype, weaponnum, section,
00286 critical, enemyX, enemyY, mapx, mapy, range, spotTerrain,
00287 sight, 2);
00288 return 1;
00289 }