00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "mech.h"
00012 #include "mech.events.h"
00013 #include "p.mech.enhanced.criticals.h"
00014 #include "p.mech.utils.h"
00015 #include "p.mech.combat.h"
00016 #include "p.mech.damage.h"
00017 #include "p.mech.bth.h"
00018 #include "failures.h"
00019
00020 void getWeapData(MECH * mech, int section, int critical, int *wWeapIndex,
00021 int *wWeapSize, int *wFirstCrit)
00022 {
00023 int wCritType = 0;
00024
00025
00026 wCritType = GetPartType(mech, section, critical);
00027
00028
00029 *wWeapIndex = Weapon2I(wCritType);
00030
00031
00032 *wWeapSize = GetWeaponCrits(mech, *wWeapIndex);
00033
00034
00035 *wFirstCrit =
00036 FindFirstWeaponCrit(mech, section, critical, 0, wCritType,
00037 *wWeapSize);
00038 }
00039
00040 int getCritAddedBTH(MECH * mech, int section, int critical, int rangeBracket)
00041 {
00042 int wWeapSize = 0;
00043 int wFirstCrit = 0;
00044 int wWeapIndex = 0;
00045 int i;
00046 int wRetMod = 0;
00047
00048 if(MechType(mech) != CLASS_MECH)
00049 return 0;
00050
00051 getWeapData(mech, section, critical, &wWeapIndex, &wWeapSize,
00052 &wFirstCrit);
00053
00054
00055 for(i = wFirstCrit; i < (wFirstCrit + wWeapSize); i++) {
00056 if(GetPartDamageFlags(mech, section, i) & WEAP_DAM_MODERATE)
00057 wRetMod++;
00058
00059 if(((GetPartDamageFlags(mech, section, i) & WEAP_DAM_EN_FOCUS) ||
00060 (GetPartDamageFlags(mech, section,
00061 i) & WEAP_DAM_MSL_RANGING)) &&
00062 (rangeBracket != RANGE_SHORT))
00063 wRetMod++;
00064 }
00065
00066 return wRetMod;
00067 }
00068
00069 int getCritAddedHeat(MECH * mech, int section, int critical)
00070 {
00071 int wWeapSize = 0;
00072 int wFirstCrit = 0;
00073 int wWeapIndex = 0;
00074 int i;
00075 int wRetMod = 0;
00076
00077 getWeapData(mech, section, critical, &wWeapIndex, &wWeapSize,
00078 &wFirstCrit);
00079
00080 if(!IsEnergy(wWeapIndex))
00081 return 0;
00082
00083
00084 for(i = wFirstCrit; i < (wFirstCrit + wWeapSize); i++) {
00085 if(GetPartDamageFlags(mech, section, i) & WEAP_DAM_EN_CRYSTAL)
00086 wRetMod++;
00087 }
00088
00089 return wRetMod;
00090 }
00091
00092 int getCritSubDamage(MECH * mech, int section, int critical)
00093 {
00094 int wWeapSize = 0;
00095 int wFirstCrit = 0;
00096 int wWeapIndex = 0;
00097 int i;
00098 int wRetMod = 0;
00099
00100 if(MechType(mech) != CLASS_MECH)
00101 return 0;
00102
00103 getWeapData(mech, section, critical, &wWeapIndex, &wWeapSize,
00104 &wFirstCrit);
00105
00106 if(!IsEnergy(wWeapIndex))
00107 return 0;
00108
00109
00110 for(i = wFirstCrit; i < (wFirstCrit + wWeapSize); i++) {
00111 if(GetPartDamageFlags(mech, section, i) & WEAP_DAM_EN_FOCUS)
00112 wRetMod++;
00113 }
00114
00115 return wRetMod;
00116 }
00117
00118 int canWeapExplodeFromDamage(MECH * mech, int section, int critical, int roll)
00119 {
00120 int wWeapSize = 0;
00121 int wFirstCrit = 0;
00122 int wWeapIndex = 0;
00123 int i;
00124 int wExplosionCheck = 0;
00125
00126 if(MechType(mech) != CLASS_MECH)
00127 return 0;
00128
00129 getWeapData(mech, section, critical, &wWeapIndex, &wWeapSize,
00130 &wFirstCrit);
00131
00132
00133 for(i = wFirstCrit; i < (wFirstCrit + wWeapSize); i++) {
00134 if((GetPartDamageFlags(mech, section, i) & WEAP_DAM_EN_CRYSTAL) ||
00135 (GetPartDamageFlags(mech, section, i) & WEAP_DAM_BALL_AMMO) ||
00136 (GetPartDamageFlags(mech, section, i) & WEAP_DAM_MSL_AMMO))
00137 wExplosionCheck++;
00138 }
00139
00140 if(wExplosionCheck > 0)
00141 wExplosionCheck += 1;
00142
00143 return wExplosionCheck >= roll;
00144 }
00145
00146 int canWeapJamFromDamage(MECH * mech, int section, int critical, int roll)
00147 {
00148 int wWeapSize = 0;
00149 int wFirstCrit = 0;
00150 int wWeapIndex = 0;
00151 int i;
00152 int wJamCheck = 0;
00153
00154 if(MechType(mech) != CLASS_MECH)
00155 return 0;
00156
00157 getWeapData(mech, section, critical, &wWeapIndex, &wWeapSize,
00158 &wFirstCrit);
00159
00160
00161 for(i = wFirstCrit; i < (wFirstCrit + wWeapSize); i++) {
00162 if(GetPartDamageFlags(mech, section, i) & WEAP_DAM_BALL_BARREL)
00163 wJamCheck++;
00164 }
00165
00166 if(wJamCheck > 0)
00167 wJamCheck += 1;
00168
00169 return wJamCheck >= roll;
00170 }
00171
00172 int isWeapAmmoFeedLocked(MECH * mech, int section, int critical)
00173 {
00174 int wWeapSize = 0;
00175 int wFirstCrit = 0;
00176 int wWeapIndex = 0;
00177 int i;
00178
00179 if(MechType(mech) != CLASS_MECH)
00180 return 0;
00181
00182 getWeapData(mech, section, critical, &wWeapIndex, &wWeapSize,
00183 &wFirstCrit);
00184
00185
00186 for(i = wFirstCrit; i < (wFirstCrit + wWeapSize); i++) {
00187 if((GetPartDamageFlags(mech, section, i) & WEAP_DAM_BALL_AMMO) ||
00188 (GetPartDamageFlags(mech, section, i) & WEAP_DAM_MSL_AMMO))
00189 return 1;
00190 }
00191
00192 return 0;
00193 }
00194
00195 int countDamagedSlotsFromCrit(MECH * mech, int section, int critical)
00196 {
00197 int wWeapSize = 0;
00198 int wFirstCrit = 0;
00199 int wWeapIndex = 0;
00200
00201 getWeapData(mech, section, critical, &wWeapIndex, &wWeapSize,
00202 &wFirstCrit);
00203
00204 return countDamagedSlots(mech, section, wFirstCrit, wWeapSize);
00205 }
00206
00207 int countDamagedSlots(MECH * mech, int section, int wFirstCrit, int wWeapSize)
00208 {
00209 int wCritsDamaged = 0;
00210 int i;
00211
00212 for(i = wFirstCrit; i < (wFirstCrit + wWeapSize); i++) {
00213 if(PartIsDamaged(mech, section, i))
00214 wCritsDamaged++;
00215 }
00216
00217 return wCritsDamaged;
00218 }
00219
00220 int shouldDestroyWeapon(MECH * mech, int section, int critical,
00221 int incrementCount)
00222 {
00223 int wCritsDamaged = 0;
00224 int wWeapSize = 0;
00225 int wFirstCrit = 0;
00226 int wWeapIndex = 0;
00227
00228 if(MechType(mech) != CLASS_MECH)
00229 return 1;
00230
00231 getWeapData(mech, section, critical, &wWeapIndex, &wWeapSize,
00232 &wFirstCrit);
00233
00234 if(incrementCount)
00235 wCritsDamaged++;
00236
00237 wCritsDamaged += countDamagedSlots(mech, section, wFirstCrit, wWeapSize);
00238
00239 if((wCritsDamaged * 2) > wWeapSize)
00240 return 1;
00241
00242 return 0;
00243 }
00244
00245 void scoreEnhancedWeaponCriticalHit(MECH * mech, MECH * attacker, int LOS,
00246 int section, int critical)
00247 {
00248 int wWeapSize = 0;
00249 int wFirstCrit = 0;
00250 int wWeapIndex = 0;
00251 int wCritRoll = Roll();
00252 int tDestroyWeapon = 0;
00253 int tNoCrit = 0;
00254 int tModerateCrit = 0;
00255
00256 getWeapData(mech, section, critical, &wWeapIndex, &wWeapSize,
00257 &wFirstCrit);
00258
00259
00260 if(shouldDestroyWeapon(mech, section, critical, 1))
00261 tDestroyWeapon = 1;
00262 else {
00263
00264 wCritRoll += countDamagedSlots(mech, section, wFirstCrit, wWeapSize);
00265 wCritRoll++;
00266 }
00267
00268 if(!tDestroyWeapon) {
00269
00270 if(IsEnergy(wWeapIndex)) {
00271 if(wCritRoll <= 3) {
00272 tNoCrit = 1;
00273 } else if(wCritRoll <= 5) {
00274 tModerateCrit = 1;
00275 } else if(wCritRoll <= 7) {
00276 mech_printf(mech, MECHALL,
00277 "Your %s's focusing mechanism gets knocked out of alignment!!",
00278 &MechWeapons[wWeapIndex].name[3]);
00279 GetPartDamageFlags(mech, section, critical) |=
00280 WEAP_DAM_EN_FOCUS;
00281 } else if(wCritRoll <= 9) {
00282 mech_printf(mech, MECHALL,
00283 "Your %s's charging crystal takes a direct hit!!",
00284 &MechWeapons[wWeapIndex].name[3]);
00285 GetPartDamageFlags(mech, section, critical) |=
00286 WEAP_DAM_EN_CRYSTAL;
00287 } else {
00288 tDestroyWeapon = 1;
00289 }
00290 } else if(IsMissile(wWeapIndex)) {
00291 if(wCritRoll <= 3) {
00292 tNoCrit = 1;
00293 } else if(wCritRoll <= 5) {
00294 tModerateCrit = 1;
00295 } else if(wCritRoll <= 7) {
00296 mech_printf(mech, MECHALL,
00297 "Your %s's ranging system takes a hit!!",
00298 &MechWeapons[wWeapIndex].name[3]);
00299 GetPartDamageFlags(mech, section, critical) |=
00300 WEAP_DAM_MSL_RANGING;
00301 } else if(wCritRoll <= 9) {
00302 mech_printf(mech, MECHALL,
00303 "Your %s's ammo feed is damaged!!",
00304 &MechWeapons[wWeapIndex].name[3]);
00305 GetPartDamageFlags(mech, section, critical) |=
00306 WEAP_DAM_MSL_AMMO;
00307 } else {
00308 tDestroyWeapon = 1;
00309 }
00310 } else if(IsBallistic(wWeapIndex) || IsArtillery(wWeapIndex)) {
00311 if(wCritRoll <= 3) {
00312 tNoCrit = 1;
00313 } else if(wCritRoll <= 5) {
00314 tModerateCrit = 1;
00315 } else if(wCritRoll <= 7) {
00316 mech_printf(mech, MECHALL,
00317 "Your %s's barrel warps from the damage!!",
00318 &MechWeapons[wWeapIndex].name[3]);
00319 GetPartDamageFlags(mech, section, critical) |=
00320 WEAP_DAM_BALL_BARREL;
00321 } else if(wCritRoll <= 9) {
00322 mech_printf(mech, MECHALL,
00323 "Your %s's ammo feed is damaged!!",
00324 &MechWeapons[wWeapIndex].name[3]);
00325 GetPartDamageFlags(mech, section, critical) |=
00326 WEAP_DAM_BALL_AMMO;
00327 } else {
00328 tDestroyWeapon = 1;
00329 }
00330 } else {
00331 tDestroyWeapon = 1;
00332 }
00333 }
00334
00335 if(tDestroyWeapon) {
00336 mech_printf(mech, MECHALL, "Your %s has been destroyed!!",
00337 &MechWeapons[wWeapIndex].name[3]);
00338 DestroyWeapon(mech, section, GetPartType(mech, section, critical),
00339 wFirstCrit, 1, wWeapSize);
00340 } else {
00341 DamagePart(mech, section, critical);
00342
00343 if(tNoCrit)
00344 mech_printf(mech, MECHALL,
00345 "Your %s takes a hit but suffers no noticeable damage!!",
00346 &MechWeapons[wWeapIndex].name[3]);
00347 else if(tModerateCrit) {
00348 mech_printf(mech, MECHALL,
00349 "Your %s takes a hit but continues working!!",
00350 &MechWeapons[wWeapIndex].name[3]);
00351 GetPartDamageFlags(mech, section, critical) |= WEAP_DAM_MODERATE;
00352 }
00353 }
00354 }
00355
00356 void mech_weaponstatus(dbref player, MECH * mech, char *buffer)
00357 {
00358 int secIter = 0;
00359 int weapIter = 0;
00360 int wWeapsInSec = 0;
00361 int wcWeaps = 0;
00362 int wDamagedSlots = 0;
00363 unsigned char weaparray[MAX_WEAPS_SECTION];
00364 unsigned char weapdata[MAX_WEAPS_SECTION];
00365 int critical[MAX_WEAPS_SECTION];
00366 char tempbuff[160];
00367 char strLocation[80];
00368 char weapbuff[120];
00369
00370 cch(MECH_USUALSP);
00371
00372 notify(player,
00373 "=========================WEAPON SYSTEMS STATUS=========================");
00374 notify(player,
00375 "[##] -------- Weapon Name -------- || Location -------- || Status -----");
00376
00377 for(secIter = 0; secIter < NUM_SECTIONS; secIter++) {
00378 wWeapsInSec =
00379 FindWeapons(mech, secIter, weaparray, weapdata, critical);
00380
00381 if(wWeapsInSec <= 0)
00382 continue;
00383
00384 ArmorStringFromIndex(secIter, tempbuff, MechType(mech),
00385 MechMove(mech));
00386 sprintf(strLocation, "%-18.18s", tempbuff);
00387
00388 for(weapIter = 0; weapIter < wWeapsInSec; weapIter++) {
00389 sprintf(weapbuff, "[%2d] %-29.29s || ", wcWeaps++,
00390 &MechWeapons[weaparray[weapIter]].name[3]);
00391
00392 strcat(weapbuff, strLocation);
00393 wDamagedSlots = 0;
00394
00395 if(PartIsBroken(mech, secIter, critical[weapIter]) ||
00396 PartTempNuke(mech, secIter,
00397 critical[weapIter]) == FAIL_DESTROYED)
00398 strcat(weapbuff, "|| %ch%cxDESTROYED%c");
00399 else {
00400
00401 if(MechType(mech) == CLASS_MECH)
00402 wDamagedSlots =
00403 countDamagedSlotsFromCrit(mech, secIter,
00404 critical[weapIter]);
00405
00406 if(PartIsDisabled(mech, secIter, critical[weapIter]))
00407 strcat(weapbuff, "|| %crDISABLED%c");
00408 else if(PartTempNuke(mech, secIter, critical[weapIter])) {
00409 switch (PartTempNuke(mech, secIter, critical[weapIter])) {
00410 case FAIL_JAMMED:
00411 strcat(weapbuff, "|| %crJAMMED%c");
00412 break;
00413 case FAIL_SHORTED:
00414 strcat(weapbuff, "|| %crSHORTED%c");
00415 break;
00416 case FAIL_EMPTY:
00417 strcat(weapbuff, "|| %crEMPTY%c");
00418 break;
00419 case FAIL_DUD:
00420 strcat(weapbuff, "|| %crDUD%c");
00421 break;
00422 case FAIL_AMMOJAMMED:
00423 strcat(weapbuff, "|| %crAMMOJAM%c");
00424 break;
00425 }
00426 } else if(wDamagedSlots > 0)
00427 strcat(weapbuff, "|| %cr%chDAMAGED%c");
00428 else
00429 strcat(weapbuff, "|| %cg%chOPERATIONAL%cn");
00430 }
00431
00432 notify(player, weapbuff);
00433
00434 showWeaponDamageAndInfo(player, mech, secIter,
00435 critical[weapIter]);
00436 }
00437 }
00438 }
00439
00440 void showWeaponDamageAndInfo(dbref player, MECH * mech, int section,
00441 int critical)
00442 {
00443 int wWeapSize = 0;
00444 int wFirstCrit = 0;
00445 int wWeapIndex = 0;
00446 int awDamage[3];
00447 int i;
00448 int tHasDamagedPart = 0;
00449 int tPrintSpace = 0;
00450 int wAmmoLoc = GetPartDesiredAmmoLoc(mech, section, critical);
00451 char strLocation[80];
00452 int awNonOpCrits[3];
00453
00454 getWeapData(mech, section, critical, &wWeapIndex, &wWeapSize,
00455 &wFirstCrit);
00456
00457 for(i = 0; i < 3; i++) {
00458 awDamage[i] = 0;
00459 awNonOpCrits[i] = 0;
00460 }
00461
00462 for(i = wFirstCrit; i < (wFirstCrit + wWeapSize); i++) {
00463 if(PartIsDamaged(mech, section, i)) {
00464 tHasDamagedPart = 1;
00465
00466 awDamage[0] +=
00467 GetPartDamageFlags(mech, section, i) & WEAP_DAM_MODERATE;
00468 awDamage[1] +=
00469 ((GetPartDamageFlags(mech, section, i) & WEAP_DAM_EN_FOCUS)
00470 || (GetPartDamageFlags(mech, section,
00471 i) & WEAP_DAM_BALL_BARREL) ||
00472 (GetPartDamageFlags(mech, section,
00473 i) & WEAP_DAM_MSL_RANGING));
00474 awDamage[2] +=
00475 ((GetPartDamageFlags(mech, section,
00476 i) & WEAP_DAM_EN_CRYSTAL) ||
00477 (GetPartDamageFlags(mech, section, i) & WEAP_DAM_BALL_AMMO)
00478 || (GetPartDamageFlags(mech, section,
00479 i) & WEAP_DAM_MSL_AMMO));
00480
00481 awNonOpCrits[0]++;
00482 } else if(PartIsDestroyed(mech, section, i)) {
00483 awNonOpCrits[1]++;
00484 } else if(PartIsDisabled(mech, section, i)) {
00485 awNonOpCrits[2]++;
00486 }
00487 }
00488
00489 if(tHasDamagedPart) {
00490 tPrintSpace = 1;
00491
00492 if(awDamage[0] > 0)
00493 notify_printf(player,
00494 " %%cr%%chGeneral damage (%d hit%s): +%d to hit.",
00495 awDamage[0], awDamage[0] > 1 ? "s" : "",
00496 awDamage[0]);
00497
00498 if(IsEnergy(wWeapIndex)) {
00499 if(awDamage[1] > 0)
00500 notify_printf(player,
00501 " %%cr%%chFocus misalignment (%d hit%s): -%d damage. +%d to hit at >%d hexes.%%c",
00502 awDamage[1], awDamage[1] > 1 ? "s" : "",
00503 awDamage[1], awDamage[1],
00504 MechWeapons[wWeapIndex].shortrange);
00505
00506 if(awDamage[2] > 0)
00507 notify_printf(player,
00508 " %%cr%%chCharging crystal damage (%d hit%s): +%d heat. Explodes on %d or less.%%c",
00509 awDamage[2], awDamage[2] > 1 ? "s" : "",
00510 awDamage[2], awDamage[2] + 1);
00511 } else if(IsMissile(wWeapIndex)) {
00512 if(awDamage[1] > 0)
00513 notify_printf(player,
00514 " %%cr%%chRanging system damage (%d hit%s): +%d to hit at >%d hexes.%%c",
00515 awDamage[1], awDamage[1] > 1 ? "s" : "",
00516 awDamage[1],
00517 MechWeapons[wWeapIndex].shortrange);
00518
00519 if(awDamage[2] > 0)
00520 notify_printf(player,
00521 " %%cr%%chAmmo feed damage (%d hit%s): Can't switch ammo. Explodes on %d or less.%%c",
00522 awDamage[2], awDamage[2] > 1 ? "s" : "",
00523 awDamage[2] + 1);
00524 } else if(IsBallistic(wWeapIndex) || IsArtillery(wWeapIndex)) {
00525 if(awDamage[1] > 0)
00526 notify_printf(player,
00527 " %%cr%%chBarrel damage (%d hit%s): Jams on a %d or less.%%c",
00528 awDamage[1], awDamage[1] > 1 ? "s" : "",
00529 awDamage[1] + 1);
00530
00531 if(awDamage[2] > 0)
00532 notify_printf(player,
00533 " %%cr%%chAmmo feed damage (%d hit%s): Can't switch ammo. Explodes on %d or less.%%c",
00534 awDamage[2], awDamage[2] > 1 ? "s" : "",
00535 awDamage[2] + 1);
00536 }
00537
00538 if((awDamage[0] == 0) && (awDamage[1] == 0) && (awDamage[2] == 0))
00539 notify(player, " %cr%chDamaged, but fully operational.%cn");
00540 tPrintSpace = 1;
00541 }
00542
00543 if(wAmmoLoc >= 0) {
00544 ArmorStringFromIndex(wAmmoLoc, strLocation, MechType(mech),
00545 MechMove(mech));
00546 notify_printf(player, " %%cg%%chPrefered ammo source: %s%%c",
00547 strLocation);
00548 tPrintSpace = 1;
00549 }
00550
00551 if((awNonOpCrits[0] > 0) || (awNonOpCrits[1] > 0) ||
00552 (awNonOpCrits[2] > 0)) {
00553 notify_printf(player,
00554 " %%cr%%chSlot status: Damaged: %d. Destroyed: %d. Disabled: %d%%c",
00555 awNonOpCrits[0], awNonOpCrits[1], awNonOpCrits[2]);
00556 tPrintSpace = 1;
00557 }
00558
00559 if(tPrintSpace)
00560 notify(player, " ");
00561 }