00001
00002
00003
00004
00005
00006
00007
00008
00009
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
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
00132
00133
00134
00135
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
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
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
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
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
00311 }
00312
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
00322
00323
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
00359
00360
00361
00362
00363
00364
00365
00366
00367
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
00377
00378
00379
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
00451
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
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
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
00537 if(AeroSI(wounded) <= damage)
00538 kill = 1;
00539 else {
00540 AeroSI(wounded) -= damage;
00541 kill = -1;
00542 }
00543 } else
00544 return;
00545 }
00546
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
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
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
00597
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
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
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
00677
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
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
00730 if(tBlowDumpingAmmo) {
00731 BlowDumpingAmmo(wounded, attacker, hitloc);
00732 }
00733 }
00734
00735
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
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
00822
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
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
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
00870 SetRecycleLimb(wounded, hitloc, 0);
00871
00872
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
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
00894 DestroyParts(attacker, wounded, hitloc, 0, 0);
00895 checkECM(wounded);
00896
00897 if((MechType(wounded) == CLASS_MECH) && MechIsQuad(wounded))
00898 if(MechLateral(wounded) && tIsLeg)
00899 MechLateral(wounded) = 0;
00900
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
00913 if(In_Character(wounded->mynum)) {
00914
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
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
00928 if(!IsDS(wounded))
00929 discard_mw(wounded);
00930 }
00931
00932
00933 return;
00934 skip_nuke:
00935
00936
00937 if(MechType(wounded) == CLASS_MW) {
00938 mwlethaldam(wounded, attacker, 4);
00939 }
00940
00941
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
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
00971 if(is_aero(wounded)) {
00972
00973
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
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 }