00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "config.h"
00012
00013 #include <stdio.h>
00014 #include <stdlib.h>
00015 #include <math.h>
00016 #include <sys/file.h>
00017
00018 #include "mech.h"
00019 #include "mech.events.h"
00020 #include "p.mech.events.h"
00021 #include "p.mech.ice.h"
00022 #include "p.mech.utils.h"
00023 #include "p.mine.h"
00024 #include "p.bsuit.h"
00025 #include "p.mech.los.h"
00026 #include "p.mech.update.h"
00027 #include "p.mech.physical.h"
00028 #include "p.mech.combat.h"
00029 #include "p.mech.combat.misc.h"
00030 #include "p.mech.damage.h"
00031 #include "p.btechstats.h"
00032 #include "p.mech.hitloc.h"
00033 #include "p.template.h"
00034 #include "p.map.conditions.h"
00035 #include "p.mech.fire.h"
00036 #include "mech.events.h"
00037
00038 struct {
00039 char *name;
00040 char *full;
00041 int ofs;
00042 } lateral_modes[] = {
00043 {
00044 "nw", "Front/Left", 300}, {
00045 "fl", "Front/Left", 300}, {
00046 "ne", "Front/Right", 60}, {
00047 "fr", "Front/Right", 60}, {
00048 "sw", "Rear/Left", 240}, {
00049 "rl", "Rear/Left", 240}, {
00050 "se", "Rear/Right", 120}, {
00051 "rr", "Rear/Right", 120}, {
00052 "-", "None", 0}, {
00053 NULL, 0}
00054 };
00055
00056 const char *LateralDesc(MECH * mech)
00057 {
00058 int i;
00059
00060 for(i = 0; MechLateral(mech) != lateral_modes[i].ofs; i++);
00061 return lateral_modes[i].full;
00062 }
00063
00064 void mech_lateral(dbref player, void *data, char *buffer)
00065 {
00066 MECH *mech = (MECH *) data;
00067 int i;
00068
00069 cch(MECH_USUALO);
00070 #ifndef BT_MOVEMENT_MODES
00071 DOCHECK(MechType(mech) != CLASS_MECH ||
00072 !MechIsQuad(mech),
00073 "Only quadrupeds can alter their lateral movement!");
00074 #else
00075 DOCHECK(!((MechType(mech) == CLASS_MECH && MechIsQuad(mech)) ||
00076 (MechType(mech) == CLASS_VTOL) ||
00077 (MechMove(mech) == MOVE_HOVER)),
00078 "You cannot alter your lateral movement!");
00079 #endif
00080 DOCHECK(CountDestroyedLegs(mech) > 0,
00081 "You need all four legs to use lateral movement!");
00082 skipws(buffer);
00083
00084 for(i = 0; lateral_modes[i].name; i++)
00085 if(!strcasecmp(lateral_modes[i].name, buffer))
00086 break;
00087 DOCHECK(!lateral_modes[i].name, "Invalid mode!");
00088 if(lateral_modes[i].ofs == MechLateral(mech)) {
00089 DOCHECK(!ChangingLateral(mech), "You are going that way already!");
00090 mech_notify(mech, MECHALL, "Lateral mode change aborted.");
00091 StopLateral(mech);
00092 return;
00093 }
00094 mech_printf(mech, MECHALL,
00095 "Wanted lateral movement mode changed to %s.",
00096 lateral_modes[i].full);
00097 StopLateral(mech);
00098 MECHEVENT(mech, EVENT_LATERAL, mech_lateral_event, LATERAL_TICK, i);
00099 }
00100 void mech_turnmode(dbref player, void *data, char *buffer)
00101 {
00102 MECH *mech = (MECH *) data;
00103
00104 if(!GotPilot(mech) || MechPilot(mech) != player) {
00105 notify(player, "You're not the pilot!");
00106 return;
00107 }
00108
00109 if(!HasBoolAdvantage(player, "maneuvering_ace")) {
00110 mech_notify(mech, MECHPILOT, "You're not skilled enough to do that.");
00111 return;
00112 }
00113
00114 if(buffer && !strcasecmp(buffer, "tight")) {
00115 SetTurnMode(mech, 1);
00116 mech_notify(mech, MECHALL, "You brace for tighter turns.");
00117 return;
00118 }
00119 if(buffer && !strcasecmp(buffer, "normal")) {
00120 SetTurnMode(mech, 0);
00121 mech_notify(mech, MECHALL, "You assume a normal turn mode.");
00122 return;
00123 }
00124 mech_printf(mech, MECHALL, "Your turning type is : %s",
00125 GetTurnMode(mech) ? "TIGHT" : "NORMAL");
00126 return;
00127 }
00128
00129 void mech_bootlegger(dbref player, void *data, char *buffer)
00130 {
00131 MECH *mech = (MECH *) data;
00132 float fMinSpeed = (4 * MP1);
00133 int wBTHMod = 0;
00134 int wFallLevels = 0;
00135 int i;
00136 int wHeadingChange = 0;
00137 int wNewHeading;
00138 float fMechSpeed = MechSpeed(mech);
00139 int wMechTons = MechTons(mech);
00140 char strLocation[50];
00141 char *args[1];
00142
00143 cch(MECH_USUALO);
00144
00145 DOCHECK(mech_parseattributes(buffer, args, 1) != 1,
00146 "Invalid number of arguments!");
00147 DOCHECK(CountDestroyedLegs(mech) > 0,
00148 "You can't perform a bootlegger with destroyed legs!");
00149 DOCHECK(fMechSpeed < fMinSpeed,
00150 tprintf
00151 ("You are going too slow to perform a bootlegger! The required minimum speed is %4.1f KPH.",
00152 fMinSpeed));
00153
00154 switch (toupper(args[0][0])) {
00155 case 'R':
00156 wHeadingChange = 90;
00157 break;
00158 case 'L':
00159 wHeadingChange = -90;
00160 break;
00161 }
00162
00163 DOCHECK(wHeadingChange == 0, "Invalid turn direction!");
00164
00165 for(i = 0; i < NUM_SECTIONS; i++) {
00166 if((i == LLEG) || (i == RLEG) || (MechIsQuad(mech) && ((i == LARM)
00167 || (i ==
00168 RARM)))) {
00169 ArmorStringFromIndex(i, strLocation, MechType(mech),
00170 MechMove(mech));
00171
00172 if(SectHasBusyWeap(mech, i)) {
00173 mech_printf(mech, MECHALL,
00174 "You have weapons recycling in your %s.",
00175 strLocation);
00176 return;
00177 }
00178
00179 if(MechSections(mech)[i].recycle) {
00180 mech_printf(mech, MECHALL,
00181 "Your %s is still recovering from its last action.",
00182 strLocation);
00183 return;
00184 }
00185
00186 wBTHMod += MechSections(mech)[i].basetohit;
00187 }
00188 }
00189
00190 if(fMechSpeed <= (4 * MP1)) {
00191 wBTHMod += 0;
00192 } else if(fMechSpeed <= (8 * MP1)) {
00193 wBTHMod += 1;
00194 } else if(fMechSpeed <= (12 * MP1)) {
00195 wBTHMod += 2;
00196 } else {
00197 wBTHMod += 3;
00198 }
00199
00200 if(wMechTons <= 35) {
00201 wBTHMod += 0;
00202 } else if(wMechTons <= 55) {
00203 wBTHMod += 1;
00204 } else if(wMechTons <= 75) {
00205 wBTHMod += 2;
00206 } else {
00207 wBTHMod += 3;
00208 }
00209
00210 wBTHMod += (InWater(mech) ? 2 : 0);
00211
00212 wBTHMod = MAX(wBTHMod, 1);
00213
00214 skipws(buffer);
00215
00216 SendDebug(tprintf
00217 ("#%d attempts to do a bootlegger (mech). Tonnage: %d, Speed: %4.1f, BTHMod: %d",
00218 mech->mynum, wMechTons, fMechSpeed, wBTHMod));
00219
00220 if(MadePilotSkillRoll(mech, wBTHMod)) {
00221 wNewHeading = AcceptableDegree(MechFacing(mech) + wHeadingChange);
00222
00223 SetFacing(mech, wNewHeading);
00224 MechDesiredFacing(mech) = wNewHeading;
00225 MechSpeed(mech) = MechSpeed(mech) / 2;
00226
00227 mech_printf(mech, MECHALL,
00228 "You plant a foot and swivel, changing your heading to %d.",
00229 wNewHeading);
00230
00231 for(i = 0; i < NUM_SECTIONS; i++) {
00232 if((i == LLEG) || (i == RLEG) || (MechIsQuad(mech) &&
00233 ((i == LARM) || (i == RARM))))
00234 SetRecycleLimb(mech, i, 30);
00235 }
00236
00237 } else {
00238 wFallLevels = MAX(wBTHMod, 1);
00239
00240 mech_notify(mech, MECHALL, "You plant a foot and try to swivel...");
00241 mech_notify(mech, MECHALL,
00242 "... but realize a little late that this is harder than it looks!");
00243 MechLOSBroadcast(mech,
00244 "attempts to fight the forces of inertia but looses the battle miserably!");
00245
00246 if(wFallLevels > 2)
00247 MechLOSBroadcast(mech, "tumbles over and over and over!");
00248
00249 MechFalls(mech, wFallLevels, 1);
00250 }
00251 }
00252
00253 void mech_eta(dbref player, void *data, char *buffer)
00254 {
00255 MECH *mech = (MECH *) data;
00256 MAP *mech_map;
00257 int argc, eta_x, eta_y;
00258 float fx, fy, range;
00259 int etahr, etamin;
00260 char *args[3];
00261
00262 cch(MECH_USUAL);
00263 mech_map = getMap(mech->mapindex);
00264 argc = mech_parseattributes(buffer, args, 2);
00265 DOCHECK(argc == 1, "Invalid number of arguments!");
00266 switch (argc) {
00267 case 0:
00268 DOCHECK(!(MechTargX(mech) >= 0 &&
00269 MechTarget(mech) < 0),
00270 "You have invalid default target for ETA!");
00271 eta_x = MechTargX(mech);
00272 eta_y = MechTargY(mech);
00273 break;
00274 case 2:
00275 eta_x = atoi(args[0]);
00276 eta_y = atoi(args[1]);
00277 break;
00278 default:
00279 notify(player, "Invalid arguments!");
00280 return;
00281 }
00282 MapCoordToRealCoord(eta_x, eta_y, &fx, &fy);
00283 range = FindRange(MechFX(mech), MechFY(mech), 0, fx, fy, 0);
00284 if(fabs(MechSpeed(mech)) < 0.1)
00285 mech_printf(mech, MECHALL,
00286 "Range to hex (%d,%d) is %.1f. ETA: Never, mech not moving.",
00287 eta_x, eta_y, range);
00288 else {
00289 etamin = abs(range / (MechSpeed(mech) / KPH_PER_MP));
00290 etahr = etamin / 60;
00291 etamin = etamin % 60;
00292 mech_printf(mech, MECHALL,
00293 "Range to hex (%d,%d) is %.1f. ETA: %.2d:%.2d.",
00294 eta_x, eta_y, range, etahr, etamin);
00295 }
00296 }
00297
00298 float MechCargoMaxSpeed(MECH * mech, float mspeed)
00299 {
00300 int lugged = 0, mod = 2;
00301 MECH *c;
00302 MAP *map;
00303
00304 if(MechCarrying(mech) > 0) {
00305 MECH *t;
00306
00307 if((t = getMech(MechCarrying(mech))))
00308 if(!(MechCritStatus(t) & OWEIGHT_OK))
00309 MechCritStatus(mech) &= ~LOAD_OK;
00310
00311 }
00312
00315 if((MechCritStatus(mech) & LOAD_OK) &&
00316 (MechCritStatus(mech) & OWEIGHT_OK) &&
00317 (MechCritStatus(mech) & SPEED_OK)) {
00318
00319 mspeed = MechRMaxSpeed(mech);
00320 #if 0
00321
00322
00323 if((MechStatus(mech) & MASC_ENABLED) &&
00324 (MechStatus(mech) & SCHARGE_ENABLED))
00325 mspeed = ceil((rint(mspeed / 1.5) / MP1) * 2.5) * MP1;
00326 else if(MechStatus(mech) & MASC_ENABLED)
00327 mspeed *= 4. / 3.;
00328 else if(MechStatus(mech) & SCHARGE_ENABLED)
00329 mspeed *= 4. / 3.;
00330
00331 if(InSpecial(mech) && InGravity(mech))
00332 if((map = FindObjectsData(mech->mapindex)))
00333 mspeed = mspeed * 100 / MAX(50, MapGravity(map));
00334
00335 #else
00336
00337 if(MechStatus(mech) & (MASC_ENABLED | SCHARGE_ENABLED) ||
00338 MechStatus2(mech) & SPRINTING)
00339 mspeed = WalkingSpeed(mspeed) * (1.5 +
00340 (MechStatus(mech) & MASC_ENABLED
00341 ? 0.5 : 0.0) +
00342 (MechStatus(mech) &
00343 SCHARGE_ENABLED ? 0.5 : 0.0) +
00344 (!MoveModeChange(mech)
00345 && MechStatus2(mech) & SPRINTING
00346 ? 0.5 : 0.0));
00347
00348
00349 if(!MoveModeChange(mech) && MechStatus2(mech) & SPRINTING
00350 && HasBoolAdvantage(MechPilot(mech), "speed_demon"))
00351 mspeed += MP1;
00352
00353 if(InSpecial(mech) && InGravity(mech))
00354 if((map = FindObjectsData(mech->mapindex)))
00355 mspeed = mspeed * 100.0 / (float)MAX(50, MapGravity(map));
00356
00357 #endif
00358 return mspeed;
00359 }
00360 MechRTonsV(mech) = get_weight(mech);
00361
00363 if(!(MechCritStatus(mech) & LOAD_OK)) {
00364 if(MechCarrying(mech) > 0)
00365 if((c = getMech(MechCarrying(mech)))) {
00366 lugged = get_weight(c) * 2;
00367 if(MechSpecials(mech) & SALVAGE_TECH)
00368 lugged = lugged / 2;
00369 if((MechSpecials(mech) & TRIPLE_MYOMER_TECH) &&
00370 (MechHeat(mech) >= 9.))
00371 lugged = lugged / 2;
00372
00373 if(MechSpecials2(mech) & CARRIER_TECH)
00374 lugged = lugged / 2;
00375 }
00376
00377 if(MechSpecials(mech) & CARGO_TECH)
00378 mod = 1;
00379
00380 if(MechType(mech) == CLASS_MECH)
00381 mod = mod * 2;
00382
00383 lugged += MechCarriedCargo(mech) * mod / 2;
00384 MechRCTonsV(mech) = lugged;
00385 MechCritStatus(mech) |= LOAD_OK;
00386 }
00387 if(Destroyed(mech))
00388 mspeed = 0.0;
00389 else {
00390 int mv = MechRTonsV(mech);
00391 int sv = MechTons(mech) * 1024;
00392
00393 if(mv == 1 && !Destroyed(mech))
00394 mv = sv;
00395 else {
00396 if(mv > sv)
00397 mv = mv + (mv - sv) / 2;
00398 else
00399 mv = mv + (sv - mv) / 3;
00400 }
00401 if(3 * sv < (MechRCTonsV(mech) + mv))
00402 mspeed = 0.0;
00403 else
00404 #ifdef WEIGHT_OVERSPEEDING
00405 mspeed =
00406 MechMaxSpeed(mech) * MechTons(mech) * 1024.0 / MAX(1024 *
00407 MechRealTons
00408 (mech) +
00409 MechRCTonsV
00410 (mech) / 3,
00411 (MAX
00412 (1024,
00413 mv +
00414 MechRCTonsV
00415 (mech))));
00416 #else
00417 mspeed =
00418 MechMaxSpeed(mech) * MechTons(mech) * 1024.0 / MAX(1024 *
00419 MechTons
00420 (mech) +
00421 MechRCTonsV
00422 (mech) / 3,
00423 (MAX
00424 (1024,
00425 mv +
00426 MechRCTonsV
00427 (mech))));
00428 #endif
00429 }
00430 MechRMaxSpeed(mech) = mspeed;
00431 MechWalkXPFactor(mech) = MAX(1, (int) mspeed / MP1) * 2;
00432 MechCritStatus(mech) |= SPEED_OK;
00433 return MMaxSpeed(mech);
00434 }
00435
00436 void mech_drop(dbref player, void *data, char *buffer)
00437 {
00438 MECH *mech = (MECH *) data;
00439 float s1;
00440 int wDropLevels = 0;
00441 int wDropBTH = 0;
00442 int tHasSwarmers = 0;
00443
00444 cch(MECH_USUAL);
00445 DOCHECK(MechType(mech) == CLASS_BSUIT, "No crawling!");
00446 DOCHECK(MechType(mech) != CLASS_MECH &&
00447 MechType(mech) != CLASS_MW, "You can't prone in this!");
00448 DOCHECK(Fallen(mech), "You are already prone.");
00449 DOCHECK(Jumping(mech) || OODing(mech), "You can't prone in the air!");
00450 DOCHECK(Standing(mech), "You can't drop while trying to stand up!");
00451
00452 s1 = MMaxSpeed(mech) / 3.0;
00453
00454 if((MechType(mech) == CLASS_MECH) && CountSwarmers(mech))
00455 tHasSwarmers = 1;
00456
00457 if(MechType(mech) != CLASS_MW && fabs(MechSpeed(mech)) > s1 * 2) {
00458 mech_notify(mech, MECHALL,
00459 "You attempt a controlled drop while running.");
00460 wDropLevels = 2;
00461 wDropBTH = 2;
00462 } else if(fabs(MechSpeed(mech)) > s1) {
00463 mech_notify(mech, MECHALL,
00464 "You attempt a controlled drop from your fast walk.");
00465 wDropLevels = 1;
00466 }
00467
00468 if(Staggering(mech)) {
00469 mech_notify(mech, MECHALL,
00470 "Still staggering, you try not to fall on your face.");
00471 wDropLevels = (wDropLevels == 0 ? 1 : wDropLevels);
00472 wDropBTH = wDropBTH + StaggerLevel(mech);
00473 }
00474
00475 if(tHasSwarmers)
00476 mech_notify(mech, MECHALL,
00477 "The suits hanging off you make a controlled drop harder!");
00478
00479 if((wDropLevels > 0) || tHasSwarmers) {
00480 if(MadePilotSkillRoll(mech, wDropBTH)) {
00481 mech_notify(mech, MECHALL,
00482 "You hit the ground with minimal damage");
00483 MechLOSBroadcast(mech, "drops to the ground!");
00484
00485 if(tHasSwarmers)
00486 StopBSuitSwarmers(FindObjectsData(mech->mapindex), mech, 0);
00487
00488 } else {
00489 mech_notify(mech, MECHALL, "You fall to the ground hard");
00490 MechLOSBroadcast(mech, "falls hard to the ground!");
00491
00492 if(wDropLevels <= 0)
00493 wDropLevels = 1;
00494
00495 if(tHasSwarmers)
00496 StopBSuitSwarmers(FindObjectsData(mech->mapindex), mech, 0);
00497
00498 MechFalls(mech, wDropLevels, 1);
00499 }
00500 } else {
00501 mech_notify(mech, MECHALL, "You drop to the ground prone!");
00502 MechLOSBroadcast(mech, "drops to the ground!");
00503 }
00504
00505 MakeMechFall(mech);
00506 MechDesiredSpeed(mech) = 0;
00507 MechSpeed(mech) = 0;
00508 MechFloods(mech);
00509 water_extinguish_inferno(mech);
00510
00511 possible_mine_poof(mech, MINE_STEP);
00512 }
00513
00514 void mech_stand(dbref player, void *data, char *buffer)
00515 {
00516 MECH *mech = (MECH *) data;
00517 char *args[2];
00518 int wcDeadLegs = 0;
00519 int tNeedsPSkill = 1;
00520 int tDoStand = 1;
00521 int bth, mechstandtime, standanyway = 0, standcarefulmod = 0;
00522 int i;
00523
00524 cch(MECH_USUAL);
00525 DOCHECK(MechType(mech) == CLASS_BSUIT, "You're standing already!");
00526 DOCHECK(MechType(mech) != CLASS_MECH &&
00527 MechType(mech) != CLASS_MW,
00528 "This vehicle cannot stand like a 'Mech.");
00529 DOCHECK(Jumping(mech), "You're standing while jumping!");
00530 DOCHECK(OODing(mech), "You're standing while flying!");
00531
00532
00533 wcDeadLegs = CountDestroyedLegs(mech);
00534
00535 DOCHECK(((MechIsQuad(mech) && (wcDeadLegs > 3)) || (!MechIsQuad(mech)
00536 && (wcDeadLegs > 1))),
00537 "You have no legs to stand on!");
00538 DOCHECK(wcDeadLegs > 2, "You'd be far too unstable!");
00539 DOCHECK(MechCritStatus(mech) & GYRO_DESTROYED,
00540 "You cannot stand with a destroyed gyro!");
00541
00542 DOCHECK(!Fallen(mech), "You're already standing!");
00543 DOCHECK(Standrecovering(mech),
00544 "You're still recovering from your last attempt!");
00545 DOCHECK(IsHulldown(mech), "You can not stand while hulldown");
00546 DOCHECK(ChangingHulldown(mech),
00547 "You are busy changing your hulldown mode");
00548
00549 bth = MechPilotSkillRoll_BTH(mech, 0);
00550
00551
00552 if(proper_explodearguments(buffer, args, 2)) {
00553 if(strcmp(args[0], "check") == 0) {
00554 notify_printf(player, "Your BTH to stand would be: %d", bth);
00555 for(i = 0; i < 2; i++) {
00556 if(args[i])
00557 free(args[i]);
00558 }
00559 return;
00560 } else if(strcmp(args[0], "anyway") == 0) {
00561 standanyway = 1;
00562 } else if(strcmp(args[0], "careful") == 0) {
00563 standcarefulmod = -2;
00564 } else {
00565 notify(player, "Unknown argument! use 'stand check', "
00566 "'stand anyway', or 'stand careful'");
00567 for(i = 0; i < 2; i++) {
00568 if(args[i])
00569 free(args[i]);
00570 }
00571 return;
00572 }
00573 }
00574
00575 DOCHECK(!standanyway && bth > 12,
00576 "You would fail; use 'stand anyway' if you really want to stand.");
00577
00578 MakeMechStand(mech);
00579
00580
00581 if(((wcDeadLegs == 0) && MechIsQuad(mech)) ||
00582 (MechType(mech) == CLASS_MW)) {
00583 tNeedsPSkill = 0;
00584 }
00585
00586 MechLOSBroadcast(mech, "attempts to stand up.");
00587
00588 if(MechRTerrain(mech) == ICE && MechZ(mech) == -1)
00589 break_thru_ice(mech);
00590
00591 if(tNeedsPSkill) {
00592 if(!MadePilotSkillRoll(mech, standcarefulmod)) {
00593 mech_notify(mech, MECHALL,
00594 "You fail your attempt to stand and fall back on the ground");
00595 MechFalls(mech, 1, 1);
00596 mechstandtime = ((MechType(mech) == CLASS_MW) ?
00597 DROP_TO_STAND_RECYCLE / 3 : StandMechTime(mech));
00598
00599 if(standcarefulmod) {
00600 mechstandtime = MAX(30, mechstandtime * 2);
00601 }
00602 MECHEVENT(mech, EVENT_STANDFAIL, mech_standfail_event,
00603 mechstandtime, 0);
00604 tDoStand = 0;
00605 }
00606 }
00607
00608 if(tDoStand) {
00609
00610 mech_notify(mech, MECHALL, "You begin to stand up.");
00611 mechstandtime = ((MechType(mech) == CLASS_MW) ?
00612 DROP_TO_STAND_RECYCLE / 3 : StandMechTime(mech));
00613
00614 if(standcarefulmod) {
00615 mechstandtime = mechstandtime * 2;
00616 }
00617 MECHEVENT(mech, EVENT_STAND, mech_stand_event, mechstandtime, 0);
00618 }
00619
00620 for(i = 0; i < 2; i++) {
00621 if(args[i])
00622 free(args[i]);
00623 }
00624
00625 }
00626
00627 void mech_land(dbref player, void *data, char *buffer)
00628 {
00629 MECH *mech = (MECH *) data;
00630
00631 cch(MECH_USUAL);
00632 if(MechType(mech) != CLASS_MECH && MechType(mech) != CLASS_MW &&
00633 MechType(mech) != CLASS_BSUIT && MechType(mech) != CLASS_VEH_GROUND) {
00634 aero_land(player, data, buffer);
00635 return;
00636 }
00637 if(Jumping(mech)) {
00638 mech_notify(mech, MECHALL,
00639 "You abort your full jump and attempt to land early");
00640 if(MadePilotSkillRoll(mech, 0)) {
00641 mech_notify(mech, MECHALL, "You are able to abort the jump.");
00642
00643
00644 LandMech(mech);
00645 } else {
00646 mech_notify(mech, MECHALL, "You don't quite make it.");
00647 MechLOSBroadcast(mech,
00648 "attempts a landing, but crashes to the ground!");
00649 MechFalls(mech, 1, 0);
00650 MechDFATarget(mech) = -1;
00651 MechGoingX(mech) = MechGoingY(mech) = 0;
00652 MechSpeed(mech) = 0;
00653 MaybeMove(mech);
00654
00655 }
00656 } else
00657 notify(player, "You're not jumping!");
00658 }
00659
00660
00661 void mech_heading(dbref player, void *data, char *buffer)
00662 {
00663 MECH *mech = (MECH *) data;
00664 char *args[1];
00665 int newheading;
00666
00667 cch(MECH_USUAL);
00668 if(mech_parseattributes(buffer, args, 1) == 1) {
00669 DOCHECK(MechMove(mech) == MOVE_NONE,
00670 "This piece of equipment is stationary!");
00671 DOCHECK(WaterBeast(mech) &&
00672 NotInWater(mech),
00673 "You are regrettably unable to move at this time. We apologize for the inconvenience.");
00674 DOCHECK(is_aero(mech) && Spinning(mech) &&
00675 !Landed(mech),
00676 "You are unable to control your craft at the moment.");
00677 DOCHECK(PerformingAction(mech),
00678 "You are too busy at the moment to turn.");
00679 DOCHECK(MechDugIn(mech),
00680 "You are in a hole you dug, unable to move [use speed cmd to get out].");
00681 DOCHECK(IsHulldown(mech), "You can not turn while hulldown");
00682 DOCHECK(ChangingHulldown(mech),
00683 "You are busy changing your hulldown mode");
00684 if(Digging(mech)) {
00685 mech_notify(mech, MECHALL,
00686 "You cease your attempts at digging in.");
00687 StopDigging(mech);
00688 }
00689 newheading = AcceptableDegree(atoi(args[0]));
00690 MechDesiredFacing(mech) = newheading;
00691 mech_printf(mech, MECHALL, "Heading changed to %d.", newheading);
00692 MaybeMove(mech);
00693 } else {
00694 notify_printf(player, "Your current heading is %i.",
00695 MechFacing(mech));
00696 }
00697 }
00698
00699 void mech_turret(dbref player, void *data, char *buffer)
00700 {
00701 MECH *mech = (MECH *) data;
00702 char *args[1];
00703 int newheading;
00704
00705 cch(MECH_USUALO);
00706 DOCHECK(MechType(mech) == CLASS_MECH || MechType(mech) == CLASS_MW ||
00707 MechType(mech) == CLASS_BSUIT || is_aero(mech) ||
00708 !GetSectInt(mech, TURRET), "You don't have a turret.");
00709 DOCHECK(MechTankCritStatus(mech) & TURRET_JAMMED,
00710 "Your turret is jammed in position.");
00711 DOCHECK(MechTankCritStatus(mech) & TURRET_LOCKED,
00712 "Your turret is locked in position.");
00713 if(mech_parseattributes(buffer, args, 1) == 1) {
00714 newheading = AcceptableDegree(atoi(args[0]) - MechFacing(mech));
00715 MechTurretFacing(mech) = newheading;
00716 mech_printf(mech, MECHALL, "Turret facing changed to %d.",
00717 AcceptableDegree(MechTurretFacing(mech) +
00718 MechFacing(mech)));
00719 } else {
00720 notify_printf(player, "Your turret is currently facing %d.",
00721 AcceptableDegree(MechTurretFacing(mech) +
00722 MechFacing(mech)));
00723 }
00724
00725 MarkForLOSUpdate(mech);
00726 }
00727
00728 void mech_rotatetorso(dbref player, void *data, char *buffer)
00729 {
00730 MECH *mech = (MECH *) data;
00731 char *args[2];
00732
00733 cch(MECH_USUALO);
00734 DOCHECK(MechType(mech) == CLASS_BSUIT, "Huh?");
00735 DOCHECK(MechType(mech) != CLASS_MECH &&
00736 MechType(mech) != CLASS_MW, "You don't have a torso.");
00737 DOCHECK(Fallen(mech),
00738 "You're lying flat on your face, you can't rotate your torso.");
00739 DOCHECK((MechType(mech) == CLASS_MECH) &&
00740 (MechIsQuad(mech)), "Quads can't rotate their torsos.");
00741 if(mech_parseattributes(buffer, args, 2) == 1) {
00742 switch (args[0][0]) {
00743 case 'L':
00744 case 'l':
00745 DOCHECK(MechStatus(mech) & TORSO_LEFT,
00746 "You cannot rotate torso beyond 60 degrees!");
00747 if(MechStatus(mech) & TORSO_RIGHT)
00748 MechStatus(mech) &= ~TORSO_RIGHT;
00749 else
00750 MechStatus(mech) |= TORSO_LEFT;
00751 mech_notify(mech, MECHALL, "You rotate your torso left.");
00752 break;
00753 case 'R':
00754 case 'r':
00755 DOCHECK(MechStatus(mech) & TORSO_RIGHT,
00756 "You cannot rotate torso beyond 60 degrees!");
00757 if(MechStatus(mech) & TORSO_LEFT)
00758 MechStatus(mech) &= ~TORSO_LEFT;
00759 else
00760 MechStatus(mech) |= TORSO_RIGHT;
00761 mech_notify(mech, MECHALL, "You rotate your torso right.");
00762 break;
00763 case 'C':
00764 case 'c':
00765 MechStatus(mech) &= ~(TORSO_RIGHT | TORSO_LEFT);
00766 mech_notify(mech, MECHALL, "You center your torso.");
00767 break;
00768 default:
00769 notify(player, "Rotate must have LEFT RIGHT or CENTER.");
00770 break;
00771 }
00772 } else
00773 notify(player, "Invalid number of arguments!");
00774 MarkForLOSUpdate(mech);
00775 }
00776
00777 struct {
00778 char *name;
00779 int flag;
00780 } speed_tables[] = {
00781 {
00782 "walk", 1}, {
00783 "run", 2}, {
00784 "stop", 0}, {
00785 "back", -1}, {
00786 "cruise", 1}, {
00787 "flank", 2}, {
00788 NULL, 0.0}
00789 };
00790
00791 void mech_speed(dbref player, void *data, char *buffer)
00792 {
00793 MECH *mech = (MECH *) data;
00794 char *args[1];
00795 float newspeed, walkspeed, maxspeed;
00796 int i;
00797
00798 cch(MECH_USUAL);
00799 if(RollingT(mech)) {
00800 DOCHECK(!Landed(mech), "Use thrust command instead!");
00801 } else if(FlyingT(mech)) {
00802 DOCHECK(MechType(mech) != CLASS_VTOL, "Use thrust command instead!");
00803 }
00804 DOCHECK(MechMove(mech) == MOVE_NONE,
00805 "This piece of equipment is stationary!");
00806 DOCHECK(PerformingAction(mech),
00807 "You are too busy at the moment to turn.");
00808 DOCHECK(Standing(mech), "You are currently standing up and cannot move.");
00809 DOCHECK((Fallen(mech)) && (MechType(mech) != CLASS_MECH &&
00810 MechType(mech) != CLASS_MW),
00811 "Your vehicle's movement system is destroyed.");
00812 DOCHECK(Fallen(mech), "You are currently prone and cannot move.");
00813 DOCHECK(WaterBeast(mech) &&
00814 NotInWater(mech),
00815 "You are regrettably unable to move at this time. We apologize for the inconvenience.");
00816
00817 if(MechType(mech) != CLASS_MECH)
00818 DOCHECK(RemovingPods(mech), "You are too busy removing iNARC pods!");
00819 DOCHECK(IsHulldown(mech), "You can not move while hulldown");
00820 DOCHECK(ChangingHulldown(mech),
00821 "You are busy changing your hulldown mode");
00822
00823 if(mech_parseattributes(buffer, args, 1) != 1) {
00824 notify_printf(player, "Your current speed is %.2f.", MechSpeed(mech));
00825 return;
00826 }
00827 DOCHECK(FlyingT(mech) && AeroFuel(mech) <= 0 &&
00828 !AeroFreeFuel(mech), "You're out of fuel!");
00829 maxspeed = MMaxSpeed(mech);
00830
00831 if(MechMove(mech) == MOVE_VTOL)
00832 maxspeed = sqrt((float) maxspeed * maxspeed -
00833 MechVerticalSpeed(mech) * MechVerticalSpeed(mech));
00834
00835 maxspeed = maxspeed > 0.0 ? maxspeed : 0.0;
00836
00837 if((MechHeat(mech) >= 9.) && (MechSpecials(mech) & TRIPLE_MYOMER_TECH))
00838 maxspeed = ceil((rint((maxspeed / 1.5) / MP1) + 1) * 1.5) * MP1;
00839
00840
00841 walkspeed = WalkingSpeed(maxspeed);
00842 newspeed = atof(args[0]);
00843
00844 if(newspeed < 0.1) {
00845
00846
00847 for(i = 0; speed_tables[i].name; i++)
00848 if(!strcasecmp(speed_tables[i].name, args[0])) {
00849 switch (speed_tables[i].flag) {
00850 case 0:
00851 newspeed = 0.0;
00852 break;
00853 case -1:
00854 newspeed = -walkspeed;
00855 break;
00856 case 1:
00857 newspeed = walkspeed;
00858 break;
00859 case 2:
00860 newspeed = maxspeed;
00861 break;
00862 }
00863 break;
00864 }
00865 }
00866
00867 if(newspeed > maxspeed)
00868 newspeed = maxspeed;
00869 if(newspeed < -walkspeed)
00870 newspeed = -walkspeed;
00871
00872 DOCHECK((newspeed < 0) && (MechCarrying(mech) > 0) &&
00873 (!(MechSpecials(mech) & SALVAGE_TECH)),
00874 "You can not backup while towing!");
00875
00876 DOCHECK((newspeed < 0) && Sprinting(mech),
00877 "You can not backup while sprinting!");
00878
00879 if(IsRunning(newspeed, maxspeed)) {
00880 DOCHECK(Dumping(mech), "You can not run while dumping ammo!");
00881 DOCHECK(UnJammingAmmo(mech),
00882 "You can not run while unjamming your weapon!");
00883
00884
00885 if(MechCritStatus(mech) & MECH_STUNNED) {
00886 mech_notify(mech, MECHALL, "You cannot move faster than cruise"
00887 " speed while stunned!");
00888 return;
00889 }
00890
00891 DOCHECK(CrewStunned(mech),
00892 "Your cannot possibly control a vehicle going this fast in your "
00893 "current mental state!");
00894 DOCHECK(MechTankCritStatus(mech) & TAIL_ROTOR_DESTROYED,
00895 "Your cannot possibly control a VTOL going this fast with a destroyed tail rotor!");
00896 DOCHECK(MechType(mech) == CLASS_MECH && ((MechZ(mech) < 0 &&
00897 (MechRTerrain(mech) == WATER
00898 || MechRTerrain(mech) ==
00899 BRIDGE
00900 || MechRTerrain(mech) ==
00901 ICE))
00902 || MechRTerrain(mech) ==
00903 HIGHWATER),
00904 "You can't run through water!");
00905 }
00906 if(!Wizard(player) && In_Character(mech->mynum) &&
00907 MechPilot(mech) != player) {
00908 if(newspeed < 0.0) {
00909 notify(player,
00910 "Not being the Pilot of this beast, you cannot move it backwards.");
00911 return;
00912 } else if(newspeed > walkspeed) {
00913 notify(player,
00914 "Not being the Pilot of this beast, you cannot go faster than walking speed.");
00915 return;
00916 }
00917 }
00918 MechDesiredSpeed(mech) = newspeed;
00919 MaybeMove(mech);
00920 if(fabs(newspeed) > 0.1) {
00921 if(MechSwarmTarget(mech) > 0) {
00922 StopSwarming(mech, 1);
00923 MechCritStatus(mech) &= ~HIDDEN;
00924 }
00925 if(Digging(mech)) {
00926 mech_notify(mech, MECHALL,
00927 "You cease your attempts at digging in.");
00928 StopDigging(mech);
00929 }
00930 MechTankCritStatus(mech) &= ~DUG_IN;
00931 }
00932 mech_printf(mech, MECHALL, "Desired speed changed to %d KPH",
00933 (int) newspeed);
00934 }
00935
00936 void mech_vertical(dbref player, void *data, char *buffer)
00937 {
00938 MECH *mech = (MECH *) data;
00939 char *args[1], buff[50];
00940 float newspeed, maxspeed;
00941
00942 cch(MECH_USUAL);
00943 DOCHECK(MechType(mech) != CLASS_VTOL &&
00944 MechMove(mech) != MOVE_SUB, "This command is for VTOLs only.");
00945 DOCHECK(MechType(mech) == CLASS_VTOL &&
00946 AeroFuel(mech) <= 0
00947 && !AeroFreeFuel(mech), "You're out of fuel!");
00948 DOCHECK(WaterBeast(mech)
00949 && NotInWater(mech),
00950 "You are regrettably unable to move at this time. We apologize for the inconvenience.");
00951 DOCHECK(mech_parseattributes(buffer, args, 1) != 1,
00952 tprintf("Current vertical speed is %.2f KPH.",
00953 (float) MechVerticalSpeed(mech)));
00954 newspeed = atof(args[0]);
00955 maxspeed = MMaxSpeed(mech);
00956 maxspeed =
00957 sqrt((float) maxspeed * maxspeed -
00958 MechDesiredSpeed(mech) * MechDesiredSpeed(mech));
00959 if((newspeed > maxspeed) || (newspeed < -maxspeed)) {
00960 sprintf(buff, "Max vertical speed is + %d KPH and - %d KPH",
00961 (int) maxspeed, (int) maxspeed);
00962 notify(player, buff);
00963 } else {
00964 DOCHECK(Fallen(mech), "Your vehicle's movement system is destroyed.");
00965 DOCHECK(MechType(mech) == CLASS_VTOL &&
00966 Landed(mech), "You need to take off first.");
00967 MechVerticalSpeed(mech) = newspeed;
00968 mech_printf(mech, MECHALL,
00969 "Vertical speed changed to %d KPH", (int) newspeed);
00970 MaybeMove(mech);
00971 }
00972 }
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986 void mech_thrash(dbref player, void *data, char *buffer)
00987 {
00988 MECH *mech = (MECH *) data;
00989 MECH *target;
00990 MAP *map = getMap(mech->mapindex);
00991 int terrain;
00992 int limbs = 4;
00993 int aLimbs[] = { RARM, LARM, LLEG, RLEG };
00994 int i;
00995 int tempLoc;
00996 char locName[50];
00997 int damage, tempDamage;
00998
00999 cch(MECH_USUALO);
01000 DOCHECK(!Fallen(mech), "You need to be prone to thrash!");
01001 DOCHECK(!map, "Invalid map! Contact a wizard!");
01002
01003 terrain = GetRTerrain(map, MechX(mech), MechY(mech));
01004
01005 DOCHECK(!((terrain == GRASSLAND) || (terrain == ROAD) ||
01006 (terrain == BRIDGE)),
01007 "Thrashing only works in clear terrain or on roads or bridges.");
01008
01009
01010 for(i = 0; i < 4; i++) {
01011 tempLoc = aLimbs[i];
01012
01013 if(SectIsDestroyed(mech, tempLoc)) {
01014 limbs--;
01015 continue;
01016 }
01017
01018 ArmorStringFromIndex(tempLoc, locName, MechType(mech),
01019 MechMove(mech));
01020
01021 DOCHECK(SectHasBusyWeap(mech, tempLoc),
01022 tprintf("You have weapons recycling on your %s.", locName));
01023 DOCHECK(MechSections(mech)[tempLoc].recycle,
01024 tprintf("Your %s is still recovering from your last attack.",
01025 locName));
01026 }
01027
01028
01029 if(!limbs) {
01030 mech_notify(mech, MECHALL, "You can't thrash if you have no limbs!");
01031 return;
01032 }
01033 #ifndef REALWEIGHT_DAMAGE
01034 damage = MechTons(mech) / 3;
01035 #else
01036 damage = MechRealTons(mech) / 3;
01037 #endif
01038 damage = (damage * limbs) / 4;
01039
01040 mech_notify(mech, MECHALL,
01041 "You start to flail your arms and legs like a wild man!");
01042 MechLOSBroadcast(mech,
01043 "starts to flail its arms and legs like a wild beast!");
01044
01045
01046 for(i = 0; i < map->first_free; i++) {
01047 if(map->mechsOnMap[i] >= 0) {
01048 target = (MECH *) FindObjectsData(map->mechsOnMap[i]);
01049
01050 if(!target)
01051 continue;
01052
01053 if(MechType(target) != CLASS_BSUIT)
01054 continue;
01055
01056 if(MechTeam(target) == MechTeam(mech))
01057 continue;
01058
01059 if(Jumping(target) || OODing(target))
01060 continue;
01061
01062 if(FaMechRange(mech, target) > 1.0)
01063 continue;
01064
01065 mech_printf(mech, MECHALL, "You manage to hit %s!",
01066 GetMechToMechID(mech, target));
01067 mech_printf(target, MECHALL,
01068 "You get hit by %s's thrashing limbs!",
01069 GetMechToMechID(target, mech));
01070
01071 tempDamage = damage;
01072
01073 while (tempDamage > 0) {
01074 if(tempDamage > 5) {
01075 DamageMech(target, mech, 1, MechPilot(mech), Number(0,
01076 NUM_BSUIT_MEMBERS
01077 - 1),
01078 0, 0, 5, 0, -1, 0, -1, 0, 1);
01079 tempDamage -= 5;
01080 } else {
01081 DamageMech(target, mech, 1, MechPilot(mech), Number(0,
01082 NUM_BSUIT_MEMBERS
01083 - 1),
01084 0, 0, tempDamage, 0, -1, 0, -1, 0, 1);
01085 tempDamage = 0;
01086 }
01087 }
01088 }
01089 }
01090
01091
01092
01093
01094
01095
01096
01097 for(i = 0; i < 4; i++) {
01098 tempLoc = aLimbs[i];
01099
01100 if(SectIsDestroyed(mech, tempLoc))
01101 continue;
01102
01103 SetRecycleLimb(mech, tempLoc, PHYSICAL_RECYCLE_TIME);
01104 }
01105 }
01106
01107 void mech_jump(dbref player, void *data, char *buffer)
01108 {
01109 MECH *mech = (MECH *) data;
01110 MECH *tempMech = NULL;
01111 MAP *mech_map;
01112 char *args[3];
01113 int argc;
01114 int target;
01115 char targetID[2];
01116 short mapx, mapy;
01117 int bearing;
01118 float range = 0.0;
01119 float realx, realy;
01120 int sz, tz, jps;
01121
01122 mech_map = getMap(mech->mapindex);
01123 cch(MECH_USUALO);
01124 #ifdef BT_MOVEMENT_MODES
01125 DOCHECK(MoveModeLock(mech), "Movement modes disallow jumping.");
01126 #endif
01127 DOCHECK(MechType(mech) != CLASS_MECH && MechType(mech) != CLASS_MW &&
01128 MechType(mech) != CLASS_BSUIT &&
01129 MechType(mech) != CLASS_VEH_GROUND, "This unit cannot jump.");
01130 DOCHECK(MechCarrying(mech) > 0, "You can't jump while towing someone!");
01131 DOCHECK((MechMaxSpeed(mech) - MMaxSpeed(mech)) > MP1,
01132 "No, with this cargo you won't!");
01133 DOCHECK(Fallen(mech), "You can't Jump from a FALLEN position");
01134 DOCHECK(IsHulldown(mech), "You can't Jump while hulldown");
01135 DOCHECK(ChangingHulldown(mech),
01136 "You are busy changing your hulldown mode");
01137 DOCHECK(Jumping(mech), "You're already jumping!");
01138 DOCHECK(Stabilizing(mech),
01139 "You haven't stabilized from your last jump yet.");
01140 DOCHECK(Standing(mech), "You haven't finished standing up yet.");
01141 DOCHECK(fabs(MechJumpSpeed(mech)) <= 0.0,
01142 "This mech doesn't have jump jets!");
01143 argc = mech_parseattributes(buffer, args, 3);
01144 DOCHECK(Dumping(mech), "You can not jump while dumping ammo!");
01145 DOCHECK(UnJammingAmmo(mech),
01146 "You can not jump while unjamming your weapon!");
01147 DOCHECK(RemovingPods(mech), "You are too busy removing iNARC pods!");
01148 DOCHECK(MapIsUnderground(mech_map),
01149 "Realize the ceiling in this grotto is a bit to low for that!");
01150 DOCHECK(OODing(mech), "You can't jump while orbital dropping!");
01151
01152 if(Staggering(mech)) {
01153 mech_notify(mech, MECHALL,
01154 "The damage inhibits your coordination...");
01155
01156 if(!MadePilotSkillRoll(mech, calcStaggerBTHMod(mech))) {
01157 mech_notify(mech, MECHALL,
01158 "... something you apparently can't handle!");
01159 MechLOSBroadcast(mech,
01160 "engages jumpjets, rolls to the side and slams into the ground!");
01161 MechFalls(mech, 1, 0);
01162 return;
01163 }
01164 }
01165
01166 if(doJettisonChecks(mech))
01167 return;
01168
01169 DOCHECK(argc > 2, "Too many arguments to JUMP function!");
01170 MechStatus(mech) &= ~DFA_ATTACK;
01171 switch (argc) {
01172 case 0:
01173
01174
01175 DOCHECK(MechType(mech) != CLASS_MECH,
01176 "Only mechs can do Death From Above attacks!");
01177
01178 target = MechTarget(mech);
01179 tempMech = getMech(target);
01180 DOCHECK(!tempMech, "Invalid Target!");
01181 range = FaMechRange(mech, tempMech);
01182 DOCHECK(!InLineOfSight(mech, tempMech, MechX(tempMech),
01183 MechY(tempMech), range),
01184 "Target is not in line of sight!");
01185 DOCHECK(MechType(tempMech) == CLASS_MW,
01186 "Even you can't aim your jump well enough to squish that!");
01187 mapx = MechX(tempMech);
01188 mapy = MechY(tempMech);
01189 MechDFATarget(mech) = MechTarget(mech);
01190 break;
01191 case 1:
01192
01193 DOCHECK(MechType(mech) != CLASS_MECH,
01194 "Only mechs can do Death From Above attacks!");
01195
01196 targetID[0] = args[0][0];
01197 targetID[1] = args[0][1];
01198 target = FindTargetDBREFFromMapNumber(mech, targetID);
01199 tempMech = getMech(target);
01200 DOCHECK(!tempMech, "Target is not in line of sight!");
01201 range = FaMechRange(mech, tempMech);
01202 DOCHECK(!InLineOfSight(mech, tempMech, MechX(tempMech),
01203 MechY(tempMech), range),
01204 "Target is not in line of sight!");
01205 DOCHECK(MechType(tempMech) == CLASS_MW,
01206 "Even you can't aim your jump well enough to squish that!");
01207 mapx = MechX(tempMech);
01208 mapy = MechY(tempMech);
01209 MechDFATarget(mech) = tempMech->mynum;
01210 break;
01211 case 2:
01212 bearing = atoi(args[0]);
01213 range = atof(args[1]);
01214 FindXY(MechFX(mech), MechFY(mech), bearing, range, &realx, &realy);
01215
01216
01217
01218 RealCoordToMapCoord(&mapx, &mapy, realx, realy);
01219 break;
01220 }
01221 DOCHECK(mapx >= mech_map->map_width || mapy >= mech_map->map_height ||
01222 mapx < 0 || mapy < 0, "That would take you off the map!");
01223 DOCHECK(MechX(mech) == mapx &&
01224 MechY(mech) == mapy, "You're already in the target hex.");
01225 sz = MechZ(mech);
01226 if(GetRTerrain(mech_map, mapx, mapy) == ICE)
01227 tz = 0;
01228 else
01229 tz = Elevation(mech_map, mapx, mapy);
01230 jps = JumpSpeedMP(mech, mech_map);
01231 DOCHECK(range > jps, "That target is out of range!");
01232 if(MechType(mech) != CLASS_BSUIT && tempMech)
01233 MechStatus(mech) |= DFA_ATTACK;
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243 MechJumpTop(mech) = MIN(jps + 1 - range / 3, 2 * range + 2);
01244 DOCHECK((tz - sz) > jps,
01245 "That target's high for you to reach with a single jump!");
01246 DOCHECK((sz - tz) > jps,
01247 "That target's low for you to reach with a single jump!");
01248 DOCHECK(sz < -1, "Glub glub glub.");
01249 MapCoordToRealCoord(mapx, mapy, &realx, &realy);
01250 bearing = FindBearing(MechFX(mech), MechFY(mech), realx, realy);
01251
01252
01253 MechCocoon(mech) = 0;
01254 MechJumpHeading(mech) = bearing;
01255 MechStatus(mech) |= JUMPING;
01256 MechStartFX(mech) = MechFX(mech);
01257 MechStartFY(mech) = MechFY(mech);
01258 MechStartFZ(mech) = MechFZ(mech);
01259 MechJumpLength(mech) =
01260 length_hypotenuse((double) (realx - MechStartFX(mech)),
01261 (double) (realy - MechStartFY(mech)));
01262 MechGoingX(mech) = mapx;
01263 MechGoingY(mech) = mapy;
01264 MechEndFZ(mech) = ZSCALE * tz;
01265 MechSpeed(mech) = 0.0;
01266 if(MechStatus(mech) & DFA_ATTACK)
01267 mech_notify(mech, MECHALL,
01268 "You engage your jump jets for a Death From Above attack!");
01269 else
01270 mech_notify(mech, MECHALL, "You engage your jump jets.");
01271 MechSwarmTarget(mech) = -1;
01272 MechLOSBroadcast(mech, "engages jumpjets!");
01273 MECHEVENT(mech, EVENT_JUMP, mech_jump_event, JUMP_TICK, 0);
01274 }
01275
01276 static void mech_hulldown_event(MUXEVENT * e)
01277 {
01278 MECH *mech = (MECH *) e->data;
01279 int type = (int) e->data2;
01280
01281 if(!ChangingHulldown(mech))
01282 return;
01283
01284 if(!Started(mech))
01285 return;
01286
01287 if(type == 0) {
01288 MechStatus(mech) &= ~HULLDOWN;
01289 mech_notify(mech, MECHALL, "You finish lifting yourself up.");
01290 MechLOSBroadcast(mech, "finishes lifting itself up");
01291 } else {
01292 MechStatus(mech) |= HULLDOWN;
01293 mech_notify(mech, MECHALL,
01294 "You finish lowering yourself to the ground.");
01295 MechLOSBroadcast(mech, "finishes lowering itself to the ground.");
01296 }
01297 }
01298
01299 #ifdef BT_MOVEMENT_MODES
01300 void mech_sprint(dbref player, void *data, char *buffer)
01301 {
01302 MECH *mech = (MECH *) data;
01303 int d = 0, i;
01304
01305 cch(MECH_USUALO);
01306 DOCHECK(OODing(mech), "While falling out of the sky?");
01307 DOCHECK(MechMove(mech) == MOVE_NONE,
01308 "This piece of equipment is stationary!");
01309 DOCHECK(MechCarrying(mech) > 0, "You cannot sprint while towing!");
01310 DOCHECK(Standing(mech), "You are currently standing up and cannot move.");
01311 DOCHECK(Jumping(mech), "You cannot do this while jumping.");
01312 DOCHECK((Fallen(mech)) && (MechType(mech) != CLASS_MECH &&
01313 MechType(mech) != CLASS_MW),
01314 "Your vehicle's movement system is destroyed.");
01315 DOCHECK(Fallen(mech), "You are currently prone and cannot move.");
01316 DOCHECK(WaterBeast(mech) &&
01317 NotInWater(mech),
01318 "You are regrettably unable to move at this time. We apologize for the inconvenience.");
01319 DOCHECK(MoveModeChange(mech), "You are already changing movement modes!");
01320 DOCHECK(MechStatus2(mech) & (EVADING | DODGING),
01321 "You cannot perform multiple movement modes!");
01322 DOCHECK(MechSwarmTarget(mech) > 0, "You cannot sprint while mounted!");
01323 if(MechType(mech) == CLASS_MECH)
01324 DOCHECK(SectIsDestroyed(mech, RLEG) || SectIsDestroyed(mech, LLEG)
01325 || (MechMove(mech) !=
01326 MOVE_QUAD ? 0 : SectIsDestroyed(mech, RLEG)
01327 || SectIsDestroyed(mech, LLEG)),
01328 "That's kind of hard while limping.");
01329
01330 d |= MODE_SPRINT | ((MechStatus2(mech) & SPRINTING) ? MODE_OFF : MODE_ON);
01331 if(d & MODE_ON) {
01332 if((i = MechFullNoRecycle(mech, CHECK_BOTH)) > 0) {
01333 mech_printf(mech, MECHALL, "You have %s recycling!",
01334 (i == 1 ? "weapons" : i == 2 ? "limbs" : "error"));
01335 return;
01336 }
01337 mech_notify(mech, MECHALL, "You begin the process of sprinting.....");
01338 MECHEVENT(mech, EVENT_MOVEMODE, mech_movemode_event,
01339 (MechType(mech) == CLASS_BSUIT
01340 || MechType(mech) == CLASS_MW) ? TURN / 2 : TURN, d);
01341 } else {
01342 mech_notify(mech, MECHALL,
01343 "You begin the process of ceasing to sprint.");
01344 MECHEVENT(mech, EVENT_MOVEMODE, mech_movemode_event,
01345 (MechType(mech) == CLASS_BSUIT
01346 || MechType(mech) == CLASS_MW) ? TURN / 2 : TURN, d);
01347 }
01348 return;
01349 }
01350
01351 void mech_evade(dbref player, void *data, char *buffer)
01352 {
01353 MECH *mech = (MECH *) data;
01354 int d = 0, i;
01355
01356 cch(MECH_USUALO);
01357 DOCHECK(OODing(mech), "While falling out of the sky?");
01358 DOCHECK(MechMove(mech) == MOVE_NONE,
01359 "This piece of equipment is stationary!");
01360 DOCHECK(Standing(mech), "You are currently standing up and cannot move.");
01361 DOCHECK(Jumping(mech), "You cannot do this while jumping.");
01362 DOCHECK((Fallen(mech))
01363 && (MechType(mech) != CLASS_MECH
01364 && MechType(mech) != CLASS_MW),
01365 "Your vehicle's movement system is destroyed.");
01366 DOCHECK(MechCarrying(mech) > 0, "You can't do that while towing");
01367 DOCHECK(Fallen(mech), "You are currently prone and cannot move.");
01368 DOCHECK(!(MechStatus2(mech) & EVADING) && MechType(mech) == CLASS_MECH
01369 && (PartIsNonfunctional(mech, LLEG, 0)
01370 || PartIsNonfunctional(mech, RLEG, 0)),
01371 "You need both hips functional to evade.");
01372 DOCHECK(WaterBeast(mech)
01373 && NotInWater(mech),
01374 "You are regrettably unable to move at this time. We apologize for the inconvenience.");
01375 DOCHECK(MoveModeChange(mech), "You are already changing movement modes!");
01376 DOCHECK(MechStatus2(mech) & (SPRINTING | DODGING),
01377 "You cannot perform multiple movement modes!");
01378 DOCHECK(MechSwarmTarget(mech) > 0, "You cannot evade while mounted!");
01379 if(MechType(mech) == CLASS_MECH)
01380 DOCHECK(SectIsDestroyed(mech, RLEG) || SectIsDestroyed(mech, LLEG)
01381 || (MechMove(mech) !=
01382 MOVE_QUAD ? 0 : SectIsDestroyed(mech, RLEG)
01383 || SectIsDestroyed(mech, LLEG)),
01384 "That's kind of hard while limping.");
01385
01386 d |= MODE_EVADE | ((MechStatus2(mech) & EVADING) ? MODE_OFF : MODE_ON);
01387 if(d & MODE_ON) {
01388 if((i = MechFullNoRecycle(mech, CHECK_BOTH)) > 0) {
01389 mech_printf(mech, MECHALL, "You have %s recycling!",
01390 (i == 1 ? "weapons" : i == 2 ? "limbs" : "error"));
01391 return;
01392 }
01393 mech_notify(mech, MECHALL, "You begin the process of evading.....");
01394 MECHEVENT(mech, EVENT_MOVEMODE, mech_movemode_event,
01395 (MechType(mech) == CLASS_BSUIT
01396 || MechType(mech) == CLASS_MW) ? TURN / 2 : TURN, d);
01397 } else {
01398 mech_notify(mech, MECHALL,
01399 "You begin the process of ceasing to evade.");
01400 MECHEVENT(mech, EVENT_MOVEMODE, mech_movemode_event,
01401 (MechType(mech) == CLASS_BSUIT
01402 || MechType(mech) == CLASS_MW) ? TURN / 2 : TURN, d);
01403 }
01404 return;
01405 }
01406
01407 void mech_dodge(dbref player, void *data, char *buffer)
01408 {
01409 MECH *mech = (MECH *) data;
01410 int d = 0, i;
01411
01412 cch(MECH_USUALO);
01413 DOCHECK(OODing(mech), "While falling out of the sky?");
01414 DOCHECK(MechMove(mech) == MOVE_NONE,
01415 "This piece of equipment is stationary!");
01416 DOCHECK(Standing(mech), "You are currently standing up and cannot move.");
01417 DOCHECK((Fallen(mech)) && (MechType(mech) != CLASS_MECH &&
01418 MechType(mech) != CLASS_MW),
01419 "Your vehicle's movement system is destroyed.");
01420 DOCHECK(Fallen(mech), "You are currently prone and cannot move.");
01421 DOCHECK(WaterBeast(mech) &&
01422 NotInWater(mech),
01423 "You are regrettably unable to move at this time. We apologize for the inconvenience.");
01424 DOCHECK(MoveModeChange(mech), "You are already changing movement modes!");
01425 DOCHECK(MechStatus2(mech) & (SPRINTING | EVADING),
01426 "You cannot perform multiple movement modes!");
01427 DOCHECK(!(HasBoolAdvantage(player, "dodge_maneuver"))
01428 || player != MechPilot(mech),
01429 "You either are not the pilot of this mech, have no Dodge Maneuver adavantage, or both.");
01430 d |= MODE_DODGE | ((MechStatus2(mech) & DODGING) ? MODE_OFF : MODE_ON);
01431 if(d & MODE_ON) {
01432 if((i = MechFullNoRecycle(mech, CHECK_PHYS)) > 0) {
01433 mech_printf(mech, MECHALL, "You have %s recycling!",
01434 (i == 1 ? "weapons" : i == 2 ? "limbs" : "error"));
01435 return;
01436 }
01437 mech_notify(mech, MECHALL, "You begin the process of dodging.....");
01438 MECHEVENT(mech, EVENT_MOVEMODE, mech_movemode_event, 1, d);
01439 } else {
01440 mech_notify(mech, MECHALL,
01441 "You begin the process of ceasing to dodge.");
01442 MECHEVENT(mech, EVENT_MOVEMODE, mech_movemode_event, TURN, d);
01443 }
01444 return;
01445 }
01446 #endif
01447
01448 void mech_hulldown(dbref player, void *data, char *buffer)
01449 {
01450 MECH *mech = (MECH *) data;
01451 char *args[1];
01452 int argc;
01453
01454 cch(MECH_USUALO);
01455
01456 DOCHECK(OODing(mech), "While falling out of the sky?");
01457 DOCHECK(!MechIsQuad(mech), "Only QUADs can hulldown.");
01458 DOCHECK(Fallen(mech), "You can't hulldown from a FALLEN position");
01459 DOCHECK(Jumping(mech), "You can't hulldown while jumping!");
01460 DOCHECK(MechSpeed(mech) > 0.5, "You can't hulldown while moving!");
01461 DOCHECK(Stabilizing(mech),
01462 "You are still stabilizing from your last jump.");
01463 DOCHECK(Standing(mech), "You haven't finished standing up yet.");
01464
01465 argc = mech_parseattributes(buffer, args, 1);
01466
01467 if(argc > 0) {
01468 if(!strcmp(args[0], "-")) {
01469 if(!IsHulldown(mech))
01470 mech_notify(mech, MECHALL, "You are not hulldown.");
01471 else if(ChangingHulldown(mech))
01472 mech_notify(mech, MECHALL,
01473 "You are busy changing your hulldown mode.");
01474 else {
01475 mech_notify(mech, MECHALL, "You start to lift yourself up.");
01476 MechLOSBroadcast(mech, "begins to raise up on its legs.");
01477
01478 MECHEVENT(mech, EVENT_CHANGING_HULLDOWN,
01479 mech_hulldown_event, StandMechTime(mech), 0);
01480 }
01481 } else if(!strcasecmp(args[0], "stop")) {
01482 if(!ChangingHulldown(mech))
01483 mech_notify(mech, MECHALL,
01484 "You are not currently changing your hulldown mode.");
01485 else {
01486 StopHullDown(mech);
01487 mech_notify(mech, MECHALL,
01488 "You stop changing your hulldown mode.");
01489 }
01490 } else
01491 mech_notify(mech, MECHALL, "Invalid argument for 'hulldown'.");
01492
01493 return;
01494 }
01495
01496 DOCHECK(IsHulldown(mech), "You are already hulldown.");
01497 DOCHECK(ChangingHulldown(mech),
01498 "You are busy changing your hulldown mode.");
01499
01500 mech_notify(mech, MECHALL, "You start to lower yourself to the ground.");
01501 MechLOSBroadcast(mech, "begins to lower itself to the ground.");
01502 MechDesiredSpeed(mech) = 0;
01503
01504 MECHEVENT(mech, EVENT_CHANGING_HULLDOWN, mech_hulldown_event,
01505 StandMechTime(mech), 1);
01506 }
01507
01508 int DropGetElevation(MECH * mech)
01509 {
01510 if(MechRTerrain(mech) == BRIDGE) {
01511 if(MechZ(mech) < (MechElev(mech))) {
01512 if(Overwater(mech))
01513 return 0;
01514 return bridge_w_elevation(mech);
01515 }
01516 return MechElevation(mech);
01517 }
01518 if(Overwater(mech) || (MechRTerrain(mech) == ICE && MechZ(mech) >= 0))
01519 return MAX(0, MechElevation(mech));
01520 else
01521 return MechElevation(mech);
01522 }
01523
01524 void DropSetElevation(MECH * mech, int wantdrop)
01525 {
01526 if(MechRTerrain(mech) == BRIDGE) {
01527 bridge_set_elevation(mech);
01528 return;
01529 }
01530 MechZ(mech) = DropGetElevation(mech);
01531 MechFZ(mech) = MechZ(mech) * ZSCALE;
01532 if(wantdrop)
01533 if(MechRTerrain(mech) == ICE && MechZ(mech) >= 0)
01534 possibly_drop_thru_ice(mech);
01535 }
01536
01537 void LandMech(MECH * mech)
01538 {
01539 MECH *target;
01540 MAP *mech_map = getMap(mech->mapindex);
01541 int dfa = 0;
01542 int done = 0;
01543
01544
01545
01546
01547
01548
01549
01550 if(Uncon(mech)) {
01551 mech_notify(mech, MECHALL,
01552 "Your lack of conciousness makes you fall to the ground. Not like you can read this anyway.");
01553 MechFalls(mech, 1, 0);
01554 dfa = 1;
01555 done = 1;
01556 } else {
01557
01558 if(MechStatus(mech) & DFA_ATTACK) {
01559
01560 target = getMech(MechDFATarget(mech));
01561 if(target) {
01562 if(MechX(target) == MechX(mech) &&
01563 MechY(target) == MechY(mech))
01564 dfa = DeathFromAbove(mech, target);
01565 else
01566 mech_notify(mech, MECHPILOT,
01567 "Your DFA target has moved!");
01568 } else
01569 mech_notify(mech, MECHPILOT,
01570 "Your target has become invalid.");
01571 }
01572
01573 if(!dfa)
01574 mech_notify(mech, MECHALL, "You finish your jump.");
01575
01576
01577 MechElev(mech) = GetElev(mech_map, MechX(mech), MechY(mech));
01578 MechZ(mech) = MechElev(mech) - 1;
01579 MechFZ(mech) = ZSCALE * MechZ(mech);
01580 DropSetElevation(mech, 1);
01581
01582 if(Staggering(mech)) {
01583 mech_notify(mech, MECHALL,
01584 "The damage you've taken makes the landing a bit harder...");
01585
01586 if(!MadePilotSkillRoll(mech, calcStaggerBTHMod(mech))) {
01587 mech_notify(mech, MECHALL,
01588 "... something you apparently can't handle!");
01589 MechLOSBroadcast(mech, "lands, staggers, and falls down!");
01590 MechFalls(mech, 1, 0);
01591 return;
01592 }
01593 }
01594
01595
01596 if(MechType(mech) == CLASS_MECH) {
01597 if(CountDestroyedLegs(mech) > 0) {
01598 mech_notify(mech, MECHPILOT,
01599 "Your missing leg makes it harder to land");
01600 if(!MadePilotSkillRoll(mech, 0)) {
01601 mech_notify(mech, MECHALL,
01602 "Your missing leg has caused you to fall upon landing!");
01603 MechLOSBroadcast(mech,
01604 "lands, unbalanced, and falls down!");
01605 dfa = 1;
01606 MechFalls(mech, 1, 0);
01607 done = 1;
01608 }
01609 } else if(MechSections(mech)[RLEG].basetohit ||
01610 MechSections(mech)[LLEG].basetohit) {
01611 mech_notify(mech, MECHPILOT,
01612 "Your damaged leg actuators make it harder to land");
01613 if(!MadePilotSkillRoll(mech, 0)) {
01614 mech_notify(mech, MECHALL,
01615 "Your damaged leg actuators have caused you to fall upon landing!");
01616 MechLOSBroadcast(mech,
01617 "lands, stumbles, and falls down!");
01618 dfa = 1;
01619 done = 1;
01620 MechFalls(mech, 1, 0);
01621 }
01622 } else if((MechCritStatus(mech) & GYRO_DAMAGED) || (MechCritStatus(mech) & GYRO_DESTROYED)) {
01623 mech_notify(mech, MECHPILOT, "Your damaged gyro makes it harder to land");
01624 if(!MadePilotSkillRoll(mech, 0)) {
01625 mech_notify(mech, MECHALL,
01626 "Your damaged gyro has caused you to fall upon landing!");
01627 MechLOSBroadcast(mech,
01628 "lands, twists awkwardly, and falls down!");
01629 dfa = 1;
01630 done = 1;
01631 MechFalls(mech,1,0);
01632 }
01633 }
01634 }
01635 }
01636
01637 if((MechType(mech) == CLASS_MECH) && CountSwarmers(mech)) {
01638 mech_notify(mech, MECHALL,
01639 "The suits hanging off you make landing harder!");
01640
01641 if(MadePilotSkillRoll(mech, 4)) {
01642 StopBSuitSwarmers(FindObjectsData(mech->mapindex), mech, 0);
01643 } else {
01644 mech_notify(mech, MECHALL,
01645 "You fail to properly control your unbalanced landing!");
01646 MechLOSBroadcast(mech,
01647 "lands and crashes to the ground from the weight of the battlesuits!");
01648 MechFalls(mech, 1, 0);
01649 }
01650 }
01651
01652 if(!dfa && !Fallen(mech) && !domino_space(mech, 1)) {
01653 if(MechType(mech) != CLASS_VEH_GROUND)
01654 MechLOSBroadcast(mech, "lands gracefully.");
01655 else
01656 MechLOSBroadcast(mech, "returns to the ground where it belongs.");
01657 }
01658
01659
01660
01661 if(Jumping(mech))
01662 MECHEVENT(mech, EVENT_JUMPSTABIL, mech_stabilizing_event,
01663 JUMP_TO_HIT_RECYCLE, 0);
01664 MechStatus(mech) &= ~JUMPING;
01665 MechStatus(mech) &= ~DFA_ATTACK;
01666 MechDFATarget(mech) = -1;
01667 MechGoingX(mech) = MechGoingY(mech) = 0;
01668 MechSpeed(mech) = 0;
01669 StopJump(mech);
01670 MaybeMove(mech);
01671
01672
01673 if(!done)
01674 possible_mine_poof(mech, MINE_LAND);
01675
01676 MechFloods(mech);
01677 water_extinguish_inferno(mech);
01678 StopStaggerCheck(mech);
01679 }
01680
01681
01682
01683
01684
01685 void MechFloodsLoc(MECH * mech, int loc, int lev)
01686 {
01687 char locbuff[32];;
01688
01689 if(MechStatus(mech) & COMBAT_SAFE)
01690 return;
01691
01692 if((GetSectArmor(mech, loc) && (GetSectRArmor(mech, loc) ||
01693 !GetSectORArmor(mech, loc)))
01694 || !GetSectInt(mech, loc))
01695 return;
01696 if(!InWater(mech))
01697 return;
01698 if(lev >= 0)
01699 return;
01700
01701 if(lev == -1 && (!Fallen(mech) && loc != LLEG && loc != RLEG &&
01702 (!MechIsQuad(mech) || (loc != LARM && loc != RARM))))
01703 return;
01704 if(MechType(mech) != CLASS_MECH)
01705 return;
01706
01707 if(SectIsFlooded(mech, loc))
01708 return;
01709
01710
01711 ArmorStringFromIndex(loc, locbuff, MechType(mech), MechMove(mech));
01712 mech_printf(mech, MECHALL,
01713 "%%ch%%crWater floods into your %s disabling everything that was there!%%c",
01714 locbuff);
01715 MechLOSBroadcast(mech,
01716 tprintf("has a gaping hole in %s, and water pours in!",
01717 locbuff));
01718
01719 SetSectFlooded(mech, loc);
01720 DestroyParts(mech, mech, loc, 1, 1);
01721
01722 }
01723
01724 void MechFloods(MECH * mech)
01725 {
01726 int i;
01727 int elev = MechElevation(mech);
01728
01729 if(!InWater(mech))
01730 return;
01731
01732
01733 if(MechSpecials2(mech) & WATERPROOF_TECH)
01734 return;
01735
01736 if(MechType(mech) == CLASS_BSUIT) {
01737
01738 if(MechSwarmTarget(mech) > 0)
01739 return;
01740
01741 mech_notify(mech, MECHALL,
01742 "You somehow find yourself in water and realize this may really really suck...");
01743 mech_notify(mech, MECHALL,
01744 "Everything gets very dark as water starts to fill your suit "
01745 "and you sink towards the bottom!");
01746
01747 MechLOSBroadcast(mech,
01748 "shudders, splashes in the water for a second, then goes limp "
01749 "and sinks to the bottom.");
01750
01751 KillMechContentsIfIC(mech->mynum);
01752 DestroyMech(mech, mech, 0);
01753 return;
01754 }
01755
01756 if(MechType(mech) != CLASS_MECH)
01757 return;
01758
01759 if(MechZ(mech) >= 0)
01760 return;
01761
01762 for(i = 0; i < NUM_SECTIONS; i++)
01763 MechFloodsLoc(mech, i, elev);
01764 }
01765
01766 void MechFalls(MECH * mech, int levels, int seemsg)
01767 {
01768 int roll, spread, i, hitloc, hitGroup = 0;
01769 int isrear = 0, damage, iscritical = 0;
01770 MAP *map;
01771
01772
01773 if(CountSwarmers(mech))
01774 StopBSuitSwarmers(FindObjectsData(mech->mapindex), mech, 0);
01775
01776
01777 MechCocoon(mech) = 0;
01778 if(MechType(mech) == CLASS_MECH || MechType(mech) == CLASS_MW || seemsg)
01779 mech_notify(mech, MECHPILOT,
01780 "You try to avoid taking damage in the fall.");
01781 else
01782 mech_notify(mech, MECHPILOT, "You try to avoid taking damage.");
01783 if(!MadePilotSkillRoll(mech, levels)) {
01784 if(MechType(mech) == CLASS_MECH || MechType(mech) == CLASS_MW ||
01785 seemsg)
01786 mech_notify(mech, MECHPILOT,
01787 "You take personal injury from the fall!");
01788 else
01789 mech_notify(mech, MECHPILOT, "You take personal injury!");
01790 headhitmwdamage(mech, mech, 1);
01791 }
01792 MechSpeed(mech) = 0;
01793 MechDesiredSpeed(mech) = 0;
01794 if(Jumping(mech)) {
01795 MechStatus(mech) &= ~JUMPING;
01796 MechStatus(mech) &= ~DFA_ATTACK;
01797 StopJump(mech);
01798 MECHEVENT(mech, EVENT_JUMPSTABIL, mech_stabilizing_event,
01799 JUMP_TO_HIT_RECYCLE, 0);
01800 }
01801 #ifdef BT_MOVEMENT_MODES
01802 if(MoveModeChange(mech))
01803 StopMoveMode(mech);
01804 if(MechStatus2(mech) & SPRINTING)
01805 MECHEVENT(mech, EVENT_MOVEMODE, mech_movemode_event,
01806 (MechType(mech) == CLASS_BSUIT
01807 || MechType(mech) == CLASS_MW) ? TURN / 2 : TURN,
01808 MODE_SPRINT | MODE_OFF);
01809 if(MechStatus2(mech) & EVADING)
01810 MECHEVENT(mech, EVENT_MOVEMODE, mech_movemode_event,
01811 (MechType(mech) == CLASS_BSUIT
01812 || MechType(mech) == CLASS_MW) ? TURN / 2 : TURN,
01813 MODE_EVADE | MODE_OFF);
01814 #endif
01815 if(MechMove(mech) == MOVE_VTOL || MechMove(mech) == MOVE_FLY) {
01816 MechVerticalSpeed(mech) = 0;
01817 MechGoingY(mech) = 0;
01818 MechStartFX(mech) = 0.0;
01819 MechStartFY(mech) = 0.0;
01820 MechStartFZ(mech) = 0.0;
01821 MechStatus(mech) |= LANDED;
01822 if(MechMove(mech) == MOVE_VTOL)
01823 mech_notify(mech, MECHALL,"Your rotor has been destroyed!");
01824 MechStatus(mech) |= FALLEN;
01825 StopMoving(mech);
01826 } else
01827 MaybeMove(mech);
01828 if(MechType(mech) == CLASS_MECH || MechType(mech) == CLASS_MW)
01829 MakeMechFall(mech);
01830
01831 if(seemsg)
01832 MechLOSBroadcast(mech, "falls down!");
01833 DropSetElevation(mech, 1);
01834 MechFZ(mech) = MechZ(mech) * ZSCALE;
01835
01836 roll = Number(1, 6);
01837 switch (roll) {
01838 case 1:
01839 hitGroup = FRONT;
01840 break;
01841 case 2:
01842 AddFacing(mech, 60);
01843 hitGroup = RIGHTSIDE;
01844 break;
01845 case 3:
01846 AddFacing(mech, 120);
01847 hitGroup = RIGHTSIDE;
01848 break;
01849 case 4:
01850 AddFacing(mech, 180);
01851 hitGroup = BACK;
01852 break;
01853 case 5:
01854 AddFacing(mech, 240);
01855 hitGroup = LEFTSIDE;
01856 break;
01857 case 6:
01858 AddFacing(mech, 300);
01859 hitGroup = LEFTSIDE;
01860 break;
01861 }
01862 if(hitGroup == BACK)
01863 isrear = 1;
01864 SetFacing(mech, AcceptableDegree(MechFacing(mech)));
01865 MechDesiredFacing(mech) = MechFacing(mech);
01866 if(!InWater(mech) && MechRTerrain(mech) != HIGHWATER)
01867 #ifndef REALWEIGHT_DAMAGE
01868 damage = (levels * (MechTons(mech) + 5)) / 10;
01869 #else
01870 damage = (levels * (MechRealTons(mech) + 5)) / 10;
01871 #endif
01872 else
01873 #ifndef REALWEIGHT_DAMAGE
01874 damage = (levels * (MechTons(mech) + 5)) / 20;
01875 #else
01876 damage = (levels * (MechRealTons(mech) + 5)) / 20;
01877 #endif
01878 if(InSpecial(mech))
01879 if((map = FindObjectsData(mech->mapindex)))
01880 if(MapUnderSpecialRules(map))
01881 damage = damage * MIN(100, MapGravity(map)) / 100;
01882
01883 if(MechType(mech) == CLASS_MW)
01884 damage *= 40;
01885
01886 spread = damage / 5;
01887
01888 for(i = 0; i < spread; i++) {
01889 hitloc = FindHitLocation(mech, hitGroup, &iscritical, &isrear);
01890 DamageMech(mech, mech, 0, -1, hitloc, isrear, iscritical, 5, -1,
01891 -1, 0, -1, 0, 0);
01892 MechFloods(mech);
01893 water_extinguish_inferno(mech);
01894 }
01895 if(damage % 5) {
01896 hitloc = FindHitLocation(mech, hitGroup, &iscritical, &isrear);
01897 DamageMech(mech, mech, 0, -1, hitloc, isrear, iscritical,
01898 (damage % 5), -1, -1, 0, -1, 0, 0);
01899 MechFloods(mech);
01900 water_extinguish_inferno(mech);
01901 }
01902
01903 possible_mine_poof(mech, MINE_FALL);
01904 MarkForLOSUpdate(mech);
01905 }
01906
01907 int mechs_in_hex(MAP * map, int x, int y, int friendly, int team)
01908 {
01909 MECH *mech;
01910 int i, cnt = 0;
01911
01912 for(i = 0; i < map->first_free; i++)
01913 if((mech = FindObjectsData(map->mechsOnMap[i]))) {
01914 if(MechX(mech) != x || MechY(mech) != y)
01915 continue;
01916 if(Destroyed(mech))
01917 continue;
01918 if(!(MechSpecials2(mech) & CARRIER_TECH) && IsDS(mech)
01919 && (Landed(mech) || !Started(mech))) {
01920 cnt += 2;
01921 continue;
01922 }
01923 if(MechType(mech) != CLASS_MECH)
01924 continue;
01925 if(Jumping(mech) || OODing(mech))
01926 continue;
01927 if(friendly < 0 || ((MechTeam(mech) == team) == friendly))
01928 cnt++;
01929 }
01930 return cnt;
01931 }
01932
01933 enum {
01934 NORMAL, PUNCH, KICK
01935 };
01936
01937 void cause_damage(MECH * att, MECH * mech, int dam, int table)
01938 {
01939 int hitGroup, isrear, iscrit = 0, hitloc = 0;
01940 int i, sp = (dam - 1) / 5;
01941
01942 if(!dam)
01943 return;
01944 if(att == mech)
01945 hitGroup = FRONT;
01946 else
01947 hitGroup = FindAreaHitGroup(att, mech);
01948 isrear = (hitGroup == BACK);
01949 if(Fallen(mech))
01950 table = NORMAL;
01951 for(i = 0; i <= sp; i++) {
01952 switch (table) {
01953 case NORMAL:
01954 hitloc = FindHitLocation(mech, hitGroup, &iscrit, &isrear);
01955 break;
01956 case PUNCH:
01957 if (MechType(mech) != CLASS_MECH) {
01958 hitloc = FindHitLocation(mech, hitGroup, &iscrit, &isrear);
01959 } else {
01960 hitloc = FindPunchLocation(mech, hitGroup);
01961 }
01962 break;
01963 case KICK:
01964 if (MechType(mech) != CLASS_MECH) {
01965 hitloc = FindHitLocation(mech, hitGroup, &iscrit, &isrear);
01966 } else {
01967 hitloc = FindKickLocation(mech, hitGroup);
01968 }
01969 break;
01970 }
01971 if(dam <= 0)
01972 return;
01973 DamageMech(mech, att, (att == mech) ? 0 : 1,
01974 (att == mech) ? -1 : MechPilot(att), hitloc, isrear,
01975 iscrit, dam > 5 ? 5 : dam, 0, -1, 0, -1, 0, 0);
01976 dam -= 5;
01977 }
01978 }
01979
01980 int domino_space_in_hex(MAP * map, MECH * me, int x, int y, int friendly,
01981 int mode, int cnt)
01982 {
01983 int tar = Number(0, cnt - 1), i, head, td;
01984 MECH *mech = NULL;
01985 int team = MechTeam(me);
01986
01987 for(i = 0; i < map->first_free; i++)
01988 if((mech = FindObjectsData(map->mechsOnMap[i]))) {
01989 if(MechX(mech) != x || MechY(mech) != y)
01990 continue;
01991 if(mech == me)
01992 continue;
01993 if(IsDS(mech) && (Landed(mech) || !Started(mech))) {
01994 tar -= 2;
01995 } else {
01996 if(!Started(mech))
01997 continue;
01998 if(MechType(mech) != CLASS_MECH)
01999 continue;
02000 if(Jumping(mech) || OODing(mech))
02001 continue;
02002 if(friendly < 0 || ((MechTeam(mech) == team) == friendly))
02003 tar--;
02004 else
02005 continue;
02006 }
02007 if(tar <= 0)
02008 break;
02009 }
02010 if(i == map->first_free)
02011 return 0;
02012
02013
02014
02015
02016
02017
02018
02019
02020 switch (mode) {
02021 case 1:
02022 case 2:
02023 head = MechJumpHeading(me);
02024 td = JumpSpeedMP(me, map) * (MechRTons(me) / 1024 + 5) / 10;
02025 break;
02026 default:
02027 head = MechFacing(me) + MechLateral(me);
02028 td = fabs(((MechSpeed(me) - MechSpeed(mech) * cos((head -
02029 (MechFacing(mech) +
02030 MechLateral
02031 (mech))) * (M_PI /
02032 180.)))
02033 * MP_PER_KPH) * (MechRTons(me) / 1024 + 5) / 15);
02034 break;
02035 }
02036 if(td > 10)
02037 td = 10 + (td - 10) / 3;
02038 if(td <= 1)
02039 return 0;
02040 switch (mode) {
02041 case 1:
02042 case 2:
02043 if(mudconf.btech_stacking == 2) {
02044 int factor = mudconf.btech_stackdamage;
02045 mech_printf(me, MECHALL, "You land on %s!",
02046 GetMechToMechID(me, mech));
02047 mech_printf(mech, MECHALL, "%s lands on you!",
02048 GetMechToMechID(mech, me));
02049 MechLOSBroadcasti(me, mech, "lands on %s!");
02050 if(IsDS(mech)) {
02051 cause_damage(me, mech, MAX(1, td * factor / 500), PUNCH);
02052 cause_damage(me, me, MAX(1, td * factor / 100), KICK);
02053 } else {
02054 cause_damage(me, mech, MAX(1, td * factor / 100), PUNCH);
02055 cause_damage(me, me, MAX(1, td * factor / 500), KICK);
02056 }
02057 } else {
02058 mech_printf(me, MECHALL, "You nearly land on %s!",
02059 GetMechToMechID(me, mech));
02060 mech_printf(mech, MECHALL, "%s nearly lands on you!",
02061 GetMechToMechID(mech, me));
02062 MechLOSBroadcasti(me, mech, "nearly lands on %s!");
02063 if(!MadePilotSkillRoll(me, cnt + JumpSpeedMP(me, map) / 2))
02064 MechFalls(me, 1, JumpSpeedMP(me, map) / 2);
02065 }
02066 return 1;
02067 }
02068 if(mudconf.btech_stacking == 2) {
02069 int factor = mudconf.btech_stackdamage;
02070 mech_printf(me, MECHALL, "You bump into %s!",
02071 GetMechToMechID(me, mech));
02072 mech_printf(mech, MECHALL, "%s bumps into you!",
02073 GetMechToMechID(mech, me));
02074 MechLOSBroadcasti(me, mech, "bumps into %s!");
02075 if(IsDS(mech)) {
02076 cause_damage(me, mech, MAX(1, td * factor / 500), NORMAL);
02077 cause_damage(me, me, MAX(1, td * factor / 100), NORMAL);
02078 } else {
02079 cause_damage(me, mech, MAX(1, td * factor / 100), NORMAL);
02080 cause_damage(me, me, MAX(1, td * factor / 500), NORMAL);
02081 }
02082 } else {
02083 mech_printf(me, MECHALL, "You nearly bump into %s!",
02084 GetMechToMechID(me, mech));
02085 mech_printf(mech, MECHALL, "%s nearly bumps into you!",
02086 GetMechToMechID(mech, me));
02087 MechLOSBroadcasti(me, mech, "nearly bumps into %s!");
02088 if(!MadePilotSkillRoll(me, cnt))
02089 MechFalls(me, 1, 0);
02090 MechDesiredSpeed(me) = 0;
02091 MechSpeed(me) = 0;
02092 }
02093 MechChargeTarget(me) = -1;
02094 MechChargeTimer(me) = 0;
02095 MechChargeDistance(me) = 0;
02096 return 1;
02097 }
02098
02099 int domino_space(MECH * mech, int mode)
02100 {
02101 MAP *map = FindObjectsData(mech->mapindex);
02102 int cnt, fcnt;
02103
02104 if(!map)
02105 return 0;
02106 if(MechType(mech) != CLASS_MECH)
02107 return 0;
02108 if(mudconf.btech_stacking == 0)
02109 return 0;
02110 cnt = mechs_in_hex(map, MechX(mech), MechY(mech), -1, 0);
02111 if(cnt <= 2)
02112 return 0;
02113
02114 if((fcnt =
02115 mechs_in_hex(map, MechX(mech), MechY(mech), 1, MechTeam(mech))) > 2)
02116 return domino_space_in_hex(map, mech, MechX(mech), MechY(mech), 1,
02117 mode, fcnt);
02118 else if(cnt > 6)
02119 return domino_space_in_hex(map, mech, MechX(mech), MechY(mech), 0,
02120 mode, cnt - fcnt);
02121 return 0;
02122 }