src/hcode/btech/mech.damage.c

Go to the documentation of this file.
00001 /*
00002 * Author: Cord Awtry <kipsta@mediaone.net>
00003 *  Copyright (c) 2000-2002 Cord Awtry
00004 *  Copyright (c) 1999-2005 Kevin Stevens
00005 *       All rights reserved
00006 *
00007 * Based on work that was:
00008 *  Copyright (c) 1997 Markus Stenberg
00009 *  Copyright (c) 1998-2000 Thomas Wouters
00010 */
00011 
00012 #include "mech.h"
00013 #include "btmacros.h"
00014 #include "mech.events.h"
00015 #include "p.bsuit.h"
00016 #include "p.btechstats.h"
00017 #include "p.crit.h"
00018 #include "p.eject.h"
00019 #include "p.map.conditions.h"
00020 #include "p.mech.ammodump.h"
00021 #include "p.mech.build.h"
00022 #include "p.mech.combat.misc.h"
00023 #include "p.mech.combat.missile.h"
00024 #include "p.mech.damage.h"
00025 #include "p.mech.ecm.h"
00026 #include "p.mech.hitloc.h"
00027 #include "p.mech.move.h"
00028 #include "p.mech.ood.h"
00029 #include "p.mech.utils.h"
00030 #include "p.mech.pickup.h"
00031 #include "p.pcombat.h"
00032 
00033 static char *MyColorStrings[] = {
00034         "", "%ch%cg", "%ch%cy", "%cr"
00035 };
00036 static char *MyMessageStrings[] = {
00037         "ERROR%c",
00038         "low.%c",
00039         "critical!%c",
00040         "BREACHED!%c"
00041 };
00042 static inline char *MySeriousColorStr(MECH * mech, int index)
00043 {
00044         return MyColorStrings[index % 4];
00045 }
00046 
00047 static inline char *MySeriousStr(MECH * mech, int index)
00048 {
00049         return MyMessageStrings[index % 4];
00050 }
00051 
00052 static inline int MySeriousnessCheck(MECH * mech, int hitloc)
00053 {
00054         int orig, new;
00055 
00056         if(!(orig = GetSectOArmor(mech, hitloc)))
00057                 return 0;
00058         if(!(new = GetSectArmor(mech, hitloc)))
00059                 return 3;
00060         if(new < orig / 4)
00061                 return 2;
00062         if(new < orig / 2)
00063                 return 1;
00064         return 0;
00065 }
00066 
00067 static inline int MySeriousnessCheckR(MECH * mech, int hitloc)
00068 {
00069         int orig, new;
00070 
00071         if(!(orig = GetSectORArmor(mech, hitloc)))
00072                 return 0;
00073         if(!(new = GetSectRArmor(mech, hitloc)))
00074                 return 3;
00075         if(new < orig / 4)
00076                 return 2;
00077         if(new < orig / 2)
00078                 return 1;
00079         return 0;
00080 }
00081 
00082 int cause_armordamage(MECH * wounded,
00083                                           MECH * attacker,
00084                                           int LOS,
00085                                           int attackPilot,
00086                                           int isrear,
00087                                           int iscritical,
00088                                           int hitloc, int damage, int *crits, int wWeapIndx,
00089                                           int wAmmoMode)
00090 {
00091         int intDamage = 0, r;
00092         int seriousness = 0;
00093         int tAPCritical = 0;
00094         int wPercentLeft = 0;
00095 
00096         if(MechType(wounded) == CLASS_MW)
00097                 return (damage > 0) ? damage : 0;
00098 
00099         if((MechSpecials(wounded) & HARDA_TECH) && damage > 0)
00100                 damage = (damage + 1) / 2;
00101 
00102         /* Now decrement armor, and if neccessary, handle criticals... */
00103         if(MechType(wounded) == CLASS_MECH && isrear && (hitloc == CTORSO
00104                                                                                                          || hitloc == RTORSO
00105                                                                                                          || hitloc == LTORSO)) {
00106 
00107                 if((GetSectRArmor(wounded, hitloc) - damage) >= 0) {
00108 
00109                         wPercentLeft = (((GetSectRArmor(wounded, hitloc) -
00110                                                           damage) * 100) / GetSectORArmor(wounded,
00111                                                                                                                           hitloc));
00112                 }
00113 
00114                 intDamage = damage - GetSectRArmor(wounded, hitloc);
00115 
00116                 if(intDamage > 0) {
00117                         SetSectRArmor(wounded, hitloc, 0);
00118                         if(intDamage != damage)
00119                                 seriousness = 3;
00120                 } else {
00121                         seriousness = MySeriousnessCheckR(wounded, hitloc);
00122                         SetSectRArmor(wounded, hitloc, GetSectRArmor(wounded,
00123                                                                                                                  hitloc) - damage);
00124                         seriousness = (seriousness == MySeriousnessCheckR(wounded,
00125                                                                                                                           hitloc)) ? 0 :
00126                                 MySeriousnessCheckR(wounded, hitloc);
00127                 }
00128 
00129         } else {
00130 
00131                 /* Silly stuff */
00132                 /*
00133                    SetSectArmor(wounded, hitloc, MAX(0, intDamage =  
00134                    GetSectArmor(wounded, hitloc) - damage));
00135                    intDamage = abs(intDamage);
00136                  */
00137 
00138                 if(GetSectOArmor(wounded, hitloc) &&
00139                    ((GetSectArmor(wounded, hitloc) - damage) >= 0)) {
00140 
00141                         wPercentLeft = (((GetSectArmor(wounded, hitloc) -
00142                                                           damage) * 100) / GetSectOArmor(wounded,
00143                                                                                                                          hitloc));
00144                 }
00145 
00146                 intDamage = damage - GetSectArmor(wounded, hitloc);
00147 
00148                 if(intDamage > 0) {
00149                         SetSectArmor(wounded, hitloc, 0);
00150                         if(intDamage != damage)
00151                                 seriousness = 3;
00152                 } else {
00153                         seriousness = MySeriousnessCheck(wounded, hitloc);
00154                         SetSectArmor(wounded, hitloc, GetSectArmor(wounded,
00155                                                                                                            hitloc) - damage);
00156                         seriousness = (seriousness == MySeriousnessCheck(wounded,
00157                                                                                                                          hitloc)) ? 0 :
00158                                 MySeriousnessCheck(wounded, hitloc);
00159                 }
00160 
00161                 if(!GetSectArmor(wounded, hitloc))
00162                         MechFloodsLoc(wounded, hitloc, MechZ(wounded));
00163         }
00164 
00165         if(!iscritical && (wAmmoMode & AC_AP_MODE) && (intDamage <= 0) &&
00166            (wPercentLeft < 50))
00167                 tAPCritical = 1;
00168 
00169         if(iscritical || tAPCritical) {
00170                 r = Roll();
00171                 rollstat.critrolls[r - 2]++;
00172                 rollstat.totcrolls++;
00173                 /* Do the AP ammo thang */
00174                 if(tAPCritical) {
00175                         if(!strcmp(&MechWeapons[wWeapIndx].name[3], "AC/2"))
00176                                 r -= 4;
00177                         else if(!strcmp(&MechWeapons[wWeapIndx].name[3], "LightAC/2"))
00178                                 r -= 4;
00179                         else if(!strcmp(&MechWeapons[wWeapIndx].name[3], "AC/5"))
00180                                 r -= 3;
00181                         else if(!strcmp(&MechWeapons[wWeapIndx].name[3], "LightAC/5"))
00182                                 r -= 3;
00183                         else if(!strcmp(&MechWeapons[wWeapIndx].name[3], "AC/10"))
00184                                 r -= 2;
00185                         else if(!strcmp(&MechWeapons[wWeapIndx].name[3], "AC/20"))
00186                                 r -= 1;
00187                         else
00188                                 r -= 10;
00189                 }
00190 
00191                 switch (r) {
00192                 case 8:
00193                 case 9:
00194                         HandleCritical(wounded, attacker, LOS, hitloc, 1);
00195                         (*crits) += 1;
00196                         break;
00197                 case 10:
00198                 case 11:
00199                         HandleCritical(wounded, attacker, LOS, hitloc, 2);
00200                         (*crits) += 2;
00201                         break;
00202                 case 12:
00203                         HandleCritical(wounded, attacker, LOS, hitloc, 3);
00204                         (*crits) += 3;
00205                         break;
00206                 default:
00207                         break;
00208                 }
00209                 iscritical = 0;
00210         }
00211 
00212         if(MechType(wounded) == CLASS_AERO && intDamage >= 0) {
00213                 DestroySection(wounded, attacker, LOS, hitloc);
00214                 if(Destroyed(wounded)) {
00215                         intDamage = 0;
00216                         return 0;
00217                 }
00218                 switch (hitloc) {
00219                 case AERO_AFT:
00220                         MakeMechFall(wounded);
00221                         MechSpeed(wounded) = 0;
00222                         SetMaxSpeed(wounded, 0);
00223                         MechVerticalSpeed(wounded) = 0;
00224                         if(!(MechStatus(wounded) & LANDED))
00225                                 mech_notify(wounded, MECHALL, "You feel the thrust die..");
00226                         else
00227                                 mech_notify(wounded, MECHALL,
00228                                                         "The computer reports engine destroyed!");
00229                         if(!Landed(wounded))
00230                                 MECHEVENT(wounded, EVENT_FALL, mech_fall_event, FALL_TICK,
00231                                                   -1);
00232                         break;
00233                 }
00234         }
00235 
00236         if(seriousness > 0 && MechArmorWarn(wounded))
00237                 mech_printf(wounded, MECHALL, "%sWARNING: %s%s Armor %s",
00238                                         MySeriousColorStr(wounded, seriousness),
00239                                         ShortArmorSectionString(MechType(wounded),
00240                                                                                         MechMove(wounded), hitloc),
00241                                         isrear ? " (Rear)" : "", MySeriousStr(wounded,
00242                                                                                                                   seriousness));
00243 
00244         return intDamage > 0 ? intDamage : 0;
00245 }
00246 
00247 int cause_internaldamage(MECH * wounded,
00248                                                  MECH * attacker,
00249                                                  int LOS,
00250                                                  int attackPilot,
00251                                                  int isrear, int hitloc, int intDamage, int weapindx,
00252                                                  int *crits)
00253 {
00254         int r = Roll();
00255         char locname[30];
00256         char msgbuf[MBUF_SIZE];
00257 
00258         ArmorStringFromIndex(hitloc, locname, MechType(wounded),
00259                                                  MechMove(wounded));
00260         if((MechSpecials(wounded) & REINFI_TECH) && intDamage > 0)
00261                 intDamage = (intDamage + 1) / 2;
00262         else if(MechSpecials(wounded) & COMPI_TECH)
00263                 intDamage = intDamage * 2;
00264         /* Critical hits? */
00265         rollstat.critrolls[r - 2]++;
00266         rollstat.totcrolls++;
00267         if(!(*crits))
00268                 switch (r) {
00269                 case 8:
00270                 case 9:
00271                         HandleCritical(wounded, attacker, LOS, hitloc, 1);
00272                         break;
00273                 case 10:
00274                 case 11:
00275                         HandleCritical(wounded, attacker, LOS, hitloc, 2);
00276                         break;
00277                 case 12:
00278                         if((MechType(wounded) == CLASS_MECH) ||
00279                            (MechType(wounded) == CLASS_MW)) {
00280                                 switch (hitloc) {
00281                                 case RARM:
00282                                 case LARM:
00283                                 case RLEG:
00284                                 case LLEG:
00285                                 case HEAD:
00286                                         /* Limb blown off */
00287                                         mech_notify(wounded, MECHALL, "%ch%cyCRITICAL HIT!!%c");
00288                                         if(!Destroyed(wounded)) {
00289                                                 sprintf(msgbuf,
00290                                                                 "'s %s is blown off in a shower of sparks and smoke!",
00291                                                                 locname);
00292                                                 MechLOSBroadcast(wounded, msgbuf);
00293                                         }
00294                                         DestroySection(wounded, attacker, LOS, hitloc);
00295                                         if(MechType(wounded) != CLASS_MW)
00296                                                 intDamage = 0;
00297                                         break;
00298                                 default:
00299                                         /* Ouch */
00300                                         HandleCritical(wounded, attacker, LOS, hitloc, 3);
00301                                         break;
00302                                 }
00303                         } else {
00304                                 HandleCritical(wounded, attacker, LOS, hitloc, 3);
00305                         }
00306 
00307                         break;
00308                 default:
00309                         break;
00310                         /* No critical hit */
00311                 }
00312         /* Hmm.. This should be interesting */
00313         if(MechType(wounded) == CLASS_MECH && intDamage && (hitloc == CTORSO)
00314            && GetSectInt(wounded, hitloc) == GetSectOInt(wounded, hitloc))
00315                 MechBoomStart(wounded) = muxevent_tick;
00316 
00317         if(GetSectInt(wounded, hitloc) <= intDamage) {
00318                 intDamage -= GetSectInt(wounded, hitloc);
00319                 DestroySection(wounded, attacker, LOS, hitloc);
00320 
00321 /*    if (Destroyed(wounded)) */
00322 
00323 /*      intDamage = 0;        */
00324         } else {
00325                 SetSectInt(wounded, hitloc, GetSectInt(wounded, hitloc) - intDamage);
00326                 intDamage = 0;
00327         }
00328         return intDamage;
00329 }
00330 
00331 int global_physical_flag = 0;
00332 void DamageMech(MECH * wounded,
00333                                 MECH * attacker,
00334                                 int LOS,
00335                                 int attackPilot,
00336                                 int hitloc,
00337                                 int isrear,
00338                                 int iscritical,
00339                                 int damage,
00340                                 int intDamage, int cause, int bth, int wWeapIndx,
00341                                 int wAmmoMode, int tIgnoreSwarmers)
00342 {
00343         char locationBuff[20];
00344         char notificationBuff[80];
00345         char rearMessage[10];
00346         int transfer = 0;
00347         int was_transfer = 0;
00348         int kill = 0;
00349         MAP *map;
00350         int crits = 0;
00351         int tBlowDumpingAmmo = 0;
00352         int wSwarmerHitChance = 0;
00353         int wRoll = Roll();
00354         MECH *mechSwarmer;
00355         int tSnapTowLines = 0;
00356         MECH *towTarget;
00357 
00358         /* if:
00359            damage = -1 && intDamage>0
00360            - ammo expl
00361            damage = -2 && intDamage>0
00362            - transferred ammo expl
00363            damage = n && intDamage = 0
00364            - usual damage
00365            damage = n && intDamage = -1/-2
00366            - usual damage + transfer/+red enable */
00367         /* if damage>0 && !intDamage usual dam. */
00368         map = getMap(attacker->mapindex);
00369         if((map && MapIsCS(map)) || (MechStatus(wounded) & COMBAT_SAFE)) {
00370                 if(wounded != attacker)
00371                         mech_notify(attacker, MECHALL,
00372                                                 "Your efforts only scratch the paint!");
00373                 return;
00374         }
00375 
00376         /* See if we have suits on us. If we get hit in any rear torso or the left/right front
00377          * torsos, there's a chance the bsuits on us will suck up the damage. In fasa rules, there's
00378          * no roll, but that's foolish if there's only one suits. 3030 rules are there's a 20 percent
00379          * chance per suit on you that the suits will eat up the damage.
00380          */
00381         if((CountSwarmers(wounded) > 0) && (!tIgnoreSwarmers)) {
00382                 if((mechSwarmer = findSwarmers(wounded))) {
00383                         if(!attacker || (attacker->mynum != mechSwarmer->mynum)) {
00384                                 wSwarmerHitChance = 20 * CountBSuitMembers(mechSwarmer);
00385                                 if(isrear) {
00386                                         if((hitloc != CTORSO) && (hitloc != RTORSO) &&
00387                                            (hitloc != LTORSO))
00388                                                 wSwarmerHitChance = 0;
00389                                 } else {
00390                                         if((hitloc != RTORSO) && (hitloc != LTORSO))
00391                                                 wSwarmerHitChance = 0;
00392                                 }
00393 
00394                                 if((wSwarmerHitChance >= wRoll) &&
00395                                    (GetSectArmor(wounded, hitloc))) {
00396                                         if(attacker && (attacker->mynum != wounded->mynum)) {
00397                                                 mech_notify(attacker, MECHALL,
00398                                                                         "The battlesuits crawling all over your target absorb the damage!");
00399                                         }
00400 
00401                                         mech_notify(wounded, MECHALL,
00402                                                                 "The battlesuits crawling all over you absorb the damage!");
00403                                         mech_notify(mechSwarmer, MECHALL,
00404                                                                 "You absorb the damage!");
00405                                         hitloc =
00406                                                 FindHitLocation(mechSwarmer, 0, &iscritical, &isrear);
00407                                         DamageMech(mechSwarmer, attacker, LOS,
00408                                                            attackPilot, hitloc, 0, 0, damage, 0,
00409                                                            cause, bth, wWeapIndx, wAmmoMode, 0);
00410                                         return;
00411                                 }
00412 
00413                         }
00414                 }
00415         }
00416 
00417         if(MechType(wounded) == CLASS_MW || MechType(wounded) == CLASS_MECH)
00418                 transfer = 1;
00419 #ifdef BT_MOVEMENT_MODES
00420         if((damage > 0 || intDamage > 0) && MechStatus2(wounded) & SPRINTING) {
00421                 MechStatus2(wounded) &= ~SPRINTING;
00422                 MechLOSBroadcast(wounded,
00423                                                  "breaks out of its sprint as it takes damage!");
00424                 mech_notify(wounded, MECHALL,
00425                                         "You lose your sprinting momentum as you take damage!");
00426                 if(!MoveModeChange(wounded))
00427                         MECHEVENT(wounded, EVENT_MOVEMODE, mech_movemode_event, TURN,
00428                                           MODE_OFF | MODE_SPRINT);
00429         }
00430 
00431         if((damage > 0 || intDamage > 0) && MechCritStatus(wounded) & HIDDEN) {
00432                 MechCritStatus(wounded) &= ~HIDDEN;
00433                 MechLOSBroadcast(wounded, "loses its cover as it takes damage!");
00434                 mech_notify(wounded, MECHALL,
00435                                         "Your cover is ruined as you take damage!");
00436                 if(!MoveModeChange(wounded))
00437                         MechCritStatus(wounded) &= ~HIDDEN;
00438         }
00439 
00440         if((damage > 0 || intDamage > 0)
00441            && (MoveModeLock(wounded)
00442                    && !(MoveModeData(wounded) &
00443                                 (MODE_EVADE | MODE_DODGE | MODE_OFF)))) {
00444                 StopMoveMode(wounded);
00445                 mech_notify(wounded, MECHALL,
00446                                         "Your movement mode changes are cancelled as you take damage!");
00447         }
00448 #endif
00449         if(damage > 0 && intDamage == 0) {
00450                 /* If we're a VTOL and the hitloc is the rotor,
00451                    we'll cut the damage by some value */
00452                 if((MechType(wounded) == CLASS_VTOL) && (hitloc == ROTOR)) {
00453                         if(mudconf.btech_divrotordamage > 0)
00454                                 damage = damage / mudconf.btech_divrotordamage;
00455                         if(damage < 1)
00456                                 damage = 1;
00457                 }
00458 
00459                 if(MechCritStatus(wounded) & HIDDEN) {
00460                         mech_notify(wounded, MECHALL,
00461                                                 "Your cover is ruined as you take damage!");
00462                         MechLOSBroadcast(wounded, "loses its cover as it takes damage.");
00463                         MechCritStatus(wounded) &= ~HIDDEN;
00464                 }
00465 
00466                 if(!global_physical_flag)
00467                         AccumulateGunXP(attackPilot, attacker, wounded, damage, 1,
00468                                                         cause, bth);
00469                 else if(global_physical_flag == 1)
00470                         if(!Destroyed(wounded) && In_Character(wounded->mynum) &&
00471                            MechTeam(wounded) != MechTeam(attacker))
00472                                 if(MechType(wounded) != CLASS_MW ||
00473                                    MechType(attacker) == CLASS_MW)
00474                                         AccumulatePilXP(attackPilot, attacker, damage / 3, 1);
00475                 damage = dam_to_pc_conversion(wounded, cause, damage);
00476         }
00477         if(isrear) {
00478                 if(!(MechSpecials(wounded) & SALVAGE_TECH) && (Roll() <= 5) &&
00479                    (hitloc == CTORSO || hitloc == LTORSO || hitloc == RTORSO))
00480                         tSnapTowLines = 1;
00481 
00482                 if(MechType(wounded) == CLASS_MECH) {
00483                         strcpy(rearMessage, "(Rear)");
00484                         if(Dumping(wounded) && ((hitloc == CTORSO) ||
00485                                                                         (hitloc == LTORSO) ||
00486                                                                         (hitloc == RTORSO)) && (cause >= 0))
00487                                         tBlowDumpingAmmo = 1;
00488                 } else {
00489                         if(hitloc == FSIDE)
00490                                 hitloc = BSIDE;
00491                         *rearMessage = '\0';
00492                         isrear = 0;
00493                 }
00494         } else
00495                 *rearMessage = '\0';
00496         /* Damage something else, ok? */
00497         if(damage < 0) {
00498                 switch (damage) {
00499                 case -2:
00500                         was_transfer = 1;
00501                 case -1:
00502                         transfer = 1;
00503                         break;
00504                 }
00505                 damage = 0;
00506         } else if(intDamage < 0) {
00507                 switch (intDamage) {
00508                 case -2:
00509                         was_transfer = 1;
00510                 case -1:
00511                         transfer = 1;
00512                         break;
00513                 }
00514                 intDamage = 0;
00515         }
00516 
00517         /*   while (SectIsDestroyed(wounded, hitloc) && !kill) */
00518         while (((!is_aero(wounded) && !GetSectInt(wounded, hitloc)) ||
00519                         (is_aero(wounded) && !GetSectArmor(wounded, hitloc))) && !kill) {
00520                 if(transfer && (hitloc = TransferTarget(wounded, hitloc)) >= 0
00521                    && (MechType(wounded) == CLASS_MECH ||
00522                            MechType(wounded) == CLASS_MW ||
00523                            MechType(wounded) == CLASS_BSUIT || is_aero(wounded))) {
00524                         DamageMech(wounded, attacker, LOS, attackPilot, hitloc,
00525                                            isrear, iscritical, damage == -1 ? -2 : damage,
00526                                            transfer == 1 ? -2 : damage, cause, bth, wWeapIndx,
00527                                            wAmmoMode, tIgnoreSwarmers);
00528                         return;
00529                 } else {
00530                         if(!((MechType(wounded) == CLASS_MECH ||
00531                                   MechType(wounded) == CLASS_MW ||
00532                                   MechType(wounded) == CLASS_BSUIT ||
00533                                   is_aero(wounded)) &&
00534                                  (hitloc = TransferTarget(wounded, hitloc)) >= 0)) {
00535                                 if(is_aero(wounded) && !Destroyed(wounded)) {
00536                                         /* Hurt SI instead. */
00537                                         if(AeroSI(wounded) <= damage)
00538                                                 kill = 1;
00539                                         else {
00540                                                 AeroSI(wounded) -= damage;
00541                                                 kill = -1;
00542                                         }
00543                                 } else
00544                                         return;
00545                         }
00546                         /* Nyah. Damage transferred to waste, shooting a dead mech? */
00547                 }
00548 
00549         }
00550         if(C_OODing(wounded) && Roll() > 8) {
00551                 mech_ood_damage(wounded, attacker,
00552                                                 damage + (intDamage < 0 ? 0 : intDamage));
00553                 return;
00554         }
00555 
00556         if(hitloc != -1) {
00557                 ArmorStringFromIndex(hitloc, locationBuff, MechType(wounded),
00558                                                          MechMove(wounded));
00559                 sprintf(notificationBuff,
00560                                 "for %d points of damage in the %s %s",
00561                                 damage + (intDamage < 0 ? 0 : intDamage), locationBuff,
00562                                 rearMessage);
00563         } else
00564                 sprintf(notificationBuff,
00565                                 "for %d points of damage in the structure.",
00566                                 damage + (intDamage < 0 ? 0 : intDamage));
00567         /*  if (LOS && attackPilot != -1) */
00568         if(LOS) {
00569                 if(!was_transfer)
00570                         mech_printf(attacker, MECHALL, "%%cgYou hit %s%%c",
00571                                                 notificationBuff);
00572                 else
00573                         mech_printf(attacker, MECHALL,
00574                                                 "%%cgDamage transfer.. %s%%c", notificationBuff);
00575         }
00576         if(MechType(wounded) == CLASS_MW && !was_transfer)
00577                 if(damage > 0)
00578                         if(!(damage =
00579                                  armor_effect(wounded, cause, hitloc, damage, intDamage)))
00580                                 return;
00581         mech_printf(wounded, MECHALL,
00582                                 "%%ch%%cyYou have been hit %s%s%%c",
00583                                 notificationBuff, was_transfer ? "(transfer)" : "");
00584 
00585         /* Always a good policy :-> */
00586         if(damage > 0 && intDamage <= 0 && !was_transfer && !Fallen(wounded)) {
00587                 if(mudconf.btech_newstagger && MechType(wounded) == CLASS_MECH) {
00588                         StaggerDamage(wounded) += damage;
00589                 } else {
00590                         MechTurnDamage(wounded) += damage;
00591                 }
00592         }
00593 
00594         if(hitloc == HEAD && MechType(wounded) == CLASS_MECH) {
00595 
00596                 /*      mech_notify (wounded, MECHALL,
00597                    "You take 10 points of Lethal damage!!"); */
00598                 headhitmwdamage(wounded, attacker, 1);
00599         }
00600         if(kill) {
00601                 if(kill == 1) {
00602                         mech_notify(wounded, MECHALL,
00603                                                 "The blast causes the last of your craft's structure to disintegrate, blowing");
00604                         mech_notify(wounded, MECHALL, "its pieces all over the sky!");
00605                         if(!Landed(wounded) && Started(wounded)) {
00606                                 mech_notify(attacker, MECHALL,
00607                                                         "You shoot the craft from the sky!");
00608                                 MechLOSBroadcasti(attacker, wounded,
00609                                                                   "shoots %s from the sky!");
00610                         }
00611                         DestroyMech(wounded, attacker, !(!Landed(wounded) &&
00612                                                                                          Started(wounded)));
00613                 }
00614                 return;
00615         }
00616         if(damage > 0) {
00617                 if(MechType(wounded) == CLASS_MECH) {
00618                         if(!isrear && (MechSpecials(wounded) & SLITE_TECH) &&
00619                            !(MechCritStatus(wounded) & SLITE_DEST) &&
00620                            (hitloc == LTORSO || hitloc == CTORSO || hitloc == RTORSO)) {
00621                                 /* Possibly destroy the light */
00622                                 if(Roll() > 6) {
00623                                         if((MechStatus2(wounded) & SLITE_ON) || (Roll() > 5)) {
00624                                                 MechCritStatus(wounded) |= SLITE_DEST;
00625                                                 MechStatus2(wounded) &= ~SLITE_ON;
00626                                                 MechLOSBroadcast(wounded,
00627                                                                                  "'s searchlight is blown apart!");
00628                                                 mech_notify(wounded, MECHALL,
00629                                                                         "%ch%cyYour searchlight is destroyed!%cn");
00630                                         }
00631                                 }
00632                         }
00633                 }
00634                 if(MechType(wounded) == CLASS_VEH_GROUND) {
00635                         if(!isrear && (MechSpecials(wounded) & SLITE_TECH) &&
00636                            !(MechCritStatus(wounded) & SLITE_DEST) && (hitloc == FSIDE)) {
00637                                 /* Possibly destroy the light */
00638                                 if(Roll() > 6) {
00639                                         if((MechStatus2(wounded) & SLITE_ON) || (Roll() > 5)) {
00640                                                 MechCritStatus(wounded) |= SLITE_DEST;
00641                                                 MechStatus2(wounded) &= ~SLITE_ON;
00642                                                 MechLOSBroadcast(wounded,
00643                                                                                  "'s searchlight is blown apart!");
00644                                                 mech_notify(wounded, MECHALL,
00645                                                                         "%ch%cyYour searchlight is destroyed!%cn");
00646                                         }
00647                                 }
00648                         }
00649                 }
00650                 intDamage +=
00651                         cause_armordamage(wounded, attacker, LOS, attackPilot, isrear,
00652                                                           iscritical, hitloc, damage, &crits, wWeapIndx,
00653                                                           wAmmoMode);
00654                 if(intDamage >= 0)
00655                         MechFloodsLoc(wounded, hitloc, MechZ(wounded));
00656                 if(intDamage > 0 && !is_aero(wounded)) {
00657                         intDamage =
00658                                 cause_internaldamage(wounded, attacker, LOS, attackPilot,
00659                                                                          isrear, hitloc, intDamage, cause,
00660                                                                          &crits);
00661                         if(!intDamage && !SectIsDestroyed(wounded, hitloc))
00662                                 BreachLoc(attacker, wounded, hitloc);
00663                 } else
00664                         PossiblyBreach(attacker, wounded, hitloc);
00665                 if(intDamage > 0 && transfer && (MechType(wounded) != CLASS_BSUIT)) {
00666                         if((hitloc = TransferTarget(wounded, hitloc)) >= 0)
00667                                 DamageMech(wounded, attacker, LOS, attackPilot, hitloc,
00668                                                    isrear, iscritical, intDamage, -2, cause, bth,
00669                                                    wWeapIndx, wAmmoMode, tIgnoreSwarmers);
00670                         else {
00671                                 DestroyMech(wounded, attacker, 1);
00672                                 return;
00673                         }
00674                 }
00675         } else
00676                 /* Cause _INTERNAL_ HAVOC! :-) */
00677                 /* Non-CASE things get _really_ hurt */
00678         {
00679                 if(intDamage > 0) {
00680                         if(is_aero(wounded))
00681                                 intDamage =
00682                                         cause_armordamage(wounded, attacker, LOS, attackPilot,
00683                                                                           isrear, iscritical, hitloc,
00684                                                                           intDamage, &crits, wWeapIndx,
00685                                                                           wAmmoMode);
00686                         else
00687                                 intDamage =
00688                                         cause_internaldamage(wounded, attacker, LOS,
00689                                                                                  attackPilot, isrear, hitloc,
00690                                                                                  intDamage, cause, &crits);
00691                         if(!SectIsDestroyed(wounded, hitloc))
00692                                 PossiblyBreach(attacker, wounded, hitloc);
00693                         if(intDamage > 0 && transfer &&
00694                            !((MechSections(wounded)[hitloc].config & CASE_TECH) ||
00695                                  (MechSpecials(wounded) & CLAN_TECH))) {
00696                                 if((hitloc = TransferTarget(wounded, hitloc)) >= 0) {
00697                                         if(!is_aero(wounded))
00698                                                 DamageMech(wounded, attacker, LOS, attackPilot,
00699                                                                    hitloc, isrear, iscritical, -2,
00700                                                                    intDamage, cause, bth, wWeapIndx,
00701                                                                    wAmmoMode, tIgnoreSwarmers);
00702                                         else
00703                                                 DamageMech(wounded, attacker, LOS, attackPilot,
00704                                                                    hitloc, isrear, iscritical, intDamage,
00705                                                                    -2, cause, bth, wWeapIndx, wAmmoMode,
00706                                                                    tIgnoreSwarmers);
00707                                 } else {
00708                                         DestroyMech(wounded, attacker, 1);
00709                                         return;
00710                                 }
00711                         }
00712                 }
00713         }
00714 
00715         /* Check to see if the tow lines should snap */
00716         if(tSnapTowLines && (MechCarrying(wounded) > 0)) {
00717                 if((towTarget = getMech(MechCarrying(wounded)))) {
00718                         mech_notify(wounded, MECHALL,
00719                                                 "The hit causes your tow line to let go!");
00720                         mech_notify(towTarget, MECHALL,
00721                                                 "Your tow lines go suddenly slack!");
00722                         MechLOSBroadcast(wounded,
00723                                                          "'s tow lines release and flap freely behind it!");
00724 
00725                         mech_dropoff(GOD, wounded, "");
00726                 }
00727         }
00728 
00729         /* Check to see if we blow up ammo that's dumping. */
00730         if(tBlowDumpingAmmo) {
00731                 BlowDumpingAmmo(wounded, attacker, hitloc);
00732         }
00733 }
00734 
00735 /* this takes care of setting all the criticals to CRIT_DESTROYED */
00736 void DestroyWeapon(MECH * wounded, int hitloc, int type, int startCrit,
00737                                    int numcrits, int totalcrits)
00738 {
00739         int i;
00740         char sum = 0;
00741         char destroyed = 0;
00742 
00743         for(i = startCrit; i < NUM_CRITICALS; i++) {
00744                 if(GetPartType(wounded, hitloc, i) == type) {
00745                         if(PartIsDamaged(wounded, hitloc, i)) {
00746                                 DestroyPart(wounded, hitloc, i);
00747                         } else if(destroyed < numcrits) {
00748                                 DestroyPart(wounded, hitloc, i);
00749                                 destroyed++;
00750                         } else {
00751                                 BreakPart(wounded, hitloc, i);
00752                         }
00753 
00754                         sum++;
00755 
00756                         if(sum == totalcrits)
00757                                 return;
00758                 }
00759         }
00760 }
00761 
00762 int CountWeaponsInLoc(MECH * mech, int loc)
00763 {
00764         int i;
00765         int j, sec, cri;
00766         int count = 0;
00767 
00768         j = FindWeaponNumberOnMech(mech, 1, &sec, &cri);
00769         for(i = 2; j != -1; i++) {
00770                 if(sec == loc)
00771                         count++;
00772                 j = FindWeaponNumberOnMech(mech, i, &sec, &cri);
00773         }
00774         return count;
00775 }
00776 
00777 int FindWeaponTypeNumInLoc(MECH * mech, int loc, int num)
00778 {
00779         int i;
00780         int j, sec, cri;
00781         int count = 0;
00782 
00783         j = FindWeaponNumberOnMech(mech, 1, &sec, &cri);
00784         for(i = 2; j != -1; i++) {
00785                 if(sec == loc) {
00786                         count++;
00787                         if(count == num)
00788                                 return j;
00789                 }
00790                 j = FindWeaponNumberOnMech(mech, i, &sec, &cri);
00791         }
00792         return -1;
00793 }
00794 
00795 void LoseWeapon(MECH * mech, int hitloc)
00796 {
00797         /* Look for hit locations.. */
00798         int i = CountWeaponsInLoc(mech, hitloc);
00799         int a, b;
00800         int firstCrit;
00801 
00802         if(!i)
00803                 return;
00804         a = random() % i + 1;
00805         b = FindWeaponTypeNumInLoc(mech, hitloc, a);
00806         if(b < 0)
00807                 return;
00808 
00809         firstCrit =
00810                 FindFirstWeaponCrit(mech, hitloc, -1, 0, I2Weapon(b),
00811                                                         GetWeaponCrits(mech, b));
00812 
00813         DestroyWeapon(mech, hitloc, I2Weapon(b), firstCrit, 1,
00814                                   GetWeaponCrits(mech, b));
00815         mech_printf(mech, MECHALL, "%%ch%%crYour %s is destroyed!%%c",
00816                                 &MechWeapons[b].name[3]);
00817 }
00818 
00819 void DestroyHeatSink(MECH * mech, int hitloc)
00820 {
00821         /* This can be done easily, or this can be done painfully. */
00822         /* Let's try the painful way, it's more fun that way. */
00823         int num;
00824         int i = I2Special(HEAT_SINK);
00825 
00826         if(FindObj(mech, hitloc, i)) {
00827                 num = HS_Size(mech);
00828                 DestroyWeapon(mech, hitloc, i, 0, 1, num);
00829                 MechRealNumsinks(mech) -= MAX(num, 2);
00830                 mech_notify(mech, MECHALL,
00831                                         "The computer shows a heatsink died due to the impact.");
00832         }
00833 }
00834 
00835 void DestroySection(MECH * wounded, MECH * attacker, int LOS, int hitloc)
00836 {
00837         char locname[30];
00838         char msgbuf[MBUF_SIZE];
00839         int i, j;
00840         int tKillMech;
00841         int tIsLeg = ((hitloc == RLEG || hitloc == LLEG) ||
00842                                   ((hitloc == RARM || hitloc == LARM)
00843                                    && (MechIsQuad(wounded))));
00844         dbref wounded_pilot = MechPilot(wounded);
00845         MECH *ttarget;
00846         
00847         /* Prevent the rare occurance of a section getting destroyed twice */
00848         if(SectIsDestroyed(wounded, hitloc)) {
00849                 fprintf(stderr, "Double-desting section %d on mech #%d\n",
00850                                 hitloc, wounded->mynum);
00851                 if(IsDS(wounded))
00852                         return;
00853                 for(i = 0; i < NUM_SECTIONS; i++)
00854                         if(GetSectOInt(wounded, i) && GetSectInt(wounded, i))
00855                                 return;
00856                 if(muxevent_count_type_data(EVENT_NUKEMECH, (void *) wounded)) {
00857                         fprintf(stderr, "And nuke event already existed.\n");
00858                         return;
00859                 }
00860                 discard_mw(wounded);
00861         }
00862         /* Ouch. They got toasted */
00863         SetSectArmor(wounded, hitloc, 0);
00864         SetSectInt(wounded, hitloc, 0);
00865         SetSectRArmor(wounded, hitloc, 0);
00866         SetSectDestroyed(wounded, hitloc);
00867         MechSections(wounded)[hitloc].specials = 0;
00868 
00869         /* uncycle the section <in the case of an arm/leg that was kicking getting blown */
00870         SetRecycleLimb(wounded, hitloc, 0);
00871         
00872         /* drop off what we were carrying, since we really can't pick it up with one arm */
00873         if((hitloc == RARM || hitloc == LARM)) {
00874                 if(MechCarrying(wounded) > 0) {
00875                         if((ttarget = getMech(MechCarrying(wounded)))) {
00876                                 mech_notify(ttarget, MECHALL, "Your tow lines go suddenly slack!");
00877                                 mech_dropoff(GOD, wounded, "");
00878                         }
00879                 }
00880         }
00881                 
00882         /* Tell the attacker about it... */
00883         if(attacker) {
00884                 ArmorStringFromIndex(hitloc, locname, MechType(wounded),
00885                                                          MechMove(wounded));
00886                 if(LOS >= 0)
00887                         mech_printf(wounded, MECHALL,
00888                                                 "Your %s has been destroyed!", locname);
00889                 sprintf(msgbuf, "'s %s has been destroyed!", locname);
00890                 MechLOSBroadcast(wounded, msgbuf);
00891         }
00892 
00893         /* Destroy everything in the loc */
00894         DestroyParts(attacker, wounded, hitloc, 0, 0);
00895         checkECM(wounded);
00896         /* Stop lateral if we're a quad */
00897         if((MechType(wounded) == CLASS_MECH) && MechIsQuad(wounded))
00898                 if(MechLateral(wounded) && tIsLeg)
00899                         MechLateral(wounded) = 0;
00900         /* Check to see if we should destroy the unit */
00901         if(MechType(wounded) == CLASS_BSUIT) {
00902                 if(CountBSuitMembers(wounded) > 0)
00903                         goto skip_nuke;
00904                 else if(!Destroyed(wounded))
00905                         DestroyMech(wounded, attacker, 1);
00906         } else {
00907                 for(i = 0; i < NUM_SECTIONS; i++)
00908                         if(GetSectOInt(wounded, i) && GetSectInt(wounded, i))
00909                                 goto skip_nuke;
00910         }
00911 
00912         /* Ensure the template's timely demise */
00913         if(In_Character(wounded->mynum)) {
00914                 /* Clear the freqs on the unit... */
00915                 for(j = 0; j < FREQS; j++) {
00916                         wounded->freq[j] = 0;
00917                         wounded->freqmodes[j] = 0;
00918                         wounded->chantitle[j][0] = 0;
00919                 }
00920 
00921                 /* There's a 25% chance of bsuit pilots living through it */
00922                 if((MechType(wounded) == CLASS_BSUIT) &&
00923                    (Number(1, 100) <= 25) && wounded_pilot)
00924                         autoeject(wounded_pilot, wounded, 1);
00925                 else
00926                         KillMechContentsIfIC(wounded->mynum);
00927                 /* Schedule removal of the template */
00928                 if(!IsDS(wounded))
00929                         discard_mw(wounded);
00930         }
00931 
00932         /* We've done everything we should do... */
00933         return;
00934   skip_nuke:
00935 
00936         /* Add 4 MW damage if it's a MW loosing a location */
00937         if(MechType(wounded) == CLASS_MW) {
00938                 mwlethaldam(wounded, attacker, 4);
00939         }
00940 
00941         /* If it's a MW or a mech, let's see if there's additional stuff we need to do */
00942         if(MechType(wounded) == CLASS_MW || MechType(wounded) == CLASS_MECH) {
00943                 if(hitloc == LTORSO)
00944                         DestroySection(wounded, attacker, LOS, LARM);
00945                 else if(hitloc == RTORSO)
00946                         DestroySection(wounded, attacker, LOS, RARM);
00947                 else if(hitloc == CTORSO || hitloc == HEAD) {
00948                         if(!Destroyed(wounded))
00949                                 DestroyMech(wounded, attacker, 1);
00950                         /* If it's the head or a MW's CT, kill the contents if IC */
00951                         if(hitloc == HEAD || ((MechType(wounded) == CLASS_MW) &&
00952                                                                   (hitloc == CTORSO))) {
00953                                 if(In_Character(wounded->mynum)) {
00954                                         for(j = 0; j < FREQS; j++) {
00955                                                 wounded->freq[j] = 0;
00956                                                 wounded->freqmodes[j] = 0;
00957                                                 wounded->chantitle[j][0] = 0;
00958                                         }
00959                                         KillMechContentsIfIC(wounded->mynum);
00960                                 }
00961                         }
00962 
00963                         if(MechType(wounded) == CLASS_MW)
00964                                 discard_mw(wounded);
00965                 }
00966 
00967                 return;
00968         }
00969 
00970         /* If we're an aero... */
00971         if(is_aero(wounded)) {
00972                 /* Aero handling is trivial ; No destruction whatsoever, for now. */
00973                 /* With one exception.. */
00974                 if(hitloc == COCKPIT && MechType(wounded) == CLASS_AERO) {
00975                         if(!Destroyed(wounded))
00976                                 DestroyMech(wounded, attacker, 1);
00977                         for(j = 0; j < FREQS; j++) {
00978                                 wounded->freq[j] = 0;
00979                                 wounded->freqmodes[j] = 0;
00980                                 wounded->chantitle[j][0] = 0;
00981                         }
00982                         KillMechContentsIfIC(wounded->mynum);
00983                 }
00984                 return;
00985         }
00986 
00987         /* Last check to see if we destroy the unit... vehicle stuff */
00988         if(TransferTarget(wounded, 0) < 0)
00989                 tKillMech = 1;
00990         else
00991                 tKillMech = 0;
00992         switch (MechType(wounded)) {
00993         case CLASS_BSUIT:
00994                 tKillMech = 0;
00995                 break;
00996         case CLASS_VEH_GROUND:
00997                 if(hitloc == TURRET) {
00998                         tKillMech = 0;
00999                         MechStatus2(wounded) &= ~AUTOTURN_TURRET;
01000                 } else
01001                         tKillMech = 1;
01002                 break;
01003         case CLASS_VTOL:
01004                 if(hitloc == ROTOR) {
01005                         tKillMech = 0;
01006                         StartVTOLCrash(wounded);
01007                 } else
01008                         tKillMech = 1;
01009                 break;
01010         }
01011 
01012         if(tKillMech) {
01013                 if(!Destroyed(wounded))
01014                         DestroyMech(wounded, attacker, 1);
01015         }
01016 }
01017 
01018 char *setarmorstatus_func(MECH * mech,
01019                                                   char *sectstr, char *typestr, char *valuestr)
01020 {
01021         int index, type, value;
01022 
01023         if(!sectstr || !*sectstr)
01024                 return "#-1 INVALID SECTION";
01025         index = ArmorSectionFromString(MechType(mech), MechMove(mech), sectstr);
01026         if(index == -1 || !GetSectOInt(mech, index))
01027                 return "#-1 INVALID SECTION";
01028         if((value = atoi(valuestr)) < 0 || value > 255)
01029                 return "#-1 INVALID ARMORVALUE";
01030         switch (type = atoi(typestr)) {
01031         case 0:
01032                 SetSectArmor(mech, index, value);
01033                 break;
01034         case 1:
01035                 SetSectInt(mech, index, value);
01036                 break;
01037         case 2:
01038                 SetSectRArmor(mech, index, value);
01039                 break;
01040         default:
01041                 return "#-1 INVALID ARMORTYPE";
01042         }
01043         return "1";
01044 }
01045 
01046 int dodamage_func(dbref player,
01047                                   MECH * mech,
01048                                   int totaldam,
01049                                   int clustersize,
01050                                   int direction, int iscritical, char *mechmsg,
01051                                   char *mechbroadcast)
01052 {
01053 
01054         int hitloc = 1, this_time, isrear = 0, dummy = 0;
01055         int *dummy1 = &dummy, *dummy2 = &dummy;
01056 
01057         if(direction < 8) {
01058                 hitloc = direction;
01059         } else if(direction < 16) {
01060                 hitloc = direction - 8;
01061                 isrear = 1;
01062         } else if(direction > 21) {
01063                 return 0;
01064         }
01065 
01066         if(mechmsg && *mechmsg)
01067                 mech_notify(mech, MECHALL, mechmsg);
01068         if(mechbroadcast && *mechbroadcast)
01069                 MechLOSBroadcast(mech, mechbroadcast);
01070         while (totaldam) {
01071                 if(direction > 18)
01072                         isrear = 1;
01073                 if(direction > 15)
01074                         hitloc =
01075                                 FindHitLocation(mech, ((direction - 1) & 3) + 1, dummy1,
01076                                                                 dummy2);
01077                 this_time = MIN(clustersize, totaldam);
01078                 DamageMech(mech, mech, 0, -1, hitloc, isrear, iscritical,
01079                                    this_time, 0, 0, 0, -1, 0, 1);
01080                 totaldam -= this_time;
01081         }
01082         return 1;
01083 }
01084 
01085 void mech_damage(dbref player, MECH * mech, char *buffer)
01086 {
01087         char *args[5];
01088         int damage, clustersize;
01089         int isrear, iscritical;
01090 
01091         DOCHECK(mech_parseattributes(buffer, args, 5) != 4, "Invalid arguments!");
01092         DOCHECK(Readnum(damage, args[0]), "Invalid damage!");
01093         DOCHECK(Readnum(clustersize, args[1]), "Invalid cluster size!");
01094         DOCHECK(Readnum(isrear, args[2]), "Invalid isrear flag!");
01095         DOCHECK(Readnum(iscritical, args[3]), "Invalid iscritical flag!");
01096         DOCHECK(damage <= 0 || damage > 1000, "Invalid damage!");
01097         DOCHECK(clustersize <= 0, "Invalid cluster size!");
01098         DOCHECK(clustersize > damage, "Invalid cluster size! (must be smaller than damage amount, but > 0)");
01099         DOCHECK(MechType(mech) == CLASS_MW, "No MW killings!");
01100         Missile_Hit(mech, mech, -1, -1, isrear, iscritical, 0, -1, -1,
01101                                 clustersize, damage / clustersize, 1, 0, 0, 0);
01102 }

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