src/hcode/btech/p.mech.combat.h File Reference

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void mech_target (dbref player, void *data, char *buffer)
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)
char * hex_target_id (MECH *mech)
int canClearOrIgnite (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)
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 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)


Function Documentation

int canClearOrIgnite ( int  weapindx  ) 

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, MAP::mynum, MECH::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 }

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 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 }


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