src/hcode/btech/mech.bth.c

Go to the documentation of this file.
00001 
00002 /*
00003  * $Id: mech.bth.c,v 1.2 2005/06/23 15:27:04 av1-op Exp $
00004  *
00005  * Author: Cord Awtry <kipsta@mediaone.net>
00006  * Author: Cord Awtry <kipsta@mediaone.net>
00007  *  Copyright (c) 2000-2002 Cord Awtry
00008  *  Copyright (c) 1999-2005 Kevin Stevens
00009  *       All rights reserved
00010  *
00011  * Based on work that was:
00012  *  Copyright (c) 1997 Markus Stenberg
00013  *  Copyright (c) 1998-2000 Thomas Wouters
00014  */
00015 
00016 #include <math.h>
00017 
00018 #include "mech.h"
00019 #include "mech.events.h"
00020 #include "p.mech.bth.h"
00021 #include "p.mech.c3.misc.h"
00022 #include "p.mech.combat.h"
00023 #include "p.mech.enhanced.criticals.h"
00024 #include "p.mech.hitloc.h"
00025 #include "p.mech.los.h"
00026 #include "p.mech.update.h"
00027 #include "p.mech.utils.h"
00028 
00029 #ifndef BTH_DEBUG
00030 #define BTHBASE(m,t,n)  baseToHit = n;
00031 #define BTHADD(desc,n)  baseToHit += n;
00032 #define BTHEND(m)
00033 #else
00034 #define BTHBASE(m,t,n)  do { if (t) sprintf(buf, "#%d -> #%d: Base %d", m->mynum, t->mynum, n); else sprintf(buf, "#%d -> (hex): Base %d", m->mynum, n); baseToHit = n; } while (0)
00035 #define BTHADD(desc,n)  do { i = n ; if (i) { sprintf(buf+strlen(buf), ", %s: %s%d", desc, i>0 ? "+" : "", i); baseToHit += i; } } while (0)
00036 #define BTHEND(m)       SendBTHDebug(tprintf("%s.", buf))
00037 #endif
00038 
00039 int arc_override;
00040 
00041 int FindNormalBTH(MECH * mech,
00042                                   MAP * mech_map,
00043                                   int section,
00044                                   int critical,
00045                                   int weapindx, float range, MECH * target, int indirectFire,
00046                                   dbref * c3Ref)
00047 {
00048         MECH *spotter = NULL;
00049         int baseToHit;
00050         int wFireMode = GetPartFireMode(mech, section, critical);
00051         int wAmmoMode = GetPartAmmoMode(mech, section, critical);
00052         int tInWater = 0;
00053         int tTargetInWater = 0;
00054         int wTargMoveMod = 0;
00055         int rangecheck = 0;
00056 #ifdef BTH_DEBUG
00057         char buf[LBUF_SIZE];
00058         int i;
00059 #endif
00060         int j, rbth = 0;
00061         float enemyX, enemyY, enemyZ;
00062         int wRangeBracket = RANGE_TOFAR;
00063 
00064         *c3Ref = -1;
00065 
00066         if(target) {
00067                 tInWater = ((MechRTerrain(mech) == WATER) && (MechZ(mech) < 0));
00068                 tTargetInWater = ((MechRTerrain(target) == WATER) &&
00069                                                   (MechZ(target) < 0));
00070         }
00071 
00072         BTHBASE(mech, target, FindPilotGunnery(mech, weapindx));
00073 
00074         if(indirectFire < 1000) {
00075                 spotter = getMech(MechSpotter(mech));
00076 
00077                 if(!spotter) {
00078                         mech_notify(mech, MECHALL,
00079                                                 "Error finding your spotter! (notify a wiz)");
00080                         return 0;
00081                 }
00082 
00083                 BTHADD("Spotting", FindPilotSpotting(spotter) - 4);
00084         }
00085 
00086         /* Our special bother for aeros */
00087         if(is_aero(mech) && target && !is_aero(target) && !Landed(mech)) {
00088                 BTHADD("Aero strafing", 2);
00089         };
00090 
00091         /* MW need +2 added per FASA */
00092         if(target && MechType(target) == CLASS_MW)
00093                 BTHADD("MechWarrior", 2);
00094 
00095         /* add in to-hit mods from criticals */
00096         BTHADD("MechBTHMod", MechBTH(mech));
00097 
00098         /* add in to-hit mods for section damage */
00099         BTHADD("MechLocBTHMod", MechSections(mech)[section].basetohit);
00100 
00101         /* Add +1 if we're firing from water */
00102         if(tInWater)
00103                 BTHADD("InWater", 1);
00104 
00105         /* Add in the rangebase.. */
00106         rangecheck = EGunRange(weapindx);
00107         if(wAmmoMode & STINGER_MODE)
00108                 rangecheck += 7;
00109         if(rangecheck < range) {
00110                 BTHADD("OutOfRange", 1000);
00111         } else {
00112                 if((MechWeapons[weapindx].min >= range) &&
00113                    (MechWeapons[weapindx].min > 0)) {
00114                         if(!HotLoading(weapindx, GetPartFireMode(mech, section,
00115                                                                                                          critical))) {
00116                                 /* if the target is in minimum range then the BTH is as good as it will get */
00117                                 rbth = (MechWeapons[weapindx].min - range + 1);
00118                         } else {
00119                                 if(mudconf.btech_hotloadaddshalfbthmod) {
00120                                         rbth = ((MechWeapons[weapindx].min - range + 2) / 2);
00121                                 }
00122                         }
00123 
00124                         BTHADD("MinRange", rbth);
00125                 } else if(HasC3(mech) && !C3Destroyed(mech) &&
00126                                   !AnyECMDisturbed(mech) && (MechC3NetworkSize(mech) > 0)) {
00127                         wRangeBracket = FindBTHByC3Range(mech, target,
00128                                                                                          section, weapindx, range,
00129                                                                                          findC3Range(mech, target, range,
00130                                                                                                                  c3Ref, 1), wAmmoMode,
00131                                                                                          &rbth);
00132 
00133                         BTHADD("C3Range", rbth);
00134                 } else if(HasC3i(mech) && !C3iDestroyed(mech) &&
00135                                   !AnyECMDisturbed(mech) && (MechC3iNetworkSize(mech) > 0)) {
00136                         wRangeBracket = FindBTHByC3Range(mech, target,
00137                                                                                          section, weapindx, range,
00138                                                                                          findC3Range(mech, target, range,
00139                                                                                                                  c3Ref, 0), wAmmoMode,
00140                                                                                          &rbth);
00141 
00142                         BTHADD("C3iRange", rbth);
00143                 } else {
00144                         wRangeBracket = FindBTHByRange(mech, target, section,
00145                                                                                    weapindx, range, wFireMode,
00146                                                                                    wAmmoMode, &rbth);
00147                         BTHADD("Range", rbth);
00148                 }
00149         }
00150 /* I decided to put it here in this rewritten form. To add it to FindBTH*() was a bit
00151  * convoluted compared to original source method, Exile and 3030/btechmux went a few
00152  * different path's on internal representation and organization of various weapon data
00153  * and BTH handling. Someday I might, after I review how some of the same things were
00154  * done here, port some of that stuff over. (Like GunStat() and such)
00155  *
00156  * For now we just do the below stuff. Besides, it might make BTH debug more obvious
00157  * that putting it into FindBTH*().
00158  */
00159         if(MechTargComp(mech) == TARGCOMP_SHORT
00160            || MechTargComp(mech) == TARGCOMP_LONG) {
00161                 int tmp_range;
00162 
00163                 if(MechWeapons[weapindx].special & PCOMBAT)
00164                         tmp_range = (int) (range * 10 + 0.95);
00165                 else
00166                         tmp_range = (int) (range + 0.95);
00167 
00168                 if(tmp_range >
00169                    (SectionUnderwater(mech, section) ? MechWeapons[weapindx].
00170                         medrange_water : MechWeapons[weapindx].medrange))
00171                         BTHADD("TargComp/Long",
00172                                    MechTargComp(mech) == TARGCOMP_LONG ? -1 : 1);
00173                 else if(tmp_range <=
00174                                 (SectionUnderwater(mech, section) ? MechWeapons[weapindx].
00175                                  medrange_water : MechWeapons[weapindx].medrange))
00176                         BTHADD("TargComp/Short",
00177                                    MechTargComp(mech) == TARGCOMP_SHORT ? -1 : 1);
00178         }
00179 
00180         if(target && MechInfantrySpecials(target) & STEALTH_TECH) {
00181                 if(MechInfantrySpecials(target) & FWL_ACHILEUS_STEALTH_TECH) {
00182                         if(wRangeBracket == RANGE_SHORT)
00183                                 BTHADD("FWLStealthBonus", 1);
00184                         else if(wRangeBracket == RANGE_MED)
00185                                 BTHADD("FWLStealthBonus", 2);
00186                         else if(wRangeBracket == RANGE_LONG)
00187                                 BTHADD("FWLStealthBonus", 3);
00188                 } else if(MechInfantrySpecials(target) & DC_KAGE_STEALTH_TECH) {
00189                         if(wRangeBracket == RANGE_MED)
00190                                 BTHADD("DCStealthBonus", 1);
00191                         else if(wRangeBracket == RANGE_LONG)
00192                                 BTHADD("DCStealthBonus", 2);
00193                 } else if(MechInfantrySpecials(target) & FC_INFILTRATOR_STEALTH_TECH) {
00194                         if(wRangeBracket == RANGE_MED)
00195                                 BTHADD("FCStealthBonus", 1);
00196                         else if(wRangeBracket == RANGE_LONG)
00197                                 BTHADD("FCStealthBonus", 2);
00198                 } else if(MechInfantrySpecials(target) &
00199                                   FC_INFILTRATORII_STEALTH_TECH) {
00200                         if(wRangeBracket == RANGE_SHORT)
00201                                 BTHADD("FCStealthIIBonus", 1);
00202                         if(wRangeBracket == RANGE_MED)
00203                                 BTHADD("FCStealthIIBonus", 1);
00204                         else if(wRangeBracket == RANGE_LONG)
00205                                 BTHADD("FCStealthIIBonus", 2);
00206                 }
00207         }
00208 
00209         /* Add in the movement modifiers */
00210         if(MechSections(mech)[section].config & STABILIZERS_DESTROYED)
00211                 BTHADD("AttackMoveX2", AttackMovementMods(mech) * 2);
00212         else
00213                 BTHADD("AttackMove", AttackMovementMods(mech));
00214 
00215         /* Add mods for overheating */
00216         BTHADD("Overheat", OverheatMods(mech));
00217 
00218         /* Add special weapon mods */
00219         if(wAmmoMode & AC_AP_MODE)
00220                 BTHADD("ArmorPiercing", 1);
00221 
00222         if(checkAllSections(mech, INARC_HAYWIRE_ATTACHED))
00223                 BTHADD("HaywirePod", 1);
00224 
00225         if(target && (wAmmoMode & NARC_MODE) &&
00226            (!(MechWeapons[weapindx].special & NARC)) &&
00227            checkAllSections(target, INARC_HOMING_ATTACHED))
00228                 BTHADD("iNARC", -1);
00229 
00230         if(MechWeapons[weapindx].special & PULSE)
00231                 BTHADD("Pulse", -2);
00232 
00233         if(MechWeapons[weapindx].special & MRM)
00234                 BTHADD("MRM", 1);
00235 
00236         if(MechWeapons[weapindx].special & HVYW)
00237                 BTHADD("HeavyWeapon", 1);
00238         if(target && (wAmmoMode & STINGER_MODE)) {
00239                 if(FlyingT(target) && !Landed(target))
00240                         BTHADD("Stinger (Flying)", -3);
00241                 else if(OODing(target))
00242                         BTHADD("Stinger (OOD)", -1);
00243                 else if(Jumping(target))
00244                         BTHADD("Stinger (Jumping)", 0);
00245         }
00246 
00247         if(MechWeapons[weapindx].special & ROCKET)
00248                 BTHADD("Rocket Launcher", 1);
00249 
00250         if(target && (MechType(target) == CLASS_VTOL) &&
00251            (fabs(MechSpeed(target)) > 0.0 ||
00252                 fabs(MechVerticalSpeed(target)) > 0.0))
00253                 BTHADD("TargetVTOL", 1);
00254 
00255         if(target && MechTargComp(mech) == TARGCOMP_AA) {
00256                 if(!Landed(target)
00257                    && (FlyingT(target) || Jumping(target) || OODing(target)))
00258                         BTHADD("TargComp/AA-Fly", MechSpecials(mech) & AA_TECH ? -3 : -2);
00259                 else
00260                         BTHADD("TargComp/AA-Ground", 1);
00261         }
00262 
00263         /* -1 for LBX, unless it's a VTOL... then -3 */
00264         if(wAmmoMode & LBX_MODE)
00265                 BTHADD("LBX", (target && (MechType(target) == CLASS_VTOL) ? -3 : -1));
00266 
00267         /* Unstable lock */
00268         if(!arc_override && (!spotter && target &&
00269                                                  ((MechTarget(mech) != target->mynum) ||
00270                                                   (Locking(mech)
00271                                                    && MechTargComp(mech) != TARGCOMP_MULTI)))) {
00272                 if(FindTargetXY(mech, &enemyX, &enemyY, &enemyZ)) {
00273                         if(InWeaponArc(mech, enemyX, enemyY) & (FORWARDARC | TURRETARC))
00274                                 BTHADD("UnstableLock/Fwarc", 1);
00275                         else
00276                                 BTHADD("UnstableLock", 2);
00277                 } else {
00278                         BTHADD("HipShot-NoLock", 2);
00279                 }
00280         }
00281 
00282         if(MechTargComp(mech) == TARGCOMP_MULTI) {
00283                 if(FindTargetXY(mech, &enemyX, &enemyY, &enemyZ)) {
00284                         if(!(InWeaponArc(mech, enemyX, enemyY) & FORWARDARC))
00285                                 BTHADD("TargComp/MultiSideArc", 1);
00286                 }
00287         }
00288 
00289         /* -4 for firing at a hex */
00290         if(!target &&
00291            (MechStatus(mech) & (LOCK_HEX | LOCK_BUILDING | LOCK_HEX_IGN |
00292                                                         LOCK_HEX_CLR)))
00293                 BTHADD("HexBonus", -4);
00294 
00295         /* -2 for firing at someone dropping out of the sky */
00296         if(target && C_OODing(target))
00297                 BTHADD("OODbonus", -2);
00298 
00299         /* Indirect fire terrain modifiers */
00300         if(indirectFire < 1000)
00301                 BTHADD("IDFTerrain", indirectFire);
00302 
00303         /* +1 if spotting */
00304         if(MechSpotter(mech) == mech->mynum)
00305                 BTHADD("Spotting", 1);
00306 
00307         /* if our target is another unit... */
00308         if(target) {
00309                 /* Add the dig-in bonus */
00310                 if(MechDugIn(target) && (!mudconf.btech_dig_only_fs || (FindAreaHitGroup(mech, target) == FRONT)) &&
00311                    (MechZ(target) >= MechZ(mech)))
00312                         BTHADD("DugIn", mudconf.btech_digbonus);
00313 
00314                 /* -3 if it's a DS... most people can hit the broadside of a barn */
00315                 if(IsDS(target))
00316                         BTHADD("DSBonus", -3);
00317 
00318                 /* Add +1 for BSuit dispersion */
00319                 if(MechType(target) == CLASS_BSUIT)
00320                         BTHADD("Bsuitbonus", 1);
00321 
00322                 /* Let's see if we're targetting the head */
00323                 if(target && !IsMissile(weapindx) && MechAim(mech) == HEAD && 
00324                         (MechType(target) == CLASS_MECH || MechType(target) == CLASS_MW)) {
00325                         if(Immobile(target))
00326                                 BTHADD("HeadTarget", 7);
00327                         else
00328                                 BTHADD("HeadTarget-Fake", 25);
00329                 } else {
00330                         if((GetPartFireMode(mech, section, critical) & ON_TC) &&
00331                            !(MechCritStatus(mech) & TC_DESTROYED) &&
00332                            !(wAmmoMode & LBX_MODE)) {
00333                                 if(MechAim(mech) != NUM_SECTIONS && !Immobile(target))
00334                                         BTHADD("TC-Target-NotImmobile", 3);
00335                                 else
00336                                         BTHADD("TC", -1);
00337                         }
00338                 }
00339 
00340                 /* Add aero targetting mods. TODO: Rewrite aero code :) */
00341                 if(MechType(mech) == CLASS_AERO) {
00342                         wTargMoveMod = TargetMovementMods(mech, target, range) * 3 / 4;
00343                 } else {
00344                         wTargMoveMod = TargetMovementMods(mech, target, range);
00345                 }
00346 
00347                 if(wAmmoMode & AC_PRECISION_MODE)
00348                         wTargMoveMod = MAX(wTargMoveMod -= 2, 0);
00349 
00350                 if(!(wAmmoMode & SGUIDED_MODE))
00351                         BTHADD("TargetMove", wTargMoveMod);
00352                 else if ((TaggedBy(target) ? MechTeam(getMech(TaggedBy(target))) == MechTeam(mech) : 0) && wTargMoveMod < 0)
00353                         BTHADD("TargetMove", wTargMoveMod);
00354 
00355                 /* Add in the terrain modifier */
00356                 if(indirectFire >= 1000) {
00357                         j = AddTerrainMod(mech, target, mech_map, range, wAmmoMode);
00358                         if(j < 1000)
00359                                 BTHADD("Terrain/Light(Sensor)", j);
00360                 }
00361 
00362                 if(mudconf.btech_moddamagewithwoods &&
00363                    IsForestHex(mech_map, MechX(target), MechY(target)) &&
00364                    ((MechZ(target) - 2) <= Elevation(mech_map, MechX(target),
00365                                                                                          MechY(target)))) {
00366                         if(GetRTerrain(mech_map, MechX(target),
00367                                                    MechY(target)) == LIGHT_FOREST)
00368                                 BTHADD("Light Woods bonus", -1);
00369                         else if(GetRTerrain(mech_map, MechX(target),
00370                                                                 MechY(target)) == HEAVY_FOREST)
00371                                 BTHADD("Heavy Woods bonus", -2);
00372                 }
00373 #ifdef BT_MOVEMENT_MODES
00374                 if(MechStatus2(target) & (SPRINTING | EVADING)) {
00375                         if(MechStatus2(target) & SPRINTING)
00376                                 BTHADD("SprintingTarget", -4);
00377                         if(!Fallen(target) && MechStatus2(target) & EVADING)
00378                                 BTHADD("EvadingTarget", 1);
00379 /*              BTHADD("EvadingTarget", (FindPilotPiloting(target) >= 6 ? 1 :
00380                                          FindPilotPiloting(target) >= 4 ? 2 :
00381                                          FindPilotPiloting(target) >= 2 ? 3 : 4) +
00382                         (HasBoolAdvantage(MechPilot(target), "speed_demon") ? 1 : 0)); */
00383                 } else if(MoveModeChange(target)) {
00384                         int i = MoveModeData(target);
00385                         if(i & MODE_SPRINT)
00386                                 BTHADD("SprintingTargetChanging", -4);
00387                         if(i & MODE_EVADE)
00388                                 BTHADD("EvadingTargetChanging", 1);
00389 /*              BTHADD("EvadingTarget", (FindPilotPiloting(target) >= 6 ? 1 :
00390                                          FindPilotPiloting(target) >= 4 ? 2 :
00391                                          FindPilotPiloting(target) >= 2 ? 3 : 4) +
00392                         (HasBoolAdvantage(MechPilot(target), "speed_demon") ? 1 : 0)); */
00393                 }
00394 #endif
00395         }
00396 
00397         /* Check for damage */
00398         BTHADD("CritDamage", getCritAddedBTH(mech, section, critical,
00399                                                                                  wRangeBracket));
00400 
00401         BTHEND(mech);
00402         return baseToHit;
00403 }
00404 
00405 int FindArtilleryBTH(MECH * mech,
00406                                          int section, int weapindx, int indirect, float range)
00407 {
00408         int baseToHit = 11;
00409         MECH *spotter;
00410 
00411         if(SectionUnderwater(mech, section))
00412                 return 5000;
00413 
00414         if(EGunRange(weapindx) < range)
00415                 return 1000;
00416 
00417         baseToHit += (FindPilotArtyGun(mech) - 4);
00418         if(indirect) {
00419                 spotter = getMech(MechSpotter(mech));
00420                 if(spotter && spotter != mech)
00421                         baseToHit += (FindPilotSpotting(spotter) - 4) / 2;
00422                 /* the usual +2, added by +1 make +3 */
00423                 if(indirect && (MechSpotter(mech) == -1 ||
00424                                                 MechSpotter(mech) == mech->mynum))
00425                         baseToHit += 1;
00426         } else
00427                 baseToHit -= 2;
00428         return baseToHit - MechFireAdjustment(mech);
00429 }
00430 
00431 int FindBTHByRange(MECH * mech, MECH * target, int section,
00432                                    int weapindx, float frange, int firemode, int ammomode,
00433                                    int *wBTH)
00434 {
00435         int range;
00436         int wTargetStealth = 0;
00437 
00438         if(target)
00439                 wTargetStealth = (StealthArmorActive(target) ||
00440                                                   NullSigSysActive(target));
00441 
00442         if(MechWeapons[weapindx].special & PCOMBAT)
00443                 range = (int) (frange * 10 + 0.95);
00444         else
00445                 range = (int) (frange + 0.95);
00446 
00447         if(SectionUnderwater(mech, section)) {
00448                 if(MechWeapons[weapindx].shortrange_water <= 0) {
00449                         *wBTH = 5000;
00450                         return RANGE_NOWATER;
00451                 }
00452 
00453                 /* Out of range range */
00454                 if(range > EGunWaterRange(weapindx)) {
00455                         *wBTH = 1000;
00456                         return RANGE_TOFAR;
00457                 }
00458 
00459                 /* Very long range */
00460                 if(range > GunWaterRange(weapindx)) {
00461                         *wBTH = wTargetStealth ? 12 : 8;
00462                         return RANGE_EXTREME;
00463                 }
00464 
00465                 /* Long range... */
00466                 if(range > MechWeapons[weapindx].medrange_water) {
00467                         *wBTH = wTargetStealth ? 6 : 4;
00468                         return RANGE_LONG;
00469                 }
00470 
00471                 /* Medium range */
00472                 if(range > MechWeapons[weapindx].shortrange_water) {
00473                         *wBTH = wTargetStealth ? 3 : 2;
00474                         return RANGE_MED;
00475                 }
00476 
00477                 /* Short range */
00478                 if(range > MechWeapons[weapindx].min_water) {
00479                         *wBTH = 0;
00480                         return RANGE_SHORT;
00481                 }
00482 
00483                 if(range == 0) {
00484                         if(MechWeapons[weapindx].min_water == 0) {
00485                                 *wBTH = 0;
00486                                 return RANGE_SHORT;
00487                         } else {
00488                                 *wBTH = MechWeapons[weapindx].min_water - range;
00489                                 return RANGE_SHORT;
00490                         }
00491                 }
00492 
00493                 /* Less than or equal to minimum range */
00494                 *wBTH = MechWeapons[weapindx].min_water - range + 1;
00495         }
00496 
00497         /* Beyond range */
00498         if(range >
00499            ((ammomode & STINGER_MODE) ? (EGunRange(weapindx) + 7)
00500                 : (EGunRange(weapindx)))) {
00501                 *wBTH = 1000;
00502                 return RANGE_TOFAR;
00503         }
00504 
00505         /* V. Long range */
00506         if(range > GunRange(weapindx)) {
00507                 *wBTH = wTargetStealth ? 12 : 8;
00508                 return RANGE_EXTREME;
00509         }
00510 
00511         /* Long range... */
00512         if(range > MechWeapons[weapindx].medrange) {
00513                 *wBTH = wTargetStealth ? 6 : 4;
00514                 return RANGE_LONG;
00515         }
00516 
00517         /* Medium range */
00518         if(range > MechWeapons[weapindx].shortrange) {
00519                 *wBTH = wTargetStealth ? 3 : 2;
00520                 return RANGE_MED;
00521         }
00522 
00523         /* Short range */
00524         if(range > MechWeapons[weapindx].min) {
00525                 *wBTH = 0;
00526                 return RANGE_SHORT;
00527         }
00528         /* If we are at range 0.0
00529 
00530          * Added 8/3/99 by Kipsta (to fix a 0.0 bug)
00531          */
00532 
00533         if(range == 0) {
00534                 if(MechWeapons[weapindx].min == 0) {
00535                         *wBTH = 0;
00536                         return RANGE_SHORT;
00537                 } else {
00538                         if(!HotLoading(weapindx, firemode)) {
00539                                 *wBTH = MechWeapons[weapindx].min - range;
00540                         } else {
00541                                 if(mudconf.btech_hotloadaddshalfbthmod)
00542                                         *wBTH = ((MechWeapons[weapindx].min - range + 1) / 2);
00543                                 else
00544                                         *wBTH = 0;
00545                         }
00546 
00547                         return RANGE_SHORT;
00548                 }
00549         }
00550 
00551         if(HotLoading(weapindx, firemode)) {
00552                 if(mudconf.btech_hotloadaddshalfbthmod)
00553                         *wBTH = ((MechWeapons[weapindx].min - range + 1) / 2);
00554                 else
00555                         *wBTH = 0;
00556 
00557                 return RANGE_SHORT;
00558         }
00559 
00560         /* Less than or equal to minimum range */
00561         *wBTH = MechWeapons[weapindx].min - range + 1;
00562         return RANGE_SHORT;
00563 }
00564 
00565 int FindBTHByC3Range(MECH * mech, MECH * target, int section,
00566                                          int weapindx, float realRange, float c3Range, int mode,
00567                                          int *wBTH)
00568 {
00569         int realRangeAdj = 0.0;
00570         int c3RangeAdj = 0.0;
00571         int wTargetStealth = 0;
00572 
00573         if(target)
00574                 wTargetStealth = (StealthArmorActive(target) ||
00575                                                   NullSigSysActive(target));
00576 
00577         if(MechWeapons[weapindx].special & PCOMBAT) {
00578                 realRangeAdj = (int) (realRange * 10 + 0.95);
00579                 c3RangeAdj = (int) (c3Range * 10 + 0.95);
00580         } else {
00581                 realRangeAdj = (int) (realRange + 0.95);
00582                 c3RangeAdj = (int) (c3Range + 0.95);
00583         }
00584 
00585         if(SectionUnderwater(mech, section)) {
00586                 if(MechWeapons[weapindx].shortrange_water <= 0) {
00587                         *wBTH = 5000;
00588                         return RANGE_NOWATER;
00589                 }
00590 
00591                 /* Out of range. No ERange in C3 */
00592                 if(realRangeAdj > GunWaterRange(weapindx)) {
00593                         *wBTH = 1000;
00594                         return RANGE_TOFAR;
00595                 }
00596 
00597                 /* Long range... */
00598                 if(c3RangeAdj > MechWeapons[weapindx].medrange_water) {
00599                         *wBTH = wTargetStealth ? 6 : 4;
00600                         return RANGE_LONG;
00601                 }
00602 
00603                 /* Medium range */
00604                 if(c3RangeAdj > MechWeapons[weapindx].shortrange_water) {
00605                         *wBTH = wTargetStealth ? 3 : 2;
00606                         return RANGE_MED;
00607                 }
00608 
00609                 /* Short range */
00610                 *wBTH = 0;
00611                 return RANGE_SHORT;
00612         }
00613 
00614         /* Beyond range */
00615         if(realRangeAdj > GunRange(weapindx)) {
00616                 *wBTH = 1000;
00617                 return RANGE_TOFAR;
00618         }
00619 
00620         /* No V. Long range in a C3 network */
00621         /* Long range... */
00622         if(c3RangeAdj > MechWeapons[weapindx].medrange) {
00623                 *wBTH = wTargetStealth ? 6 : 4;
00624                 return RANGE_LONG;
00625         }
00626 
00627         /* Medium range */
00628         if(c3RangeAdj > MechWeapons[weapindx].shortrange) {
00629                 *wBTH = wTargetStealth ? 3 : 2;
00630                 return RANGE_MED;
00631         }
00632 
00633         /* Short range */
00634         if(realRange > MechWeapons[weapindx].min) {
00635                 *wBTH = 0;
00636                 return RANGE_SHORT;
00637         }
00638 
00639         /* Check for range 0.0 */
00640         if(c3RangeAdj == 0) {
00641                 if(MechWeapons[weapindx].min == 0) {
00642                         *wBTH = 0;
00643                         return RANGE_SHORT;
00644                 }
00645         }
00646 
00647         /* We don't care about min range if we're Hotloading */
00648         if(!HotLoading(weapindx, mode)) {
00649                 if(mudconf.btech_hotloadaddshalfbthmod)
00650                         *wBTH = ((MechWeapons[weapindx].min - realRange + 1) / 2);
00651                 else
00652                         *wBTH = 0;
00653 
00654                 return RANGE_SHORT;
00655         }
00656 
00657         /* Less than or equal to minimum PHYSICAL range */
00658         *wBTH = MechWeapons[weapindx].min - realRange + 1;
00659         return RANGE_SHORT;
00660 }
00661 
00662 int AttackMovementMods(MECH * mech)
00663 {
00664         float maxspeed;
00665         float speed;
00666         int base = 0;
00667 
00668         if(MechType(mech) == CLASS_BSUIT)
00669                 return 0;
00670 
00671         maxspeed = MechMaxSpeed(mech);
00672         if((MechHeat(mech) >= 9.) && (MechSpecials(mech) & TRIPLE_MYOMER_TECH))
00673                 maxspeed += 1.5 * MP1;
00674         if(Jumping(mech))
00675                 return 3;
00676 
00677         /* quads don't suffer the +2 BTH firing while prone if they have all 4 legs */
00678         if((!MechIsQuad(mech) || (MechIsQuad(mech) &&
00679                                                           CountDestroyedLegs(mech) > 0)) && Fallen(mech)
00680            && !IsDS(mech))
00681                 return 2;
00682 
00683         if(!Jumping(mech) && (Stabilizing(mech) || Standing(mech)))
00684                 return 2;
00685 
00686         if(fabs(MechSpeed(mech)) > fabs(MechDesiredSpeed(mech)))
00687                 speed = MechSpeed(mech);
00688         else
00689                 speed = MechDesiredSpeed(mech);
00690 
00691         if(mudconf.btech_fasaturn)
00692                 if(MechFacing(mech) != MechDesiredFacing(mech))
00693                         base++;
00694 
00695         if(!(fabs(speed) > 0.0))
00696                 return base + 0;
00697         if(IsRunning(speed, maxspeed))
00698                 return 2;
00699         return base + 1;
00700 }
00701 
00702 int TargetMovementMods(MECH * mech, MECH * target, float range)
00703 {
00704         float target_speed = 0.0;
00705         int returnValue = 0;
00706         float m = 1.0;
00707         MAP *map = FindObjectsData(target->mapindex);
00708         MECH *swarmTarget;
00709 
00710         if(is_aero(target)) {
00711                 if(is_aero(mech))
00712                         m = ACCEL_MOD;
00713                 target_speed =
00714                         (float) length_hypotenuse((double) MechSpeed(target) / m,
00715                                                                           (double) MechVerticalSpeed(target) / m);
00716         } else {
00717                 if(Jumping(target)) {
00718                         target_speed = JumpSpeed(target, map);
00719                 } else if(MechSwarmTarget(target) > 0) {
00720                         if((swarmTarget = getMech(MechSwarmTarget(target)))) {
00721                                 if(Jumping(swarmTarget))
00722                                         target_speed = JumpSpeed(swarmTarget, map);
00723                                 else
00724                                         target_speed = fabs(MechSpeed(swarmTarget));
00725                         }
00726                 } else {
00727                         target_speed = fabs(MechSpeed(target));
00728                 }
00729         }
00730 
00731         if(MechInfantrySpecials(target) & CS_PURIFIER_STEALTH_TECH) {
00732                 if(target_speed == 0.0) {
00733                         /* Mech moved 0-2 hexes */
00734                         returnValue = 3;
00735                 } else if(target_speed <= MP1) {
00736                         /* Mech moved 3-4 hexes */
00737                         returnValue = 2;
00738                 } else if(target_speed <= MP2) {
00739                         /* Mech moved 5-6 hexes */
00740                         returnValue = 1;
00741                 } else {
00742                         returnValue = 0;
00743                 }
00744         } else {
00745                 if(target_speed <= MP2) {
00746                         /* Mech moved 0-2 hexes */
00747                         returnValue = 0;
00748                 } else if(target_speed <= MP4) {
00749                         /* Mech moved 3-4 hexes */
00750                         returnValue = 1;
00751                 } else if(target_speed <= MP6) {
00752                         /* Mech moved 5-6 hexes */
00753                         returnValue = 2;
00754                 } else if(target_speed <= MP9) {
00755                         /* Mech moved 7-9 hexes */
00756                         returnValue = 3;
00757                 } else {
00758                         /* Moving more than 9 hexes */
00759                         if(mudconf.btech_extendedmovemod)
00760                                 returnValue = 4 + (target_speed - 10 * MP1) / MP4;
00761                         else
00762                                 returnValue = 4;
00763                 }
00764         }
00765 
00766         if(Immobile(target))
00767                 returnValue += -4;
00768 
00769         if(Fallen(target) && ((MechType(target) == CLASS_MECH) ||
00770                                                   (MechType(target) == CLASS_MW)))
00771                 returnValue += (range <= 1.0) ? -2 : 1;
00772 
00773         if(Jumping(target))
00774                 returnValue++;
00775 
00776         return (returnValue);
00777 }

Generated on Mon May 28 04:25:21 2007 for BattletechMUX by  doxygen 1.4.7