/*
 * $Id: repair.c,v 1.19 1999/04/15 09:14:17 fjoe Exp $
 */

/***************************************************************************
 *     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;

 	worn->condition -= damage;

	act_puts("{gThe $p inflicts 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") 
		||  destroy->pIndexData->limit != -1
		||  (i == WEAR_WIELD || i== WEAR_SECOND_WIELD ||
		     i == WEAR_TATTOO || i == WEAR_STUCK_IN ||
		     i == WEAR_CLANMARK ))
			continue;
	
		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") 
	||  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;

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

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