src/hcode/btech/ds.bay.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 #include "config.h"
00012 
00013 #include <math.h>
00014 
00015 #include "mech.h"
00016 #include "mech.events.h"
00017 #include "p.mech.utils.h"
00018 #include "p.bsuit.h"
00019 #include "p.eject.h"
00020 #include "p.mech.restrict.h"
00021 #include "p.mech.startup.h"
00022 
00023 dbref match_thing(dbref player, char *name);
00024 
00025 void mech_createbays(dbref player, void *data, char *buffer)
00026 {
00027         char *args[NUM_BAYS + 1];
00028         int argc;
00029         dbref it;
00030         int i;
00031         MECH *ds = (MECH *) data;
00032         MAP *map;
00033 
00034         DOCHECK((argc =
00035                          mech_parseattributes(buffer, args,
00036                                                                   NUM_BAYS + 1)) == (NUM_BAYS + 1),
00037                         "Invalid number of arguments!");
00038         for(i = 0; i < argc; i++) {
00039                 it = match_thing(player, args[i]);
00040                 DOCHECK(it == NOTHING, tprintf("Argument %d is invalid.", i + 1));
00041                 DOCHECK(!IsMap(it), tprintf("Argument %d is not a map.", i + 1));
00042                 map = FindObjectsData(it);
00043                 AeroBay(ds, i) = it;
00044                 map->onmap = ds->mynum;
00045         }
00046         for(i = argc; i < NUM_BAYS; i++)
00047                 AeroBay(ds, i) = -1;
00048         notify_printf(player, "%d bay(s) set up!", argc);
00049 }
00050 
00051 extern int dirs[6][2];
00052 
00053 static int dir2loc[6] =
00054         { DS_NOSE, DS_RWING, DS_RRWING, DS_AFT, DS_LRWING, DS_LWING };
00055 
00056 int Find_DS_Bay_Number(MECH * ds, int dir)
00057 {
00058         int bayn = 0;
00059         int i, j;
00060 
00061         for(i = 0; i <= dir; i++) {
00062                 for(j = 0; j < NUM_CRITICALS; j++)
00063                         if(GetPartType(ds, dir2loc[i % 6],
00064                                                    j) == I2Special(DS_MECHDOOR) ||
00065                            GetPartType(ds, dir2loc[i % 6], j) == I2Special(DS_AERODOOR))
00066                                 break;
00067                 if(j != NUM_CRITICALS) {
00068                         if(i == dir)
00069                                 return bayn;
00070                         bayn++;
00071                 }
00072         }
00073         return -1;
00074 }
00075 
00076 int Find_DS_Bay_Dir(MECH * ds, int num)
00077 {
00078         int i;
00079 
00080         for(i = 0; i < 6; i++)
00081                 if(Find_DS_Bay_Number(ds, i) == num)
00082                         return i;
00083         return -1;
00084 }
00085 
00086 #define KLUDGE(fx,tx) ((((fx)%2)&&!((tx)%2)) ? -1 : 0)
00087 
00088 int Find_DS_Bay_In_MechHex(MECH * seer, MECH * ds, int *bayn)
00089 {
00090         int i;
00091         int t = DSBearMod(ds);
00092 
00093         for(i = t; i < (t + 6); i++) {
00094 
00095                 if(((MechX(ds) + dirs[i % 6][0]) == MechX(seer)) &&
00096                    ((MechY(ds) + dirs[i % 6][1] + KLUDGE(MechX(ds),
00097                                                                                                  MechX(ds) +
00098                                                                                                  dirs[i % 6][0])) ==
00099                         MechY(seer))) {
00100                         if((*bayn = Find_DS_Bay_Number(ds, ((i - t + 6) % 6))) >= 0)
00101                                 return 1;
00102                         return 0;
00103                 }
00104         }
00105         return 0;
00106 }
00107 
00108 static int Find_Single_DS_In_MechHex(MECH * mech, int *ref, int *bayn)
00109 {
00110         MAP *map = FindObjectsData(mech->mapindex);
00111         int loop;
00112         MECH *tempMech;
00113         int count = 0;
00114 
00115         *ref = 0;
00116         if(!map)
00117                 return 0;
00118         for(loop = 0; loop < map->first_free; loop++)
00119                 if(map->mechsOnMap[loop] >= 0) {
00120                         if(!(tempMech = getMech(map->mechsOnMap[loop])))
00121                                 continue;
00122                         if(!IsDS(tempMech))
00123                                 continue;
00124                         if(!Landed(tempMech))
00125                                 continue;               /* This might break midflight-aero-DS-docking. But aeros are broken anyway. */
00126                         if(Find_DS_Bay_In_MechHex(mech, tempMech, bayn)) {
00127                                 if(count++)
00128                                         *ref = -1;
00129                                 else
00130                                         *ref = tempMech->mynum;
00131                         }
00132                 }
00133         return count;
00134 }
00135 
00136 static void mech_enterbay_event(MUXEVENT * e)
00137 {
00138         MECH *mech = (MECH *) e->data, *ds, *tmpm = NULL;
00139         int ref = (int) e->data2;
00140         int bayn;
00141         int x = 5, y = 5;
00142         MAP *tmpmap;
00143 
00144         if(!Started(mech) || Uncon(mech) || Jumping(mech) ||
00145            (MechType(mech) == CLASS_MECH && (Fallen(mech) || Standing(mech))) ||
00146            OODing(mech) || (fabs(MechSpeed(mech)) * 5 >= MMaxSpeed(mech) &&
00147                                                 fabs(MMaxSpeed(mech)) >= MP1)
00148            || (MechType(mech) == CLASS_VTOL && AeroFuel(mech) <= 0))
00149                 return;
00150         tmpmap = getMap(ref);
00151         if(!(ds = getMech(tmpmap->onmap)))
00152                 return;
00153         if(!Find_DS_Bay_In_MechHex(mech, ds, &bayn))
00154                 return;
00155         /* whee */
00156         ref = AeroBay(ds, bayn);
00157         StopBSuitSwarmers(FindObjectsData(mech->mapindex), mech, 1);
00158         mech_notify(mech, MECHALL, "You enter bay.");
00159         MechLOSBroadcast(mech, tprintf("has entered %s at %d,%d.",
00160                                                                    GetMechID(ds), MechX(mech), MechY(mech)));
00161         MarkForLOSUpdate(mech);
00162         if(MechType(mech) == CLASS_MW && !In_Character(ref)) {
00163                 enter_mw_bay(mech, ref);
00164                 return;
00165         }
00166         if(MechCarrying(mech) > 0)
00167                 tmpm = getMech(MechCarrying(mech));
00168         mech_Rsetmapindex(GOD, (void *) mech, tprintf("%d", ref));
00169         mech_Rsetxy(GOD, (void *) mech, tprintf("%d %d", x, y));
00170         MechLOSBroadcast(mech, "has entered the bay.");
00171         loud_teleport(mech->mynum, ref);
00172         if(tmpm) {
00173                 mech_Rsetmapindex(GOD, (void *) tmpm, tprintf("%d", ref));
00174                 mech_Rsetxy(GOD, (void *) tmpm, tprintf("%d %d", x, y));
00175                 loud_teleport(tmpm->mynum, ref);
00176         }
00177 }
00178 
00179 static int DS_Bay_Is_Open(MECH * mech, MECH * ds, dbref bayref)
00180 {
00181         int i, j;
00182 
00183         for(i = 0; i < NUM_BAYS; i++)
00184                 if(AeroBay(ds, i) > 0)
00185                         if(AeroBay(ds, i) == bayref) {
00186                                 j = Find_DS_Bay_Dir(ds, i);
00187                                 for(i = 0; i < NUM_CRITICALS; i++) {
00188                                         if(((is_aero(mech) &&
00189                                                  GetPartType(ds, dir2loc[j],
00190                                                                          i) == I2Special(DS_AERODOOR)) ||
00191                                                 (!is_aero(mech)
00192                                                  && GetPartType(ds, dir2loc[j],
00193                                                                                 i) == I2Special(DS_MECHDOOR))) &&
00194                                            !PartIsDestroyed(ds, dir2loc[j], i))
00195                                                 return 1;
00196                                 }
00197                                 return 0;
00198                         }
00199         return 0;
00200 }
00201 
00202 static int DS_Bay_Is_EnterOK(MECH * mech, MECH * ds, dbref bayref)
00203 {
00204         int i;
00205 
00206         for(i = 0; i < NUM_BAYS; i++)
00207                 if(AeroBay(ds, i) > 0)
00208                         if(AeroBay(ds, i) == bayref)
00209                                 return muxevent_count_type_data2(EVENT_ENTER_HANGAR,
00210                                                                                                  (void *) bayref) > 0 ? 0 : 1;
00211         return 0;
00212 }
00213 
00214 /* ID / Number, both optional (this _will_ be painful) */
00215 
00216 void mech_enterbay(dbref player, void *data, char *buffer)
00217 {
00218         char *args[3];
00219         int argc;
00220         dbref ref = -1, bayn = -1;
00221         MECH *mech = data, *ds;
00222         MAP *map;
00223 
00224         cch(MECH_USUAL);
00225         DOCHECK(MechType(mech) == CLASS_VTOL &&
00226                         AeroFuel(mech) <= 0, "You lack fuel to maneuver in!");
00227         DOCHECK(Jumping(mech), "While in mid-jump? No way.");
00228         DOCHECK(MechType(mech) == CLASS_MECH && (Fallen(mech) ||
00229                                                                                          Standing(mech)),
00230                         "Crawl inside? I think not. Stand first.");
00231         DOCHECK(OODing(mech), "While in mid-flight? No way.");
00232         DOCHECK((argc =
00233                          mech_parseattributes(buffer, args, 2)) == 2,
00234                         "Hmm, invalid number of arguments?");
00235         if(argc > 0)
00236                 DOCHECK((ref =
00237                                  FindTargetDBREFFromMapNumber(mech, args[0])) <= 0,
00238                                 "Invalid target!");
00239         if(ref < 0) {
00240                 DOCHECK(!Find_Single_DS_In_MechHex(mech, &ref, &bayn),
00241                                 "No DS bay found in your hex!");
00242                 DOCHECK(ref < 0,
00243                                 "Multiple enterable things found ; use the id for specifying which you want.");
00244                 DOCHECK(!(ds =
00245                                   getMech(ref)), "You sense wrongness in fabric of space.");
00246         } else {
00247                 DOCHECK(!(ds =
00248                                   getMech(ref)), "You sense wrongness in fabric of space.");
00249                 DOCHECK(!Find_DS_Bay_In_MechHex(mech, ds, &bayn),
00250                                 "You see no bays in your hex.");
00251         }
00252         DOCHECK(IsDS(mech)
00253                         && !(MechSpecials2(mech) & CARRIER_TECH),
00254                         "Your craft can't enter bays.");
00255         DOCHECK(!DS_Bay_Is_Open(mech, ds, AeroBay(ds, bayn)),
00256                         "The door has been jammed!");
00257         DOCHECK(IsDS(mech), "Your unit is a bit too large to fit in there.");
00258         DOCHECK((fabs((float) (MechSpeed(mech) - MechSpeed(ds)))) > MP1,
00259                         "Speed difference's too large to enter!");
00260         DOCHECK(MechZ(ds) != MechZ(mech),
00261                         "Get to same elevation before thinking about entering!");
00262         DOCHECK(abs(MechVerticalSpeed(mech) - MechVerticalSpeed(ds)) > 10,
00263                         "Vertical speed difference is too great to enter safely!");
00264         DOCHECK(MechType(mech) == CLASS_MECH && !MechIsQuad(mech) &&
00265                         (IsMechLegLess(mech)), "Without legs? Are you kidding?");
00266         ref = AeroBay(ds, bayn);
00267         map = getMap(ref);
00268 
00269         DOCHECK(!map, "You sense wrongness in fabric of space.");
00270 
00271         DOCHECK(EnteringHangar(mech), "You are already entering the hangar!");
00272         if(!can_pass_lock(mech->mynum, ref, A_LENTER)) {
00273                 char *msg = silly_atr_get(ref, A_FAIL);
00274                 if(!msg || !*msg)
00275                         msg = "You are unable to enter the bay!";
00276                 notify(player, msg);
00277                 return;
00278         }
00279         DOCHECK(!DS_Bay_Is_EnterOK(mech, ds, AeroBay(ds, bayn)),
00280                         "Someone else is using the door at the moment.");
00281         DOCHECK(!(map =
00282                           getMap(mech->mapindex)),
00283                         "You sense a wrongness in fabric of space.");
00284         HexLOSBroadcast(map, MechX(mech), MechY(mech),
00285                                         "The bay doors at $h start to open..");
00286         MECHEVENT(mech, EVENT_ENTER_HANGAR, mech_enterbay_event, 12, ref);
00287 }
00288 
00289 static void DS_Place(MECH * ds, MECH * mech, int frombay)
00290 {
00291         int i;
00292         int nx, ny;
00293         MAP *mech_map;
00294 
00295         for(i = 0; i < NUM_BAYS; i++)
00296                 if(AeroBay(ds, i) == frombay)
00297                         break;
00298         if(i == NUM_BAYS || !(mech_map = getMap(mech->mapindex))) {
00299                 /* i _should_ be set, otherwise things are deeply disturbing */
00300                 mech_notify(mech, MECHALL, "Reality collapse imminent.");
00301                 return;
00302         }
00303         i = Find_DS_Bay_Dir(ds, i);
00304         nx = dirs[(DSBearMod(ds) + i) % 6][0] + MechX(ds);
00305         ny = dirs[(DSBearMod(ds) + i) % 6][1] + MechY(ds) + KLUDGE(MechX(ds), nx);
00306         nx = BOUNDED(0, nx, mech_map->map_width - 1);
00307         ny = BOUNDED(0, ny, mech_map->map_height - 1);
00308 
00309         /* snippage from mech_Rsetxy */
00310         MechX(mech) = nx;
00311         MechLastX(mech) = nx;
00312         MechY(mech) = ny;
00313         MechLastY(mech) = ny;
00314         MechZ(mech) = MechZ(ds);
00315         MechElev(mech) = MechElev(ds);
00316         MapCoordToRealCoord(MechX(mech), MechY(mech), &MechFX(mech),
00317                                                 &MechFY(mech));
00318         MechTerrain(mech) = GetTerrain(mech_map, MechX(mech), MechY(mech));
00319 }
00320 
00321 static int Leave_DS_Bay(MAP * map, MECH * ds, MECH * mech, dbref frombay)
00322 {
00323         MECH *car = NULL;
00324 
00325         StopBSuitSwarmers(FindObjectsData(mech->mapindex), mech, 1);
00326         MechLOSBroadcast(mech, "has left the bay.");
00327         /* We escape confines of the bay to open air/land! */
00328         mech_Rsetmapindex(GOD, (void *) mech, tprintf("%d", ds->mapindex));
00329         if(MechCarrying(mech) > 0)
00330                 car = getMech(MechCarrying(mech));
00331         if(car)
00332                 mech_Rsetmapindex(GOD, (void *) car, tprintf("%d", ds->mapindex));
00333         DOCHECKMA0(mech->mapindex == map->mynum,
00334                            "Fatal error: Unable to find the map 'ship is on.");
00335         loud_teleport(mech->mynum, mech->mapindex);
00336         if(car)
00337                 loud_teleport(car->mynum, mech->mapindex);
00338         mech_notify(mech, MECHALL, "You have left the bay.");
00339         DS_Place(ds, mech, frombay);
00340         if(car)
00341                 MirrorPosition(mech, car, 0);
00342         MechLOSBroadcasti(mech, ds, "has left %s's bay.");
00343         mech_notify(ds, MECHALL, tprintf("%s has left the bay.",
00344                                                                          GetMechID(mech)));
00345         ContinueFlying(mech);
00346         if(In_Character(mech->mynum) && Location(MechPilot(mech)) != mech->mynum) {
00347                 mech_notify(mech, MECHALL,
00348                                         "%ch%cr%cf%ciINTRUDER ALERT! INTRUDER ALERT!%c");
00349                 mech_notify(mech, MECHALL,
00350                                         "%ch%cr%cfAutomatic self-destruct sequence initiated.%c");
00351                 mech_shutdown(GOD, (void *) mech, "");
00352         }
00353         return 1;
00354 }
00355 
00356 int Leave_DS(MAP * map, MECH * mech)
00357 {
00358         MECH *car;
00359 
00360         DOCHECKMA0(!(car = getMech(map->onmap)), "Invalid : No parent object?");
00361         DOCHECKMA0(!DS_Bay_Is_Open(mech, car, map->mynum),
00362                            "The door has been jammed!");
00363         DOCHECKMA0(!Landed(car) &&
00364                            !FlyingT(mech), "The 'ship is still airborne!");
00365         DOCHECKMA0(Zombie(car->mynum),
00366                            "You don't feel leaving right now would be prudent..");
00367         return Leave_DS_Bay(map, car, mech, map->mynum);
00368 }

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