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.tech.commands.c,v 1.1.1.1 2005/01/11 21:18:25 kstevens 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: Sun Sep  1 16:06:40 1996 fingon
 * Last modified: Thu Sep 10 07:37:29 1998 fingon
 *
 */

#include <math.h>
#include <string.h>
#include "mech.h"
#include "muxevent.h"
#include "mech.events.h"
#include "mech.tech.h"
#include "failures.h"
#include "p.mech.utils.h"
#include "p.mech.tech.h"
#include "p.mech.consistency.h"
#include "p.mech.tech.do.h"
#include "p.bsuit.h"

#define my_parsepart(loc,part) \
switch (tech_parsepart(mech, buffer, loc, part,NULL)) \
{ case -1: notify(player, "Invalid section!");return; \
case -2: notify(player, "Invalid part!");return; }

#define my_parsepart2(loc,part,brand) \
switch (tech_parsepart(mech, buffer, loc, part,brand)) \
{ case -1: notify(player, "Invalid section!");return; \
case -2: notify(player, "Invalid part!");return; }

#define my_parsegun(loc,part,brand) \
switch (tech_parsegun(mech, buffer, loc, part, brand)) \
{ case -1: notify(player, "Invalid gun #!");return; \
  case -2: notify(player, "Invalid object to replace with!");return; \
  case -3: notify(player, "Invalid object type - not matching with original.");return; \
  case -4: notify(player, "Invalid gun location - subscript out of range.");return; }

#define ClanMod(num) \
  MAX(1, (((num) / ((MechSpecials(mech) & CLAN_TECH) ? 2 : 1))))

static int tmp_flag = 0;
static int tmp_loc;
static int tmp_part;

static void tech_check_locpart(MUXEVENT * e)
{
    int loc, pos;
    int l = (int) e->data2;

    UNPACK_LOCPOS(l, loc, pos);
    if (loc == tmp_loc && pos == tmp_part)
	tmp_flag++;
}

static void tech_check_loc(MUXEVENT * e)
{
    int loc;

    loc = (((int) e->data2) % 16);
    if (loc == tmp_loc)
	tmp_flag++;
}

#define CHECK(t,fun) \
  tmp_flag=0;tmp_loc=loc;tmp_part = part; \
  muxevent_gothru_type_data(t, (void *) mech, fun); \
  return tmp_flag

#define CHECKL(t,fun) \
  tmp_flag=0;tmp_loc=loc; \
  muxevent_gothru_type_data(t, (void *) mech, fun); \
  return tmp_flag

#define CHECK2(t,t2,fun) \
  tmp_flag=0;tmp_loc=loc;tmp_part = part; \
  muxevent_gothru_type_data(t, (void *) mech, fun); \
  muxevent_gothru_type_data(t2, (void *) mech, fun); \
  return tmp_flag


/* Replace/reload */
int SomeoneRepairing_s(MECH * mech, int loc, int part, int t)
{
    CHECK(t, tech_check_locpart);
}

#define DAT(t) \
if (SomeoneRepairing_s(mech, loc, part, t)) return 1

int SomeoneRepairing(MECH * mech, int loc, int part)
{
    DAT(EVENT_REPAIR_RELO);
    DAT(EVENT_REPAIR_REPL);
    DAT(EVENT_REPAIR_REPLG);
    DAT(EVENT_REPAIR_REPAP);
    DAT(EVENT_REPAIR_REPAG);
    DAT(EVENT_REPAIR_MOB);
    DAT(EVENT_REPAIR_REPENHCRIT);
    return 0;
}

/* Fixinternal/armor */
int SomeoneFixingA(MECH * mech, int loc)
{
    CHECKL(EVENT_REPAIR_FIX, tech_check_loc);
}

int SomeoneFixingI(MECH * mech, int loc)
{
    CHECKL(EVENT_REPAIR_FIXI, tech_check_loc);
}

int SomeoneFixing(MECH * mech, int loc)
{
    return SomeoneFixingA(mech, loc) || SomeoneFixingI(mech, loc);
}

/* Reattach */
int SomeoneAttaching(MECH * mech, int loc)
{
    CHECKL(EVENT_REPAIR_REAT, tech_check_loc);
}

int SomeoneReplacingSuit(MECH * mech, int loc)
{
    CHECKL(EVENT_REPAIR_REPSUIT, tech_check_loc);
}

/* Reseal
 *
 * Added by Kipsta
 * 8/4/99
 */

int SomeoneResealing(MECH * mech, int loc)
{
    CHECKL(EVENT_REPAIR_RESE, tech_check_loc);
}

int SomeoneScrappingLoc(MECH * mech, int loc)
{
    CHECKL(EVENT_REPAIR_SCRL, tech_check_loc);
}

int SomeoneScrappingPart(MECH * mech, int loc, int part)
{
    DAT(EVENT_REPAIR_SCRP);
    DAT(EVENT_REPAIR_SCRG);
    DAT(EVENT_REPAIR_UMOB);
    return 0;
}

#undef CHECK
#undef CHECK2
#undef DAT

int CanScrapLoc(MECH * mech, int loc)
{
    tmp_flag = 0;
    tmp_loc = loc % 8;
    muxevent_gothru_type_data(EVENT_REPAIR_REPL, (void *) mech,
	tech_check_loc);
    muxevent_gothru_type_data(EVENT_REPAIR_RELO, (void *) mech,
	tech_check_loc);
    return !tmp_flag && !SomeoneFixing(mech, loc);
}

int CanScrapPart(MECH * mech, int loc, int part)
{
    return !(SomeoneRepairing(mech, loc, part));
}

#define tech_gun_is_ok(a,b,c) !PartIsNonfunctional(a,b,c)

extern char *silly_get_uptime_to_string(int);

int ValidGunPos(MECH * mech, int loc, int pos)
{
    unsigned char weaparray_f[MAX_WEAPS_SECTION];
    unsigned char weapdata_f[MAX_WEAPS_SECTION];
    int critical_f[MAX_WEAPS_SECTION];
    int i, num_weaps_f;

    if ((num_weaps_f =
	    FindWeapons_Advanced(mech, loc, weaparray_f, weapdata_f,
		critical_f, 1)) < 0)
	return 0;
    for (i = 0; i < num_weaps_f; i++)
	if (critical_f[i] == pos)
	    return 1;
    return 0;
}

void tech_checkstatus(dbref player, void *data, char *buffer)
{
    MECH *mech = (MECH *) data;
    int i = figure_latest_tech_event(mech);
    char *ms;

    DOCHECK(!i, "The mech's ready to rock!");
    ms = silly_get_uptime_to_string(game_lag_time(i));
    notify(player, tprintf("The 'mech has approximately %s until done.",
	    ms));
}

TECHCOMMANDH(tech_removegun)
{
    TECHCOMMANDB;
    TECHCOMMANDC;
    my_parsegun(&loc, &part, NULL);
    DOCHECK(SectIsDestroyed(mech, loc),
	"That part's blown off! You can assume the gun's gone too!");
    DOCHECK(!IsWeapon(GetPartType(mech, loc, part)), "That's no gun!");
    DOCHECK(PartIsDestroyed(mech, loc, part), "That gun's gone already!");
    DOCHECK(!ValidGunPos(mech, loc, part),
	"You can't remove middle of a gun!");
    DOCHECK(SomeoneScrappingPart(mech, loc, part),
	"Someone's scrapping it already!");
    DOCHECK(!CanScrapPart(mech, loc, part),
	"Someone's tinkering with it already!");
    DOCHECK(SomeoneScrappingLoc(mech, loc),
	"Someone's scrapping that section - no additional removals are possible!");
    /* Ok.. Everything's valid (we hope). */
    if (tech_weapon_roll(player, mech, REMOVEG_DIFFICULTY) < 0) {
	START
	    ("Ack! Your attempt is far from perfect, you try to recover the gun..");
	if (tech_weapon_roll(player, mech, REMOVEG_DIFFICULTY) < 0) {
	    START("No good. Consider the part gone.");
	    FAKEREPAIR(REMOVEG_TIME * ClanMod(GetWeaponCrits(mech,
			Weapon2I(GetPartType(mech, loc, part)))),
		EVENT_REPAIR_SCRG, mech, PACK_LOCPOS_E(loc, part, mod));
	    mod = 3;
	    return;
	}
    }
    START("You start removing the gun..");
    STARTREPAIR(REMOVEG_TIME * ClanMod(GetWeaponCrits(mech,
		Weapon2I(GetPartType(mech, loc, part)))), mech,
	PACK_LOCPOS_E(loc, part, mod), muxevent_tickmech_removegun,
	EVENT_REPAIR_SCRG);
}


TECHCOMMANDH(tech_removepart)
{
    TECHCOMMANDB;
    TECHCOMMANDC;
    my_parsepart(&loc, &part);
    DOCHECK((t =
	    GetPartType(mech, loc, part)) == EMPTY,
	"That location is empty!");
    DOCHECK(SectIsDestroyed(mech, loc),
	"That part's blown off! You can assume the part's gone too!");
    DOCHECK(IsWeapon(t), "That's a gun - use removegun instead!");
    DOCHECK(PartIsDestroyed(mech, loc, part), "That part's gone already!");
    DOCHECK(IsCrap(GetPartType(mech, loc, part)),
	"That type isn't scrappable!");
    DOCHECK(t == Special(ENDO_STEEL) ||
	t == Special(FERRO_FIBROUS) || t == Special(STEALTH_ARMOR) ||
	t == Special(HVY_FERRO_FIBROUS) || t == Special(LT_FERRO_FIBROUS),
	"That type of item can't be removed!");
    DOCHECK(SomeoneScrappingPart(mech, loc, part),
	"Someone's scrapping it already!");
    DOCHECK(SomeoneScrappingLoc(mech, loc),
	"Someone's scrapping that section - no additional removals are possible!");
    DOCHECK(!CanScrapPart(mech, loc, part),
	"Someone's tinkering with it already!");
    /* Ok.. Everything's valid (we hope). */
    START("You start removing the part..");
    if (tech_roll(player, mech, REMOVEP_DIFFICULTY) < 0) {
	START
	    ("Ack! Your attempt is far from perfect, you try to recover the part..");
	if (tech_roll(player, mech, REMOVEP_DIFFICULTY) < 0) {
	    START("No good. Consider the part gone.");
	    mod = 3;
	    FAKEREPAIR(REMOVEP_TIME, EVENT_REPAIR_SCRP, mech,
		PACK_LOCPOS_E(loc, part, mod));
	    return;
	}
    }
    STARTREPAIR(REMOVEP_TIME, mech, PACK_LOCPOS_E(loc, part, mod),
	muxevent_tickmech_removepart, EVENT_REPAIR_SCRP);
}

#define CHECK_S(nloc) \
if (!SectIsDestroyed(mech,nloc)) return 1; \
if (Invalid_Scrap_Path(mech,nloc)) return 1

#define CHECK(tloc,nloc) \
case tloc: CHECK_S(nloc)

int Invalid_Scrap_Path(MECH * mech, int loc)
{
    if (loc < 0)
	return 0;
    if (MechType(mech) != CLASS_MECH)
	return 0;
    switch (loc) {
	CHECK(CTORSO, HEAD);
	CHECK_S(LTORSO);
	CHECK_S(RTORSO);
	break;
	CHECK(LTORSO, LARM);
	break;
	CHECK(RTORSO, RARM);
	break;
    }
    return 0;
}

#undef CHECK
#undef CHECK_S

TECHCOMMANDH(tech_removesection)
{
    TECHCOMMANDB;
    TECHCOMMANDC;
    my_parsepart(&loc, NULL);
    DOCHECK(SectIsDestroyed(mech, loc), "That section's gone already!");
    DOCHECK(Invalid_Scrap_Path(mech, loc),
	"You need to remove the outer sections first!");
    DOCHECK(SomeoneScrappingLoc(mech, loc),
	"Someone's scrapping it already!");
    DOCHECK(!CanScrapLoc(mech, loc),
	"Someone's tinkering with it already!");
    /* Ok.. Everything's valid (we hope). */
    if (tech_roll(player, mech, REMOVES_DIFFICULTY) < 0)
	mod = 3;
    START("You start removing the section..");
    STARTREPAIR(REMOVES_TIME, mech, PACK_LOCPOS_E(loc, 0, mod),
	muxevent_tickmech_removesection, EVENT_REPAIR_SCRL);
}


TECHCOMMANDH(tech_replacegun)
{
    int brand = 0, ob = 0;

    TECHCOMMANDB;
    TECHCOMMANDC;
    my_parsegun(&loc, &part, &brand);
    DOCHECK(SectIsDestroyed(mech, loc),
	"That part's blown off! Use reattach first!");
    DOCHECK(SectIsFlooded(mech, loc),
	"That location has been flooded! Use reseal first!");
    DOCHECK(SomeoneRepairing(mech, loc, part),
	"Someone's repairing that part already!");
    DOCHECK(!IsWeapon(GetPartType(mech, loc, part)), "That's no gun!");
    DOCHECK(!ValidGunPos(mech, loc, part),
	"You can't replace middle of a gun!");
    DOCHECK(!PartIsNonfunctional(mech, loc, part),
	"That gun isn't hurtin'!");
    DOCHECK(SomeoneScrappingLoc(mech, loc),
	"Someone's scrapping that section - no repairs are possible!");
    if (brand) {
	ob = GetPartBrand(mech, loc, part);
	SetPartBrand(mech, loc, part, brand);
    }
    DOTECH_LOCPOS(REPLACE_DIFFICULTY +
	WEAPTYPE_DIFFICULTY(GetPartType(mech, loc, part)), replaceg_fail,
	replaceg_succ, replace_econ,
	REPLACEGUN_TIME * ClanMod(GetWeaponCrits(mech,
		Weapon2I(GetPartType(mech, loc, part)))), mech,
	PACK_LOCPOS_E(loc, part, brand), muxevent_tickmech_replacegun,
	EVENT_REPAIR_REPLG, "You start replacing the gun..", 1);
    if (brand)
	SetPartBrand(mech, loc, part, ob);
}

TECHCOMMANDH(tech_repairgun)
{
    int extra_hard = 0;

    TECHCOMMANDB;
    TECHCOMMANDC;
    /* Find the gun for us */
    my_parsegun(&loc, &part, NULL);
    DOCHECK(SectIsDestroyed(mech, loc),
	"That part's blown off! Use reattach first!");
    DOCHECK(SectIsFlooded(mech, loc),
	"That location has been flooded! Use reseal first!");
    DOCHECK(SomeoneRepairing(mech, loc, part),
	"Someone's repairing that part already!");
    DOCHECK(!IsWeapon(GetPartType(mech, loc, part)), "That's no gun!");
    DOCHECK(!ValidGunPos(mech, loc, part),
	"You can't repair middle of a gun!");
    DOCHECK(SomeoneScrappingPart(mech, loc, part),
	"Someone's scrapping it already!");
    DOCHECK(SomeoneScrappingLoc(mech, loc),
	"Someone's scrapping that section - no repairs are possible!");
    DOCHECK(PartIsDisabled(mech, loc, part),
	"That gun can't be fixed yet!");

    if (PartIsDestroyed(mech, loc, part)) {
	if (GetWeaponCrits(mech, Weapon2I(GetPartType(mech, loc,
			part))) < 5 ||
	    PartIsDestroyed(mech, loc, part + 1)) {
	    notify(player, "That gun is gone for good!");
	    return;
	}
	extra_hard = 1;
    } else if (!PartTempNuke(mech, loc, part)) {
	notify(player, "That gun isn't hurtin'!");
	return;
    }

    DOTECH_LOCPOS(REPAIR_DIFFICULTY + WEAPTYPE_DIFFICULTY(GetPartType(mech,
		loc, part)) + extra_hard, repairg_fail, repairg_succ,
	repair_econ, REPAIRGUN_TIME, mech, PACK_LOCPOS(loc, part),
	muxevent_tickmech_repairgun, EVENT_REPAIR_REPAP,
	"You start repairing the weapon..", 1);
}

TECHCOMMANDH(tech_fixenhcrit)
{
    int extra_hard = 0;

    TECHCOMMANDB;
    TECHCOMMANDC;
    /* Find the gun for us */
    my_parsegun(&loc, &part, NULL);
    DOCHECK(SectIsDestroyed(mech, loc),
	"That part's blown off! Use reattach first!");
    DOCHECK(SectIsFlooded(mech, loc),
	"That location has been flooded! Use reseal first!");
    DOCHECK(SomeoneRepairing(mech, loc, part),
	"Someone's repairing that part already!");
    DOCHECK(!IsWeapon(GetPartType(mech, loc, part)), "That's no gun!");
    DOCHECK(SomeoneScrappingPart(mech, loc, part),
	"Someone's scrapping it already!");
    DOCHECK(SomeoneScrappingLoc(mech, loc),
	"Someone's scrapping that section - no repairs are possible!");
    DOCHECK(PartIsDisabled(mech, loc, part),
	"That gun can't be fixed yet!");

    if (!PartIsDamaged(mech, loc, part)) {
	notify(player, "That gun isn't damaged!");
	return;
    }

    DOTECH_LOCPOS(ENHCRIT_DIFFICULTY,
	repairenhcrit_fail,
	repairenhcrit_succ,
	repairenhcrit_econ,
	REPAIRENHCRIT_TIME,
	mech,
	PACK_LOCPOS(loc, part),
	muxevent_tickmech_repairenhcrit,
	EVENT_REPAIR_REPENHCRIT, "You start repairing the weapon...", 1);
}

TECHCOMMANDH(tech_replacepart)
{
    TECHCOMMANDB;

    TECHCOMMANDC;
    my_parsepart(&loc, &part);
    DOCHECK((t =
	    GetPartType(mech, loc, part)) == EMPTY,
	"That location is empty!");
    DOCHECK(!PartIsNonfunctional(mech, loc, part),
	"That part looks ok to me..");
    DOCHECK(IsCrap(GetPartType(mech, loc, part)),
	"That part isn't hurtin'!");
    DOCHECK(IsWeapon(t), "That's a weapon! Use replacegun instead.");
    DOCHECK(SectIsDestroyed(mech, loc),
	"That part's blown off! Use reattach first!");
    DOCHECK(SectIsFlooded(mech, loc),
	"That location has been flooded! Use reseal first!");
    DOCHECK(SomeoneRepairing(mech, loc, part),
	"Someone's repairing that part already!");
    DOCHECK(SomeoneScrappingLoc(mech, loc),
	"Someone's scrapping that section - no repairs are possible!");
    DOTECH_LOCPOS(REPLACE_DIFFICULTY +
	PARTTYPE_DIFFICULTY(GetPartType(mech, loc, part)), replacep_fail,
	replacep_succ, replace_econ, REPLACEPART_TIME, mech,
	PACK_LOCPOS(loc, part), muxevent_tickmech_repairpart, EVENT_REPAIR_REPL,
	"You start replacing the part..", 0);
}

TECHCOMMANDH(tech_repairpart)
{
    TECHCOMMANDB;

    TECHCOMMANDC;
    my_parsepart(&loc, &part);
    DOCHECK((t =
	    GetPartType(mech, loc, part)) == EMPTY,
	"That location is empty!");
    DOCHECK(PartIsDestroyed(mech, loc, part),
	"That part is gone for good!");
    DOCHECK(PartIsDisabled(mech, loc, part),
	"That part can't be repaired yet!");
    DOCHECK(!PartTempNuke(mech, loc, part), "That part isn't hurtin'!");
    DOCHECK(IsCrap(GetPartType(mech, loc, part)),
	"That part isn't hurtin'!");
    DOCHECK(IsWeapon(t), "That's a weapon! Use repairgun instead.");
    DOCHECK(SectIsDestroyed(mech, loc),
	"That part's blown off! Use reattach first!");
    DOCHECK(SectIsFlooded(mech, loc),
	"That location has been flooded! Use reseal first!");
    DOCHECK(SomeoneRepairing(mech, loc, part),
	"Someone's repairing that part already!");
    DOCHECK(SomeoneScrappingLoc(mech, loc),
	"Someone's scrapping that section - no repairs are possible!");
    DOTECH_LOCPOS(REPAIR_DIFFICULTY + PARTTYPE_DIFFICULTY(GetPartType(mech,
		loc, part)), repairp_fail, repairp_succ, repair_econ,
	REPAIRPART_TIME, mech, PACK_LOCPOS(loc, part),
	muxevent_tickmech_repairpart, EVENT_REPAIR_REPAP,
	"You start repairing the part..", 0);
}

TECHCOMMANDH(tech_toggletype)
{
    int atype;

    TECHCOMMANDB;

    DOCHECK((!Wizard(player)) && In_Character(mech->mynum),
	"This command only works in simpods!");
    my_parsepart2(&loc, &part, &atype);
    DOCHECK(!IsAmmo((t =
		GetPartType(mech, loc, part))), "That's no ammo!");
    DOCHECK(PartIsNonfunctional(mech, loc, part) ||
	PartIsDisabled(mech, loc, part),
	"The ammo compartment is nonfunctional!");
    DOCHECK(!atype,
	"You need to give a type to toggle to (use - for normal)");
    DOCHECK((t =
	    (valid_ammo_mode(mech, loc, part, atype))) < 0,
	"That is invalid ammo type for this weapon!");
    GetPartAmmoMode(mech, loc, part) &= ~(AMMO_MODES);
    GetPartAmmoMode(mech, loc, part) |= t;
    SetPartData(mech, loc, part, FullAmmo(mech, loc, part));
    mech_notify(mech, MECHALL, "Ammo toggled.");
}



TECHCOMMANDH(tech_reload)
{
    int atype;

    TECHCOMMANDB;
    TECHCOMMANDD;
    my_parsepart2(&loc, &part, &atype);
    DOCHECK(!IsAmmo((t =
		GetPartType(mech, loc, part))), "That's no ammo!");
    DOCHECK(PartIsNonfunctional(mech, loc, part),
	"The ammo compartment is destroyed ; repair/replacepart it first.");
    DOCHECK(PartIsDisabled(mech, loc, part),
	"The ammo compartment is disabled ; repair/replacepart it first.");
    DOCHECK((now = GetPartData(mech, loc, part)) == (full =
	    FullAmmo(mech, loc, part)),
	"That particular ammo compartment doesn't need reloading.");
    DOCHECK(SomeoneRepairing(mech, loc, part),
	"Someone's playing with that part already!");
    DOCHECK(SectIsDestroyed(mech, loc),
	"That part's blown off! Use reattach first!");
    DOCHECK(SectIsFlooded(mech, loc),
	"That location has been flooded! Use reseal first!");
    DOCHECK(SomeoneScrappingLoc(mech, loc),
	"Someone's scrapping that section - no repairs are possible!");
    if (atype) {
	DOCHECK((t =
		(valid_ammo_mode(mech, loc, part, atype))) < 0,
	    "That is invalid ammo type for this weapon!");
	SetPartData(mech, loc, part, 0);
	GetPartAmmoMode(mech, loc, part) &= ~(AMMO_MODES);
	GetPartAmmoMode(mech, loc, part) |= t;
    }
    change = 0;
    DOTECH_LOCPOS_VAL(RELOAD_DIFFICULTY, reload_fail, reload_succ,
	reload_econ, &change, RELOAD_TIME, mech, PACK_LOCPOS_E(loc, part,
	    change), muxevent_tickmech_reload, EVENT_REPAIR_RELO,
	"You start reloading the ammo compartment..");
}

TECHCOMMANDH(tech_unload)
{
    TECHCOMMANDB;

    TECHCOMMANDD;
    my_parsepart(&loc, &part);
    DOCHECK(!IsAmmo((t =
		GetPartType(mech, loc, part))), "That's no ammo!");
    DOCHECK(PartIsNonfunctional(mech, loc, part),
	"The ammo compartment is destroyed ; repair/replacepart it first.");
    DOCHECK(PartIsDisabled(mech, loc, part),
	"The ammo compartment is disabled ; repair/replacepart it first.");
    DOCHECK(!(now =
	    GetPartData(mech, loc, part)),
	"That particular ammo compartment is empty already.");
    DOCHECK(SomeoneRepairing(mech, loc, part),
	"Someone's playing with that part already!");
    DOCHECK(SectIsDestroyed(mech, loc),
	"That part's blown off! Use reattach first!");
    DOCHECK(SectIsFlooded(mech, loc),
	"That location has been flooded! Use reseal first!");
    DOCHECK(SomeoneScrappingLoc(mech, loc),
	"Someone's scrapping that section - no repairs are possible!");
    if ((full = FullAmmo(mech, loc, part)) == now)
	change = 2;
    else
	change = 1;
    if (tech_roll(player, mech, REMOVES_DIFFICULTY) < 0)
	mod = 3;
    START("You start unloading the ammo compartment..");
    STARTREPAIR(RELOAD_TIME, mech, PACK_LOCPOS_E(loc, part, change),
	muxevent_tickmech_reload, EVENT_REPAIR_RELO);
}

TECHCOMMANDH(tech_fixarmor)
{
    int ochange;

    TECHCOMMANDB;

    TECHCOMMANDD;
    DOCHECK(tech_parsepart_advanced(mech, buffer, &loc, NULL, NULL, 1) < 0,
	"Invalid section!");
    if (loc >= 8) {
	from = GetSectRArmor(mech, loc % 8);
	to = GetSectORArmor(mech, loc % 8);
    } else {
	from = GetSectArmor(mech, loc);
	to = GetSectOArmor(mech, loc);
    }
    DOCHECK(SectIsDestroyed(mech, loc % 8),
	"That part's blown off! Use reattach first!");
    DOCHECK(SectIsFlooded(mech, loc % 8),
	"That location has been flooded! Use reseal first!");
    DOCHECK(SomeoneFixingA(mech, loc) ||
	SomeoneFixingI(mech, loc % 8),
	"Someone's repairing that section already!");
    DOCHECK(GetSectInt(mech, loc % 8) != GetSectOInt(mech, loc % 8),
	"The internals need to be fixed first!");
    DOCHECK(SomeoneScrappingLoc(mech, loc),
	"Someone's scrapping that section - no repairs are possible!");
    from = MIN(to, from);
    DOCHECK(from == to, "The location doesn't need armor repair!");
    change = to - from;
    ochange = change;
    DOTECH_LOC_VAL_S(FIXARMOR_DIFFICULTY, fixarmor_fail, fixarmor_succ,
	fixarmor_econ, &change, FIXARMOR_TIME * ochange, loc,
	EVENT_REPAIR_FIX, mech, "You start fixing the armor..");
    STARTIREPAIR(FIXARMOR_TIME * change, mech, (change * 16 + loc),
	muxevent_tickmech_repairarmor, EVENT_REPAIR_FIX, change);
}

TECHCOMMANDH(tech_fixinternal)
{
    TECHCOMMANDB int ochange;

    TECHCOMMANDC;
    my_parsepart(&loc, NULL);
    from = GetSectInt(mech, loc);
    to = GetSectOInt(mech, loc);
    DOCHECK(from == to, "The location doesn't need internals' repair!");
    change = to - from;
    DOCHECK(SectIsDestroyed(mech, loc),
	"That part's blown off! Use reattach first!");
    DOCHECK(SectIsFlooded(mech, loc),
	"That location has been flooded! Use reseal first!");
    DOCHECK(SomeoneFixing(mech, loc),
	"Someone's repairing that section already!");
    DOCHECK(SomeoneScrappingLoc(mech, loc),
	"Someone's scrapping that section - no repairs are possible!");
    ochange = change;
    DOTECH_LOC_VAL_S(FIXINTERNAL_DIFFICULTY, fixinternal_fail,
	fixinternal_succ, fixinternal_econ, &change,
	FIXINTERNAL_TIME * ochange, loc, EVENT_REPAIR_FIX, mech,
	"You start fixing the internals..");
    STARTIREPAIR(FIXINTERNAL_TIME * change, mech, (change * 16 + loc),
	muxevent_tickmech_repairinternal, EVENT_REPAIR_FIXI, change);
}


#define CHECK(tloc,nloc) \
case tloc:if (SectIsDestroyed(mech,nloc))return 1;break;

int Invalid_Repair_Path(MECH * mech, int loc)
{
    if (MechType(mech) != CLASS_MECH)
	return 0;
    switch (loc) {
	CHECK(HEAD, CTORSO);
	CHECK(LTORSO, CTORSO);
	CHECK(RTORSO, CTORSO);
	CHECK(LARM, LTORSO);
	CHECK(RARM, RTORSO);
	CHECK(LLEG, CTORSO);
	CHECK(RLEG, CTORSO);
    }
    return 0;
}

int unit_is_fixable(MECH * mech)
{
    int i;

    for (i = 0; i < NUM_SECTIONS; i++) {
	if (!GetSectOInt(mech, i))
	    continue;
	if (!SectIsDestroyed(mech, i))
	    continue;
	if (MechType(mech) == CLASS_MECH)
	    if (i == CTORSO)
		return 0;
	if (MechType(mech) == CLASS_VTOL)
	    if (i != ROTOR)
		return 0;
	if (MechType(mech) == CLASS_VEH_GROUND)
	    if (i != TURRET)
		return 0;
    }
    return 1;
};

TECHCOMMANDH(tech_reattach)
{
    TECHCOMMANDB;

    TECHCOMMANDC;
    my_parsepart(&loc, NULL);
    DOCHECK(MechType(mech) == CLASS_BSUIT,
	"You can't reattach a Battlesuit! Use 'replacesuit'!");
    DOCHECK(!SectIsDestroyed(mech, loc), "That section isn't destroyed!");
    DOCHECK(Invalid_Repair_Path(mech, loc),
	"You need to reattach adjacent locations first!");
    DOCHECK(SomeoneAttaching(mech, loc),
	"Someone's attaching that section already!");
    DOCHECK(!unit_is_fixable(mech),
	"You see nothing to reattach it to (read:unit is cored).");
    DOTECH_LOC(REATTACH_DIFFICULTY, reattach_fail, reattach_succ,
	reattach_econ, REATTACH_TIME, mech, loc, muxevent_tickmech_reattach,
	EVENT_REPAIR_REAT, "You start replacing the section..");
}

TECHCOMMANDH(tech_replacesuit)
{
    int wSuits = 0;

    TECHCOMMANDB;

    TECHCOMMANDC;
    my_parsepart(&loc, NULL);
    DOCHECK(MechType(mech) != CLASS_BSUIT,
	"You can only use 'replacesuit' on a battlesuit unit!");

    wSuits = CountBSuitMembers(mech);

    DOCHECK(MechMaxSuits(mech) <= wSuits,
	tprintf
	("This %s is already full! This %s only consists of %d suits!",
	    GetLCaseBSuitName(mech), GetLCaseBSuitName(mech),
	    MechMaxSuits(mech)));
    DOCHECK((loc >= MechMaxSuits(mech)) ||
	(loc < 0),
	tprintf("Invalid suit! This %s only consists of %d suits!",
	    GetLCaseBSuitName(mech), MechMaxSuits(mech)));

    DOCHECK(!SectIsDestroyed(mech, loc), "That suit isn't destroyed!");

    DOCHECK(SomeoneReplacingSuit(mech, loc),
	"Someone's already rebuilding that suit!");
    DOCHECK(wSuits <= 0,
	"You are unable to replace the suits here! None of the buggers are still alive!");
    DOTECH_LOC(REPLACESUIT_DIFFICULTY, replacesuit_fail, replacesuit_succ,
	replacesuit_econ, REPLACESUIT_TIME, mech, loc,
	muxevent_tickmech_replacesuit, EVENT_REPAIR_REPSUIT,
	"You start replacing the missing suit.");
}

/*
 * Reseal
 * Added by Kipsta
 * 8/4/99
 */

TECHCOMMANDH(tech_reseal)
{
    TECHCOMMANDB;

    TECHCOMMANDC;
    my_parsepart(&loc, NULL);
    DOCHECK(SectIsDestroyed(mech, loc), "That section is destroyed!");
    DOCHECK(!SectIsFlooded(mech, loc), "That has not been flooded!");
    DOCHECK(Invalid_Repair_Path(mech, loc),
	"You need to reattach adjacent locations first!");
    DOCHECK(SomeoneResealing(mech, loc),
	"Someone's sealing that section already!");
    DOTECH_LOC(RESEAL_DIFFICULTY, reseal_fail, reseal_succ, reseal_econ,
	RESEAL_TIME, mech, loc, muxevent_tickmech_reseal, EVENT_REPAIR_RESE,
	"You start resealing the section.");
}

TECHCOMMANDH(tech_magic)
{
    TECHCOMMANDB;

    TECHCOMMANDC;
    notify(player, "Doing the magic..");
    do_magic(mech);
    mech_int_check(mech, 1);
    notify(player, "Done!");
}