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: mech.pickup.c,v 1.5 2005/08/10 14:09:34 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
 *  Copyright (c) 2002 Dr. Martin Brumm
 *  Copyright (c) 1999-2005 Kevin Stevens
 *       All rights reserved
 *
 */

#include "config.h"

/* Avenger's contribution to 3030 MUX ('nother one) */

#include <math.h>

#include "mech.h"
#include "mech.events.h"
#include "muxevent.h"
#include "p.event.h"
#include "p.mech.utils.h"
#include "p.mech.los.h"
#include "p.eject.h"
#include "p.mech.pickup.h"
#include "p.mech.update.h"
#include "p.crit.h"
#include "p.mech.tag.h"
#include "p.bsuit.h"
#include "p.mech.ice.h"

void mech_pickup(dbref player, void *data, char *buffer)
{
    MECH *mech = (MECH *) data;
    MECH *target;
    dbref target_num;
    MAP *newmap;
    int argc, through_ice;
    char *args[4];

    if (player != GOD)
        cch(MECH_USUAL);
    argc = mech_parseattributes(buffer, args, 1);
#ifdef BT_MOVEMENT_MODES
    DOCHECK(MoveModeLock(mech),
            "You cannot tow currently in this movement mode!");
#endif
    DOCHECK(argc != 1, "Invalid number of arguments.");
    target_num = FindTargetDBREFFromMapNumber(mech, args[0]);
    DOCHECK(target_num == -1, "That target is not in your line of sight.");
    target = getMech(target_num);
    DOCHECK(!target ||
            !InLineOfSight(mech, target, MechX(target), MechY(target),
                FaMechRange(mech, target)),
            "That target is not in your line of sight.");
    DOCHECK(MechSpecials2(target) & CARRIER_TECH && !MechSpecials2(mech) & CARRIER_TECH,
            "You cannot handle the mass on that carrier.");
    DOCHECK(CarryingClub(mech),
            "You can't pickup while you're carrying a club!");
    DOCHECK(Jumping(mech), "You can't pickup while jumping!");
    DOCHECK(Jumping(target),
            "What are you going to do? Grab it from mid air?");
    DOCHECK(Fallen(mech), "You are in no position to pick anything up!");
    DOCHECK(MechZ(mech) > (MechZ(target) + 3),
            "You are too high above the target.");
    DOCHECK(MechZ(mech) < MechZ(target) - 2,
            "You are too far below the target.");
    DOCHECK(MechX(mech) != MechX(target) ||
            MechY(mech) != MechY(target), "You need to be in the same hex!");
    DOCHECK(((MechZ(target) <= 0) && (MechRTerrain(target) == BRIDGE) &&
                (MechZ(mech) > 0)),
            "You need to be under the bridge to pick up this unit.");
    DOCHECK(Towed(target),
            "That target's already being towed by someone!");
    DOCHECK(MechSwarmTarget(target) == mech->mynum,
            "You can't grab hold!");
    DOCHECK(MechTons(mech) < 5 || (!In_Character(target->mynum) &&
                !Towable(target)), "You can't tow that!");
    DOCHECK(MechCritStatus(target) & HIDDEN, "You cannot pickup hiding targets....");
    DOCHECK(Burning(target), "You can't tow a burning unit!");
    if (MechType(target) == CLASS_MW) {
        pickup_mw(mech, target);
        return;
    } else {
        if (MechType(mech) == CLASS_MECH) {
            DOCHECKMA(MechIsQuad(mech),
                    "You've got four left feet, you can't tow!");
            DOCHECKMA(SectIsDestroyed(mech, LARM),
                    "Your left arm is destroyed, you can't pick up anything.");
            DOCHECKMA(SectIsDestroyed(mech, RARM),
                    "Your right arm is destroyed, you can't pick up anything.");
            DOCHECKMA(!(OkayCritSectS(RARM, 3, HAND_OR_FOOT_ACTUATOR) &&
                        OkayCritSectS(RARM, 0, SHOULDER_OR_HIP)) &&
                    !(OkayCritSectS(LARM, 3, HAND_OR_FOOT_ACTUATOR) &&
                        OkayCritSectS(LARM, 0, SHOULDER_OR_HIP)),
                    "You need functioning arm to pick things up!");
        } else
            DOCHECK(!(MechSpecials(mech) & SALVAGE_TECH),
                    "You can't pick that up in this MECH/VEHICLE");
    }
    DOCHECK(MechCarrying(mech) > 0, "You are already carrying a Mech");
    DOCHECK(((fabs(MechSpeed(mech)) > 1.0) ||
                (fabs((float) MechVerticalSpeed(mech)) > 1.0)),
            "You are moving too fast to attempt a pickup.");
    DOCHECK(IsDS(target), "You can't pick that up!");
    DOCHECK(MechMove(target) == MOVE_NONE, "That's simply immobile!");
    DOCHECK(MechTeam(mech) != MechTeam(target) &&
            Started(target), "You can't pick that up!");

    if (Moving(target) && !Falling(target) && !OODing(target))
        StopMoving(target);

    DOCHECK(Moving(target), "You can't pick up a moving target!");

    mech_notify(target, MECHALL,
            tprintf("%s attaches his tow lines to you.",
                GetMechToMechID(target, mech)));
    mech_notify(mech, MECHALL, tprintf("You attach your tow lines to %s.",
                GetMechToMechID(mech, target)));
    if (MechCarrying(target) > 0)
        mech_dropoff(GOD, target, "");
    if ((newmap = getMap(target->mapindex)))
        MechLOSBroadcasti(mech, target, "picks up %s!");
    SetCarrying(mech, target->mynum);
    MechSwarmTarget(target) = -1;
    if (MechType(target) == CLASS_MECH) {
        MechStatus(target) |= FALLEN;
        FallCentersTorso(target);
        StopStand(target);
    }
    MechStatus(target) |= TOWED;
    MechStatus(target) &= ~HULLDOWN;
    MechTankCritStatus(target) &= ~DUG_IN;

    through_ice = (MechRTerrain(target) == ICE && MechZ(mech) >= 0 &&
    		   MechZ(target) < 0);
    MirrorPosition(mech, target, 0);
    if (through_ice) {
        if (MechZ(mech) == 0 && MechMove(mech) != MOVE_HOVER)
            drop_thru_ice(mech);
        else
            break_thru_ice(mech);
    }
    if (!Destroyed(target))
        Shutdown(target);

    /* Adjust the speed involved */
    correct_speed(mech);

    /* Send emit for triggers/debugging */
    SendDebug(tprintf("#%d has picked up #%d", mech->mynum, target->mynum));
}

void mech_attachcables(dbref player, void *data, char *buffer)
{
    MECH *mech = (MECH *) data;
    MECH *towMech;
    MECH *target;
    dbref towMech_num;
    dbref target_num;
    int argc;
    char *args[3];
    char mechName[SBUF_SIZE];
    char towMechName[SBUF_SIZE];
    char targetName[SBUF_SIZE];

    if (player != GOD)
	cch(MECH_USUAL);

    argc = mech_parseattributes(buffer, args, 2);
    DOCHECK(argc != 2, "Invalid number of arguments.");

    DOCHECK(OODing(mech),
	"You can't attach cables while floating in the air!");

    /* Check the towing unit. */
    towMech_num = FindTargetDBREFFromMapNumber(mech, args[0]);
    DOCHECK(towMech_num == -1,
	"That towing unit is not in your line of sight.");
    towMech = getMech(towMech_num);
    DOCHECK(!towMech ||
	!InLineOfSight(mech, towMech, MechX(towMech), MechY(towMech),
	    FaMechRange(mech, towMech)),
	"That towing unit is not in your line of sight.");
    DOCHECK(MechX(mech) != MechX(towMech) ||
	MechY(mech) != MechY(towMech),
	"You need to be in the same hex as the towing unit!");
    DOCHECK(Jumping(towMech),
	"That towing unit is currently flying through the air!");
    DOCHECK(MechZ(mech) != MechZ(towMech),
	"You must be on the same elevation as the towing unit!");
    DOCHECK(MechCarrying(towMech) > 0,
	"That towing unit is towing someone else!");
    DOCHECK(Towed(towMech),
	"That towing unit is already being towed by someone!");
    DOCHECK((MechType(towMech) == CLASS_MW), "That unit can not tow!");
    DOCHECK(MechMove(towMech) == MOVE_NONE, "That unit can not tow!");
    DOCHECK(MechTons(towMech) < 5, "That unit can not tow!");
    DOCHECK(Destroyed(towMech), "Destroyed units can not tow!");
    DOCHECK((MechTons(towMech) < 5) ||
	(!In_Character(towMech->mynum)), "That unit can not tow!");
    DOCHECK(Burning(towMech),
	"You can not attach tow cables to a burning unit!");
    DOCHECK((MechSpecials(towMech) & SALVAGE_TECH),
	"That is a dedicated towing unit and can pick up the target itself!");
    DOCHECK(((fabs(MechSpeed(towMech)) > 0.0) ||
	    (fabs((float) MechVerticalSpeed(towMech)) > 0.0)),
	"The towing unit is moving to fast for you to grab the tow cables!");
    DOCHECK((MechTeam(towMech) != MechTeam(mech)),
	"You can not grab the tow cables from that unit!");
    DOCHECK((MechType(towMech) != CLASS_MECH) &&
	(MechType(towMech) != CLASS_VEH_GROUND), "That unit can not tow!");

    /* Check the target */
    target_num = FindTargetDBREFFromMapNumber(mech, args[1]);
    DOCHECK(target_num == -1, "That target is not in your line of sight.");
    target = getMech(target_num);
    DOCHECK(!target ||
	!InLineOfSight(mech, target, MechX(target), MechY(target),
	    FaMechRange(mech, target)),
	"That target is not in your line of sight.");
    DOCHECK(MechX(mech) != MechX(target) ||
	MechY(mech) != MechY(target),
	"You need to be in the same hex as the target!");
    DOCHECK(Jumping(target),
	"That target is currently flying through the air!");
    DOCHECK(MechZ(mech) != MechZ(target),
	"You must be on the same elevation as the target!");
    DOCHECK(MechCarrying(target) > 0,
	"That target is towing someone else!");
    DOCHECK(Towed(target),
	"That target is already being towed by someone!");
    DOCHECK((!In_Character(target->mynum) &&
	    !Towable(target)), "That unit can not be towed!");
    DOCHECK(MechType(target) == CLASS_MW, "That unit can not be towed!");
    DOCHECK(MechMove(target) == MOVE_NONE, "That unit can not be towed!");
    DOCHECK(IsDS(target), "That unit can not be towed!");
    DOCHECK(Burning(target),
	"You can not attach tow cables to a burning unit!");
    DOCHECK(((fabs(MechSpeed(target)) > 0.0) ||
	    (fabs((float) MechVerticalSpeed(target)) > 0.0)),
	"The target is moving to fast for you to attach the tow cables!");
    DOCHECK((MechTeam(target) != MechTeam(mech)) &&
	Started(target), "That unit can not be towed!");

    if (Moving(target) && !Falling(target) && !OODing(target))
	StopMoving(target);

    DOCHECK(Moving(target),
	"The target is moving to fast for you to attach the tow cables!");

    strcpy(mechName, GetMechID(mech));
    strcpy(towMechName, GetMechID(towMech));
    strcpy(targetName, GetMechID(target));

    mech_notify(target, MECHALL,
	tprintf("%s attaches tow lines from %s to you.", mechName,
	    towMechName));
    mech_notify(towMech, MECHALL,
	tprintf("%s attaches your tow lines to %s.", mechName,
	    targetName));
    mech_notify(mech, MECHALL, tprintf("You attach %s's tow lines to %s.",
	    towMechName, targetName));

    MechLOSBroadcast(mech,
	tprintf("attaches tow cables from %s to %s!", towMechName,
	    targetName));

    SetCarrying(towMech, target->mynum);
    MechSwarmTarget(target) = -1;

    if (MechType(target) == CLASS_MECH) {
	MechStatus(target) |= FALLEN;
	FallCentersTorso(target);
	StopStand(target);
    }

    MechStatus(target) |= TOWED;
    MechStatus(target) &= ~HULLDOWN;
    MechTankCritStatus(target) &= ~DUG_IN;

    if (!Destroyed(target))
	Shutdown(target);

    /* Adjust the speed involved */
    correct_speed(towMech);
}

void mech_detachcables(dbref player, void *data, char *buffer)
{
    MECH *mech = (MECH *) data;
    MECH *towMech;
    MECH *target;
    dbref towMech_num;
    MAP *newmap;
    dbref aRef;
    int argc;
    char *args[2];
    char mechName[SBUF_SIZE];
    char towMechName[SBUF_SIZE];
    char targetName[SBUF_SIZE];

    cch(MECH_USUAL);

    argc = mech_parseattributes(buffer, args, 1);
    DOCHECK(argc != 1, "Invalid number of arguments.");

    towMech_num = FindTargetDBREFFromMapNumber(mech, args[0]);
    DOCHECK(towMech_num == -1,
	"That towing unit is not in your line of sight.");
    towMech = getMech(towMech_num);
    DOCHECK(!towMech ||
	!InLineOfSight(mech, towMech, MechX(towMech), MechY(towMech),
	    FaMechRange(mech, towMech)),
	"That towing unit is not in your line of sight.");
    DOCHECK(MechX(mech) != MechX(towMech) ||
	MechY(mech) != MechY(towMech),
	"You need to be in the same hex as the towing unit!");
    DOCHECK(MechZ(mech) != MechZ(towMech),
	"You must be on the same elevation as the towing unit!");
    DOCHECK(MechCarrying(towMech) <= 0, "That unit is not towing anyone!");

    aRef = MechCarrying(towMech);
    SetCarrying(towMech, -1);
    target = getMech(aRef);
    DOCHECK(!target, "The towed unit was invalid!");
    MechStatus(target) &= ~TOWED;	/* Reset the Towed flag */

    strcpy(mechName, GetMechID(mech));
    strcpy(towMechName, GetMechID(towMech));
    strcpy(targetName, GetMechID(target));

    mech_notify(mech, MECHALL,
	tprintf("You detach %s's tow lines from %s.", towMechName,
	    targetName));
    mech_notify(towMech, MECHALL,
	tprintf("%s detaches your tow lines from %s.", mechName,
	    targetName));
    mech_notify(target, MECHALL, "You have been released from towing.");

    StopMoving(target);
    MechSpeed(target) = 0;
    MechDesiredSpeed(target) = 0;

    MechLOSBroadcast(mech, tprintf("detaches %s's tow cables from %s!",
	towMechName, targetName));

    if ((newmap = getMap(target->mapindex))) {
	MechZ(target) = Elevation(newmap, MechX(towMech), MechY(towMech));
    }

    correct_speed(towMech);
}

void mech_dropoff(dbref player, void *data, char *buffer)
{
    MECH *mech = (MECH *) data;
    MECH *target;
    MAP *newmap;
    dbref aRef;
    int x, y;

    if (player != GOD)
        cch(MECH_USUAL);

    DOCHECK(MechCarrying(mech) <= 0, "You aren't carrying a mech!");
    aRef = MechCarrying(mech);
    SetCarrying(mech, -1);
    target = getMech(aRef);
    DOCHECK(!target, "You were towing invalid target!");
    MechStatus(target) &= ~TOWED;	/* Reset the Towed flag */
    mech_notify(mech, MECHALL, "You drop the mech you were carrying.");
    mech_notify(target, MECHALL, "You have been released from towing.");

    StopMoving(target);
    MechSpeed(target) = 0;
    MechDesiredSpeed(target) = 0;

    if ((newmap = getMap(target->mapindex))) {
        MechLOSBroadcasti(mech, target, "drops %s!");
        if ((x = MechZ(target)) > ((y =
                        Elevation(newmap, MechX(target),
                            MechY(target))) + 2)) {
            mech_notify(mech, MECHALL,
                    "Maybe you should have done this closer to the ground.");
            mech_notify(target, MECHALL,
                    "You wish he had done that a might bit closer to the ground.");
            MechLOSBroadcast(target, "falls through the sky.");
            MECHEVENT(target, EVENT_FALL, mech_fall_event, FALL_TICK, -1);
        } else {
            MechZ(target) = Elevation(newmap, MechX(mech), MechY(mech));
        }
    }
    correct_speed(mech);
    SendDebug(tprintf("#%d has dropped off #%d", mech->mynum, target->mynum));
}