zim/area/
zim/bin/
zim/clans/plists/
zim/corefiles/
zim/doc/muddy/
zim/gods/
zim/log/
zim/player/
zim/skill_tree/
zim/tmp/
/*
 * $Id: repair.c 932 2006-11-11 00:07:22Z zsuzsu $
 */

/***************************************************************************
 *     ANATOLIA 2.1 is copyright 1996-1997 Serdar BULUT, Ibrahim CANPUNAR  *	
 *     ANATOLIA has been brought to you by ANATOLIA consortium		   *
 *	 Serdar BULUT {Chronos}		bulut@rorqual.cc.metu.edu.tr       *
 *	 Ibrahim Canpunar  {Asena}	canpunar@rorqual.cc.metu.edu.tr    *	
 *	 Murat BICER  {KIO}		mbicer@rorqual.cc.metu.edu.tr	   *	
 *	 D.Baris ACAR {Powerman}	dbacar@rorqual.cc.metu.edu.tr	   *	
 *     By using this code, you have agreed to follow the terms of the      *
 *     ANATOLIA license, in the file Anatolia/anatolia.licence             *	
 ***************************************************************************/

/***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

/***************************************************************************
*	ROM 2.4 is copyright 1993-1995 Russ Taylor			   *
*	ROM has been brought to you by the ROM consortium		   *
*	    Russ Taylor (rtaylor@pacinfo.com)				   *
*	    Gabrielle Taylor (gtaylor@pacinfo.com)			   *
*	    Brian Moore (rom@rom.efn.org)				   *
*	By using this code, you have agreed to follow the terms of the	   *
*	ROM license, in the file Rom24/doc/rom.license			   *
***************************************************************************/

#include <stdio.h>
#include "merc.h"

DECLARE_DO_FUN(do_say);

void damage_to_obj(CHAR_DATA * ch, OBJ_DATA * wield, OBJ_DATA * worn,
		   int damage)
{

	if (damage == 0)
		return;

	if (!wield || !worn) {
		bug("damage_to_obj: wield or worn is NULL", 0);
		return;
	}

	/* Hammers damage equipment more */
	if (wield->value[ITEM_WEAPON_TYPE] == WEAPON_HAMMER)
		damage *= 2;

	worn->condition -= damage;

	/* different message if damaged with a hammer */
	if (wield->value[ITEM_WEAPON_TYPE] == WEAPON_HAMMER)
		act_puts("{g$p {ginflicts {Rbrutal damage{g on {r$P{g.{x",
			 ch, wield, worn, TO_ROOM, POS_RESTING);
	else
		act_puts("{g$p {ginflicts damage on {r$P{g.{x",
			 ch, wield, worn, TO_ROOM, POS_RESTING);

	if (worn->condition < 1) {
		act_puts("{gThe {r$P{g breaks into pieces.{x",
			 ch, wield, worn, TO_ROOM, POS_RESTING);
		extract_obj(worn, 0);
		return;
	}

	if (IS_SET(wield->extra_flags, ITEM_ANTI_EVIL)
	    && IS_SET(wield->extra_flags, ITEM_ANTI_NEUTRAL)
	    && IS_SET(worn->extra_flags, ITEM_ANTI_EVIL)
	    && IS_SET(worn->extra_flags, ITEM_ANTI_NEUTRAL)) {
		act_puts("$p doesn't want to fight against $P.",
			 ch, wield, worn, TO_ROOM, POS_RESTING);
		act_puts("$p removes itself from you!",
			 ch, wield, worn, TO_CHAR, POS_RESTING);
		act_puts("$p removes itself from $n.",
			 ch, wield, worn, TO_ROOM, POS_RESTING);
		unequip_char(ch, wield);
		return;
	}

	if (IS_SET(wield->extra_flags, ITEM_ANTI_EVIL)
	    && IS_SET(worn->extra_flags, ITEM_ANTI_EVIL)) {
		act_puts("The $p worries for the damage to $P.",
			 ch, wield, worn, TO_ROOM, POS_RESTING);
		return;
	}
}

void do_repair(CHAR_DATA * ch, const char *argument)
{
	CHAR_DATA *mob;
	char arg[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	int cost;

	for (mob = ch->in_room->people; mob; mob = mob->next_in_room) {
		if (!IS_NPC(mob))
			continue;
		if (mob->spec_fun == spec_lookup("spec_repairman"))
			break;
	}

	if (mob == NULL) {
		char_puts("You can't do that here.\n", ch);
		return;
	}

	one_argument(argument, arg, sizeof(arg));

	if (arg[0] == '\0') {
		do_say(mob, "I will repair a weapon for you, for a price.");
		char_puts("Type estimate <weapon> to be assessed for damage.\n",
			  ch);
		return;
	}
	if ((obj = get_obj_carry(ch, arg)) == NULL) {
		do_say(mob, "You don't have that item");
		return;
	}

	if (obj->pIndexData->vnum == OBJ_VNUM_HAMMER) {
		do_say(mob, "That hammer is beyond my power.");
		return;
	}

	if (obj->condition >= 100) {
		do_say(mob, "But that item is not broken.");
		return;
	}

	if (obj->cost == 0) {
		/* XXX */
		doprintf(do_say, mob, "%s is beyond repair.\n",
			 mlstr_mval(obj->short_descr));
		return;
	}

	cost = ((obj->level * 10) +
		((obj->cost * (100 - obj->condition)) / 100));
	cost /= 100;

	if (cost > ch->gold) {
		do_say(mob, "You do not have enough gold for my services.");
		return;
	}

	WAIT_STATE(ch, PULSE_VIOLENCE);

	ch->gold -= cost;
	mob->gold += cost;
	act_puts("$n takes $p from $N, repairs it, and returns it to $N",
		 mob, obj, ch, TO_ROOM, POS_RESTING);
	obj->condition = 100;
}

void do_estimate(CHAR_DATA * ch, const char *argument)
{
	OBJ_DATA *obj;
	CHAR_DATA *mob;
	char arg[MAX_INPUT_LENGTH];
	int cost;

	for (mob = ch->in_room->people; mob; mob = mob->next_in_room) {
		if (!IS_NPC(mob))
			continue;
		if (mob->spec_fun == spec_lookup("spec_repairman"))
			break;
	}

	if (mob == NULL) {
		char_puts("You can't do that here.\n", ch);
		return;
	}

	one_argument(argument, arg, sizeof(arg));

	if (arg[0] == '\0') {
		do_say(mob, "Try estimate <item>");
		return;
	}
	if ((obj = (get_obj_carry(ch, arg))) == NULL) {
		do_say(mob, "You don't have that item");
		return;
	}
	if (obj->pIndexData->vnum == OBJ_VNUM_HAMMER) {
		do_say(mob, "That hammer is beyond my power.");
		return;
	}
	if (obj->condition >= 100) {
		do_say(mob, "But that item's not broken");
		return;
	}
	if (obj->cost == 0) {
		do_say(mob, "That item is beyond repair");
		return;
	}

	cost = ((obj->level * 10) +
		((obj->cost * (100 - obj->condition)) / 100));
	cost /= 100;

	doprintf(do_say, mob, "It will cost %d to fix that item", cost);
}

void do_restring(CHAR_DATA * ch, const char *argument)
{
#if 0
	CHAR_DATA *mob;
	char arg[MAX_INPUT_LENGTH];
	char arg1[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	int cost = 2000;

	for (mob = ch->in_room->people; mob; mob = mob->next_in_room) {
		if (IS_NPC(mob) && IS_SET(mob->pIndexData->act, ACT_HEALER))
			break;
	}

	if (mob == NULL) {
#endif
		char_puts("You can't do that here.\n", ch);
		return;
#if 0
		/* XXX */
	}

	argument = one_argument(argument, arg, sizeof(arg));
	argument = one_argument(argument, arg1, sizeof(arg1));

	if (arg[0] == '\0' || arg1[0] == '\0' || argument[0] == '\0') {
		char_puts("Syntax:\n", ch);
		char_puts("  restring <obj> <field> <string>\n", ch);
		char_puts("    fields: name short long\n", ch);
		return;
	}

	if ((obj = (get_obj_carry(ch, arg))) == NULL) {
		do_say(mob, "You don't have that item.");
		return;
	}

	cost += (obj->level * 1500);

	if (cost > ch->gold) {
		act("$N says 'You do not have enough gold for my services.'",
		    ch, NULL, mob, TO_CHAR);
		return;
	}

	if (!str_prefix(arg1, "name")) {
		free_string(obj->name);
		obj->name = str_dup(argument);
	} else if (!str_prefix(arg1, "short")) {
		free_string(obj->short_descr);
		obj->short_descr = str_dup(argument);
	} else if (!str_prefix(arg1, "long")) {
		free_string(obj->description);
		obj->description = str_dup(argument);
	} else {
		char_puts("That's not a valid Field.\n", ch);
		return;
	}

	WAIT_STATE(ch, PULSE_VIOLENCE);

	ch->gold -= cost;
	mob->gold += cost;
	act("$N takes $n's item, tinkers with it, and returns it to $n.",
	    ch, NULL, mob, TO_ROOM);
	act_puts("$N takes $p, tinkers with it and returns it to you.\n",
		 ch, obj, mob, TO_CHAR, POS_DEAD);
	act_puts("Remember, if we find your new string offensive, "
		 "we will not be happy.", chi, NULL, NULL, TO_CHAR, POS_DEAD);
	act_puts("This is your ONE AND ONLY warning.",
		 ch, NULL, NULL, TO_CHAR, POS_DEAD);
#endif
}

void do_smithing(CHAR_DATA * ch, const char *argument)
{
	char arg[MAX_INPUT_LENGTH];
	OBJ_DATA *obj;
	OBJ_DATA *hammer;
	int sn;
	int chance;

	if ((sn = sn_lookup("smithing")) < 0
	    || (chance = get_skill(ch, sn)) == 0) {
		char_puts("Huh?\n", ch);
		return;
	}

	if (ch->fighting) {
		char_puts("Wait until the fight finishes.\n", ch);
		return;
	}

	one_argument(argument, arg, sizeof(arg));
	if (arg[0] == '\0') {
		char_puts("Which object do you want to repair.\n", ch);
		return;
	}

	if ((obj = get_obj_carry(ch, arg)) == NULL) {
		char_puts("You are not carrying that.\n", ch);
		return;
	}

	if (obj->condition >= 100) {
		char_puts("But that item is not broken.\n", ch);
		return;
	}

	if ((hammer = get_eq_char(ch, WEAR_HOLD)) == NULL) {
		char_puts("You are not holding a hammer.\n", ch);
		return;
	}

	if (hammer->pIndexData->vnum != OBJ_VNUM_HAMMER) {
		char_puts("That is not the correct hammer.\n", ch);
		return;
	}

	WAIT_STATE(ch, SKILL(sn)->beats);
	if (number_percent() > chance) {
		check_improve(ch, sn, FALSE, 8);
		act_puts("$n tries to repair $p with the hammer but fails.",
			 ch, obj, NULL, TO_ROOM, POS_RESTING);
		act_puts("You failed to repair $p.",
			 ch, obj, NULL, TO_CHAR, POS_RESTING);
		hammer->condition -= 25;
	} else {
		check_improve(ch, sn, TRUE, 4);
		act_puts("$n repairs $p with the hammer.",
			 ch, obj, NULL, TO_ROOM, POS_RESTING);
		act_puts("You repair $p.", ch, obj, NULL, TO_CHAR, POS_RESTING);
		obj->condition = UMAX(100, obj->condition + (chance / 2));
		hammer->condition -= 25;
	}

	if (hammer->condition < 1)
		extract_obj(hammer, 0);
}

/*----------------------------------------------------------------------------
 * eq damage functions
 *	- the third parameter is the location of wielded weapon
 *	  (must be WEAR_WIELD or WEAR_SECOND_WIELD), not the
 *	  location of damaged eq
 */

void check_eq_damage(CHAR_DATA * ch, CHAR_DATA * victim, int loc)
{
	OBJ_DATA *wield, *destroy;
	int skill, chance = 0, sn, i;

	if (IS_NPC(victim) || number_percent() < 94)
		return;

	if ((wield = get_eq_char(ch, loc)) == NULL)
		return;
	sn = get_weapon_sn(wield);
	skill = get_skill(ch, sn);

	for (i = 0; i < MAX_WEAR; i++) {
		if ((destroy = get_eq_char(victim, i)) == NULL
		    || number_percent() > 95
		    || number_percent() > 94 || ch->level < (victim->level - 10)
		    || check_material(destroy, "platinum")
		    || check_material(destroy, "ionium")
		    || destroy->pIndexData->limit != -1
		    || (i == WEAR_WIELD || i == WEAR_SECOND_WIELD ||
			i == WEAR_TATTOO || i == WEAR_STUCK_IN ||
			i == WEAR_CLANMARK))
			continue;

		if (wield->pIndexData->extra_flags == ITEM_QUEST)
			continue;

		/* Wielded maces have higher chance of damaging things */
		if (wield->value[ITEM_WEAPON_TYPE] == WEAPON_MACE)
			chance += 5;

		if (is_metal(wield)) {
			if (number_percent() > skill)
				continue;

			chance += 20;
			if (check_material(wield, "platinium")
			    || check_material(wield, "titanium"))
				chance += 5;

			if (is_metal(destroy))
				chance -= 20;
			else
				chance += 20;

			chance += ((ch->level - victim->level) / 5);
			chance += ((wield->level - destroy->level) / 2);
		} else {
			if (number_percent() < skill)
				continue;

			chance += 10;

			if (is_metal(destroy))
				chance -= 20;
			chance += (ch->level - victim->level);
			chance += (wield->level - destroy->level);
		}

		/* sharpness */
		if (IS_WEAPON_STAT(wield, WEAPON_SHARP))
			chance += 10;

		if (sn == gsn_axe)
			chance += 10;

		/* spell affects */
		if (IS_OBJ_STAT(destroy, ITEM_BLESS))
			chance -= 10;
		if (IS_OBJ_STAT(destroy, ITEM_MAGIC))
			chance -= 20;

		chance += skill - 85;
		chance += get_curr_stat(ch, STAT_STR);

		if (number_percent() < chance && chance > 50) {
			damage_to_obj(ch, wield, destroy, chance / 5);
			break;
		}
	}
}

void check_shield_damage(CHAR_DATA * ch, CHAR_DATA * victim, int loc)
{
	OBJ_DATA *wield, *destroy;
	int skill, chance = 0, sn;

	if (IS_NPC(victim) || number_percent() < 94)
		return;

	if ((wield = get_eq_char(ch, loc)) == NULL)
		return;
	sn = get_weapon_sn(wield);
	skill = get_skill(ch, sn);

	if ((destroy = get_eq_char(victim, WEAR_SHIELD)) == NULL
	    || number_percent() > 94 || ch->level < (victim->level - 10)
	    || check_material(destroy, "platinum")
	    || check_material(destroy, "ionium")
	    || destroy->pIndexData->limit != -1)
		return;

	if (is_metal(wield)) {
		if (number_percent() > skill)
			return;

		chance += 20;
		if (check_material(wield, "platinium")
		    || check_material(wield, "titanium"))
			chance += 5;

		if (is_metal(destroy))
			chance -= 20;
		else
			chance += 20;

		chance += ((ch->level - victim->level) / 5);
		chance += ((wield->level - destroy->level) / 2);
	} else {
		if (number_percent() < skill)
			return;

		chance += 10;
		if (is_metal(destroy))
			chance -= 20;

		chance += (ch->level - victim->level);
		chance += (wield->level - destroy->level);
	}

	/* sharpness */
	if (IS_WEAPON_STAT(wield, WEAPON_SHARP))
		chance += 10;

	if (sn == gsn_axe)
		chance += 10;

	/* Wielded maces have higher chance of damaging things */
	if (wield->value[ITEM_WEAPON_TYPE] == WEAPON_MACE)
		chance += 15;

	/* spell affects */
	if (IS_OBJ_STAT(destroy, ITEM_BLESS))
		chance -= 10;
	if (IS_OBJ_STAT(destroy, ITEM_MAGIC))
		chance -= 20;

	chance += skill - 85;
	chance += get_curr_stat(ch, STAT_STR);

	if (number_percent() < chance && chance > 20)
		damage_to_obj(ch, wield, destroy, chance / 4);
}

void check_weapon_damage(CHAR_DATA * ch, CHAR_DATA * victim, int loc)
{
	OBJ_DATA *wield, *destroy;
	int skill, chance = 0, sn;

	if (IS_NPC(victim) || number_percent() < 94)
		return;

	if ((wield = get_eq_char(ch, loc)) == NULL)
		return;
	sn = get_weapon_sn(wield);
	skill = get_skill(ch, sn);

	if ((destroy = get_eq_char(victim, WEAR_WIELD)) == NULL
	    || number_percent() > 94 || ch->level < (victim->level - 10)
	    || check_material(destroy, "platinum")
	    || check_material(destroy, "ionium")
	    || destroy->pIndexData->limit != -1)
		return;

	if (wield->pIndexData->extra_flags == ITEM_QUEST)
		return;

	if (is_metal(wield)) {
		if (number_percent() > skill)
			return;

		chance += 20;
		if (check_material(wield, "platinium")
		    || check_material(wield, "titanium"))
			chance += 5;

		if (is_metal(destroy))
			chance -= 20;
		else
			chance += 20;

		chance += ((ch->level - victim->level) / 5);
		chance += ((wield->level - destroy->level) / 2);
	} else {
		if (number_percent() < skill)
			return;

		chance += 10;

		if (is_metal(destroy))
			chance -= 20;

		chance += (ch->level - victim->level);
		chance += (wield->level - destroy->level);
	}

	/* sharpness */
	if (IS_WEAPON_STAT(wield, WEAPON_SHARP))
		chance += 10;

	if (sn == gsn_axe)
		chance += 10;

	/* spell affects */
	if (IS_OBJ_STAT(destroy, ITEM_BLESS))
		chance -= 10;
	if (IS_OBJ_STAT(destroy, ITEM_MAGIC))
		chance -= 20;

	chance += skill - 85;
	chance += get_curr_stat(ch, STAT_STR);

	if (number_percent() < (chance / 2) && chance > 20)
		damage_to_obj(ch, wield, destroy, chance / 4);
}