/*
* $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));
}