btmux-0.6-rc4/doc/
btmux-0.6-rc4/event/
btmux-0.6-rc4/game/
btmux-0.6-rc4/game/maps/
btmux-0.6-rc4/game/mechs/
btmux-0.6-rc4/game/text/help/
btmux-0.6-rc4/game/text/help/cat_faction/
btmux-0.6-rc4/game/text/help/cat_inform/
btmux-0.6-rc4/game/text/help/cat_misc/
btmux-0.6-rc4/game/text/help/cat_mux/
btmux-0.6-rc4/game/text/help/cat_mux/cat_commands/
btmux-0.6-rc4/game/text/help/cat_mux/cat_functions/
btmux-0.6-rc4/game/text/help/cat_templates/
btmux-0.6-rc4/game/text/wizhelp/
btmux-0.6-rc4/include/
btmux-0.6-rc4/misc/
btmux-0.6-rc4/python/
btmux-0.6-rc4/src/hcode/btech/
btmux-0.6-rc4/tree/
/*
 * $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);
}