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