00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #define MIN_TAKEOFF_SPEED 3
00012
00013 #include <math.h>
00014 #include "muxevent.h"
00015 #include "mech.h"
00016 #include "mech.events.h"
00017 #include "p.mech.sensor.h"
00018 #include "p.mech.update.h"
00019 #include "p.artillery.h"
00020 #include "p.mech.combat.h"
00021 #include "p.mech.combat.misc.h"
00022 #include "p.mech.utils.h"
00023 #include "p.econ_cmds.h"
00024 #include "p.mech.ecm.h"
00025 #include "p.mech.tag.h"
00026 #include "p.mech.lite.h"
00027 #include "spath.h"
00028 #include "p.mine.h"
00029
00030 struct land_data_type {
00031 int type;
00032 int maxvertup;
00033 int maxvertdown;
00034 int minhoriz;
00035 int maxhoriz;
00036 int launchvert;
00037 int launchtime;
00038 char *landmsg;
00039 char *landmsg_others;
00040 char *takeoff;
00041 char *takeoff_others;
00042 }
00043
00044 land_data[] = {
00045 {
00046 CLASS_VTOL, 10, -60, -15, 15, 5, 0,
00047 "You bring your VTOL to a safe landing.", "lands.",
00048 "The rotor whines overhead as you lift off into the sky.",
00049 "takes off!"}, {
00050 CLASS_AERO, 10, -30, MIN_TAKEOFF_SPEED * MP1, 999, 20, 10,
00051 "You land your AeroFighter safely.", "lands safely.",
00052 "The Aerofighter launches into the air!",
00053 "launches into the air!"}, {
00054 CLASS_DS, 10, -25, MIN_TAKEOFF_SPEED * MP1, 999, 20, 300,
00055 "The DropShip lands safely.", "lands safely.",
00056 "The DropShip's nose lurches upward, and it starts climbing to the sky!",
00057 "starts climbing to the sky!"}, {
00058 CLASS_SPHEROID_DS, 15, -40, -40, 40, 20, 300,
00059 "The DropShip touches down safely.",
00060 "touches down, and settles.",
00061 "The DropShip slowly lurches upwards as engines battle the gravity..",
00062 "starts climbing up to the sky!"}
00063 };
00064
00065 #define NUM_LAND_TYPES (sizeof(land_data)/sizeof(struct land_data_type))
00066
00067 static void aero_takeoff_event(MUXEVENT * e)
00068 {
00069 MECH *mech = (MECH *) e->data;
00070 MAP *map = getMap(mech->mapindex);
00071 int i = -1;
00072 int count = (int) e->data2;
00073
00074 if(IsDS(mech))
00075 for(i = 0; i < NUM_LAND_TYPES; i++)
00076 if(MechType(mech) == land_data[i].type)
00077 break;
00078 if(count > 0) {
00079 if(count > 5) {
00080 if(!(count % 10))
00081 mech_printf(mech, MECHALL, "Launch countdown: %d.", count);
00082 } else
00083 mech_printf(mech, MECHALL, "Launch countdown: %d.", count);
00084 if(i >= 0) {
00085 if(count == (land_data[i].launchtime / 4))
00086 DSSpam_O(mech,
00087 "'s engines start to glow with unbearable intensity..");
00088 switch (count) {
00089 case 10:
00090 DSSpam_O(mech, "'s engines are almost ready to lift off!");
00091 break;
00092 case 6:
00093 DSSpam_O(mech, "'s engines generate a tremendous heat wave!");
00094 ScrambleInfraAndLiteAmp(mech, 2, 0,
00095 "The blinding flash of light momentarily blinds you!",
00096 "The blinding flash of light momentarily blinds you!");
00097 break;
00098 case 2:
00099 mech_notify(mech, MECHALL,
00100 "The engines pulse out a stream of superheated plasma!");
00101 DSSpam_O(mech,
00102 "'s engines send forth a tremendous stream of superheated plasma!");
00103 ScrambleInfraAndLiteAmp(mech, 4, 0,
00104 "The blinding flash of light blinds you!",
00105 "The blinding flash of light blinds you!");
00106 break;
00107 case 1:
00108 DS_BlastNearbyMechsAndTrees(mech,
00109 "You receive a direct hit!",
00110 "is caught in the middle of the inferno!",
00111 "You are hit by the wave!",
00112 "gets hit by the wave!",
00113 "are instantly burned to ash!",
00114 400);
00115 break;
00116 }
00117 }
00118 MECHEVENT(mech, EVENT_TAKEOFF, aero_takeoff_event, 1, (void *)
00119 (count - 1));
00120 return;
00121 }
00122 if(i < 0) {
00123 if(RollingT(mech) && MechSpeed(mech) < (MIN_TAKEOFF_SPEED * MP1)) {
00124 mech_notify(mech, MECHALL,
00125 "You're moving too slowly to lift off!");
00126 return;
00127 }
00128 for(i = 0; i < NUM_LAND_TYPES; i++)
00129 if(MechType(mech) == land_data[i].type)
00130 break;
00131 }
00132 StopSpinning(mech);
00133 mech_notify(mech, MECHALL, land_data[i].takeoff);
00134 MechLOSBroadcast(mech, land_data[i].takeoff_others);
00135 MechStartFX(mech) = 0;
00136 MechStartFY(mech) = 0;
00137 MechStartFZ(mech) = 0;
00138 if(IsDS(mech))
00139 SendDSInfo(tprintf("DS #%d has lifted off at %d %d "
00140 "on map #%d", mech->mynum, MechX(mech),
00141 MechY(mech), map->mynum));
00142 if(MechCritStatus(mech) & HIDDEN) {
00143 mech_notify(mech, MECHALL, "You move too much and break your cover!");
00144 MechLOSBroadcast(mech, "breaks its cover in the brush.");
00145 MechCritStatus(mech) &= ~(HIDDEN);
00146 }
00147 if(MechType(mech) != CLASS_VTOL) {
00148 MechDesiredAngle(mech) = 90;
00149 MechDesiredSpeed(mech) = MechMaxSpeed(mech) * 2 / 3;
00150 } else {
00151 MechSpeed(mech) = 0;
00152 MechDesiredSpeed(mech) = 0;
00153 MechVerticalSpeed(mech) = 60.0;
00154 }
00155 ContinueFlying(mech);
00156 MaybeMove(mech);
00157 }
00158
00159 void aero_takeoff(dbref player, void *data, char *buffer)
00160 {
00161 MECH *mech = (MECH *) data;
00162 MAP *map = getMap(mech->mapindex);
00163 int i, j;
00164
00165 for(i = 0; i < NUM_LAND_TYPES; i++)
00166 if(MechType(mech) == land_data[i].type)
00167 break;
00168
00169 if((j = atoi(buffer)))
00170 DOCHECK(!WizP(player), "Insufficient access!");
00171
00172 DOCHECK(TakingOff(mech),
00173 "The launch sequence has already been initiated!");
00174 DOCHECK(i == NUM_LAND_TYPES, "This vehicle type cannot takeoff!");
00175 cch(MECH_USUAL);
00176 DOCHECK(!FlyingT(mech),
00177 "Only VTOL, Aerospace fighters and Dropships can take off.");
00178 DOCHECK(!Landed(mech), "You haven't landed!");
00179 if(Fallen(mech) || (MMaxSpeed(mech) <= MP1) ||
00180 (SectIsDestroyed(mech, ROTOR))) {
00181 DOCHECK(MechType(mech) == CLASS_VTOL, "The rotor's dead!");
00182 notify(player, "The engines are dead!");
00183 return;
00184 }
00185 if(!AeroFreeFuel(mech) && AeroFuel(mech) < 1) {
00186 DOCHECK(MechType(mech) == CLASS_VTOL, "Your VTOL's out of fuel!");
00187 notify(player,
00188 "Your craft's out of fuel! No taking off until it's refueled.");
00189 return;
00190 }
00191 DOCHECK(MechType(mech) == CLASS_AERO &&
00192 MechSpeed(mech) < (MIN_TAKEOFF_SPEED * MP1),
00193 "You're moving too slowly to take off!");
00194 DOCHECK(MapIsUnderground(map),
00195 "Realize the ceiling in this grotto is a bit to low for that!");
00196 if(land_data[i].launchtime > 0)
00197 mech_notify(mech, MECHALL,
00198 "Launch sequence initiated.. type 'land' to abort it.");
00199 DSSpam(mech, "starts warming engines for liftoff!");
00200 if(IsDS(mech))
00201 SendDSInfo(tprintf("DS #%d has started takeoff at %d %d on map #%d",
00202 mech->mynum, MechX(mech), MechY(mech),
00203 map->mynum));
00204 if(MechCritStatus(mech) & HIDDEN) {
00205 mech_notify(mech, MECHALL, "You break your cover to takeoff!");
00206 MechLOSBroadcast(mech, "breaks its cover as it begins takeoff.");
00207 MechCritStatus(mech) &= ~(HIDDEN);
00208 }
00209 StopHiding(mech);
00210 MECHEVENT(mech, EVENT_TAKEOFF, aero_takeoff_event, 1, (void *)
00211 j ? j : land_data[i].launchtime);
00212 }
00213
00214 #define NUM_NEIGHBORS 7
00215
00216 void DS_BlastNearbyMechsAndTrees(MECH * mech, char *hitmsg, char *hitmsg1,
00217 char *nearhitmsg, char *nearhitmsg1,
00218 char *treehitmsg, int damage)
00219 {
00220 MAP *map = getMap(mech->mapindex);
00221 int x = MechX(mech), y = MechY(mech), z = MechZ(mech);
00222 int x1, y1, x2, y2, d;
00223 int rng = (damage > 100 ? 5 : 3);
00224
00225 for(x1 = x - rng; x1 <= (x + rng); x1++)
00226 for(y1 = y - rng; y1 <= (y + rng); y1++) {
00227 x2 = BOUNDED(0, x1, map->map_width - 1);
00228 y2 = BOUNDED(0, y1, map->map_height - 1);
00229 if(x1 != x2 || y1 != y2)
00230 continue;
00231 if((d = MyHexDist(x, y, x1, y1, 0)) > rng)
00232 continue;
00233 d = MAX(1, d);
00234 switch (GetRTerrain(map, x1, y1)) {
00235 case LIGHT_FOREST:
00236 case HEAVY_FOREST:
00237 if(!find_decorations(map, x1, y1)) {
00238 HexLOSBroadcast(map, x1, y1,
00239 tprintf("%%ch%%crThe trees in $h %s%%cn",
00240 treehitmsg));
00241 if((damage / d) > 100) {
00242 SetTerrain(map, x1, y1, ROUGH);
00243 } else {
00244 add_decoration(map, x1, y1, TYPE_FIRE, FIRE,
00245 FIRE_DURATION);
00246 }
00247 }
00248 break;
00249 }
00250 }
00251 MechZ(mech) = z + 6;
00252 blast_hit_hexesf(map, damage, 5, damage / 2, MechFX(mech),
00253 MechFY(mech), MechFX(mech), MechFY(mech), hitmsg,
00254 hitmsg1, nearhitmsg, nearhitmsg1, 0, 4, 4, 1, rng);
00255 MechZ(mech) = z;
00256 }
00257
00258 enum {
00259 NO_ERROR, INVALID_TERRAIN, UNEVEN_TERRAIN, BLOCKED_LZ
00260 };
00261
00262 char *reasons[] = {
00263 "Improper terrain",
00264 "Uneven ground",
00265 "Blocked landing zone"
00266 };
00267
00268 static int improper_lz_status;
00269 static int improper_lz_height;
00270
00271 static void ImproperLZ_callback(MAP * map, int x, int y)
00272 {
00273 if(Elevation(map, x, y) != improper_lz_height)
00274 improper_lz_status = 0;
00275 else
00276 improper_lz_status++;
00277 }
00278
00279 #define MechCheckLZ(m) ImproperLZ((m), MechX((m)), MechY((m)))
00280
00281 int ImproperLZ(MECH * mech, int x, int y)
00282 {
00283 MAP *map = getMap(mech->mapindex);
00284
00285 if(GetRTerrain(map, x, y) != GRASSLAND && GetRTerrain(map, x, y) != ROAD)
00286 return INVALID_TERRAIN;
00287
00288 improper_lz_status = 0;
00289 improper_lz_height = Elevation(map, x, y);
00290 visit_neighbor_hexes(map, x, y, ImproperLZ_callback);
00291
00292 if(improper_lz_status != 6)
00293 return UNEVEN_TERRAIN;
00294 if(is_blocked_lz(mech, map, x, y))
00295 return BLOCKED_LZ;
00296 return NO_ERROR;
00297 }
00298
00299 void aero_land(dbref player, void *data, char *buffer)
00300 {
00301 MECH *mech = (MECH *) data;
00302 MAP *map = getMap(mech->mapindex);
00303 int i, t;
00304 double horiz = 0.0;
00305 int vert, vertmin = 0, vertmax = 0;
00306
00307 DOCHECK(MechType(mech) != CLASS_VTOL &&
00308 MechType(mech) != CLASS_AERO &&
00309 !IsDS(mech), "You can't land this type of vehicle.");
00310 DOCHECK(MechType(mech) == CLASS_VTOL &&
00311 AeroFuel(mech) <= 0 &&
00312 !AeroFreeFuel(mech), "You lack fuel to maneuver for landing!");
00313
00314 for(i = 0; i < NUM_LAND_TYPES; i++)
00315 if(MechType(mech) == land_data[i].type)
00316 break;
00317 if(i == NUM_LAND_TYPES)
00318 return;
00319 DOCHECK((Fallen(mech)) &&
00320 (MechType(mech) == CLASS_VTOL), "The rotor's dead!");
00321 DOCHECK((Fallen(mech)) &&
00322 (MechType(mech) != CLASS_VTOL), "The engines are dead!");
00323 if(MechStatus(mech) & LANDED) {
00324 if(TakingOff(mech)) {
00325 mech_printf(mech, MECHALL, "Launch aborted by %s.", Name(player));
00326 if(IsDS(mech))
00327 SendDSInfo(tprintf("DS #%d aborted takeoff at %d %d "
00328 "on map #%d", mech->mynum, MechX(mech),
00329 MechY(mech), map->mynum));
00330 StopTakeOff(mech);
00331 return;
00332 }
00333 notify(player, "You're already landed!");
00334 return;
00335 }
00336 DOCHECK(MechZ(mech) > MechElevation(mech) + 1,
00337 "You are too high to land here.");
00338 DOCHECK(((horiz =
00339 my_sqrtm((double) MechDesiredSpeed(mech),
00340 (double) MechVerticalSpeed(mech))) >=
00341 ((double) 1.0 + land_data[i].maxhoriz)),
00342 "You're moving too fast to land.");
00343 DOCHECK(horiz < land_data[i].minhoriz,
00344 "You're moving too slowly to land.");
00345 DOCHECK(((vert = MechVerticalSpeed(mech)) > (vertmax =
00346 land_data[i].maxvertup)) ||
00347 (MechVerticalSpeed(mech) < (vertmin =
00348 land_data[i].maxvertdown)),
00349 "You are moving too fast to land. ");
00350 if(MechSpeed(mech) < land_data[i].minhoriz) {
00351 if(MechStartFZ(mech) <= 0)
00352 notify(player,
00353 "You're falling, not landing! Pick up some horizontal speed first.");
00354 else
00355 notify(player, "You're climbing not landing!");
00356 return;
00357 }
00358 t = MechRTerrain(mech);
00359 DOCHECK(!(t == GRASSLAND || t == ROAD || (MechType(mech) == CLASS_VTOL
00360 && t == BUILDING)),
00361 "You can't land on this type of terrain.");
00362 if(MechType(mech) != CLASS_VTOL && MechCheckLZ(mech)) {
00363 mech_notify(mech, MECHALL, "This location is no good for landing!");
00364 return;
00365 }
00366 if(IsDS(mech))
00367 SendDSInfo(tprintf("DS #%d has landed at %d %d on map #%d",
00368 mech->mynum, MechX(mech), MechY(mech),
00369 map->mynum));
00370
00371 mech_notify(mech, MECHALL, land_data[i].landmsg);
00372 MechLOSBroadcast(mech, land_data[i].landmsg_others);
00373 MechZ(mech) = MechElevation(mech);
00374 MechFZ(mech) = ZSCALE * MechZ(mech);
00375 MechStatus(mech) |= LANDED;
00376 MechSpeed(mech) = 0.0;
00377 MechVerticalSpeed(mech) = 0.0;
00378 MechStartFX(mech) = 0.0;
00379 MechStartFY(mech) = 0.0;
00380 MechStartFZ(mech) = 0.0;
00381 possible_mine_poof(mech, MINE_LAND);
00382 }
00383
00384 void aero_ControlEffect(MECH * mech)
00385 {
00386 if(Spinning(mech))
00387 return;
00388 if(Destroyed(mech))
00389 return;
00390 if(Landed(mech))
00391 return;
00392 mech_notify(mech, MECHALL, "You lose control of your craft!");
00393 MechLOSBroadcast(mech, "spins out of control!");
00394 StartSpinning(mech);
00395 MechStartSpin(mech) = mudstate.now;
00396 }
00397
00398 void ds_BridgeHit(MECH * mech)
00399 {
00400
00401 if(Destroyed(mech))
00402 return;
00403 if(In_Character(mech->mynum))
00404 mech_notify(mech, MECHALL,
00405 "SHIT! The shot seems to be coming straight for the bridge!");
00406 KillMechContentsIfIC(mech->mynum);
00407 }
00408
00409 #define degsin(a) ((double) sin((double) (a) * M_PI / 180.0))
00410 #define degcos(a) ((double) cos((double) (a) * M_PI / 180.0))
00411
00412 void aero_UpdateHeading(MECH * mech)
00413 {
00414
00415
00416 if(SpheroidDS(mech))
00417 UpdateHeading(mech);
00418 }
00419
00420 double length_hypotenuse(double x, double y)
00421 {
00422 if(x < 0)
00423 x = -x;
00424 if(y < 0)
00425 y = -y;
00426 return sqrt(x * x + y * y);
00427 }
00428
00429 double my_sqrtm(double x, double y)
00430 {
00431 double d;
00432
00433 if(x < 0)
00434 x = -x;
00435 if(y < 0)
00436 y = -y;
00437 if(y > x) {
00438 d = y;
00439 y = x;
00440 x = d;
00441 }
00442 return sqrt(x * x - y * y);
00443 }
00444
00445 #define AERO_BONUS 3
00446
00447 void aero_UpdateSpeed(MECH * mech)
00448 {
00449 float xypart;
00450 float wx, wy, wz;
00451 float nx, ny, nz;
00452 float nh;
00453 float dx, dy, dz;
00454 float vlen, mod;
00455 float sp;
00456 float ab = 0.7;
00457 float m = 1.0;
00458
00459 if(Spinning(mech)) {
00460 MechDesiredSpeed(mech) =
00461 BOUNDED(0, MechDesiredSpeed(mech) + Number(1, 10),
00462 MMaxSpeed(mech));
00463 MechDesiredAngle(mech) =
00464 MAX(-90, MechDesiredAngle(mech) - Number(1, 15));
00465 MechDesiredFacing(mech) =
00466 AcceptableDegree(MechDesiredFacing(mech) + Number(-3, 3));
00467 }
00468 wz = MechDesiredSpeed(mech) * degsin(MechDesiredAngle(mech));
00469 if(MechType(mech) == CLASS_AERO)
00470 ab = 2.5;
00471 if(MechZ(mech) < ATMO_Z)
00472 ab = ab / 2;
00473
00474 xypart = MechDesiredSpeed(mech) * degcos(MechDesiredAngle(mech));
00475 if(AeroFuel(mech) < 0) {
00476 wz = wz / 5.0;
00477 xypart = xypart / 5.0;
00478 }
00479 if(xypart < 0)
00480 xypart = 0 - xypart;
00481 m = ACCEL_MOD;
00482 FindComponents(m * xypart, MechDesiredFacing(mech), &wx, &wy);
00483 wz = wz * m;
00484
00485
00486 nx = MechStartFX(mech);
00487 ny = MechStartFY(mech);
00488 nz = MechStartFZ(mech);
00489
00490
00491
00492 dx = wx - nx;
00493 dy = wy - ny;
00494 dz = wz - nz;
00495 vlen = length_hypotenuse(length_hypotenuse(dx, dy), dz);
00496 if(!(vlen > 0.0))
00497 return;
00498 if(vlen > (m * ab * MMaxSpeed(mech) / AERO_SECS_THRUST)) {
00499 mod = (float) ab *m * MMaxSpeed(mech) / AERO_SECS_THRUST / vlen;
00500
00501 dx *= mod;
00502 dy *= mod;
00503 dz *= mod;
00504
00505 }
00506 nx += dx;
00507 ny += dy;
00508 nz += dz;
00509
00510 nh = (float) atan2(ny, nx) / TWOPIOVER360;
00511 if(!SpheroidDS(mech))
00512 SetFacing(mech, AcceptableDegree((int) nh + 90));
00513 xypart = length_hypotenuse(nx, ny);
00514 MechSpeed(mech) = xypart;
00515 sp = length_hypotenuse(length_hypotenuse(nx, ny), nz);
00516 MechVerticalSpeed(mech) = nz;
00517 if(!SpheroidDS(mech) && fabs(MechSpeed(mech)) < MP1)
00518 SetFacing(mech, MechDesiredFacing(mech));
00519 MechStartFX(mech) = nx;
00520 MechStartFY(mech) = ny;
00521 MechStartFZ(mech) = nz;
00522 }
00523
00524 int FuelCheck(MECH * mech)
00525 {
00526 int fuelcost = 1;
00527
00528
00529 if(!Started(mech))
00530 return 0;
00531 if(AeroFreeFuel(mech))
00532 return 0;
00533 if(fabs(MechSpeed(mech)) > MMaxSpeed(mech)) {
00534 if(MechZ(mech) < ATMO_Z)
00535 fuelcost = abs(MechSpeed(mech) / MMaxSpeed(mech));
00536 } else if(fabs(MechSpeed(mech)) < MP1 &&
00537 fabs(MechVerticalSpeed(mech)) < MP2)
00538 if(Number(0, 1) == 0)
00539 return 0;
00540 if(AeroFuel(mech) > 0) {
00541 if(AeroFuel(mech) <= fuelcost)
00542 AeroFuel(mech) = 0;
00543 else
00544 AeroFuel(mech) -= fuelcost;
00545 return 0;
00546 }
00547
00548
00549 if(IsDS(mech)) {
00550 if(AeroFuel(mech) < 0)
00551 return 0;
00552 AeroFuel(mech)--;
00553 mech_notify(mech, MECHALL,
00554 "As the fuel runs out, the engines switch to backup power.");
00555 return 0;
00556 }
00557 if(AeroFuel(mech) < 0)
00558 return 1;
00559
00560 AeroFuel(mech)--;
00561 if(!(AeroFuel(mech) % 100) && AeroFuel(mech) >= AeroFuelOrig(mech))
00562 SetCargoWeight(mech);
00563 if(MechType(mech) == CLASS_VTOL) {
00564 MechLOSBroadcast(mech, "'s rotors suddenly stop!");
00565 mech_notify(mech, MECHALL, "The sound of rotors slowly stops..");
00566 } else {
00567 MechLOSBroadcast(mech, "'s engines die suddenly..");
00568 mech_notify(mech, MECHALL, "Your engines die suddenly..");
00569 }
00570 MechSpeed(mech) = 0.0;
00571 MechDesiredSpeed(mech) = 0.0;
00572 if(!Landed(mech)) {
00573 mech_notify(mech, MECHALL,
00574 "You ponder F = ma, S = F/m, S = at^2 => S=agt^2 in relation to the ground..");
00575
00576 MechVerticalSpeed(mech) = 0;
00577
00578 mech_notify(mech, MECHALL, "You start free-fall.. Enjoy the ride!");
00579 MECHEVENT(mech, EVENT_FALL, mech_fall_event, FALL_TICK, -1);
00580 }
00581 return 1;
00582 }
00583
00584 void aero_update(MECH * mech)
00585 {
00586 if(Destroyed(mech))
00587 return;
00588 if(Started(mech) || Uncon(mech)) {
00589 UpdatePilotSkillRolls(mech);
00590 }
00591 if(Started(mech) || MechPlusHeat(mech) > 0.)
00592 UpdateHeat(mech);
00593 if(!(mudstate.now / 3 % 5)) {
00594 if(!Spinning(mech))
00595 return;
00596 if(Destroyed(mech))
00597 return;
00598 if(Landed(mech))
00599 return;
00600 if(MadePilotSkillRoll(mech,
00601 (MechStartSpin(mech) - mudstate.now) / 15 +
00602 8)) {
00603 mech_notify(mech, MECHALL, "You recover control of your craft.");
00604 StopSpinning(mech);
00605 }
00606 }
00607 if(Started(mech))
00608 MechVisMod(mech) =
00609 BOUNDED(0, MechVisMod(mech) + Number(-40, 40), 100);
00610 checkECM(mech);
00611 checkTAG(mech);
00612 end_lite_check(mech);
00613 }
00614
00615 void aero_thrust(dbref player, void *data, char *arg)
00616 {
00617 MECH *mech = (MECH *) data;
00618 char *args[1];
00619 float newspeed, maxspeed;
00620
00621 DOCHECK(Landed(mech), "You're landed!");
00622 DOCHECK(is_aero(mech) && Spinning(mech) &&
00623 !Landed(mech),
00624 "You are unable to control your craft at the moment.");
00625 if(mech_parseattributes(arg, args, 1) != 1) {
00626 notify_printf(player, "Your current thrust is %.2f.",
00627 MechDesiredSpeed(mech));
00628 return;
00629 }
00630 newspeed = atof(args[0]);
00631 if(RollingT(mech))
00632 DOCHECK(newspeed < (MP1 * MIN_TAKEOFF_SPEED / ACCEL_MOD),
00633 tprintf("Minimum thrust you stay in air with is %.1f kph.",
00634 (float) MP1 * MIN_TAKEOFF_SPEED / ACCEL_MOD));
00635 maxspeed = MMaxSpeed(mech);
00636 if(!(maxspeed > 0.0))
00637 maxspeed = 0.0;
00638 DOCHECK(Fallen(mech), "Your engine's dead, no way to thrust!");
00639 DOCHECK(newspeed < 0,
00640 "Doh, thrust backwards.. where's your sense of adventure?");
00641 if(newspeed > maxspeed) {
00642 notify_printf(player, "Maximum thrust: %.2f (%.2f kb/sec2)",
00643 maxspeed, maxspeed / 10);
00644 return;
00645 }
00646 MechDesiredSpeed(mech) = newspeed;
00647 mech_printf(mech, MECHALL, "Thrust set to %.2f.", newspeed);
00648 MaybeMove(mech);
00649 }
00650
00651 void aero_vheading(dbref player, void *data, char *arg, int flag)
00652 {
00653 char *args[1];
00654 int i = 0;
00655 MECH *mech = (MECH *) data;
00656
00657 if(mech_parseattributes(arg, args, 1) != 1) {
00658 notify_printf(player, "Present angle: %d degrees.",
00659 MechDesiredAngle(mech));
00660 return;
00661 }
00662 i = flag * atoi(args[0]);
00663 if(abs(i) > 90)
00664 i = 90 * flag;
00665 DOCHECK(abs(i) != 90 && MechZ(mech) < ATMO_Z &&
00666 SpheroidDS(mech), tprintf("You can go only up / down at <%d z!",
00667 ATMO_Z));
00668 if(i >= 0)
00669 mech_printf(mech, MECHALL, "Climbing angle set to %d degrees.", i);
00670 else
00671 mech_printf(mech, MECHALL, "Diving angle set to %d degrees.", 0 - i);
00672 MechDesiredAngle(mech) = i;
00673 }
00674
00675 void aero_climb(dbref player, MECH * mech, char *arg)
00676 {
00677 aero_vheading(player, mech, arg, 1);
00678 }
00679
00680 void aero_dive(dbref player, MECH * mech, char *arg)
00681 {
00682 aero_vheading(player, mech, arg, -1);
00683 }
00684
00685 static char *colorstr(int serious)
00686 {
00687 if(serious == 1)
00688 return "%ch%cr";
00689 if(serious == 0)
00690 return "%ch%cy";
00691 return "";
00692 }
00693
00694 void DS_LandWarning(MECH * mech, int serious)
00695 {
00696 int ilz = MechCheckLZ(mech);
00697
00698 if(!ilz)
00699 return;
00700 ilz--;
00701 mech_printf(mech, MECHALL, "%sWARNING: %s - %s%%cn",
00702 colorstr(serious), reasons[ilz],
00703 serious == 1 ? "CLIMB UP NOW!!!" : serious ==
00704 0 ? "No further descent is advisable." :
00705 "Please do not even consider landing here.");
00706 }
00707
00708 void aero_checklz(dbref player, MECH * mech, char *buffer)
00709 {
00710 int ilz, argc;
00711 char *args[3];
00712 int x, y;
00713
00714 cch(MECH_USUAL);
00715
00716 argc = mech_parseattributes(buffer, args, 3);
00717 switch (argc) {
00718 case 2:
00719 x = atoi(args[0]);
00720 y = atoi(args[1]);
00721 if(!MechIsObservator(mech)) {
00722 float fx, fy;
00723 MapCoordToRealCoord(x, y, &fx, &fy);
00724 DOCHECK(FindHexRange(MechFX(mech), MechFY(mech), fx, fy) >
00725 MechTacRange(mech), "Out of range!");
00726 }
00727 break;
00728 case 0:
00729 x = MechX(mech);
00730 y = MechY(mech);
00731 break;
00732 default:
00733 notify(player, "Invalid number of parameters!");
00734 return;
00735 }
00736
00737 ilz = ImproperLZ(mech, x, y);
00738 DOCHECKMA(!ilz,
00739 tprintf("The hex (%d,%d) looks good enough for a landing.",
00740 x, y));
00741 ilz--;
00742 mech_printf(mech, MECHALL,
00743 "The hex (%d,%d) doesn't look good for landing: %s.",
00744 x, y, reasons[ilz]);
00745 }