src/hcode/btech/aero.move.c

Go to the documentation of this file.
00001 /*
00002  * Author: Markus Stenberg <fingon@iki.fi>
00003  *
00004  *  Copyright (c) 1996 Markus Stenberg
00005  *  Copyright (c) 1998-2002 Thomas Wouters
00006  *  Copyright (c) 2000-2002 Cord Awtry
00007  *       All rights reserved
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;                         /* In secs */
00038         char *landmsg;
00039         char *landmsg_others;
00040         char *takeoff;
00041         char *takeoff_others;
00042 }                                                               /*            maxvertup / maxvertdown / minhoriz / maxhoriz / launchv /
00043 
00044                                                                    launchtime */ 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         /* Implementation: Kill all players on bridge :-) */
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         /* Heading things are done in speed now, odd as though it might 
00415            seem */
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         /* First, we calculate the vector we want to be going */
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         /* Then, we calculate the present heading / speed */
00486         nx = MechStartFX(mech);
00487         ny = MechStartFY(mech);
00488         nz = MechStartFZ(mech);
00489 
00490         /* Ok, we've present heading / speed */
00491         /* Next, we make vector from n[xyz] -> w[xyz] */
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                 /* Ok.. we've a new modified speed vector */
00505         }
00506         nx += dx;
00507         ny += dy;
00508         nz += dz;
00509         /* Then, we need to calculate present heading / speed / verticalspeed */
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);  /* Whole speed */
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         /* We don't do anything particularly nasty to shutdown things */
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;                       /* Approximately half of the time free */
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         /* DropShips do not need crash ; they switch to (VERY SLOW) secondary
00548            power source. */
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         /* Now, the true nastiness begins ;) */
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                 /* Start free-fall */
00576                 MechVerticalSpeed(mech) = 0;
00577                 /* Hmm. This _can_ be ugly if things crash in middle of fall. Oh well. */
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 }

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