btmux/autom4te.cache/
btmux/doc/.svn/
btmux/event/.svn/
btmux/game/.svn/
btmux/game/bin/.svn/
btmux/game/data/.svn/
btmux/game/logs/.svn/
btmux/game/maps/
btmux/game/maps/.svn/
btmux/game/maps/.svn/prop-base/
btmux/game/maps/.svn/props/
btmux/game/maps/.svn/text-base/
btmux/game/maps/.svn/wcprops/
btmux/game/mechs/
btmux/game/mechs/.svn/
btmux/game/mechs/.svn/prop-base/
btmux/game/mechs/.svn/props/
btmux/game/mechs/.svn/text-base/
btmux/game/mechs/.svn/wcprops/
btmux/game/text/.svn/
btmux/include/.svn/
btmux/misc/
btmux/misc/.svn/
btmux/misc/.svn/prop-base/
btmux/misc/.svn/props/
btmux/misc/.svn/text-base/
btmux/misc/.svn/wcprops/
btmux/python/
btmux/python/.svn/
btmux/python/.svn/prop-base/
btmux/python/.svn/props/
btmux/python/.svn/text-base/
btmux/python/.svn/wcprops/
btmux/src/.svn/prop-base/
btmux/src/.svn/props/
btmux/src/.svn/text-base/
btmux/src/.svn/wcprops/
btmux/src/hcode/.svn/
btmux/src/hcode/btech/
btmux/src/hcode/btech/.svn/
btmux/src/hcode/btech/.svn/prop-base/
btmux/src/hcode/btech/.svn/props/
btmux/src/hcode/btech/.svn/text-base/
btmux/src/hcode/btech/.svn/wcprops/
btmux/src/hcode/include/.svn/
/*
 * $Id: ds.bay.c,v 1.4 2005/06/24 04:39:07 av1-op Exp $
 *
 * Author: Markus Stenberg <fingon@iki.fi>
 *
 *  Copyright (c) 1996 Markus Stenberg
 *  Copyright (c) 1998-2002 Thomas Wouters
 *  Copyright (c) 2000-2002 Cord Awtry
 *       All rights reserved
 *
 * Created: Wed Nov 20 20:48:28 1996 fingon
 * Last modified: Sat Jul 18 22:25:57 1998 fingon
 *
 */

#include "config.h"

#include <math.h>

#include "mech.h"
#include "mech.events.h"
#include "p.mech.utils.h"
#include "p.bsuit.h"
#include "p.eject.h"
#include "p.mech.restrict.h"
#include "p.mech.startup.h"

dbref match_thing(dbref player, char *name);

void mech_createbays(dbref player, void *data, char *buffer)
{
    char *args[NUM_BAYS + 1];
    int argc;
    dbref it;
    int i;
    MECH *ds = (MECH *) data;
    MAP *map;

    DOCHECK((argc =
	    mech_parseattributes(buffer, args,
		NUM_BAYS + 1)) == (NUM_BAYS + 1),
	"Invalid number of arguments!");
    for (i = 0; i < argc; i++) {
	it = match_thing(player, args[i]);
	DOCHECK(it == NOTHING, tprintf("Argument %d is invalid.", i + 1));
	DOCHECK(!IsMap(it), tprintf("Argument %d is not a map.", i + 1));
	map = FindObjectsData(it);
	AeroBay(ds, i) = it;
	map->onmap = ds->mynum;
    }
    for (i = argc; i < NUM_BAYS; i++)
	AeroBay(ds, i) = -1;
    notify(player, tprintf("%d bay(s) set up!", argc));
}

extern int dirs[6][2];

static int dir2loc[6] =
    { DS_NOSE, DS_RWING, DS_RRWING, DS_AFT, DS_LRWING, DS_LWING };

int Find_DS_Bay_Number(MECH * ds, int dir)
{
    int bayn = 0;
    int i, j;

    for (i = 0; i <= dir; i++) {
	for (j = 0; j < NUM_CRITICALS; j++)
	    if (GetPartType(ds, dir2loc[i % 6],
		    j) == I2Special(DS_MECHDOOR) ||
		GetPartType(ds, dir2loc[i % 6],
		    j) == I2Special(DS_AERODOOR))
		break;
	if (j != NUM_CRITICALS) {
	    if (i == dir)
		return bayn;
	    bayn++;
	}
    }
    return -1;
}

int Find_DS_Bay_Dir(MECH * ds, int num)
{
    int i;

    for (i = 0; i < 6; i++)
	if (Find_DS_Bay_Number(ds, i) == num)
	    return i;
    return -1;
}

#define KLUDGE(fx,tx) ((((fx)%2)&&!((tx)%2)) ? -1 : 0)


int Find_DS_Bay_In_MechHex(MECH * seer, MECH * ds, int *bayn)
{
    int i;
    int t = DSBearMod(ds);

    for (i = t; i < (t + 6); i++) {

	if (((MechX(ds) + dirs[i % 6][0]) == MechX(seer)) &&
	    ((MechY(ds) + dirs[i % 6][1] + KLUDGE(MechX(ds),
			MechX(ds) + dirs[i % 6][0])) == MechY(seer))) {
	    if ((*bayn = Find_DS_Bay_Number(ds, ((i - t + 6) % 6))) >= 0)
		return 1;
	    return 0;
	}
    }
    return 0;
}

static int Find_Single_DS_In_MechHex(MECH * mech, int *ref, int *bayn)
{
    MAP *map = FindObjectsData(mech->mapindex);
    int loop;
    MECH *tempMech;
    int count = 0;

    *ref = 0;
    if (!map)
	return 0;
    for (loop = 0; loop < map->first_free; loop++)
	if (map->mechsOnMap[loop] >= 0) {
	    if (!(tempMech = getMech(map->mechsOnMap[loop])))
		continue;
	    if (!IsDS(tempMech))
		continue;
	    if (!Landed(tempMech))
		continue;	/* This might break midflight-aero-DS-docking. But aeros are broken anyway. */
	    if (Find_DS_Bay_In_MechHex(mech, tempMech, bayn)) {
		if (count++)
		    *ref = -1;
		else
		    *ref = tempMech->mynum;
	    }
	}
    return count;
}


static void mech_enterbay_event(MUXEVENT * e)
{
    MECH *mech = (MECH *) e->data, *ds, *tmpm = NULL;
    int ref = (int) e->data2;
    int bayn;
    int x = 5, y = 5;
    MAP *tmpmap;

    if (!Started(mech) || Uncon(mech) || Jumping(mech) ||
	(MechType(mech) == CLASS_MECH && (Fallen(mech) || Standing(mech))) ||
	OODing(mech) || (fabs(MechSpeed(mech)) * 5 >= MMaxSpeed(mech) &&
	    fabs(MMaxSpeed(mech)) >= MP1) || (MechType(mech) == CLASS_VTOL
	    && AeroFuel(mech) <= 0))
	return;
    tmpmap = getMap(ref);
    if (!(ds = getMech(tmpmap->onmap)))
	return;
    if (!Find_DS_Bay_In_MechHex(mech, ds, &bayn))
	return;
    /* whee */
    ref = AeroBay(ds, bayn);
    StopBSuitSwarmers(FindObjectsData(mech->mapindex), mech, 1);
    mech_notify(mech, MECHALL, "You enter bay.");
    MechLOSBroadcast(mech, tprintf("has entered %s at %d,%d.",
	    GetMechID(ds), MechX(mech), MechY(mech)));
    MarkForLOSUpdate(mech);
    if (MechType(mech) == CLASS_MW && !In_Character(ref)) {
	enter_mw_bay(mech, ref);
	return;
    }
    if (MechCarrying(mech) > 0)
	tmpm = getMech(MechCarrying(mech));
    mech_Rsetmapindex(GOD, (void *) mech, tprintf("%d", ref));
    mech_Rsetxy(GOD, (void *) mech, tprintf("%d %d", x, y));
    MechLOSBroadcast(mech, "has entered the bay.");
    loud_teleport(mech->mynum, ref);
    if (tmpm) {
	mech_Rsetmapindex(GOD, (void *) tmpm, tprintf("%d", ref));
	mech_Rsetxy(GOD, (void *) tmpm, tprintf("%d %d", x, y));
	loud_teleport(tmpm->mynum, ref);
    }
}

static int DS_Bay_Is_Open(MECH * mech, MECH * ds, dbref bayref)
{
    int i, j;

    for (i = 0; i < NUM_BAYS; i++)
	if (AeroBay(ds, i) > 0)
	    if (AeroBay(ds, i) == bayref) {
		j = Find_DS_Bay_Dir(ds, i);
		for (i = 0; i < NUM_CRITICALS; i++) {
		    if (((is_aero(mech) &&
				GetPartType(ds, dir2loc[j],
				    i) == I2Special(DS_AERODOOR)) ||
			    (!is_aero(mech)
				&& GetPartType(ds, dir2loc[j],
				    i) == I2Special(DS_MECHDOOR))) &&
			!PartIsDestroyed(ds, dir2loc[j], i))
			return 1;
		}
		return 0;
	    }
    return 0;
}

static int DS_Bay_Is_EnterOK(MECH * mech, MECH * ds, dbref bayref)
{
    int i;

    for (i = 0; i < NUM_BAYS; i++)
	if (AeroBay(ds, i) > 0)
	    if (AeroBay(ds, i) == bayref)
		return muxevent_count_type_data2(EVENT_ENTER_HANGAR,
		    (void *) bayref) > 0 ? 0 : 1;
    return 0;
}


/* ID / Number, both optional (this _will_ be painful) */

void mech_enterbay(dbref player, void *data, char *buffer)
{
    char *args[3];
    int argc;
    dbref ref = -1, bayn = -1;
    MECH *mech = data, *ds;
    MAP *map;

    cch(MECH_USUAL);
    DOCHECK(MechType(mech) == CLASS_VTOL &&
	AeroFuel(mech) <= 0, "You lack fuel to maneuver in!");
    DOCHECK(Jumping(mech), "While in mid-jump? No way.");
    DOCHECK(MechType(mech) == CLASS_MECH && (Fallen(mech) ||
	    Standing(mech)), "Crawl inside? I think not. Stand first.");
    DOCHECK(OODing(mech), "While in mid-flight? No way.");
    DOCHECK((argc =
	    mech_parseattributes(buffer, args, 2)) == 2,
	"Hmm, invalid number of arguments?");
    if (argc > 0)
	DOCHECK((ref =
		FindTargetDBREFFromMapNumber(mech, args[0])) <= 0,
	    "Invalid target!");
    if (ref < 0) {
	DOCHECK(!Find_Single_DS_In_MechHex(mech, &ref, &bayn),
	    "No DS bay found in your hex!");
	DOCHECK(ref < 0,
	    "Multiple enterable things found ; use the id for specifying which you want.");
	DOCHECK(!(ds =
		getMech(ref)), "You sense wrongness in fabric of space.");
    } else {
	DOCHECK(!(ds =
		getMech(ref)), "You sense wrongness in fabric of space.");
	DOCHECK(!Find_DS_Bay_In_MechHex(mech, ds, &bayn),
	    "You see no bays in your hex.");
    }
    DOCHECK(IsDS(mech) && !(MechSpecials2(mech) & CARRIER_TECH), "Your craft can't enter bays.");
    DOCHECK(!DS_Bay_Is_Open(mech, ds, AeroBay(ds, bayn)),
	"The door has been jammed!");
    DOCHECK(IsDS(mech),
	"Your unit is a bit too large to fit in there.");
    DOCHECK((fabs((float) (MechSpeed(mech) - MechSpeed(ds)))) > MP1,
	"Speed difference's too large to enter!");
    DOCHECK(MechZ(ds) != MechZ(mech),
	"Get to same elevation before thinking about entering!");
    DOCHECK(abs(MechVerticalSpeed(mech) - MechVerticalSpeed(ds)) > 10,
	"Vertical speed difference is too great to enter safely!");
    DOCHECK(MechType(mech) == CLASS_MECH && !MechIsQuad(mech) &&
	(IsMechLegLess(mech)), "Without legs? Are you kidding?");
    ref = AeroBay(ds, bayn);
    map = getMap(ref);

    DOCHECK(!map, "You sense wrongness in fabric of space.");

    DOCHECK(EnteringHangar(mech), "You are already entering the hangar!");
    if (!can_pass_lock(mech->mynum, ref, A_LENTER)) {
    	char *msg = silly_atr_get(ref, A_FAIL);
    	if (!msg || !*msg)
    	    msg = "You are unable to enter the bay!";
    	notify(player, msg);
    	return;
    }
    DOCHECK(!DS_Bay_Is_EnterOK(mech, ds, AeroBay(ds, bayn)),
	"Someone else is using the door at the moment.");
    DOCHECK(!(map =
	    getMap(mech->mapindex)),
	"You sense a wrongness in fabric of space.");
    HexLOSBroadcast(map, MechX(mech), MechY(mech),
	"The bay doors at $h start to open..");
    MECHEVENT(mech, EVENT_ENTER_HANGAR, mech_enterbay_event, 12, ref);
}

static void DS_Place(MECH * ds, MECH * mech, int frombay)
{
    int i;
    int nx, ny;
    MAP *mech_map;

    for (i = 0; i < NUM_BAYS; i++)
	if (AeroBay(ds, i) == frombay)
	    break;
    if (i == NUM_BAYS || !(mech_map = getMap(mech->mapindex))) {
	/* i _should_ be set, otherwise things are deeply disturbing */
	mech_notify(mech, MECHALL, "Reality collapse imminent.");
	return;
    }
    i = Find_DS_Bay_Dir(ds, i);
    nx = dirs[(DSBearMod(ds) + i) % 6][0] + MechX(ds);
    ny = dirs[(DSBearMod(ds) + i) % 6][1] + MechY(ds) + KLUDGE(MechX(ds),
	nx);
    nx = BOUNDED(0, nx, mech_map->map_width - 1);
    ny = BOUNDED(0, ny, mech_map->map_height - 1);

    /* snippage from mech_Rsetxy */
    MechX(mech) = nx;
    MechLastX(mech) = nx;
    MechY(mech) = ny;
    MechLastY(mech) = ny;
    MechZ(mech) = MechZ(ds);
    MechElev(mech) = MechElev(ds);
    MapCoordToRealCoord(MechX(mech), MechY(mech), &MechFX(mech),
	&MechFY(mech));
    MechTerrain(mech) = GetTerrain(mech_map, MechX(mech), MechY(mech));
}

static int Leave_DS_Bay(MAP * map, MECH * ds, MECH * mech, dbref frombay)
{
    MECH *car = NULL;

    StopBSuitSwarmers(FindObjectsData(mech->mapindex), mech, 1);
    MechLOSBroadcast(mech, "has left the bay.");
    /* We escape confines of the bay to open air/land! */
    mech_Rsetmapindex(GOD, (void *) mech, tprintf("%d", ds->mapindex));
    if (MechCarrying(mech) > 0)
	car = getMech(MechCarrying(mech));
    if (car)
	mech_Rsetmapindex(GOD, (void *) car, tprintf("%d", ds->mapindex));
    DOCHECKMA0(mech->mapindex == map->mynum,
	"Fatal error: Unable to find the map 'ship is on.");
    loud_teleport(mech->mynum, mech->mapindex);
    if (car)
	loud_teleport(car->mynum, mech->mapindex);
    mech_notify(mech, MECHALL, "You have left the bay.");
    DS_Place(ds, mech, frombay);
    if (car)
	MirrorPosition(mech, car, 0);
    MechLOSBroadcasti(mech, ds, "has left %s's bay.");
    mech_notify(ds, MECHALL, tprintf("%s has left the bay.",
	    GetMechID(mech)));
    ContinueFlying(mech);
    if (In_Character(mech->mynum) &&
	Location(MechPilot(mech)) != mech->mynum) {
	mech_notify(mech, MECHALL,
	    "%ch%cr%cf%ciINTRUDER ALERT! INTRUDER ALERT!%c");
	mech_notify(mech, MECHALL,
	    "%ch%cr%cfAutomatic self-destruct sequence initiated.%c");
	mech_shutdown(GOD, (void *) mech, "");
    }
    return 1;
}

int Leave_DS(MAP * map, MECH * mech)
{
    MECH *car;

    DOCHECKMA0(!(car =
	    getMech(map->onmap)), "Invalid : No parent object?");
    DOCHECKMA0(!DS_Bay_Is_Open(mech, car, map->mynum),
	"The door has been jammed!");
    DOCHECKMA0(!Landed(car) &&
	!FlyingT(mech), "The 'ship is still airborne!");
    DOCHECKMA0(Zombie(car->mynum),
	"You don't feel leaving right now would be prudent..");
    return Leave_DS_Bay(map, car, mech, map->mynum);
}