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