00001
00002
00003
00004
00005
00006
00007
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;
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
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
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
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
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
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 }