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.damages.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: Mon Dec  2 19:00:35 1996 fingon
 * Last modified: Thu Sep 10 09:55:13 1998 fingon
 *
 */

#include "mech.h"
#include "mech.events.h"
#include "mech.tech.h"
#include "mech.tech.damages.h"
#include "coolmenu.h"
#include "mycool.h"
#include "failures.h"
#include "p.mech.utils.h"
#include "p.mech.tech.commands.h"
#include "p.mech.status.h"
#include "p.mech.build.h"

/* 0 = type, 1 = loc, 2 = (pos/amnt), 3 = (val) */
short damage_table[MAX_DAMAGES][3];
int damage_last;

const char *repair_need_msgs[] = {
    "Reattachment",
    "Repairs on %s",
    "Repairs on %s",
    "Repairs on %s",
    "Realign focus on %s",
    "Charging crystal repairs on %s",
    "Barrel repairs on %s",
    "Ammo feed repairs on %s",
    "Ranging system repairs on %s",
    "Ammo feed repairs on %s",
    "Replacement of %s",
    "Reload of %s (%d rounds)",
    "Repairs on armor (%d points)",
    "Repairs on rear armor (%d points)",
    "Repairs on internals (%d points)",
    "Removal of section",
    "Removal of %s",
    "Removal of %s",
    "Unload of %s (%d rounds)",
    "Reseal",
    "Replace suit",
};

#define CHECK(loc) check_for_damage(mech,loc)
#define DAMAGE2(a,b) do {\
   damage_table[damage_last][0]=a;\
   damage_table[damage_last++][1]=b;\
 } while (0)
#define DAMAGE3(a,b,c) do {\
   damage_table[damage_last][0]=a;\
   damage_table[damage_last][1]=b;\
   damage_table[damage_last++][2]=c;\
 } while (0)

static int check_for_damage(MECH * mech, int loc)
{
    int a, b, c, d;

    if (SectIsDestroyed(mech, loc)) {
	if (MechType(mech) != CLASS_BSUIT)
	    DAMAGE2(REATTACH, loc);
	else
	    DAMAGE2(REPLACESUIT, loc);
	return 0;
    }

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

    if (SectIsFlooded(mech, loc)) {
	DAMAGE2(RESEAL, loc);
	return 0;
    }
    if ((a = GetSectInt(mech, loc)) != (b = GetSectOInt(mech, loc)))
	DAMAGE3(FIXINTERNAL, loc, (b - a));
    else {
	if ((a = GetSectArmor(mech, loc)) != (b =
		GetSectOArmor(mech, loc)))
	    DAMAGE3(FIXARMOR, loc, (b - a));
	if ((a = GetSectRArmor(mech, loc)) != (b =
		GetSectORArmor(mech, loc)))
	    DAMAGE3(FIXARMOR_R, loc, (b - a));
    }
    for (a = 0; a < NUM_CRITICALS; a++) {
	if (!(b = GetPartType(mech, loc, a)))
	    continue;
	if (IsAmmo(b) && !PartIsDestroyed(mech, loc, a) &&
	    (c = GetPartData(mech, loc, a)) != (d =
		FullAmmo(mech, loc, a)))
	    DAMAGE3(RELOAD, loc, a);
	if (!PartIsNonfunctional(mech, loc, a) &&
	    !PartTempNuke(mech, loc, a) && !PartIsDamaged(mech, loc, a))
	    continue;
	if (IsCrap(b))
	    continue;
	/* Destroyed / tempnuke'd part. Either case, it works for us :) */

	if (PartIsDamaged(mech, loc, a)) {
	    if (GetPartDamageFlags(mech, loc, a) & WEAP_DAM_EN_FOCUS)
		DAMAGE3(ENHCRIT_FOCUS, loc, a);
	    else if (GetPartDamageFlags(mech, loc,
		    a) & WEAP_DAM_EN_CRYSTAL)
		DAMAGE3(ENHCRIT_CRYSTAL, loc, a);
	    else if (GetPartDamageFlags(mech, loc,
		    a) & WEAP_DAM_BALL_BARREL)
		DAMAGE3(ENHCRIT_BARREL, loc, a);
	    else if (GetPartDamageFlags(mech, loc, a) & WEAP_DAM_BALL_AMMO)
		DAMAGE3(ENHCRIT_AMMOB, loc, a);
	    else if (GetPartDamageFlags(mech, loc,
		    a) & WEAP_DAM_MSL_RANGING)
		DAMAGE3(ENHCRIT_RANGING, loc, a);
	    else if (GetPartDamageFlags(mech, loc, a) & WEAP_DAM_MSL_AMMO)
		DAMAGE3(ENHCRIT_AMMOM, loc, a);
	    else
		DAMAGE3(ENHCRIT_MISC, loc, a);

	} else if (IsWeapon(b) && GetWeaponCrits(mech, Weapon2I(b)) > 4 &&
	    !PartIsDestroyed(mech, loc, a + 1))
	    DAMAGE3(REPAIRP_T, loc, a);
	else
	    DAMAGE3(IsWeapon(b) ? REPAIRG : REPAIRP, loc, a);

	if (IsWeapon(b))
	    a += GetWeaponCrits(mech, Weapon2I(b)) - 1;
    }
    return 1;
}

static int check_for_scrappage(MECH * mech, int loc)
{
    int a, b;
    int ret = 1;

    if (SectIsDestroyed(mech, loc))
	return 1;

    if (SomeoneScrappingLoc(mech, loc)) {
	DAMAGE2(DETACH, loc);
	return 1;
    }
    for (a = 0; a < NUM_CRITICALS; a++) {
	if (!(b = GetPartType(mech, loc, a)))
	    continue;
	if (PartIsBroken(mech, loc, a))
	    continue;
	if (IsCrap(b))
	    continue;
	if (IsAmmo(b) && GetPartData(mech, loc, a)) {
	    DAMAGE3(UNLOAD, loc, a);
	    if (ret && !SomeoneRepairing(mech, loc, a))
		ret = 0;
	    continue;
	}
	DAMAGE3(IsWeapon(b) ? SCRAPG : SCRAPP, loc, a);
	if (ret && !SomeoneScrappingPart(mech, loc, a))
	    ret = 0;
	if (IsWeapon(b))
	    a += GetWeaponCrits(mech, Weapon2I(b)) - 1;
    }

    if (ret && !Invalid_Scrap_Path(mech, loc))
	DAMAGE2(DETACH, loc);

    return 0;
}

void make_scrap_table(MECH * mech)
{
    int i = 4;

    damage_last = 0;
    if (MechType(mech) == CLASS_MECH) {
	if (check_for_scrappage(mech, RARM))
	    i -= check_for_scrappage(mech, RTORSO);
	if (check_for_scrappage(mech, LARM))
	    i -= check_for_scrappage(mech, LTORSO);
	i -= check_for_scrappage(mech, RLEG);
	i -= check_for_scrappage(mech, LLEG);

	if (!i)
	    check_for_scrappage(mech, CTORSO);

	check_for_scrappage(mech, HEAD);
    } else
	for (i = 0; i < NUM_SECTIONS; i++)
	    if (GetSectOInt(mech, i))
		check_for_scrappage(mech, i);
}

void make_damage_table(MECH * mech)
{
    int i;

    damage_last = 0;
    if (MechType(mech) == CLASS_MECH) {
	if (check_for_damage(mech, CTORSO)) {
	    if (check_for_damage(mech, LTORSO)) {
		CHECK(LARM);
	    }
	    if (check_for_damage(mech, RTORSO)) {
		CHECK(RARM);
	    }
	    CHECK(LLEG);
	    CHECK(RLEG);
	    CHECK(HEAD);
	}
    } else
	for (i = 0; i < NUM_SECTIONS; i++)
	    if (GetSectOInt(mech, i))
		check_for_damage(mech, i);
}

int is_under_repair(MECH * mech, int i)
{
    int v1 = damage_table[i][1];
    int v2 = damage_table[i][2];

    switch (damage_table[i][0]) {
    case RELOAD:
    case REPAIRP:
    case REPAIRP_T:
    case REPAIRG:
    case UNLOAD:
    case ENHCRIT_MISC:
    case ENHCRIT_FOCUS:
    case ENHCRIT_CRYSTAL:
    case ENHCRIT_BARREL:
    case ENHCRIT_AMMOB:
    case ENHCRIT_RANGING:
    case ENHCRIT_AMMOM:
	return SomeoneRepairing(mech, v1, v2);
    case REATTACH:
	return SomeoneAttaching(mech, v1);
    case RESEAL:
	return SomeoneResealing(mech, v1);
    case FIXARMOR_R:
	return SomeoneFixing(mech, v1 + 8);
    case FIXARMOR:
    case FIXINTERNAL:
	return SomeoneFixing(mech, v1);
    case DETACH:
	return SomeoneScrappingLoc(mech, v1);
    case SCRAPP:
    case SCRAPG:
	return SomeoneScrappingPart(mech, v1, v2);
    case REPLACESUIT:
	return SomeoneReplacingSuit(mech, v1);
    }
    return 0;
}

char *damages_func(MECH * mech)
{
    static char buffer[MBUF_SIZE];
    int i;

    if (unit_is_fixable(mech))
        make_damage_table(mech);
    else
        make_scrap_table(mech);

    buffer[0] = '\0';
    if (!damage_last)
        return "";
    for (i = 0; i < damage_last; i++) {
        /* Ok... i think we want: */
        /* repairnum|location|typenum|data|fixing? */
        if (i)
            sprintf(buffer, "%s,", buffer);
        sprintf(buffer, "%s%d|%s|%d|", buffer, i + 1,
                ShortArmorSectionString(MechType(mech), MechMove(mech),
                    damage_table[i][1]), (int) damage_table[i][0]);
        switch (damage_table[i][0]) {
            case REPAIRP:
            case REPAIRP_T:
            case REPAIRG:
            case ENHCRIT_MISC:
            case ENHCRIT_FOCUS:
            case ENHCRIT_CRYSTAL:
            case ENHCRIT_BARREL:
            case ENHCRIT_AMMOB:
            case ENHCRIT_RANGING:
            case ENHCRIT_AMMOM:
            case SCRAPP:
            case SCRAPG:
                sprintf(buffer, "%s%s", buffer, pos_part_name(mech,
                            damage_table[i][1], damage_table[i][2]));
                break;
            case RELOAD:
                sprintf(buffer, "%s%s:%d", buffer, pos_part_name(mech,
                            damage_table[i][1], damage_table[i][2]), FullAmmo(mech,
                                damage_table[i][1],
                                damage_table[i][2]) - GetPartData(mech,
                                    damage_table[i][1], damage_table[i][2]));
                break;
            case UNLOAD:
                sprintf(buffer, "%s%s:%d", buffer, pos_part_name(mech,
                            damage_table[i][1], damage_table[i][2]),
                        GetPartData(mech, damage_table[i][1], damage_table[i]
                            [2]));
                break;
            case FIXARMOR:
            case FIXARMOR_R:
            case FIXINTERNAL:
                sprintf(buffer, "%s%d", buffer, damage_table[i][2]);
                break;
            default:
                sprintf(buffer, "%s-", buffer);
        }
        sprintf(buffer, "%s|%d", buffer, is_under_repair(mech, i));
    }
    return buffer;
}

void show_mechs_damage(dbref player, void *data, char *buffer)
{
    MECH *mech = data;
    coolmenu *c = NULL;
    int i, j, v1, v2;
    char buf[MBUF_SIZE];
    char buf2[MBUF_SIZE];
    int isds;

    TECHCOMMANDD;
    if (unit_is_fixable(mech))
	make_damage_table(mech);
    else
	make_scrap_table(mech);
    DOCHECK(!damage_last &&
	MechType(mech) == CLASS_MECH,
	"The 'mech is in pristine condition!");
    DOCHECK(!damage_last, "It's in pristine condition!");
    addline();
    cent(tprintf("Damage for %s", GetMechID(mech)));
    addline();
    for (i = 0; i < damage_last; i++) {
	v1 = damage_table[i][1];
	v2 = damage_table[i][2];
	switch (damage_table[i][0]) {
	case REATTACH:
	case DETACH:
	case RESEAL:
	case REPLACESUIT:
	    strcpy(buf, repair_need_msgs[(int) damage_table[i][0]]);
	    break;
	case REPAIRP:
	case REPAIRP_T:
	case REPAIRG:
	case ENHCRIT_MISC:
	case ENHCRIT_FOCUS:
	case ENHCRIT_CRYSTAL:
	case ENHCRIT_BARREL:
	case ENHCRIT_AMMOB:
	case ENHCRIT_RANGING:
	case ENHCRIT_AMMOM:
	case SCRAPP:
	case SCRAPG:
	    sprintf(buf, repair_need_msgs[(int) damage_table[i][0]],
		pos_part_name(mech, v1, v2));
	    break;
	case RELOAD:
	    sprintf(buf, repair_need_msgs[(int) damage_table[i][0]],
		pos_part_name(mech, v1, v2), FullAmmo(mech, v1,
		    v2) - GetPartData(mech, v1, v2));
	    break;
	case UNLOAD:
	    sprintf(buf, repair_need_msgs[(int) damage_table[i][0]],
		pos_part_name(mech, v1, v2), GetPartData(mech, v1, v2));
	    break;
	case FIXARMOR:
	case FIXARMOR_R:
	case FIXINTERNAL:
	    sprintf(buf, repair_need_msgs[(int) damage_table[i][0]],
		damage_table[i][2]);
	    break;
	}
	j = is_under_repair(mech, i);
	sprintf(buf2, "%%ch%s%-2d:%s %%cn%s%s", j ? "%cg" : "%cy", i + 1,
	    ShortArmorSectionString(MechType(mech), MechMove(mech), v1),
	    buf, j ? " (*)" : "");
	vsi(buf2);
    }
    addline();
    vsi("(*) / %ch%cgGreen%cn = Job already done. %ch%cyYellow%cn = To be done.");
    addline();
    ShowCoolMenu(player, c);
    KillCoolMenu(c);
}

static void fix_entry(dbref player, MECH * mech, int n)
{
    char buf[MBUF_SIZE];
    char *c;

    /* whee */
    n--;
    c = ShortArmorSectionString(MechType(mech), MechMove(mech),
	damage_table[n][1]);
    switch (damage_table[n][0]) {
    case REPAIRP_T:
	sprintf(buf, "%s %d", c, damage_table[n][2] + 1);
	tech_repairgun(player, mech, buf);
	break;
    case ENHCRIT_MISC:
    case ENHCRIT_FOCUS:
    case ENHCRIT_CRYSTAL:
    case ENHCRIT_BARREL:
    case ENHCRIT_AMMOB:
    case ENHCRIT_RANGING:
    case ENHCRIT_AMMOM:
	sprintf(buf, "%s %d", c, damage_table[n][2] + 1);
	tech_fixenhcrit(player, mech, buf);
	break;
    case REPAIRG:
	sprintf(buf, "%s %d", c, damage_table[n][2] + 1);
	tech_replacegun(player, mech, buf);
	break;
    case REPAIRP:
	sprintf(buf, "%s %d", c, damage_table[n][2] + 1);
	tech_replacepart(player, mech, buf);
	break;
    case RELOAD:
	sprintf(buf, "%s %d", c, damage_table[n][2] + 1);
	tech_reload(player, mech, buf);
	break;
    case REATTACH:
	sprintf(buf, "%s", c);
	tech_reattach(player, mech, buf);
	break;
    case RESEAL:
	sprintf(buf, "%s", c);
	tech_reseal(player, mech, buf);
	break;
    case FIXARMOR:
	sprintf(buf, "%s", c);
	tech_fixarmor(player, mech, buf);
	break;
    case FIXARMOR_R:
	sprintf(buf, "%s r", c);
	tech_fixarmor(player, mech, buf);
	break;
    case FIXINTERNAL:
	sprintf(buf, "%s", c);
	tech_fixinternal(player, mech, buf);
	break;
    case DETACH:
	sprintf(buf, "%s", c);
	tech_removesection(player, mech, buf);
	break;
    case SCRAPP:
	sprintf(buf, "%s %d", c, damage_table[n][2] + 1);
	tech_removepart(player, mech, buf);
	break;
    case SCRAPG:
	sprintf(buf, "%s %d", c, damage_table[n][2] + 1);
	tech_removegun(player, mech, buf);
	break;
    case UNLOAD:
	sprintf(buf, "%s %d", c, damage_table[n][2] + 1);
	tech_unload(player, mech, buf);
	break;
    case REPLACESUIT:
	sprintf(buf, "%s", c);
	tech_replacesuit(player, mech, buf);
	break;
    }
}

void tech_fix(dbref player, void *data, char *buffer)
{
    MECH *mech = data;
    int n = atoi(buffer);
    int low, high;
    int isds;

    skipws(buffer);
    TECHCOMMANDC;
    if (unit_is_fixable(mech))
	make_damage_table(mech);
    else
	make_scrap_table(mech);
    DOCHECK(!damage_last &&
	MechType(mech) == CLASS_MECH,
	"The 'mech is in pristine condition!");
    DOCHECK(!damage_last, "It's in pristine condition!");
    if (sscanf(buffer, "%d-%d", &low, &high) == 2) {
	DOCHECK(low < 1 || low > damage_last, "Invalid low #!");
	DOCHECK(high < 1 || high > damage_last, "Invalid high #!");
	for (n = low; n <= high; n++)
	    fix_entry(player, mech, n);
	return;
    }
    DOCHECK(n < 1 || n > damage_last, "Invalid #!");
    fix_entry(player, mech, n);
}