src/hcode/btech/mech.combat.c File Reference

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/file.h>
#include "mech.h"
#include "map.h"
#include "btmacros.h"
#include "mech.events.h"
#include "create.h"
#include "failures.h"
#include "mech.combat.h"
#include "mech.partnames.h"
#include "p.mech.ice.h"
#include "p.pcombat.h"
#include "p.mech.utils.h"
#include "p.mech.los.h"
#include "p.mech.build.h"
#include "p.map.obj.h"
#include "p.mech.combat.h"
#include "p.btechstats.h"
#include "p.mech.update.h"
#include "p.bsuit.h"
#include "p.artillery.h"
#include "p.mech.fire.h"
#include "p.mech.c3.h"
#include "p.mech.c3i.h"
#include "p.mech.c3.misc.h"
#include "p.mine.h"
#include "p.mech.hitloc.h"
#include "p.eject.h"
#include "p.crit.h"
#include "p.mech.ood.h"
#include "p.map.conditions.h"
#include "p.template.h"
#include "p.mech.pickup.h"
#include "p.event.h"
#include "p.mech.tag.h"
#include "p.mech.ecm.h"
#include "mech.ecm.h"
#include "p.mech.enhanced.criticals.h"
#include "p.mech.spot.h"
#include "p.mech.combat.misc.h"
#include "p.mech.combat.missile.h"
#include "p.mech.bth.h"
#include "p.mech.damage.h"

Include dependency graph for mech.combat.c:

Go to the source code of this file.

Defines

#define SSDistMod(r)   ((r < 9) ? 0 : ((r < 20) ? 1 : 2))
#define SSTonMod(d)   ((d <= -20) ? 0 : (d >= 20) ? 2 : 1)
#define ARCCHECK(mech, ex, ey, sec, crit, msg)

Functions

void mech_target (dbref player, void *data, char *buffer)
static void mech_ss_event (MUXEVENT *ev)
void sixth_sense_check (MECH *mech, MECH *target)
void mech_settarget (dbref player, void *data, char *buffer)
void mech_fireweapon (dbref player, void *data, char *buffer)
int FireWeaponNumber (dbref player, MECH *mech, MAP *mech_map, int weapnum, int argc, char **args, int sight)
int weapon_failure_stuff (MECH *mech, int *weapnum, int *weapindx, int *section, int *critical, int *ammoLoc, int *ammoCrit, int *ammoLoc1, int *ammoCrit1, int *modifier, int *type, float range, int *range_ok, int wGattlingShots)
void sendC3TrackEmit (MECH *mech, dbref c3Ref, MECH *c3Mech)
void FireWeapon (MECH *mech, MAP *mech_map, MECH *target, int LOS, int weapindx, int weapnum, int section, int critical, float enemyX, float enemyY, int mapx, int mapy, float range, int indirectFire, int sight, int ishex)
int determineDamageFromHit (MECH *mech, int wSection, int wCritSlot, MECH *hitMech, int hitX, int hitY, int weapindx, int wGattlingShots, int wBaseWeapDamage, int wAmmoMode, int type, int modifier, int isTempCalc)
void HitTarget (MECH *mech, int weapindx, int wSection, int wCritSlot, MECH *hitMech, int hitX, int hitY, int LOS, int type, int modifier, int reallyhit, int bth, int wGattlingShots, int tIsSwarmAttack, int player_roll)
char * hex_target_id (MECH *mech)
int canWeaponIgnite (int weapindx)
int canWeaponClear (int weapindx)
void possibly_ignite (MECH *mech, MAP *map, int weapindx, int ammoMode, int x, int y, int intentional)
void possibly_clear (MECH *mech, MAP *map, int weapindx, int ammoMode, int damage, int x, int y, int intentional)
void possibly_ignite_or_clear (MECH *mech, int weapindx, int ammoMode, int damage, int x, int y, int intentional)
void hex_hit (MECH *mech, int x, int y, int weapindx, int ammoMode, int damage, int ishit)

Variables

int arc_override
dbref pilot_override
char * ss_messages []


Define Documentation

#define ARCCHECK ( mech,
ex,
ey,
sec,
crit,
msg   ) 

Value:

if (AeroUnusableArcs(mech)) \
{ int ar; ar = InWeaponArc(mech, ex, ey); \
DOCHECK0((!arc_override && (AeroUnusableArcs(mech) & ar)) || \
(arc_override && !(arc_override & ar)), \
"That arc's weapons aren't under your control!"); \
}; \
DOCHECK0(!IsInWeaponArc (mech, ex, ey, sec, crit), \
msg);

Definition at line 357 of file mech.combat.c.

Referenced by FireWeaponNumber().

#define SSDistMod (  )     ((r < 9) ? 0 : ((r < 20) ? 1 : 2))

Definition at line 149 of file mech.combat.c.

Referenced by sixth_sense_check().

#define SSTonMod (  )     ((d <= -20) ? 0 : (d >= 20) ? 2 : 1)

Definition at line 150 of file mech.combat.c.

Referenced by sixth_sense_check().


Function Documentation

int canWeaponClear ( int  weapindx  ) 

Definition at line 1849 of file mech.combat.c.

References MechWeapons.

Referenced by possibly_clear().

01850 {
01851         if(strcmp(&MechWeapons[weapindx].name[3], "ERSmallLaser") &&
01852            strcmp(&MechWeapons[weapindx].name[3], "SmallLaser") &&
01853            strcmp(&MechWeapons[weapindx].name[3], "SmallPulseLaser") &&
01854            strcmp(&MechWeapons[weapindx].name[3], "X-SmallPulseLaser") &&
01855            strcmp(&MechWeapons[weapindx].name[3], "ERSmallPulseLaser") &&
01856            strcmp(&MechWeapons[weapindx].name[3], "HeavySmallLaser") &&
01857            strcmp(&MechWeapons[weapindx].name[3], "MachineGun") &&
01858            strcmp(&MechWeapons[weapindx].name[3], "LightMachineGun") &&
01859            strcmp(&MechWeapons[weapindx].name[3], "HeavyMachineGun") &&
01860            strcmp(&MechWeapons[weapindx].name[3], "AC/2") &&
01861            strcmp(&MechWeapons[weapindx].name[3], "UltraAC/2") &&
01862            strcmp(&MechWeapons[weapindx].name[3], "CaselessAC/2") &&
01863            strcmp(&MechWeapons[weapindx].name[3], "HyperAC/2") &&
01864            strcmp(&MechWeapons[weapindx].name[3], "LightAC/2") &&
01865            strcmp(&MechWeapons[weapindx].name[3], "RotaryAC/2") &&
01866            strcmp(&MechWeapons[weapindx].name[3], "LB2-XAC") &&
01867            strcmp(&MechWeapons[weapindx].name[3], "AC/5") &&
01868            strcmp(&MechWeapons[weapindx].name[3], "UltraAC/5") &&
01869            strcmp(&MechWeapons[weapindx].name[3], "CaselessAC/5") &&
01870            strcmp(&MechWeapons[weapindx].name[3], "HyperAC/5") &&
01871            strcmp(&MechWeapons[weapindx].name[3], "LightAC/5") &&
01872            strcmp(&MechWeapons[weapindx].name[3], "RotaryAC/5") &&
01873            strcmp(&MechWeapons[weapindx].name[3], "LB5-XAC") &&
01874            strcmp(&MechWeapons[weapindx].name[3], "StreakSRM-2") &&
01875            strcmp(&MechWeapons[weapindx].name[3], "SRM-2"))
01876                 return 1;
01877 
01878         return 0;
01879 }

int canWeaponIgnite ( int  weapindx  ) 

Definition at line 1825 of file mech.combat.c.

References MechWeapons.

Referenced by possibly_ignite().

01826 {
01827         if(strcmp(&MechWeapons[weapindx].name[3], "ERSmallLaser") &&
01828            strcmp(&MechWeapons[weapindx].name[3], "SmallLaser") &&
01829            strcmp(&MechWeapons[weapindx].name[3], "SmallPulseLaser") &&
01830            strcmp(&MechWeapons[weapindx].name[3], "X-SmallPulseLaser") &&
01831            strcmp(&MechWeapons[weapindx].name[3], "ERSmallPulseLaser") &&
01832            strcmp(&MechWeapons[weapindx].name[3], "HeavySmallLaser") &&
01833            strcmp(&MechWeapons[weapindx].name[3], "GaussRifle") &&
01834            strcmp(&MechWeapons[weapindx].name[3], "LightGaussRifle") &&
01835            strcmp(&MechWeapons[weapindx].name[3], "HeavyGaussRifle") &&
01836            strcmp(&MechWeapons[weapindx].name[3], "MagshotGaussRifle") &&
01837            strcmp(&MechWeapons[weapindx].name[3], "MachineGun") &&
01838            strcmp(&MechWeapons[weapindx].name[3], "LightMachineGun") &&
01839            strcmp(&MechWeapons[weapindx].name[3], "HeavyMachineGun") &&
01840            strcmp(&MechWeapons[weapindx].name[3], "StreakSRM-2") &&
01841            strcmp(&MechWeapons[weapindx].name[3], "SRM-2") &&
01842            strcmp(&MechWeapons[weapindx].name[3], "NarcBeacon") &&
01843            strcmp(&MechWeapons[weapindx].name[3], "iNarcBeacon"))
01844                 return 1;
01845 
01846         return 0;
01847 }

int determineDamageFromHit ( MECH mech,
int  wSection,
int  wCritSlot,
MECH hitMech,
int  hitX,
int  hitY,
int  weapindx,
int  wGattlingShots,
int  wBaseWeapDamage,
int  wAmmoMode,
int  type,
int  modifier,
int  isTempCalc 
)

Definition at line 1409 of file mech.combat.c.

References AC_FLECHETTE_MODE, AC_INCENDIARY_MODE, confdata::btech_moddamagewithrange, confdata::btech_moddamagewithwoods, CLASS_BSUIT, CLASS_MW, DAMAGE, Elevation, FaMechRange, FindHexRange(), getCritSubDamage(), getMap(), GetRTerrain, GRASSLAND, HEAVY_FOREST, IsEnergy, IsForestHex, LIGHT_FOREST, MapCoordToRealCoord(), MECH::mapindex, mech_notify(), MECHALL, MechFX, MechFY, MechRTerrain, MechType, MechWeapons, MechX, MechY, MechZ, mudconf, possibly_ignite_or_clear(), and SectionUnderwater.

Referenced by HitTarget().

01420 {
01421         MAP *mech_map;
01422         float fRange = 0.0;
01423         int wWeapDamage = wBaseWeapDamage;
01424         int wClearDamage = 0;
01425 
01426         /* Find the range to our target */
01427         if(hitMech)
01428                 fRange = FaMechRange(mech, hitMech);
01429         else {
01430                 float fx, fy;
01431                 MapCoordToRealCoord(hitX, hitY, &fx, &fy);
01432                 fRange = FindHexRange(MechFX(mech), MechFY(mech), fx, fy);
01433         }
01434 
01435         /* If our Gattling shots are greater then 0, use that as the damage. */
01436         if(wGattlingShots > 0)
01437                 wWeapDamage = wGattlingShots;
01438 
01439         /* If we're a heavy gauss rifle, damage gets altered by range. */
01440         if(MechWeapons[weapindx].special & HVYGAUSS) {
01441                 if(fRange > MechWeapons[weapindx].medrange)
01442                         wWeapDamage = 10;
01443                 else if(fRange > MechWeapons[weapindx].shortrange)
01444                         wWeapDamage = 20;
01445         }
01446 
01447         wWeapDamage -= getCritSubDamage(mech, wSection, wCritSlot);
01448 
01449         /* See if we're using flechette ammo */
01450         if(hitMech) {
01451                 if(wAmmoMode & AC_FLECHETTE_MODE) {
01452                         if(MechType(hitMech) == CLASS_MW) {
01453                                 if(MechRTerrain(hitMech) == GRASSLAND)
01454                                         wWeapDamage *= 4;
01455                                 else
01456                                         wWeapDamage *= 2;
01457                         } else if(MechType(hitMech) != CLASS_BSUIT)
01458                                 wWeapDamage /= 2;
01459                 }
01460 
01461                 if(wAmmoMode & AC_INCENDIARY_MODE) {
01462                         if(MechType(hitMech) == CLASS_MW)
01463                                 wWeapDamage += 2;
01464                 }
01465         }
01466 
01467         /* Check to see if we have an energy weapon and we're modding the damage based on range */
01468         if(mudconf.btech_moddamagewithrange && IsEnergy(weapindx)) {
01469                 if(fRange <= 1.0)
01470                         wWeapDamage++;
01471                 else {
01472                         if(SectionUnderwater(mech, wSection)) {
01473                                 if(fRange > MechWeapons[weapindx].longrange_water)
01474                                         wWeapDamage = (wWeapDamage / 2);
01475                                 else if(fRange > MechWeapons[weapindx].medrange_water)
01476                                         wWeapDamage--;
01477                         } else {
01478                                 if(fRange > MechWeapons[weapindx].longrange)
01479                                         wWeapDamage = (wWeapDamage / 2);
01480                                 else if(fRange > MechWeapons[weapindx].medrange)
01481                                         wWeapDamage--;
01482                         }
01483                 }
01484         }
01485 
01486         /* Check to see if we're modding the damage based on woods cover */
01487         mech_map = getMap(mech->mapindex);
01488 
01489         /* If there was a damage type failure, mod the damage */
01490         if(type == DAMAGE)
01491                 wWeapDamage -= modifier;
01492 
01493         if(hitMech && !isTempCalc) {
01494                 if(mudconf.btech_moddamagewithwoods &&
01495                    IsForestHex(mech_map, MechX(hitMech), MechY(hitMech)) &&
01496                    ((MechZ(hitMech) - 2) <= Elevation(mech_map, MechX(hitMech),
01497                                                                                           MechY(hitMech)))) {
01498                         wClearDamage = wWeapDamage;
01499 
01500                         if(GetRTerrain(mech_map, MechX(hitMech),
01501                                                    MechY(hitMech)) == LIGHT_FOREST)
01502                                 wWeapDamage -= 2;
01503                         else if(GetRTerrain(mech_map, MechX(hitMech),
01504                                                                 MechY(hitMech)) == HEAVY_FOREST)
01505                                 wWeapDamage -= 4;
01506 
01507                         mech_notify(mech, MECHALL, "The woods absorb some of your shot!");
01508                         mech_notify(hitMech, MECHALL,
01509                                                 "The woods absorb some of the damage!");
01510 
01511                         possibly_ignite_or_clear(mech, weapindx, wAmmoMode,
01512                                                                          wClearDamage, MechX(hitMech),
01513                                                                          MechY(hitMech), 1);
01514                 }
01515         }
01516 
01517         if(wWeapDamage <= 0)
01518                 wWeapDamage = 1;
01519 
01520         return wWeapDamage;
01521 }

void FireWeapon ( MECH mech,
MAP mech_map,
MECH target,
int  LOS,
int  weapindx,
int  weapnum,
int  section,
int  critical,
float  enemyX,
float  enemyY,
int  mapx,
int  mapy,
float  range,
int  indirectFire,
int  sight,
int  ishex 
)

Definition at line 761 of file mech.combat.c.

References ArmorStringFromIndex(), ATTACKEMIT_MECH, CrewStunned, DFM, DOCHECKMA, ELRM, FaMechRange, FindAndCheckAmmo(), FindArtilleryBTH(), FindNormalBTH(), MAP::first_free, FlyingT, GATTLING_MODE, getMech(), GetMechToMechID(), GetPartAmmoMode, GetPartFireMode, HEAT_MODE, hex_target_id(), IsArtillery, IsCoolant, IsMissile, Jumping, Landed, LBUF_SIZE, mech_printf(), MechAim, MechAimType, MECHALL, MechMove, MECHPILOT, MAP::mechsOnMap, MechStatus, MechStatus2, MechSwarmTarget, MechTeam, MechType, MechWeapons, MechX, MechY, MECH::mynum, name, NUM_SECTIONS, Number, OODing, PARTIAL_COVER, RemovingPods, Roll(), SBUF_SIZE, SectionUnderwater, SendAttackEmits, SendAttacks, sendC3TrackEmit(), short_hextarget(), STINGER_MODE, Swap, tprintf(), UnJammingAmmo, and UnjammingTurret.

Referenced by FireSpot(), and FireWeaponNumber().

00773 {
00774         MECH *altTarget;
00775         int baseToHit,RbaseToHit;
00776         int ammoLoc;
00777         int ammoCrit;
00778         int ammoLoc1;
00779         int ammoCrit1;
00780         int roll;
00781         int r1, r2, r3, rtmp;
00782         int type = -1, modifier;
00783         int isarty = (IsArtillery(weapindx));
00784         int range_ok = 1;
00785         int wGattlingShots = 0;         /* If we're a gattling MG, then we need to figure out how many shots */
00786         char buf[SBUF_SIZE];
00787         char buf3[SBUF_SIZE];
00788         char buf2[LBUF_SIZE];
00789         int wRACHeat = 0;
00790         int wHGRPSkillMod = 0;
00791         int tIsSwarmAttack = 0;
00792         dbref c3Ref = -1;
00793         MECH *c3Mech = NULL;
00794         int firstCrit = 0;
00795         int mode = GetPartFireMode(mech, section, critical);
00796         int wAmmoMode = GetPartAmmoMode(mech, section, critical);
00797 
00798         DOCHECKMA((wAmmoMode & STINGER_MODE)
00799                           && ishex, "Stinger missiles cannot shoot hexes!");
00800         DOCHECKMA((wAmmoMode & STINGER_MODE) && target
00801                           && !(Jumping(target) || OODing(target)
00802                                    || (FlyingT(target)
00803                                            && !Landed(target))),
00804                           "Stinger missiles can only engage airborne targets!");
00805 
00806         /* If its a coolant gun set to heat, set the target
00807          * to the mech (ie it shoots itself with coolant gun) */
00808         if(IsCoolant(weapindx) && mode & HEAT_MODE)
00809                 target = mech;
00810 
00811         DOCHECKMA((SectionUnderwater(mech, section) &&
00812                            (MechWeapons[weapindx].shortrange_water <= 0)),
00813                           "This weapon may not be fired underwater.");
00814         DOCHECKMA(CrewStunned(mech), "You are too stunned to fire a weapon!");
00815         DOCHECKMA(UnjammingTurret(mech),
00816                           "You are too busy unjamming your turret!");
00817         DOCHECKMA(UnJammingAmmo(mech), "You are too busy unjamming a weapon!");
00818         DOCHECKMA(RemovingPods(mech), "You are too busy removing iNARC pods!");
00819 
00820         DOCHECKMA((MechSwarmTarget(mech) > 0) && ((!target) ||
00821                                                                                           (MechSwarmTarget(mech) !=
00822                                                                                            target->mynum)),
00823                           "You're too busy holding on for dear life!");
00824 
00825         if(MechSwarmTarget(mech) > 0) {
00826                 if(target && (MechSwarmTarget(mech) == target->mynum))
00827                         tIsSwarmAttack = 1;
00828         }
00829 
00830         /*
00831          * Gattling MGs do d6 damage (all as one hit), causing the same in heat
00832          * and using 3 * damage in ammo.
00833          */
00834         if(GetPartFireMode(mech, section, critical) & GATTLING_MODE)
00835                 wGattlingShots = Number(1, 6);
00836 
00837         /* Find and check Ammunition */
00838         if(!sight)
00839                 if(!FindAndCheckAmmo(mech, weapindx, section, critical, &ammoLoc,
00840                                                          &ammoCrit, &ammoLoc1, &ammoCrit1,
00841                                                          &wGattlingShots))
00842                         return;
00843 
00844                         /****************************************
00845             * START: Calc BTH and Roll
00846         ****************************************/
00847         if(!isarty) {
00848                 baseToHit =
00849                         FindNormalBTH(mech, mech_map, section, critical, weapindx,
00850                                                   range, target, indirectFire, &c3Ref);
00851 
00852                 if(c3Ref) {
00853                         c3Mech = getMech(c3Ref);
00854 
00855                         if(c3Mech && ((MechTeam(c3Mech) != MechTeam(mech)) ||
00856                                                   (c3Ref == mech->mynum))) {
00857                                 c3Mech = NULL;
00858                         }
00859                 }
00860 
00861         } else
00862                 baseToHit = FindArtilleryBTH(mech, section, weapindx, !LOS, range);
00863 
00864         /* If it's a swarm attack, make the BTH 0 'cause they always hit */
00865         if(tIsSwarmAttack)
00866                 baseToHit = 0;
00867 
00868         /* Mod the roll for DFMs and ELRMS */
00869         if((MechWeapons[weapindx].special & DFM) ||
00870            ((MechWeapons[weapindx].special & ELRM) &&
00871                 range < MechWeapons[weapindx].min)) {
00872                 r1 = Number(1, 6);
00873                 r2 = Number(1, 6);
00874                 r3 = Number(1, 6);
00875                 /* Sort 'em to ascending order */
00876                 if(r1 > r2)
00877                         Swap(r1, r2);
00878                 if(r2 > r3)
00879                         Swap(r2, r3);
00880                 roll = r1 + r2;
00881         } else {
00882                 if(target)
00883                         roll = Roll();
00884                 else
00885                         roll = Roll();
00886         }
00887         buf[0] = 0;
00888         if(LOS)
00889                 sprintf(buf, "Roll: %d ", roll);
00890 
00891                         /****************************************
00892             * END: Calc BTH and Roll
00893         ****************************************/
00894 
00895                 /****************************************
00896         * START: Do all the necessary emits for sighting and firing
00897         ****************************************/
00898         if(target && !ishex) {
00899                 range = FaMechRange(mech, target);
00900                 strcpy(buf2, "");
00901                 if(MechAim(mech) != NUM_SECTIONS &&
00902                    MechAimType(mech) == MechType(target) && !IsMissile(weapindx)) {
00903                         ArmorStringFromIndex(MechAim(mech), buf3, MechType(target),
00904                                                                  MechMove(target));
00905                         sprintf(buf2, "'s %s", buf3);
00906                 }
00907 
00908                 if(sight) {
00909                         DOCHECKMA(baseToHit >= 900,
00910                                           tprintf("You aim %s at %s%s - Out of range.",
00911                                                           &MechWeapons[weapindx].name[3],
00912                                                           GetMechToMechID(mech, target), buf2));
00913 
00914                         sendC3TrackEmit(mech, c3Ref, c3Mech);
00915 
00916                         mech_printf(mech, MECHALL,
00917                                                 "You aim %s at %s%s - BTH: %d %s",
00918                                                 &MechWeapons[weapindx].name[3],
00919                                                 GetMechToMechID(mech, target), buf2,
00920                                                 baseToHit,
00921                                                 MechStatus(target) & PARTIAL_COVER ?
00922                                                 "(Partial cover)" : "");
00923                         return;
00924                 }
00925                 if(baseToHit > 12) {
00926                         DOCHECKMA(baseToHit >= 900,
00927                                           tprintf("Fire %s at %s%s - Out of range.",
00928                                                           &MechWeapons[weapindx].name[3],
00929                                                           GetMechToMechID(mech, target), buf2));
00930                         mech_printf(mech, MECHALL,
00931                                                 "Fire %s at %s%s - BTH: %d  Roll: Impossible! %s",
00932                                                 &MechWeapons[weapindx].name[3],
00933                                                 GetMechToMechID(mech, target), buf2, baseToHit,
00934                                                 MechStatus(target) & PARTIAL_COVER ?
00935                                                 "(Partial cover)" : "");
00936                         return;
00937                 }
00938         } else {
00939                 /* Hex target sight info */
00940                 if(sight) {
00941                         if(baseToHit > 900)
00942                                 mech_printf(mech, MECHPILOT,
00943                                                         "You aim your %s at (%d,%d) - Out of Range.",
00944                                                         &MechWeapons[weapindx].name[3], mapx, mapy);
00945                         else {
00946                                 sendC3TrackEmit(mech, c3Ref, c3Mech);
00947 
00948                                 mech_printf(mech, MECHPILOT,
00949                                                         "You aim your %s at (%d,%d) - BTH: %d",
00950                                                         &MechWeapons[weapindx].name[3], mapx,
00951                                                         mapy, baseToHit);
00952                         }
00953 
00954                         return;
00955                 }
00956                 if(!isarty && baseToHit > 12) {
00957                         mech_printf(mech, MECHALL,
00958                                                 "Fire %s at (%d,%d) - BTH: %d  Roll: Impossible!",
00959                                                 &MechWeapons[weapindx].name[3], mapx, mapy,
00960                                                 baseToHit);
00961                         return;
00962                 }
00963         }
00964 
00965         if(target && !ishex) {
00966                 sendC3TrackEmit(mech, c3Ref, c3Mech);
00967 
00968                 mech_printf(mech, MECHALL,
00969                                         "You fire %s at %s%s - BTH: %d  %s%s",
00970                                         &MechWeapons[weapindx].name[3],
00971                                         GetMechToMechID(mech, target), buf2, baseToHit,
00972                                         buf,
00973                                         MechStatus(target) & PARTIAL_COVER ?
00974                                         "(Partial cover)" : "");
00975 
00976                 /* Switching to Exile method of tracking xp, where we split
00977                  * Attacking and Piloting xp into two different channels
00978                  * And since this is neither it goes to its own channel
00979                  */
00980                 SendAttacks(tprintf("#%i attacks #%i (weapon) (%i/%i)",
00981                                                         mech->mynum, target->mynum, baseToHit, roll));
00982 /*    
00983         SendXP(tprintf("#%i attacks #%i (weapon) (%i/%i)", mech->mynum,
00984             target->mynum, baseToHit, roll));
00985 */
00986                 /* If the target has the ATTACKEMIT_MECH flag on have it
00987                  * output this info as well
00988                  */
00989                 if(MechStatus2(target) & ATTACKEMIT_MECH)
00990                         SendAttackEmits(tprintf("#%i attacks #%i (weapon) (%i/%i)",
00991                                                                         mech->mynum, target->mynum, baseToHit,
00992                                                                         roll));
00993 
00994         } else {
00995                 sendC3TrackEmit(mech, c3Ref, c3Mech);
00996 
00997                 mech_printf(mech, MECHALL,
00998                                         "You fire %s %s (%d,%d) - BTH: %d  %s",
00999                                         &MechWeapons[weapindx].name[3],
01000                                         hex_target_id(mech), mapx, mapy, baseToHit, buf);
01001 
01002                 /* Switching to Exile method of tracking xp, where we split
01003                  * Attacking and Piloting xp into two different channels
01004                  * And since this is neither it goes to its own channel
01005                  */
01006                 SendAttacks(tprintf("#%i attacks %d,%d (%s) (weapon) (%i/%i)",
01007                                                         mech->mynum, mapx, mapy, short_hextarget(mech),
01008                                                         baseToHit, roll));
01009 /*
01010         SendXP(tprintf("#%i attacks %d,%d (%s) (weapon) (%i/%i)",
01011             mech->mynum, mapx, mapy, short_hextarget(mech),
01012             baseToHit, roll));
01013 */
01014 
01015                 /* Big Block of code here. Basicly it checks all the targets
01016                  * in the hex the attacker is firing at. For each one that
01017                  * has ATTACKEMIT_MECH set, it broadcasts that info
01018                  */
01019                 {
01020                         MECH *tmpmech;
01021                         int foo;
01022 
01023                         for(foo = 0; foo < mech_map->first_free; foo++) {
01024 
01025                                 if(mech_map->mechsOnMap[foo] >= 0) {
01026 
01027                                         if(!(tmpmech = getMech(mech_map->mechsOnMap[foo])))
01028                                                 continue;
01029                                         if(mech->mynum == tmpmech->mynum)
01030                                                 continue;
01031                                         if(MechX(tmpmech) != mapx && MechY(tmpmech) != mapy)
01032                                                 continue;
01033                                         if(MechStatus2(tmpmech) & ATTACKEMIT_MECH)
01034                                                 SendAttackEmits(tprintf
01035                                                                                 ("#%i attacks %d,%d (%s) (weapon)"
01036                                                                                  " (%i/%i)", mech->mynum, mapx, mapy,
01037                                                                                  short_hextarget(mech), baseToHit,
01038                                                                                  roll));
01039                                 }
01040 
01041                         }
01042 
01043                 }
01044 
01045         }
01046 
01047                 /****************************************
01048         * END: Do all the necessary emits for sighting and firing
01049         ****************************************/
01050 
01051         /* Check for weapon failures */
01052         if(weapon_failure_stuff(mech, &weapnum, &weapindx, &section,
01053                                                         &critical, &ammoLoc, &ammoCrit, &ammoLoc1,
01054                                                         &ammoCrit1, &modifier, &type, range,
01055                                                         &range_ok, wGattlingShots))
01056                 return;
01057 
01058         /* See if our streaks work */
01059         if(MechWeapons[weapindx].special & STREAK) {
01060                 if(target && (AngelECMDisturbed(mech) || AngelECMProtected(target)))
01061                         mech_notify(mech, MECHALL,
01062                                                 "The ECM confuses your streak homing system!");
01063                 else if(roll < baseToHit) {
01064                         SetRecyclePart(mech, section, critical,
01065                                                    WEAPON_TICK * MechWeapons[weapindx].vrt);
01066                         mech_notify(mech, MECHALL, "Your streak fails to lock on.");
01067                         return;
01068                 }
01069         }
01070 
01071         /* Hotload LRM jams on 2 or 3 */
01072         if(GetPartFireMode(mech, section, critical) & HOTLOAD_MODE) {
01073                 if(roll == 2 || roll == 3) {
01074                         mech_printf(mech, MECHALL,
01075                                                 "%%ch%%crThe ammo loading mechanism jams on your %s!%%cn",
01076                                                 &(MechWeapons[weapindx].name[3]));
01077                         SetPartTempNuke(mech, section, critical, FAIL_AMMOJAMMED);
01078                         return;
01079                 }
01080         }
01081 
01082         /* Caseless jams on a 2. Next internal roll of 8+ explodes */
01083         if(GetPartAmmoMode(mech, section, critical) & AC_CASELESS_MODE) {
01084                 if(roll == 2 || roll == 3) {
01085                         mech_printf(mech, MECHALL,
01086                                         "%%ch%%crThe ammo loading mechanism jams on your %s!%%cn",
01087                                         &(MechWeapons[weapindx].name[3]));
01088                         SetPartTempNuke(mech, section, critical, FAIL_AMMOJAMMED);
01089                         /* do 8+ explosion check. Per tac handbook, the launcher explodes on failure*/
01090                         if(Roll() > 7 ) {
01091                                 /* Rut roh shaggy. Time to cause some damage! */
01092                                 mech_printf(mech, MECHALL,
01093                                                 "%%ch%%crPropellant from your %s ignites and destroys it!%%cn",
01094                                                 &(MechWeapons[weapindx].name[3]));
01095                                 firstCrit = FindFirstWeaponCrit(mech, section, -1, 0, I2Weapon(weapindx), GetWeaponCrits(mech,weapindx));
01096                                 DestroyWeapon(mech, section, I2Weapon(weapindx), firstCrit,
01097                                                 GetWeaponCrits(mech, weapindx), GetWeaponCrits(mech,weapindx));
01098                                 MechLOSBroadcast(mech, "shudders from an internal explosion!");
01099                                 /* Apply damage equal to one shot, follow crits as well */
01100 
01101                                 DamageMech(mech, mech, 0, -1, section, 0, 1, 0,
01102                                                 MechWeapons[weapindx].damage, -1, 0, -1, 0,1);
01103                                 decrement_ammunition(mech, weapindx, section, critical, ammoLoc, ammoCrit,
01104                                                 ammoLoc1, ammoCrit1, wGattlingShots);
01105                                 
01106 
01107                         }
01108                         
01109                         return;
01110                 }
01111         }
01112         
01113         /* Check for RFAC explosion/jams */
01114         if(GetPartFireMode(mech, section, critical) & RFAC_MODE) {
01115                 if(roll == 2) {
01116                         mech_printf(mech, MECHALL,
01117                                                 "%%ch%%crA catastrophic misload on your %s destroys it and causes an internal explosion!%%cn",
01118                                                 &(MechWeapons[weapindx].name[3]));
01119                         firstCrit =
01120                                 FindFirstWeaponCrit(mech, section, -1, 0,
01121                                                                         I2Weapon(weapindx), GetWeaponCrits(mech,
01122                                                                                                                                            weapindx));
01123                         DestroyWeapon(mech, section, I2Weapon(weapindx), firstCrit,
01124                                                   GetWeaponCrits(mech, weapindx), GetWeaponCrits(mech,
01125                                                                                                                                                  weapindx));
01126                         MechLOSBroadcast(mech, "shudders from an internal explosion!");
01127                         DamageMech(mech, mech, 0, -1, section, 0, 0, 0,
01128                                            MechWeapons[weapindx].damage, -1, 0, -1, 0, 1);
01129                         decrement_ammunition(mech, weapindx, section, critical,
01130                                                                  ammoLoc, ammoCrit, ammoLoc1, ammoCrit1,
01131                                                                  wGattlingShots);
01132                         return;
01133                 } else if(roll < 5) {
01134                         mech_printf(mech, MECHALL,
01135                                                 "%%ch%%crThe ammo loader mechanism jams on your %s!%%cn",
01136                                                 &(MechWeapons[weapindx].name[3]));
01137                         SetPartTempNuke(mech, section, critical, FAIL_AMMOJAMMED);
01138                         return;
01139                 }
01140         }
01141 
01142         /* Check for RAC explosion/jams */
01143         if(MechWeapons[weapindx].special & RAC) {
01144                 if(((GetPartFireMode(mech, section, critical) & RAC_TWOSHOT_MODE)
01145                         && (roll == 2)) ||
01146                    ((GetPartFireMode(mech, section, critical) & RAC_FOURSHOT_MODE)
01147                         && (roll <= 3)) ||
01148                    ((GetPartFireMode(mech, section, critical) & RAC_SIXSHOT_MODE)
01149                         && (roll <= 4))) {
01150                         mech_printf(mech, MECHALL,
01151                                                 "%%ch%%crThe ammo loader mechanism jams on your %s!%%cn",
01152                                                 &(MechWeapons[weapindx].name[3]));
01153                         SetPartTempNuke(mech, section, critical, FAIL_AMMOJAMMED);
01154                         return;
01155                 }
01156         }
01157 
01158         /* Check for Ultra explosion/jams */
01159         if(GetPartFireMode(mech, section, critical) & ULTRA_MODE) {
01160                 if(roll == 2) {
01161                         mech_printf(mech, MECHALL,
01162                                                 "The loader jams on your %s, destroying it!",
01163                                                 &(MechWeapons[weapindx].name[3]));
01164                         firstCrit =
01165                                 FindFirstWeaponCrit(mech, section, -1, 0,
01166                                                                         I2Weapon(weapindx), GetWeaponCrits(mech,
01167                                                                                                                                            weapindx));
01168                         DestroyWeapon(mech, section, I2Weapon(weapindx), firstCrit,
01169                                                   GetWeaponCrits(mech, weapindx), GetWeaponCrits(mech,
01170                                                                                                                                                  weapindx));
01171                         return;
01172                 }
01173         }
01174 
01175         /* See if the sucker will explode from damage taken */
01176         if(canWeapExplodeFromDamage(mech, section, critical, roll)) {
01177                 if(IsEnergy(weapindx)) {
01178                         mech_printf(mech, MECHALL,
01179                                                 "%%ch%%crThe damaged charging crystal on your %s overloads!%%cn",
01180                                                 &(MechWeapons[weapindx].name[3]));
01181                 } else {
01182                         mech_printf(mech, MECHALL,
01183                                                 "%%ch%%crThe damaged ammo feed on your %s triggers an internal explosion!%%cn",
01184                                                 &(MechWeapons[weapindx].name[3]));
01185                         decrement_ammunition(mech, weapindx, section, critical,
01186                                                                  ammoLoc, ammoCrit, ammoLoc1, ammoCrit1,
01187                                                                  wGattlingShots);
01188                 }
01189 
01190                 MechLOSBroadcast(mech, "shudders from an internal explosion!");
01191                 firstCrit =
01192                         FindFirstWeaponCrit(mech, section, -1, 0, I2Weapon(weapindx),
01193                                                                 GetWeaponCrits(mech, weapindx));
01194                 DestroyWeapon(mech, section, I2Weapon(weapindx), firstCrit,
01195                                           GetWeaponCrits(mech, weapindx), GetWeaponCrits(mech,
01196                                                                                                                                          weapindx));
01197                 DamageMech(mech, mech, 0, -1, section, 0, 0, 0,
01198                                    MechWeapons[weapindx].damage, -1, 0, -1, 0, 1);
01199 
01200                 return;
01201         }
01202 
01203         /* See if the sucker will jam from damage taken */
01204         if(canWeapJamFromDamage(mech, section, critical, roll)) {
01205                 mech_printf(mech, MECHALL,
01206                                         "%%ch%%crThe ammo loader mechanism jams on your %s!%%cn",
01207                                         &(MechWeapons[weapindx].name[3]));
01208                 SetPartTempNuke(mech, section, critical, FAIL_AMMOCRITJAMMED);
01209 
01210                 return;
01211         }
01212 
01213         /* Trash our cocoon if we're OODing */
01214         if(OODing(mech)) {
01215                 if(MechZ(mech) > MechElevation(mech)) {
01216                         if(MechJumpSpeed(mech) >= MP1) {
01217                                 mech_notify(mech, MECHALL,
01218                                                         "You initiate your jumpjets to compensate for the opened cocoon!");
01219                                 MechCocoon(mech) = -1;
01220                         } else {
01221                                 mech_notify(mech, MECHALL,
01222                                                         "Your action splits open the cocoon - have a nice fall!");
01223                                 MechLOSBroadcast(mech,
01224                                                                  "starts plummeting down, as the cocoon opens!.");
01225                                 MechCocoon(mech) = 0;
01226                                 StopOOD(mech);
01227                                 MECHEVENT(mech, EVENT_FALL, mech_fall_event, FALL_TICK, -1);
01228                         }
01229                 }
01230         }
01231 
01232         /* Better setup some glancing stuff. There will be 3 ways to get hit..
01233          * Glancing_Blows = 0: NO Glancing. ROLL>=BTH=Normal
01234          * Glancing_Blows = 1: MaxTech Glancing. ROLL=BTH=Glance, ROLL>BTH=Normal
01235          * Glancing_Blows = 2: Exile Glancing. ROLL=BTH-1=Glance, ROLL>=BTH=Normal
01236          * We need to do a little handling here. The rest happens over it HitTarget 
01237          */
01238         RbaseToHit = baseToHit;
01239         if(mudconf.btech_glancing_blows == 2)
01240                 RbaseToHit = baseToHit - 1; /* only time we modify it */
01241         
01242         if(!isarty)
01243                 MechFireBroadcast(mech, ishex ? NULL : target, mapx, mapy,
01244                                                   mech_map, &MechWeapons[weapindx].name[3],
01245                                                   (roll >= RbaseToHit) && range_ok);
01246 
01247         /* Tell our target they were just shot at... */
01248         if(target) {
01249                 if(InLineOfSight(target, mech, MechX(mech), MechY(mech), range))
01250                         mech_printf(target, MECHALL,
01251                                                 "%s has fired a %s at you!",
01252                                                 GetMechToMechID(target, mech),
01253                                                 &MechWeapons[weapindx].name[3]);
01254                 else
01255                         mech_printf(target, MECHALL,
01256                                                 "Something has fired a %s at you from bearing %d!",
01257                                                 &MechWeapons[weapindx].name[3],
01258                                                 FindBearing(MechFX(target), MechFY(target),
01259                                                                         MechFX(mech), MechFY(mech)));
01260         }
01261 
01262         /* Time to decide if we've really hit them and wot to do */
01263         MechStatus(mech) |= FIRED;
01264 
01265         if(isarty) {
01266                 artillery_shoot(mech, mapx, mapy, weapindx,
01267                                                 GetPartAmmoMode(mech, section, critical),
01268                                                 baseToHit <= roll);
01269         } else if(range_ok) {
01270                 if(IsMissile(weapindx)) {
01271                         HitTarget(mech, weapindx, section, critical, target, mapx,
01272                                           mapy, LOS, type, modifier,
01273                                  (roll >= RbaseToHit) && range_ok, baseToHit, wGattlingShots, tIsSwarmAttack,
01274                                           roll);
01275                 } else {
01276                         if(roll >= RbaseToHit) {
01277                                 HitTarget(mech, weapindx, section, critical, target, mapx,
01278                                                   mapy, LOS, type, modifier, 1, RbaseToHit,
01279                                                   wGattlingShots, tIsSwarmAttack, roll);
01280                         } else {
01281                                 int tTryClear = 1;
01282 
01283                                 if(target) {
01284                                         if((MechType(target) == CLASS_BSUIT) &&
01285                                            (MechSwarmTarget(target) > -1) &&
01286                                            (altTarget = getMech(MechSwarmTarget(target)))) {
01287 
01288                                                 baseToHit =
01289                                                         FindNormalBTH(mech, mech_map, section,
01290                                                                                   critical, weapindx, range,
01291                                                                                   altTarget, indirectFire, &c3Ref);
01292 
01293                                                 if(roll >= baseToHit) {
01294                                                         mech_notify(altTarget, MECHALL,
01295                                                                                 "The shot hits you instead!");
01296                                                         MechLOSBroadcast(altTarget,
01297                                                                                          "manages to get in the way of the shot instead!");
01298                                                         HitTarget(mech, weapindx, section, critical,
01299                                                                           altTarget, mapx, mapy, LOS, type,
01300                                                                           modifier, 1, baseToHit, wGattlingShots,
01301                                                                           tIsSwarmAttack, roll);
01302 
01303                                                         tTryClear = 0;
01304                                                 } else {
01305                                                         if(Elevation(mech_map, MechX(target),
01306                                                                                  MechY(target)) < (MechZ(target) - 2))
01307                                                                 tTryClear = 0;
01308                                                 }
01309                                         }
01310                                 }
01311 
01312                                 if(tTryClear) {
01313                                         int tempDamage =
01314                                                 determineDamageFromHit(mech, section, critical,
01315                                                                                            target, mapx,
01316                                                                                            mapy, weapindx, wGattlingShots,
01317                                                                                            MechWeapons[weapindx].damage,
01318                                                                                            GetPartAmmoMode(mech, section,
01319                                                                                                                            critical),
01320                                                                                            type,
01321                                                                                            modifier, 1);
01322 
01323                                         possibly_ignite_or_clear(mech, weapindx,
01324                                                                                          GetPartAmmoMode(mech, section,
01325                                                                                                                          critical),
01326                                                                                          tempDamage, mapx, mapy, 0);
01327                                 }
01328                         }
01329                 }
01330         }
01331 
01332         /* Recycle the weapon */
01333         SetRecyclePart(mech, section, critical,
01334                                    WEAPON_TICK * MechWeapons[weapindx].vrt);
01335 
01336                 /****************************************
01337         * START: Set the heat after firing
01338         ****************************************/
01339         if(type == HEAT)
01340                 MechWeapHeat(mech) += (float) modifier;
01341 
01342         if(GetPartFireMode(mech, section, critical) & GATTLING_MODE) {
01343                 MechWeapHeat(mech) += wGattlingShots;
01344         } else if(MechWeapons[weapindx].special & RAC) {
01345                 if(GetPartFireMode(mech, section, critical) & RAC_TWOSHOT_MODE)
01346                         wRACHeat = 2;
01347                 else if(GetPartFireMode(mech, section, critical) & RAC_FOURSHOT_MODE)
01348                         wRACHeat = 4;
01349                 else if(GetPartFireMode(mech, section, critical) & RAC_SIXSHOT_MODE)
01350                         wRACHeat = 6;
01351                 else
01352                         wRACHeat = 1;
01353 
01354                 MechWeapHeat(mech) += (float) (MechWeapons[weapindx].heat * wRACHeat);
01355 
01356                 if(type == HEAT)
01357                         MechWeapHeat(mech) += (float) (modifier * wRACHeat);
01358         } else {
01359                 MechWeapHeat(mech) += (float) MechWeapons[weapindx].heat;
01360 
01361                 if(IsEnergy(weapindx))
01362                         MechWeapHeat(mech) +=
01363                                 (float) getCritAddedHeat(mech, section, critical);
01364 
01365                 if((GetPartFireMode(mech, section, critical) & ULTRA_MODE) ||
01366                    (GetPartFireMode(mech, section, critical) & RFAC_MODE)) {
01367 
01368                         if(type == HEAT)
01369                                 MechWeapHeat(mech) += (float) modifier;
01370 
01371                         MechWeapHeat(mech) += (float) MechWeapons[weapindx].heat;
01372                 }
01373         }
01374 
01375                 /****************************************
01376         * END: Set the heat after firing
01377         ****************************************/
01378 
01379         /* Decrement Ammunition */
01380         decrement_ammunition(mech, weapindx, section, critical, ammoLoc,
01381                                                  ammoCrit, ammoLoc1, ammoCrit1, wGattlingShots);
01382 
01383         /* Special for Heavy Gauss Rifles */
01384         if((MechWeapons[weapindx].special & HVYGAUSS) &&
01385            (MechType(mech) == CLASS_MECH)) {
01386                 if(abs(MechSpeed(mech)) > 0.0) {
01387                         mech_notify(mech, MECHALL,
01388                                                 "You realize that moving while firing this weapon may not be a good idea after all.");
01389                         if(MechTons(mech) <= 35)
01390                                 wHGRPSkillMod = 2;
01391                         else if(MechTons(mech) <= 55)
01392                                 wHGRPSkillMod = 1;
01393                         else if(MechTons(mech) <= 75)
01394                                 wHGRPSkillMod = 0;
01395                         else
01396                                 wHGRPSkillMod = -1;
01397                         if(!MadePilotSkillRoll(mech, wHGRPSkillMod)) {
01398                                 mech_notify(mech, MECHALL,
01399                                                         "The weapon's recoil knocks you to the ground!");
01400                                 MechLOSBroadcast(mech,
01401                                                                  tprintf("topples over from the %s's recoil!",
01402                                                                                  &MechWeapons[weapindx].name[3]));
01403                                 MechFalls(mech, 1, 0);
01404                         }
01405                 }
01406         }
01407 }

int FireWeaponNumber ( dbref  player,
MECH mech,
MAP mech_map,
int  weapnum,
int  argc,
char **  args,
int  sight 
)

Definition at line 370 of file mech.combat.c.

References ARCCHECK, ArmorStringFromIndex(), confdata::btech_idf_requires_spotter, CARRYING_CLUB, CLASS_BSUIT, CLASS_MECH, CLASS_MW, CountDestroyedLegs(), CTORSO, DOCHECK0, DOCHECK1, Elevation, FAIL_DESTROYED, Fallen, FaMechRange, find_mech_in_hex(), FindRange(), FindTargetDBREFFromMapNumber(), FindTargetXY(), FindWeaponNumberOnMech_Advanced(), FireSpot(), FireWeapon(), getMech(), GetPartFireMode, HEAT_MODE, HIDDEN, IDF, IsAMS, IsArtillery, IsCoolant, IsMechMounted(), LARM, LLEG, Locking, LOS_NB, LTORSO, MAP::map_height, MAP::map_width, MapCoordToRealCoord(), MapIsUnderground, MapNoFriendlyFire, mech_notify(), MECH_STUNNED, MECHALL, MechCritStatus, MechDugIn, MechFX, MechFY, MechFZ, MechIsQuad, MechLockFire, MechLOSBroadcast(), MechMove, MechNoFriendlyFire, MechPKiller, MechSections, MechSpotter, MechSwarmTarget, MechTarget, MechTargX, MechTargY, MechTargZ, MechTeam, MechType, MechWeapons, MechX, MechY, MoveModeLock, mudconf, MECH::mynum, notify_printf(), NUM_BSUIT_MEMBERS, PartTempNuke, RARM, RLEG, RTORSO, SectHasBusyWeap(), SectIsDestroyed, weapon_struct::special, specials, StealthArmorActive, StopHiding, tprintf(), TURRET, and ZSCALE.

Referenced by firetic_sub_func(), mech_fireweapon(), and mech_sight().

00374 {
00375         int weaptype;
00376         dbref target;
00377         char targetID[2];
00378         int mapx = 0, mapy = 0, LOS = 0;
00379         MECH *tempMech = NULL;
00380         int section, critical;
00381         float range = 0;
00382         float enemyX, enemyY, enemyZ;
00383         int ishex = 0;
00384         int wcDeadLegs = 0;
00385         char location[20];
00386         int mode;
00387         int i;
00388 
00389         if(MechType(mech) == CLASS_BSUIT) {
00390                 for(i = 0; i < NUM_BSUIT_MEMBERS; i++) {
00391                         DOCHECK1(!SectIsDestroyed(mech, i) &&
00392                                          MechSections(mech)[i].recycle,
00393                                          tprintf("Suit %d is still recovering from attack.",
00394                                                          i + 1));
00395                 }
00396         }
00397 
00398         /* If they fire their weapon while hidden, they should appear */
00399         if(!sight && (MechCritStatus(mech) & HIDDEN)) {
00400                 mech_notify(mech, MECHALL,
00401                                         "You break out of your cover to initiate weapons fire!");
00402                 MechLOSBroadcast(mech,
00403                                                  "breaks out of its cover and begins firing rabidly!");
00404                 MechCritStatus(mech) &= ~HIDDEN;
00405         }
00406 
00407         /* If they fire a weapon while trying to hide stop them from hiding */
00408         if(!sight) {
00409                 StopHiding(mech);
00410         }
00411 #ifdef BT_MOVEMENT_MODES
00412         DOCHECK0(MoveModeLock(mech),
00413                          "You cannot fire while using a special movement mode.");
00414 #endif
00415         DOCHECK0(MechSpotter(mech) > 0
00416                          && MechSpotter(mech) == mech->mynum,
00417                          "You cannot fire while spotting.");
00418         DOCHECK0(weapnum < 0,
00419                          "The weapons system chirps: 'Illegal Weapon Number!'");
00420 
00421         weaptype =
00422                 FindWeaponNumberOnMech_Advanced(mech, weapnum, &section, &critical,
00423                                                                                 sight);
00424 
00425         DOCHECK0(weaptype == -1,
00426                          "The weapons system chirps: 'Illegal Weapon Number!'");
00427 
00428         mode = GetPartFireMode(mech, section, critical);
00429 
00430         if(!sight) {
00431 
00432                 /* Exile Stun Code Check */
00433                 DOCHECK0((MechCritStatus(mech) & MECH_STUNNED),
00434                                  "You cannot take actions while stunned! That includes finding the trigger.");
00435 
00436                 DOCHECK0(PartTempNuke(mech, section, critical),
00437                                  "The weapons system chirps: 'That weapon is still unusable - please stand by.'");
00438                 DOCHECK0(weaptype == -3,
00439                                  "The weapons system chirps: 'That weapon is still reloading!'");
00440                 DOCHECK0(weaptype == -4,
00441                                  "The weapons system chirps: 'That weapon is still recharging!'");
00442 
00443                 /* New fancy message for when they try and fire a weapon and the section
00444                  * is busy */
00445                 if(weaptype == -5) {
00446 
00447                         /* Get the section name and print the message */
00448                         ArmorStringFromIndex(section, location, MechType(mech),
00449                                                                  MechMove(mech));
00450                         notify_printf(player, "%s%s is still recovering from a "
00451                                                   "previous action!",
00452                                                   MechType(mech) == CLASS_BSUIT ? "" : "Your ",
00453                                                   location);
00454                         return 0;
00455                 }
00456 
00457                 DOCHECK0(MechSections(mech)[section].specials & CARRYING_CLUB,
00458                                  "You're carrying a club in that arm.");
00459 
00460                 if(Fallen(mech) && MechType(mech) == CLASS_MECH) {
00461 
00462                         /* if a quad has 3 of 4 legs dead, it can't fire at all while prone */
00463                         wcDeadLegs = CountDestroyedLegs(mech);
00464                         if(MechIsQuad(mech))
00465                                 DOCHECK0(wcDeadLegs > 2,
00466                                                  "Quads need at least 3 legs to fire while prone.");
00467 
00468                         /* quads with all 4 legs can fire all weapons while prone. They do not need to prop. */
00469                         if(!MechIsQuad(mech) || (MechIsQuad(mech) && wcDeadLegs > 0)) {
00470                                 DOCHECK0(section == RLEG || section == LLEG,
00471                                                  "You cannot fire leg mounted weapons when prone.");
00472                                 switch (section) {
00473                                 case RARM:
00474                                         DOCHECK0(SectHasBusyWeap(mech, LARM) ||
00475                                                          MechSections(mech)[LARM].recycle ||
00476                                                          SectIsDestroyed(mech, LARM),
00477                                                          "You currently can't use your Left Arm to prop yourself up.");
00478                                         break;
00479                                 case LARM:
00480                                         DOCHECK0(SectHasBusyWeap(mech, RARM) ||
00481                                                          MechSections(mech)[RARM].recycle ||
00482                                                          SectIsDestroyed(mech, RARM),
00483                                                          "Your currently can't use your Right Arm to prop yourself up.");
00484                                         break;
00485                                 default:
00486                                         DOCHECK0((SectHasBusyWeap(mech, RARM) ||
00487                                                           MechSections(mech)[RARM].recycle ||
00488                                                           SectIsDestroyed(mech, RARM))
00489                                                          && (SectHasBusyWeap(mech, LARM) ||
00490                                                                  MechSections(mech)[LARM].recycle ||
00491                                                                  SectIsDestroyed(mech, LARM)),
00492                                                          "You currently don't have any arms to spare to prop yourself up.");
00493                                 }
00494                         }
00495                 }
00496         }
00497 
00498         if(IsMechMounted(mech)) {
00499                 DOCHECK0(((section == CTORSO) || (section == RTORSO) ||
00500                                   (section == LTORSO)),
00501                                  "You cannot fire torso-mounted weapons while you have battlesuits on you!");
00502         }
00503 
00504         DOCHECK0((MechDugIn(mech)) && section != TURRET,
00505                          "Only turret weapons are available while in cover.");
00506         DOCHECK0(weaptype == -2 ||
00507                          (PartTempNuke(mech, section, critical) == FAIL_DESTROYED),
00508                          "The weapons system chirps: 'That weapon has been destroyed!'");
00509         DOCHECK0(IsAMS(weaptype), "That weapon is defensive only!");
00510         DOCHECK0(argc > 3, "Invalid number of arguments!");
00511 
00512         if((MechWeapons[weaptype].special & IDF) && MechSpotter(mech) != -1 &&
00513            MechTarget(mech) == -1 && MechTargY(mech) == -1 &&
00514            MechTargX(mech) == -1)
00515                 if(FireSpot(player, mech, mech_map, weapnum, weaptype, sight,
00516                                         section, critical))
00517                         return 1;
00518 
00519         switch (argc) {
00520 
00521                 /* Fire at default target */
00522         case 1:
00523 
00524                 /* If its a coolant gun in heat mode we should shot our mech */
00525                 if(IsCoolant(weaptype) && (mode & HEAT_MODE)) {
00526 
00527                         /* Setting our mech as the target and the other parameters
00528                          * as well */
00529                         tempMech = mech;
00530                         DOCHECK0(!tempMech, "Error in FireWeaponNumber routine");
00531                         mapx = MechX(tempMech);
00532                         mapy = MechY(tempMech);
00533                         range = 0.2;
00534                         LOS = 1;
00535 
00536                 } else {
00537 
00538                         DOCHECK0(!FindTargetXY(mech, &enemyX, &enemyY, &enemyZ),
00539                                          "You do not have a default target set!");
00540 
00541                         if(MechTarget(mech) != -1) {
00542 
00543                                 tempMech = getMech(MechTarget(mech));
00544                                 DOCHECK0(!tempMech, "Error in FireWeaponNumber routine");
00545                                 mapx = MechX(tempMech);
00546                                 mapy = MechY(tempMech);
00547                                 range = FaMechRange(mech, tempMech);
00548                                 LOS = LOS_NB(mech, tempMech, mapx, mapy, range);
00549 
00550                                 if(!(MechWeapons[weaptype].special & IDF)) {
00551                                         DOCHECK0(!LOS,
00552                                                          "That target is not in your line of sight!");
00553                                 } else if(MapIsUnderground(mech_map)) {
00554                                         DOCHECK0(!LOS,
00555                                                          "That target is not in your direct line of sight, and "
00556                                                          "you cannot fire your IDF weapons underground!");
00557                                 }
00558                                 if(mudconf.btech_idf_requires_spotter
00559                                    && (MechWeapons[weaptype].special & IDF)
00560                                    && (MechSpotter(mech) == -1))
00561                                         DOCHECK0(!LOS,
00562                                                          "That target is not in your direct line of sight"
00563                                                          " and you do not have a spotter set!!");
00564                         } else {
00565 
00566                                 /* default target is a hex */
00567                                 ishex = 1;
00568                                 if(!sight && !IsArtillery(weaptype) && MechLockFire(mech)) {
00569 
00570                                         /* look for enemies in the default hex cause they may have moved */
00571                                         if((tempMech =
00572                                                 find_mech_in_hex(mech, mech_map, MechTargX(mech),
00573                                                                                  MechTargY(mech), 0))) {
00574 
00575                                                 enemyX = MechFX(tempMech);
00576                                                 enemyY = MechFY(tempMech);
00577                                                 enemyZ = MechFZ(tempMech);
00578                                                 mapx = MechX(tempMech);
00579                                                 mapy = MechY(tempMech);
00580                                         }
00581 
00582                                 }
00583 
00584                                 if(!tempMech) {
00585                                         mapx = MechTargX(mech);
00586                                         mapy = MechTargY(mech);
00587                                         MechTargZ(mech) = Elevation(mech_map, mapx, mapy);
00588                                         enemyZ = ZSCALE * MechTargZ(mech);
00589                                         MapCoordToRealCoord(mapx, mapy, &enemyX, &enemyY);
00590                                 }
00591 
00592                                 /* don't check LOS for missile weapons firing at hex number */
00593                                 range =
00594                                         FindRange(MechFX(mech), MechFY(mech), MechFZ(mech),
00595                                                           enemyX, enemyY, enemyZ);
00596                                 LOS = LOS_NB(mech, tempMech, mapx, mapy, range);
00597 
00598                                 /* Check for Spotter here */
00599                                 if(mudconf.btech_idf_requires_spotter &&
00600                                    (MechWeapons[weaptype].special & IDF)
00601                                    && (MechSpotter(mech) == -1))
00602                                         DOCHECK0(!LOS,
00603                                                          "That hex target is not in your direct line of sight"
00604                                                          " and you do not have a spotter set!!");
00605 
00606                                 if(!
00607                                    (IsArtillery(weaptype)
00608                                         || (MechWeapons[weaptype].special & IDF))) {
00609                                         DOCHECK0(!LOS,
00610                                                          "That hex target is not in your line of sight!");
00611                                 } else if(MapIsUnderground(mech_map)) {
00612                                         DOCHECK0(!LOS,
00613                                                          "That target is not in your direct line of sight, and "
00614                                                          "you cannot fire your IDF weapons underground!");
00615                                 }
00616                         }
00617 
00618                         if(MechType(mech) != CLASS_BSUIT) {
00619                                 ARCCHECK(mech, enemyX, enemyY, section, critical,
00620                                                  "Default target is not in your weapons arc!");
00621                         }
00622                 }
00623                 break;
00624 
00625         case 2:
00626                 /* Fire at the numbered target */
00627                 targetID[0] = args[1][0];
00628                 targetID[1] = args[1][1];
00629                 target = FindTargetDBREFFromMapNumber(mech, targetID);
00630                 DOCHECK0(target == -1, "That target is not in your line of sight!");
00631                 tempMech = getMech(target);
00632                 DOCHECK0(!tempMech, "Error in FireWeaponNumber routine!");
00633                 enemyX = MechFX(tempMech);
00634                 enemyY = MechFY(tempMech);
00635                 enemyZ = MechFZ(tempMech);
00636                 mapx = MechX(tempMech);
00637                 mapy = MechY(tempMech);
00638 
00639                 range = FindRange(MechFX(mech), MechFY(mech), MechFZ(mech), enemyX,
00640                                                   enemyY, enemyZ);
00641                 LOS = LOS_NB(mech, tempMech, MechX(tempMech), MechY(tempMech), range);
00642 
00643                 DOCHECK0(!LOS, "That target is not in your line of sight!");
00644 
00645                 if(MechType(mech) != CLASS_BSUIT) {
00646                         ARCCHECK(mech, enemyX, enemyY, section, critical,
00647                                          "That target is not in your weapons arc!");
00648                 }
00649                 break;
00650 
00651         case 3:
00652 
00653                 /* Fire at the Map X Y */
00654                 mapx = atoi(args[1]);
00655                 mapy = atoi(args[2]);
00656                 ishex = 1;
00657                 DOCHECK0(mapx < 0 || mapx >= mech_map->map_width || mapy < 0 ||
00658                                  mapy >= mech_map->map_height,
00659                                  "Map coordinates out of range!");
00660 
00661                 if(!sight && !IsArtillery(weaptype))
00662 
00663                         /* look for enemies in that hex... */
00664                         if((tempMech = find_mech_in_hex(mech, mech_map, MechTargX(mech),
00665                                                                                         MechTargY(mech), 0))) {
00666                                 enemyX = MechFX(tempMech);
00667                                 enemyY = MechFY(tempMech);
00668                                 enemyZ = MechFZ(tempMech);
00669                         }
00670 
00671                 if(!tempMech) {
00672                         MapCoordToRealCoord(mapx, mapy, &enemyX, &enemyY);
00673                         MechTargZ(mech) = Elevation(mech_map, mapx, mapy);
00674                         enemyZ = ZSCALE * MechTargZ(mech);
00675                 }
00676 
00677                 if(MechType(mech) != CLASS_BSUIT) {
00678                         ARCCHECK(mech, enemyX, enemyY, section, critical,
00679                                          "That hex target is not in your weapons arc!");
00680                 }
00681 
00682                 /* Don't check LOS for missile weapons */
00683                 range = FindRange(MechFX(mech), MechFY(mech), MechFZ(mech), enemyX,
00684                                                   enemyY, enemyZ);
00685                 LOS = LOS_NB(mech, tempMech, mapx, mapy, range);
00686 
00687                 if(!IsArtillery(weaptype))
00688                         DOCHECK0(!LOS, "That hex target is not in your line of sight!");
00689         }
00690 
00691     if(tempMech) {
00692         DOCHECK0(IsArtillery(weaptype),
00693                 "You can only target hexes with this kind of artillery.");
00694         DOCHECK0(MechSwarmTarget(tempMech) == mech->mynum,
00695                 "You are unable to use your weapons against a 'swarmer!");
00696         DOCHECK0(StealthArmorActive(tempMech) &&
00697                 ((MechTarget(mech) != tempMech->mynum) || Locking(mech)),
00698                 "You need a stable lock to fire on that target!");
00699         DOCHECK0(!IsCoolant(weaptype) && MechTeam(tempMech) == MechTeam(mech)
00700                 && MechNoFriendlyFire(mech),
00701                 "You can't fire on a teammate with FFSafeties on!");
00702         DOCHECK0(!IsCoolant(weaptype) && MechTeam(tempMech) == MechTeam(mech)
00703                 && MapNoFriendlyFire(mech_map),
00704                 "Friendly Fire? I don't think so...");
00705         DOCHECK0(MechType(tempMech) == CLASS_MW && MechType(mech) != CLASS_MW
00706                 && !MechPKiller(mech),
00707                 "That's a living, breathing person! Switch off the safety first, "
00708                 "if you really want to assassinate the target.");
00709     }
00710 
00711         FireWeapon(mech, mech_map, tempMech, LOS, weaptype, weapnum, section,
00712                            critical, enemyX, enemyY, mapx, mapy, range, 1000, sight,
00713                            ishex);
00714         return (1);
00715 }

void hex_hit ( MECH mech,
int  x,
int  y,
int  weapindx,
int  ammoMode,
int  damage,
int  ishit 
)

Definition at line 1964 of file mech.combat.c.

References hit_building(), LOCK_BUILDING, LOCK_HEX, LOCK_HEX_CLR, LOCK_HEX_IGN, MechStatus, possibly_blow_bridge(), possibly_blow_ice(), and possibly_ignite_or_clear().

Referenced by HitTarget(), Missile_Hit(), and MissileHitTarget().

01966 {
01967         if(!(MechStatus(mech) & (LOCK_BUILDING | LOCK_HEX | LOCK_HEX_IGN |
01968                                                          LOCK_HEX_CLR)))
01969                 return;
01970 
01971         /* Ok.. we either try to clear/ignite the hex, or alternatively we try to hit building in it */
01972         if(MechStatus(mech) & LOCK_BUILDING) {
01973                 if(ishit > 0)
01974                         hit_building(mech, x, y, weapindx, damage);
01975         } else {
01976                 possibly_ignite_or_clear(mech, weapindx, ammoMode, damage, x, y, 1);
01977 
01978                 if(MechStatus(mech) & LOCK_HEX) {
01979                         possibly_blow_ice(mech, weapindx, x, y);
01980                         possibly_blow_bridge(mech, weapindx, x, y);
01981                 }
01982         }
01983 }

char* hex_target_id ( MECH mech  ) 

Definition at line 1786 of file mech.combat.c.

References LOCK_BUILDING, LOCK_HEX, LOCK_HEX_CLR, LOCK_HEX_IGN, and MechStatus.

Referenced by FireWeapon().

01787 {
01788         if(MechStatus(mech) & LOCK_HEX_IGN)
01789                 return "at the hex, trying to ignite it";
01790         if(MechStatus(mech) & LOCK_HEX_CLR)
01791                 return "at the hex, trying to clear it";
01792         if(MechStatus(mech) & LOCK_HEX)
01793                 return "at the hex";
01794         if(MechStatus(mech) & LOCK_BUILDING)
01795                 return "at the building at";
01796         return "at";
01797 }

void HitTarget ( MECH mech,
int  weapindx,
int  wSection,
int  wCritSlot,
MECH hitMech,
int  hitX,
int  hitY,
int  LOS,
int  type,
int  modifier,
int  reallyhit,
int  bth,
int  wGattlingShots,
int  tIsSwarmAttack,
int  player_roll 
)

Definition at line 1523 of file mech.combat.c.

References confdata::btech_glancing_blows, CLASS_MW, Clustersize, CRAZY_MISSILES, weapon_struct::damage, DamageMech(), determineDamageFromHit(), FindAimHitLoc(), FindTargetHitLoc(), FindTCHitLoc(), GetPartAmmoMode, GetPartFireMode, GunPilot, HEAT_MODE, hex_hit(), Immobile, IsArtillery, IsCoolant, IsFlamer, IsMissile, missile_hit_table_struct::key, LBX_MODE, mech_notify(), mech_printf(), MechAim, MechAimType, MECHALL, MechCritStatus, MechLOSBroadcast(), MechType, MechWeapHeat, MechWeapons, Missile_Hit(), MissileHitIndex(), MissileHitTable, MissileHitTarget(), mudconf, missile_hit_table_struct::num_missiles, NUM_SECTIONS, ON_TC, pc_to_dam_conversion(), RAC_MODES, Roll(), SWARM1_MODE, SWARM_MODE, SwarmHitTarget(), and TC_DESTROYED.

01535 {
01536         int isrear = 0, iscritical = 0;
01537         int hitloc = 0;
01538         int loop;
01539         int roll;
01540         int aim_hit = 0;
01541         int wBaseWeapDamage = MechWeapons[weapindx].damage;
01542         int wWeapDamage = 0;
01543         int num_missiles_hit;
01544         int wFireMode = GetPartFireMode(mech, wSection, wCritSlot);
01545         int wAmmoMode = GetPartAmmoMode(mech, wSection, wCritSlot);
01546         int tIsUltra = ((wFireMode & ULTRA_MODE) || (wFireMode & RFAC_MODE));
01547         int tIsRAC = (wFireMode & RAC_MODES);
01548         int tIsLBX = (wAmmoMode & LBX_MODE);
01549         int tIsSwarm = ((wAmmoMode & SWARM_MODE) || (wAmmoMode & SWARM1_MODE));
01550         char strMissileFakeName[30];
01551         int tFoundRACFake = 0;
01552         int tUsingTC = ((wFireMode & ON_TC) && !IsArtillery(weapindx) &&
01553                                         !IsMissile(weapindx) &&
01554                                         (!(MechCritStatus(mech) & TC_DESTROYED)) &&
01555                                         ((MechAim(mech) != NUM_SECTIONS) && hitMech &&
01556                                          (MechAimType(mech) == MechType(hitMech))));
01557         int missileindex = 0;
01558 
01559         if(hitMech) {
01560 
01561                 /* Check to see if we're aiming at a particular location. Swarm attacks can't aim. */
01562                 if((MechAim(mech) != NUM_SECTIONS) && hitMech && Immobile(hitMech)
01563                    && !tIsSwarmAttack) {
01564 
01565                         roll = Roll();
01566 
01567                         if(roll == 6 || roll == 7 || roll == 8)
01568                                 aim_hit = 1;
01569                 }
01570 
01571         }
01572 
01573         if(!IsMissile(weapindx)) {
01574                 wWeapDamage =
01575                         determineDamageFromHit(mech, wSection, wCritSlot, hitMech, hitX,
01576                                                                    hitY, weapindx, wGattlingShots,
01577                                                                    wBaseWeapDamage, wAmmoMode, type, modifier,
01578                                                                    0);
01579 
01580                 /* Check if it is a glancing blow, if so, make an emit */
01581                 if((mudconf.btech_glancing_blows) && (player_roll == bth) && hitMech) {
01582                         /* Yes, even though we have two different glance modes, the above is correct
01583                          * because we modified the bth in FireWeapon. Nothing to see here. move along
01584                          */
01585                         MechLOSBroadcast(hitMech, "is nicked by a glancing blow!");
01586                         mech_notify(hitMech, MECHALL, 
01587                                         "You are nicked by a glancing blow!");
01588                         wWeapDamage = (int ) (wWeapDamage +1) / 2 ;
01589                         if(wWeapDamage < 1 )
01590                                 wWeapDamage = 1; /* very rare case */
01591                 }
01592         }
01593 
01594         /*
01595          * Ok, if we're not an artillery weapon or missile and we're not in
01596          * LBX, RAC, Ultra or RFAC mode...
01597          */
01598         if(!IsArtillery(weapindx) && !IsMissile(weapindx) && !tIsUltra &&
01599            !tIsLBX && !tIsRAC) {
01600 
01601                 if(hitMech) {
01602 
01603                         /* Flamers - if in heat mode don't do damage */
01604                         if((IsFlamer(weapindx)) && (wFireMode & HEAT_MODE)) {
01605 
01606                                 mech_notify(hitMech, MECHALL,
01607                                                         "%cy%chThe flaming plasma sprays all over you!%cn");
01608                                 mech_notify(mech, MECHALL,
01609                                                         "%cgYou cover your target in flaming plasma!%cn");
01610                                 MechWeapHeat(hitMech) += (float) wBaseWeapDamage;
01611                                 return;
01612 
01613                         } else if((IsCoolant(weapindx))
01614                                           && (MechType(hitMech) != CLASS_MW)) {
01615 
01616                                 /* Its a Coolant Gun */
01617                                 /* So now we figure out if we want to hit our unit with it
01618                                  * or a target */
01619 
01620                                 if(wFireMode & HEAT_MODE) {
01621 
01622                                         /* Hit our own unit with the coolant gun */
01623                                         mech_notify(mech, MECHALL,
01624                                                                 "%ccCoolant washes over your systems!!%c");
01625                                         MechWeapHeat(mech) -= (float) wBaseWeapDamage;
01626 
01627                                 } else {
01628 
01629                                         /* Hit the target with the coolant gun */
01630                                         mech_notify(mech, MECHALL,
01631                                                                 "%ccYou hit with the stream of coolant!!%c");
01632                                         mech_notify(hitMech, MECHALL,
01633                                                                 "%ccCoolant washes over your systems!!%c");
01634                                         MechWeapHeat(hitMech) -= (float) wBaseWeapDamage;
01635 
01636                                 }
01637 
01638                                 /* Never does damage so return */
01639                                 return;
01640 
01641                         }
01642 
01643                         if(aim_hit)
01644                                 hitloc = FindAimHitLoc(mech, hitMech, &isrear, &iscritical);
01645                         else if(tUsingTC)
01646                                 hitloc = FindTCHitLoc(mech, hitMech, &isrear, &iscritical);
01647                         else
01648                                 hitloc =
01649                                         FindTargetHitLoc(mech, hitMech, &isrear, &iscritical);
01650 
01651                         DamageMech(hitMech, mech, LOS, GunPilot(mech), hitloc, isrear,
01652                                            iscritical, pc_to_dam_conversion(hitMech, weapindx,
01653                                                                                                                 wWeapDamage), 0,
01654                                            weapindx, bth, weapindx, wAmmoMode, tIsSwarmAttack);
01655 
01656                 } else {
01657                         hex_hit(mech, hitX, hitY, weapindx, wAmmoMode, wWeapDamage, 1);
01658                 }
01659 
01660                 return;
01661         }
01662 
01663         /*
01664          * Since we're here, we're either
01665          *      - A missile weapon
01666          *      - An artillery weapon
01667          *      - An AC in Ultra, RF or LBX mode
01668          *      - A RAC in RAC mode
01669          */
01670 
01671         /*
01672          * Do special case for RACs since they don't have an entry in the MissileHitTable.
01673          *
01674          * We're gonna fake it by pretending we're either an SRM-2, SRM-4 or SRM-6, depending
01675          * upon the mode
01676          */
01677         if(tIsRAC) {
01678                 if(GetPartFireMode(mech, wSection, wCritSlot) & RAC_TWOSHOT_MODE)
01679                         strcpy(strMissileFakeName, "IS.SRM-2");
01680                 else if(GetPartFireMode(mech, wSection,
01681                                                                 wCritSlot) & RAC_FOURSHOT_MODE)
01682                         strcpy(strMissileFakeName, "IS.SRM-4");
01683                 else if(GetPartFireMode(mech, wSection, wCritSlot) & RAC_SIXSHOT_MODE)
01684                         strcpy(strMissileFakeName, "IS.SRM-6");
01685                 for(loop = 0; MissileHitTable[loop].key != -1; loop++) {
01686                         if(!strcmp(MissileHitTable[loop].name, strMissileFakeName)) {
01687                                 tFoundRACFake = 1;
01688                                 break;
01689                         }
01690                 }
01691 
01692                 if(!tFoundRACFake)
01693                         return;
01694         } else {
01695                 for(loop = 0; MissileHitTable[loop].key != -1; loop++)
01696                         if(MissileHitTable[loop].key == weapindx)
01697                                 break;
01698                 if(!(MissileHitTable[loop].key == weapindx))
01699                         return;
01700         }
01701 
01702         if(IsMissile(weapindx)) {
01703                 if(player_roll < bth )
01704                 {
01705                         return;
01706                 }
01707                 else
01708 
01709                 if(tIsSwarm && hitMech) /* No swarms on hex hits */
01710                         SwarmHitTarget(mech, weapindx, wSection, wCritSlot, hitMech,
01711                                                    LOS, bth, reallyhit ? bth + 1 : bth - 1,
01712                                                    (type ==
01713                                                         CRAZY_MISSILES) ? MissileHitTable[loop].
01714                                                    num_missiles[10] * modifier /
01715                                                    100 : MissileHitTable[loop].num_missiles[10],
01716                                                    (GetPartAmmoMode(mech, wSection, wCritSlot) &
01717                                                         SWARM1_MODE), tIsSwarmAttack, player_roll);
01718                 else
01719                         MissileHitTarget(mech, weapindx, wSection, wCritSlot, hitMech,
01720                                                          hitX, hitY, LOS ? 1 : 0, bth,
01721                                                          reallyhit ? bth + 1 : bth - 1,
01722                                                          (type ==
01723                                                           CRAZY_MISSILES) ? MissileHitTable[loop].
01724                                                          num_missiles[10] * modifier /
01725                                                          100 : MissileHitTable[loop].num_missiles[10],
01726                                                          tIsSwarmAttack, player_roll);
01727 
01728                 return;
01729         }
01730 
01731         missileindex = MissileHitIndex(mech, hitMech,weapindx, wSection, wCritSlot, (mudconf.btech_glancing_blows) && (player_roll == bth) ? 1: 0);
01732         /* This is how we'll handle glancing. Any roll < 2 is considering just one missile hit, full damage */
01733         if (missileindex == -1)
01734                 num_missiles_hit = 1;
01735         else
01736                 num_missiles_hit = MissileHitTable[loop].num_missiles[missileindex];
01737 
01738         /*
01739          * Check for non-missile, multiple hit weapons, like LBXs, RACs, RFACs and Ultras
01740          */
01741         if(LOS)
01742                 mech_printf(mech, MECHALL,
01743                                         "%%cgYou hit with %d %s%s!%%c",
01744                                         num_missiles_hit, (tIsUltra ||
01745                                                                            tIsRAC ? "slug" : tIsLBX ? "pellet" :
01746                                                                            "missile"),
01747                                         (num_missiles_hit > 1 ? "s" : ""));
01748 
01749         if(tIsLBX)
01750                 Missile_Hit(mech, hitMech, hitX, hitY, isrear, iscritical,
01751                                         weapindx, wFireMode, wAmmoMode, num_missiles_hit,
01752                                         tIsLBX ? 1 : wWeapDamage, Clustersize(weapindx), LOS, bth,
01753                                         tIsSwarmAttack);
01754         else {
01755                 while (num_missiles_hit) {
01756                         if(hitMech) {
01757                                 if(aim_hit)
01758                                         hitloc =
01759                                                 FindAimHitLoc(mech, hitMech, &isrear, &iscritical);
01760                                 if(tUsingTC)
01761                                         hitloc =
01762                                                 FindTCHitLoc(mech, hitMech, &isrear, &iscritical);
01763                                 else
01764                                         hitloc =
01765                                                 FindTargetHitLoc(mech, hitMech, &isrear, &iscritical);
01766                                 DamageMech(hitMech, mech, LOS, GunPilot(mech), hitloc,
01767                                                    isrear, iscritical, pc_to_dam_conversion(hitMech,
01768                                                                                                                                         weapindx,
01769                                                                                                                                         wWeapDamage),
01770                                                    0, weapindx, bth, weapindx, wAmmoMode,
01771                                                    tIsSwarmAttack);
01772                         } else
01773                                 hex_hit(mech, hitX, hitY, weapindx, wAmmoMode, wWeapDamage,
01774                                                 1);
01775 
01776                         num_missiles_hit--;
01777                 }
01778         }
01779 
01780 }

void mech_fireweapon ( dbref  player,
void *  data,
char *  buffer 
)

Definition at line 341 of file mech.combat.c.

References args, cch, DOCHECK, FireWeaponNumber(), getMap(), MECH::mapindex, mech_parseattributes(), and MECH_USUALO.

Referenced by mech_snipe_func(), and turret_fireweapon().

00342 {
00343         MECH *mech = (MECH *) data;
00344         MAP *mech_map;
00345         char *args[5];
00346         int argc;
00347         int weapnum;
00348 
00349         mech_map = getMap(mech->mapindex);
00350         cch(MECH_USUALO);
00351         argc = mech_parseattributes(buffer, args, 5);
00352         DOCHECK(argc < 1, "Not enough arguments to the function");
00353         weapnum = atoi(args[0]);
00354         FireWeaponNumber(player, mech, mech_map, weapnum, argc, args, 0);
00355 }

void mech_settarget ( dbref  player,
void *  data,
char *  buffer 
)

Definition at line 181 of file mech.combat.c.

References arc_override, args, cch, ClearFireAdjustments(), DOCHECK, Elevation, EVENT_LOCK, FindTargetDBREFFromMapNumber(), FlMechRange, getMap(), getMech(), GetMechToMechID(), InLineOfSight(), LOCK_BUILDING, LOCK_HEX, LOCK_HEX_CLR, LOCK_HEX_IGN, LOCK_TARGET, LOCK_TICK, MECH::mapindex, mech_lock_event(), mech_notify(), mech_parseattributes(), mech_printf(), MECH_USUALO, MECHALL, MECHEVENT, MechFireAdjustment, MechSpotter, MechStatus, MechSwarmTarget, MechTarget, MechTargX, MechTargY, MechTargZ, MechX, MechY, MECH::mynum, MAP::mynum, notify, notify_printf(), sixth_sense_check(), StopLock, and ValidCoord.

Referenced by mech_snipe_func(), and turret_settarget().

00182 {
00183         MECH *mech = (MECH *) data, *target;
00184         MAP *mech_map;
00185         char *args[5];
00186         char targetID[2];
00187         int argc;
00188         int LOS = 1;
00189         int newx, newy;
00190         dbref targetref;
00191         int mode;
00192 
00193         cch(MECH_USUALO);
00194 
00195         argc = mech_parseattributes(buffer, args, 5);
00196         switch (argc) {
00197         case 1:
00198                 mech_map = getMap(mech->mapindex);
00199                 if(args[0][0] == '-') {
00200                         MechTarget(mech) = -1;
00201                         MechTargX(mech) = -1;
00202                         MechTargY(mech) = -1;
00203                         mech_notify(mech, MECHALL, "All locks cleared.");
00204                         StopLock(mech);
00205                         if(MechSpotter(mech) == mech->mynum)
00206                                 ClearFireAdjustments(mech_map, mech->mynum);
00207                         return;
00208                 }
00209                 targetID[0] = args[0][0];
00210                 targetID[1] = args[0][1];
00211                 targetref = FindTargetDBREFFromMapNumber(mech, targetID);
00212                 target = getMech(targetref);
00213                 if(target)
00214                         LOS =
00215                                 InLineOfSight(mech, target, MechX(target), MechY(target),
00216                                                           FlMechRange(mech_map, mech, target));
00217                 else
00218                         targetref = -1;
00219                 DOCHECK(targetref == -1 ||
00220                                 !LOS, "That is not a valid targetID. Try again.");
00221 
00222                 if(MechSwarmTarget(mech) > 0) {
00223                         if(MechSwarmTarget(mech) != target->mynum) {
00224                                 mech_notify(mech, MECHALL,
00225                                                         "You're a bit too busy holding on for dear life to lock a target!");
00226                                 return;
00227                         }
00228                 }
00229 
00230                 mech_printf(mech, MECHALL, "Target set to %s.",
00231                                         GetMechToMechID(mech, target));
00232                 StopLock(mech);
00233                 MechTarget(mech) = targetref;
00234                 MechStatus(mech) |= LOCK_TARGET;
00235                 sixth_sense_check(mech, target);
00236 #if LOCK_TICK > 0
00237                 if(!arc_override)
00238                         MECHEVENT(mech, EVENT_LOCK, mech_lock_event, LOCK_TICK, 0);
00239 #endif
00240                 break;
00241         case 2:
00242                 /* Targetted a square */
00243                 if(MechSwarmTarget(mech) > 0) {
00244                         mech_notify(mech, MECHALL,
00245                                                 "You're a bit too busy holding on for dear life to lock a target!");
00246                         return;
00247                 }
00248 
00249                 mech_map = getMap(mech->mapindex);
00250                 newx = atoi(args[0]);
00251                 newy = atoi(args[1]);
00252                 ValidCoord(mech_map, newx, newy);
00253                 MechTarget(mech) = -1;
00254                 MechTargX(mech) = newx;
00255                 MechTargY(mech) = newy;
00256                 MechFireAdjustment(mech) = 0;
00257                 if(MechSpotter(mech) == mech->mynum)
00258                         ClearFireAdjustments(mech_map, mech->mynum);
00259                 MechTargZ(mech) = Elevation(mech_map, newx, newy);
00260                 notify_printf(player, "Target coordinates set at (X,Y) %d, %d",
00261                                           newx, newy);
00262                 StopLock(mech);
00263                 MechStatus(mech) |= LOCK_TARGET;
00264 #if LOCK_TICK > 0
00265                 if(!arc_override)
00266                         MECHEVENT(mech, EVENT_LOCK, mech_lock_event, LOCK_TICK, 0);
00267 #endif
00268                 break;
00269         case 3:
00270                 /* Targetted a square w/ special mode (hex / building) */
00271                 if(MechSwarmTarget(mech) > 0) {
00272                         mech_notify(mech, MECHALL,
00273                                                 "You're a bit too busy holding on for dear life to lock a target!");
00274                         return;
00275                 }
00276 
00277                 DOCHECK(strlen(args[2]) > 1, "Invalid lock mode!");
00278                 switch (toupper(args[2][0])) {
00279                 case 'B':
00280                         mode = LOCK_BUILDING;
00281                         break;
00282                 case 'I':
00283                         mode = LOCK_HEX_IGN;
00284                         break;
00285                 case 'C':
00286                         mode = LOCK_HEX_CLR;
00287                         break;
00288                 case 'H':
00289                         mode = LOCK_HEX;
00290                         break;
00291                 default:
00292                         notify(player, "Invalid mode selected!");
00293                         return;
00294                 }
00295                 mech_map = getMap(mech->mapindex);
00296                 newx = atoi(args[0]);
00297                 newy = atoi(args[1]);
00298                 ValidCoord(mech_map, newx, newy);
00299                 MechTarget(mech) = -1;
00300                 MechTargX(mech) = newx;
00301                 MechTargY(mech) = newy;
00302                 MechFireAdjustment(mech) = 0;
00303                 if(MechSpotter(mech) == mech->mynum)
00304                         ClearFireAdjustments(mech_map, mech->mynum);
00305                 MechTargZ(mech) = Elevation(mech_map, newx, newy);
00306                 switch (mode) {
00307                 case LOCK_HEX:
00308                         notify_printf(player,
00309                                                   "Target coordinates set to hex at (X,Y) %d, %d",
00310                                                   newx, newy);
00311                         break;
00312                 case LOCK_HEX_CLR:
00313                         notify_printf(player,
00314                                                   "Target coordinates set to clearing hex at (X,Y) %d, %d",
00315                                                   newx, newy);
00316                         break;
00317                 case LOCK_HEX_IGN:
00318                         notify_printf(player,
00319                                                   "Target coordinates set to igniting hex at (X,Y) %d, %d",
00320                                                   newx, newy);
00321                         break;
00322                 default:
00323                         notify_printf(player,
00324                                                   "Target coordinates set to building at (X,Y) %d, %d",
00325                                                   newx, newy);
00326                         break;
00327                 }
00328 
00329                 StopLock(mech);
00330                 MechStatus(mech) |= mode;
00331 #if LOCK_TICK > 0
00332                 if(!arc_override)
00333                         MECHEVENT(mech, EVENT_LOCK, mech_lock_event, LOCK_TICK, 0);
00334 #endif
00335         }
00336 }

static void mech_ss_event ( MUXEVENT ev  )  [static]

Definition at line 152 of file mech.combat.c.

References BOUNDED(), my_event_type::data, my_event_type::data2, mech_notify(), MECHPILOT, RGotPilot, ss_messages, and Uncon.

Referenced by sixth_sense_check().

00153 {
00154         MECH *mech = (MECH *) ev->data;
00155         int i = (int) ev->data2;
00156 
00157         if(Uncon(mech))
00158                 return;
00159         if(!RGotPilot(mech))
00160                 return;
00161         mech_notify(mech, MECHPILOT, ss_messages[BOUNDED(0, i, 8)]);
00162 }

void mech_target ( dbref  player,
void *  data,
char *  buffer 
)

Definition at line 95 of file mech.combat.c.

References args, ArmorSectionFromString(), ArmorStringFromIndex(), cch, DOCHECK, FindObjectsData(), mech_parseattributes(), MECH_USUALO, MechAim, MechAimType, MechMove, MechTarget, MechType, notify, notify_printf(), and NUM_SECTIONS.

00096 {
00097         MECH *mech = (MECH *) data;
00098         MECH *target;
00099         char *args[5];
00100         int argc;
00101         char section[50];
00102         char type, move, index;
00103 
00104         cch(MECH_USUALO);
00105         argc = mech_parseattributes(buffer, args, 5);
00106         DOCHECK(argc != 1, "Invalid number of arguments to function!");
00107         if(!strcmp(args[0], "-")) {
00108                 MechAim(mech) = NUM_SECTIONS;
00109                 notify(player, "Targetting disabled.");
00110                 return;
00111         }
00112         DOCHECK(MechTarget(mech) < 0 ||
00113                         !(target =
00114                           FindObjectsData(MechTarget(mech))),
00115                         "Error: You need to be locked onto something to target its part!");
00116         type = MechType(target);
00117         move = MechMove(target);
00118         DOCHECK((index =
00119                          ArmorSectionFromString(type, move, args[0])) < 0,
00120                         "Invalid location!");
00121         MechAim(mech) = index;
00122         MechAimType(mech) = type;
00123         ArmorStringFromIndex(index, section, type, move);
00124         notify_printf(player, "%s targetted.", section);
00125 }

void possibly_clear ( MECH mech,
MAP map,
int  weapindx,
int  ammoMode,
int  damage,
int  x,
int  y,
int  intentional 
)

Definition at line 1911 of file mech.combat.c.

References canWeaponClear(), clear_hex(), MechWeapons, PCOMBAT, possibly_ignite(), possibly_remove_mines(), and Roll().

Referenced by possibly_ignite_or_clear().

01913 {
01914         int igniteBTH = 5;                      /* This is for intentional clearing */
01915         int igniteRoll = Roll();
01916         int clearRoll = Roll();
01917 
01918         if(MechWeapons[weapindx].special & PCOMBAT)
01919                 return;
01920 
01921         if(!intentional)
01922                 igniteBTH = 3;
01923 
01924         if(igniteRoll <= igniteBTH) {
01925                 possibly_ignite(mech, map, weapindx, ammoMode, x, y, intentional);
01926                 return;
01927         }
01928 
01929         if(!canWeaponClear(weapindx))
01930                 return;
01931 
01932         if(clearRoll > damage)
01933                 return;
01934 
01935         clear_hex(mech, x, y, intentional);
01936         possibly_remove_mines(mech, x, y);
01937 }

void possibly_ignite ( MECH mech,
MAP map,
int  weapindx,
int  ammoMode,
int  x,
int  y,
int  intentional 
)

Definition at line 1881 of file mech.combat.c.

References AC_FLECHETTE_MODE, canWeaponIgnite(), fire_hex(), GetTerrain, HEAVY_FOREST, INFERNO_MODE, IsBallistic, IsEnergy, IsMissile, LIGHT_FOREST, MechWeapons, PCOMBAT, and Roll().

Referenced by possibly_clear(), and possibly_ignite_or_clear().

01883 {
01884         char terrain = GetTerrain(map, x, y);
01885         int roll = Roll();
01886         int bth = 13;
01887 
01888         if(MechWeapons[weapindx].special & PCOMBAT)
01889                 return;
01890 
01891         if((terrain != LIGHT_FOREST) && (terrain != HEAVY_FOREST))
01892                 return;
01893 
01894         if(!strcmp(&MechWeapons[weapindx].name[3], "Flamer") ||
01895            !strcmp(&MechWeapons[weapindx].name[3], "HeavyFlamer"))
01896                 bth = 4;
01897         else if(IsMissile(weapindx) && (ammoMode & INFERNO_MODE))
01898                 bth = 5;
01899         else if(IsBallistic(weapindx) && (ammoMode & AC_FLECHETTE_MODE))
01900                 bth = 5;
01901         else if(IsEnergy(weapindx) && canWeaponIgnite(weapindx))
01902                 bth = 5;
01903         else if((IsMissile(weapindx) || IsBallistic(weapindx)) &&
01904                         canWeaponIgnite(weapindx))
01905                 bth = 9;
01906 
01907         if(roll >= bth)
01908                 fire_hex(mech, x, y, intentional);
01909 }

void possibly_ignite_or_clear ( MECH mech,
int  weapindx,
int  ammoMode,
int  damage,
int  x,
int  y,
int  intentional 
)

Definition at line 1939 of file mech.combat.c.

References FindObjectsData(), LOCK_HEX_CLR, LOCK_HEX_IGN, MECH::mapindex, MechStatus, possibly_clear(), possibly_ignite(), and Roll().

Referenced by determineDamageFromHit(), hex_hit(), and Missile_Hit().

01941 {
01942         int r;
01943         MAP *map;
01944 
01945         r = Roll();
01946         map = FindObjectsData(mech->mapindex);
01947 
01948         if(!map)
01949                 return;
01950 
01951         if(MechStatus(mech) & LOCK_HEX_IGN) {
01952                 possibly_ignite(mech, map, weapindx, ammoMode, x, y, 1);
01953                 return;
01954         }
01955 
01956         if(MechStatus(mech) & LOCK_HEX_CLR) {
01957                 possibly_clear(mech, map, weapindx, ammoMode, damage, x, y, 1);
01958                 return;
01959         }
01960 
01961         possibly_clear(mech, map, weapindx, ammoMode, damage, x, y, intentional);
01962 }

void sendC3TrackEmit ( MECH mech,
dbref  c3Ref,
MECH c3Mech 
)

Definition at line 751 of file mech.combat.c.

References A_MECHNAME, mech_printf(), MECHALL, MechIDS(), MECH::mynum, and silly_atr_get().

Referenced by FireWeapon().

00752 {
00753         if(c3Mech && (c3Mech->mynum != mech->mynum)) {
00754                 mech_printf(mech, MECHALL,
00755                                         "Using range data from %s [%s]",
00756                                         silly_atr_get(c3Mech->mynum,
00757                                                                   A_MECHNAME), MechIDS(c3Mech, 1));
00758         }
00759 }

void sixth_sense_check ( MECH mech,
MECH target 
)

Definition at line 164 of file mech.combat.c.

References Destroyed, EVENT_SS, FaMechRange, mech_ss_event(), MECHEVENT, MechIsObservator, MechRTonsV, MechSpecials, Number, Roll(), SS_ABILITY, SSDistMod, and SSTonMod.

Referenced by mech_settarget().

00165 {
00166         float r;
00167         int d;
00168 
00169         if(!(MechSpecials(target) & SS_ABILITY) || MechIsObservator(mech))
00170                 return;
00171         if(Destroyed(target))
00172                 return;
00173         if(Roll() > 8)
00174                 return;
00175         r = FaMechRange(mech, target);
00176         d = (MechRTonsV(mech) - MechRTonsV(target)) / 1024;
00177         MECHEVENT(target, EVENT_SS, mech_ss_event, Number(1, 3),
00178                           ((3 * (SSDistMod(r))) + (SSTonMod(d))));
00179 }

int weapon_failure_stuff ( MECH mech,
int *  weapnum,
int *  weapindx,
int *  section,
int *  critical,
int *  ammoLoc,
int *  ammoCrit,
int *  ammoLoc1,
int *  ammoCrit1,
int *  modifier,
int *  type,
float  range,
int *  range_ok,
int  wGattlingShots 
)

Definition at line 717 of file mech.combat.c.

References CheckWeaponFailed(), decrement_ammunition(), EGunRangeWithCheck, mech_notify(), MECHALL, POWER_SPIKE, RANGE, WEAPON_DUD, and WEAPON_JAMMED.

00729 {
00730         CheckWeaponFailed(mech, *weapnum, *weapindx, *section, *critical,
00731                                           modifier, type);
00732         if(*type == POWER_SPIKE)
00733                 return 1;
00734         if(*type == WEAPON_JAMMED || *type == WEAPON_DUD) {
00735                 /* Just decrement ammunition */
00736                 decrement_ammunition(mech, *weapindx, *section, *critical,
00737                                                          *ammoLoc, *ammoCrit, *ammoLoc1, *ammoCrit1,
00738                                                          wGattlingShots);
00739                 return 1;
00740         }
00741         if(*type == RANGE)
00742                 if((EGunRangeWithCheck(mech, *section,
00743                                                            *weapindx) - *modifier) < range) {
00744                         mech_notify(mech, MECHALL,
00745                                                 "Due to weapons failure your shot falls short of its target!");
00746                         *range_ok = 0;
00747                 }
00748         return 0;
00749 }


Variable Documentation

int arc_override

Definition at line 21 of file ds.turret.c.

dbref pilot_override

Definition at line 22 of file ds.turret.c.

char* ss_messages[]

Initial value:

 {
        "You feel you'll have your hands full before too long..",
        "You have a bad feeling about this..",
        "You feel a homicidal maniac is about to pounce on you!",

        "You think something is amiss..",
        "You have a slightly bad feeling about this..",
        "You think someone thinks ill of you..",

        "Something makes you somewhat feel uneasy..",
        "Something makes you definitely feel uneasy..",
        "Something makes you feel out of your element.."
}

Definition at line 135 of file mech.combat.c.

Referenced by mech_ss_event().


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