/****************************************************************************
* [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | \\._.// *
* -----------------------------------------------------------| (0...0) *
* SMAUG 1.4 (C) 1994, 1995, 1996, 1998 by Derek Snider | ).:.( *
* -----------------------------------------------------------| {o o} *
* SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, | / ' ' \ *
* Scryn, Rennard, Swordbearer, Gorog, Grishnakh, Nivek, |~'~.VxvxV.~'~*
* Tricops and Fireblade | *
* ------------------------------------------------------------------------ *
* Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* ------------------------------------------------------------------------ *
* Player skills module *
****************************************************************************/
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "mud.h"
char *const spell_flag[] = { "water", "earth", "air", "astral", "area", "distant", "reverse",
"noself", "_unused2_", "accumulative", "recastable", "noscribe",
"nobrew", "group", "object", "character", "secretskill", "pksensitive",
"stoponfail", "nofight", "nodispel", "deq", "noapplystack", "r3", "r4", "r5", "r6",
"r7", "r8", "r9", "r10", "r11"
};
char *const spell_saves[] = { "none", "poison_death", "wands", "para_petri", "breath", "spell_staff" };
char *const spell_save_effect[] = { "none", "negate", "eightdam", "quarterdam", "halfdam", "3qtrdam",
"reflect", "absorb"
};
char *const spell_damage[] = { "none", "fire", "water", "earth", "energy", "air", "holy", "unholy", "undead" };
char *const spell_action[] = { "none", "create", "destroy", "resist", "suscept", "divinate", "obscure",
"change"
};
char *const spell_power[] = { "none", "minor", "greater", "major" };
char *const spell_class[] = { "none", "lunar", "solar", "travel", "summon", "life", "death", "illusion" };
char *const target_type[] = { "ignore", "offensive", "defensive", "self", "objinv", "objroom" };
void show_char_to_char(CHAR_DATA * list, CHAR_DATA * ch);
void show_list_to_char(OBJ_DATA * list, CHAR_DATA * ch, bool fShort, bool fShowN, const int iDefaultAction);
int ris_save(CHAR_DATA * ch, int chance, int ris);
bool check_illegal_psteal(CHAR_DATA * ch, CHAR_DATA * victim);
/* from magic.c */
void failed_casting(struct skill_type *skill, CHAR_DATA * ch, CHAR_DATA * victim, OBJ_DATA * obj);
/*
* Dummy function
*/
void skill_notfound(CHAR_DATA * ch, char *argument)
{
send_to_char("Huh?\n\r", ch);
return;
}
int get_ssave(char *name)
{
int x;
for (x = 0; x < sizeof(spell_saves) / sizeof(spell_saves[0]); x++)
if (!str_cmp(name, spell_saves[x]))
return x;
return -1;
}
int get_starget(char *name)
{
int x;
for (x = 0; x < sizeof(target_type) / sizeof(target_type[0]); x++)
if (!str_cmp(name, target_type[x]))
return x;
return -1;
}
int get_sflag(char *name)
{
int x;
for (x = 0; x < sizeof(spell_flag) / sizeof(spell_flag[0]); x++)
if (!str_cmp(name, spell_flag[x]))
return x;
return -1;
}
int get_sdamage(char *name)
{
int x;
for (x = 0; x < sizeof(spell_damage) / sizeof(spell_damage[0]); x++)
if (!str_cmp(name, spell_damage[x]))
return x;
return -1;
}
int get_saction(char *name)
{
int x;
for (x = 0; x < sizeof(spell_action) / sizeof(spell_action[0]); x++)
if (!str_cmp(name, spell_action[x]))
return x;
return -1;
}
int get_ssave_effect(char *name)
{
int x;
for (x = 0; x < sizeof(spell_save_effect) / sizeof(spell_save_effect[0]); x++)
if (!str_cmp(name, spell_save_effect[x]))
return x;
return -1;
}
int get_spower(char *name)
{
int x;
for (x = 0; x < sizeof(spell_power) / sizeof(spell_power[0]); x++)
if (!str_cmp(name, spell_power[x]))
return x;
return -1;
}
int get_sclass(char *name)
{
int x;
for (x = 0; x < sizeof(spell_class) / sizeof(spell_class[0]); x++)
if (!str_cmp(name, spell_class[x]))
return x;
return -1;
}
bool is_legal_kill(CHAR_DATA * ch, CHAR_DATA * vch)
{
if (IS_NPC(ch) || IS_NPC(vch))
return TRUE;
if (ch->pcdata->clan && vch->pcdata->clan && ch->pcdata->clan == vch->pcdata->clan)
return FALSE;
if (is_safe(ch, vch))
return FALSE;
return TRUE;
}
extern char *target_name; /* from magic.c */
int check_twohand_shield(CHAR_DATA *ch)
{
OBJ_DATA *shield;
if ((shield = get_eq_char(ch, WEAR_SHIELD)) && IS_OBJ_STAT(shield, ITEM_TWOHANDED))
{
send_to_char("You cannot do that while wearing a two-handed shield.\n\r", ch);
return FALSE;
}
else
return TRUE;
}
/*
* Perform a binary search on a section of the skill table
* Each different section of the skill table is sorted alphabetically
* Only match skills player knows -Thoric
*/
bool check_skill(CHAR_DATA * ch, char *command, char *argument)
{
int sn;
int first = gsn_first_skill;
int top = gsn_first_weapon - 1;
int mana, blood;
struct timeval time_used;
CHAR_DATA *starget;
sh_int begmod = 0; // Used to penalize beginners on the to hit on skills
/* bsearch for the skill */
for (;;)
{
sn = (first + top) >> 1;
if (LOWER(command[0]) == LOWER(skill_table[sn]->name[0])
&& !str_prefix(command, skill_table[sn]->name)
&& (skill_table[sn]->skill_fun || skill_table[sn]->spell_fun != spell_null) && (can_use_skill(ch, 0, sn)))
break;
if (first >= top)
return FALSE;
if (strcmp(command, skill_table[sn]->name) < 1)
top = sn - 1;
else
first = sn + 1;
}
if (!check_pos(ch, skill_table[sn]->minimum_position))
return TRUE;
if (IS_NPC(ch) && (IS_AFFECTED(ch, AFF_CHARM) || IS_AFFECTED(ch, AFF_POSSESS)))
{
send_to_char("For some reason, you seem unable to perform that...\n\r", ch);
act(AT_GREY, "$n wanders around aimlessly.", ch, NULL, NULL, TO_ROOM);
return TRUE;
}
/* check if mana is required */
if (skill_table[sn]->min_mana)
{
mana = IS_NPC(ch) ? 0 : skill_table[sn]->min_mana;
blood = UMAX(1, (mana + 4) / 8); /* NPCs don't have PCDatas. -- Altrag */
if (IS_VAMPIRE(ch))
{
if (ch->pcdata->condition[COND_BLOODTHIRST] < blood)
{
send_to_char("You don't have enough blood power.\n\r", ch);
return TRUE;
}
}
else if (!IS_NPC(ch) && ch->mana < mana)
{
send_to_char("You don't have enough mana.\n\r", ch);
return TRUE;
}
}
else
{
mana = 0;
blood = 0;
}
/*
* Is this a real do-fun, or a really a spell?
*/
if (!skill_table[sn]->skill_fun)
{
ch_ret retcode = rNONE;
void *vo = NULL;
CHAR_DATA *victim = NULL;
OBJ_DATA *obj = NULL;
int suc;
target_name = "";
switch (skill_table[sn]->target)
{
default:
bug("Check_skill: bad target for sn %d.", sn);
send_to_char("Something went wrong...\n\r", ch);
return TRUE;
case TAR_IGNORE:
vo = NULL;
starget = NULL;
if (argument[0] == '\0')
{
if ((victim = who_fighting(ch)) != NULL)
target_name = victim->name;
}
else
target_name = argument;
break;
case TAR_CHAR_OFFENSIVE:
if (argument[0] == '\0' && (victim = who_fighting(ch)) == NULL)
{
ch_printf(ch, "Confusion overcomes you as your '%s' has no target.\n\r", skill_table[sn]->name);
return TRUE;
}
else if (argument[0] != '\0' && (victim = get_char_room_new(ch, argument, 1)) == NULL)
{
send_to_char("They aren't here.\n\r", ch);
return TRUE;
}
if (is_safe(ch, victim))
return TRUE;
if (ch == victim && SPELL_FLAG(skill_table[sn], SF_NOSELF))
{
send_to_char("You can't target yourself!\n\r", ch);
return TRUE;
}
if (!IS_NPC(ch))
{
if (IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim)
{
send_to_char("You can't do that on your own follower.\n\r", ch);
return TRUE;
}
}
check_illegal_pk(ch, victim);
vo = (void *) victim;
starget = victim;
break;
case TAR_CHAR_DEFENSIVE:
if (argument[0] != '\0' && (victim = get_char_room_new(ch, argument, 1)) == NULL)
{
send_to_char("They aren't here.\n\r", ch);
return TRUE;
}
if (!victim)
victim = ch;
if (ch == victim && SPELL_FLAG(skill_table[sn], SF_NOSELF))
{
send_to_char("You can't target yourself!\n\r", ch);
return TRUE;
}
vo = (void *) victim;
starget = victim;
break;
case TAR_CHAR_SELF:
vo = (void *) ch;
starget = ch;
break;
case TAR_OBJ_INV:
if ((obj = get_obj_carry(ch, argument)) == NULL)
{
send_to_char("You can't find that.\n\r", ch);
return TRUE;
}
vo = (void *) obj;
starget = NULL;
break;
case TAR_OBJ_ROOM:
if ((obj = get_obj_here(ch, argument)) == NULL)
{
send_to_char("You are not in the room with that.\n\r", ch);
return TRUE;
}
vo = (void *) obj;
starget = NULL;
break;
}
/* waitstate */
if (!ch->fighting)
WAIT_STATE(ch, skill_table[sn]->beats*2);
else
ch->fight_timer = get_btimer(ch, sn, NULL);
/* check for failure */
if (!IS_NPC(ch) && ch->pcdata->ranking[sn] <= 1)
begmod = 30;
if (!IS_NPC(ch) && ch->pcdata->ranking[sn] == 2)
begmod = 15;
if (!IS_NPC(ch) && ch->pcdata->ranking[sn] == 4)
begmod = -15;
suc = 1;
if (IS_NPC(ch))
{
if (number_percent() > 85)
suc = 0;
}
else
{
if ((number_percent() + skill_table[sn]->difficulty * 5) > (90 + (ch->pcdata->learned[sn]*10)))
suc = 0;
}
if (!suc)
{
failed_casting(skill_table[sn], ch, vo, obj);
learn_from_failure(ch, sn, starget);
if (mana)
{
if (IS_VAMPIRE(ch))
gain_condition(ch, COND_BLOODTHIRST, -blood / 2);
else
{
ch->mana -= mana / 2;
if (skill_table[sn]->type == SKILL_SKILL)
gain_mana_per(ch, victim, mana/2);
}
}
return TRUE;
}
if (mana)
{
if (IS_VAMPIRE(ch))
gain_condition(ch, COND_BLOODTHIRST, -blood);
else
{
ch->mana -= mana;
if (skill_table[sn]->type == SKILL_SKILL)
gain_mana_per(ch, victim, mana/2);
}
}
start_timer(&time_used);
retcode = (*skill_table[sn]->spell_fun) (sn, ch->level, ch, vo);
end_timer(&time_used);
update_userec(&time_used, &skill_table[sn]->userec);
if (retcode == rCHAR_DIED || retcode == rERROR)
return TRUE;
if (char_died(ch))
return TRUE;
if (retcode == rSPELL_FAILED)
{
learn_from_failure(ch, sn, starget);
retcode = rNONE;
}
else
{
learn_from_success(ch, sn, starget);
}
if (skill_table[sn]->target == TAR_CHAR_OFFENSIVE && victim != ch && !char_died(victim))
{
CHAR_DATA *vch;
CHAR_DATA *vch_next;
for (vch = ch->in_room->first_person; vch; vch = vch_next)
{
vch_next = vch->next_in_room;
if (victim == vch && !victim->fighting && victim->master != ch)
{
retcode = one_hit(victim, ch, TYPE_UNDEFINED, LM_BODY);
break;
}
}
}
return TRUE;
}
//for flee, don't remove
if(!ch->fighting && !IS_NPC(ch))
ch->fight_timer = 0;
if(ch->fight_timer > 0)
{
displayFightTimer(ch);
return TRUE;
}
if (mana)
{
if (IS_VAMPIRE(ch))
gain_condition(ch, COND_BLOODTHIRST, -blood);
else
{
ch->mana -= mana;
if (skill_table[sn]->type == SKILL_SKILL)
gain_mana_per(ch, NULL, mana/2);
}
}
ch->prev_cmd = ch->last_cmd; /* haus, for automapping */
ch->last_cmd = skill_table[sn]->skill_fun;
start_timer(&time_used);
(*skill_table[sn]->skill_fun) (ch, argument);
end_timer(&time_used);
update_userec(&time_used, &skill_table[sn]->userec);
tail_chain();
return TRUE;
}
void do_skin(CHAR_DATA * ch, char *argument)
{
OBJ_DATA *korps;
OBJ_DATA *corpse;
OBJ_DATA *obj;
OBJ_DATA *skin;
bool found;
char *name;
char buf[MSL];
found = FALSE;
if (argument[0] == '\0')
{
send_to_char("Whose corpse do you wish to skin?\n\r", ch);
return;
}
if ((corpse = get_obj_here(ch, argument)) == NULL)
{
send_to_char("You cannot find that here.\n\r", ch);
return;
}
if ((obj = get_eq_char(ch, WEAR_WIELD)) == NULL)
{
send_to_char("You have no weapon with which to perform this deed.\n\r", ch);
return;
}
if (corpse->item_type != ITEM_CORPSE_PC)
{
send_to_char("You can only skin the bodies of player characters.\n\r", ch);
return;
}
if (wielding_skill_weapon(ch, 0) != 7)
{
send_to_char("There is nothing you can do with this corpse.\n\r", ch);
return;
}
if (get_obj_index(OBJ_VNUM_SKIN) == NULL)
{
bug("Vnum 23 (OBJ_VNUM_SKIN) not found for do_skin!", 0);
return;
}
korps = create_object(get_obj_index(OBJ_VNUM_CORPSE_PC), 0);
skin = create_object(get_obj_index(OBJ_VNUM_SKIN), 0);
name = IS_NPC(ch) ? korps->short_descr : corpse->short_descr;
sprintf(buf, skin->short_descr, name);
STRFREE(skin->short_descr);
skin->short_descr = STRALLOC(buf);
sprintf(buf, skin->description, name);
STRFREE(skin->description);
skin->description = STRALLOC(buf);
act(AT_BLOOD, "$n strips the skin from $p.", ch, corpse, NULL, TO_ROOM);
act(AT_BLOOD, "You strip the skin from $p.", ch, corpse, NULL, TO_CHAR);
/* act( AT_MAGIC, "\nThe skinless corpse is dragged through the ground by a strange force...", ch, corpse, NULL, TO_CHAR);
act( AT_MAGIC, "\nThe skinless corpse is dragged through the ground by a strange force...", ch, corpse, NULL, TO_ROOM);
extract_obj( corpse ); */
obj_to_char(skin, ch);
return;
}
/*
* Lookup a skills information
* High god command
*/
void do_slookup(CHAR_DATA * ch, char *argument)
{
char buf[MSL];
char arg[MIL];
int sn;
int iRace;
SKILLTYPE *skill = NULL;
argument = one_argument(argument, arg);
if (arg[0] == '\0')
{
send_to_char("Slookup what?\n\r", ch);
return;
}
if (!str_cmp(arg, "all"))
{
for (sn = 0; sn < top_sn && skill_table[sn] && skill_table[sn]->name; sn++)
pager_printf(ch, "Sn: %4d Slot: %4d Skill/spell: '%-20s' Damtype: %s\n\r",
sn, skill_table[sn]->slot, skill_table[sn]->name, spell_damage[SPELL_DAMAGE(skill_table[sn])]);
}
else if (!str_cmp(arg, "mana"))
{
pager_printf(ch, " Sn Name Mana Tier Sphere Beats Group\n\r");
pager_printf(ch, "---------------------------------------------------------------------------\n\r");
for (sn = 0; sn < top_sn && skill_table[sn] && skill_table[sn]->name; sn++)
{
if (atoi(argument) >= 1 && atoi(argument) <= 4)
{
if (atoi(argument) == skill_table[sn]->masterydiff[0])
{
pager_printf(ch, "%4d %-25s %-3d %d %d %-2d %d\n\r", sn, skill_table[sn]->name,
skill_table[sn]->min_mana, skill_table[sn]->masterydiff[0], skill_table[sn]->stype,
skill_table[sn]->beats, skill_table[sn]->group[0]);
}
}
}
return;
}
else if (!str_cmp(arg, "prototype"))
{
pager_printf(ch, " Sn Name Creator\n\r");
pager_printf(ch, "-------------------------------------------\n\r");
for (sn = 0; sn < top_sn && skill_table[sn] && skill_table[sn]->name; sn++)
if (skill_table[sn]->prototype > 0)
{
pager_printf(ch, "%4d %-20s %-15s\n\r", sn, skill_table[sn]->name, skill_table[sn]->made_char);
}
}
else if (!str_cmp(arg, "herbs"))
{
for (sn = 0; sn < top_herb && herb_table[sn] && herb_table[sn]->name; sn++)
pager_printf(ch, "%d) %s\n\r", sn, herb_table[sn]->name);
}
else
{
SMAUG_AFF *aff;
int cnt = 0;
if (arg[0] == 'h' && is_number(arg + 1))
{
sn = atoi(arg + 1);
if (!IS_VALID_HERB(sn))
{
send_to_char("Invalid herb.\n\r", ch);
return;
}
skill = herb_table[sn];
}
else if (is_number(arg))
{
sn = atoi(arg);
if ((skill = get_skilltype(sn)) == NULL)
{
send_to_char("Invalid sn.\n\r", ch);
return;
}
sn %= 1000;
}
else if ((sn = skill_lookup(arg)) >= 0)
skill = skill_table[sn];
else if ((sn = herb_lookup(arg)) >= 0)
skill = herb_table[sn];
else
{
send_to_char("No such skill, spell, proficiency or tongue.\n\r", ch);
return;
}
if (!skill)
{
send_to_char("Not created yet.\n\r", ch);
return;
}
ch_printf(ch, "Sn: %4d Slot: %4d %s: '%-20s'\n\r", sn, skill->slot, skill_tname[skill->type], skill->name);
if (skill->prototype)
ch_printf(ch, "Prototype: %s ", (skill->prototype == 0) ? "No" : "Yes");
if (skill->made_char)
ch_printf(ch, "Made By: %s ", skill->made_char);
ch_printf(ch, "\n\r");
if (skill->info)
ch_printf(ch, "DamType: %s ActType: %s ClassType: %s PowerType: %s\n\r",
spell_damage[SPELL_DAMAGE(skill)], spell_action[SPELL_ACTION(skill)], spell_class[SPELL_CLASS(skill)], spell_power[SPELL_POWER(skill)]);
if (skill->flags)
{
int x;
strcpy(buf, "Flags:");
for (x = 0; x < 32; x++)
if (SPELL_FLAG(skill, 1 << x))
{
strcat(buf, " ");
strcat(buf, spell_flag[x]);
}
strcat(buf, "\n\r");
send_to_char(buf, ch);
}
ch_printf(ch, "Saves: %s SaveEffect: %s\n\r", spell_saves[(int) skill->saves], spell_save_effect[SPELL_SAVE(skill)]);
if (skill->difficulty != '\0')
ch_printf(ch, "Difficulty: %d\n\r", (int) skill->difficulty);
ch_printf(ch, "Tier %d TrainerNum %d Group %d Sphere %d", skill->masterydiff[0], skill->bookinfo[0], skill->group[0], skill->stype);
if (skill->targetlimb > 0)
ch_printf(ch, " Targetlimb %d\n\r", skill->targetlimb);
else
send_to_char("\n\r", ch);
ch_printf(ch, "Type: %s Target: %s Minpos: %d Mana: %d Beats: %d Range: %d\n\r",
skill_tname[skill->type],
target_type[URANGE(TAR_IGNORE, skill->target, TAR_OBJ_ROOM)], skill->minimum_position, skill->min_mana, skill->beats, skill->range);
ch_printf(ch, "Flags: %d Guild: %d Value: %d Info: %d Code: %s\n\r",
skill->flags, skill->guild, skill->value, skill->info, skill->skill_fun ? skill_name(skill->skill_fun) : spell_name(skill->spell_fun));
ch_printf(ch, "Dammsg: %s\n\rWearoff: %s\n", skill->noun_damage, skill->msg_off ? skill->msg_off : "(none set)");
if (skill->dice && skill->dice[0] != '\0')
ch_printf(ch, "Dice: %s\n\r", skill->dice);
if (skill->teachers && skill->teachers[0] != '\0')
ch_printf(ch, "Teachers: %s\n\r", skill->teachers);
if (skill->components && skill->components[0] != '\0')
ch_printf(ch, "Components: %s\n\r", skill->components);
if (skill->participants)
ch_printf(ch, "Participants: %d\n\r", (int) skill->participants);
if (skill->userec.num_uses)
send_timer(&skill->userec, ch);
for (aff = skill->affects; aff; aff = aff->next)
{
if (aff == skill->affects)
send_to_char("\n\r", ch);
sprintf(buf, "Affect %d", ++cnt);
if (aff->location)
{
strcat(buf, " modifies ");
strcat(buf, a_types[aff->location % REVERSE_APPLY]);
strcat(buf, " by '");
strcat(buf, aff->modifier);
if (aff->bitvector != -1)
strcat(buf, "' and");
else
strcat(buf, "'");
}
if (aff->bitvector != -1)
{
strcat(buf, " applies ");
strcat(buf, a_flags[aff->bitvector]);
}
if (aff->duration[0] != '\0' && aff->duration[0] != '0')
{
strcat(buf, " for '");
strcat(buf, aff->duration);
strcat(buf, "' rounds");
}
if (aff->location >= REVERSE_APPLY)
strcat(buf, " (affects caster only)");
strcat(buf, "\n\r");
send_to_char(buf, ch);
if (!aff->next)
send_to_char("\n\r", ch);
}
if (skill->hit_char && skill->hit_char[0] != '\0')
ch_printf(ch, "Hitchar : %s\n\r", skill->hit_char);
if (skill->hit_vict && skill->hit_vict[0] != '\0')
ch_printf(ch, "Hitvict : %s\n\r", skill->hit_vict);
if (skill->hit_room && skill->hit_room[0] != '\0')
ch_printf(ch, "Hitroom : %s\n\r", skill->hit_room);
if (skill->hit_dest && skill->hit_dest[0] != '\0')
ch_printf(ch, "Hitdest : %s\n\r", skill->hit_dest);
if (skill->miss_char && skill->miss_char[0] != '\0')
ch_printf(ch, "Misschar : %s\n\r", skill->miss_char);
if (skill->miss_vict && skill->miss_vict[0] != '\0')
ch_printf(ch, "Missvict : %s\n\r", skill->miss_vict);
if (skill->miss_room && skill->miss_room[0] != '\0')
ch_printf(ch, "Missroom : %s\n\r", skill->miss_room);
if (skill->die_char && skill->die_char[0] != '\0')
ch_printf(ch, "Diechar : %s\n\r", skill->die_char);
if (skill->die_vict && skill->die_vict[0] != '\0')
ch_printf(ch, "Dievict : %s\n\r", skill->die_vict);
if (skill->die_room && skill->die_room[0] != '\0')
ch_printf(ch, "Dieroom : %s\n\r", skill->die_room);
if (skill->imm_char && skill->imm_char[0] != '\0')
ch_printf(ch, "Immchar : %s\n\r", skill->imm_char);
if (skill->imm_vict && skill->imm_vict[0] != '\0')
ch_printf(ch, "Immvict : %s\n\r", skill->imm_vict);
if (skill->imm_room && skill->imm_room[0] != '\0')
ch_printf(ch, "Immroom : %s\n\r", skill->imm_room);
if (skill->type != SKILL_HERB)
{
if (skill->type == SKILL_RACIAL)
{
send_to_char("\n\r--------------------------[RACE USE]--------------------------\n\r", ch);
for (iRace = 0; iRace < MAX_RACE; iRace++)
{
sprintf(buf, "%8.8s) lvl: %3d max: %2d%%", race_table[iRace]->race_name, skill->race_level[iRace], skill->race_adept[iRace]);
if (!strcmp(race_table[iRace]->race_name, "unused"))
sprintf(buf, " ");
if ((iRace > 0) && (iRace % 2 == 1))
strcat(buf, "\n\r");
else
strcat(buf, " ");
send_to_char(buf, ch);
}
}
}
send_to_char("\n\r", ch);
}
return;
}
/*
* Set a skill's attributes or what skills a player has.
* High god command, with support for creating skills/spells/herbs/etc
*/
void do_sset(CHAR_DATA * ch, char *argument)
{
char arg1[MIL];
char arg2[MIL];
char arg3[MIL]; /* Used for mastery setting -- Xerves 2/00 */
CHAR_DATA *victim;
int value;
int mvalue = -1;
int sn, i;
bool fAll;
argument = one_argument(argument, arg1);
argument = one_argument(argument, arg2);
if (arg1[0] == '\0' || arg2[0] == '\0' || argument[0] == '\0')
{
send_to_char("Syntax: sset <victim> <skill> <point value/keep> [mastery value]\n\r", ch);
send_to_char("or: sset <victim> all <point value/keep> [mastery value]\n\r", ch);
if (get_ftrust(ch) >= LEVEL_HI_STAFF) /* Tracker1 */
{
send_to_char("or: sset save skill table\n\r", ch);
send_to_char("or: sset save herb table\n\r", ch);
send_to_char("or: sset create skill 'new skill'\n\r", ch);
send_to_char("or: sset create herb 'new herb'\n\r", ch);
send_to_char("or: sset create ability 'new ability'\n\r", ch);
}
if (get_ftrust(ch) >= LEVEL_STAFF) /* Tracker1 */
{
send_to_char("or: sset <sn> <field> <value>\n\r", ch);
send_to_char("\n\rField being one of:\n\r", ch);
send_to_char(" name code target minpos slot mana beats dammsg wearoff guild minlevel\n\r", ch);
send_to_char(" type damtype acttype classtype powertype seffect flag dice value difficulty\n\r", ch);
send_to_char(" affect rmaffect mastery hit miss die imm (char/vict/room) targetlimb\n\r", ch);
send_to_char(" components teachers racelevel raceadept prototype madeby group tier sphere\n\r", ch);
send_to_char("Affect having the fields: <location> <modfifier> [duration] [bitvector]\n\r", ch);
send_to_char("(See AFFECTTYPES for location, and AFFECTED_BY for bitvector)\n\r", ch);
}
send_to_char("Skill being any skill or spell.\n\r", ch);
return;
}
if (get_ftrust(ch) > LEVEL_HI_STAFF /* Tracker1 */
&& !str_cmp(arg1, "save") && !str_cmp(argument, "table"))
{
if (!str_cmp(arg2, "skill"))
{
send_to_char("Saving skill table...\n\r", ch);
save_skill_table();
save_classes();
/* save_races(); */
return;
}
if (!str_cmp(arg2, "herb"))
{
send_to_char("Saving herb table...\n\r", ch);
save_herb_table();
return;
}
}
if (get_ftrust(ch) > LEVEL_HI_STAFF /* Tracker1 */
&& !str_cmp(arg1, "create") && (!str_cmp(arg2, "skill") || !str_cmp(arg2, "herb") || !str_cmp(arg2, "ability")))
{
struct skill_type *skill;
sh_int type = SKILL_UNKNOWN;
if (!str_cmp(arg2, "herb"))
{
type = SKILL_HERB;
if (top_herb >= MAX_HERB)
{
ch_printf(ch, "The current top herb is %d, which is the maximum. "
"To add more herbs,\n\rMAX_HERB will have to be " "raised in mud.h, and the mud recompiled.\n\r", top_sn);
return;
}
}
else if (top_sn >= MAX_SKILL)
{
ch_printf(ch, "The current top sn is %d, which is the maximum. "
"To add more skills,\n\rMAX_SKILL will have to be " "raised in mud.h, and the mud recompiled.\n\r", top_sn);
return;
}
CREATE(skill, struct skill_type, 1);
skill->slot = 0;
if (type == SKILL_HERB)
{
int max, x;
herb_table[top_herb++] = skill;
for (max = x = 0; x < top_herb - 1; x++)
if (herb_table[x] && herb_table[x]->slot > max)
max = herb_table[x]->slot;
skill->slot = max + 1;
}
else
skill_table[top_sn++] = skill;
skill->min_mana = 0;
skill->name = str_dup(argument);
skill->noun_damage = str_dup("");
skill->msg_off = str_dup("");
skill->spell_fun = spell_smaug;
skill->type = type;
skill->prototype = 1;
skill->made_char = ch->name;
if (!str_cmp(arg2, "ability"))
skill->type = SKILL_RACIAL;
for (i = 0; i < MAX_RACE; i++)
{
skill->race_level[i] = LEVEL_IMMORTAL;
skill->race_adept[i] = 95;
}
send_to_char("Done.\n\r", ch);
return;
}
if (arg1[0] == 'h')
sn = atoi(arg1 + 1);
else
sn = atoi(arg1);
if (get_trust(ch) > LEVEL_STAFF /* Tracker1 */
&& ((arg1[0] == 'h' && is_number(arg1 + 1) && (sn = atoi(arg1 + 1)) >= 0) || (is_number(arg1) && (sn = atoi(arg1)) >= 0)))
{
struct skill_type *skill;
if (arg1[0] == 'h')
{
if (sn >= top_herb)
{
send_to_char("Herb number out of range.\n\r", ch);
return;
}
skill = herb_table[sn];
}
else
{
if ((skill = get_skilltype(sn)) == NULL)
{
send_to_char("Skill number out of range.\n\r", ch);
return;
}
sn %= 1000;
}
if (!str_cmp(arg2, "difficulty"))
{
skill->difficulty = atoi(argument);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "participants"))
{
skill->participants = atoi(argument);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "damtype"))
{
int x = get_sdamage(argument);
if (x == -1)
send_to_char("Not a spell damage type.\n\r", ch);
else
{
SET_SDAM(skill, x);
send_to_char("Ok.\n\r", ch);
}
return;
}
if (!str_cmp(arg2, "acttype"))
{
int x = get_saction(argument);
if (x == -1)
send_to_char("Not a spell action type.\n\r", ch);
else
{
SET_SACT(skill, x);
send_to_char("Ok.\n\r", ch);
}
return;
}
if (!str_cmp(arg2, "classtype"))
{
int x = get_sclass(argument);
if (x == -1)
send_to_char("Not a spell class type.\n\r", ch);
else
{
SET_SCLA(skill, x);
send_to_char("Ok.\n\r", ch);
}
return;
}
if (!str_cmp(arg2, "powertype"))
{
int x = get_spower(argument);
if (x == -1)
send_to_char("Not a spell power type.\n\r", ch);
else
{
SET_SPOW(skill, x);
send_to_char("Ok.\n\r", ch);
}
return;
}
if (!str_cmp(arg2, "seffect"))
{
int x = get_ssave_effect(argument);
if (x == -1)
send_to_char("Not a spell save effect type.\n\r", ch);
else
{
SET_SSAV(skill, x);
send_to_char("Ok.\n\r", ch);
}
return;
}
if (!str_cmp(arg2, "flag"))
{
int x = get_sflag(argument);
if (x == -1)
send_to_char("Not a spell flag.\n\r", ch);
else
{
TOGGLE_BIT(skill->flags, 1 << x);
send_to_char("Ok.\n\r", ch);
}
return;
}
if (!str_cmp(arg2, "saves"))
{
int x = get_ssave(argument);
if (x == -1)
send_to_char("Not a saving type.\n\r", ch);
else
{
skill->saves = x;
send_to_char("Ok.\n\r", ch);
}
return;
}
if (!str_cmp(arg2, "code"))
{
SPELL_FUN *spellfun;
DO_FUN *dofun;
if ((spellfun = spell_function(argument)) != spell_notfound)
{
skill->spell_fun = spellfun;
skill->skill_fun = NULL;
}
else if ((dofun = skill_function(argument)) != skill_notfound)
{
skill->skill_fun = dofun;
skill->spell_fun = NULL;
}
else
{
send_to_char("Not a spell or skill.\n\r", ch);
return;
}
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "target"))
{
int x = get_starget(argument);
if (x == -1)
send_to_char("Not a valid target type.\n\r", ch);
else
{
skill->target = x;
send_to_char("Ok.\n\r", ch);
}
return;
}
if (!str_cmp(arg2, "sphere"))
{
if (atoi(argument) < 1 || atoi(argument) > MAX_SPHERE)
{
ch_printf(ch, "Valid range is 1 to %d.\n\r", MAX_SPHERE);
return;
}
else
{
skill->stype = atoi(argument);
send_to_char("Ok.\n\r", ch);
return;
}
}
if (!str_cmp(arg2, "targetlimb"))
{
if (atoi(argument) < 0 || atoi(argument) > 5)
{
send_to_char("Range is 0 to 5.\n\r", ch);
return;
}
else
{
skill->targetlimb = atoi(argument);
send_to_char("Ok.\n\r", ch);
return;
}
}
if (!str_cmp(arg2, "group"))
{
if (atoi(argument) < 1 || atoi(argument) > MAX_GROUP)
{
ch_printf(ch, "Valid range is 1 to %d.\n\r", MAX_GROUP);
return;
}
else
{
skill->group[0] = atoi(argument);
send_to_char("Ok.\n\r", ch);
return;
}
}
if (!str_cmp(arg2, "masterydiff") || !str_cmp(arg2, "mastery diff") || !str_cmp(arg2, "tier"))
{
if (atoi(argument) < 1 || atoi(argument) > MAX_RANKING)
{
ch_printf(ch, "Valid range is 1 to %d.\n\r", MAX_RANKING);
return;
}
else
{
skill->masterydiff[0] = atoi(argument);
send_to_char("Ok.\n\r", ch);
return;
}
}
if (!str_cmp(arg2, "minpos"))
{
skill->minimum_position = URANGE(POS_DEAD, atoi(argument), POS_DRAG);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "minlevel"))
{
skill->min_level = URANGE(1, atoi(argument), MAX_LEVEL);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "slot"))
{
skill->slot = URANGE(0, atoi(argument), 30000);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "mana"))
{
skill->min_mana = URANGE(0, atoi(argument), 2000);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "beats"))
{
skill->beats = URANGE(0, atoi(argument), 120);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "range"))
{
skill->range = URANGE(0, atoi(argument), 20);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "guild"))
{
skill->guild = atoi(argument);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "value"))
{
skill->value = atoi(argument);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "type"))
{
skill->type = get_skill(argument);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "rmaffect"))
{
SMAUG_AFF *aff = skill->affects;
SMAUG_AFF *aff_next;
int num = atoi(argument);
int cnt = 1;
if (!aff)
{
send_to_char("This spell has no special affects to remove.\n\r", ch);
return;
}
if (num == 1)
{
skill->affects = aff->next;
DISPOSE(aff->duration);
DISPOSE(aff->modifier);
DISPOSE(aff);
send_to_char("Removed.\n\r", ch);
return;
}
for (; aff; aff = aff->next)
{
if (++cnt == num && (aff_next = aff->next) != NULL)
{
aff->next = aff_next->next;
DISPOSE(aff_next->duration);
DISPOSE(aff_next->modifier);
DISPOSE(aff_next);
send_to_char("Removed.\n\r", ch);
return;
}
}
send_to_char("Not found.\n\r", ch);
return;
}
/*
* affect <location> <modifier> <duration> <bitvector>
*/
if (!str_cmp(arg2, "affect"))
{
char location[MIL];
char modifier[MIL];
char duration[MIL];
/* char bitvector[MIL]; */
int loc, bit, tmpbit;
SMAUG_AFF *aff;
argument = one_argument(argument, location);
argument = one_argument(argument, modifier);
argument = one_argument(argument, duration);
if (location[0] == '!')
loc = get_atype(location + 1) + REVERSE_APPLY;
else
loc = get_atype(location);
if ((loc % REVERSE_APPLY) < 0 || (loc % REVERSE_APPLY) >= MAX_APPLY_TYPE)
{
send_to_char("Unknown affect location. See AFFECTTYPES.\n\r", ch);
return;
}
bit = -1;
if (argument[0] != 0)
{
if ((tmpbit = get_aflag(argument)) == -1)
ch_printf(ch, "Unknown bitvector: %s. See AFFECTED_BY\n\r", argument);
else
bit = tmpbit;
}
CREATE(aff, SMAUG_AFF, 1);
if (!str_cmp(duration, "0"))
duration[0] = '\0';
if (!str_cmp(modifier, "0"))
modifier[0] = '\0';
aff->duration = str_dup(duration);
aff->location = loc;
aff->modifier = str_dup(modifier);
aff->bitvector = bit;
aff->next = skill->affects;
skill->affects = aff;
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "racelevel"))
{
char arg3[MIL];
int race;
argument = one_argument(argument, arg3);
race = atoi(arg3);
if (race >= MAX_RACE || race < 0)
send_to_char("Not a valid race.\n\r", ch);
else
skill->race_level[race] = URANGE(0, atoi(argument), MAX_LEVEL);
return;
}
if (!str_cmp(arg2, "raceadept"))
{
char arg3[MIL];
int race;
argument = one_argument(argument, arg3);
race = atoi(arg3);
if (race >= MAX_RACE || race < 0)
send_to_char("Not a valid race.\n\r", ch);
else
skill->race_adept[race] = URANGE(0, atoi(argument), 100);
return;
}
if (!str_cmp(arg2, "name"))
{
DISPOSE(skill->name);
skill->name = str_dup(argument);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "prototype"))
{
int pro = atoi(argument);
if (get_trust(ch) < LEVEL_STAFF) /* Tracker1 */
{
send_to_char("Sorry, only staff can change this.\n\r", ch);
return;
}
if (pro > 1 || pro < 0)
{
send_to_char("0 for no, 1 for yes\n\r", ch);
return;
}
skill->prototype = atoi(argument);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "madeby"))
{
if (get_trust(ch) < LEVEL_STAFF) /* Tracker1 */
{
send_to_char("Sorry, only staff can change this.\n\r", ch);
return;
}
DISPOSE(skill->made_char);
skill->made_char = str_dup(argument);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "dammsg"))
{
DISPOSE(skill->noun_damage);
if (!str_cmp(argument, "clear"))
skill->noun_damage = str_dup("");
else
skill->noun_damage = str_dup(argument);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "wearoff"))
{
DISPOSE(skill->msg_off);
if (str_cmp(argument, "clear"))
skill->msg_off = str_dup(argument);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "hitchar"))
{
if (skill->hit_char)
DISPOSE(skill->hit_char);
if (str_cmp(argument, "clear"))
skill->hit_char = str_dup(argument);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "hitvict"))
{
if (skill->hit_vict)
DISPOSE(skill->hit_vict);
if (str_cmp(argument, "clear"))
skill->hit_vict = str_dup(argument);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "hitroom"))
{
if (skill->hit_room)
DISPOSE(skill->hit_room);
if (str_cmp(argument, "clear"))
skill->hit_room = str_dup(argument);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "hitdest"))
{
if (skill->hit_dest)
DISPOSE(skill->hit_dest);
if (str_cmp(argument, "clear"))
skill->hit_dest = str_dup(argument);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "misschar"))
{
if (skill->miss_char)
DISPOSE(skill->miss_char);
if (str_cmp(argument, "clear"))
skill->miss_char = str_dup(argument);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "missvict"))
{
if (skill->miss_vict)
DISPOSE(skill->miss_vict);
if (str_cmp(argument, "clear"))
skill->miss_vict = str_dup(argument);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "missroom"))
{
if (skill->miss_room)
DISPOSE(skill->miss_room);
if (str_cmp(argument, "clear"))
skill->miss_room = str_dup(argument);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "diechar"))
{
if (skill->die_char)
DISPOSE(skill->die_char);
if (str_cmp(argument, "clear"))
skill->die_char = str_dup(argument);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "dievict"))
{
if (skill->die_vict)
DISPOSE(skill->die_vict);
if (str_cmp(argument, "clear"))
skill->die_vict = str_dup(argument);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "dieroom"))
{
if (skill->die_room)
DISPOSE(skill->die_room);
if (str_cmp(argument, "clear"))
skill->die_room = str_dup(argument);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "immchar"))
{
if (skill->imm_char)
DISPOSE(skill->imm_char);
if (str_cmp(argument, "clear"))
skill->imm_char = str_dup(argument);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "immvict"))
{
if (skill->imm_vict)
DISPOSE(skill->imm_vict);
if (str_cmp(argument, "clear"))
skill->imm_vict = str_dup(argument);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "immroom"))
{
if (skill->imm_room)
DISPOSE(skill->imm_room);
if (str_cmp(argument, "clear"))
skill->imm_room = str_dup(argument);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "dice"))
{
if (skill->dice)
DISPOSE(skill->dice);
if (str_cmp(argument, "clear"))
skill->dice = str_dup(argument);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "components"))
{
if (skill->components)
DISPOSE(skill->components);
if (str_cmp(argument, "clear"))
skill->components = str_dup(argument);
send_to_char("Ok.\n\r", ch);
return;
}
if (!str_cmp(arg2, "teachers"))
{
if (skill->teachers)
DISPOSE(skill->teachers);
if (str_cmp(argument, "clear"))
skill->teachers = str_dup(argument);
send_to_char("Ok.\n\r", ch);
return;
}
do_sset(ch, "");
return;
}
//sset <victim> <skill> <point value> <mastery value>
if ((victim = get_char_world(ch, arg1)) == NULL)
{
if ((sn = skill_lookup(arg1)) >= 0)
{
sprintf(arg1, "%d %s %s", sn, arg2, argument);
do_sset(ch, arg1);
}
else
send_to_char("They aren't here.\n\r", ch);
return;
}
if (IS_NPC(victim))
{
send_to_char("Not on NPC's.\n\r", ch);
return;
}
argument = one_argument(argument, arg3);
fAll = !str_cmp(arg2, "all");
sn = 0;
if (!fAll && (sn = skill_lookup(arg2)) < 0)
{
send_to_char("No such skill or spell.\n\r", ch);
return;
}
if (!is_number(arg3) && str_cmp(arg3, "keep"))
{
send_to_char("Point Value must be numeric.\n\r", ch);
return;
}
value = atoi(arg3);
if (!str_cmp(arg3, "keep"))
value = -1;
if (value < -1 || value > MAX_SKPOINTS)
{
ch_printf(ch, "Point Value range is 0 to %d.\n\r", MAX_SKPOINTS);
return;
}
if (argument[0] != '\0')
{
if (!is_number(argument))
{
send_to_char("Mastery Value must be numeric.\n\r", ch);
return;
}
mvalue = atoi(argument);
if (mvalue < 0 || mvalue > MAX_RANKING)
{
ch_printf(ch, "Mastery Value range is 0 to %d.\n\r", MAX_RANKING);
return;
}
}
if (fAll)
{
for (sn = 0; sn < top_sn; sn++)
{
/* Fix by Narn to prevent ssetting skills the player shouldn't have. */
if (skill_table[sn]->name)
{
if (value >= 0)
victim->pcdata->learned[sn] = value;
if (mvalue >= 0)
victim->pcdata->ranking[sn] = mvalue;
if ((skill_table[sn]->group[0] < 23 || skill_table[sn]->group[0] > 29)
&& (skill_table[sn]->group[0] < 31 || skill_table[sn]->group[0] > 34))
{
if (value >= 0)
victim->pcdata->spellpoints[skill_table[sn]->group[0]] = value;
if (mvalue >= 0)
victim->pcdata->spellgroups[skill_table[sn]->group[0]] = mvalue;
}
}
}
}
else
{
if ((skill_table[sn]->group[0] < 23 || skill_table[sn]->group[0] > 29)
&& (skill_table[sn]->group[0] < 31 || skill_table[sn]->group[0] > 34))
{
if (value >= 0)
victim->pcdata->spellpoints[skill_table[sn]->group[0]] = value;
if (mvalue >= 0)
victim->pcdata->spellgroups[skill_table[sn]->group[0]] = mvalue;
}
if (value >= 0)
victim->pcdata->learned[sn] = value;
if (mvalue >= 0)
victim->pcdata->ranking[sn] = mvalue;
}
return;
}
int group_in_sphere(int group)
{
switch (group)
{
case 1:
case 2:
case 3:
case 4:
case 5:
return 3;
case 6:
case 19:
case 20:
case 21:
case 22:
case 23:
return 4;
case 7:
case 8:
case 9:
case 10:
case 18:
return 5;
case 11:
case 12:
case 13:
return 2;
case 14:
case 15:
case 16:
case 17:
return 1;
}
return 0;
}
//Gets values to modify flux on a skill/spell, the actually "curving" of the system to prevent super characters
//Can make some beginnger skills/spells master difficulty to learn if you are going against the grain
int get_skillflux_value(CHAR_DATA *ch, int ssn)
{
int sn;
int i;
int snvalue = 0; //Point value for the sn's group/mastery
int restvalue = 0; //Point value for the other groups/mastery
int totalvalue = 0; //Point total for all spheres.
int diff = 0;
int master = 0;
int specialist = 0;
//Check to see if points are setup yet in spherepoints and grouppoints
if (ch->pcdata->spherepoints[1] == -1 || ch->pcdata->grouppoints[1] == -1)
{
for (i = 1; i <= MAX_SPHERE; i++)
ch->pcdata->spherepoints[i] = 0;
for (i = 1; i <= MAX_GROUP+5; i++)
ch->pcdata->grouppoints[i] = 0;
for (sn = 0; sn < top_sn && skill_table[sn] && skill_table[sn]->name; sn++)
{
if (skill_table[sn]->group[0] > 0)
{
if (skill_table[sn]->stype == 4 && skill_table[sn]->group[0] != 6)
{
ch->pcdata->grouppoints[skill_table[sn]->group[0]+MAX_GROUP] += ch->pcdata->learned[sn];
ch->pcdata->spherepoints[skill_table[sn]->stype] += ch->pcdata->learned[sn];
}
else
{
ch->pcdata->grouppoints[skill_table[sn]->group[0]] += ch->pcdata->learned[sn];
ch->pcdata->spherepoints[skill_table[sn]->stype] += ch->pcdata->learned[sn];
}
}
}
}
//Check to see if player is beyond Beginner
for (sn = 0; sn < top_sn && skill_table[sn] && skill_table[sn]->name; sn++)
{
if ((ch->pcdata->ranking[sn] >= 2 || ch->pcdata->learned[sn] >= 6)
&& (skill_table[sn]->type == SKILL_SPELL || skill_table[sn]->type == SKILL_SKILL))
{
diff = 1; //Beyond the "grace period" above the curve
break;
}
}
//Next check groups, if the sn is in the "master" sphere, compare against other groups instead of spheres
//Has to possess majority of points or more
for (i = 1; i <= MAX_SPHERE; i++)
{
totalvalue += ch->pcdata->spherepoints[i];
}
for (i = 1; i <= MAX_SPHERE; i++)
{
if (ch->pcdata->spherepoints[i] > totalvalue/2) // > 50 percent of all points
break;
}
if (ch->pcdata->spherepoints[skill_table[ssn]->stype] == totalvalue)
{
specialist = 1;
master = 1;
}
else if (i > MAX_SPHERE)
master = 0; //no master sphere
else if (skill_table[ssn]->stype == i)
master = 1; //skill is in master sphere
else if (i <= MAX_SPHERE)
master = 0; //there is a master sphere, but you aren't in it
if (master == 1 && diff == 1) //spell/skill is in the master sphere
{
int group = skill_table[ssn]->group[0];
if (skill_table[ssn]->stype == 4 && skill_table[ssn]->group[0] != 6)
group = skill_table[ssn]->group[0]+MAX_GROUP;
for (i = 1; i <= MAX_GROUP+5; i++)
{
if (group_in_sphere(i) == skill_table[ssn]->stype)
{
if (i == group)
snvalue += ch->pcdata->grouppoints[i];
else
restvalue += ch->pcdata->grouppoints[i];
}
}
}
else //spell/skill is not in the master sphere
{
for (i = 1; i <= MAX_SPHERE; i++)
{
if (skill_table[ssn]->stype == i)
snvalue += ch->pcdata->spherepoints[i];
else
restvalue += ch->pcdata->spherepoints[i];
}
}
//now we have all the values talied, lets spit out the percents and modify based on the "curve"
//a slightly less mean curve when you first start out so you can start a few different things at once before
//getting blasted by the curve
if (diff == 0)
{
if (snvalue > restvalue)
return 100;
else
return 70;
}
if (restvalue <= 0 || specialist == 1)
diff = 1000;
else
diff = 1000*snvalue/(restvalue+snvalue);
//1000 diff means 1:1 500 diff means 1:2 10000 diff means 10:1, etc. Higher the more dominant the group/sphere
//Lower the less dominant. Higher dominance equals more gain, pretty straight.
if (master == 0) //no dominant group, lets make one :-)
{
if (diff < 1000)
{
return (diff*100/1000);
}
else
return 100;
}
if (master == 1) //bonus if you are learning in the master sphere
{
if (diff < 1000)
{
return 60+(diff*40/1000);
}
else
return 100;
}
return 100;
}
//return points earned on percent based on mastery alone, used for learn_from_success/failure
int base_learn_value(CHAR_DATA *ch, int sn)
{
int change = 0;
int pos = 0;
if (ch->pcdata->learned[sn] >= 1 && ch->pcdata->learned[sn] <= 4)
{
if (ch->pcdata->learned[sn] == 1)
change = number_range(500, 750);
if (ch->pcdata->learned[sn] == 2)
change = number_range(400, 600);
if (ch->pcdata->learned[sn] == 3)
change = number_range(350, 550);
if (ch->pcdata->learned[sn] == 4)
change = number_range(300, 500);
}
else if (ch->pcdata->learned[sn] >= 5 && ch->pcdata->learned[sn] <= 7)
{
if (ch->pcdata->learned[sn] == 5)
change = number_range(200, 300);
if (ch->pcdata->learned[sn] == 6)
change = number_range(170, 250);
if (ch->pcdata->learned[sn] == 7)
change = number_range(130, 190);
if (ch->pcdata->ranking[sn] == 1 && ch->pcdata->learned[sn] >= 5)
change /= 3;
}
else if (ch->pcdata->learned[sn] >= 8 && ch->pcdata->learned[sn] <= 10)
{
if (ch->pcdata->learned[sn] == 8)
change = number_range(80, 120);
if (ch->pcdata->learned[sn] == 9)
change = number_range(65, 90);
if (ch->pcdata->learned[sn] == 10)
change = number_range(50, 70);
if (ch->pcdata->ranking[sn] == 1)
change = 1;
if (ch->pcdata->ranking[sn] == 2 && ch->pcdata->learned[sn] >= 8)
change /= 3;
}
else if (ch->pcdata->learned[sn] >= 11 && ch->pcdata->learned[sn] <= 13)
{
if (ch->pcdata->learned[sn] == 11)
change = number_range(35, 45);
if (ch->pcdata->learned[sn] == 12)
change = number_range(25, 30);
if (ch->pcdata->learned[sn] == 13)
change = number_range(20, 25);
if (ch->pcdata->ranking[sn] < 4)
change = 1;
}
else if (ch->pcdata->learned[sn] >= 14 && ch->pcdata->learned[sn] <= 19)
{
change = number_range(5, 15);
if (ch->pcdata->learned[sn] >= 15 && ch->pcdata->ranking[sn] < 5)
change = 0;
if (ch->pcdata->learned[sn] >= 18 && ch->pcdata->ranking[sn] < 6)
change = 0;
}
else
{
if (ch->pcdata->spercent[sn] > 3000)
change = 0;
else
change = number_range(3, 10);
}
change = change * sysdata.exp_percent / 100;
if (change > 0)
pos = 1;
if (ch->race == RACE_HUMAN)
change = change * 150 / 100;
if (sn > 0 && sn < top_sn && skill_table[sn] && skill_table[sn]->name && skill_table[sn]->type == SKILL_SPELL && ch->race == RACE_OGRE)
change = change * 20 / 100;
else
{
if (ch->race == RACE_OGRE)
change = change * 80 / 100;
}
if (sn > 0 && sn < top_sn && skill_table[sn] && skill_table[sn]->name && skill_table[sn]->type == SKILL_SPELL && ch->race == RACE_FAIRY)
change = change * 175 / 100;
//Agent sphere for hobbits
if (sn > 0 && sn < top_sn && skill_table[sn] && skill_table[sn]->name && skill_table[sn]->stype == 2 && ch->race == RACE_HOBBIT)
change = change * 175 / 100;
if (skill_table[sn]->difficulty >= 0 && skill_table[sn]->difficulty <= 13)
{
if (skill_table[sn]->difficulty == 1)
change = change * 95 / 100;
if (skill_table[sn]->difficulty == 2)
change *= .9;
if (skill_table[sn]->difficulty == 3)
change = change * 80 / 100;
if (skill_table[sn]->difficulty == 4)
change = change * 70 / 100;
if (skill_table[sn]->difficulty == 5)
change = change * 65 / 100;
if (skill_table[sn]->difficulty == 6)
change = change * 50 / 100;
if (skill_table[sn]->difficulty == 7)
change = change * 33 / 100;
if (skill_table[sn]->difficulty == 8)
change = change * 25 / 100;
if (skill_table[sn]->difficulty == 9)
change = change * 20 / 100;
if (skill_table[sn]->difficulty == 10)
change = change * 15 / 100;
if (skill_table[sn]->difficulty == 11)
change = change * 10 / 100;
if (skill_table[sn]->difficulty == 12)
change = change * 5 / 100;
if (skill_table[sn]->difficulty == 13)
change = change * 1 / 100;
}
else
{
bug("Sn %d as a difficulty out of the range >= 0 <= 13", sn);
}
change = change * get_skillflux_value(ch, sn) / 100;
if (change < 1 && pos == 1)
change = 1;
return change;
}
/* Added these back in, but made the chance to increase minimal -- Xerves 11/1/99 */
// Put back in for new skill system, a more hybrid version of stock/new system -- Xerves 2001
void learn_from_success(CHAR_DATA * ch, int sn, CHAR_DATA *target)
{
int change;
SKILLTYPE *skill = get_skilltype(sn);
int pos = 0;
int x;
if (IS_NPC(ch))
return;
if (sn == -1)
return;
for (x = 0; x < 5; x++) //no learning list
{
if (ch->pcdata->nolearn[x] == sn)
return;
}
change = base_learn_value(ch, sn);
if (change > 0)
pos = 1;
if (target && !IS_NPC(target) && is_affected(target, sn) && !SPELL_FLAG(skill, SF_ACCUMULATIVE) && !SPELL_FLAG(skill, SF_RECASTABLE))
change /= 3; //Come on quit casting the bloody spell already if they have it already
if (target && IS_NPC(target) && xIS_SET(target->act, ACT_MOUNTSAVE))
{
change = 0;
pos = 0;
}
if (change < 1 && pos == 1)
change = 1;
ch->pcdata->spercent[sn] += change;
if (ch->pcdata->spercent[sn] >= 10000)
{
ch_printf(ch, "&R*********************************************************************\n\r");
ch_printf(ch, "&R*****Your skills in %s has increased 1 Point.*****\n\r", skill_table[sn]->name);
ch_printf(ch, "&R*********************************************************************\n\r");
ch->pcdata->learned[sn]++;
ch->pcdata->spercent[sn] = 200; //So skill doesn't go down in a few minutes
if (skill_table[sn]->stype == 4 && skill_table[sn]->group[0] != 6)
{
ch->pcdata->grouppoints[skill_table[sn]->group[0]+MAX_GROUP]++;
ch->pcdata->spherepoints[skill_table[sn]->stype]++;
}
else
{
ch->pcdata->grouppoints[skill_table[sn]->group[0]]++;
ch->pcdata->spherepoints[skill_table[sn]->stype]++;
}
}
return;
}
void learn_from_failure(CHAR_DATA * ch, int sn, CHAR_DATA *target)
{
int change;
SKILLTYPE *skill = get_skilltype(sn);
int x;
int pos = 0;
if (IS_NPC(ch))
return;
if (sn == 1)
return;
for (x = 0; x < 5; x++) //no learning list
{
if (ch->pcdata->nolearn[x] == sn)
return;
}
change = base_learn_value(ch, sn);
if (change > 0)
pos = 1;
change /= 3; //Failure gives you only 1/3 of the points
if (sn == gsn_critical) //slow this down quite a bit on failures...
change /= 4;
if (target && !IS_NPC(target) && is_affected(target, sn) && !SPELL_FLAG(skill, SF_ACCUMULATIVE) && !SPELL_FLAG(skill, SF_RECASTABLE))
change /= 3; //Come on quit casting the bloody spell already if they have it already
if (target && IS_NPC(target) && xIS_SET(target->act, ACT_MOUNTSAVE))
{
change = 0;
pos = 0;
}
if (change < 1 && pos == 1)
change = 1;
ch->pcdata->spercent[sn] += change;
if (ch->pcdata->spercent[sn] >= 10000)
{
ch_printf(ch, "&R*********************************************************************\n\r");
ch_printf(ch, "&R*****Your skills in %s has increased 1 Point.*****\n\r", skill_table[sn]->name);
ch_printf(ch, "&R*********************************************************************\n\r");
ch->pcdata->learned[sn]++;
ch->pcdata->spercent[sn] = 200; //So skill does not go down in a few minutes
if (skill_table[sn]->stype == 4 && skill_table[sn]->group[0] != 6)
{
ch->pcdata->grouppoints[skill_table[sn]->group[0]+MAX_GROUP]++;
ch->pcdata->spherepoints[skill_table[sn]->stype]++;
}
else
{
ch->pcdata->grouppoints[skill_table[sn]->group[0]]++;
ch->pcdata->spherepoints[skill_table[sn]->stype]++;
}
}
return;
}
void do_gouge(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
AFFECT_DATA af;
sh_int dam;
int chance;
sh_int level;
sh_int mastery;
mastery = MASTERED(ch, gsn_gouge);
level = POINT_LEVEL(LEARNED(ch, gsn_gouge), MASTERED(ch, gsn_gouge));
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't concentrate enough for that.\n\r", ch);
return;
}
if (!can_use_skill(ch, 0, gsn_gouge))
{
send_to_char("You do not yet know of this skill.\n\r", ch);
return;
}
if (ch->mount)
{
send_to_char("You can't get close enough while mounted.\n\r", ch);
return;
}
if ((victim = who_fighting(ch)) == NULL)
{
send_to_char("You aren't fighting anyone.\n\r", ch);
return;
}
chance = 15+(level/6)+((get_curr_dex(ch) - get_curr_dex(victim))*2);
chance = ((get_curr_dex(victim) - get_curr_dex(ch)) * 10) + 10;
if (!IS_NPC(ch) && !IS_NPC(victim))
chance += sysdata.gouge_plr_vs_plr;
if (victim->fighting && victim->fighting->who != ch)
chance += sysdata.gouge_nontank;
if (number_range(1, 100) <= chance)
{
dam = number_range(1, 1+(level/20));
global_retcode = damage(ch, victim, dam, gsn_gouge, 0, -1);
if (global_retcode == rNONE)
{
if (!IS_AFFECTED(victim, AFF_BLIND))
{
af.type = gsn_blindness;
af.location = APPLY_TOHIT;
af.modifier = -4;
af.duration = number_range(8+(level/10), 10+(level/8));
af.bitvector = meb(AFF_BLIND);
affect_to_char(victim, &af);
act(AT_SKILL, "You can't see a thing!", victim, NULL, NULL, TO_CHAR);
}
ch->fight_timer = skill_table[gsn_gouge]->beats;
victim->fight_timer += 2*skill_table[gsn_gouge]->beats;
}
else if (global_retcode == rVICT_DIED)
{
act(AT_BLOOD, "Your fingers plunge into your victim's brain, causing immediate death!", ch, NULL, NULL, TO_CHAR);
}
if (global_retcode != rCHAR_DIED && global_retcode != rVICT_DIED && global_retcode != rBOTH_DIED)
learn_from_success(ch, gsn_gouge, victim);
}
else
{
ch->fight_timer = skill_table[gsn_gouge]->beats;
global_retcode = damage(ch, victim, 0, gsn_gouge, 0, -1);
learn_from_failure(ch, gsn_gouge, victim);
}
return;
}
void do_manashot(CHAR_DATA *ch, char *argument)
{
int level;
CHAR_DATA *victim = NULL;
int dam;
level = POINT_LEVEL(LEARNED(ch, gsn_manashot), MASTERED(ch, gsn_manashot));
if (ch->fighting)
victim = ch->fighting->who;
if (argument[0] != '\0')
{
if ((victim = get_char_room_new(ch, argument, 1)) == NULL)
{
send_to_char("Your target is not in the room with you.\n\r", ch);
return;
}
}
if (!check_twohand_shield(ch))
return;
if (!victim)
{
send_to_char("Syntax: manashot <target>\n\rDo not need to supply a target if fighting.\n\r", ch);
return;
}
if (is_room_safe(ch))
{
send_to_char("This room is a safe area, you cannot fight here.\n\r", ch);
return;
}
dam = UMAX(6, level-2);
dam = number_range(dam*80/100, dam*120/100);
if (is_immune(victim, -1, RIS_MAGIC))
{
act(AT_WHITE, "$n releases a powerful manashot toward $N, but $N is immune to magic.", ch, NULL, victim, TO_NOTVICT);
act(AT_WHITE, "$n releases a powerful manashot toward you, but you are immune to magic.", ch, NULL, victim, TO_VICT);
act(AT_WHITE, "You release a powerful manashot toward $N, but $N is immune to magic.", ch, NULL, victim, TO_CHAR);
damage(ch, victim, 0, gsn_manashot, 0, -1);
return;
}
if (saves_spell_staff(level, victim))
dam = dam * 3 / 4;
act(AT_WHITE, "$n channels $s energy and blasts $N with a powerful manashot.", ch, NULL, victim, TO_NOTVICT);
act(AT_WHITE, "$n channels $s energy and blasts you with a powerful manashot.", ch, NULL, victim, TO_VICT);
act(AT_WHITE, "You channel your energy and blast $N with a powerful manashot.", ch, NULL, victim, TO_CHAR);
damage(ch, victim, dam, gsn_manashot, 0, -1);
learn_from_success(ch, gsn_manashot, victim);
if (ch->fighting)
ch->fight_timer = get_btimer(ch, gsn_manashot, NULL);
else
WAIT_STATE(ch, skill_table[gsn_manashot]->beats*2);
return;
}
void do_manaburst(CHAR_DATA *ch, char *argument)
{
int level;
CHAR_DATA *vch;
CHAR_DATA *vch_next;
int dam;
int num = 0;
level = POINT_LEVEL(LEARNED(ch, gsn_manaburst), MASTERED(ch, gsn_manaburst));
if (is_room_safe(ch))
{
send_to_char("This room is a safe area, you cannot fight here.\n\r", ch);
return;
}
if (!check_twohand_shield(ch))
return;
act(AT_WHITE, "$n starts scream and a large amount of energy pours and hits everything around $m.", ch, NULL, NULL, TO_ROOM);
act(AT_WHITE, "You start screaming and a large amount of energy pours out and hits everything around you.", ch, NULL, NULL, TO_CHAR);
for (vch = ch->in_room->first_person; vch; vch = vch_next)
{
vch_next = vch->next_in_room;
if (ch->coord->x != vch->coord->x || ch->coord->y != vch->coord->y
|| ch->map != vch->map)
continue;
if (!IS_NPC(vch) && xIS_SET(vch->act, PLR_WIZINVIS) && vch->pcdata->wizinvis >= LEVEL_IMMORTAL)
continue;
if (IS_NPC(vch) && IS_AFFECTED(vch, AFF_CHARM) && vch->master == ch)
continue;
if (!IS_NPC(ch) && IS_NPC(vch) && IS_ACT_FLAG(vch, ACT_MOUNTSAVE))
continue;
if (vch != ch && (IS_NPC(ch) ? !IS_NPC(vch) : IS_NPC(vch)))
{
num++;
dam = 30+level*15/10;
dam = number_range(dam*80/100, dam*120/100);
if (saves_spell_staff(level, vch))
dam = dam * 3 / 4;
damage(ch, vch, dam, gsn_manaburst, 0, -1);
}
if (char_died(ch))
return;
}
if (ch->fighting)
ch->fight_timer = get_btimer(ch, gsn_manaburst, NULL);
else
WAIT_STATE(ch, skill_table[gsn_manaburst]->beats*2);
if (num)
learn_from_success(ch, gsn_manaburst, NULL);
return;
}
void do_nervestrike(CHAR_DATA *ch, char *argument)
{
CHAR_DATA *victim;
AFFECT_DATA af;
int chance;
int level;
bool fail;
level = POINT_LEVEL(LEARNED(ch, gsn_nervestrike), MASTERED(ch, gsn_nervestrike));
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't concentrate enough for that.\n\r", ch);
return;
}
if (!IS_NPC(ch) && ch->pcdata->ranking[gsn_nervestrike] <= 0)
{
send_to_char("Hard to strike at a nerve if you don't even know where one is.\n\r", ch);
return;
}
if (!ch->fighting || !ch->fighting->who)
{
send_to_char("You can only use this during the heat of battle.\n\r", ch);
return;
}
if ((victim = get_char_room_new(ch, argument, 1)) == NULL)
{
victim = ch->fighting->who;
}
if (is_safe(ch, victim))
{
send_to_char("You cannot nervestrike that target.\n\r", ch);
return;
}
check_illegal_pk(ch, victim);
check_attacker(ch, victim);
if (!IS_NPC(ch) && HAS_WAIT(ch))
{
send_to_char("You are too busy in battle to do that.\n\r", ch);
return;
}
ch->fight_timer = get_btimer(ch, gsn_nervestrike, NULL);
fail = FALSE;
chance = 5+level/4;
if (!IS_NPC(ch) && !IS_NPC(victim))
chance -= sysdata.stun_plr_vs_plr;
else
chance -= sysdata.stun_regular;
chance += ((get_curr_dex(victim) + get_curr_str(victim)) - (get_curr_dex(ch) + get_curr_str(ch))) * 3;
chance += URANGE(-10, (get_curr_int(ch)-14)/2 + (get_curr_wis(ch)-14)/2, 10);
chance += victim->saving_para_petri;
if (victim->max_hit > 2000)
chance /= 2;
if (victim->max_hit > 5000)
chance /= 2;
chance = URANGE(5, chance, 45);
if (!fail)
{
if (number_range(1, 100) > chance)
fail = TRUE;
}
if (!fail)
{
learn_from_success(ch, gsn_nervestrike, victim);
ch->fight_timer = skill_table[gsn_nervestrike]->beats;
act(AT_SKILL, "$N lunges at your neck and strikes a vital nerve. You are PARALYZED TEMPORARILY!", victim, NULL, ch, TO_CHAR);
act(AT_SKILL, "You lunge at $N's neck and strike a vital nerve. $N is PARALYZED TEMPORARILY!", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n lunges at $N's neck and strike a vital nerve. $N is PARALYZED TEMPORARILY!", ch, NULL, victim, TO_NOTVICT);
if (!IS_AFFECTED(victim, AFF_PARALYSIS))
{
af.type = gsn_stun;
af.location = APPLY_ARMOR;
af.modifier = -3;
af.duration = 5+(MASTERED(ch, gsn_nervestrike)*3/2);
if (IS_NPC(ch))
af.duration = 2+MASTERED(ch, gsn_nervestrike);
af.bitvector = meb(AFF_PARALYSIS);
affect_to_char(victim, &af);
update_pos(victim);
}
start_hating(victim, ch);
start_hunting(victim, ch);
}
else
{
ch->fight_timer = skill_table[gsn_nervestrike]->beats;
learn_from_failure(ch, gsn_nervestrike, victim);
act(AT_SKILL, "$n lunges at your neck and attempts to strike a vital nerve, but $e misses.", ch, NULL, victim, TO_VICT);
act(AT_SKILL, "You try to strike a vital nerve on $N's neck, but you miss.", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n lunges at $N's neck and attempts to strike a vital nerve, but $e fails.", ch, NULL, victim, TO_NOTVICT);
start_hating(victim, ch);
start_hunting(victim, ch);
}
return;
}
void do_quickcombo(CHAR_DATA *ch, char *argument)
{
CHAR_DATA *victim = NULL;
int level;
int sn[6];
char arg[MIL];
int x, y;
int right;
char buf[MSL];
int remain;
for (x = 0; x <= 5; x++)
sn[x] = 0;
level = POINT_LEVEL(LEARNED(ch, gsn_quickcombo), MASTERED(ch, gsn_quickcombo));
if (argument[0] == '\0')
{
send_to_char("Syntax: quickcombo <right/left> <strike1> <strike2> [strike3] [strike4] [strike5] [victim]\n\r", ch);
send_to_char("Note: strike3-5 is available if you have expert/elite/flawless in quickcombo.\n\r", ch);
return;
}
argument = one_argument(argument, arg);
if (!str_cmp(arg, "right"))
right = 1;
else
right = 0;
argument = one_argument(argument, arg);
if ((sn[1] = skill_lookup(arg)) < 1)
{
send_to_char("Strike1 is not a valid strike.\n\r", ch);
return;
}
if (skill_table[sn[1]]->group[0] != 7) //Group with all the strikes
{
send_to_char("Strike1 has to be an actual strike (ex: blitz)\n\r", ch);
return;
}
argument = one_argument(argument, arg);
if ((sn[2] = skill_lookup(arg)) < 1)
{
send_to_char("Strike2 is not a valid strike.\n\r", ch);
return;
}
if (skill_table[sn[2]]->group[0] != 7) //Group with all the strikes
{
send_to_char("Strike2 has to be an actual strike (ex: blitz)\n\r", ch);
return;
}
one_argument(argument, arg);
if ((sn[3] = skill_lookup(arg)) >= 1)
{
argument = one_argument(argument, arg);
if (MASTERED(ch, gsn_quickcombo) < 3)
{
send_to_char("You can only specify a 3rd strike if you have expert or higher mastery.\n\r", ch);
return;
}
if (skill_table[sn[3]]->group[0] != 7) //Group with all the strikes
{
send_to_char("Strike3 has to be an actual strike (ex: blitz)\n\r", ch);
return;
}
}
one_argument(argument, arg);
if ((sn[4] = skill_lookup(arg)) >= 1)
{
argument = one_argument(argument, arg);
if (MASTERED(ch, gsn_quickcombo) < 5)
{
send_to_char("You can only specify a 4rd strike if you have elite or higher mastery.\n\r", ch);
return;
}
if (skill_table[sn[4]]->group[0] != 7) //Group with all the strikes
{
send_to_char("Strike4 has to be an actual strike (ex: blitz)\n\r", ch);
return;
}
}
one_argument(argument, arg);
if ((sn[5] = skill_lookup(arg)) >= 1)
{
argument = one_argument(argument, arg);
if (MASTERED(ch, gsn_quickcombo) < 5)
{
send_to_char("You can only specify a 5th strike if you have flawless or higher mastery.\n\r", ch);
return;
}
if (skill_table[sn[5]]->group[0] != 7) //Group with all the strikes
{
send_to_char("Strike5 has to be an actual strike (ex: blitz)\n\r", ch);
return;
}
}
for (x = 1; x <= 5; x++)
{
for (y = 1; y <= 5; y++)
{
if (x == y)
continue;
if (sn[x] <= 0 || sn[y] <= 0)
continue;
if (skill_table[sn[x]]->targetlimb == skill_table[sn[y]]->targetlimb)
break;
}
if (y != 6)
{
send_to_char("Each strike has to target a different limb.\n\r", ch);
return;
}
}
if (ch->fighting)
victim = ch->fighting->who;
if (argument[0] != '\0')
{
if ((victim = get_char_room_new(ch, argument, 1)) == NULL)
{
send_to_char("Your target is not in the room with you.\n\r", ch);
return;
}
}
if (!victim)
{
do_quickcombo(ch, "");
return;
}
if (is_room_safe(ch))
{
send_to_char("This room is a safe area, you cannot fight here.\n\r", ch);
return;
}
sprintf(buf, "'%s' %s", victim->name, right ? "right" : "left");
//Legs/Arms need right/left argument
if (skill_table[sn[1]]->targetlimb == 1 || skill_table[sn[1]]->targetlimb == 2)
(*skill_table[sn[1]]->skill_fun) (ch, buf);
else
(*skill_table[sn[1]]->skill_fun) (ch, victim->name);
if (skill_table[sn[2]]->targetlimb == 1 || skill_table[sn[2]]->targetlimb == 2)
(*skill_table[sn[2]]->skill_fun) (ch, buf);
else
(*skill_table[sn[2]]->skill_fun) (ch, victim->name);
if (sn[3] > 0)
{
if (skill_table[sn[3]]->targetlimb == 1 || skill_table[sn[3]]->targetlimb == 2)
(*skill_table[sn[3]]->skill_fun) (ch, buf);
else
(*skill_table[sn[3]]->skill_fun) (ch, victim->name);
}
if (sn[4] > 0)
{
if (skill_table[sn[4]]->targetlimb == 1 || skill_table[sn[4]]->targetlimb == 2)
(*skill_table[sn[4]]->skill_fun) (ch, buf);
else
(*skill_table[sn[4]]->skill_fun) (ch, victim->name);
}
if (sn[5] > 0)
{
if (skill_table[sn[5]]->targetlimb == 1 || skill_table[sn[5]]->targetlimb == 2)
(*skill_table[sn[5]]->skill_fun) (ch, buf);
else
(*skill_table[sn[5]]->skill_fun) (ch, victim->name);
}
remain = ch->fight_timer * UMAX(40, (100-(level*2/3))) % 100;
ch->fight_timer = ch->fight_timer * UMAX(40, (100-(level*2/3))) / 100;
if (number_range(1, 100) <= remain)
ch->fight_timer += 1;
if (ch->fight_timer < 1)
ch->fight_timer = 1;
learn_from_success(ch, gsn_quickcombo, victim);
return;
}
void do_kickdirt(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
AFFECT_DATA af;
int chance;
sh_int level;
sh_int mastery;
int sector;
mastery = MASTERED(ch, gsn_kickdirt);
level = POINT_LEVEL(LEARNED(ch, gsn_kickdirt), MASTERED(ch, gsn_kickdirt));
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't concentrate enough for that.\n\r", ch);
return;
}
if (!can_use_skill(ch, 0, gsn_kickdirt))
{
send_to_char("You do not yet know of this skill.\n\r", ch);
return;
}
if (ch->mount)
{
send_to_char("What do you want to do, blind your target with your mount?.\n\r", ch);
return;
}
if ((victim = who_fighting(ch)) == NULL)
{
send_to_char("You aren't fighting anyone.\n\r", ch);
return;
}
if (IN_WILDERNESS(ch))
{
sector = map_sector[ch->map][ch->coord->x][ch->coord->y];
}
else
{
sector = ch->in_room->sector_type;
}
if (sector != SECT_FIELD && sector != SECT_FOREST && sector != SECT_HILLS && sector != SECT_MOUNTAIN
&& sector != SECT_DESERT && sector != SECT_UNDERGROUND && sector != SECT_MINEGOLD && sector != SECT_MINEIRON
&& sector != SECT_HCORN && sector != SECT_HGRAIN && sector != SECT_STREE && sector != SECT_NTREE
&& sector != SECT_SCORN && sector != SECT_NCORN && sector != SECT_SIRON && sector != SECT_NIRON
&& sector != SECT_SGRAIN && sector != SECT_NGRAIN && sector != SECT_JUNGLE && sector != SECT_SHORE
&& sector != SECT_SWAMP && sector != SECT_PATH && sector != SECT_PLAINS && sector != SECT_BURNT
&& sector != SECT_STONE && sector != SECT_SSTONE && sector != SECT_NSTONE)
{
send_to_char("There has to be dirt on the ground to kick.\n\r", ch);
return;
}
chance = 15+(level/4)+((get_curr_dex(ch) - get_curr_dex(victim))*5);
if (number_range(1, 100) <= chance)
{
act(AT_RED, "$n kicks dirt into the eyes of $N blinding $M.", ch, NULL, victim, TO_NOTVICT);
act(AT_RED, "$n kicks dirt into your eyes blinding you!", ch, NULL, victim, TO_VICT);
act(AT_RED, "You kick dirt into the eyes of $N blinding $M.", ch, NULL, victim, TO_CHAR);
if (!IS_AFFECTED(victim, AFF_BLIND))
{
af.type = gsn_blindness;
af.location = APPLY_TOHIT;
af.modifier = -2;
af.duration = number_range(4+(level/10), 6+(level/8));
af.bitvector = meb(AFF_BLIND);
affect_to_char(victim, &af);
act(AT_SKILL, "You can't see a thing!", victim, NULL, NULL, TO_CHAR);
}
ch->fight_timer = skill_table[gsn_kickdirt]->beats;
learn_from_success(ch, gsn_kickdirt, victim);
}
else
{
act(AT_RED, "$n kicks dirt toward the eyes of $N, but $E dodges it.", ch, NULL, victim, TO_NOTVICT);
act(AT_RED, "$n kicks dirt toward your eyes, but you happen to dodge it.", ch, NULL, victim, TO_VICT);
act(AT_RED, "You kick dirt toward the eyes of $N, but $E dodges it.", ch, NULL, victim, TO_CHAR);
ch->fight_timer = skill_table[gsn_kickdirt]->beats;
learn_from_failure(ch, gsn_kickdirt, victim);
}
return;
}
void do_detrap(CHAR_DATA * ch, char *argument)
{
char arg[MIL];
OBJ_DATA *obj;
OBJ_DATA *trap;
TRAP_DATA *ntrap;
OBJ_DATA *tool;
int percent;
sh_int level;
sh_int mastery;
trap = NULL;
ntrap = NULL;
mastery = MASTERED(ch, gsn_detrap);
level = POINT_LEVEL(LEARNED(ch, gsn_detrap), MASTERED(ch, gsn_detrap));
switch (ch->substate)
{
default:
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't concentrate enough for that.\n\r", ch);
return;
}
argument = one_argument(argument, arg);
if (!can_use_skill(ch, 0, gsn_detrap))
{
send_to_char("You do not yet know of this skill.\n\r", ch);
return;
}
if (arg[0] == '\0')
{
send_to_char("Detrap what?\n\r", ch);
return;
}
if (ms_find_obj(ch))
return;
if (ch->mount)
{
send_to_char("You can't do that while mounted.\n\r", ch);
return;
}
if ((obj = get_obj_here(ch, arg)) == NULL)
{
send_to_char("You can't find that here.\n\r", ch);
return;
}
act(AT_ACTION, "You carefully begin your attempt to remove a trap from $p...", ch, obj, NULL, TO_CHAR);
act(AT_ACTION, "$n carefully attempts to remove a trap from $p...", ch, obj, NULL, TO_ROOM);
ch->alloc_ptr = str_dup(obj->name);
add_timer(ch, TIMER_DO_FUN, 6, do_detrap, 1);
WAIT_STATE( ch, skill_table[gsn_detrap]->beats*2 );
return;
case 1:
if (!ch->alloc_ptr)
{
send_to_char("Your detrapping was interrupted!\n\r", ch);
bug("do_detrap: ch->alloc_ptr NULL!", 0);
return;
}
strcpy(arg, ch->alloc_ptr);
DISPOSE(ch->alloc_ptr);
ch->alloc_ptr = NULL;
ch->substate = SUB_NONE;
break;
case SUB_TIMER_DO_ABORT:
DISPOSE(ch->alloc_ptr);
ch->substate = SUB_NONE;
send_to_char("You carefully stop what you were doing.\n\r", ch);
return;
}
if ((obj = get_obj_here(ch, arg)) == NULL)
{
send_to_char("You can't find that here.\n\r", ch);
return;
}
trap = get_trap(obj);
if (obj->trap)
{
ntrap = obj->trap;
trap = NULL;
}
if (!trap && !ntrap)
{
send_to_char("You find no trap on that.\n\r", ch);
return;
}
percent = UMIN(100, 30 + level + URANGE(-15, (14-get_curr_lck(ch))*3, 20));
if (ntrap)
percent -= ntrap->difficulty;
if (ntrap && ntrap->toolkit > 0)
{
for (tool = ch->first_carrying; tool; tool = tool->next_content)
{
if (tool->item_type == ITEM_TRAPTOOL && tool->value[0] == ntrap->toolkit)
percent += ntrap->toolnegate;
}
}
separate_obj(obj);
if (number_range(1, 100) > percent)
{
send_to_char("Ooops!\n\r", ch);
pre_spring_trap(ch, trap, ntrap, obj);
learn_from_failure(ch, gsn_detrap, NULL);
return;
}
if (ntrap)
{
if (ntrap->uid >= START_INV_TRAP)
{
UNLINK(ntrap, first_trap, last_trap, next, prev);
ntrap->obj->trap = NULL;
DISPOSE(ntrap);
save_trap_file(NULL, NULL);
}
else
{
ntrap->obj->trap = NULL;
ntrap->obj = NULL;
ntrap->area = NULL;
}
}
if (trap)
extract_obj(trap);
send_to_char("You successfully remove a trap.\n\r", ch);
learn_from_success(ch, gsn_detrap, NULL);
return;
}
void do_dig(CHAR_DATA * ch, char *argument)
{
char arg[MIL];
OBJ_DATA *obj;
OBJ_DATA *startobj;
bool found, shovel;
EXIT_DATA *pexit;
sh_int mastery;
mastery = 10;
if (IS_ONMAP_FLAG(ch))
{
send_to_char("You cannot dig on an overland map.\n\r", ch);
return;
}
switch (ch->substate)
{
default:
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't concentrate enough for that.\n\r", ch);
return;
}
if (ch->mount)
{
send_to_char("You can't do that while mounted.\n\r", ch);
return;
}
one_argument(argument, arg);
if (arg[0] != '\0')
{
if ((pexit = find_door(ch, arg, TRUE)) == NULL && get_dir(arg) == -1)
{
send_to_char("What direction is that?\n\r", ch);
return;
}
if (pexit)
{
if (!IS_SET(pexit->exit_info, EX_DIG) && !IS_SET(pexit->exit_info, EX_CLOSED))
{
send_to_char("There is no need to dig out that exit.\n\r", ch);
return;
}
}
}
else
{
switch (ch->in_room->sector_type)
{
case SECT_CITY:
case SECT_INSIDE:
send_to_char("The floor is too hard to dig through.\n\r", ch);
return;
case SECT_WATER_SWIM:
case SECT_WATER_NOSWIM:
case SECT_UNDERWATER:
send_to_char("You cannot dig here.\n\r", ch);
return;
case SECT_AIR:
send_to_char("What? In the air?!\n\r", ch);
return;
}
}
add_timer(ch, TIMER_DO_FUN, 3, do_dig, 1);
ch->alloc_ptr = str_dup(arg);
send_to_char("You begin digging...\n\r", ch);
act(AT_PLAIN, "$n begins digging...", ch, NULL, NULL, TO_ROOM);
return;
case 1:
if (!ch->alloc_ptr)
{
send_to_char("Your digging was interrupted!\n\r", ch);
act(AT_PLAIN, "$n's digging was interrupted!", ch, NULL, NULL, TO_ROOM);
bug("do_dig: alloc_ptr NULL", 0);
return;
}
strcpy(arg, ch->alloc_ptr);
DISPOSE(ch->alloc_ptr);
break;
case SUB_TIMER_DO_ABORT:
DISPOSE(ch->alloc_ptr);
ch->substate = SUB_NONE;
send_to_char("You stop digging...\n\r", ch);
act(AT_PLAIN, "$n stops digging...", ch, NULL, NULL, TO_ROOM);
return;
}
ch->substate = SUB_NONE;
/* not having a shovel makes it harder to succeed */
shovel = FALSE;
for (obj = ch->first_carrying; obj; obj = obj->next_content)
if (obj->item_type == ITEM_SHOVEL)
{
shovel = TRUE;
break;
}
/* dig out an EX_DIG exit... */
if (arg[0] != '\0')
{
if ((pexit = find_door(ch, arg, TRUE)) != NULL && IS_SET(pexit->exit_info, EX_DIG) && IS_SET(pexit->exit_info, EX_CLOSED))
{
if (number_range(1, 100) <= mastery * (shovel ? 8 : 1))
{
REMOVE_BIT(pexit->exit_info, EX_CLOSED);
send_to_char("You dig open a passageway!\n\r", ch);
act(AT_PLAIN, "$n digs open a passageway!", ch, NULL, NULL, TO_ROOM);
return;
}
}
send_to_char("Your dig did not discover any exit...\n\r", ch);
act(AT_PLAIN, "$n's dig did not discover any exit...", ch, NULL, NULL, TO_ROOM);
return;
}
startobj = ch->in_room->first_content;
found = FALSE;
for (obj = startobj; obj; obj = obj->next_content)
{
/* twice as hard to find something without a shovel */
if (IS_OBJ_STAT(obj, ITEM_BURIED) && (number_range(1, 100) <= mastery * (shovel ? 8 : 1)))
{
found = TRUE;
break;
}
}
if (!found)
{
send_to_char("Your dig uncovered nothing.\n\r", ch);
act(AT_PLAIN, "$n's dig uncovered nothing.", ch, NULL, NULL, TO_ROOM);
return;
}
separate_obj(obj);
xREMOVE_BIT(obj->extra_flags, ITEM_BURIED);
act(AT_SKILL, "Your dig uncovered $p!", ch, obj, NULL, TO_CHAR);
act(AT_SKILL, "$n's dig uncovered $p!", ch, obj, NULL, TO_ROOM);
if (obj->item_type == ITEM_CORPSE_PC || obj->item_type == ITEM_CORPSE_NPC)
adjust_favor(ch, 14, 1);
return;
}
void do_search(CHAR_DATA * ch, char *argument)
{
char arg[MIL];
OBJ_DATA *obj;
OBJ_DATA *container;
OBJ_DATA *startobj;
int percent, door;
sh_int mastery;
mastery = 30;
door = -1;
switch (ch->substate)
{
default:
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't concentrate enough for that.\n\r", ch);
return;
}
if (ch->mount)
{
send_to_char("You can't do that while mounted.\n\r", ch);
return;
}
argument = one_argument(argument, arg);
if (arg[0] != '\0' && (door = get_door(arg)) == -1)
{
container = get_obj_here(ch, arg);
if (!container)
{
send_to_char("You can't find that here.\n\r", ch);
return;
}
if (container->item_type != ITEM_CONTAINER)
{
send_to_char("You can't search in that!\n\r", ch);
return;
}
if (IS_SET(container->value[1], CONT_CLOSED))
{
send_to_char("It is closed.\n\r", ch);
return;
}
}
add_timer(ch, TIMER_DO_FUN, 3, do_search, 1);
send_to_char("You begin your search...\n\r", ch);
ch->alloc_ptr = str_dup(arg);
return;
case 1:
if (!ch->alloc_ptr)
{
send_to_char("Your search was interrupted!\n\r", ch);
bug("do_search: alloc_ptr NULL", 0);
return;
}
strcpy(arg, ch->alloc_ptr);
DISPOSE(ch->alloc_ptr);
break;
case SUB_TIMER_DO_ABORT:
DISPOSE(ch->alloc_ptr);
ch->substate = SUB_NONE;
send_to_char("You stop your search...\n\r", ch);
return;
}
ch->substate = SUB_NONE;
if (arg[0] == '\0')
startobj = ch->in_room->first_content;
else
{
if ((door = get_door(arg)) != -1)
startobj = NULL;
else
{
container = get_obj_here(ch, arg);
if (!container)
{
send_to_char("You can't find that here.\n\r", ch);
return;
}
startobj = container->first_content;
}
}
if ((!startobj && door == -1) || IS_NPC(ch))
{
send_to_char("You find nothing.\n\r", ch);
return;
}
percent = mastery;
if (door != -1)
{
EXIT_DATA *pexit;
if ((pexit = get_exit(ch->in_room, door)) != NULL
&& IS_SET(pexit->exit_info, EX_SECRET) && IS_SET(pexit->exit_info, EX_xSEARCHABLE) && number_range(1,100) <= mastery)
{
act(AT_SKILL, "Your search reveals the $d!", ch, NULL, pexit->keyword, TO_CHAR);
act(AT_SKILL, "$n finds the $d!", ch, NULL, pexit->keyword, TO_ROOM);
REMOVE_BIT(pexit->exit_info, EX_SECRET);
return;
}
}
else
for (obj = startobj; obj; obj = obj->next_content)
{
if (IS_OBJ_STAT(obj, ITEM_HIDDEN) && number_range(1, 100) <= mastery)
{
separate_obj(obj);
xREMOVE_BIT(obj->extra_flags, ITEM_HIDDEN);
act(AT_SKILL, "Your search reveals $p!", ch, obj, NULL, TO_CHAR);
act(AT_SKILL, "$n finds $p!", ch, obj, NULL, TO_ROOM);
return;
}
}
send_to_char("You find nothing.\n\r", ch);
return;
}
void set_thief(CHAR_DATA *ch, CHAR_DATA *victim)
{
INTRO_DATA *intro = NULL;
CHAR_DATA *rch;
if (!IS_NPC(victim))
{
for (intro = victim->pcdata->first_introduction; intro; intro = intro->next)
{
if (intro->pid == ch->pcdata->pid && can_see_intro(ch, victim))
{
if (intro->value > 0)
intro->value *=-1;
intro->value -=15000;
if (intro->value < -150000)
intro->value = -150000;
SET_BIT(intro->flags, INTRO_MYTHIEF);
REMOVE_BIT(intro->flags, INTRO_THIEF);
intro->lastseen = time(0);
break;
}
}
}
if (!IS_NPC(victim) && !intro && can_see_intro(ch, victim))
{
CREATE(intro, INTRO_DATA, 1);
intro->pid = ch->pcdata->pid;
intro->value = -15000;
intro->lastseen = time(0);
SET_BIT(intro->flags, INTRO_MYTHIEF);
LINK(intro, victim->pcdata->first_introduction, victim->pcdata->last_introduction, next, prev);
}
for (rch = ch->in_room->first_person; rch; rch = rch->next)
{
if (!IS_NPC(rch))
{
for (intro = rch->pcdata->first_introduction; intro; intro = intro->next)
{
if (rch->pcdata->pid == intro->pid && rch != ch && rch != victim && can_see_intro(rch, victim))
{
if (intro->value > 100000)
continue;
if (intro->value > 0)
intro->value *=-1;
intro->value -=15000;
if (intro->value < -150000)
intro->value = -150000;
intro->lastseen = time(0);
if (!IS_SET(intro->flags, INTRO_MYTHIEF))
SET_BIT(intro->flags, INTRO_THIEF);
break;
}
}
if (!intro && can_see_intro(rch, victim) && rch != ch && rch != victim)
{
CREATE(intro, INTRO_DATA, 1);
intro->pid = ch->pcdata->pid;
intro->value = -15000;
intro->lastseen = time(0);
SET_BIT(intro->flags, INTRO_THIEF);
LINK(intro, rch->pcdata->first_introduction, rch->pcdata->last_introduction, next, prev);
}
save_char_obj(rch);
}
}
if (!IS_NPC(victim))
save_char_obj(victim);
save_char_obj(ch);
}
void do_gathertinder(CHAR_DATA *ch, char *argument)
{
int chance = 0;
OBJ_DATA *tinder;
int sector;
if (IN_WILDERNESS(ch))
{
sector = map_sector[ch->map][ch->coord->x][ch->coord->y];
}
else
{
sector = ch->in_room->sector_type;
}
if (sector == SECT_FOREST || sector == SECT_STREE || sector == SECT_NTREE)
{
if (sector == SECT_FOREST)
chance = 85;
if (sector == SECT_STREE)
chance = 55;
if (sector == SECT_NTREE)
chance = 20;
if (number_range(1, 100) <= chance)
{
act(AT_ORANGE, "$n starts to search around for some free tinder and happens to find some.", ch, NULL, NULL, TO_ROOM);
act(AT_ORANGE, "You start to search around for some free tinder and happen to find some!", ch, NULL, NULL, TO_CHAR);
tinder = create_object(get_obj_index(OBJ_VNUM_TINDER), 1);
if (!tinder)
{
bug("do_gathertinder. Missing the tinder vnum!");
return;
}
obj_to_room(tinder, ch->in_room, ch);
WAIT_STATE(ch, PULSE_PER_SECOND*4);
return;
}
else
{
act(AT_GREEN, "$n starts to search around for some free tinder, but happens to find none.", ch, NULL, NULL, TO_ROOM);
act(AT_GREEN, "You start to search around for some free tinder, but you happen to fine none.", ch, NULL, NULL, TO_CHAR);
WAIT_STATE(ch, PULSE_PER_SECOND*10);
return;
}
}
else
{
send_to_char("This will only work in an area highly populated with trees.\n\r", ch);
return;
}
}
void do_startfire(CHAR_DATA * ch, char *argument)
{
OBJ_DATA *tinder;
OBJ_DATA *flint;
OBJ_DATA *knife;
OBJ_DATA *fire;
int sector;
int chance;
int level = POINT_LEVEL(LEARNED(ch, gsn_startfire), MASTERED(ch, gsn_startfire));
if (IN_WILDERNESS(ch))
{
sector = map_sector[ch->map][ch->coord->x][ch->coord->y];
}
else
{
sector = ch->in_room->sector_type;
}
if ((knife = get_eq_char(ch, WEAR_WIELD)) == NULL)
{
send_to_char("You need to be wielding some knife like weapon to do this.\n\r", ch);
return;
}
if (wielding_skill_weapon(ch, 0) != 7)
{
send_to_char("You need to be wielding some knife like weapon to do this.\n\r", ch);
return;
}
for (tinder = ch->first_carrying; tinder; tinder = tinder->next_content)
{
if (tinder->item_type == ITEM_TINDER)
{
break;
}
}
if (!tinder)
{
send_to_char("You need to have some tinder to start a fire. See (HELP STARTFIRE) to see how to get tinder.\n\r", ch);
return;
}
for (flint = ch->first_carrying; flint; flint = flint->next_content)
{
if (flint->item_type == ITEM_FLINT)
{
break;
}
}
if (!flint)
{
send_to_char("You need to have a flint to start a fire. See (HELP STARTFIRE) to see how to get a flint.\n\r", ch);
return;
}
if (sector == SECT_WATER_SWIM || sector == SECT_WATER_NOSWIM || sector == SECT_UNDERWATER || sector == SECT_AIR
|| sector == SECT_OCEANFLOOR || sector == SECT_OCEAN || sector == SECT_RIVER)
{
send_to_char("You need dry ground to start a fire.\n\r", ch);
return;
}
chance = 1 + (level*3/2);
if (number_range(1, 100) <= chance)
{
act(AT_RED, "$n pulls out a $p and strikes it against a flint....a fire starts burning up the tinder.", ch, knife, NULL, TO_ROOM);
act(AT_RED, "You pull out a $p and strike it against a flint....luckily a fire starts burning up the tinder.", ch, knife, NULL, TO_CHAR);
learn_from_success(ch, gsn_startfire, NULL);
fire = create_object(get_obj_index(OBJ_VNUM_FIRE), 1);
if (!fire)
{
bug("do_startfire. Missing the fire vnum!");
return;
}
WAIT_STATE(ch, PULSE_PER_SECOND*2);
obj_to_room(fire, ch->in_room, ch);
separate_obj(tinder);
obj_from_char(tinder);
extract_obj(tinder);
return;
}
else
{
act(AT_GREEN, "$n pulls out a $p and strikes it against a flint....no such luck though creating a fire.", ch, knife, NULL, TO_ROOM);
act(AT_GREEN, "You pull out a $p and strike it against a flint.....no luck today, the tinder did not catch fire.", ch, knife, NULL, TO_CHAR);
learn_from_failure(ch, gsn_startfire, NULL);
WAIT_STATE(ch, PULSE_PER_SECOND*5);
return;
}
}
void do_forage(CHAR_DATA * ch, char *argument)
{
int sector;
int food;
char name[MSL];
char shortd[MSL];
char longd[MSL];
char arg[MIL];
int fv=1;
int chance;
int speed = PULSE_PER_SECOND*6;
OBJ_DATA *ofood;
if (check_npc(ch))
return;
if (argument[0] == '\0')
{
send_to_char("Syntax: forage food [quick/normal/long]\n\r", ch);
send_to_char("Syntax: forage water [quick/normal/long]\n\r", ch);
return;
}
if (IN_WILDERNESS(ch))
{
sector = map_sector[ch->map][ch->coord->x][ch->coord->y];
}
else
{
sector = ch->in_room->sector_type;
}
argument = one_argument(argument, arg);
if (!str_cmp(arg, "water"))
{
for (ofood = ch->first_carrying; ofood; ofood = ofood->next_content)
{
if (ofood->item_type == ITEM_DRINK_CON)
{
break;
}
}
if (!ofood)
{
send_to_char("You need something to hold the water.\n\r", ch);
return;
}
if (ofood->value[1] >= ofood->value[0])
{
send_to_char("Your drinking container is full.\n\r", ch);
return;
}
if (sector == SECT_WATER_SWIM || sector == SECT_WATER_NOSWIM || sector == SECT_RIVER)
{
act(AT_GREEN, "$n gets on $s knees and fills up $p with fresh water.", ch, ofood, NULL, TO_ROOM);
act(AT_GREEN, "You get on your knees and fill up $p with fresh water.", ch, ofood, NULL, TO_CHAR);
ofood->value[1] = ofood->value[0];
learn_from_success(ch, gsn_forage, NULL);
WAIT_STATE(ch, speed);
return;
}
else if (sector == SECT_FIELD || sector == SECT_FOREST || sector == SECT_HILLS || sector == SECT_PLAINS ||
sector == SECT_HCORN || sector == SECT_HGRAIN || sector == SECT_STREE || sector == SECT_NTREE ||
sector == SECT_SCORN || sector == SECT_NCORN || sector == SECT_SGRAIN || sector == SECT_NGRAIN ||
sector == SECT_PATH || sector == SECT_STONE || sector == SECT_SSTONE || sector == SECT_NSTONE)
{
chance = 5 + (POINT_LEVEL(LEARNED(ch, gsn_forage), MASTERED(ch, gsn_forage)/2));
if (!str_cmp(argument, "quick"))
{
chance -= 15;
speed = PULSE_PER_SECOND*3;
}
else if (!str_cmp(argument, "long"))
{
chance += 15;
speed = PULSE_PER_SECOND*14;
}
if (number_range(1, 100) > chance)
{
act(AT_GREEN, "$n gets on $s knees and starts to search for water....but finds none.", ch, NULL, NULL, TO_ROOM);
act(AT_GREEN, "You get on your knees and search for water....no water here.", ch, NULL, NULL, TO_CHAR);
learn_from_failure(ch, gsn_forage, NULL);
WAIT_STATE(ch, speed);
return;
}
else
{
act(AT_GREEN, "$n gets on $s knees and fills up $p with fresh water.", ch, ofood, NULL, TO_ROOM);
act(AT_GREEN, "You get on your knees and fill up $p with fresh water.", ch, ofood, NULL, TO_CHAR);
separate_obj(ofood);
ofood->value[1] = ofood->value[0];
learn_from_success(ch, gsn_forage, NULL);
WAIT_STATE(ch, speed);
return;
}
}
else if (sector == SECT_OCEANFLOOR || sector == SECT_OCEAN || sector == SECT_UNDERWATER)
{
send_to_char("You cannot find fresh water here.\n\r", ch);
return;
}
else
{
send_to_char("You cannot forage for water here, sorry.\n\r", ch);
return;
}
}
if (!str_cmp(arg, "food"))
{
if (IN_WILDERNESS(ch) && sector == SECT_HCORN && resource_sector[ch->map][ch->coord->x][ch->coord->y] >= 3000)
{
chance = 30 + (POINT_LEVEL(LEARNED(ch, gsn_forage), MASTERED(ch, gsn_forage)/2));
if (!str_cmp(argument, "quick"))
{
chance -= 15;
speed = PULSE_PER_SECOND*3;
}
else if (!str_cmp(argument, "long"))
{
chance += 20;
speed = PULSE_PER_SECOND*14;
}
if (number_range(1, 100) > chance)
{
act(AT_GREEN, "$n gets on $s knees and starts to forage for food, but is able to find nothing.", ch, NULL, NULL, TO_ROOM);
act(AT_GREEN, "You get on your knees and start to forage for food, but you are not able to find anything.", ch, NULL, NULL, TO_CHAR);
learn_from_failure(ch, gsn_forage, NULL);
WAIT_STATE(ch, speed);
return;
}
sprintf(name, "fresh corn");
sprintf(shortd, "fresh corn");
sprintf(longd, "Someone has left behind some fresh corn for you to eat.\n\r");
fv = 3;
}
else if (sector == SECT_FIELD || sector == SECT_FOREST || sector == SECT_HILLS || sector == SECT_PLAINS
|| sector == SECT_STREE || sector == SECT_NTREE)
{
chance = 5 + (POINT_LEVEL(LEARNED(ch, gsn_forage), MASTERED(ch, gsn_forage)/2));
if (!str_cmp(argument, "quick"))
{
chance -= 15;
speed = PULSE_PER_SECOND*3;
}
else if (!str_cmp(argument, "long"))
{
chance += 15;
speed = PULSE_PER_SECOND*14;
}
if (number_range(1, 100) > chance)
{
act(AT_GREEN, "$n gets on $s knees and starts to forage for food, but is able to find nothing.", ch, NULL, NULL, TO_ROOM);
act(AT_GREEN, "You get on your knees and start to forage for food, but you are not able to find anything.", ch, NULL, NULL, TO_CHAR);
learn_from_failure(ch, gsn_forage, NULL);
WAIT_STATE(ch, speed);
return;
}
food = number_range(1, 10);
if (food == 1)
{
sprintf(name, "barries");
sprintf(shortd, "barries");
sprintf(longd, "Someone has left behind some edible barries for you to eat.\n\r");
fv = 3;
}
if (food == 2)
{
sprintf(name, "roots");
sprintf(shortd, "roots");
sprintf(longd, "Someone has left behind some tasty looking roots to eat.\n\r");
fv = 2;
}
if (food == 3)
{
sprintf(name, "non-poisonous mushrooms");
sprintf(shortd, "non-poionous mushrooms");
sprintf(longd, "Someone has left behind some non-poisonous mushrooms for you to eat.\n\r");
fv = 3;
}
if (food == 4)
{
sprintf(name, "fresh grubs");
sprintf(shortd, "fresh grubs");
sprintf(longd, "Some ever so tasteful fresh grubs has been left here for all to enjoy.\n\r");
fv = 2;
}
if (food == 5)
{
sprintf(name, "deer meat");
sprintf(shortd, "left over deer meat");
sprintf(longd, "Someone has left behind some left over deet meat for you to enjoy.\n\r");
fv = 5;
}
if (food == 6)
{
sprintf(name, "small apples");
sprintf(shortd, "small apples");
sprintf(longd, "Someone has left behind a small assortment of apples for you to enjoy.\n\r");
fv = 3;
}
if (food == 7)
{
sprintf(name, "fresh grapes");
sprintf(shortd, "some frash grapes");
sprintf(longd, "Someone has left behind a small pile of fresh grapes for you to enjoy.\n\r");
fv = 3;
}
if (food == 8)
{
sprintf(name, "honey");
sprintf(shortd, "fresh honey");
sprintf(longd, "Someone has left behind a small batch of fresh honey, how delightful!\n\r");
fv = 3;
}
if (food == 9)
{
sprintf(name, "eggs");
sprintf(shortd, "mystery eggs");
sprintf(longd, "Someone has left behind some eggs, eggs of what, who knows.\n\r");
fv = 3;
}
if (food == 10)
{
sprintf(name, "assorted fresh weeds");
sprintf(shortd, "assorted fresh weeds");
sprintf(longd, "Someone has left behind an assortment of fresh, edible weeds\n\r");
fv = 3;
}
}
else
{
send_to_char("You cannot forage here, sorry.\n\r", ch);
return;
}
ofood = create_object(get_obj_index(OBJ_VNUM_MUSHROOM), 1);
STRFREE(ofood->name);
STRFREE(ofood->short_descr);
STRFREE(ofood->description);
ofood->name = STRALLOC(name);
ofood->short_descr = STRALLOC(shortd);
ofood->description = STRALLOC(longd);
ofood->value[0] = fv;
if (get_ch_carry_number(ch) + (get_obj_number(ofood) / ofood->count) > can_carry_n(ch))
{
obj_to_room(ofood, ch->in_room, ch);
sprintf(name, "Your hands are full, just going to have to leave it on the ground.\n\r");
}
else if (get_ch_carry_weight(ch) + (get_obj_weight(ofood) / ofood->count) > can_carry_w(ch))
{
obj_to_room(ofood, ch->in_room, ch);
sprintf(name, "You cannot carry the extra weight, leaving it on the ground.\n\r");
}
else
{
obj_to_char(ofood, ch);
strcpy(name, "");
}
act(AT_GREEN, "$n gets on $s knees and starts to forage for food .... and finds $p", ch, ofood, NULL, TO_ROOM);
act(AT_GREEN, "You get on your knees and start to forage for food .... and you find $p", ch, ofood, NULL, TO_CHAR);
send_to_char(name, ch);
WAIT_STATE(ch, speed);
return;
}
else
{
do_forage(ch, "");
return;
}
}
void do_cutpurse(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
int percent;
sh_int mastery, m;
sh_int level;
int amount;
mastery = MASTERED(ch, gsn_cutpurse);
level = POINT_LEVEL(LEARNED(ch, gsn_cutpurse), MASTERED(ch, gsn_cutpurse));
if (ch->mount)
{
send_to_char("You can't do that while mounted.\n\r", ch);
return;
}
if (argument[0] == '\0')
{
send_to_char("Attempt a cutpurse on whom?\n\r", ch);
return;
}
if (ms_find_obj(ch))
return;
if ((victim = get_char_room_new(ch, argument, 1)) == NULL)
{
send_to_char("They aren't here.\n\r", ch);
return;
}
if (victim == ch)
{
send_to_char("That's pointless.\n\r", ch);
return;
}
if (is_safe(ch, victim))
{
set_char_color(AT_MAGIC, ch);
send_to_char("A magical force interrupts you.\n\r", ch);
return;
}
if (IS_IMMORTAL(victim))
{
send_to_char("You cannot steal from immortals.\n\r", ch);
bug("%s tried to steal from an immortal", ch->name);
return;
}
if (xIS_SET(victim->act, ACT_PACIFIST)) /* Gorog */
{
send_to_char("They are a pacifist - Shame on you!\n\r", ch);
return;
}
if (wielding_skill_weapon(ch, 0) != 7)
{
send_to_char("You can only cutpurse if you are wielding a dagger like weapon.\n\r", ch);
return;
}
if (!ch->fighting)
WAIT_STATE(ch, skill_table[gsn_cutpurse]->beats*2);
else
ch->fight_timer = get_btimer(ch, gsn_cutpurse, NULL);
percent = 20+(level/2) + (IS_AWAKE(victim) ? 0 : 50) + UMIN(10, ((get_curr_lck(ch)-14)/2) + ((get_curr_dex(ch)-14)/2));
if (mastery < 3 && ch->position != POS_STANDING)
percent = 0;
else
{
if (ch->position == POS_BERSERK || ch->position == POS_AGGRESSIVE || ch->position == POS_FIGHTING
|| ch->position == POS_DEFENSIVE || ch->position == POS_EVASIVE)
{
if (mastery < 4)
percent /= 2;
}
else
percent = 0;
}
if (percent > 0)
{
if (mastery == 3)
percent+=5;
if (mastery == 4)
percent+=10;
}
if (!IS_NPC(victim) && check_room_pk(ch) < 2)
{
send_to_char("You can only steal coins from players in noloot zones or higher.\n\r", ch);
return;
}
if (!can_see(victim, ch))
percent+=20;
percent = UMIN(95, percent);
if (level < number_range(1, 100))
{
/*
* Failure.
*/
send_to_char("Oops...\n\r", ch);
learn_from_failure(ch, gsn_cutpurse, victim);
affect_strip(ch, gsn_invis);
affect_strip(ch, gsn_mass_invis);
affect_strip(ch, gsn_sneak);
affect_strip(ch, gsn_stalk);
xREMOVE_BIT(ch->affected_by, AFF_HIDE);
xREMOVE_BIT(ch->affected_by, AFF_INVISIBLE);
xREMOVE_BIT(ch->affected_by, AFF_SNEAK);
xREMOVE_BIT(ch->affected_by, AFF_STALK);
m = 25+(mastery*10);
if (number_range(1, 100) > m)
{
act(AT_ACTION, "$n tried to steal money from you!", ch, NULL, victim, TO_VICT);
act(AT_ACTION, "$n tried to steal money from $N.", ch, NULL, victim, TO_NOTVICT);
if (!IS_NPC(victim))
{
if (legal_loot_coins(ch, victim))
{
set_thief(ch, victim);
}
}
else
global_retcode = one_hit(victim, ch, TYPE_UNDEFINED, LM_BODY);
}
return;
}
if (IS_NPC(ch))
{
amount = (int) (victim->gold * number_range(12, 16) / 100);
}
else
{
if (mastery == 4)
amount = (int) (victim->gold * number_range(20, 25) / 100);
else if (mastery == 3)
amount = (int) (victim->gold * number_range(15, 20) / 100);
else if (mastery == 2)
amount = (int) (victim->gold * number_range(12, 16) / 100);
else
amount = (int) (victim->gold * number_range(8, 13) / 100);
}
if (amount <= 0)
{
send_to_char("You couldn't get any gold.\n\r", ch);
learn_from_failure(ch, gsn_cutpurse, victim);
return;
}
ch->gold += amount;
victim->gold -= amount;
ch_printf(ch, "Aha! You got %d gold coins.\n\r", amount);
learn_from_success(ch, gsn_cutpurse, victim);
return;
}
void do_grab(CHAR_DATA *ch, char *argument)
{
char arg1[MIL];
char arg2[MIL];
CHAR_DATA *victim;
OBJ_DATA *obj;
int percent;
sh_int mastery;
sh_int level;
mastery = MASTERED(ch, gsn_grab);
level = POINT_LEVEL(LEARNED(ch, gsn_grab), MASTERED(ch, gsn_grab));
argument = one_argument(argument, arg1);
argument = one_argument(argument, arg2);
if (ch->mount)
{
send_to_char("You can't do that while mounted.\n\r", ch);
return;
}
if (arg1[0] == '\0' || arg2[0] == '\0')
{
send_to_char("Grab what from whom?\n\r", ch);
return;
}
if (ms_find_obj(ch))
return;
if ((victim = get_char_room_new(ch, arg2, 1)) == NULL)
{
send_to_char("They aren't here.\n\r", ch);
return;
}
if (victim == ch)
{
send_to_char("That's pointless.\n\r", ch);
return;
}
if (is_safe(ch, victim))
{
set_char_color(AT_MAGIC, ch);
send_to_char("A magical force interrupts you.\n\r", ch);
return;
}
if (IS_IMMORTAL(victim))
{
send_to_char("You cannot steal from immortals.\n\r", ch);
bug("%s tried to steal from an immortal", ch->name);
return;
}
if (xIS_SET(victim->act, ACT_PACIFIST)) /* Gorog */
{
send_to_char("They are a pacifist - Shame on you!\n\r", ch);
return;
}
if (ch->position != POS_STANDING)
{
send_to_char("You can only grab an item if you are standing.\n\r", ch);
return;
}
if (can_see(victim, ch))
{
send_to_char("This will only work if the target cannot see you.\n\r", ch);
return;
}
if (!IS_NPC(victim) && check_room_pk(ch) < 4)
{
send_to_char("You can only steal items from players in fulloot zones or higher.\n\r", ch);
return;
}
if (xIS_SET(victim->act, ACT_GRABBED))
{
send_to_char("Your target has already had an attempt made, he/she will not fall for it again.\n\r", ch);
return;
}
if ((obj = get_obj_wear(victim, arg1)) == NULL)
{
send_to_char("You can't seem to find the object in question.\n\r", ch);
return;
}
if (!ch->fighting)
WAIT_STATE(ch, skill_table[gsn_steal]->beats*2);
else
ch->fight_timer = get_btimer(ch, gsn_steal, NULL);
percent = 20+(level/2) + (IS_AWAKE(victim) ? 0 : 50) + UMIN(10, ((get_curr_lck(ch)-14)/2) + ((get_curr_dex(ch)-14)/2));
if (mastery == 3)
percent+=5;
if (mastery == 4)
percent+=10;
percent = UMIN(95, percent);
if (level < number_range(1, 100))
{
/*
* Failure.
*/
send_to_char("Oops...\n\r", ch);
learn_from_failure(ch, gsn_grab, victim);
affect_strip(ch, gsn_invis);
affect_strip(ch, gsn_mass_invis);
affect_strip(ch, gsn_sneak);
affect_strip(ch, gsn_stalk);
xREMOVE_BIT(ch->affected_by, AFF_HIDE);
xREMOVE_BIT(ch->affected_by, AFF_INVISIBLE);
xREMOVE_BIT(ch->affected_by, AFF_SNEAK);
xREMOVE_BIT(ch->affected_by, AFF_STALK);
if (IS_NPC(victim))
xSET_BIT(victim->act, ACT_GRABBED);
act(AT_ACTION, "$n tried to grab $p from you!", ch, obj, victim, TO_VICT);
act(AT_ACTION, "$n tried to grab $p from $N.", ch, obj, victim, TO_NOTVICT);
if (!IS_NPC(victim))
{
if (legal_loot(ch, victim))
{
set_thief(ch, victim);
}
}
else
{
global_retcode = one_hit(victim, ch, TYPE_UNDEFINED, LM_BODY);
}
return;
}
if (!can_drop_obj(ch, obj) || IS_OBJ_STAT(obj, ITEM_INVENTORY) || IS_OBJ_STAT(obj, ITEM_PROTOTYPE) || obj->level > ch->level)
{
send_to_char("You can't manage to pry it away.\n\r", ch);
return;
}
if (IS_OBJ_STAT(obj, ITEM_NOGIVE))
{
send_to_char("You cannot grab an item that is nogive, sorry.\n\r", ch);
return;
}
if (IS_UNIQUE(ch, obj))
{
send_to_char("You already have one, cannot grab another.\n\r", ch);
return;
}
if (get_ch_carry_number(ch) + (get_obj_number(obj) / obj->count) > can_carry_n(ch))
{
send_to_char("You have your hands full.\n\r", ch);
return;
}
if (get_ch_carry_weight(ch) + (get_obj_weight(obj) / obj->count) > can_carry_w(ch))
{
send_to_char("You can't carry that much weight.\n\r", ch);
return;
}
separate_obj(obj);
unequip_char(victim, obj);
obj_from_char(obj);
obj_to_char(obj, ch);
learn_from_success(ch, gsn_grab, victim);
adjust_favor(ch, 9, 1);
affect_strip(ch, gsn_invis);
affect_strip(ch, gsn_mass_invis);
affect_strip(ch, gsn_sneak);
affect_strip(ch, gsn_stalk);
xREMOVE_BIT(ch->affected_by, AFF_HIDE);
xREMOVE_BIT(ch->affected_by, AFF_INVISIBLE);
xREMOVE_BIT(ch->affected_by, AFF_SNEAK);
xREMOVE_BIT(ch->affected_by, AFF_STALK);
act(AT_ACTION, "You grab $p from $N.", ch, obj, victim, TO_CHAR);
act(AT_ACTION, "$n grabs $p from you!", ch, obj, victim, TO_VICT);
act(AT_ACTION, "$n grabs $p from $N.", ch, obj, victim, TO_NOTVICT);
if (IS_NPC(victim))
xSET_BIT(victim->act, ACT_GRABBED);
if (!IS_NPC(ch))
{
if (legal_loot(ch, victim))
{
set_thief(ch, victim);
}
}
else
global_retcode = one_hit(victim, ch, TYPE_UNDEFINED, LM_BODY);
return;
}
void do_steal(CHAR_DATA * ch, char *argument)
{
char arg1[MIL];
char arg2[MIL];
CHAR_DATA *victim;
OBJ_DATA *obj;
int percent;
sh_int mastery, m;
sh_int level;
mastery = MASTERED(ch, gsn_steal);
level = POINT_LEVEL(LEARNED(ch, gsn_steal), MASTERED(ch, gsn_steal));
argument = one_argument(argument, arg1);
argument = one_argument(argument, arg2);
if (ch->mount)
{
send_to_char("You can't do that while mounted.\n\r", ch);
return;
}
if (arg1[0] == '\0' || arg2[0] == '\0')
{
send_to_char("Steal what from whom?\n\r", ch);
return;
}
if (ms_find_obj(ch))
return;
if ((victim = get_char_room_new(ch, arg2, 1)) == NULL)
{
send_to_char("They aren't here.\n\r", ch);
return;
}
if (victim == ch)
{
send_to_char("That's pointless.\n\r", ch);
return;
}
if (is_safe(ch, victim))
{
set_char_color(AT_MAGIC, ch);
send_to_char("A magical force interrupts you.\n\r", ch);
return;
}
if (IS_IMMORTAL(victim))
{
send_to_char("You cannot steal from immortals.\n\r", ch);
bug("%s tried to steal from an immortal", ch->name);
return;
}
/* Disabled stealing among players because of complaints naked avatars were
running around stealing eq from equipped pkillers. -- Narn
*/
/* if ( check_illegal_psteal( ch, victim ) )
{
send_to_char( "You can't steal from that player.\n\r", ch );
return;
}
*/
/* if (!IS_NPC(ch) && !IS_NPC(victim))
{
set_char_color(AT_IMMORT, ch);
send_to_char("The gods forbid theft between players.\n\r", ch);
return;
} */
if (xIS_SET(victim->act, ACT_PACIFIST)) /* Gorog */
{
send_to_char("They are a pacifist - Shame on you!\n\r", ch);
return;
}
if (!ch->fighting)
WAIT_STATE(ch, skill_table[gsn_steal]->beats*2);
else
ch->fight_timer = get_btimer(ch, gsn_steal, NULL);
percent = 25+(level*2/3) + (IS_AWAKE(victim) ? 0 : 50) + UMIN(10, ((get_curr_lck(ch)-14)/2) + ((get_curr_dex(ch)-14)/2));
if (mastery < 3 && ch->position != POS_STANDING)
percent = 0;
else
{
if (ch->position == POS_BERSERK || ch->position == POS_AGGRESSIVE || ch->position == POS_FIGHTING
|| ch->position == POS_DEFENSIVE || ch->position == POS_EVASIVE)
{
if (mastery < 4)
percent /= 2;
}
else
percent = 0;
}
if (percent > 0)
{
if (mastery == 3)
percent+=10;
if (mastery == 4)
percent+=20;
}
if (!can_see(victim, ch))
percent+=30;
if (str_cmp(arg1, "coin") && str_cmp(arg1, "coins") && str_cmp(arg1, "gold"))
{
percent/=2;
if (check_room_pk(ch) < 4 && !IS_NPC(victim))
{
send_to_char("You can only steal items from players in fulloot zones or higher.\n\r", ch);
return;
}
}
else
{
if (check_room_pk(ch) < 2 && !IS_NPC(victim))
{
send_to_char("You can only steal coins from players in noloot zones or higher.\n\r", ch);
return;
}
}
percent = UMIN(95, percent);
if (level < number_range(1, 100))
{
/*
* Failure.
*/
send_to_char("Oops...\n\r", ch);
learn_from_failure(ch, gsn_steal, victim);
affect_strip(ch, gsn_invis);
affect_strip(ch, gsn_mass_invis);
affect_strip(ch, gsn_sneak);
affect_strip(ch, gsn_stalk);
xREMOVE_BIT(ch->affected_by, AFF_HIDE);
xREMOVE_BIT(ch->affected_by, AFF_INVISIBLE);
xREMOVE_BIT(ch->affected_by, AFF_SNEAK);
xREMOVE_BIT(ch->affected_by, AFF_STALK);
m = 35+(mastery*15);
if (number_range(1, 100) > m)
{
act(AT_ACTION, "$n tried to steal from you!", ch, NULL, victim, TO_VICT);
act(AT_ACTION, "$n tried to steal from $N.", ch, NULL, victim, TO_NOTVICT);
if (!IS_NPC(victim))
{
if (legal_loot_coins(ch, victim))
{
set_thief(ch, victim);
}
}
else
global_retcode = one_hit(victim, ch, TYPE_UNDEFINED, LM_BODY);
}
return;
}
if (!str_cmp(arg1, "coin") || !str_cmp(arg1, "coins") || !str_cmp(arg1, "gold"))
{
int amount;
if (IS_NPC(ch))
{
amount = (int) (victim->gold * number_range(1, 7) / 100);
}
else
{
if (mastery == 4)
amount = (int) (victim->gold * number_range(3, 13) / 100);
else if (mastery == 3)
amount = (int) (victim->gold * number_range(1, 10) / 100);
else if (mastery == 2)
amount = (int) (victim->gold * number_range(1, 7) / 100);
else
amount = (int) (victim->gold * number_range(1, 5) / 100);
}
if (amount <= 0)
{
send_to_char("You couldn't get any gold.\n\r", ch);
learn_from_failure(ch, gsn_steal, victim);
return;
}
ch->gold += amount;
victim->gold -= amount;
ch_printf(ch, "Aha! You got %d gold coins.\n\r", amount);
learn_from_success(ch, gsn_steal, victim);
return;
}
if ((obj = get_obj_carry(victim, arg1)) == NULL)
{
send_to_char("You can't seem to find it.\n\r", ch);
return;
}
if (!can_drop_obj(ch, obj) || IS_OBJ_STAT(obj, ITEM_INVENTORY) || IS_OBJ_STAT(obj, ITEM_PROTOTYPE) || obj->level > ch->level)
{
send_to_char("You can't manage to pry it away.\n\r", ch);
return;
}
if (IS_OBJ_STAT(obj, ITEM_NOGIVE))
{
send_to_char("You cannot steal an item that is nogive, sorry.\n\r", ch);
return;
}
if (IS_UNIQUE(ch, obj))
{
send_to_char("You already have one, cannot steal another.\n\r", ch);
return;
}
if (get_ch_carry_number(ch) + (get_obj_number(obj) / obj->count) > can_carry_n(ch))
{
send_to_char("You have your hands full.\n\r", ch);
return;
}
if (get_ch_carry_weight(ch) + (get_obj_weight(obj) / obj->count) > can_carry_w(ch))
{
send_to_char("You can't carry that much weight.\n\r", ch);
return;
}
separate_obj(obj);
obj_from_char(obj);
obj_to_char(obj, ch);
if (!can_see(victim, ch))
level += 60;
if (number_range(1, 100) > level/2)
{
act(AT_ACTION, "You steal $p from $N. It appears $N might of noticed", ch, obj, victim, TO_CHAR);
act(AT_ACTION, "You feel like you are missing something.....", ch, obj, victim, TO_VICT);
}
else
{
act(AT_ACTION, "You steal $p from $N. It appears $N did not notice it.", ch, obj, victim, TO_CHAR);
}
learn_from_success(ch, gsn_steal, victim);
adjust_favor(ch, 9, 1);
return;
}
void do_assassinate(CHAR_DATA *ch, char *argument)
{
char arg[MIL];
CHAR_DATA *victim;
OBJ_DATA *obj;
int percent;
sh_int mastery;
int level;
mastery = MASTERED(ch, gsn_assassinate);
level = POINT_LEVEL(LEARNED(ch, gsn_assassinate), MASTERED(ch, gsn_assassinate));
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't do that right now.\n\r", ch);
return;
}
one_argument(argument, arg);
if (ch->mount)
{
send_to_char("You can't get close enough while mounted.\n\r", ch);
return;
}
if (arg[0] == '\0')
{
send_to_char("Assassinate whom?\n\r", ch);
return;
}
if ((victim = get_char_room_new(ch, arg, 1)) == NULL)
{
send_to_char("They aren't here.\n\r", ch);
return;
}
if (victim == ch)
{
send_to_char("How can you sneak up on yourself?\n\r", ch);
return;
}
if (is_safe(ch, victim))
return;
if (wielding_skill_weapon(ch, 0) != 7)
{
send_to_char("You can only assassinate with a dagger.\n\r", ch);
return;
}
if ((obj = get_eq_char(ch, WEAR_WIELD)) == NULL)
{
send_to_char("You are not wielding a weapon.\n\r", ch);
return;
}
if (victim->fighting)
{
send_to_char("You can't assassinate someone who is in combat.\n\r", ch);
return;
}
/* Can backstab a char even if it's hurt as long as it's sleeping. -Narn */
if (victim->hit < victim->max_hit && IS_AWAKE(victim))
{
act(AT_PLAIN, "$N is hurt and suspicious ... you can't sneak up.", ch, NULL, victim, TO_CHAR);
return;
}
percent = 5 + (level/3) + UMIN(10, ((get_curr_dex(ch)-14)/2) + ((get_curr_lck(ch)-14)/2));
if (can_see(victim, ch))
percent /= 3;
percent -= (victim->max_hit - ch->max_hit) / 30;
if (victim->max_hit >= 5000)
percent = 0;
else
percent = URANGE(5, percent, 95);
check_attacker(ch, victim);
if (!IS_AWAKE(victim) || number_range(1, 100) <= percent)
{
learn_from_success(ch, gsn_assassinate, victim);
act(AT_RED, "You slide behind $N and in a quick motion to slit $S throat. Blood pours EVERYWHERE!", ch, NULL, victim, TO_CHAR);
act(AT_RED, "$n slides behind you and in a quick motion slitting your throat.", ch, NULL, victim, TO_VICT);
act(AT_RED, "$n slides behind $N and in a quick motion to slit $S throat. Blood pours EVERYWHERE!", ch, NULL, victim, TO_NOTVICT);
damage(ch, victim, 50, TYPE_HIT, DM_DEATH, LM_NECK);
}
else
{
act(AT_RED, "You slide behind $N and in a quick motion to slit $S throat, but you fail", ch, NULL, victim, TO_CHAR);
act(AT_RED, "$n slides behind you and in a quick motion to slit your throat, but fails.", ch, NULL, victim, TO_VICT);
act(AT_RED, "$n slides behind $N and in a quick motion to slit $S throat, but fails.", ch, NULL, victim, TO_NOTVICT);
learn_from_failure(ch, gsn_assassinate, victim);
one_hit(ch, victim, TYPE_HIT, LM_BODY);
}
return;
}
void do_backstab(CHAR_DATA * ch, char *argument)
{
char arg[MIL];
CHAR_DATA *victim;
OBJ_DATA *obj;
int percent;
sh_int mastery;
int level;
mastery = MASTERED(ch, gsn_backstab);
level = POINT_LEVEL(LEARNED(ch, gsn_backstab), MASTERED(ch, gsn_backstab));
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't do that right now.\n\r", ch);
return;
}
one_argument(argument, arg);
if (ch->mount)
{
send_to_char("You can't get close enough while mounted.\n\r", ch);
return;
}
if (arg[0] == '\0')
{
send_to_char("Backstab whom?\n\r", ch);
return;
}
if ((victim = get_char_room_new(ch, arg, 1)) == NULL)
{
send_to_char("They aren't here.\n\r", ch);
return;
}
if (victim == ch)
{
send_to_char("How can you sneak up on yourself?\n\r", ch);
return;
}
if (is_safe(ch, victim))
return;
if (wielding_skill_weapon(ch, 0) != 7)
{
send_to_char("You can only backstab with a dagger.\n\r", ch);
return;
}
if (ch->grip != GRIP_STAB)
{
send_to_char("You can only use backstab if you are gripping your dagger for a stab strike.\n\r", ch);
return;
}
if ((obj = get_eq_char(ch, WEAR_WIELD)) == NULL)
{
send_to_char("You are not wielding a weapon.\n\r", ch);
return;
}
if (victim->fighting)
{
send_to_char("You can't backstab someone who is in combat.\n\r", ch);
return;
}
/* Can backstab a char even if it's hurt as long as it's sleeping. -Narn */
if (victim->hit < victim->max_hit && IS_AWAKE(victim))
{
act(AT_PLAIN, "$N is hurt and suspicious ... you can't sneak up.", ch, NULL, victim, TO_CHAR);
return;
}
percent = 40 + (level/2) + UMIN(10, (14-get_curr_dex(ch)) + (14-get_curr_lck(ch)));
if (!can_see(victim, ch))
percent+=30;
if (mastery == 4)
percent=95;
percent = UMIN(95, percent);
check_attacker(ch, victim);
if (!IS_AWAKE(victim) || number_range(1, 100) <= percent)
{
learn_from_success(ch, gsn_backstab, victim);
global_retcode = one_hit(ch, victim, gsn_backstab, LM_BODY);
adjust_favor(ch, 10, 1);
check_illegal_pk(ch, victim);
}
else
{
learn_from_failure(ch, gsn_backstab, victim);
global_retcode = damage(ch, victim, 0, gsn_backstab, 0, LM_BODY);
ch->fight_timer = get_btimer(ch, -1, NULL);
}
return;
}
void do_rescue(CHAR_DATA * ch, char *argument)
{
char arg[MIL];
CHAR_DATA *victim;
CHAR_DATA *fch;
int percent;
int level;
int adiff = 0;
int aggroc, aggrov;
AGGRO_DATA *aggro;
aggroc = aggrov = -1;
level = POINT_LEVEL(LEARNED(ch, gsn_rescue), MASTERED(ch, gsn_rescue));
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't concentrate enough for that.\n\r", ch);
return;
}
if (IS_AFFECTED(ch, AFF_BERSERK))
{
send_to_char("You aren't thinking clearly...\n\r", ch);
return;
}
one_argument(argument, arg);
if (arg[0] == '\0')
{
send_to_char("Rescue whom?\n\r", ch);
return;
}
if ((victim = get_char_room_new(ch, arg, 1)) == NULL)
{
send_to_char("They aren't here.\n\r", ch);
return;
}
if (victim == ch)
{
send_to_char("How about fleeing instead?\n\r", ch);
return;
}
if (ch->mount)
{
send_to_char("You can't do that while mounted.\n\r", ch);
return;
}
if (!IS_NPC(ch) && IS_NPC(victim))
{
send_to_char("They don't need your help!\n\r", ch);
return;
}
if (!ch->fighting)
{
send_to_char("Too late...\n\r", ch);
return;
}
if ((fch = who_fighting(victim)) == NULL)
{
send_to_char("They are not fighting right now.\n\r", ch);
return;
}
if (who_fighting(victim) == ch)
{
send_to_char("Just running away would be better...\n\r", ch);
return;
}
if (IS_AFFECTED(victim, AFF_BERSERK))
{
send_to_char("Stepping in front of a berserker would not be an intelligent decision.\n\r", ch);
return;
}
if (HAS_WAIT(ch))
{
send_to_char("You are too busy in battle to do that.\n\r", ch);
return;
}
if (IS_NPC(victim->fighting->who))
{
for (aggro = victim->fighting->who->first_aggro; aggro; aggro = aggro->next)
{
if (aggro->ch == victim)
aggrov = aggro->value;
if (aggro->ch == ch)
aggroc = aggro->value;
}
adiff = URANGE(-20, (aggrov - aggroc)/3, 30);
}
percent = 10 + URANGE(-3, (get_curr_lck(ch) - 14)/2, 3) + URANGE(-3, (get_curr_lck(victim) - 14)/2, 3);
percent += URANGE(1, level/3, 25);
percent -= adiff;
percent = URANGE(5, percent, 70);
if (!ch->fighting)
WAIT_STATE(ch, skill_table[gsn_rescue]->beats*2);
else
ch->fight_timer = get_btimer(ch, gsn_rescue, NULL);
if (number_range(1, 100) > percent)
{
send_to_char("You fail the rescue.\n\r", ch);
act(AT_SKILL, "$n tries to rescue you!", ch, NULL, victim, TO_VICT);
act(AT_SKILL, "$n tries to rescue $N!", ch, NULL, victim, TO_NOTVICT);
learn_from_failure(ch, gsn_rescue, victim);
return;
}
act(AT_SKILL, "You rescue $N!", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n rescues you!", ch, NULL, victim, TO_VICT);
act(AT_SKILL, "$n moves in front of $N!", ch, NULL, victim, TO_NOTVICT);
learn_from_success(ch, gsn_rescue, victim);
adjust_favor(ch, 8, 1);
if (aggrov > aggroc)
{
for (aggro = victim->fighting->who->first_aggro; aggro; aggro = aggro->next)
{
if (aggro->ch == ch)
aggro->value = aggrov+1;
}
}
stop_fighting(fch, FALSE);
stop_fighting(victim, FALSE);
if (ch->fighting)
stop_fighting(ch, FALSE);
set_fighting(ch, fch);
set_fighting(fch, ch);
return;
}
//Take up less space, put all the normal checks in here -- Xerves
int check_battle_skills(CHAR_DATA *ch, CHAR_DATA *victim, sh_int usgn)
{
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't concentrate enough for that.\n\r", ch);
return 0;
}
if (IS_NPC(ch) || ch->pcdata->ranking[usgn] <= 0)
{
send_to_char("You better leave the martial arts to those who have the knowledge.\n\r", ch);
return 0;
}
if (HAS_WAIT(ch))
{
send_to_char("You are too busy in battle to do that.\n\r", ch);
return 0;
}
return 1;
}
int get_limb_location args((int limb));
//Similar to one_hit, checks to make sure you hit, adds bonuses
int check_combat_hit(CHAR_DATA *ch, CHAR_DATA *victim, int dam, int at, int wear, int usgn)
{
sh_int victim_ac = 0;
sh_int armor_ac = 0;
sh_int weapon_ac = 0;
int block = 0;
sh_int tohit, mastery, hnum, percent, holder;
OBJ_DATA *eq;
OBJ_DATA *wield;
OBJ_DATA *damobj;
sh_int dameq;
int miss = 0;
int counter = 0;
sh_int mry, pv, tol, lvl;
int suc = 0;
int limb;
OBJ_DATA *shield;
int cond;
int noarmor = 0;
holder = -1;
mry = MASTERED(ch, usgn);
pv = LEARNED(ch, usgn);
lvl = POINT_LEVEL(pv, mry);
tol = 2+lvl/6;
blockdam = 0;
if (wear == WEAR_HEAD)
limb = LM_HEAD;
else if (wear == WEAR_NECK)
limb = LM_NECK;
else if (wear == WEAR_ARM_R)
limb = LM_RARM;
else if (wear == WEAR_ARM_L)
limb = LM_LARM;
else if (wear == WEAR_LEG_R)
limb = LM_RLEG;
else if (wear == WEAR_LEG_L)
limb = LM_LLEG;
else
limb = LM_BODY;
if ((eq = get_eq_char(victim, wear)) == NULL)
{
if (IS_NPC(victim))
{
armor_ac = victim->armor;
weapon_ac += tol;
if (victim->armor == 0)
noarmor = 1;
if (wear == WEAR_HEAD)
armor_ac += 2;
else if (wear == WEAR_NECK)
armor_ac += 3;
}
else
armor_ac = 0;
}
else
{
if (at == GRIP_BASH)
{
armor_ac = eq->value[0];
weapon_ac += tol;
}
else if (at == GRIP_STAB)
{
armor_ac = eq->value[2];
weapon_ac += tol;
}
else if (at == GRIP_SLASH)
{
armor_ac = eq->value[1];
weapon_ac += tol;
}
}
if (armor_ac == 0)
noarmor = 1;
if (eq)
cond = eq->value[3];
else
cond = 1000*victim->hit/victim->max_hit;
if ((wield = get_eq_char(ch, WEAR_WIELD)) != NULL)
{
if (IS_OBJ_STAT(wield, ITEM_MONKWEAPON))
{
if (at == GRIP_BASH)
weapon_ac += wield->value[7];
if (at == GRIP_SLASH)
weapon_ac += wield->value[8];
if (at == GRIP_STAB)
weapon_ac += wield->value[9];
}
}
if (armor_ac > 0)
{
armor_ac -= (3 -(cond / 251));
if (armor_ac < 1)
armor_ac = 1;
}
victim_ac = armor_ac - weapon_ac; //negative is a better to hit //negative is a better to hit
/* if you can't see what's coming... */
if (!can_see(ch, victim))
victim_ac += 1;
if (!can_see(victim, ch))
victim_ac -= 1;
tohit = get_hit_or_miss(ch, victim, victim_ac, at, limb, noarmor, NULL, -1);
if ((shield = get_eq_char(victim, WEAR_SHIELD)) != NULL && IS_AWAKE(victim))
{
int spoints = POINT_LEVEL(GET_POINTS(victim, gsn_shieldblock, 0, 1), GET_MASTERY(victim, gsn_shieldblock, 0, 1));
if (spoints > 0 && number_range(1, 100) <= UMIN(95, (UMIN(15, URANGE(-20, victim->apply_shield, 20)/2))+ shield->value[2]+ (spoints/4)))
{
learn_from_success(victim, gsn_shieldblock, NULL);
block = 1;
}
else
{
if (spoints > 0)
learn_from_failure(victim, gsn_shieldblock, NULL);
}
}
else if (victim->apply_shield > 0)
{
if (number_range(1, 100) <= URANGE(-20, victim->apply_shield, 20))
block = 1;
}
if (tohit == DM_MISS || block) //miss or block
{
/* Miss. */
miss = 1;
}
dam += str_app[get_curr_str(ch)].todam; //Strength Bonus
if (wield)
{
if (IS_OBJ_STAT(wield, ITEM_MONKWEAPON))
{
dam += number_range(wield->value[1], wield->value[2]);
}
}
if (dam <= 3)
{
if (number_range(1, 5) == 1)
suc = 1;
}
else if (dam <= 6)
{
if (number_range(1, 3) == 1)
suc = 1;
}
else if (dam <= 10)
{
if (number_range(1, 2) == 1)
suc = 1;
}
else
{
suc = 1;
}
if (miss != 1)
{
dam -= URANGE(-6, victim->apply_stone, 6);
dam -= URANGE(-4, victim->apply_hardening, 4);
if (victim->apply_hardening > 0)
check_aff_learn(victim, "bracing", 0, ch, 1);
if (!IS_NPC(victim) && victim->pcdata->learned[gsn_krundi_style] > 0)
{
int level;
level = POINT_LEVEL(LEARNED(victim, gsn_krundi_style), MASTERED(victim, gsn_krundi_style));
level = number_range(level*3, level*4);
level += 100;
level = URANGE(100, level, 600);
dam -= level/100;
level = level % 100;
if (number_range(1, 100) <= level)
{
dam--;
}
learn_from_success(victim, gsn_krundi_style, ch);
}
dam = UMAX(1, dam);
}
//Calculated fightstyle damage
if (miss != 1 && suc)
{
dam = get_fightingstyle_dam(victim, dam, ch, 0, 1);
dam = get_fightingstyle_dam(ch, dam, victim, 1, 1);
}
else
{
dam = get_fightingstyle_dam(victim, dam, ch, 0, 0);
dam = get_fightingstyle_dam(ch, dam, victim, 1, 0);
}
if (!IS_NPC(ch) && ch->pcdata->learned[gsn_concentration] > 0)
{
int dam1, dam2, level;
level = POINT_LEVEL(LEARNED(ch, gsn_concentration), MASTERED(ch, gsn_concentration));
mastery = MASTERED(ch, gsn_concentration);
dam1 = level/15;
if (mastery == 6)
hnum = number_range(35, 30);
else if (mastery == 5)
hnum = number_range(30, 25);
else if (mastery == 4)
hnum = number_range(18, 25);
else if (mastery == 3)
hnum = number_range(10, 17);
else if (mastery == 2)
hnum = number_range(5, 10);
else
hnum = number_range(1, 5);
dam2 = (int) (dam * hnum / 150);
if (dam1 < dam2)
dam += dam1;
else
dam += dam2;
if (miss != 1 && suc)
learn_from_success(ch, gsn_concentration, victim);
}
if (!IS_NPC(ch) && ch->pcdata->learned[gsn_enhanced_damage] > 0)
{
int dam1, dam2, level;
level = POINT_LEVEL(LEARNED(ch, gsn_enhanced_damage), MASTERED(ch, gsn_enhanced_damage));
mastery = MASTERED(ch, gsn_enhanced_damage);
dam1 = level/10;
if (mastery == 6)
hnum = number_range(35, 30);
else if (mastery == 5)
hnum = number_range(30, 25);
else if (mastery == 4)
hnum = number_range(18, 25);
else if (mastery == 3)
hnum = number_range(10, 17);
else if (mastery == 2)
hnum = number_range(5, 10);
else
hnum = number_range(1, 5);
dam2 = (int) (dam * hnum / 100);
if (dam1 < dam2)
dam += dam1;
else
dam += dam2;
if (miss != 1 && suc)
learn_from_success(ch, gsn_enhanced_damage, victim);
}
if (!IS_NPC(ch) && ch->pcdata->learned[gsn_deadly_accuracy] > 0)
{
int dam1, dam2, level;
level = POINT_LEVEL(LEARNED(ch, gsn_deadly_accuracy), MASTERED(ch, gsn_deadly_accuracy));
mastery = MASTERED(ch, gsn_deadly_accuracy);
dam1 = level/15;
if (mastery == 6)
hnum = number_range(35, 30);
else if (mastery == 5)
hnum = number_range(30, 25);
else if (mastery == 4)
hnum = number_range(18, 25);
else if (mastery == 3)
hnum = number_range(10, 17);
else if (mastery == 2)
hnum = number_range(5, 10);
else
hnum = number_range(1, 5);
dam2 = (int) (dam * hnum / 150);
if (dam1 < dam2)
dam += dam1;
else
dam += dam2;
if (miss != 1 && suc)
learn_from_success(ch, gsn_deadly_accuracy, victim);
}
if (!IS_AWAKE(victim))
dam *= 2;
if (!IS_NPC(victim) && victim->pcdata->learned[gsn_counter] > 0 && victim->pcdata->ranking[gsn_counter] > 0 && !xIS_SET(victim->act, PLR_COUNTER))
{
percent = number_range(1, 10000);
mastery = MASTERED(ch, gsn_counter);
if (mastery == 6)
hnum = number_range(220, 200);
else if (mastery == 5)
hnum = number_range(180, 160);
else if (mastery == 4)
hnum = number_range(135, 150);
else if (mastery == 3)
hnum = number_range(90, 105);
else if (mastery == 2)
hnum = number_range(50, 90);
else
hnum = number_range(20, 45);
if (victim->pcdata->tier > 1)
holder = holder + 200;
if (victim->pcdata->caste > 5)
holder = holder + 100;
holder += 100 * (get_curr_dex(victim) - get_curr_dex(ch));
holder += 50 * (get_curr_lck(victim) - get_curr_lck(ch));
holder += 100 * (get_curr_str(victim) - get_curr_str(ch));
if (percent < holder)
{
counter = 1;
learn_from_success(victim, gsn_counter, ch);
}
}
if (dam <= 0)
dam = 1;
/* immune to damage */
if (dam == -1)
{
return 0;
}
if(xIS_SET(victim->act, ACT_UNDEAD))
{
if(!wield || (wield && !xIS_SET(wield->extra_flags, ITEM_BLESS) && !xIS_SET(wield->extra_flags, ITEM_SANCTIFIED)))
{
return 0;
}
if(xIS_SET(wield->extra_flags, ITEM_BLESS) && wield->bless_dur > 0)
{
if (dam)
wield->bless_dur -= 1;
if(xIS_SET(wield->extra_flags, ITEM_BLESS) && wield->bless_dur <= 0)
{
xTOGGLE_BIT(wield->extra_flags, ITEM_BLESS);
act(AT_MAGIC, "Your $p stops glowing...\n\r", ch, wield, NULL, TO_CHAR);
}
}
}
if(xIS_SET(victim->act, ACT_LIVING_DEAD))
{
if(!wield || (wield && !xIS_SET(wield->extra_flags, ITEM_BLESS) && !xIS_SET(wield->extra_flags, ITEM_SANCTIFIED)))
{
dam = dam / 2;
}
if(wield && (xIS_SET(wield->extra_flags, ITEM_BLESS) || xIS_SET(wield->extra_flags, ITEM_SANCTIFIED)))
{
dam = dam * 2;
}
if(wield && xIS_SET(wield->extra_flags, ITEM_BLESS) && wield->bless_dur > 0)
{
if (dam)
wield->bless_dur -= 1;
if(xIS_SET(wield->extra_flags, ITEM_BLESS) && wield->bless_dur <= 0)
{
xTOGGLE_BIT(wield->extra_flags, ITEM_BLESS);
act(AT_MAGIC, "Your $p stops glowing...\n\r", ch, wield, NULL, TO_CHAR);
}
}
}
/* Counter Attack Check -- Xerves 8/25/99 */
if (counter == 1)
{
damage(victim, ch, dam, TYPE_HIT, DM_COUNTER, LM_BODY);
return 0;
}
if (!block && (tohit == DM_HIT || tohit == DM_CRITICAL || tohit == DM_SLICEDLIMB))
{
/* damage eq */
dameq = get_limb_location(limb);
damobj = get_eq_char(victim, dameq);
if (damobj)
{
if (number_range(1, 100) > (50 + (get_obj_resistance(damobj, victim) * 5/2)))
{
set_cur_obj(damobj);
damage_obj(damobj, victim, 0, dam);
}
}
}
damobj = NULL;
// Weapon deteriates over time...
if (wield && (tohit == DM_HIT || tohit == DM_CRITICAL || tohit == DM_SLICEDLIMB))
{
damobj = wield;
if (damobj)
{
if (number_range(1, 100) > (40 + (get_obj_resistance(damobj, ch) * 3)))
{
set_cur_obj(damobj);
damage_obj(damobj, ch, 0, dam);
}
}
}
if (block)
{
damobj = get_eq_char(victim, WEAR_SHIELD);
if (damobj)
{
set_cur_obj(damobj);
damage_obj(damobj, ch, 0, dam);
}
}
if (tohit == DM_DEATH)
return 5000; //Critical attack
else if (block == 1)
{
blockdam = dam;
return -1;
}
else if (tohit == DM_MISS)
return 0;
else
{
if (tohit > 200)
return (tohit-100)*dam*100;
dam = dam*(tohit-100) / 100;
dam += URANGE(-15, ch->apply_sanctify, 15);
dam += URANGE(-10, ch->apply_manaburn, 10);
if (ch->apply_manaburn > 0 && skill_lookup("arrowcatch") > 0 && LEARNED(ch, skill_lookup("arrowcatch")) > 0)
learn_from_success(ch, skill_lookup("arrowcatch"), victim);
if (tohit > -300 && dam <= 0)
dam = 0;
return dam;
}
return 1;
}
CHAR_DATA *get_battle_target(CHAR_DATA *ch, char *argument)
{
CHAR_DATA *victim = NULL;
victim = who_fighting(ch);
if ((victim = get_char_room_new(ch, argument, 1)) != NULL)
return victim;
else if ((victim = who_fighting(ch)) != NULL)
return victim;
else
return NULL;
}
//Below are the 20 combat skills, enjoy -- Xerves
void do_roundhouse(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
sh_int lvl; //Point_level
sh_int mry; //Mastery
sh_int pv; //Points
sh_int usgn; //Gn of the skill
sh_int at; //Attack type
sh_int dam;
at = GRIP_SLASH;
usgn = gsn_roundhouse;
mry = MASTERED(ch, usgn);
pv = UMIN(13, LEARNED(ch, usgn));
lvl = UMIN(80, POINT_LEVEL(LEARNED(ch, usgn), MASTERED(ch, usgn)));
victim = get_battle_target(ch, argument);
if (!victim)
{
send_to_char("Your target is not here.\n\r", ch);
return;
}
if (!check_twohand_shield(ch))
return;
if (ch == victim)
{
send_to_char("Targetting yourself is not a wise idea.\n\r", ch);
return;
}
//Checks the normal stuff to see if they can attack
if (check_battle_skills(ch, victim, usgn) == 0)
return;
ch->fight_timer += get_btimer(ch, usgn, NULL);
if (can_use_skill(ch, number_percent()-((mry-1)*10), usgn))
{
learn_from_success(ch, usgn, victim);
dam = pv;
dam = check_combat_hit(ch, victim, dam, at, WEAR_HEAD, usgn);
if (dam == 5000)
global_retcode = damage(ch, victim, 50, usgn, DM_DEATH, LM_HEAD);
else if (dam == -1)
global_retcode = damage(ch, victim, dam, usgn, DM_BLOCK, LM_HEAD);
else if (dam == 0)
global_retcode = damage(ch, victim, 0, usgn, DM_MISS, LM_HEAD);
else if (dam <= -2)
global_retcode = damage(ch, victim, dam*-1, usgn, DM_SLICEDLIMB, LM_HEAD);
else if (dam >= 20000)
global_retcode = damage(ch, victim, dam/10000, usgn, DM_CRITICAL, LM_HEAD);
else
global_retcode = damage(ch, victim, dam, usgn, 0, LM_HEAD);
}
else
{
learn_from_failure(ch, usgn, victim);
global_retcode = damage(ch, victim, 0, usgn, 0, -1);
}
return;
}
void do_spinkick(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
sh_int lvl; //Point_level
sh_int mry; //Mastery
sh_int pv; //Points
sh_int usgn; //Gn of the skill
sh_int at; //Attack type
sh_int dam;
at = GRIP_SLASH;
usgn = gsn_spinkick;
mry = MASTERED(ch, usgn);
pv = UMIN(13, LEARNED(ch, usgn));
lvl = UMIN(80, POINT_LEVEL(LEARNED(ch, usgn), MASTERED(ch, usgn)));
victim = get_battle_target(ch, argument);
if (!victim)
{
send_to_char("Your target is not here.\n\r", ch);
return;
}
if (!check_twohand_shield(ch))
return;
if (ch == victim)
{
send_to_char("Targetting yourself is not a wise idea.\n\r", ch);
return;
}
//Checks the normal stuff to see if they can attack
if (check_battle_skills(ch, victim, usgn) == 0)
return;
ch->fight_timer += get_btimer(ch, usgn, NULL);
if (can_use_skill(ch, number_percent()-((mry-1)*10), usgn))
{
learn_from_success(ch, usgn, victim);
dam = 3 + lvl * 30 / 100;
dam = check_combat_hit(ch, victim, dam, at, WEAR_HEAD, usgn);
if (dam == 5000)
global_retcode = damage(ch, victim, 50, usgn, DM_DEATH, LM_HEAD);
else if (dam == -1)
global_retcode = damage(ch, victim, dam, usgn, DM_BLOCK, LM_HEAD);
else if (dam == 0)
global_retcode = damage(ch, victim, 0, usgn, DM_MISS, LM_HEAD);
else if (dam <= -2)
global_retcode = damage(ch, victim, dam*-1, usgn, DM_SLICEDLIMB, LM_HEAD);
else if (dam >= 20000)
global_retcode = damage(ch, victim, dam/10000, usgn, DM_CRITICAL, LM_HEAD);
else
global_retcode = damage(ch, victim, dam, usgn, 0, LM_HEAD);
}
else
{
learn_from_failure(ch, usgn, victim);
global_retcode = damage(ch, victim, 0, usgn, 0, -1);
}
return;
}
void do_tornadokick(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
sh_int lvl; //Point_level
sh_int mry; //Mastery
sh_int pv; //Points
sh_int usgn; //Gn of the skill
sh_int at; //Attack type
sh_int dam;
at = GRIP_BASH;
usgn = gsn_tornadokick;
mry = MASTERED(ch, usgn);
pv = UMIN(13, LEARNED(ch, usgn));
lvl = UMIN(80, POINT_LEVEL(LEARNED(ch, usgn), MASTERED(ch, usgn)));
victim = get_battle_target(ch, argument);
if (!victim)
{
send_to_char("Your target is not here.\n\r", ch);
return;
}
if (!check_twohand_shield(ch))
return;
if (ch == victim)
{
send_to_char("Targetting yourself is not a wise idea.\n\r", ch);
return;
}
//Checks the normal stuff to see if they can attack
if (check_battle_skills(ch, victim, usgn) == 0)
return;
ch->fight_timer += get_btimer(ch, usgn, NULL);
if (can_use_skill(ch, number_percent()-((mry-1)*10), usgn))
{
learn_from_success(ch, usgn, victim);
dam = 5 + lvl*40/100;
dam = check_combat_hit(ch, victim, dam, at, WEAR_HEAD, usgn);
if (dam == 5000)
global_retcode = damage(ch, victim, 50, usgn, DM_DEATH, LM_HEAD);
else if (dam == -1)
global_retcode = damage(ch, victim, dam, usgn, DM_BLOCK, LM_HEAD);
else if (dam == 0)
global_retcode = damage(ch, victim, 0, usgn, DM_MISS, LM_HEAD);
else if (dam <= -2)
global_retcode = damage(ch, victim, dam*-1, usgn, DM_SLICEDLIMB, LM_HEAD);
else if (dam >= 20000)
global_retcode = damage(ch, victim, dam/10000, usgn, DM_CRITICAL, LM_HEAD);
else
global_retcode = damage(ch, victim, dam, usgn, 0, LM_HEAD);
}
else
{
learn_from_failure(ch, usgn, victim);
global_retcode = damage(ch, victim, 0, usgn, 0, -1);
}
return;
}
void do_niburo(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
sh_int lvl; //Point_level
sh_int mry; //Mastery
sh_int pv; //Points
sh_int usgn; //Gn of the skill
sh_int at; //Attack type
sh_int dam;
at = GRIP_BASH;
usgn = gsn_niburo;
mry = MASTERED(ch, usgn);
pv = UMIN(13, LEARNED(ch, usgn));
lvl = UMIN(80, POINT_LEVEL(LEARNED(ch, usgn), MASTERED(ch, usgn)));
victim = get_battle_target(ch, argument);
if (!victim)
{
send_to_char("Your target is not here.\n\r", ch);
return;
}
if (!check_twohand_shield(ch))
return;
if (ch == victim)
{
send_to_char("Targetting yourself is not a wise idea.\n\r", ch);
return;
}
//Checks the normal stuff to see if they can attack
if (check_battle_skills(ch, victim, usgn) == 0)
return;
ch->fight_timer += get_btimer(ch, usgn, NULL);
if (can_use_skill(ch, number_percent()-((mry-1)*10), usgn))
{
learn_from_success(ch, usgn, victim);
dam = 7 + lvl * 55/100;
dam = check_combat_hit(ch, victim, dam, at, WEAR_HEAD, usgn);
if (dam == 5000)
global_retcode = damage(ch, victim, 50, usgn, DM_DEATH, LM_HEAD);
else if (dam == -1)
global_retcode = damage(ch, victim, dam, usgn, DM_BLOCK, LM_HEAD);
else if (dam == 0)
global_retcode = damage(ch, victim, 0, usgn, DM_MISS, LM_HEAD);
else if (dam <= -2)
global_retcode = damage(ch, victim, dam*-1, usgn, DM_SLICEDLIMB, LM_HEAD);
else if (dam >= 20000)
global_retcode = damage(ch, victim, dam/10000, usgn, DM_CRITICAL, LM_HEAD);
else
global_retcode = damage(ch, victim, dam, usgn, 0, LM_HEAD);
}
else
{
learn_from_failure(ch, usgn, victim);
global_retcode = damage(ch, victim, 0, usgn, 0, -1);
}
return;
}
void do_neckpinch(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
sh_int lvl; //Point_level
sh_int mry; //Mastery
sh_int pv; //Points
sh_int usgn; //Gn of the skill
sh_int at; //Attack type
sh_int dam;
at = GRIP_STAB;
usgn = gsn_neckpinch;
mry = MASTERED(ch, usgn);
pv = UMIN(13, LEARNED(ch, usgn));
lvl = UMIN(80, POINT_LEVEL(LEARNED(ch, usgn), MASTERED(ch, usgn)));
victim = get_battle_target(ch, argument);
if (!victim)
{
send_to_char("Your target is not here.\n\r", ch);
return;
}
if (!check_twohand_shield(ch))
return;
if (ch == victim)
{
send_to_char("Targetting yourself is not a wise idea.\n\r", ch);
return;
}
//Checks the normal stuff to see if they can attack
if (check_battle_skills(ch, victim, usgn) == 0)
return;
ch->fight_timer += get_btimer(ch, usgn, NULL);
if (can_use_skill(ch, number_percent()-((mry-1)*10), usgn))
{
learn_from_success(ch, usgn, victim);
dam = pv+1;
dam = check_combat_hit(ch, victim, dam, at, WEAR_NECK, usgn);
if (dam == 5000)
global_retcode = damage(ch, victim, 50, usgn, DM_DEATH, LM_NECK);
else if (dam == -1)
global_retcode = damage(ch, victim, dam, usgn, DM_BLOCK, LM_NECK);
else if (dam == 0)
global_retcode = damage(ch, victim, 0, usgn, DM_MISS, LM_NECK);
else if (dam <= -2)
global_retcode = damage(ch, victim, dam*-1, usgn, DM_SLICEDLIMB, LM_NECK);
else if (dam >= 20000)
global_retcode = damage(ch, victim, dam/10000, usgn, DM_CRITICAL, LM_NECK);
else
global_retcode = damage(ch, victim, dam, usgn, 0, LM_NECK);
}
else
{
learn_from_failure(ch, usgn, victim);
global_retcode = damage(ch, victim, 0, usgn, 0, -1);
}
return;
}
void do_neckchop(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
sh_int lvl; //Point_level
sh_int mry; //Mastery
sh_int pv; //Points
sh_int usgn; //Gn of the skill
sh_int at; //Attack type
sh_int dam;
at = GRIP_SLASH;
usgn = gsn_neckchop;
mry = MASTERED(ch, usgn);
pv = UMIN(13, LEARNED(ch, usgn));
lvl = UMIN(80, POINT_LEVEL(LEARNED(ch, usgn), MASTERED(ch, usgn)));
victim = get_battle_target(ch, argument);
if (!victim)
{
send_to_char("Your target is not here.\n\r", ch);
return;
}
if (!check_twohand_shield(ch))
return;
if (ch == victim)
{
send_to_char("Targetting yourself is not a wise idea.\n\r", ch);
return;
}
//Checks the normal stuff to see if they can attack
if (check_battle_skills(ch, victim, usgn) == 0)
return;
ch->fight_timer += get_btimer(ch, usgn, NULL);
if (can_use_skill(ch, number_percent()-((mry-1)*10), usgn))
{
learn_from_success(ch, usgn, victim);
dam = 3 + lvl * 35 / 100;
dam = check_combat_hit(ch, victim, dam, at, WEAR_NECK, usgn);
if (dam == 5000)
global_retcode = damage(ch, victim, 50, usgn, DM_DEATH, LM_NECK);
else if (dam == -1)
global_retcode = damage(ch, victim, dam, usgn, DM_BLOCK, LM_NECK);
else if (dam == 0)
global_retcode = damage(ch, victim, 0, usgn, DM_MISS, LM_NECK);
else if (dam <= -2)
global_retcode = damage(ch, victim, dam*-1, usgn, DM_SLICEDLIMB, LM_NECK);
else if (dam >= 20000)
global_retcode = damage(ch, victim, dam/10000, usgn, DM_CRITICAL, LM_NECK);
else
global_retcode = damage(ch, victim, dam, usgn, 0, LM_NECK);
}
else
{
learn_from_failure(ch, usgn, victim);
global_retcode = damage(ch, victim, 0, usgn, 0, -1);
}
return;
}
void do_neckrupture(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
sh_int lvl; //Point_level
sh_int mry; //Mastery
sh_int pv; //Points
sh_int usgn; //Gn of the skill
sh_int at; //Attack type
sh_int dam;
at = GRIP_STAB;
usgn = gsn_neckrupture;
mry = MASTERED(ch, usgn);
pv = UMIN(13, LEARNED(ch, usgn));
lvl = UMIN(80, POINT_LEVEL(LEARNED(ch, usgn), MASTERED(ch, usgn)));
victim = get_battle_target(ch, argument);
if (!victim)
{
send_to_char("Your target is not here.\n\r", ch);
return;
}
if (!check_twohand_shield(ch))
return;
if (ch == victim)
{
send_to_char("Targetting yourself is not a wise idea.\n\r", ch);
return;
}
//Checks the normal stuff to see if they can attack
if (check_battle_skills(ch, victim, usgn) == 0)
return;
ch->fight_timer += get_btimer(ch, usgn, NULL);
if (can_use_skill(ch, number_percent()-((mry-1)*10), usgn))
{
learn_from_success(ch, usgn, victim);
dam = 5 + lvl * 45/ 100;
dam = check_combat_hit(ch, victim, dam, at, WEAR_NECK, usgn);
if (dam == 5000)
global_retcode = damage(ch, victim, 50, usgn, DM_DEATH, LM_NECK);
else if (dam == -1)
global_retcode = damage(ch, victim, dam, usgn, DM_BLOCK, LM_NECK);
else if (dam == 0)
global_retcode = damage(ch, victim, 0, usgn, DM_MISS, LM_NECK);
else if (dam <= -2)
global_retcode = damage(ch, victim, dam*-1, usgn, DM_SLICEDLIMB, LM_NECK);
else if (dam >= 20000)
global_retcode = damage(ch, victim, dam/10000, usgn, DM_CRITICAL, LM_NECK);
else
global_retcode = damage(ch, victim, dam, usgn, 0, LM_NECK);
}
else
{
learn_from_failure(ch, usgn, victim);
global_retcode = damage(ch, victim, 0, usgn, 0, -1);
}
return;
}
void do_emeru(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
sh_int lvl; //Point_level
sh_int mry; //Mastery
sh_int pv; //Points
sh_int usgn; //Gn of the skill
sh_int at; //Attack type
sh_int dam;
at = GRIP_STAB;
usgn = gsn_emeru;
mry = MASTERED(ch, usgn);
pv = UMIN(13, LEARNED(ch, usgn));
lvl = UMIN(80, POINT_LEVEL(LEARNED(ch, usgn), MASTERED(ch, usgn)));
victim = get_battle_target(ch, argument);
if (!victim)
{
send_to_char("Your target is not here.\n\r", ch);
return;
}
if (!check_twohand_shield(ch))
return;
if (ch == victim)
{
send_to_char("Targetting yourself is not a wise idea.\n\r", ch);
return;
}
//Checks the normal stuff to see if they can attack
if (check_battle_skills(ch, victim, usgn) == 0)
return;
ch->fight_timer += get_btimer(ch, usgn, NULL);
if (can_use_skill(ch, number_percent()-((mry-1)*10), usgn))
{
learn_from_success(ch, usgn, victim);
dam = 7 + lvl * 60 / 100;
dam = check_combat_hit(ch, victim, dam, at, WEAR_NECK, usgn);
if (dam == 5000)
global_retcode = damage(ch, victim, 50, usgn, DM_DEATH, LM_NECK);
else if (dam == -1)
global_retcode = damage(ch, victim, dam, usgn, DM_BLOCK, LM_NECK);
else if (dam == 0)
global_retcode = damage(ch, victim, 0, usgn, DM_MISS, LM_NECK);
else if (dam <= -2)
global_retcode = damage(ch, victim, dam*-1, usgn, DM_SLICEDLIMB, LM_NECK);
else if (dam >= 20000)
global_retcode = damage(ch, victim, dam/10000, usgn, DM_CRITICAL, LM_NECK);
else
global_retcode = damage(ch, victim, dam, usgn, 0, LM_NECK);
}
else
{
learn_from_failure(ch, usgn, victim);
global_retcode = damage(ch, victim, 0, usgn, 0, -1);
}
return;
}
void do_elbowjab(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
char arg[MIL];
sh_int lvl; //Point_level
sh_int mry; //Mastery
sh_int pv; //Points
sh_int usgn; //Gn of the skill
sh_int at; //Attack type
int wtype;
int limb;
sh_int dam;
at = GRIP_STAB;
usgn = gsn_elbowjab;
mry = MASTERED(ch, usgn);
pv = UMIN(13, LEARNED(ch, usgn));
lvl = UMIN(80, POINT_LEVEL(LEARNED(ch, usgn), MASTERED(ch, usgn)));
argument = one_argument(argument, arg);
victim = get_battle_target(ch, arg);
if (!victim)
{
send_to_char("Your target is not here.\n\r", ch);
return;
}
if (!check_twohand_shield(ch))
return;
if (ch == victim)
{
send_to_char("Targetting yourself is not a wise idea.\n\r", ch);
return;
}
//Checks the normal stuff to see if they can attack
if (check_battle_skills(ch, victim, usgn) == 0)
return;
if (str_cmp(argument, "right") && str_cmp(argument, "left"))
{
send_to_char("Which arm do you want to strike?.\n\r", ch);
return;
}
if (!str_cmp(argument, "right"))
{
wtype = WEAR_ARM_R;
limb = LM_RARM;
}
else
{
wtype = WEAR_ARM_L;
limb = LM_LARM;
}
ch->fight_timer += get_btimer(ch, usgn, NULL);
if (can_use_skill(ch, number_percent()-((mry-1)*10), usgn))
{
learn_from_success(ch, usgn, victim);
dam = pv;
dam = check_combat_hit(ch, victim, dam, at, wtype, usgn);
if (dam == 5000)
global_retcode = damage(ch, victim, 50, usgn, DM_DEATH, LM_NECK);
else if (dam == -1)
global_retcode = damage(ch, victim, dam, usgn, DM_BLOCK, LM_NECK);
else if (dam == 0)
global_retcode = damage(ch, victim, 0, usgn, DM_MISS, LM_NECK);
else if (dam <= -2)
global_retcode = damage(ch, victim, dam*-1, usgn, DM_SLICEDLIMB, LM_NECK);
else if (dam >= 20000)
global_retcode = damage(ch, victim, dam/10000, usgn, DM_CRITICAL, LM_NECK);
else
global_retcode = damage(ch, victim, dam, usgn, 0, LM_NECK);
}
else
{
learn_from_failure(ch, usgn, victim);
global_retcode = damage(ch, victim, 0, usgn, 0, -1);
}
return;
}
void do_elbowstab(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
sh_int lvl; //Point_level
sh_int mry; //Mastery
sh_int pv; //Points
sh_int usgn; //Gn of the skill
sh_int at; //Attack type
char arg[MIL];
int wtype;
int limb;
sh_int dam;
at = GRIP_STAB;
usgn = gsn_elbowstab;
mry = MASTERED(ch, usgn);
pv = UMIN(13, LEARNED(ch, usgn));
lvl = UMIN(80, POINT_LEVEL(LEARNED(ch, usgn), MASTERED(ch, usgn)));
argument = one_argument(argument, arg);
victim = get_battle_target(ch, arg);
if (!victim)
{
send_to_char("Your target is not here.\n\r", ch);
return;
}
if (!check_twohand_shield(ch))
return;
if (ch == victim)
{
send_to_char("Targetting yourself is not a wise idea.\n\r", ch);
return;
}
//Checks the normal stuff to see if they can attack
if (check_battle_skills(ch, victim, usgn) == 0)
return;
if (str_cmp(argument, "right") && str_cmp(argument, "left"))
{
send_to_char("Which arm do you want to strike?.\n\r", ch);
return;
}
if (!str_cmp(argument, "right"))
{
wtype = WEAR_ARM_R;
limb = LM_RARM;
}
else
{
wtype = WEAR_ARM_L;
limb = LM_LARM;
}
ch->fight_timer += get_btimer(ch, usgn, NULL);
if (can_use_skill(ch, number_percent()-((mry-1)*10), usgn))
{
learn_from_success(ch, usgn, victim);
dam = 3 + lvl * 27/100;
dam = check_combat_hit(ch, victim, dam, at, wtype, usgn);
if (dam == 5000)
global_retcode = damage(ch, victim, 50, usgn, DM_DEATH, limb);
else if (dam == -1)
global_retcode = damage(ch, victim, dam, usgn, DM_BLOCK, limb);
else if (dam == 0)
global_retcode = damage(ch, victim, 0, usgn, DM_MISS, limb);
else if (dam <= -2)
global_retcode = damage(ch, victim, dam*-1, usgn, DM_SLICEDLIMB, limb);
else if (dam >= 20000)
global_retcode = damage(ch, victim, dam/10000, usgn, DM_CRITICAL, limb);
else
global_retcode = damage(ch, victim, dam, usgn, 0, limb);
}
else
{
learn_from_failure(ch, usgn, victim);
global_retcode = damage(ch, victim, 0, usgn, 0, -1);
}
return;
}
void do_elbowbreak(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
sh_int lvl; //Point_level
sh_int mry; //Mastery
sh_int pv; //Points
sh_int usgn; //Gn of the skill
sh_int at; //Attack type
char arg[MIL];
int wtype;
int limb;
sh_int dam;
at = GRIP_BASH;
usgn = gsn_elbowbreak;
mry = MASTERED(ch, usgn);
pv = UMIN(13, LEARNED(ch, usgn));
lvl = UMIN(80, POINT_LEVEL(LEARNED(ch, usgn), MASTERED(ch, usgn)));
argument = one_argument(argument, arg);
victim = get_battle_target(ch, arg);
if (!victim)
{
send_to_char("Your target is not here.\n\r", ch);
return;
}
if (!check_twohand_shield(ch))
return;
if (ch == victim)
{
send_to_char("Targetting yourself is not a wise idea.\n\r", ch);
return;
}
//Checks the normal stuff to see if they can attack
if (check_battle_skills(ch, victim, usgn) == 0)
return;
if (str_cmp(argument, "right") && str_cmp(argument, "left"))
{
send_to_char("Which arm do you want to strike?.\n\r", ch);
return;
}
if (!str_cmp(argument, "right"))
{
wtype = WEAR_ARM_R;
limb = LM_RARM;
}
else
{
wtype = WEAR_ARM_L;
limb = LM_LARM;
}
ch->fight_timer += get_btimer(ch, usgn, NULL);
if (can_use_skill(ch, number_percent()-((mry-1)*10), usgn))
{
learn_from_success(ch, usgn, victim);
dam = 5 + lvl*37/100;
dam = check_combat_hit(ch, victim, dam, at, wtype, usgn);
if (dam == 5000)
global_retcode = damage(ch, victim, 50, usgn, DM_DEATH, limb);
else if (dam == -1)
global_retcode = damage(ch, victim, dam, usgn, DM_BLOCK, limb);
else if (dam == 0)
global_retcode = damage(ch, victim, 0, usgn, DM_MISS, limb);
else if (dam <= -2)
global_retcode = damage(ch, victim, dam*-1, usgn, DM_SLICEDLIMB, limb);
else if (dam >= 20000)
global_retcode = damage(ch, victim, dam/10000, usgn, DM_CRITICAL, limb);
else
global_retcode = damage(ch, victim, dam, usgn, 0, limb);
}
else
{
learn_from_failure(ch, usgn, victim);
global_retcode = damage(ch, victim, 0, usgn, 0, -1);
}
return;
}
void do_amberio(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
sh_int lvl; //Point_level
sh_int mry; //Mastery
sh_int pv; //Points
sh_int usgn; //Gn of the skill
sh_int at; //Attack type
char arg[MIL];
int wtype;
int limb;
sh_int dam;
at = GRIP_SLASH;
usgn = gsn_amberio;
mry = MASTERED(ch, usgn);
pv = UMIN(13, LEARNED(ch, usgn));
lvl = UMIN(80, POINT_LEVEL(LEARNED(ch, usgn), MASTERED(ch, usgn)));
argument = one_argument(argument, arg);
victim = get_battle_target(ch, arg);
if (!victim)
{
send_to_char("Your target is not here.\n\r", ch);
return;
}
if (!check_twohand_shield(ch))
return;
if (ch == victim)
{
send_to_char("Targetting yourself is not a wise idea.\n\r", ch);
return;
}
//Checks the normal stuff to see if they can attack
if (check_battle_skills(ch, victim, usgn) == 0)
return;
if (str_cmp(argument, "right") && str_cmp(argument, "left"))
{
send_to_char("Which arm do you want to strike?.\n\r", ch);
return;
}
if (!str_cmp(argument, "right"))
{
wtype = WEAR_ARM_R;
limb = LM_RARM;
}
else
{
wtype = WEAR_ARM_L;
limb = LM_LARM;
}
ch->fight_timer += get_btimer(ch, usgn, NULL);
if (can_use_skill(ch, number_percent()-((mry-1)*10), usgn))
{
learn_from_success(ch, usgn, victim);
dam = 7 + lvl*52/100;
dam = check_combat_hit(ch, victim, dam, at, wtype, usgn);
if (dam == 5000)
global_retcode = damage(ch, victim, 50, usgn, DM_DEATH, limb);
else if (dam == -1)
global_retcode = damage(ch, victim, dam, usgn, DM_BLOCK, limb);
else if (dam == 0)
global_retcode = damage(ch, victim, 0, usgn, DM_MISS, limb);
else if (dam <= -2)
global_retcode = damage(ch, victim, dam*-1, usgn, DM_SLICEDLIMB, limb);
else if (dam >= 20000)
global_retcode = damage(ch, victim, dam/10000, usgn, DM_CRITICAL, limb);
else
global_retcode = damage(ch, victim, dam, usgn, 0, limb);
}
else
{
learn_from_failure(ch, usgn, victim);
global_retcode = damage(ch, victim, 0, usgn, 0, -1);
}
return;
}
void do_sidekick(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
sh_int lvl; //Point_level
sh_int mry; //Mastery
sh_int pv; //Points
sh_int usgn; //Gn of the skill
sh_int at; //Attack type
char arg[MIL];
int wtype;
int limb;
sh_int dam;
at = GRIP_BASH;
usgn = gsn_sidekick;
mry = MASTERED(ch, usgn);
pv = UMIN(13, LEARNED(ch, usgn));
lvl = UMIN(80, POINT_LEVEL(LEARNED(ch, usgn), MASTERED(ch, usgn)));
argument = one_argument(argument, arg);
victim = get_battle_target(ch, arg);
if (!victim)
{
send_to_char("Your target is not here.\n\r", ch);
return;
}
if (!check_twohand_shield(ch))
return;
if (ch == victim)
{
send_to_char("Targetting yourself is not a wise idea.\n\r", ch);
return;
}
//Checks the normal stuff to see if they can attack
if (check_battle_skills(ch, victim, usgn) == 0)
return;
if (str_cmp(argument, "right") && str_cmp(argument, "left"))
{
send_to_char("Which leg do you want to strike?.\n\r", ch);
return;
}
if (!str_cmp(argument, "right"))
{
wtype = WEAR_LEG_R;
limb = LM_RLEG;
}
else
{
wtype = WEAR_LEG_L;
limb = LM_LLEG;
}
ch->fight_timer += get_btimer(ch, usgn, NULL);
if (can_use_skill(ch, number_percent()-((mry-1)*10), usgn))
{
learn_from_success(ch, usgn, victim);
dam = pv;
dam = check_combat_hit(ch, victim, dam, at, wtype, usgn);
if (dam == 5000)
global_retcode = damage(ch, victim, 50, usgn, DM_DEATH, limb);
else if (dam == -1)
global_retcode = damage(ch, victim, dam, usgn, DM_BLOCK, limb);
else if (dam == 0)
global_retcode = damage(ch, victim, 0, usgn, DM_MISS, limb);
else if (dam <= -2)
global_retcode = damage(ch, victim, dam*-1, usgn, DM_SLICEDLIMB, limb);
else if (dam >= 20000)
global_retcode = damage(ch, victim, dam/10000, usgn, DM_CRITICAL, limb);
else
global_retcode = damage(ch, victim, dam, usgn, 0, limb);
}
else
{
learn_from_failure(ch, usgn, victim);
global_retcode = damage(ch, victim, 0, usgn, 0, -1);
}
return;
}
void do_kneestrike(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
sh_int lvl; //Point_level
sh_int mry; //Mastery
sh_int pv; //Points
sh_int usgn; //Gn of the skill
sh_int at; //Attack type
char arg[MIL];
int wtype;
int limb;
sh_int dam;
at = GRIP_BASH;
usgn = gsn_kneestrike;
mry = MASTERED(ch, usgn);
pv = UMIN(13, LEARNED(ch, usgn));
lvl = UMIN(80, POINT_LEVEL(LEARNED(ch, usgn), MASTERED(ch, usgn)));
argument = one_argument(argument, arg);
victim = get_battle_target(ch, arg);
if (!victim)
{
send_to_char("Your target is not here.\n\r", ch);
return;
}
if (!check_twohand_shield(ch))
return;
if (ch == victim)
{
send_to_char("Targetting yourself is not a wise idea.\n\r", ch);
return;
}
//Checks the normal stuff to see if they can attack
if (check_battle_skills(ch, victim, usgn) == 0)
return;
if (str_cmp(argument, "right") && str_cmp(argument, "left"))
{
send_to_char("Which leg do you want to strike?.\n\r", ch);
return;
}
if (!str_cmp(argument, "right"))
{
wtype = WEAR_LEG_R;
limb = LM_RLEG;
}
else
{
wtype = WEAR_LEG_L;
limb = LM_LLEG;
}
ch->fight_timer += get_btimer(ch, usgn, NULL);
if (can_use_skill(ch, number_percent()-((mry-1)*10), usgn))
{
learn_from_success(ch, usgn, victim);
dam = 3 + lvl * 28/100;
dam = check_combat_hit(ch, victim, dam, at, wtype, usgn);
if (dam == 5000)
global_retcode = damage(ch, victim, 50, usgn, DM_DEATH, limb);
else if (dam == -1)
global_retcode = damage(ch, victim, dam, usgn, DM_BLOCK, limb);
else if (dam == 0)
global_retcode = damage(ch, victim, 0, usgn, DM_MISS, limb);
else if (dam <= -2)
global_retcode = damage(ch, victim, dam*-1, usgn, DM_SLICEDLIMB, limb);
else if (dam >= 20000)
global_retcode = damage(ch, victim, dam/10000, usgn, DM_CRITICAL, limb);
else
global_retcode = damage(ch, victim, dam, usgn, 0, limb);
}
else
{
learn_from_failure(ch, usgn, victim);
global_retcode = damage(ch, victim, 0, usgn, 0, -1);
}
return;
}
void do_kneecrusher(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
sh_int lvl; //Point_level
sh_int mry; //Mastery
sh_int pv; //Points
sh_int usgn; //Gn of the skill
sh_int at; //Attack type
char arg[MIL];
int wtype;
int limb;
sh_int dam;
at = GRIP_SLASH;
usgn = gsn_kneecrusher;
mry = MASTERED(ch, usgn);
pv = UMIN(13, LEARNED(ch, usgn));
lvl = UMIN(80, POINT_LEVEL(LEARNED(ch, usgn), MASTERED(ch, usgn)));
argument = one_argument(argument, arg);
victim = get_battle_target(ch, arg);
if (!victim)
{
send_to_char("Your target is not here.\n\r", ch);
return;
}
if (ch == victim)
{
send_to_char("Targetting yourself is not a wise idea.\n\r", ch);
return;
}
if (!check_twohand_shield(ch))
return;
//Checks the normal stuff to see if they can attack
if (check_battle_skills(ch, victim, usgn) == 0)
return;
if (str_cmp(argument, "right") && str_cmp(argument, "left"))
{
send_to_char("Which leg do you want to strike?.\n\r", ch);
return;
}
if (!str_cmp(argument, "right"))
{
wtype = WEAR_LEG_R;
limb = LM_RLEG;
}
else
{
wtype = WEAR_LEG_L;
limb = LM_LLEG;
}
ch->fight_timer += get_btimer(ch, usgn, NULL);
if (can_use_skill(ch, number_percent()-((mry-1)*10), usgn))
{
learn_from_success(ch, usgn, victim);
dam = 5 + lvl*38/100;
dam = check_combat_hit(ch, victim, dam, at, wtype, usgn);
if (dam == 5000)
global_retcode = damage(ch, victim, 50, usgn, DM_DEATH, limb);
else if (dam == -1)
global_retcode = damage(ch, victim, dam, usgn, DM_BLOCK, limb);
else if (dam == 0)
global_retcode = damage(ch, victim, 0, usgn, DM_MISS, limb);
else if (dam <= -2)
global_retcode = damage(ch, victim, dam*-1, usgn, DM_SLICEDLIMB, limb);
else if (dam >= 20000)
global_retcode = damage(ch, victim, dam/10000, usgn, DM_CRITICAL, limb);
else
global_retcode = damage(ch, victim, dam, usgn, 0, limb);
}
else
{
learn_from_failure(ch, usgn, victim);
global_retcode = damage(ch, victim, 0, usgn, 0, -1);
}
return;
}
void do_lembecu(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
sh_int lvl; //Point_level
sh_int mry; //Mastery
sh_int pv; //Points
sh_int usgn; //Gn of the skill
sh_int at; //Attack type
char arg[MIL];
int wtype;
int limb;
sh_int dam;
at = GRIP_BASH;
usgn = gsn_lembecu;
mry = MASTERED(ch, usgn);
pv = UMIN(13, LEARNED(ch, usgn));
lvl = UMIN(80, POINT_LEVEL(LEARNED(ch, usgn), MASTERED(ch, usgn)));
argument = one_argument(argument, arg);
victim = get_battle_target(ch, arg);
if (!victim)
{
send_to_char("Your target is not here.\n\r", ch);
return;
}
if (!check_twohand_shield(ch))
return;
if (ch == victim)
{
send_to_char("Targetting yourself is not a wise idea.\n\r", ch);
return;
}
//Checks the normal stuff to see if they can attack
if (check_battle_skills(ch, victim, usgn) == 0)
return;
if (str_cmp(argument, "right") && str_cmp(argument, "left"))
{
send_to_char("Which LEG do you want to strike?.\n\r", ch);
return;
}
if (!str_cmp(argument, "right"))
{
wtype = WEAR_LEG_R;
limb = LM_RLEG;
}
else
{
wtype = WEAR_LEG_L;
limb = LM_LLEG;
}
ch->fight_timer += get_btimer(ch, usgn, NULL);
if (can_use_skill(ch, number_percent()-((mry-1)*10), usgn))
{
learn_from_success(ch, usgn, victim);
dam = 7 + lvl*53/100;
dam = check_combat_hit(ch, victim, dam, at, wtype, usgn);
if (dam == 5000)
global_retcode = damage(ch, victim, 50, usgn, DM_DEATH, limb);
else if (dam == -1)
global_retcode = damage(ch, victim, dam, usgn, DM_BLOCK, limb);
else if (dam == 0)
global_retcode = damage(ch, victim, 0, usgn, DM_MISS, limb);
else if (dam <= -2)
global_retcode = damage(ch, victim, dam*-1, usgn, DM_SLICEDLIMB, limb);
else if (dam >= 20000)
global_retcode = damage(ch, victim, dam/10000, usgn, DM_CRITICAL, limb);
else
global_retcode = damage(ch, victim, dam, usgn, 0, limb);
}
else
{
learn_from_failure(ch, usgn, victim);
global_retcode = damage(ch, victim, 0, usgn, 0, -1);
}
return;
}
void do_blitz(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
sh_int lvl; //Point_level
sh_int mry; //Mastery
sh_int pv; //Points
sh_int usgn; //Gn of the skill
sh_int at; //Attack type
sh_int dam;
at = GRIP_BASH;
usgn = gsn_blitz;
mry = MASTERED(ch, usgn);
pv = UMIN(13, LEARNED(ch, usgn));
lvl = UMIN(80, POINT_LEVEL(LEARNED(ch, usgn), MASTERED(ch, usgn)));
victim = get_battle_target(ch, argument);
if (!victim)
{
send_to_char("Your target is not here.\n\r", ch);
return;
}
if (!check_twohand_shield(ch))
return;
if (ch == victim)
{
send_to_char("Targetting yourself is not a wise idea.\n\r", ch);
return;
}
//Checks the normal stuff to see if they can attack
if (check_battle_skills(ch, victim, usgn) == 0)
return;
ch->fight_timer += get_btimer(ch, usgn, NULL);
if (can_use_skill(ch, number_percent()-((mry-1)*10), usgn))
{
learn_from_success(ch, usgn, victim);
dam = pv;
dam = check_combat_hit(ch, victim, dam, at, WEAR_BODY, usgn);
if (dam == 5000)
global_retcode = damage(ch, victim, 50, usgn, DM_DEATH, LM_BODY);
else if (dam == -1)
global_retcode = damage(ch, victim, dam, usgn, DM_BLOCK, LM_BODY);
else if (dam == 0)
global_retcode = damage(ch, victim, 0, usgn, DM_MISS, LM_BODY);
else if (dam <= -2)
global_retcode = damage(ch, victim, dam*-1, usgn, DM_SLICEDLIMB, LM_BODY);
else if (dam >= 20000)
global_retcode = damage(ch, victim, dam/10000, usgn, DM_CRITICAL, LM_BODY);
else
global_retcode = damage(ch, victim, dam, usgn, 0, LM_BODY);
}
else
{
learn_from_failure(ch, usgn, victim);
global_retcode = damage(ch, victim, 0, usgn, 0, -1);
}
return;
}
void do_spear(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
sh_int lvl; //Point_level
sh_int mry; //Mastery
sh_int pv; //Points
sh_int usgn; //Gn of the skill
sh_int at; //Attack type
sh_int dam;
at = GRIP_BASH;
usgn = gsn_spear;
mry = MASTERED(ch, usgn);
pv = UMIN(13, LEARNED(ch, usgn));
lvl = UMIN(80, POINT_LEVEL(LEARNED(ch, usgn), MASTERED(ch, usgn)));
victim = get_battle_target(ch, argument);
if (!victim)
{
send_to_char("Your target is not here.\n\r", ch);
return;
}
if (!check_twohand_shield(ch))
return;
if (ch == victim)
{
send_to_char("Targetting yourself is not a wise idea.\n\r", ch);
return;
}
//Checks the normal stuff to see if they can attack
if (check_battle_skills(ch, victim, usgn) == 0)
return;
ch->fight_timer += get_btimer(ch, usgn, NULL);
if (can_use_skill(ch, number_percent()-((mry-1)*10), usgn))
{
learn_from_success(ch, usgn, victim);
dam = 3 + lvl * 25 / 100;
dam = check_combat_hit(ch, victim, dam, at, WEAR_BODY, usgn);
if (dam == 5000)
global_retcode = damage(ch, victim, 50, usgn, DM_DEATH, LM_BODY);
else if (dam == -1)
global_retcode = damage(ch, victim, dam, usgn, DM_BLOCK, LM_BODY);
else if (dam == 0)
global_retcode = damage(ch, victim, 0, usgn, DM_MISS, LM_BODY);
else if (dam <= -2)
global_retcode = damage(ch, victim, dam*-1, usgn, DM_SLICEDLIMB, LM_BODY);
else if (dam >= 20000)
global_retcode = damage(ch, victim, dam/10000, usgn, DM_CRITICAL, LM_BODY);
else
global_retcode = damage(ch, victim, dam, usgn, 0, LM_BODY);
}
else
{
learn_from_failure(ch, usgn, victim);
global_retcode = damage(ch, victim, 0, usgn, 0, -1);
}
return;
}
void do_ribpuncture(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
sh_int lvl; //Point_level
sh_int mry; //Mastery
sh_int pv; //Points
sh_int usgn; //Gn of the skill
sh_int at; //Attack type
sh_int dam;
at = GRIP_STAB;
usgn = gsn_ribpuncture;
mry = MASTERED(ch, usgn);
pv = UMIN(13, LEARNED(ch, usgn));
lvl = UMIN(80, POINT_LEVEL(LEARNED(ch, usgn), MASTERED(ch, usgn)));
victim = get_battle_target(ch, argument);
if (!victim)
{
send_to_char("Your target is not here.\n\r", ch);
return;
}
if (!check_twohand_shield(ch))
return;
if (ch == victim)
{
send_to_char("Targetting yourself is not a wise idea.\n\r", ch);
return;
}
//Checks the normal stuff to see if they can attack
if (check_battle_skills(ch, victim, usgn) == 0)
return;
ch->fight_timer += get_btimer(ch, usgn, NULL);
if (can_use_skill(ch, number_percent()-((mry-1)*10), usgn))
{
learn_from_success(ch, usgn, victim);
dam = 5 + lvl*35/100;
dam = check_combat_hit(ch, victim, dam, at, WEAR_BODY, usgn);
if (dam == 5000)
global_retcode = damage(ch, victim, 50, usgn, DM_DEATH, LM_BODY);
else if (dam == -1)
global_retcode = damage(ch, victim, dam, usgn, DM_BLOCK, LM_BODY);
else if (dam == 0)
global_retcode = damage(ch, victim, 0, usgn, DM_MISS, LM_BODY);
else if (dam <= -2)
global_retcode = damage(ch, victim, dam*-1, usgn, DM_SLICEDLIMB, LM_BODY);
else if (dam >= 20000)
global_retcode = damage(ch, victim, dam/10000, usgn, DM_CRITICAL, LM_BODY);
else
global_retcode = damage(ch, victim, dam, usgn, 0, LM_BODY);
}
else
{
learn_from_failure(ch, usgn, victim);
global_retcode = damage(ch, victim, 0, usgn, 0, -1);
}
return;
}
void do_timmuru(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
sh_int lvl; //Point_level
sh_int mry; //Mastery
sh_int pv; //Points
sh_int usgn; //Gn of the skill
sh_int at; //Attack type
sh_int dam;
at = GRIP_SLASH;
usgn = gsn_timmuru;
mry = MASTERED(ch, usgn);
pv = UMIN(13, LEARNED(ch, usgn));
lvl = UMIN(80, POINT_LEVEL(LEARNED(ch, usgn), MASTERED(ch, usgn)));
victim = get_battle_target(ch, argument);
if (!victim)
{
send_to_char("Your target is not here.\n\r", ch);
return;
}
if (!check_twohand_shield(ch))
return;
if (ch == victim)
{
send_to_char("Targetting yourself is not a wise idea.\n\r", ch);
return;
}
//Checks the normal stuff to see if they can attack
if (check_battle_skills(ch, victim, usgn) == 0)
return;
ch->fight_timer += get_btimer(ch, usgn, NULL);
if (can_use_skill(ch, number_percent()-((mry-1)*10), usgn))
{
learn_from_success(ch, usgn, victim);
dam = 7 + lvl*50/100;
dam = check_combat_hit(ch, victim, dam, at, WEAR_BODY, usgn);
if (dam == 5000)
global_retcode = damage(ch, victim, 50, usgn, DM_DEATH, LM_BODY);
else if (dam == -1)
global_retcode = damage(ch, victim, dam, usgn, DM_BLOCK, LM_BODY);
else if (dam == 0)
global_retcode = damage(ch, victim, 0, usgn, DM_MISS, LM_BODY);
else if (dam <= -2)
global_retcode = damage(ch, victim, dam*-1, usgn, DM_SLICEDLIMB, LM_BODY);
else if (dam >= 20000)
global_retcode = damage(ch, victim, dam/10000, usgn, DM_CRITICAL, LM_BODY);
else
global_retcode = damage(ch, victim, dam, usgn, 0, LM_BODY);
}
else
{
learn_from_failure(ch, usgn, victim);
global_retcode = damage(ch, victim, 0, usgn, 0, -1);
}
return;
}
void do_nervepinch(CHAR_DATA *ch, char *argument)
{
int level;
CHAR_DATA *victim = NULL;
int chance = 0;
AFFECT_DATA af;
level = POINT_LEVEL(LEARNED(ch, gsn_nervepinch), MASTERED(ch, gsn_nervepinch));
if (argument[0] != '\0')
{
if ((victim = get_char_room_new(ch, argument, 1)) == NULL)
{
send_to_char("Your target is not here.\n\r", ch);
return;
}
}
if (!victim && !ch->fighting)
{
send_to_char("Syntax: nervepinch <target>\n\r", ch);
send_to_char("Note: You do not have to specify a target if you are fighting.\n\r", ch);
return;
}
if (!check_twohand_shield(ch))
return;
if (!victim)
victim = ch->fighting->who;
if (victim == ch)
{
send_to_char("Pinching yourself is not a good idea you idiot.\n\r", ch);
return;
}
if (IS_AFFECTED(victim, AFF_NERVEPINCH))
{
send_to_char("Your victim is already in pain from a nervepinch, adding to it will not help.\n\r", ch);
return;
}
if (!victim->fighting)
chance += 15;
if (!can_see(victim, ch))
chance += 20;
chance += URANGE(-4, (14 - get_curr_int(victim))*2, 4);
chance += URANGE(-4, (14 - get_curr_dex(victim))*2, 4);
chance += level/2;
chance = URANGE(1, chance, 60);
if (victim->max_hit > 1000)
chance/=2;
if (victim->max_hit > 5000)
chance/=2;
if (victim->max_hit > 10000)
chance/=4;
chance = URANGE(1, chance, 60);
if (number_range(1, 100) <= chance)
{
act(AT_RED, "$n quickly strikes $N with a deadly nervepinch. $N starts to twitch in pain!", ch, NULL, victim, TO_NOTVICT);
act(AT_RED, "You quickly strike at $N with a deadly nervepinch. $N twiches in pain, success!", ch, NULL, victim, TO_CHAR);
act(AT_RED, "$n quickly strikes at you with a deadly nervepinch. A horribly pain shoots down your spine!", ch, NULL, victim, TO_VICT);
af.type = gsn_nervepinch;
af.duration = 2+level/3;
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = meb(AFF_NERVEPINCH);
affect_join(victim, &af);
learn_from_success(ch, gsn_nervepinch, victim);
if (ch->fighting)
ch->fight_timer = skill_table[gsn_kickdirt]->beats;
else
WAIT_STATE(ch, skill_table[gsn_kickdirt]->beats*2);
if (victim->fighting)
victim->fight_timer *= 2;
else
set_fighting(victim, ch);
return;
}
else
{
act(AT_GREEN, "$n quickly strikes $N with a deadly nervepinch, but $N quickly evades it.", ch, NULL, victim, TO_NOTVICT);
act(AT_GREEN, "You quickly strike at $N with a deadly nervepinch, but $N quickly evades it.", ch, NULL, victim, TO_CHAR);
act(AT_GREEN, "$n quickly strikes at you with a deadly nervepinch, but you quickly evades it.", ch, NULL, victim, TO_VICT);
learn_from_failure(ch, gsn_nervepinch, victim);
if (ch->fighting)
ch->fight_timer = skill_table[gsn_kickdirt]->beats;
else
WAIT_STATE(ch, skill_table[gsn_kickdirt]->beats*2);
if (!victim->fighting)
set_fighting(victim, ch);
return;
}
}
//Attempt to cure poison or weaken
void do_cleansing(CHAR_DATA *ch, char *argument)
{
int level;
int succ = 0;
int weaken = (skill_lookup("weaken"));
if (!is_affected(ch, gsn_poison) && !is_affected(ch, weaken))
{
send_to_char("You need to be affected by poison or weaken to use this.\n\r", ch);
return;
}
level = POINT_LEVEL(LEARNED(ch, gsn_cleansing), MASTERED(ch, gsn_cleansing));
act(AT_GREEN, "$n closes $s eyes and starts to chant for spiritual cleansing.", ch, NULL, NULL, TO_ROOM);
act(AT_GREEN, "You close your eyes and start to chant for spiritual cleansing.", ch, NULL, NULL, TO_CHAR);
level += URANGE(-4, get_curr_wis(ch) - 14, 6);
level = URANGE(3, level, 90);
if (number_range(1, 100) > level)
{
act(AT_DGREEN, "You are unable to pull up enough energy to cleanse your body.", ch, NULL, NULL, TO_CHAR);
learn_from_failure(ch, gsn_cleansing, NULL);
WAIT_STATE(ch, skill_table[gsn_cleansing]->beats*2);
return;
}
if (is_affected(ch, gsn_poison))
{
affect_strip(ch, gsn_poison);
act(AT_BLUE, "You feel the poison being ripped from your body.", ch, NULL, NULL, TO_CHAR);
ch->mental_state = URANGE(-100, ch->mental_state, -10);
learn_from_success(ch, gsn_cleansing, NULL);
succ = 1;
}
if (is_affected(ch, weaken))
{
affect_strip(ch, weaken);
act(AT_BLUE, "You feel the weakening in your bones start to lift.", ch, NULL, NULL, TO_CHAR);
ch->mental_state = URANGE(-100, ch->mental_state, -10);
if (succ == 0)
learn_from_success(ch, gsn_cleansing, NULL);
}
WAIT_STATE(ch, skill_table[gsn_cleansing]->beats*2);
return;
}
void do_daze(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
AFFECT_DATA af;
int chance;
int level;
bool fail;
level = POINT_LEVEL(LEARNED(ch, gsn_daze), MASTERED(ch, gsn_daze));
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't concentrate enough for that.\n\r", ch);
return;
}
if (IS_NPC(ch) || ch->pcdata->ranking[gsn_daze] <= 0)
{
send_to_char("You better leave the martial arts to those who are skilled.\n\r", ch);
return;
}
if (!ch->fighting)
{
send_to_char("You can only use this during the heat of battle.\n\r", ch);
return;
}
if ((victim = get_char_room_new(ch, argument, 1)) == NULL)
{
victim = ch->fighting->who;
}
if (is_safe(ch, victim))
{
send_to_char("You cannot daze that target.\n\r", ch);
return;
}
check_illegal_pk(ch, victim);
check_attacker(ch, victim);
if (!IS_NPC(ch) && ch->move < ch->max_move / 10)
{
set_char_color(AT_SKILL, ch);
send_to_char("You are far too tired to do that.\n\r", ch);
return; /* missing return fixed March 11/96 */
}
if (HAS_WAIT(ch))
{
send_to_char("You are too busy in battle to do that.\n\r", ch);
return;
}
ch->fight_timer = get_btimer(ch, gsn_daze, NULL);
fail = FALSE;
chance = ris_save(victim, level, RIS_PARALYSIS);
if (chance == 1000)
fail = TRUE;
chance = 5+chance/4;
if (!IS_NPC(ch) && !IS_NPC(victim))
chance -= sysdata.stun_plr_vs_plr;
else
chance -= sysdata.stun_regular;
chance += ((get_curr_dex(victim) + get_curr_str(victim)) - (get_curr_dex(ch) + get_curr_str(ch))) * 3;
chance += victim->saving_para_petri;
chance = URANGE(5, chance, 35);
if (!fail)
{
if (number_range(1, 100) > chance)
fail = TRUE;
}
if (!fail)
{
learn_from_success(ch, gsn_daze, victim);
/* DO *NOT* CHANGE! -Thoric */
if (!IS_NPC(ch))
{
if (MASTERED(ch, gsn_daze) == 4)
ch->move -= ch->max_move / 20;
else
ch->move -= ch->max_move / 15;
}
ch->fight_timer = skill_table[gsn_daze]->beats;
act(AT_SKILL, "$N smashes into you, leaving you dazed!", victim, NULL, ch, TO_CHAR);
act(AT_SKILL, "You smash into $N, leaving $M dazed!", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n smashes into $N, leaving $M dazed!", ch, NULL, victim, TO_NOTVICT);
if (!IS_AFFECTED(victim, AFF_PARALYSIS))
{
af.type = gsn_daze;
af.location = APPLY_ARMOR;
af.modifier = -2;
af.duration = 4+(MASTERED(ch, gsn_stun));
af.bitvector = meb(AFF_PARALYSIS);
affect_to_char(victim, &af);
update_pos(victim);
}
start_hating(victim, ch);
start_hunting(victim, ch);
}
else
{
ch->fight_timer = skill_table[gsn_daze]->beats;
if (!IS_NPC(ch))
{
if (MASTERED(ch, gsn_daze) == 4)
ch->move -= ch->max_move / 30;
else
ch->move -= ch->max_move / 25;
}
learn_from_failure(ch, gsn_daze, victim);
act(AT_SKILL, "$n charges at you trying to daze you, but you dodge out of the way.", ch, NULL, victim, TO_VICT);
act(AT_SKILL, "You try to daze $N, but $E dodges out of the way.", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n charges at $N trying to daze $M, but keeps going right on past.", ch, NULL, victim, TO_NOTVICT);
start_hating(victim, ch);
start_hunting(victim, ch);
}
return;
}
void do_stun(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
AFFECT_DATA af;
int chance;
int level;
bool fail;
level = POINT_LEVEL(LEARNED(ch, gsn_stun), MASTERED(ch, gsn_stun));
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't concentrate enough for that.\n\r", ch);
return;
}
if (!IS_NPC(ch) && ch->pcdata->ranking[gsn_stun] <= 0)
{
send_to_char("You better leave the martial arts to those who are skilled.\n\r", ch);
return;
}
if (!ch->fighting || !ch->fighting->who)
{
send_to_char("You can only use this during the heat of battle.\n\r", ch);
return;
}
if ((victim = get_char_room_new(ch, argument, 1)) == NULL)
{
victim = ch->fighting->who;
}
if (is_safe(ch, victim))
{
send_to_char("You cannot stun that target.\n\r", ch);
return;
}
check_illegal_pk(ch, victim);
check_attacker(ch, victim);
if (!IS_NPC(ch) && ch->move < ch->max_move / 10)
{
set_char_color(AT_SKILL, ch);
send_to_char("You are far too tired to do that.\n\r", ch);
return; /* missing return fixed March 11/96 */
}
if (!IS_NPC(ch) && HAS_WAIT(ch))
{
send_to_char("You are too busy in battle to do that.\n\r", ch);
return;
}
ch->fight_timer = get_btimer(ch, gsn_stun, NULL);
fail = FALSE;
chance = ris_save(victim, level, RIS_PARALYSIS);
if (chance == 1000)
fail = TRUE;
chance = 15+chance/4;
if (!IS_NPC(ch) && !IS_NPC(victim))
chance -= sysdata.stun_plr_vs_plr;
else
chance -= sysdata.stun_regular;
chance += ((get_curr_dex(victim) + get_curr_str(victim)) - (get_curr_dex(ch) + get_curr_str(ch))) * 3;
chance += victim->saving_para_petri;
chance = URANGE(5, chance, 45);
if (!fail)
{
if (number_range(1, 100) > chance)
fail = TRUE;
}
if (!fail)
{
learn_from_success(ch, gsn_stun, victim);
/* DO *NOT* CHANGE! -Thoric */
if (!IS_NPC(ch))
{
if (MASTERED(ch, gsn_stun) == 4)
ch->move -= ch->max_move / 20;
else
ch->move -= ch->max_move / 15;
}
ch->fight_timer = skill_table[gsn_stun]->beats;
act(AT_SKILL, "$N smashes into you, leaving you stunned!", victim, NULL, ch, TO_CHAR);
act(AT_SKILL, "You smash into $N, leaving $M stunned!", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n smashes into $N, leaving $M stunned!", ch, NULL, victim, TO_NOTVICT);
if (!IS_AFFECTED(victim, AFF_PARALYSIS))
{
af.type = gsn_stun;
af.location = APPLY_ARMOR;
af.modifier = -4;
af.duration = 4+(MASTERED(ch, gsn_stun)*3/2);
if (IS_NPC(ch))
af.duration = 2+MASTERED(ch, gsn_stun);
af.bitvector = meb(AFF_PARALYSIS);
affect_to_char(victim, &af);
update_pos(victim);
}
start_hating(victim, ch);
start_hunting(victim, ch);
}
else
{
ch->fight_timer = skill_table[gsn_stun]->beats;
if (!IS_NPC(ch))
{
if (MASTERED(ch, gsn_stun) == 4)
ch->move -= ch->max_move / 30;
else
ch->move -= ch->max_move / 25;
}
learn_from_failure(ch, gsn_stun, victim);
act(AT_SKILL, "$n charges at you screaming, but you dodge out of the way.", ch, NULL, victim, TO_VICT);
act(AT_SKILL, "You try to stun $N, but $E dodges out of the way.", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n charges screaming at $N, but keeps going right on past.", ch, NULL, victim, TO_NOTVICT);
start_hating(victim, ch);
start_hunting(victim, ch);
}
return;
}
/*
* Disarm a creature.
* Caller must check for successful attack.
* Check for loyalty flag (weapon disarms to inventory) for pkillers -Blodkai
*/
void disarm(CHAR_DATA * ch, CHAR_DATA * victim)
{
OBJ_DATA *obj, *tmpobj;
char buf[MSL];
int level;
int trigger;
if ((obj = get_eq_char(victim, WEAR_WIELD)) == NULL)
return;
if ((tmpobj = get_eq_char(victim, WEAR_DUAL_WIELD)) != NULL && number_bits(1) == 0)
obj = tmpobj;
if (get_eq_char(ch, WEAR_WIELD) == NULL && number_bits(1) == 0)
{
learn_from_failure(ch, gsn_disarm, victim);
return;
}
if (IS_NPC(ch) && !can_see_obj(ch, obj) && number_bits(1) == 0)
{
learn_from_failure(ch, gsn_disarm, victim);
return;
}
if (HAS_WAIT(ch))
{
return;
}
if (check_grip(ch, victim))
{
learn_from_failure(ch, gsn_disarm, victim);
return;
}
if (IS_OBJ_STAT(obj, ITEM_NODISARM))
{
sprintf(buf, "%s has a nodisarm object", victim->name);
if (get_trust(ch) > LEVEL_HI_IMM)
level = get_trust(ch);
else
level = LEVEL_HI_IMM;
log_string_plus(buf, LOG_COMM, level);
return;
}
trigger = MOBtrigger;
MOBtrigger = TRUE;
act(AT_SKILL, "&G$n &R****[&G&WDISARMS&R]****&G you!", ch, NULL, victim, TO_VICT);
act(AT_SKILL, "&GYou &R****[&G&WDISARM&R]****&G $N!", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n disarms $N!", ch, NULL, victim, TO_NOTVICT);
MOBtrigger = trigger;
learn_from_success(ch, gsn_disarm, victim);
if (obj == get_eq_char(victim, WEAR_WIELD) && (tmpobj = get_eq_char(victim, WEAR_DUAL_WIELD)) != NULL)
tmpobj->wear_loc = WEAR_WIELD;
if ((!IS_NPC(victim) && victim->pcdata->quest && victim->pcdata->quest->questarea == victim->in_room->area)
|| (IS_OBJ_STAT(obj, ITEM_NOGIVE)) || (IS_OBJ_STAT(obj, ITEM_NODROP)))
{
unequip_char(victim, obj);
obj->wear_loc = -1;
}
else
{
unequip_char(victim, obj);
obj->wear_loc = -1;
obj_from_char(obj);
obj_to_room(obj, victim->in_room, victim);
}
return;
}
void do_disarm(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
OBJ_DATA *obj;
int percent;
sh_int points;
points = POINT_LEVEL(LEARNED(ch, gsn_disarm), MASTERED(ch, gsn_disarm));
points /= 2;
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't concentrate enough for that.\n\r", ch);
return;
}
if (IS_NPC(ch) || ch->pcdata->ranking[gsn_disarm] <= 0)
{
send_to_char("You don't know how to disarm opponents.\n\r", ch);
return;
}
if (get_eq_char(ch, WEAR_WIELD) == NULL)
{
send_to_char("You must wield a weapon to disarm.\n\r", ch);
return;
}
if ((victim = who_fighting(ch)) == NULL)
{
send_to_char("You aren't fighting anyone.\n\r", ch);
return;
}
if ((obj = get_eq_char(victim, WEAR_WIELD)) == NULL)
{
send_to_char("Your opponent is not wielding a weapon.\n\r", ch);
return;
}
ch->fight_timer = get_btimer(ch, gsn_disarm, NULL);
percent = points + URANGE(-5, get_curr_lck(ch)-get_curr_lck(victim), 5);
percent = percent + URANGE(-5, get_curr_str(ch)-get_curr_str(victim), 5);
percent = URANGE(1, percent, 45);
if (!can_see_obj(ch, obj))
percent /= 2;
if (number_range(1, 100) <= percent)
disarm(ch, victim);
else
{
send_to_char("You failed.\n\r", ch);
learn_from_failure(ch, gsn_disarm, victim);
}
return;
}
/*
* Trip a creature.
* Caller must check for successful attack.
*/
void trip(CHAR_DATA * ch, CHAR_DATA * victim)
{
int chance;
if (IS_AFFECTED(victim, AFF_FLYING) || IS_AFFECTED(victim, AFF_FLOATING))
return;
if (HAS_WAIT(ch))
{
return;
}
chance = 50-((get_curr_str(victim)-14)*2)-((get_curr_dex(victim)-14)*3)-((get_curr_lck(victim)-14));
chance = URANGE(15, chance, 85);
if (victim->mount)
{
chance /= 3;
if (IS_AFFECTED(victim->mount, AFF_FLYING) || IS_AFFECTED(victim->mount, AFF_FLOATING))
return;
if (number_range(1, 100) <= chance)
{
act(AT_SKILL, "$n trips your mount and you fall off!", ch, NULL, victim, TO_VICT);
act(AT_SKILL, "You trip $N's mount and $N falls off!", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n trips $N's mount and $N falls off!", ch, NULL, victim, TO_NOTVICT);
xREMOVE_BIT(victim->mount->act, ACT_MOUNTED);
victim->mount = NULL;
if (victim->fighting)
{
victim->fight_timer+=2;
}
else
{
WAIT_STATE(victim, 2 * PULSE_VIOLENCE);
victim->position = POS_RESTING;
}
return;
}
else
{
act(AT_SKILL, "$n attempts to trip your mount but it does not budge!", ch, NULL, victim, TO_VICT);
act(AT_SKILL, "You attempt to trip $N's mount but it will not budge!", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n attempts to trip $N's mount but it will not budge!", ch, NULL, victim, TO_NOTVICT);
}
}
else
{
if (number_range(1, 100) <= chance)
{
act(AT_SKILL, "$n trips you and you go down!", ch, NULL, victim, TO_VICT);
act(AT_SKILL, "You trip $N and $N goes down!", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n trips $N and $N goes down!", ch, NULL, victim, TO_NOTVICT);
if (victim->fighting)
{
victim->fight_timer+=2;
}
else
{
WAIT_STATE(victim, 2 * PULSE_VIOLENCE);
victim->position = POS_RESTING;
}
}
else
{
act(AT_SKILL, "$n attempts to trip you but fails!", ch, NULL, victim, TO_VICT);
act(AT_SKILL, "You attempt to trip $N but you fail!", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n attempts to trip $N but fails!", ch, NULL, victim, TO_NOTVICT);
}
}
return;
}
void do_begging(CHAR_DATA * ch, char *argument)
{
int level;
CHAR_DATA *victim;
int chance;
level = POINT_LEVEL(LEARNED(ch, gsn_begging), MASTERED(ch, gsn_begging));
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't concentrate enough for that.\n\r", ch);
return;
}
if (IS_NPC(ch) || ch->pcdata->ranking[gsn_begging] <= 0)
{
send_to_char("You don't know how to beg.\n\r", ch);
return;
}
if ((victim = get_char_room_new(ch, argument, 1)) == NULL)
{
send_to_char("Your target is not here for you to beg from.\n\r", ch);
return;
}
if (xIS_SET(victim->act, ACT_AGGRESSIVE))
{
send_to_char("Your target doesn't look very friendly, begging is not a good idea.\n\r", ch);
return;
}
if (IS_AFFECTED(ch, AFF_HIDE) || IS_AFFECTED(ch, AFF_INVISIBLE) || IS_AFFECTED(ch, AFF_STALK))
{
send_to_char("You can only beg if you are visible.\n\r", ch);
return;
}
if (!IS_NPC(victim))
{
send_to_char("You can only use this on NPCs, if you want to beg from players use say.\n\r", ch);
return;
}
if (IS_ACT_FLAG(victim, ACT_MOUNTSAVE))
{
send_to_char("You mount doesn't look very interested in helping you out.\n\r", ch);
return;
}
if (victim->race >= MAX_PC_RACE)
{
send_to_char("You can only beg from humanoid NPCs.\n\r", ch);
return;
}
if (ch->position != POS_STANDING)
{
send_to_char("You have to be standing to beg.\n\r", ch);
return;
}
chance = 30 + (level/2);
chance -= victim->begatt;
if (xIS_SET(victim->act, ACT_PACIFIST))
chance /=2;
WAIT_STATE(ch, skill_table[gsn_begging]->beats*2);
if (number_range(1, 100) > chance)
{
learn_from_failure(ch, gsn_begging, victim);
victim->begatt++;
if (!xIS_SET(victim->act, ACT_PACIFIST))
{
if (number_range(1, 100) > UMIN(95, 45+(level/2)))
{
act(AT_RED, "$n tries to beg for some money from $N, but $N decides $n should DIE instead!", ch, NULL, victim, TO_NOTVICT);
act(AT_RED, "You try to beg for some money from $N, but $N decides you should DIE instead!", ch, NULL, victim, TO_CHAR);
one_hit(victim, ch, TYPE_HIT, LM_BODY);
return;
}
}
act(AT_RED, "$n tries to beg for some money from $N, but $N refuses to give $n any money.", ch, NULL, victim, TO_NOTVICT);
act(AT_RED, "You try to beg for some money from $N, but $N refuses to give you any money.", ch, NULL, victim, TO_CHAR);
return;
}
else
{
learn_from_success(ch, gsn_begging, victim);
victim->begatt++;
ch->gold += URANGE(2, number_range(2+level/6, 5+level/6), 15);
act(AT_RED, "$n tries to beg for some money from $N and $N gives $n a few coins.", ch, NULL, victim, TO_NOTVICT);
act(AT_RED, "You try to beg for some money from $N and $N gives you a few coins.", ch, NULL, victim, TO_CHAR);
return;
}
}
char *const insult_target[4] = {
"mother", "father", "family", "lover"
};
char *const insult_fun[18] = {
"a useless tool", "a giant failure", "a nasty cesspool", "a filthy maggot", "a scorge",
"a scar on humanity", "a worthless f**k", "a stupid f**k", "a giant pile of lard", "an eyesore",
"a bastard", "a waste of space", "a fairy's b***h", "uglier than a troll", "another stupid fool",
"a bastard child", "the stupidest motherf****r on this earth", "a son of a b***h"
};
void do_insult(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
int level;
int chance;
char buf[MSL];
int x;
int y;
if (check_npc(ch))
return;
if (argument[0] != '\0')
{
if ((victim = get_char_room_new(ch, argument, 1)) == NULL)
{
send_to_char("Your target is not here.\n\r", ch);
return;
}
}
else
{
if (!ch->fighting || !ch->fighting->who)
{
send_to_char("You need to be fighting to insult someone.\n\r", ch);
return;
}
victim = ch->fighting->who;
}
if (!victim->fighting)
{
send_to_char("You can only taunt a target that is fighting.\n\r", ch);
return;
}
if (!IS_NPC(victim))
{
send_to_char("Save the smack for the say and chat channels ok.\n\r", ch);
return;
}
x = number_range(0, 4);
y = number_range(0, 17);
if (x == 4)
{
sprintf(buf, "$n calls $N %s", insult_fun[y]);
act(AT_RED, buf, ch, NULL, victim, TO_ROOM);
sprintf(buf, "You call $N %s", insult_fun[y]);
act(AT_RED, buf, ch, NULL, victim, TO_CHAR);
}
else
{
sprintf(buf, "$n calls $N's %s %s", insult_target[x], insult_fun[y]);
act(AT_RED, buf, ch, NULL, victim, TO_ROOM);
sprintf(buf, "You call $N's %s %s", insult_target[x], insult_fun[y]);
act(AT_RED, buf, ch, NULL, victim, TO_CHAR);
}
ch->fight_timer = 2;
level = POINT_LEVEL(LEARNED(ch, gsn_insult), MASTERED(ch, gsn_insult));
chance = 50 + (level * 5 / 6);
if (get_curr_int(victim) <= 14)
chance += 20;
else if (get_curr_int(victim) <= 16)
chance += 10;
else if (get_curr_int(victim) <= 18)
chance -= 10;
else if (get_curr_int(victim) <= 20)
chance -= 30;
else if (get_curr_int(victim) <= 22)
chance -= 60;
else if (get_curr_int(victim) <= 24)
chance -= 90;
else
chance = 0;
if (number_range(1, 100) <= chance)
{
learn_from_success(ch, gsn_insult, victim);
adjust_aggression_list(victim, ch, 0, 2, gsn_insult);
}
else
learn_from_failure(ch, gsn_insult, victim);
return;
}
void do_pick(CHAR_DATA * ch, char *argument)
{
char arg[MIL];
CHAR_DATA *gch;
OBJ_DATA *obj;
EXIT_DATA *pexit;
int x, y, z;
sh_int percent;
int level;
TOWN_DATA *town;
level = POINT_LEVEL(LEARNED(ch, gsn_pick_lock), MASTERED(ch, gsn_pick_lock));
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't concentrate enough for that.\n\r", ch);
return;
}
one_argument(argument, arg);
if (arg[0] == '\0')
{
send_to_char("Pick what?\n\r", ch);
return;
}
if (ms_find_obj(ch))
return;
if (ch->mount)
{
send_to_char("You can't do that while mounted.\n\r", ch);
return;
}
WAIT_STATE(ch, skill_table[gsn_pick_lock]->beats*2);
/* look for guards */
for (gch = ch->in_room->first_person; gch; gch = gch->next_in_room)
{
if (IN_SAME_ROOM(gch, ch) && IS_NPC(gch) && IS_AWAKE(gch))
{
act(AT_PLAIN, "$N is standing too close to the lock.", ch, NULL, gch, TO_CHAR);
return;
}
}
percent = 35 + (level*2/3) + (14-get_curr_lck(ch));
if (number_range(1, 100) > percent)
{
send_to_char("You failed.\n\r", ch);
learn_from_failure(ch, gsn_pick_lock, NULL);
/* for ( gch = ch->in_room->first_person; gch; gch = gch->next_in_room )
{
if ( IS_NPC(gch) && IS_AWAKE(gch) && xIS_SET(gch->act, ACT_GUARDIAN ) )
one_hit( gch, ch, TYPE_UNDEFINED );
}
*/
return;
}
if ((pexit = find_door(ch, arg, TRUE)) != NULL)
{
/* 'pick door' */
/* ROOM_INDEX_DATA *to_room; *//* Unused */
EXIT_DATA *pexit_rev;
if (!IS_SET(pexit->exit_info, EX_CLOSED))
{
send_to_char("It's not closed.\n\r", ch);
return;
}
if (pexit->key < 0)
{
send_to_char("It can't be picked.\n\r", ch);
return;
}
if (!IS_SET(pexit->exit_info, EX_LOCKED))
{
send_to_char("It's already unlocked.\n\r", ch);
return;
}
if (IS_SET(pexit->exit_info, EX_PICKPROOF))
{
send_to_char("You failed.\n\r", ch);
learn_from_failure(ch, gsn_pick_lock, NULL);
check_room_for_traps(ch, TRAP_PICK | trap_door[pexit->vdir]);
return;
}
REMOVE_BIT(pexit->exit_info, EX_LOCKED);
send_to_char("*Click*\n\r", ch);
act(AT_ACTION, "$n picks the $d.", ch, NULL, pexit->keyword, TO_ROOM);
learn_from_success(ch, gsn_pick_lock, NULL);
adjust_favor(ch, 9, 1);
/* pick the other side */
if ((pexit_rev = pexit->rexit) != NULL && pexit_rev->to_room == ch->in_room)
{
REMOVE_BIT(pexit_rev->exit_info, EX_LOCKED);
}
check_room_for_traps(ch, TRAP_PICK | trap_door[pexit->vdir]);
return;
}
if ((obj = get_obj_here(ch, arg)) != NULL)
{
/* 'pick object' */
if (obj->item_type != ITEM_CONTAINER)
{
send_to_char("That's not a container.\n\r", ch);
return;
}
if (!IS_SET(obj->value[1], CONT_CLOSED))
{
send_to_char("It's not closed.\n\r", ch);
return;
}
if (obj->value[2] < 0)
{
send_to_char("It can't be unlocked.\n\r", ch);
return;
}
if (!IS_SET(obj->value[1], CONT_LOCKED))
{
send_to_char("It's already unlocked.\n\r", ch);
return;
}
if (IS_SET(obj->value[1], CONT_PICKPROOF))
{
send_to_char("You failed.\n\r", ch);
learn_from_failure(ch, gsn_pick_lock, NULL);
check_for_trap(ch, obj, TRAP_PICK, NEW_TRAP_PICK);
return;
}
separate_obj(obj);
REMOVE_BIT(obj->value[1], CONT_LOCKED);
send_to_char("*Click*\n\r", ch);
act(AT_ACTION, "$n picks $p.", ch, obj, NULL, TO_ROOM);
learn_from_success(ch, gsn_pick_lock, NULL);
adjust_favor(ch, 9, 1);
check_for_trap(ch, obj, TRAP_PICK, NEW_TRAP_PICK);
return;
}
x = ch->coord->x;
y = ch->coord->y;
if (IN_WILDERNESS(ch) && is_valid_movement(&x, &y, arg, ch))
{
if (map_sector[ch->map][x][y] != SECT_LDOOR)
{
send_to_char("There is no locked door in that direction.\n\r", ch);
return;
}
town = find_town(x, y, ch->map);
if (!town)
{
bug("do_pick: %s at %d %d has picked a door that does not belong to a town.", ch->name, x, y);
}
else
{
for (z = 0; z <= 99; z++)
{
if (town->doorstate[4][z] > 0)
{
if (town->doorstate[5][z] == x && town->doorstate[6][z] == y && town->doorstate[7][z] == ch->map)
{
town->doorstate[0][z] = 1;
write_kingdom_file(town->kingdom);
break;
}
}
}
if (z == 100)
{
bug("do_open: %s at %d %d in town %s has found a door not belonging to that town", ch->name, x, y, town->name);
}
}
send_to_char("*Click*\n\r", ch);
act(AT_ACTION, "$n picks the door to the $d.", ch, NULL, arg, TO_ROOM);
map_sector[ch->map][x][y] = SECT_LDOOR;
return;
}
ch_printf(ch, "You see no %s here.\n\r", arg);
return;
}
//Allows you to climb over walls depending on what is on the otherside. Does not allow
//allow moving into "bad" sectors or into roofed areas. As soon as one is encountered
//it fails. If you cannot get past the layers of walls you cannot climb in either.
//--Xerves
void do_climbwall(CHAR_DATA *ch, char *argument)
{
int x = ch->coord->x;
int y = ch->coord->y;
int cnt=0;
int level;
TOWN_DATA *town;
if (argument[0] == '\0')
{
send_to_char("Syntax: climbwall [direction]\n\r", ch);
return;
}
if (!is_valid_movement(&x, &y, argument, ch))
return;
if (ch->position != POS_STANDING)
{
send_to_char("You have to be standing to climb over a wall.\n\r", ch);
return;
}
if (map_sector[ch->map][x][y] != SECT_WALL && map_sector[ch->map][x][y] != SECT_DWALL
&& map_sector[ch->map][x][y] != SECT_NBWALL && map_sector[ch->map][x][y] != SECT_DOOR
&& map_sector[ch->map][x][y] != SECT_CDOOR && map_sector[ch->map][x][y] != SECT_LDOOR)
{
send_to_char("There is not a wall in that direction.\n\r", ch);
return;
}
level = POINT_LEVEL(LEARNED(ch, gsn_gag), MASTERED(ch, gsn_gag));
for (;;)
{
if (cnt++ > 2+(level/10))
{
send_to_char("There is simply too much wall for you to climb in that direction.\n\r", ch);
return;
}
town = find_town(x, y, ch->map);
if (map_sector[ch->map][x][y] != SECT_WALL && map_sector[ch->map][x][y] != SECT_DWALL
&& map_sector[ch->map][x][y] != SECT_NBWALL && map_sector[ch->map][x][y] != SECT_DOOR
&& map_sector[ch->map][x][y] != SECT_CDOOR && map_sector[ch->map][x][y] != SECT_LDOOR
&& (!town || (town && town->usedpoint[x - town->startx+30][y - town->starty+30] == 0)))
{
if (!sect_show[(int)map_sector[ch->map][x][y]].canpass)
{
send_to_char("There is a nopass sector in your wall that direction.\n\r", ch);
return;
}
//Looks to be a free sector lets jump in it
if (40+level > number_range(1, 100)+(cnt-2)*15)
{
send_to_char("You carefully crawl up the wall and land SUCCESSFULLY on the other side.\n\r", ch);
ch->coord->x = x;
ch->coord->y = y;
update_objects(ch, x, y, ch->map);
if (ch->rider)
{
act(AT_WHITE, "$n successfully climbs over the wall with you on $s back.", ch, NULL, ch->rider, TO_VICT);
ch->rider->coord->x = x;
ch->rider->coord->y = y;
do_look(ch->rider, "auto");
update_objects(ch->rider, x, y, ch->map);
}
do_look(ch, "auto");
learn_from_success(ch, gsn_climbwall, NULL);
return;
}
else
{
send_to_char("You attempt to climb the wall but you end up falling off it instead!.\n\r", ch);
WAIT_STATE(ch, 20);
learn_from_failure(ch, gsn_climbwall, NULL);
damage(ch, ch, number_range(5, 10), TYPE_UNDEFINED, 0, -1);
return;
}
}
else
{
if (!is_valid_movement(&x, &y, argument, ch))
return;
}
}
}
//Removes the gag affect if you happen to have a handy knife around
void do_cutgag(CHAR_DATA *ch, char *argument)
{
OBJ_DATA *obj;
if (argument[0] == '\0')
{
send_to_char("Syntax: cutgag <object>\n\r", ch);
send_to_char("Syntax: cutgag none\n\r", ch);
return;
}
if (IS_NPC(ch))
{
send_to_char("Not for NPCS!.\n\r", ch);
return;
}
if (ch->position <= POS_SLEEPING)
{
send_to_char("You need to be fighting/standing/mounted/resting to remove a gag.\n\r", ch);
return;
}
if (!IS_AFFECTED(ch, AFF_GAGGED))
{
send_to_char("Your aren't gagged, no real reason to do that now is there?", ch);
return;
}
if ((obj = get_obj_carry(ch, argument)) == NULL)
{
if (!str_cmp(argument, "none"))
;
else
{
send_to_char("You cannot seem to find the object in your inventory.\n\r", ch);
return;
}
}
if (obj && !IS_OBJ_STAT(obj, ITEM_GAGREMOVE))
{
send_to_char("That cannot be used to remove gags.\n\r", ch);
return;
}
affect_strip(ch, gsn_gag);
if (obj)
{
act(AT_WHITE, "$n pulls out $p and cuts the gag off.", ch, obj, NULL, TO_NOTVICT);
act(AT_WHITE, "You pull out $p and cut the gag off.", ch, obj, NULL, TO_CHAR);
}
else
{
act(AT_WHITE, "$n works franticly to remove the gag.", ch, NULL, NULL, TO_NOTVICT);
act(AT_WHITE, "You work franticly to remove the gag.", ch, NULL, NULL, TO_CHAR);
}
if (!ch->fighting)
{
if (obj)
WAIT_STATE(ch, 1);
else
WAIT_STATE(ch, 8);
}
else
{
if (obj)
ch->fight_timer = 1;
else
ch->fight_timer = 8;
}
}
void do_gag(CHAR_DATA * ch, char *argument)
{
AFFECT_DATA af;
CHAR_DATA *victim;
int level;
int fighting=0;
char arg1[MIL];
OBJ_DATA *obj;
if (argument[0] == '\0')
{
send_to_char("Syntax: gag <object> <target>\n\r", ch);
return;
}
argument = one_argument(argument, arg1);
level = POINT_LEVEL(LEARNED(ch, gsn_gag), MASTERED(ch, gsn_gag));
if (IS_NPC(ch))
{
send_to_char("Not for NPCS!.\n\r", ch);
return;
}
if (ch->position != POS_STANDING && ch->position != POS_EVASIVE && ch->position != POS_DEFENSIVE
&& ch->position != POS_FIGHTING && ch->position != POS_AGGRESSIVE)
{
send_to_char("You can only use this if you are standing, or fighting no higher than aggressive style.\n\r", ch);
return;
}
if (ch->mount)
{
send_to_char("You can't do that while mounted.\n\r", ch);
return;
}
if (!ch->fighting)
fighting = 1;
if ((obj = get_obj_carry(ch, arg1)) == NULL)
{
send_to_char("You cannot seem to find the object in your inventory.\n\r", ch);
return;
}
if (obj->item_type != ITEM_GAG)
{
send_to_char("You cannot use that to gag someone!\n\r", ch);
return;
}
if ((victim = get_char_room_new(ch, argument, 1)) == NULL)
{
send_to_char("Your target is not here with you.\n\r", ch);
return;
}
if (IS_AFFECTED(victim, AFF_GAGGED))
{
send_to_char("Your target is already gagged, no use in doing it twice!", ch);
return;
}
if (IS_ACT_FLAG(victim, ACT_PACIFIST))
{
send_to_char("Target is pacifist, cannot do that now!\n\r", ch);
return;
}
if (is_safe(ch, victim))
return;
if (!IS_NPC(victim) && !IS_NPC(ch) && get_trust(victim) >= LEVEL_IMMORTAL)
{
send_to_char("Sorry, you cannot gag immortals.\n\r", ch);
return;
}
separate_obj(obj);
if (number_range(1, 100) <= (10+(fighting*40)+UMIN(50, level * 2 / 3)))
{
//success
act(AT_WHITE, "$n pulls out $p and shoves it in $N's mouth to shut $M up.", ch, obj, victim, TO_NOTVICT);
act(AT_WHITE, "You pull out $p and shove it in $N's mouth to shut $M up.", ch, obj, victim, TO_CHAR);
act(AT_WHITE, "$n pulls out $p and shoves it in your mouth to shut you up.", ch, obj, victim, TO_VICT);
af.type = gsn_gag;
af.duration = 5+UMIN(12, level/6);
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = meb(AFF_GAGGED);
affect_to_char(victim, &af);
if (ch->fighting)
ch->fight_timer = 5 - UMIN(2, level/30);
else
WAIT_STATE(ch, 5 - UMIN(2, level/30));
learn_from_success(ch, gsn_gag, victim);
obj_from_char(obj);
extract_obj(obj);
if (IS_NPC(victim) && !victim->fighting)
one_hit(victim, ch, TYPE_HIT, LM_BODY);
}
else
{
act(AT_WHITE, "$n pulls out $p and tries to gag $N but fails.", ch, obj, victim, TO_NOTVICT);
act(AT_WHITE, "You pull out $p and try to gag $N but fail.", ch, obj, victim, TO_CHAR);
act(AT_WHITE, "$n pulls out $p and tries to gag you but fails", ch, obj, victim, TO_VICT);
if (ch->fighting)
ch->fight_timer = 7 - UMIN(2, level/30);
else
WAIT_STATE(ch, 7 - UMIN(2, level/30));
learn_from_failure(ch, gsn_gag, victim);
obj_from_char(obj);
extract_obj(obj);
if (IS_NPC(victim) && !victim->fighting)
one_hit(victim, ch, TYPE_HIT, LM_BODY);
}
}
void get_wilderness_move(CHAR_DATA *ch, int dir)
{
if (dir == 0)
do_north(ch, "");
else if (dir == 1)
do_east(ch, "");
else if (dir == 2)
do_south(ch, "");
else if (dir == 3)
do_west(ch, "");
else if (dir == 6)
do_northeast(ch, "");
else if (dir == 7)
do_northwest(ch, "");
else if (dir == 8)
do_southeast(ch, "");
else if (dir == 9)
do_southwest(ch, "");
}
void do_stalk(CHAR_DATA * ch, char *argument)
{
AFFECT_DATA af;
sh_int level;
int dir;
level = POINT_LEVEL(LEARNED(ch, gsn_stalk), MASTERED(ch, gsn_stalk));
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't concentrate enough for that.\n\r", ch);
return;
}
if (ch->mount)
{
send_to_char("You can't do that while mounted.\n\r", ch);
return;
}
if ((dir = get_door(argument)) == -1)
{
send_to_char("Stalk in WHAT direction?\n\r", ch);
return;
}
if (!IN_WILDERNESS(ch) && !(get_exit(ch->in_room, dir)))
{
send_to_char("You cannot go that direction.\n\r", ch);
return;
}
ch_printf(ch, "You attempt to stalk silently %s\n\r", argument);
affect_strip(ch, gsn_stalk);
af.type = gsn_stalk;
af.duration = 10+level/2;
af.location = APPLY_NONE;
af.modifier = level;
af.bitvector = meb(AFF_STALK);
affect_to_char(ch, &af);
if (IN_WILDERNESS(ch))
{
get_wilderness_move(ch, dir);
}
else
move_char(ch, get_exit(ch->in_room, dir), 0);
return;
}
void do_sneak(CHAR_DATA * ch, char *argument)
{
AFFECT_DATA af;
sh_int level;
sh_int mastery;
mastery = MASTERED(ch, gsn_sneak) * 20;
mastery = mastery - 60;
level = POINT_LEVEL(LEARNED(ch, gsn_sneak), MASTERED(ch, gsn_sneak));
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't concentrate enough for that.\n\r", ch);
return;
}
if (ch->mount)
{
send_to_char("You can't do that while mounted.\n\r", ch);
return;
}
send_to_char("You attempt to move silently.....\n\r", ch);
affect_strip(ch, gsn_sneak);
if (can_use_skill(ch, number_percent() - mastery, gsn_sneak))
{
send_to_char("You feel you have the ability to move secretly now...\n\r", ch);
af.type = gsn_sneak;
af.duration = 600+level*6;
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = meb(AFF_SNEAK);
affect_to_char(ch, &af);
learn_from_success(ch, gsn_sneak, ch);
}
else
learn_from_failure(ch, gsn_sneak, ch);
return;
}
void do_hide(CHAR_DATA * ch, char *argument)
{
sh_int mastery;
mastery = MASTERED(ch, gsn_hide) * 20;
mastery = mastery - 60;
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't concentrate enough for that.\n\r", ch);
return;
}
if (ch->mount)
{
send_to_char("You can't do that while mounted.\n\r", ch);
return;
}
if (!IS_NPC(ch) && !is_nighttime() && LEARNED(ch, gsn_lightprawl) <= 0)
{
send_to_char("You can only hide during the day if you have knowledge of lightprawl.\n\r", ch);
return;
}
send_to_char("You attempt to hide....\n\r", ch);
if (IS_AFFECTED(ch, AFF_HIDE))
xREMOVE_BIT(ch->affected_by, AFF_HIDE);
if (ch->race == RACE_FAIRY)
{
xSET_BIT(ch->affected_by, AFF_HIDE);
if (ch->pcdata->learned[gsn_hide] > 0)
learn_from_success(ch, gsn_hide, ch);
return;
}
if (can_use_skill(ch, number_percent() - mastery, gsn_hide))
{
xSET_BIT(ch->affected_by, AFF_HIDE);
learn_from_success(ch, gsn_hide, ch);
}
else
learn_from_failure(ch, gsn_hide, ch);
return;
}
/*
* Contributed by Alander.
*/
void do_visible(CHAR_DATA * ch, char *argument)
{
affect_strip(ch, gsn_invis);
affect_strip(ch, gsn_mass_invis);
affect_strip(ch, gsn_sneak);
affect_strip(ch, gsn_stalk);
xREMOVE_BIT(ch->affected_by, AFF_HIDE);
xREMOVE_BIT(ch->affected_by, AFF_INVISIBLE);
xREMOVE_BIT(ch->affected_by, AFF_SNEAK);
xREMOVE_BIT(ch->affected_by, AFF_STALK);
send_to_char("Ok.\n\r", ch);
return;
}
void do_recall(CHAR_DATA * ch, char *argument)
{
ROOM_INDEX_DATA *location;
CHAR_DATA *opponent;
location = NULL;
if (IS_NPC(ch))
return;
if (!IS_NPC(ch) && ch->pcdata->caste < 2)
location = get_room_index(5644);
if (!IS_NPC(ch) && ch->pcdata->clan)
location = get_room_index(ch->pcdata->clan->recall);
/* Hometown code - Xerves */
/* Replaced with Kingdom, pretty much the same damn thing -- Xerves 12/99 */
if (!location && ch->pcdata->town)
location = get_room_index(OVERLAND_SOLAN);
if (!location)
location = get_room_index(ROOM_VNUM_TEMPLE);
if (!str_cmp(argument, "rolen"))
location = get_room_index(ROOM_VNUM_TEMPLE);
if (!location)
{
send_to_char("You are completely lost.\n\r", ch);
return;
}
if (ch->in_room == location && location->vnum != OVERLAND_SOLAN)
return;
if (ch->pcdata->town && location->vnum == OVERLAND_SOLAN && ch->coord->x == ch->pcdata->town->recall[0]
&& ch->coord->y == ch->pcdata->town->recall[1] && ch->map == ch->pcdata->town->recall[2])
return;
if (ch->fighting)
{
send_to_char("You cannot recall during a battle now, flee.\n\r", ch);
return;
}
if (xIS_SET(ch->in_room->room_flags, ROOM_NO_RECALL))
{
send_to_char("For some strange reason... nothing happens.\n\r", ch);
return;
}
if (in_hellmaze(ch))
{
send_to_char("The only way out of the maze from hell is death or reaching the end.\n\r", ch);
return;
}
if (get_timer(ch, TIMER_RECENTFIGHT) >= 1)
{
send_to_char("Your blood is pumping too much to do this at this time.\n\r", ch);
return;
}
if (IS_AFFECTED(ch, AFF_CURSE))
{
send_to_char("You are cursed and cannot recall!\n\r", ch);
return;
}
if (xIS_SET(ch->act, PLR_GAMBLER))
{
send_to_char("You cannot recall while you are gambling!\n\r", ch);
return;
}
if (ch->ship)
{
send_to_char("You cannot recall while on a ship.\n\r", ch);
return;
}
if (HAS_WAIT(ch))
{
send_to_char("You are too busy in battle to do that.\n\r", ch);
return;
}
if ((opponent = who_fighting(ch)) != NULL)
{
if (number_bits(1) == 0 || (!IS_NPC(opponent) && number_bits(3) > 1))
{
WAIT_STATE(ch, 4);
ch_printf(ch, "You failed!\n\r");
return;
}
ch_printf(ch, "You recall from combat!\n\r");
stop_fighting(ch, TRUE);
}
act(AT_ACTION, "$n disappears in a swirl of smoke.", ch, NULL, NULL, TO_ROOM);
ch->coord->x = ch->coord->y = ch->map = -1;
REMOVE_ONMAP_FLAG(ch);
if (ch->on)
{
ch->on = NULL;
ch->position = POS_STANDING;
}
if (ch->position != POS_STANDING && ch->position != POS_RIDING)
{
ch->position = POS_STANDING;
}
char_from_room(ch);
char_to_room(ch, location);
if (location->vnum == OVERLAND_SOLAN)
{
ch->coord->x = ch->pcdata->town->recall[0];
ch->coord->y = ch->pcdata->town->recall[1];
ch->map = ch->pcdata->town->recall[2];
SET_ONMAP_FLAG(ch);
if (ch->mount)
{
char_from_room(ch->mount);
char_to_room(ch->mount, location);
ch->mount->coord->x = ch->coord->x;
ch->mount->coord->y = ch->coord->y;
ch->mount->map = ch->map;
SET_ONMAP_FLAG(ch->mount);
do_look(ch->mount, "auto");
}
if (!IS_NPC(ch) && ch->pcdata->pet)
{
char_from_room(ch->pcdata->pet);
char_to_room(ch->pcdata->pet, location);
ch->pcdata->pet->coord->x = ch->coord->x;
ch->pcdata->pet->coord->y = ch->coord->y;
ch->pcdata->pet->map = ch->map;
SET_ONMAP_FLAG(ch->pcdata->pet);
do_look(ch->pcdata->pet, "auto");
}
if (!IS_NPC(ch) && ch->pcdata->mount && !ch->mount)
{
char_from_room(ch->pcdata->mount);
char_to_room(ch->pcdata->mount, location);
ch->pcdata->mount->coord->x = ch->coord->x;
ch->pcdata->mount->coord->y = ch->coord->y;
ch->pcdata->mount->map = ch->map;
SET_ONMAP_FLAG(ch->pcdata->mount);
do_look(ch->pcdata->mount, "auto");
}
if (ch->rider)
{
char_from_room(ch->rider);
char_to_room(ch->rider, location);
ch->rider->coord->x = ch->coord->x;
ch->rider->coord->y = ch->coord->y;
ch->rider->map = ch->map;
SET_ONMAP_FLAG(ch->rider);
update_objects(ch->rider, ch->rider->map, ch->rider->coord->x, ch->rider->coord->y);
do_look(ch->rider, "auto");
}
if (ch->riding)
{
char_from_room(ch->riding);
char_to_room(ch->riding, location);
ch->riding->coord->x = ch->coord->x;
ch->riding->coord->y = ch->coord->y;
ch->riding->map = ch->map;
SET_ONMAP_FLAG(ch->riding);
update_objects(ch->riding, ch->riding->map, ch->riding->coord->x, ch->riding->coord->y);
do_look(ch->riding, "auto");
}
}
else
{
if (ch->mount)
{
ch->mount->coord->x = ch->mount->coord->y = ch->mount->map = -1;
REMOVE_ONMAP_FLAG(ch->mount);
char_from_room(ch->mount);
char_to_room(ch->mount, location);
update_objects(ch->mount, ch->mount->map, ch->mount->coord->x, ch->mount->coord->y);
do_look(ch->mount, "auto");
}
if (ch->pcdata->pet)
{
ch->pcdata->pet->coord->x = ch->pcdata->pet->coord->y = ch->pcdata->pet->map = -1;
REMOVE_ONMAP_FLAG(ch->pcdata->pet);
char_from_room(ch->pcdata->pet);
char_to_room(ch->pcdata->pet, location);
do_look(ch->pcdata->pet, "auto");
}
if (ch->pcdata->mount && !ch->mount)
{
ch->pcdata->mount->coord->x = ch->pcdata->mount->coord->y = ch->pcdata->mount->map = -1;
REMOVE_ONMAP_FLAG(ch->pcdata->mount);
char_from_room(ch->pcdata->mount);
char_to_room(ch->pcdata->mount, location);
do_look(ch->pcdata->mount, "auto");
}
if (ch->rider)
{
ch->rider->coord->x = ch->rider->coord->y = ch->rider->map = -1;
REMOVE_ONMAP_FLAG(ch->rider);
char_from_room(ch->rider);
char_to_room(ch->rider, location);
do_look(ch->rider, "auto");
}
if (ch->riding)
{
ch->riding->coord->x = ch->riding->coord->y = ch->riding->map = -1;
REMOVE_ONMAP_FLAG(ch->riding);
char_from_room(ch->riding);
char_to_room(ch->riding, location);
do_look(ch->riding, "auto");
}
}
update_objects(ch, ch->map, ch->coord->x, ch->coord->y);
act(AT_ACTION, "$n appears in the room.", ch, NULL, NULL, TO_ROOM);
do_look(ch, "auto");
return;
}
void do_aid(CHAR_DATA * ch, char *argument)
{
char arg[MIL];
CHAR_DATA *victim;
int percent;
int mastery;
mastery = MASTERED(ch, gsn_aid) * 15;
mastery = mastery - 60;
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't concentrate enough for that.\n\r", ch);
return;
}
one_argument(argument, arg);
if (arg[0] == '\0')
{
send_to_char("Aid whom?\n\r", ch);
return;
}
if ((victim = get_char_room_new(ch, arg, 1)) == NULL)
{
send_to_char("They aren't here.\n\r", ch);
return;
}
if (IS_NPC(victim)) /* Gorog */
{
send_to_char("Not on mobs.\n\r", ch);
return;
}
if (ch->mount)
{
send_to_char("You can't do that while mounted.\n\r", ch);
return;
}
if (victim == ch)
{
send_to_char("Aid yourself?\n\r", ch);
return;
}
if (victim->position > POS_STUNNED)
{
act(AT_PLAIN, "$N doesn't need your help.", ch, NULL, victim, TO_CHAR);
return;
}
if (victim->hit <= -6)
{
act(AT_PLAIN, "$N's condition is beyond your aiding ability.", ch, NULL, victim, TO_CHAR);
return;
}
if (HAS_WAIT(ch))
{
send_to_char("You are too busy in battle to do that.\n\r", ch);
return;
}
percent = number_percent() - (get_curr_lck(ch) - 13);
if (!ch->fighting)
WAIT_STATE(ch, skill_table[gsn_aid]->beats*2);
else
ch->fight_timer = get_btimer(ch, gsn_aid, NULL);
if (!can_use_skill(ch, percent + mastery, gsn_aid))
{
send_to_char("You fail.\n\r", ch);
learn_from_failure(ch, gsn_aid, victim);
return;
}
act(AT_SKILL, "You aid $N!", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n aids $N!", ch, NULL, victim, TO_NOTVICT);
learn_from_success(ch, gsn_aid, victim);
adjust_favor(ch, 8, 1);
if (victim->hit < 1)
victim->hit = 1;
update_pos(victim);
act(AT_SKILL, "$n aids you!", ch, NULL, victim, TO_VICT);
return;
}
//Allow a PC to give another PC a ride....Be scared of the hobbit totting
//ogres
void do_piggyback(CHAR_DATA *ch, char *argument)
{
CHAR_DATA *victim;
if ((victim = get_char_room_new(ch, argument, 1)) == NULL)
{
send_to_char("You can't find that here.\n\r", ch);
return;
}
if (ch->mount)
{
send_to_char("Might be a good idea to dismount whatever you are on right now.\n\r", ch);
return;
}
if (victim->rider)
{
send_to_char("Your target already has a rider.\n\r", ch);
return;
}
if (ch->riding)
{
send_to_char("You are already hitching a ride.\n\r", ch);
return;
}
if (!IS_NPC(victim) && xIS_SET(victim->act, PLR_NORIDERS))
{
send_to_char("Your target would crush you like a peanut if you even attempted.\n\r", ch);
return;
}
if (IS_NPC(victim) && !xIS_SET(victim->act, ACT_ALLOWRIDE))
{
send_to_char("You cannot piggyback that mob.\n\r", ch);
return;
}
if (victim->position < POS_STANDING)
{
send_to_char("Your target must be standing.\n\r", ch);
return;
}
if (victim->position == POS_FIGHTING || victim->fighting)
{
send_to_char("Your mount is moving around too much.\n\r", ch);
return;
}
if (get_ch_carry_weight(ch)+ ch->weight > can_carry_w(victim))
{
send_to_char("You weight too much for your target to carry.\n\r", ch);
return;
}
ch->riding = victim;
victim->rider = ch;
/* Take away Hide + Sneak */
if (IS_AFFECTED(ch, AFF_STALK))
{
xREMOVE_BIT(ch->affected_by, AFF_STALK);
xREMOVE_BIT(ch->affected_by, AFF_HIDE);
xREMOVE_BIT(ch->affected_by, AFF_SNEAK);
affect_strip(ch, gsn_stalk);
act(AT_SKILL, "You appear from the shadows amd jump on $N's back.", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n appears from the shadows and jumps on the back of $N.", ch, NULL, victim, TO_NOTVICT);
act(AT_SKILL, "$n appears from the shadows and then jumps on YOUR BACK.", ch, NULL, victim, TO_VICT);
}
else if (IS_AFFECTED(ch, AFF_HIDE) && IS_AFFECTED(ch, AFF_SNEAK))
{
xREMOVE_BIT(ch->affected_by, AFF_HIDE);
xREMOVE_BIT(ch->affected_by, AFF_SNEAK);
act(AT_SKILL, "You stop sneaking, appear from the shadows, and then jump on $N's back.", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n stops sneaking, appears from the shadows, and jumps on the back of $N.", ch, NULL, victim, TO_NOTVICT);
act(AT_SKILL, "$n stops sneaking, appears from the shadows, and then jumps on YOUR BACK.", ch, NULL, victim, TO_VICT);
}
else if (IS_AFFECTED(ch, AFF_HIDE))
{
xREMOVE_BIT(ch->affected_by, AFF_HIDE);
act(AT_SKILL, "You appear from the shadows amd jump on $N's back.", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n appears from the shadows and jumps on the back of $N.", ch, NULL, victim, TO_NOTVICT);
act(AT_SKILL, "$n appears from the shadows and then jumps on YOUR BACK.", ch, NULL, victim, TO_VICT);
}
else if (IS_AFFECTED(ch, AFF_SNEAK))
{
xREMOVE_BIT(ch->affected_by, AFF_SNEAK);
act(AT_SKILL, "You stop sneaking and then jump on $N's back.", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n stops sneaking and jumps on the back of $N.", ch, NULL, victim, TO_NOTVICT);
act(AT_SKILL, "$n stops sneaking and then jumps on YOUR BACK.", ch, NULL, victim, TO_VICT);
}
else
{
act(AT_SKILL, "You jump on the back of $N.", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n skillfully jumps on the back of $N.", ch, NULL, victim, TO_NOTVICT);
act(AT_SKILL, "$n jumps on YOUR BACK.", ch, NULL, victim, TO_VICT);
}
ch->position = POS_RIDING;
return;
}
void do_mount(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
if (ch->mount)
{
send_to_char("You're already mounted!\n\r", ch);
return;
}
if ((victim = get_char_room_new(ch, argument, 1)) == NULL)
{
send_to_char("You can't find that here.\n\r", ch);
return;
}
if (!IS_NPC(victim) || !xIS_SET(victim->act, ACT_MOUNTABLE))
{
send_to_char("You can't mount that!\n\r", ch);
return;
}
if (ch->riding)
{
send_to_char("You need to be not riding someone to use mount.\n\r", ch);
return;
}
if (xIS_SET(victim->act, ACT_MOUNTED))
{
send_to_char("That mount already has a rider.\n\r", ch);
return;
}
if (victim->position < POS_STANDING)
{
send_to_char("Your mount must be standing.\n\r", ch);
return;
}
if (victim->position == POS_FIGHTING || victim->fighting)
{
send_to_char("Your mount is moving around too much.\n\r", ch);
return;
}
if (xIS_SET(victim->act, ACT_MOUNTSAVE) && (ch->pcdata->mount == NULL))
{
send_to_char("Only the owner can mount this one.\n\r", ch);
return;
}
if (xIS_SET(victim->act, ACT_MOUNTSAVE) && (ch->pcdata->mount != victim))
{
send_to_char("Only the owner can mount this one.\n\r", ch);
return;
}
if (get_ch_carry_weight(ch) > can_carry_w(victim))
{
send_to_char("Your mount thinks you weight a bit too much to try that.\n\r", ch);
return;
}
xSET_BIT(victim->act, ACT_MOUNTED);
ch->mount = victim;
/* Take away Hide + Sneak */
if (IS_AFFECTED(ch, AFF_STALK))
{
xREMOVE_BIT(ch->affected_by, AFF_STALK);
xREMOVE_BIT(ch->affected_by, AFF_HIDE);
xREMOVE_BIT(ch->affected_by, AFF_SNEAK);
affect_strip(ch, gsn_stalk);
act(AT_SKILL, "You appear from the shadows to mount $N.", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n appears from the shadows and skillfully mounts $N.", ch, NULL, victim, TO_NOTVICT);
act(AT_SKILL, "$n appears from the shadows to mounts you.", ch, NULL, victim, TO_VICT);
}
else if (IS_AFFECTED(ch, AFF_HIDE) && IS_AFFECTED(ch, AFF_HIDE))
{
xREMOVE_BIT(ch->affected_by, AFF_HIDE);
xREMOVE_BIT(ch->affected_by, AFF_SNEAK);
act(AT_SKILL, "You stop sneaking and appear from the shadows to mount $N.", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n stops sneaking and appears from the shadows to skillfully mounts $N.", ch, NULL, victim, TO_NOTVICT);
act(AT_SKILL, "$n stops sneaking and appears from the shadows to mounts you.", ch, NULL, victim, TO_VICT);
}
else if (IS_AFFECTED(ch, AFF_HIDE))
{
xREMOVE_BIT(ch->affected_by, AFF_HIDE);
act(AT_SKILL, "You appear from the shadows to mount $N.", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n appears from the shadows and skillfully mounts $N.", ch, NULL, victim, TO_NOTVICT);
act(AT_SKILL, "$n appears from the shadows to mounts you.", ch, NULL, victim, TO_VICT);
}
else if (IS_AFFECTED(ch, AFF_SNEAK))
{
xREMOVE_BIT(ch->affected_by, AFF_SNEAK);
act(AT_SKILL, "You stop sneaking and mount $N.", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n stops sneaking and skillfully mounts $N.", ch, NULL, victim, TO_NOTVICT);
act(AT_SKILL, "$n stops sneaking and mounts you.", ch, NULL, victim, TO_VICT);
}
else
{
act(AT_SKILL, "You mount $N.", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n skillfully mounts $N.", ch, NULL, victim, TO_NOTVICT);
act(AT_SKILL, "$n mounts you.", ch, NULL, victim, TO_VICT);
}
ch->position = POS_MOUNTED;
return;
}
void do_toss(CHAR_DATA *ch, char *argument)
{
int dam;
CHAR_DATA *victim;
char arg[MIL];
if (argument[0] == '\0')
{
send_to_char("Syntax: toss [soft/hard]\n\r", ch);
send_to_char("Syntax: toss at <victim>\n\r", ch);
return;
}
if (!ch->rider)
{
send_to_char("You have no one currently on your back to toss off.\n\r", ch);
return;
}
argument = one_argument(argument, arg);
if (!str_cmp(arg, "soft"))
{
act(AT_SKILL, "You gently toss $N off of his back and onto the ground.", ch, NULL, ch->rider, TO_CHAR);
act(AT_SKILL, "$n gently tosses $N off of $s back and onto the ground.", ch, NULL, ch->rider, TO_NOTVICT);
act(AT_SKILL, "$n gently tosses you off of $s back and onto the ground.", ch, NULL, ch->rider, TO_VICT);
ch->rider->position = POS_STANDING;
ch->rider->riding = NULL;
ch->rider = NULL;
return;
}
if (!str_cmp(arg, "hard"))
{
act(AT_SKILL, "You grab $N and toss $S with great velocity toward the ground.", ch, NULL, ch->rider, TO_CHAR);
act(AT_SKILL, "$n grabs $N and tosses $S with great velocity toward the ground.", ch, NULL, ch->rider, TO_NOTVICT);
act(AT_SKILL, "$n grabs you and tosses you with great velocity toward the ground.", ch, NULL, ch->rider, TO_VICT);
dam = URANGE(-4, (get_curr_str(ch)-13)/2, 4)+5;
ch->rider->position = POS_STANDING;
ch->rider->riding = NULL;
damage(ch->rider, ch->rider, dam, TYPE_UNDEFINED, 0, -1);
ch->rider = NULL;
return;
}
if (!str_cmp(arg, "at"))
{
if ((victim = get_char_room_new(ch, argument, 1)) == NULL)
{
send_to_char("Your target is not in the room with you.\n\r", ch);
return;
}
if (is_safe(ch, victim))
{
send_to_char("This room is safe from fighting, sorry.\n\r", ch);
return;
}
if (!IS_NPC(victim) && !IS_NPC(ch) && get_trust(ch) >= LEVEL_IMMORTAL)
{
sprintf(log_buf, "%s: immortal attempting player murder of %s.", ch->name, victim->name);
log_string_plus(log_buf, LOG_NORMAL, LEVEL_ADMIN);
send_to_char("Sorry, you cannot murder players.\n\r", ch);
return;
}
if (!IS_NPC(victim) && !IS_NPC(ch) && get_trust(victim) >= LEVEL_IMMORTAL)
{
sprintf(log_buf, "%s: player attempted immortal murder of %s.", ch->name, victim->name);
log_string_plus(log_buf, LOG_NORMAL, LEVEL_ADMIN);
send_to_char("Sorry, you cannot murder immortals.\n\r", ch);
return;
}
check_illegal_pk(ch, victim);
check_attacker(ch, victim);
act(AT_SKILL, "You are grabbed and thrown toward $N, this cannot be good!", ch->rider, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n is promply thrown from $s riding position toward $N. Look out!", ch->rider, NULL, victim, TO_NOTVICT);
act(AT_SKILL, "$n is being thrown toward you, stupid little bastards!.", ch->rider, NULL, victim, TO_VICT);
dam = URANGE(-4, (get_curr_str(ch)-13)/2, 4)+5;
ch->rider->position = POS_STANDING;
ch->rider->riding = NULL;
damage(ch->rider, ch->rider, dam, TYPE_UNDEFINED, 0, -1);
if (!char_died(ch->rider))
damage(ch->rider, victim, dam, TYPE_UNDEFINED, 0, -1);
ch->rider = NULL;
return;
}
do_toss(ch, "");
return;
}
void do_dismount(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *victim;
if (ch->riding)
{
act(AT_SKILL, "You jump off the back of $N.", ch, NULL, ch->riding, TO_CHAR);
act(AT_SKILL, "$n skillfully jumps off the back of $N.", ch, NULL, ch->riding, TO_NOTVICT);
act(AT_SKILL, "$n jumps of your back...about damn time!", ch, NULL, ch->riding, TO_VICT);
ch->riding->rider = NULL;
ch->riding = NULL;
ch->position = POS_STANDING;
return;
}
if ((victim = ch->mount) == NULL)
{
send_to_char("You're not mounted.\n\r", ch);
return;
}
act(AT_SKILL, "You dismount $N.", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n skillfully dismounts $N.", ch, NULL, victim, TO_NOTVICT);
act(AT_SKILL, "$n dismounts you. Whew!", ch, NULL, victim, TO_VICT);
xREMOVE_BIT(victim->act, ACT_MOUNTED);
ch->mount = NULL;
ch->position = POS_STANDING;
return;
}
/**************************************************************************/
/*
* Check for parry.
*/
int check_parry(CHAR_DATA * ch, CHAR_DATA *victim)
{
sh_int mastery;
sh_int level;
OBJ_DATA *aweapon;
OBJ_DATA *vweapon;
int aparry = 0, vparry = 0;
int chance;
mastery = MASTERED(victim, gsn_parry);
level = POINT_LEVEL(LEARNED(victim, gsn_parry), MASTERED(victim, gsn_parry));
if (!IS_AWAKE(victim))
return FALSE;
if (IS_NPC(victim) && !xIS_SET(victim->defenses, DFND_PARRY))
return FALSE;
aweapon = get_eq_char(ch, WEAR_WIELD);
vweapon = get_eq_char(victim, WEAR_WIELD);
if (!vweapon && !IS_NPC(victim))
return FALSE;
if (aweapon)
{
aparry = aweapon->value[13];
aparry += (get_curr_str(ch) - 14)/2;
if (victim->position == POS_BERSERK)
aparry *= 140/100;
if (victim->position == POS_AGGRESSIVE)
aparry *= 120/100;
if (victim->position == POS_FIGHTING)
aparry *= 100/100;
if (victim->position == POS_DEFENSIVE)
aparry *= 80/100;
if (victim->position == POS_EVASIVE)
aparry *= 60/100;
}
else if (!aweapon && IS_NPC(ch))
{
aparry = URANGE(0, (get_curr_str(ch)-14)*2, 20);
}
if (vweapon)
{
vparry = vweapon->value[12];
vparry += (get_curr_dex(victim) - 14)/2;
if (victim->position == POS_BERSERK)
vparry *= 60/100;
if (victim->position == POS_AGGRESSIVE)
vparry *= 80/100;
if (victim->position == POS_FIGHTING)
vparry *= 100/100;
if (victim->position == POS_DEFENSIVE)
vparry *= 120/100;
if (victim->position == POS_EVASIVE)
vparry *= 140/100;
}
else if (!vweapon && IS_NPC(victim))
{
vparry = URANGE(0, (get_curr_dex(victim)-14)*4, 40);
}
if (!IS_NPC(victim))
{
vparry += number_range(level/3, level/4);
}
chance = vparry - aparry;
//bug("v%d a%d t%d", vparry, aparry, chance);
chance = chance * sysdata.parry_mod / 100;
if (victim->morph)
chance += victim->morph->parry;
chance = URANGE(1, chance, 40);
if (chance >= number_range(1, 100))
{
//slight gain to dex, not as much as dodge...
if (!IS_NPC(victim))
{
int mdex = 1;
int dex = victim->perm_dex;
int bdex = 14 + race_table[victim->race]->dex_plus;
if (sysdata.stat_gain <= 1)
mdex = number_range(2,3);
else if (sysdata.stat_gain <= 3)
mdex = number_range(3,5);
else if (sysdata.stat_gain >= 5)
mdex = number_range(6,9);
if (dex == bdex - 4)
mdex *= 2;
if (dex == bdex - 3)
mdex *= 1.7;
if (dex == bdex - 2)
mdex *= 1.5;
if (dex == bdex - 1)
mdex *= 1.2;
if (dex == bdex)
mdex *= 1;
if (dex == bdex + 1)
mdex *= .85;
if (dex == bdex + 2)
mdex *= .7;
if (dex == bdex + 3)
mdex *= .6;
if (dex == bdex + 4)
mdex *= .4;
if (dex == bdex + 5)
mdex *= .3;
if (dex == bdex + 6)
mdex *= .275;
if (dex == bdex + 7)
mdex *= .25;
if (dex == bdex + 8)
mdex *= .225;
if (dex > bdex + 8) //Base + 8 should be the max unless you screwed it up
mdex = 0;
else
{
if (mdex == 0)
mdex = 1;
}
if (victim->perm_dex == (14 + race_table[victim->race]->dex_plus + race_table[victim->race]->dex_range + get_talent_increase(victim, 2)) && victim->pcdata->per_dex >= 3000 && mdex > 0)
mdex = 0;
victim->pcdata->per_dex += mdex;
if (victim->pcdata->per_dex > 10000)
{
victim->perm_dex++;
send_to_char("&G***************************************\n\r", victim);
send_to_char("&G*****You Gain 1 Point of Dexterity*****\n\r", victim);
send_to_char("&G***************************************\n\r", victim);
victim->pcdata->per_dex = 0;
}
}
if (victim->position == POS_EVASIVE || (victim->position == POS_DEFENSIVE && mastery >= 3)
|| (victim->position == POS_FIGHTING && mastery >= 4) || IS_NPC(victim))
{
if (!IS_NPC(victim) && !IS_SET(victim->pcdata->flags, PCFLAG_GAG))
act(AT_SKILL, "You parry $n's attack.", ch, NULL, victim, TO_VICT);
if (!IS_NPC(ch) && !IS_SET(ch->pcdata->flags, PCFLAG_GAG)) /* SB */
act(AT_SKILL, "$N parries your attack.", ch, NULL, victim, TO_CHAR);
// act(AT_SKILL, "$N parries $n's attack.", ch, NULL, victim, TO_NOTVICT);
learn_from_success(victim, gsn_parry, ch);
return TRUE; //No damage
}
else
{
if (!IS_NPC(victim) && !IS_SET(victim->pcdata->flags, PCFLAG_GAG))
act(AT_SKILL, "You partially deflect $n's attack with a parry.", ch, NULL, victim, TO_VICT);
if (!IS_NPC(ch) && !IS_SET(ch->pcdata->flags, PCFLAG_GAG)) /* SB */
act(AT_SKILL, "$N partially deflect your attack with a parry.", ch, NULL, victim, TO_CHAR);
// act(AT_SKILL, "$N partially deflect $n's attack with a parry.", ch, NULL, victim, TO_NOTVICT);
learn_from_success(victim, gsn_parry, ch);
}
if (victim->position == POS_EVASIVE)
return TRUE; //No damage
if (victim->position == POS_DEFENSIVE)
{
if (mastery == 1)
return 10; // 10 percent damage
else if (mastery == 2)
return 5;
else
return TRUE;
}
if (victim->position == POS_FIGHTING)
{
if (mastery == 1)
return 20;
else if (mastery == 2)
return 15;
else if (mastery == 3)
return 10;
else
return TRUE;
}
if (victim->position == POS_AGGRESSIVE)
{
if (mastery == 1)
return 30;
else if (mastery == 2)
return 25;
else if (mastery == 3)
return 20;
else
return 15;
}
if (victim->position == POS_BERSERK)
{
if (mastery == 1)
return 50;
else if (mastery == 2)
return 45;
else if (mastery == 3)
return 40;
else
return 35;
}
}
else
return FALSE;
return FALSE;
}
/*
* Check for dodge.
*/
bool check_dodge(CHAR_DATA * ch, CHAR_DATA * victim, int limb)
{
int percent;
int mdex;
int bdex;
int dex = victim->perm_dex;
int empty = 0;
sh_int mastery, level;
OBJ_DATA *armor;
int limbadd = 0;
int hobbit;
int tlevel;
int diff;
mastery = MASTERED(victim, gsn_dodge);
level = POINT_LEVEL(LEARNED(victim, gsn_dodge), MASTERED(victim, gsn_dodge));
tlevel = POINT_LEVEL(LEARNED(victim, gsn_tumble), MASTERED(victim, gsn_tumble));
if (!IS_AWAKE(victim))
return FALSE;
if (IS_NPC(victim))
{
int chance = 0;
if (!xIS_SET(victim->defenses, DFND_DODGE))
return FALSE;
chance = URANGE(10, 15 + ((get_curr_dex(victim) - 14)*3), 35);
if (number_range(1, 100) >= chance)
return FALSE;
else
{
if (!IS_NPC(victim) && !IS_SET(victim->pcdata->flags, PCFLAG_GAG))
act(AT_SKILL, "You dodge $n's attack.", ch, NULL, victim, TO_VICT);
if (!IS_NPC(ch) && !IS_SET(ch->pcdata->flags, PCFLAG_GAG))
act(AT_SKILL, "$N dodges your attack.", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$N dodges $n's attack.", ch, NULL, victim, TO_NOTVICT);
return TRUE;
}
}
if (!IS_NPC(victim) && victim->pcdata->learned[gsn_dodge] == 0)
level = 0;
if (limb == LM_HEAD)
limbadd = 10;
else if (limb == LM_NECK)
limbadd = 15;
else if (limb == LM_RARM || limb == LM_LARM)
limbadd = 7;
else if (limb == LM_RLEG || limb == LM_LLEG)
limbadd = 3;
else if (limb == LM_BODY)
limbadd = -5;
percent = 10 + URANGE(-12, (get_curr_dex(victim) - 15) * 2, 14) + URANGE(-6, get_curr_lck(victim) - 14, 7);
percent += limbadd;
diff = percent;
if (victim->race == RACE_HOBBIT)
hobbit = 2;
else
hobbit = 0;
if ((armor = get_eq_char(victim, WEAR_HEAD)) == NULL)
{
empty++;
percent += 3;
}
else
{
if (armor->value[5] == 0)
{
if (armor->pIndexData->value[5] == 0)
{
bug("%s on %s has an invalid v5 for armorsize", armor->name, victim->name);
send_to_char("There is some problem with your armor, tell an immortal.\n\r", victim);
}
else
armor->value[5] = armor->pIndexData->value[5];
}
if (armor->value[5] == ASIZE_LEATHER)
percent += 1+hobbit;
else if (armor->value[5] == ASIZE_LIGHT)
percent -= 1-hobbit;
else if (armor->value[5] == ASIZE_MEDIUM)
percent -= 2;
else if (armor->value[5] == ASIZE_HEAVY)
percent -= 4;
else if (armor->value[5] == ASIZE_HEAVIEST)
percent -= 7;
}
if ((armor = get_eq_char(victim, WEAR_NECK)) == NULL)
{
empty++;
percent += 3;
}
else
{
if (armor->value[5] == 0)
{
if (armor->pIndexData->value[5] == 0)
{
bug("%s on %s has an invalid v5 for armorsize", armor->name, victim->name);
send_to_char("There is some problem with your armor, tell an immortal.\n\r", victim);
}
else
armor->value[5] = armor->pIndexData->value[5];
}
if (armor->value[5] == ASIZE_LEATHER)
percent += 1+hobbit;
else if (armor->value[5] == ASIZE_LIGHT)
percent -= 1-hobbit;
else if (armor->value[5] == ASIZE_MEDIUM)
percent -= 2;
else if (armor->value[5] == ASIZE_HEAVY)
percent -= 4;
else if (armor->value[5] == ASIZE_HEAVIEST)
percent -= 6;
}
if ((armor = get_eq_char(victim, WEAR_ARM_R)) == NULL)
{
empty++;
percent += 3;
}
else
{
if (armor->value[5] == 0)
{
if (armor->pIndexData->value[5] == 0)
{
bug("%s on %s has an invalid v5 for armorsize", armor->name, victim->name);
send_to_char("There is some problem with your armor, tell an immortal.\n\r", victim);
}
else
armor->value[5] = armor->pIndexData->value[5];
}
if (armor->value[5] == ASIZE_LEATHER)
percent += 1+hobbit;
else if (armor->value[5] == ASIZE_LIGHT)
percent -= 1-hobbit;
else if (armor->value[5] == ASIZE_MEDIUM)
percent -= 3;
else if (armor->value[5] == ASIZE_HEAVY)
percent -= 5;
else if (armor->value[5] == ASIZE_HEAVIEST)
percent -= 8;
}
if ((armor = get_eq_char(victim, WEAR_ARM_L)) == NULL)
{
empty++;
percent += 3;
}
else
{
if (armor->value[5] == 0)
{
if (armor->pIndexData->value[5] == 0)
{
bug("%s on %s has an invalid v5 for armorsize", armor->name, victim->name);
send_to_char("There is some problem with your armor, tell an immortal.\n\r", victim);
}
else
armor->value[5] = armor->pIndexData->value[5];
}
if (armor->value[5] == ASIZE_LEATHER)
percent += 1+hobbit;
else if (armor->value[5] == ASIZE_LIGHT)
percent -= 1-hobbit;
else if (armor->value[5] == ASIZE_MEDIUM)
percent -= 3;
else if (armor->value[5] == ASIZE_HEAVY)
percent -= 5;
else if (armor->value[5] == ASIZE_HEAVIEST)
percent -= 8;
}
if ((armor = get_eq_char(victim, WEAR_LEG_R)) == NULL)
{
empty++;
percent += 3;
}
else
{
if (armor->value[5] == 0)
{
if (armor->pIndexData->value[5] == 0)
{
bug("%s on %s has an invalid v5 for armorsize", armor->name, victim->name);
send_to_char("There is some problem with your armor, tell an immortal.\n\r", victim);
}
else
armor->value[5] = armor->pIndexData->value[5];
}
if (armor->value[5] == ASIZE_LEATHER)
percent += 1+hobbit;
else if (armor->value[5] == ASIZE_LIGHT)
percent -= 1-hobbit;
else if (armor->value[5] == ASIZE_MEDIUM)
percent -= 3;
else if (armor->value[5] == ASIZE_HEAVY)
percent -= 6;
else if (armor->value[5] == ASIZE_HEAVIEST)
percent -= 9;
}
if ((armor = get_eq_char(victim, WEAR_LEG_L)) == NULL)
{
empty++;
percent += 3;
}
else
{
if (armor->value[5] == 0)
{
if (armor->pIndexData->value[5] == 0)
{
bug("%s on %s has an invalid v5 for armorsize", armor->name, victim->name);
send_to_char("There is some problem with your armor, tell an immortal.\n\r", victim);
}
else
armor->value[5] = armor->pIndexData->value[5];
}
if (armor->value[5] == ASIZE_LEATHER)
percent += 1+hobbit;
else if (armor->value[5] == ASIZE_LIGHT)
percent -= 1-hobbit;
else if (armor->value[5] == ASIZE_MEDIUM)
percent -= 3;
else if (armor->value[5] == ASIZE_HEAVY)
percent -= 6;
else if (armor->value[5] == ASIZE_HEAVIEST)
percent -= 9;
}
if ((armor = get_eq_char(victim, WEAR_BODY)) == NULL)
{
empty++;
percent += 5;
}
else
{
if (hobbit > 0)
hobbit+=1;
if (armor->value[5] == 0)
{
if (armor->pIndexData->value[5] == 0)
{
bug("%s on %s has an invalid v5 for armorsize", armor->name, victim->name);
send_to_char("There is some problem with your armor, tell an immortal.\n\r", victim);
}
else
armor->value[5] = armor->pIndexData->value[5];
}
if (armor->value[5] == ASIZE_LEATHER)
percent += 2+hobbit;
else if (armor->value[5] == ASIZE_LIGHT)
percent -= 1-hobbit;
else if (armor->value[5] == ASIZE_MEDIUM)
percent -= 4;
else if (armor->value[5] == ASIZE_HEAVY)
percent -= 8;
else if (armor->value[5] == ASIZE_HEAVIEST)
percent -= 12;
}
diff = percent - diff;
if (diff > 0 && tlevel > 0)
{
percent += 1 + number_range(tlevel/5, tlevel/4);
}
if (!IS_NPC(ch))
{
percent += race_table[ch->race]->dodge_bonus;
}
percent = percent * sysdata.dodge_mod / 100;
if (victim->morph)
percent += victim->morph->dodge;
percent += number_range(level/4, level/3);
percent = URANGE(1, percent, 50);
if ((armor = get_eq_char(victim, WEAR_SHIELD)) != NULL)
{
percent = percent - UMAX(0, (armor->value[2] - 15));
percent = URANGE(1, percent, 75);
}
if (!IS_NPC(victim))
{
if (percent <= 3)
mdex = number_range(-2, -1);
else if (percent <= 7)
mdex = number_range(-1, 0);
else if (percent <= 15)
mdex = number_range(-1, 2);
else if (percent <= 25)
mdex = number_range(1, 2);
else if (percent <= 40)
mdex = number_range(2, 3);
else if (percent <= 60)
mdex = number_range(3, 5);
else if (percent <= 80)
mdex = number_range(5, 7);
else
mdex = number_range(7, 9);
if (sysdata.stat_gain <= 3 && mdex > 0)
mdex = number_range(150*mdex/100, 180*mdex/100);
else if (sysdata.stat_gain >= 5 && mdex > 0)
mdex = number_range(250*mdex/100, 300*mdex/100);
//dex mods
if (mdex > 0)
{
bdex = 14 + race_table[victim->race]->dex_plus;
if (dex == bdex - 4)
mdex *= 2;
if (dex == bdex - 3)
mdex *= 1.7;
if (dex == bdex - 2)
mdex *= 1.5;
if (dex == bdex - 1)
mdex *= 1.2;
if (dex == bdex)
mdex *= 1;
if (dex == bdex + 1)
mdex *= .85;
if (dex == bdex + 2)
mdex *= .7;
if (dex == bdex + 3)
mdex *= .6;
if (dex == bdex + 4)
mdex *= .4;
if (dex == bdex + 5)
mdex *= .3;
if (dex == bdex + 6)
mdex *= .275;
if (dex == bdex + 7)
mdex *= .25;
if (dex == bdex + 8)
mdex *= .225;
if (dex > bdex + 8) //Base + 8 should be the max unless you screwed it up
mdex = 0;
else
{
if (mdex == 0)
mdex = 1;
}
}
else
{
bdex = 14 + race_table[victim->race]->dex_plus;
if (dex == bdex - 4)
mdex = 0;
if (dex == bdex - 3)
mdex *= .3;
if (dex == bdex - 2)
mdex *= .4;
if (dex == bdex - 1)
mdex *= .6;
if (dex == bdex)
mdex *= 1;
if (dex == bdex + 1)
mdex *= 1.2;
if (dex == bdex + 2)
mdex *= 1.4;
if (dex == bdex + 3)
mdex *= 1.6;
if (dex == bdex + 4)
mdex *= 1.8;
if (dex == bdex + 5)
mdex *= 2;
}
if (victim->perm_dex == (14 + race_table[victim->race]->dex_plus + race_table[victim->race]->dex_range + get_talent_increase(victim, 2)) && victim->pcdata->per_dex >= 3000 && mdex > 0)
mdex = 0;
if (victim->perm_dex == (14 + race_table[victim->race]->dex_plus - 5 + race_table[victim->race]->dex_range) && victim->pcdata->per_dex <= 3000 && mdex < 0)
mdex = 0;
victim->pcdata->per_dex += mdex;
if (victim->pcdata->per_dex > 10000)
{
victim->perm_dex++;
send_to_char("&G***************************************\n\r", victim);
send_to_char("&G*****You Gain 1 Point of Dexterity*****\n\r", victim);
send_to_char("&G***************************************\n\r", victim);
victim->pcdata->per_dex = 0;
}
if (victim->pcdata->per_dex < 0)
{
victim->perm_dex--;
send_to_char("&g***************************************\n\r", victim);
send_to_char("&g*****You Lose 1 Point of Dexterity*****\n\r", victim);
send_to_char("&g***************************************\n\r", victim);
victim->pcdata->per_dex = 9999;
}
}
if (xIS_SET(victim->act, PLR_DODGE))
return FALSE;
if (number_range(1, 100) > percent)
return FALSE;
if (diff > 0 && tlevel > 0)
{
if (!IS_NPC(victim) && !IS_SET(victim->pcdata->flags, PCFLAG_GAG))
act(AT_SKILL, "You tumble out of the way of $n's attack.", ch, NULL, victim, TO_VICT);
if (!IS_NPC(ch) && !IS_SET(ch->pcdata->flags, PCFLAG_GAG))
act(AT_SKILL, "$N tumbles away from your attack.", ch, NULL, victim, TO_CHAR);
// act(AT_SKILL, "$N tumbles away from $n's attack.", ch, NULL, victim, TO_NOTVICT);
learn_from_success(victim, gsn_tumble, ch);
}
else
{
if (!IS_NPC(victim) && !IS_SET(victim->pcdata->flags, PCFLAG_GAG))
act(AT_SKILL, "You dodge $n's attack.", ch, NULL, victim, TO_VICT);
if (!IS_NPC(ch) && !IS_SET(ch->pcdata->flags, PCFLAG_GAG))
act(AT_SKILL, "$N dodges your attack.", ch, NULL, victim, TO_CHAR);
// act(AT_SKILL, "$N dodges $n's attack.", ch, NULL, victim, TO_NOTVICT);
}
learn_from_success(victim, gsn_dodge, ch);
return TRUE;
}
void do_poison_weapon(CHAR_DATA * ch, char *argument)
{
OBJ_DATA *obj;
OBJ_DATA *pobj;
OBJ_DATA *wobj;
char arg[MIL];
int percent;
sh_int mastery, level;
mastery = MASTERED(ch, gsn_poison_weapon) * 20;
mastery = mastery - 70;
level = POINT_LEVEL(LEARNED(ch, gsn_poison_weapon), MASTERED(ch, gsn_poison_weapon));
if (IS_NPC(ch) || ch->pcdata->ranking[gsn_poison_weapon] <= 0)
{
send_to_char("What do you think you are, a talented thief?\n\r", ch);
return;
}
one_argument(argument, arg);
if (arg[0] == '\0')
{
send_to_char("What are you trying to poison?\n\r", ch);
return;
}
if (ch->fighting)
{
send_to_char("While you're fighting? Nice try.\n\r", ch);
return;
}
if (ms_find_obj(ch))
return;
if (!(obj = get_obj_carry(ch, arg)))
{
send_to_char("You do not have that weapon.\n\r", ch);
return;
}
if (obj->item_type != ITEM_WEAPON)
{
send_to_char("That item is not a weapon.\n\r", ch);
return;
}
if (IS_OBJ_STAT(obj, ITEM_POISONED))
{
send_to_char("That weapon is already poisoned.\n\r", ch);
return;
}
if (IS_OBJ_STAT(obj, ITEM_CLANOBJECT))
{
send_to_char("It doesn't appear to be fashioned of a poisonable material.\n\r", ch);
return;
}
/* Now we have a valid weapon...check to see if we have the powder. */
for (pobj = ch->first_carrying; pobj; pobj = pobj->next_content)
{
if (pobj->pIndexData->vnum == OBJ_VNUM_BLACK_POWDER)
break;
}
if (!pobj)
{
send_to_char("You do not have the black poison powder.\n\r", ch);
return;
}
/* Okay, we have the powder...do we have water? */
for (wobj = ch->first_carrying; wobj; wobj = wobj->next_content)
{
if (wobj->item_type == ITEM_DRINK_CON && wobj->value[1] > 0 && wobj->value[2] == 0)
break;
}
if (!wobj)
{
send_to_char("You have no water to mix with the powder.\n\r", ch);
return;
}
if (!ch->fighting)
WAIT_STATE(ch, skill_table[gsn_poison_weapon]->beats*2);
else
ch->fight_timer = get_btimer(ch, gsn_poison_weapon, NULL);
percent = (number_percent() - ((get_curr_wis(ch) - 15)*5) - ((get_curr_dex(ch) - 15)*5) - ((get_curr_lck(ch) - 14)*5) - mastery);
/* Check the skill percentage */
separate_obj(pobj);
separate_obj(wobj);
if (!can_use_skill(ch, percent, gsn_poison_weapon))
{
set_char_color(AT_RED, ch);
send_to_char("You failed and spill some on yourself. Ouch!\n\r", ch);
set_char_color(AT_GREY, ch);
damage(ch, ch, 3+level/2, gsn_poison_weapon, 0, -1);
if (number_range(1, 5) == 1) //20 percent
{
AFFECT_DATA af;
af.type = gsn_poison;
af.duration = 60;
af.location = APPLY_STR;
af.modifier = -1;
af.bitvector = meb(AFF_POISON);
affect_join(ch, &af);
ch->mental_state = URANGE(20, (ch->mental_state + 2), 100);
send_to_char("You feel your skin start to swell, you have poisoned yourself!!!!!\n\r", ch);
}
act(AT_RED, "$n spills the poison all over!", ch, NULL, NULL, TO_ROOM);
extract_obj(pobj);
extract_obj(wobj);
learn_from_failure(ch, gsn_poison_weapon, NULL);
return;
}
separate_obj(obj);
/* Well, I'm tired of waiting. Are you? */
act(AT_RED, "You mix $p in $P, creating a deadly poison!", ch, pobj, wobj, TO_CHAR);
act(AT_RED, "$n mixes $p in $P, creating a deadly poison!", ch, pobj, wobj, TO_ROOM);
act(AT_GREEN, "You pour the poison over $p, which glistens wickedly!", ch, obj, NULL, TO_CHAR);
act(AT_GREEN, "$n pours the poison over $p, which glistens wickedly!", ch, obj, NULL, TO_ROOM);
xSET_BIT(obj->extra_flags, ITEM_POISONED);
obj->cost *= 2;
/* Set an object timer. Don't want proliferation of poisoned weapons */
obj->timer = 5+level*2;
if (IS_OBJ_STAT(obj, ITEM_GLOW))
obj->timer *= 1.3;
if (IS_OBJ_STAT(obj, ITEM_MAGIC))
obj->timer *= 1.5;
/* WHAT? All of that, just for that one bit? How lame. ;) */
act(AT_BLUE, "The remainder of the poison eats through $p.", ch, wobj, NULL, TO_CHAR);
act(AT_BLUE, "The remainder of the poison eats through $p.", ch, wobj, NULL, TO_ROOM);
extract_obj(pobj);
extract_obj(wobj);
learn_from_success(ch, gsn_poison_weapon, NULL);
return;
}
void do_manatap(CHAR_DATA *ch, char *argument)
{
int level;
int mana;
int maxgain;
level = POINT_LEVEL(LEARNED(ch, gsn_manatap), MASTERED(ch, gsn_manatap));
maxgain = UMAX(ch->max_mana * level / 120, level*35/10);
if (IS_NPC(ch))
return;
if (ch->position != POS_STANDING && ch->position != POS_SITTING && ch->position != POS_RESTING && ch->position != POS_MOUNTED)
{
send_to_char("You can only use this while standing, sitting, mounted, or resting.\n\r", ch);
return;
}
if (IS_NPC(ch) || ch->pcdata->ranking[gsn_manatap] <= 0)
{
send_to_char("A skill such as this requires more magical ability than that of your skills.\n\r", ch);
return;
}
if (ch->mana < ch->max_mana)
{
send_to_char("You can only tap mana when your mana is full.\n\r", ch);
return;
}
if (ch->mana >= ch->max_mana + maxgain)
{
send_to_char("Your mana is maxed out, you cannot tap any more.\n\r", ch);
return;
}
if (number_range(1, 100) <= (40+level/2))
{
act(AT_MAGIC, "You tap your surroundings and gain additional mana.", ch, NULL, NULL, TO_CHAR);
act(AT_MAGIC, "$n taps the surroundings area and gains additional mana.", ch, NULL, NULL, TO_CANSEE);
mana = UMAX(5, level/2);
if (ch->mana + mana >= (ch->max_mana + maxgain))
mana = ch->max_mana + maxgain - ch->mana;
ch->mana+=mana;
learn_from_success(ch, gsn_manatap, NULL);
}
else
{
act(AT_MAGIC, "You attempt to tap your surroundings for additional mana but fail.", ch, NULL, NULL, TO_CHAR);
act(AT_MAGIC, "$n attempts to tap the surrounding area for additional mana but fails.", ch, NULL, NULL, TO_CANSEE);
learn_from_failure(ch, gsn_manatap, NULL);
}
WAIT_STATE(ch, skill_table[gsn_manatap]->beats*2);
}
void do_scribe(CHAR_DATA * ch, char *argument)
{
OBJ_DATA *scroll;
int sn;
char buf1[MSL];
char buf2[MSL];
char buf3[MSL];
int mana;
sh_int mastery;
int fvnum;
int points;
int chance;
int strength;
points = POINT_LEVEL(LEARNED(ch, gsn_scribe), MASTERED(ch, gsn_scribe));
mastery = MASTERED(ch, gsn_scribe) * 25;
mastery = mastery - 100;
if (IS_NPC(ch))
return;
if (IS_NPC(ch) || ch->pcdata->ranking[gsn_scribe] <= 0)
{
send_to_char("A skill such as this requires more magical ability than that of your skills.\n\r", ch);
return;
}
if (argument[0] == '\0' || !str_cmp(argument, ""))
{
send_to_char("Scribe what?\n\r", ch);
return;
}
if (ms_find_obj(ch))
return;
if ((sn = find_spell(ch, argument, TRUE)) < 0)
{
send_to_char("You have not learned that spell.\n\r", ch);
return;
}
if (skill_table[sn]->spell_fun == spell_null)
{
send_to_char("That's not a spell!\n\r", ch);
return;
}
if (SPELL_FLAG(skill_table[sn], SF_NOSCRIBE))
{
send_to_char("You cannot scribe that spell.\n\r", ch);
return;
}
mana = IS_NPC(ch) ? 0 : skill_table[sn]->min_mana;
if (MASTERED(ch, gsn_scribe) == 6)
mana *= 3;
else if (MASTERED(ch, gsn_scribe) == 5)
mana = mana * 7 / 2;
else if (MASTERED(ch, gsn_scribe) == 4)
mana *= 4;
else
mana *= 5;
if (!IS_NPC(ch) && ch->mana < mana)
{
send_to_char("You don't have enough mana.\n\r", ch);
return;
}
if (MASTERED(ch, sn) < 4)
{
send_to_char("You can only scribe a spell that you have mastered.\n\r", ch);
return;
}
if (skill_table[sn]->masterydiff[0] == 5 && MASTERED(ch, gsn_scribe) < 6)
{
send_to_char("You can only scribe a Tier 5 spell if you have a mastery of flawless in scribe.\n\r", ch);
return;
}
if (skill_table[sn]->masterydiff[0] == 4 && MASTERED(ch, gsn_scribe) < 5)
{
send_to_char("You can only scribe a Tier 4 spell if you have a mastery of elite in scribe.\n\r", ch);
return;
}
if (skill_table[sn]->masterydiff[0] == 3 && MASTERED(ch, gsn_scribe) < 4)
{
send_to_char("You can only scribe a Tier 3 spell if you have mastered scribe.\n\r", ch);
return;
}
if (skill_table[sn]->masterydiff[0] == 2 && MASTERED(ch, gsn_scribe) < 3)
{
send_to_char("You can only scribe a Tier 2 spell if you at least an expert scribe.\n\r", ch);
return;
}
if (skill_table[sn]->masterydiff[0] == 3 || skill_table[sn]->masterydiff[0] == 4 || skill_table[sn]->masterydiff[0] == 5)
fvnum = OBJ_VNUM_SCROLL_SCRIBING_TIER3;
else if (skill_table[sn]->masterydiff[0] == 2)
fvnum = OBJ_VNUM_SCROLL_SCRIBING_TIER2;
else
fvnum = OBJ_VNUM_SCROLL_SCRIBING;
for (scroll = ch->first_carrying; scroll; scroll = scroll->next_content)
{
if (scroll->pIndexData->vnum == fvnum && scroll->value[1] == -1)
break;
}
if (!scroll)
{
send_to_char("You must have a blank scroll in your inventory to scribe it.\n\r", ch);
return;
}
if ((scroll->value[1] != -1) && (scroll->pIndexData->vnum == fvnum))
{
send_to_char("That scroll has already been inscribed.\n\r", ch);
return;
}
if (!process_spell_components(ch, sn))
{
learn_from_failure(ch, gsn_scribe, NULL);
ch->mana -= (mana / 2);
gain_mana_per(ch, NULL, mana/2);
return;
}
chance = 15 + (points * 123 / 100);
chance = URANGE(15, chance, 95);
if (number_range(1, 100) > chance)
{
set_char_color(AT_MAGIC, ch);
send_to_char("You failed.\n\r", ch);
learn_from_failure(ch, gsn_scribe, NULL);
ch->mana -= (mana / 2);
gain_mana_per(ch, NULL, mana/2);
return;
}
strength = SPOWER_MIN + (points/10) - ((skill_table[sn]->masterydiff[0]*2)-2);
strength = URANGE(SPOWER_MIN, strength, SPOWER_GREATEST);
chance = 1+ (points/10) + UMIN(5, get_curr_lck(ch)-14);
if (number_range(1, 100) <= chance)
{
strength = SPOWER_GREATEST;
send_to_char("&w&WYour magical blessing is so pure that you create a very powerful scroll!\n\r", ch);
}
scroll->value[5] = strength;
scroll->value[1] = sn;
scroll->value[0] = ch->level;
sprintf(buf1, "%s scroll", skill_table[sn]->name);
STRFREE(scroll->short_descr);
scroll->short_descr = STRALLOC(aoran(buf1));
sprintf(buf2, "A glowing scroll inscribed '%s' lies in the dust.", skill_table[sn]->name);
STRFREE(scroll->description);
scroll->description = STRALLOC(buf2);
sprintf(buf3, "scroll scribing %s", skill_table[sn]->name);
STRFREE(scroll->name);
scroll->name = STRALLOC(buf3);
act(AT_MAGIC, "$n magically scribes $p.", ch, scroll, NULL, TO_ROOM);
act(AT_MAGIC, "You magically scribe $p.", ch, scroll, NULL, TO_CHAR);
learn_from_success(ch, gsn_scribe, NULL);
ch->mana -= mana;
gain_mana_per(ch, NULL, mana);
}
void do_brew(CHAR_DATA * ch, char *argument)
{
OBJ_DATA *potion;
OBJ_DATA *fire;
int sn;
char buf1[MSL];
char buf2[MSL];
char buf3[MSL];
int mana;
sh_int mastery;
bool found;
int fvnum;
int points;
int chance;
int strength;
points = POINT_LEVEL(LEARNED(ch, gsn_brew), MASTERED(ch, gsn_brew));
if (IS_NPC(ch))
return;
if (IS_NPC(ch) || ch->pcdata->ranking[gsn_brew] <= 0)
{
send_to_char("A skill such as this requires more magical ability than that of your abilities.\n\r", ch);
return;
}
if (argument[0] == '\0' || !str_cmp(argument, ""))
{
send_to_char("Brew what?\n\r", ch);
return;
}
if (ms_find_obj(ch))
return;
if ((sn = find_spell(ch, argument, TRUE)) < 0)
{
send_to_char("You have not learned that spell.\n\r", ch);
return;
}
if (skill_table[sn]->spell_fun == spell_null)
{
send_to_char("That's not a spell!\n\r", ch);
return;
}
if (SPELL_FLAG(skill_table[sn], SF_NOBREW))
{
send_to_char("You cannot brew that spell.\n\r", ch);
return;
}
mana = IS_NPC(ch) ? 0 : skill_table[sn]->min_mana;
mastery = MASTERED(ch, gsn_brew);
if (mastery == 6)
mana *= 2;
if (mastery == 5)
mana = mana * 5 / 2;
if (mastery == 4)
mana *= 3;
else
mana *= 4;
if (!IS_NPC(ch) && ch->mana < mana)
{
send_to_char("You don't have enough mana.\n\r", ch);
return;
}
found = FALSE;
for (fire = ch->in_room->first_content; fire; fire = fire->next_content)
{
if (fire->item_type == ITEM_FIRE)
{
found = TRUE;
break;
}
}
/* Masters don't need a fire */
if (!found && mastery != 4)
{
send_to_char("There must be a fire in the room to brew a potion.\n\r", ch);
return;
}
if (MASTERED(ch, sn) < 4)
{
send_to_char("You can only brew a spell that you have mastered.\n\r", ch);
return;
}
if (skill_table[sn]->masterydiff[0] == 5 && MASTERED(ch, gsn_brew) < 6)
{
send_to_char("You can only brew a Tier 3 spell if you have mastered brew.\n\r", ch);
return;
}
if (skill_table[sn]->masterydiff[0] == 4 && MASTERED(ch, gsn_brew) < 5)
{
send_to_char("You can only brew a Tier 3 spell if you have mastered brew.\n\r", ch);
return;
}
if (skill_table[sn]->masterydiff[0] == 3 && MASTERED(ch, gsn_brew) < 4)
{
send_to_char("You can only brew a Tier 3 spell if you have mastered brew.\n\r", ch);
return;
}
if (skill_table[sn]->masterydiff[0] == 2 && MASTERED(ch, gsn_brew) < 3)
{
send_to_char("You can only brew a Tier 2 spell if you at least an expert brewer.\n\r", ch);
return;
}
if (skill_table[sn]->masterydiff[0] == 3 || skill_table[sn]->masterydiff[0] == 4 || skill_table[sn]->masterydiff[0] == 5)
fvnum = OBJ_VNUM_FLASK_BREWING_TIER3;
else if (skill_table[sn]->masterydiff[0] == 2)
fvnum = OBJ_VNUM_FLASK_BREWING_TIER2;
else
fvnum = OBJ_VNUM_FLASK_BREWING;
for (potion = ch->first_carrying; potion; potion = potion->next_content)
{
if (potion->pIndexData->vnum == fvnum && potion->value[1] == -1)
break;
}
if (!potion)
{
send_to_char("You must have an empty flask in your inventory to brew a potion.\n\r", ch);
return;
}
mastery = mastery * 30;
mastery = mastery - 120;
chance = 15 + (points * 123 / 100);
chance = URANGE(15, chance, 95);
if ((potion->value[1] != -1) && (potion->pIndexData->vnum == fvnum))
{
send_to_char("That's not an empty flask.\n\r", ch);
return;
}
if (!process_spell_components(ch, sn))
{
learn_from_failure(ch, gsn_brew, NULL);
ch->mana -= (mana / 2);
gain_mana_per(ch, NULL, mana/2);
return;
}
if (number_range(1, 100) > chance)
{
set_char_color(AT_MAGIC, ch);
send_to_char("You failed.\n\r", ch);
learn_from_failure(ch, gsn_brew, NULL);
ch->mana -= (mana / 2);
gain_mana_per(ch, NULL, mana/2);
return;
}
strength = SPOWER_MIN + (points/10) - ((skill_table[sn]->masterydiff[0]*2)-2);
strength = URANGE(SPOWER_MIN, strength, SPOWER_GREATEST);
chance = 1+ (points/10) + UMIN(5, get_curr_lck(ch)-14);
if (number_range(1, 100) <= chance)
{
strength = SPOWER_GREATEST;
send_to_char("&w&WYour magical blessing is so pure that you create a very powerful potion!\n\r", ch);
}
potion->value[5] = strength;
potion->value[1] = sn;
potion->value[0] = 0;
sprintf(buf1, "%s potion", skill_table[sn]->name);
STRFREE(potion->short_descr);
potion->short_descr = STRALLOC(aoran(buf1));
sprintf(buf2, "A strange potion labelled '%s' sizzles in a glass flask.", skill_table[sn]->name);
STRFREE(potion->description);
potion->description = STRALLOC(buf2);
sprintf(buf3, "flask potion %s", skill_table[sn]->name);
STRFREE(potion->name);
potion->name = STRALLOC(buf3);
act(AT_MAGIC, "$n brews up $p.", ch, potion, NULL, TO_ROOM);
act(AT_MAGIC, "You brew up $p.", ch, potion, NULL, TO_CHAR);
learn_from_success(ch, gsn_brew, NULL);
ch->mana -= mana;
gain_mana_per(ch, NULL, mana);
}
bool check_grip(CHAR_DATA * ch, CHAR_DATA * victim)
{
int chance = 0;
int percent = 0;
sh_int mastery, level;
mastery = MASTERED(victim, gsn_grip);
level = POINT_LEVEL(LEARNED(victim, gsn_grip), MASTERED(victim, gsn_grip));
if (!IS_AWAKE(victim))
return FALSE;
if (IS_NPC(victim) && !xIS_SET(victim->defenses, DFND_GRIP))
return FALSE;
if (IS_NPC(victim))
chance = URANGE(5, level, 50);
else
{
percent = 10+level*1.5;
chance = (int) (percent / 3 * 2);
}
/* Consider luck+str as a factor */
chance += get_curr_lck(victim) - 14;
chance += get_curr_str(victim) - get_curr_str(ch);
chance = URANGE(5, chance, 85);
if (number_range(1, 100) >= chance)
{
learn_from_failure(victim, gsn_grip, ch);
return FALSE;
}
act(AT_SKILL, "You evade $n's attempt to disarm you.", ch, NULL, victim, TO_VICT);
act(AT_SKILL, "$N holds $S weapon strongly, and is not disarmed.", ch, NULL, victim, TO_CHAR);
learn_from_success(victim, gsn_grip, ch);
return TRUE;
}
//Sort of like shove but a bit more nasty
void do_drive(CHAR_DATA *ch, char *argument)
{
char arg[MIL];
CHAR_DATA *victim;
EXIT_DATA *pexit = NULL;
int dir;
int level;
int nomove = 0;
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't concentrate enough for that.\n\r", ch);
return;
}
argument = one_argument(argument, arg);
if (arg[0] == '\0')
{
send_to_char("Attempt to drive whom?\n\r", ch);
return;
}
if ((victim = get_char_room_new(ch, arg, 1)) == NULL)
{
send_to_char("They aren't here.\n\r", ch);
return;
}
if (victim == ch)
{
send_to_char("Why would you want to do that to yourself?\n\r", ch);
return;
}
if (is_safe(ch, victim))
return;
if (wielding_skill_weapon(ch, 0) != 3 || !get_eq_char(ch, WEAR_WIELD))
{
send_to_char("You have to wielding a polearm to make use of this command..\n\r", ch);
return;
}
if ((dir = get_truedir(argument)) == -1)
{
send_to_char("That is not a valid direction!\n\r", ch);
return;
}
if (!IN_WILDERNESS(ch))
{
ROOM_INDEX_DATA *to_room;
if ((pexit = get_exit(ch->in_room, dir)) == NULL)
{
send_to_char("There's no exit in that direction.\n\r", ch);
return;
}
else if (IS_SET(pexit->exit_info, EX_CLOSED) && (!IS_AFFECTED(victim, AFF_PASS_DOOR) || IS_SET(pexit->exit_info, EX_NOPASSDOOR)))
{
send_to_char("There's no exit in that direction.\n\r", ch);
return;
}
to_room = pexit->to_room;
if (xIS_SET(to_room->room_flags, ROOM_DEATH))
{
send_to_char("You cannot drive someone into a deathtrap!.\n\r", ch);
return;
}
}
level = POINT_LEVEL(LEARNED(ch, gsn_drive), MASTERED(ch, gsn_drive))/2;
level += 35;
if (ch->position == POS_MOUNTED)
level +=15;
if (victim->position == POS_MOUNTED)
level -=10;
level += (get_curr_str(ch) - get_curr_str(victim))*2;
check_attacker(ch, victim);
if (number_range(1, 100) <= level)
{
learn_from_success(ch, gsn_drive, victim);
global_retcode = one_hit(ch, victim, gsn_drive, LM_BODY);
if (char_died(victim))
return;
if (victim->position == POS_MOUNTED)
{
if (victim->mount)
{
xREMOVE_BIT(victim->mount->act, ACT_MOUNTED);
victim->mount = NULL;
}
}
victim->position = POS_STANDING;
if (IN_WILDERNESS(ch))
{
process_movement_value(victim, dir);
if (IN_SAME_ROOM(ch, victim))
nomove = 1;
}
if (!IN_WILDERNESS(ch))
{
if ((move_char(victim, get_exit(ch->in_room, dir), 0)) == rSTOP)
nomove = 1;
}
if (!nomove)
{
act(AT_RED, "You drive into $N with your weapon and roll $M into another room.", ch, NULL, victim, TO_CHAR);
act(AT_RED, "$n drives into you with $s weapon and rolls you into another room.", ch, NULL, victim, TO_VICT);
act(AT_RED, "$n drives into $N and rolls him into another room.", ch, NULL, victim, TO_NOTVICT);
act(AT_RED, "$N drove into $n rolling him into this room with you!", victim, NULL, ch, TO_NOTVICT);
}
else
{
act(AT_RED, "You drive into $N with your weapon but there is nowhere for $M to go that way!", ch, NULL, victim, TO_CHAR);
act(AT_RED, "$n drives into you with your weapon but there is nowhere for you to go that way!", ch, NULL, victim, TO_VICT);
act(AT_RED, "$n drives into $N with your weapon but there is nowhere for $M to go that way!", ch, NULL, victim, TO_NOTVICT);
}
stop_fighting(victim, FALSE);
if (IS_NPC(victim))
victim->fight_timer = 2 + MASTERED(ch, gsn_drive);
else
WAIT_STATE(victim, 4 + MASTERED(ch, gsn_drive)*2);
}
else
{
learn_from_failure(ch, gsn_drive, victim);
act(AT_RED, "You drive into $N but $E refuses to budge.", ch, NULL, victim, TO_CHAR);
act(AT_RED, "$n drives into you but you refuse to budge.", ch, NULL, victim, TO_VICT);
act(AT_RED, "$n drives into $N but $E refuses to budge.", ch, NULL, victim, TO_NOTVICT);
global_retcode = one_hit(ch, victim, gsn_drive, LM_BODY);
return;
}
}
//pretty much is do_fire but with a room check/gsn addition
void do_perfectshot(CHAR_DATA *ch, char *argument)
{
char arg[MIL];
CHAR_DATA *victim = NULL;
OBJ_DATA *arrow;
OBJ_DATA *bow;
if ((bow = get_eq_char(ch, WEAR_MISSILE_WIELD)) == NULL)
{
send_to_char("But you are not wielding a missile weapon!!\n\r", ch);
return;
}
one_argument(argument, arg);
if (arg[0] == '\0' && ch->fighting == NULL)
{
send_to_char("Perform a perfect shot at whom or what?\n\r", ch);
return;
}
if (!str_cmp(arg, "none") || !str_cmp(arg, "self") || victim == ch)
{
send_to_char("How exactly did you plan on firing at yourself?\n\r", ch);
return;
}
if ((arrow = get_eq_char(ch, WEAR_NOCKED)) == NULL)
{
send_to_char("You are not holding a projectile!\n\r", ch);
return;
}
if (arrow->item_type != ITEM_PROJECTILE)
{
send_to_char("You are not holding a projectile!\n\r", ch);
return;
}
if (!str_cmp(arg, "target"))
{
if (ch->pcdata->aimtarget == NULL)
{
send_to_char("Your target does not exist anymore, sorry.\n\r", ch);
return;
}
if (!IN_WILDERNESS(ch))
{
send_to_char("Can only fire at a target out in the Wilderness.\n\r", ch);
return;
}
victim = ch->pcdata->aimtarget;
}
else if (arg[0] == '\0')
{
if (ch->fighting == NULL)
{
send_to_char("Your target does not seem to exist anymore.\n\r", ch);
return;
}
victim = ch->fighting->who;
}
else if ((victim = get_char_room_new(ch, arg, 1)) == NULL)
{
send_to_char("They aren't here.\n\r", ch);
return;
}
if (!IN_SAME_ROOM(ch, victim))
{
send_to_char("You can only use this command if you are in the same room as the target!\n\r", ch);
return;
}
if (bow->value[7] != arrow->value[7])
{
char *msg = "You have nothing to fire...\n\r";
send_to_char(msg, ch);
return;
}
/* Add wait state to fire for pkill, etc... */
ch->fight_timer = get_btimer(ch, 1000, NULL);
/* handle the ranged attack */
learn_from_success(ch, gsn_perfect_shot, victim);
ranged_attack(ch, argument, bow, arrow, gsn_perfect_shot, 1);
return;
}
void do_deshield(CHAR_DATA *ch, char *argument)
{
char arg[MIL];
CHAR_DATA *victim;
OBJ_DATA *shield;
int level;
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't concentrate enough for that.\n\r", ch);
return;
}
one_argument(argument, arg);
if (ch->mount)
{
send_to_char("You can't deshield an individual while mounted.\n\r", ch);
return;
}
if (arg[0] == '\0')
{
send_to_char("Attempt to deshield the shield of whom?\n\r", ch);
return;
}
if ((victim = get_char_room_new(ch, arg, 1)) == NULL)
{
send_to_char("They aren't here.\n\r", ch);
return;
}
if (victim == ch)
{
send_to_char("Why would you want to do that to yourself?\n\r", ch);
return;
}
if (is_safe(ch, victim))
return;
if (wielding_skill_weapon(ch, 0) != 5 || !get_eq_char(ch, WEAR_WIELD))
{
send_to_char("You have to wielding a staff to make use of this command..\n\r", ch);
return;
}
if ((shield = get_eq_char(victim, WEAR_SHIELD)) == NULL)
{
send_to_char("Your target is not holding a shield.\n\r", ch);
return;
}
level = POINT_LEVEL(LEARNED(ch, gsn_deshield), MASTERED(ch, gsn_deshield))*3/2;
if (!victim->fighting) //If you aren't expecting it....
level+=50;
level += (get_curr_str(ch) - 14)/2;
level += get_curr_dex(ch) - get_curr_dex(victim)*3;
check_attacker(ch, victim);
if (number_range(1, 1000) <= level)
{
learn_from_success(ch, gsn_deshield, victim);
ch->fight_timer = get_btimer(ch, gsn_deshield, NULL);
act(AT_RED, "You lunge at $N's shield and manage to knock it out of $S grasp!", ch, NULL, victim, TO_CHAR);
act(AT_RED, "$n lunges at your shield and manages to knock it out of your grasp!", ch, NULL, victim, TO_VICT);
act(AT_RED, "$n lunges at $N's shield and manages to knock it out of $S grasp!", ch, NULL, victim, TO_NOTVICT);
if ((!IS_NPC(victim) && victim->pcdata->quest && victim->pcdata->quest->questarea == victim->in_room->area)
|| (IS_OBJ_STAT(shield, ITEM_NOGIVE)) || (IS_OBJ_STAT(shield, ITEM_NODROP)))
{
unequip_char(victim, shield);
shield->wear_loc = -1;
}
else
{
unequip_char(victim, shield);
shield->wear_loc = -1;
obj_from_char(shield);
obj_to_room(shield, victim->in_room, victim);
}
if (!victim->fighting && IS_NPC(victim))
one_hit(victim, ch, TYPE_HIT, LM_BODY);
}
else
{
learn_from_failure(ch, gsn_deshield, victim);
ch->fight_timer = get_btimer(ch, gsn_deshield, NULL);
act(AT_RED, "You lunge at $N's shield, but cannot manage to knock it out of $S grasp!", ch, NULL, victim, TO_CHAR);
act(AT_RED, "$n lunges at your shield, but cannot manage to knock it out of your grasp!", ch, NULL, victim, TO_VICT);
act(AT_RED, "$n lunges at $N's shield, but cannot manage to knock it out of $S grasp!", ch, NULL, victim, TO_NOTVICT);
if (!victim->fighting && IS_NPC(victim))
one_hit(victim, ch, TYPE_HIT, LM_BODY);
}
return;
}
void do_weaponbreak(CHAR_DATA *ch, char *argument)
{
char arg[MIL];
CHAR_DATA *victim;
OBJ_DATA *wield;
OBJ_DATA *awield;
int level;
int percent;
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't concentrate enough for that.\n\r", ch);
return;
}
one_argument(argument, arg);
if (ch->mount)
{
send_to_char("You can't weaponbreak while mounted.\n\r", ch);
return;
}
if (arg[0] == '\0')
{
send_to_char("Attempt to break the weapon of whom?\n\r", ch);
return;
}
if ((victim = get_char_room_new(ch, arg, 1)) == NULL)
{
send_to_char("They aren't here.\n\r", ch);
return;
}
if (victim == ch)
{
send_to_char("Why would you want to do that to yourself?\n\r", ch);
return;
}
if (is_safe(ch, victim))
return;
if (wielding_skill_weapon(ch, 0) != 4 || !get_eq_char(ch, WEAR_WIELD))
{
send_to_char("You have to wielding a blunt weapon to make use of this command..\n\r", ch);
return;
}
if ((wield = get_eq_char(victim, WEAR_WIELD)) == NULL)
{
send_to_char("Your target is not wielding a weapon.\n\r", ch);
return;
}
level = POINT_LEVEL(LEARNED(ch, gsn_weaponbreak), MASTERED(ch, gsn_weaponbreak));
if (!victim->fighting)
level+=15;
level += (get_curr_str(ch) - 14);
check_attacker(ch, victim);
percent = 200 + level*5;
//first attempt to snap it in half, slight chance of execution compared to actual damage
if (number_range(1, 10000) <= percent)
{
learn_from_success(ch, gsn_weaponbreak, victim);
ch->fight_timer = get_btimer(ch, gsn_weaponbreak, NULL);
act(AT_RED, "You swing wildly at $N's weapon and snap it into two!", ch, NULL, victim, TO_CHAR);
act(AT_RED, "$n swings wildly at your weapon and snaps it into two!", ch, NULL, victim, TO_VICT);
act(AT_RED, "$n swings wildly at $N's weapon and snaps it into two!", ch, NULL, victim, TO_NOTVICT);
make_scraps(wield, victim);
if ((wield =get_eq_char(victim, WEAR_DUAL_WIELD)) != NULL)
{
wield->wear_loc = WEAR_WIELD;
}
if (!victim->fighting && IS_NPC(victim))
one_hit(victim, ch, TYPE_HIT, LM_BODY);
}
level+= 10;
if (number_range(1, 100) <= level/3*2)
{
int sdiff;
int dam;
learn_from_success(ch, gsn_weaponbreak, victim);
ch->fight_timer = get_btimer(ch, gsn_weaponbreak, NULL);
act(AT_RED, "You swing wildly at $N's weapon and manage only to damage it!", ch, NULL, victim, TO_CHAR);
act(AT_RED, "$n swings wildly at your weapon and manages only to damage it!", ch, NULL, victim, TO_VICT);
act(AT_RED, "$n swings wildly at $N's weapon and manages only to damage it!!", ch, NULL, victim, TO_NOTVICT);
awield = get_eq_char(ch, WEAR_WIELD);
sdiff = awield->value[3] - wield->value[3];
dam = URANGE(20, level*10 + sdiff*50, 1000);
damage_obj(wield, ch, 0, dam);
if (!victim->fighting && IS_NPC(victim))
one_hit(victim, ch, TYPE_HIT, LM_BODY);
}
else
{
learn_from_failure(ch, gsn_weaponbreak, victim);
ch->fight_timer = get_btimer(ch, gsn_weaponbreak, NULL);
act(AT_RED, "You swing wildly at $N's weapon and miss!", ch, NULL, victim, TO_CHAR);
act(AT_RED, "$n swings wildly at your weapon and misses!", ch, NULL, victim, TO_VICT);
act(AT_RED, "$n swings wildly at $N's weapon and misses!", ch, NULL, victim, TO_NOTVICT);
if (!victim->fighting && IS_NPC(victim))
one_hit(victim, ch, TYPE_HIT, LM_BODY);
}
return;
}
void do_powerslice(CHAR_DATA *ch, char *argument)
{
char arg[MIL];
CHAR_DATA *victim;
int limb = 0;
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't concentrate enough for that.\n\r", ch);
return;
}
argument = one_argument(argument, arg);
if (ch->mount)
{
send_to_char("You can't powerslice while mounted.\n\r", ch);
return;
}
if (arg[0] == '\0')
{
send_to_char("Attempt to slice off the arm of whom?\n\r", ch);
return;
}
if ((victim = get_char_room_new(ch, arg, 1)) == NULL)
{
send_to_char("They aren't here.\n\r", ch);
return;
}
if (!str_cmp(argument, "right"))
limb = LM_RARM;
if (!str_cmp(argument, "left"))
limb = LM_LARM;
if (limb == 0)
{
send_to_char("You need to select a limb to attempt to slice off\n\r", ch);
return;
}
if (victim == ch)
{
send_to_char("Why would you want to do that to yourself?\n\r", ch);
return;
}
if (is_safe(ch, victim))
return;
if (wielding_skill_weapon(ch, 0) != 2 || !get_eq_char(ch, WEAR_WIELD))
{
send_to_char("You have to be wielding a sword to use this command.\n\r", ch);
return;
}
if (ch->grip != GRIP_SLASH)
{
send_to_char("You need to be have a slash grip to use this skill.\n\r", ch);
return;
}
check_attacker(ch, victim);
global_retcode = one_hit(ch, victim, gsn_powerslice, limb);
adjust_favor(ch, 10, 1);
check_illegal_pk(ch, victim);
return;
}
void do_pincer(CHAR_DATA * ch, char *argument)
{
char arg[MIL];
CHAR_DATA *victim;
OBJ_DATA *wield;
OBJ_DATA *dual;
int level;
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't concentrate enough for that.\n\r", ch);
return;
}
one_argument(argument, arg);
if (ch->mount)
{
send_to_char("You can't pincer while mounted.\n\r", ch);
return;
}
if (arg[0] == '\0')
{
send_to_char("Pincer whom?\n\r", ch);
return;
}
if ((victim = get_char_room_new(ch, arg, 1)) == NULL)
{
send_to_char("They aren't here.\n\r", ch);
return;
}
if (victim == ch)
{
send_to_char("Why would you want to do that to yourself?\n\r", ch);
return;
}
if (is_safe(ch, victim))
return;
if (wielding_skill_weapon(ch, 0) != 1 || !get_eq_char(ch, WEAR_WIELD))
{
send_to_char("You have to be dual wielding axes to use this command.\n\r", ch);
return;
}
else
{
if ((dual = get_eq_char(ch, WEAR_DUAL_WIELD)) == NULL)
{
send_to_char("You have to be dual wielding axes to use this command.\n\r", ch);
return;
}
else
{
wield = get_eq_char(ch, WEAR_WIELD);
dual->wear_loc = WEAR_WIELD;
wield->wear_loc = WEAR_DUAL_WIELD;
if (wielding_skill_weapon(ch, 0) != 1)
{
send_to_char("You have to be dual wielding axes to use this command.\n\r", ch);
wield->wear_loc = WEAR_WIELD;
dual->wear_loc = WEAR_DUAL_WIELD;
return;
}
wield->wear_loc = WEAR_WIELD;
dual->wear_loc = WEAR_DUAL_WIELD;
}
}
level = 30;
level += POINT_LEVEL(LEARNED(ch, gsn_pincer), MASTERED(ch, gsn_pincer))/2;
level += (get_curr_lck(ch) - 14)/2;
check_attacker(ch, victim);
if (number_range(1, 100) <= level)
{
learn_from_success(ch, gsn_pincer, victim);
act(AT_RED, "You pince $N together with your axes", ch, NULL, victim, TO_CHAR);
act(AT_RED, "$n pinces you together with $s axes", ch, NULL, victim, TO_VICT);
global_retcode = one_hit(ch, victim, gsn_pincer, LM_BODY);
adjust_favor(ch, 10, 1);
check_illegal_pk(ch, victim);
}
else
{
learn_from_failure(ch, gsn_pincer, victim);
act(AT_RED, "You try to pince $N together with your axes but fail", ch, NULL, victim, TO_CHAR);
act(AT_RED, "$n tries to pinces you together with $s axes but fails", ch, NULL, victim, TO_VICT);
global_retcode = one_hit(ch, victim, TYPE_HIT, LM_BODY);
adjust_favor(ch, 10, 1);
check_illegal_pk(ch, victim);
}
return;
}
void do_kick_back(CHAR_DATA * ch, char *argument)
{
char arg[MIL];
CHAR_DATA *victim;
int percent;
int level;
level = POINT_LEVEL(LEARNED(ch, gsn_kick_back), MASTERED(ch, gsn_kick_back));
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't concentrate enough for that.\n\r", ch);
return;
}
one_argument(argument, arg);
if (ch->mount)
{
send_to_char("You can't kick back while mounted.\n\r", ch);
return;
}
if (arg[0] == '\0')
{
send_to_char("Kick back whom?\n\r", ch);
return;
}
if ((victim = get_char_room_new(ch, arg, 1)) == NULL)
{
send_to_char("They aren't here.\n\r", ch);
return;
}
if (victim == ch)
{
send_to_char("Why would you want to do that to yourself?\n\r", ch);
return;
}
if (is_safe(ch, victim))
return;
if (wielding_skill_weapon(ch, 0) != 2)
{
send_to_char("You can only use a sword to do a kickback.\n\r", ch);
return;
}
if (ch->grip == GRIP_BASH)
{
send_to_char("Have to be using slash or stab grips to use kickback.\n\r", ch);
return;
}
percent = 35+ UMIN(15, ((get_curr_str(ch) - get_curr_str(victim))*2) + ((get_curr_lck(ch) - get_curr_lck(victim))));
percent += level*2/3;
if (victim->fighting && victim->fighting->who == ch)
percent -=30;
percent = URANGE(5, percent, 95);
check_attacker(ch, victim);
if (number_range(1, 100) <= percent)
{
learn_from_success(ch, gsn_kick_back, victim);
global_retcode = one_hit(ch, victim, gsn_kick_back, LM_BODY);
adjust_favor(ch, 10, 1);
check_illegal_pk(ch, victim);
}
else
{
learn_from_failure(ch, gsn_kick_back, victim);
global_retcode = one_hit(ch, victim, TYPE_HIT, LM_BODY);
check_illegal_pk(ch, victim);
}
return;
}
void do_circle(CHAR_DATA * ch, char *argument)
{
char arg[MIL];
CHAR_DATA *victim;
int percent;
int level;
level = POINT_LEVEL(LEARNED(ch, gsn_circle), MASTERED(ch, gsn_circle));
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't concentrate enough for that.\n\r", ch);
return;
}
one_argument(argument, arg);
if (ch->mount)
{
send_to_char("You can't circle while mounted.\n\r", ch);
return;
}
if (arg[0] == '\0')
{
send_to_char("Circle around whom?\n\r", ch);
return;
}
if ((victim = get_char_room_new(ch, arg, 1)) == NULL)
{
send_to_char("They aren't here.\n\r", ch);
return;
}
if (victim == ch)
{
send_to_char("How can you sneak up on yourself?\n\r", ch);
return;
}
if (is_safe(ch, victim))
return;
if (wielding_skill_weapon(ch, 0) != 7)
{
send_to_char("You can only circle with a dagger.\n\r", ch);
return;
}
if (ch->grip != GRIP_STAB)
{
send_to_char("You can only use circle if you are gripping your dagger for a stab strike.\n\r", ch);
return;
}
percent = 35+ UMIN(15, ((get_curr_dex(ch) - get_curr_dex(victim))*2) + ((get_curr_lck(ch) - get_curr_lck(victim))));
percent += level*2/3;
if (victim->fighting && victim->fighting->who == ch)
percent -=30;
percent = URANGE(5, percent, 95);
check_attacker(ch, victim);
if (number_range(1, 100) <= percent)
{
learn_from_success(ch, gsn_circle, victim);
global_retcode = one_hit(ch, victim, gsn_circle, LM_BODY);
adjust_favor(ch, 10, 1);
check_illegal_pk(ch, victim);
}
else
{
learn_from_failure(ch, gsn_circle, victim);
global_retcode = one_hit(ch, victim, TYPE_HIT, LM_BODY);
check_illegal_pk(ch, victim);
}
return;
}
//Kind of what bash use to do in stock, but made more useful in the new system.
//Not quite as powerful as stun (not asleep), but it takes time to recover from
//plus it should land a bit more than stun
void do_bash(CHAR_DATA *ch, char *argument)
{
CHAR_DATA *victim;
int chance;
int level;
level = POINT_LEVEL(LEARNED(ch, gsn_bash), MASTERED(ch, gsn_bash));
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't concentrate enough for that.\n\r", ch);
return;
}
if (IS_NPC(ch) || ch->pcdata->ranking[gsn_bash] <= 0)
{
send_to_char("You better leave the martial arts to those who are skilled.\n\r", ch);
return;
}
if ((victim = who_fighting(ch)) == NULL)
{
send_to_char("You aren't fighting anyone.\n\r", ch);
return;
}
if (!IS_NPC(ch) && ch->move < ch->max_move / 15)
{
set_char_color(AT_SKILL, ch);
send_to_char("You are far too tired to do that.\n\r", ch);
return; /* missing return fixed March 11/96 */
}
if (!ch->fighting)
{
send_to_char("You can only use this command in battle.\n\r", ch);
return;
}
ch->fight_timer = get_btimer(ch, gsn_bash, NULL);
chance = level/5*2;
chance += (get_curr_str(ch) - get_curr_str(victim)) * 3;
chance -= UMIN(((get_curr_dex(victim) - 14) *2), 16);
chance += get_curr_lck(ch) - get_curr_lck(victim);
chance = URANGE(1, chance, 50);
if (number_range(1, 100) <= chance)
{
learn_from_success(ch, gsn_bash, victim);
if (!IS_NPC(ch))
{
if (MASTERED(ch, gsn_bash) == 4)
ch->move -= ch->max_move / 30;
else
ch->move -= ch->max_move / 25;
}
victim->fight_timer += skill_table[gsn_bash]->beats + 3 + UMIN(level/10, 7);
victim->fight_timer = UMIN(victim->fight_timer, 24);
act(AT_SKILL, "$N bashes into you, leaving you dazed!", victim, NULL, ch, TO_CHAR);
act(AT_SKILL, "You bash into $N, leaving $M dazed!", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n bashes into $N, leaving $M dazed!", ch, NULL, victim, TO_NOTVICT);
}
else
{
if (!IS_NPC(ch))
{
if (MASTERED(ch, gsn_bash) == 4)
ch->move -= ch->max_move / 40;
else
ch->move -= ch->max_move / 35;
}
learn_from_failure(ch, gsn_bash, victim);
act(AT_SKILL, "$n charges at you shoulder first, but you dodge out of the way.", ch, NULL, victim, TO_VICT);
act(AT_SKILL, "You try to bash $N, but $E dodges out of the way.", ch, NULL, victim, TO_CHAR);
act(AT_SKILL, "$n charges shoulder first at $N, but keeps going right on past.", ch, NULL, victim, TO_NOTVICT);
}
return;
}
//Attempts to make the enemies in the room stop fighting with you, rather useful
//against lower level mobs if you are in a hurry. Also removes the
//aggro flags from mobs in actual areas (wilderness mobs, well they just
//go away)
void do_roar(CHAR_DATA *ch, char *argument)
{
int level;
int chance;
CHAR_DATA *victim;
CHAR_DATA *next_victim;
int succ = 0;
level = POINT_LEVEL(LEARNED(ch, gsn_roar), MASTERED(ch, gsn_roar));
if (IS_NPC(ch) && IS_AFFECTED(ch, AFF_CHARM))
{
send_to_char("You can't concentrate enough for that.\n\r", ch);
return;
}
if (IS_NPC(ch) || ch->pcdata->ranking[gsn_roar] <= 0)
{
send_to_char("You better leave the roaring to those who are skilled.\n\r", ch);
return;
}
if (!ch->fighting)
{
send_to_char("You have to be fighting to use this command.\n\r", ch);
return;
}
ch->fight_timer = get_btimer(ch, gsn_roar, NULL);
for (victim = ch->in_room->first_person; victim; victim = next_victim)
{
next_victim = victim->next_in_room;
if (!IN_SAME_ROOM(ch, victim))
continue;
if (!victim->fighting)
continue;
if (!IS_NPC(victim))
continue;
chance = level;
chance -= victim->max_hit/5; //Won't work on any mob over 600 hp or so because of this
chance -= (get_curr_int(victim) - 11)*2;
chance -= (get_curr_str(victim) - 11)*2;
chance += ch->max_hit/10;
chance += (get_curr_str(ch) - 16)*2;
if (number_range(1, 100) <= chance)
{
act(AT_RED, "$N cowers in fear from the mighty roar of $n", ch, NULL, victim, TO_ROOM);
act(AT_RED, "Your mighty roar causes $N to cower in fear and cease fighting you!", ch, NULL, victim, TO_CHAR);
succ++;
if (IN_WILDERNESS(ch))
{
stop_fighting(victim, FALSE);
extract_char(victim, TRUE);
}
else
{
stop_fighting(victim, TRUE);
stop_hating(victim);
stop_hunting(victim);
start_fearing(victim, ch);
if (xIS_SET(victim->act, ACT_AGGRESSIVE))
{
xREMOVE_BIT(victim->act, ACT_AGGRESSIVE);
}
}
}
else
{
act(AT_RED, "$n lets out a mighty roar but $N seems unimpressed", ch, NULL, victim, TO_ROOM);
act(AT_RED, "You let out a mighty roar but $N seems not to care.", ch, NULL, victim, TO_CHAR);
}
}
if (succ == 0)
learn_from_failure(ch, gsn_roar, NULL);
else
learn_from_success(ch, gsn_roar, NULL);
}
/* Berserk and HitAll. -- Altrag */
void do_berserk(CHAR_DATA * ch, char *argument)
{
sh_int percent;
AFFECT_DATA af;
int level;
level = POINT_LEVEL(LEARNED(ch, gsn_berserk), MASTERED(ch, gsn_berserk));
if (IS_AFFECTED(ch, AFF_BERSERK))
{
send_to_char("Your rage is already at its peak!\n\r", ch);
return;
}
percent = level+20;
if (!ch->fighting)
WAIT_STATE(ch, skill_table[gsn_berserk]->beats*2);
else
ch->fight_timer = get_btimer(ch, gsn_berserk, NULL);
if (number_range(1, 100) > percent)
{
send_to_char("You couldn't build up enough rage.\n\r", ch);
learn_from_failure(ch, gsn_berserk, ch);
return;
}
if (HAS_WAIT(ch))
{
send_to_char("You are too busy in battle to do that.\n\r", ch);
return;
}
af.type = gsn_berserk;
af.duration = number_range(level/2, level)+10;
af.modifier = level;
af.location = APPLY_NONE;
af.bitvector = meb(AFF_BERSERK);
affect_to_char(ch, &af);
send_to_char("You start to lose control..\n\r", ch);
learn_from_success(ch, gsn_berserk, ch);
return;
}
/* External from fight.c */
ch_ret one_hit args((CHAR_DATA * ch, CHAR_DATA * victim, int dt, int limb));
void do_hitall(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *vch;
CHAR_DATA *vch_next;
CHAR_DATA *mount = NULL;
sh_int nvict = 0;
OBJ_DATA *shield;
sh_int nhit = 0;
int pcount = 0;
sh_int percent, level, mastery;
mastery = MASTERED(ch, gsn_hitall);
level = POINT_LEVEL(LEARNED(ch, gsn_hitall), mastery);
if (is_room_safe(ch))
{
send_to_char_color("&BA godly force prevents you.\n\r", ch);
return;
}
if (!ch->in_room->first_person)
{
send_to_char("There's no one else here!\n\r", ch);
return;
}
if (IS_SET(ch->in_room->area->flags, AFLAG_NOAREA))
{
send_to_char("A mystical force in this area blocks your area attack.\n\r", ch);
return;
}
if (HAS_WAIT(ch))
{
send_to_char("You are too busy in battle to do that.\n\r", ch);
return;
}
if ((shield = get_eq_char(ch, WEAR_SHIELD)) && IS_OBJ_STAT(shield, ITEM_TWOHANDED))
{
send_to_char("Cannot use hitall while wearing a two-handed shield!\n\r", ch);
return;
}
if (ch->position == POS_BERSERK)
pcount = 2;
if (ch->position == POS_AGGRESSIVE)
pcount = 1;
if (ch->position == POS_DEFENSIVE)
pcount = -1;
if (ch->position == POS_EVASIVE)
pcount = -2;
percent = URANGE(10, level*4/3+UMIN(get_curr_lck(ch)-14, 8), 95);
act(AT_RED, "$n pulls back to attempt to hit everyone in the room!", ch, NULL, NULL, TO_ROOM);
act(AT_RED, "You pull back and attempt to hit everyone in the room!", ch, NULL, NULL, TO_CHAR);
for (vch = ch->in_room->first_person; vch; vch = vch_next)
{
vch_next = vch->next_in_room;
if (ch->coord->x != vch->coord->x || ch->coord->y != vch->coord->y || ch->map != vch->map)
continue;
if (is_same_group(ch, vch) || !is_legal_kill(ch, vch) || !can_see(ch, vch) || is_safe(ch, vch))
continue;
if (++nvict > UMAX(1, URANGE(1, level / 10, 7)+pcount))
break;
check_illegal_pk(ch, vch);
if (xIS_SET(vch->act, ACT_MOUNTSAVE))
mount = vch;
if (number_range(1, 100) <= percent || nhit == 0)
{
nhit++;
global_retcode = one_hit(ch, vch, TYPE_HIT, ch->grip);
}
else
global_retcode = damage(ch, vch, 0, TYPE_HIT, 0, -1);
/* Fireshield, etc. could kill ch too.. :>.. -- Altrag */
if (global_retcode == rCHAR_DIED || global_retcode == rBOTH_DIED || char_died(ch))
return;
}
if (!nvict)
{
send_to_char("There's no one else here!\n\r", ch);
return;
}
if (nhit)
{
learn_from_success(ch, gsn_hitall, mount);
if (nhit > 1)
ch->fight_timer = URANGE(2, nhit * get_btimer(ch, -1, NULL) * (95-(level/4))/100, 48); //24 seconds should be plenty, ha ha
else
ch->fight_timer = get_btimer(ch, -1, NULL);
}
else
{
if (ch->fighting)
ch->fight_timer = get_btimer(ch, -1, NULL);
else
WAIT_STATE(ch, 2*get_btimer(ch, -1, NULL));
learn_from_failure(ch, gsn_hitall, mount);
}
return;
}
bool check_illegal_psteal(CHAR_DATA * ch, CHAR_DATA * victim)
{
return FALSE;
}
void do_scan(CHAR_DATA * ch, char *argument)
{
ROOM_INDEX_DATA *was_in_room;
EXIT_DATA *pexit;
sh_int dir = -1;
sh_int dist;
sh_int max_dist = 6;
sh_int mastery;
mastery = MASTERED(ch, gsn_scan) * 30;
mastery = mastery - 90;
set_char_color(AT_ACTION, ch);
if (IS_AFFECTED(ch, AFF_BLIND))
{
send_to_char("Not very effective when you're blind...\n\r", ch);
return;
}
if (ch->position <= POS_SLEEPING)
{
send_to_char("You cannot do that in your sleep.\n\r", ch);
return;
}
if (ch->pcdata->learned[gsn_scan] <= 0 || ch->pcdata->ranking[gsn_scan] <= 0)
{
send_to_char("You are not skilled enough to use this skill.\n\r", ch);
return;
}
if (ch->coord->x > -1 || ch->coord->y > -1 || ch->map > -1)
{
display_map(ch, 6000, 6000, 0);
learn_from_success(ch, gsn_scan, NULL);
return;
}
if (argument[0] == '\0')
{
send_to_char("Scan in a direction...\n\r", ch);
return;
}
if ((dir = get_door(argument)) == -1)
{
send_to_char("Scan in WHAT direction?\n\r", ch);
return;
}
was_in_room = ch->in_room;
act(AT_GREY, "Scanning $t...", ch, dir_name[dir], NULL, TO_CHAR);
act(AT_GREY, "$n scans $t.", ch, dir_name[dir], NULL, TO_ROOM);
if (!can_use_skill(ch, number_percent() - mastery, gsn_scan))
{
act(AT_GREY, "You stop scanning $t as your vision blurs.", ch, dir_name[dir], NULL, TO_CHAR);
learn_from_failure(ch, gsn_scan, NULL);
return;
}
mastery = MASTERED(ch, gsn_scan);
if (IS_VAMPIRE(ch))
{
if ((gethour() < 21 && gethour() > 5) && mastery < 4)
{
send_to_char("You have trouble seeing clearly through all the " "light.\n\r", ch);
max_dist = 1;
}
}
if ((pexit = get_exit(ch->in_room, dir)) == NULL)
{
act(AT_GREY, "You can't see $t.", ch, dir_name[dir], NULL, TO_CHAR);
return;
}
max_dist = max_dist + (mastery - 2);
if (mastery <= 2)
max_dist--;
for (dist = 1; dist <= max_dist;)
{
if (IS_SET(pexit->exit_info, EX_CLOSED))
{
if (IS_SET(pexit->exit_info, EX_SECRET) || IS_SET(pexit->exit_info, EX_DIG))
act(AT_GREY, "Your view $t is blocked by a wall.", ch, dir_name[dir], NULL, TO_CHAR);
else
act(AT_GREY, "Your view $t is blocked by a door.", ch, dir_name[dir], NULL, TO_CHAR);
break;
}
if (room_is_private(pexit->to_room) && ch->level < LEVEL_STAFF) /* Tracker1 */
{
act(AT_GREY, "Your view $t is blocked by a private room.", ch, dir_name[dir], NULL, TO_CHAR);
break;
}
if (xIS_SET(pexit->to_room->room_flags, ROOM_IMP) && ch->pcdata->caste < caste_Staff)
{
send_to_char("No peeking, for Staff only!\n\r", ch);
break;
}
if (xIS_SET(pexit->to_room->room_flags, ROOM_MAP))
{
send_to_char("Your view $t is stopped at the Wilderness.\n\r", ch);
break;
}
char_from_room(ch);
char_to_room(ch, pexit->to_room);
set_char_color(AT_RMNAME, ch);
send_to_char(ch->in_room->name, ch);
send_to_char("\n\r", ch);
show_list_to_char( ch->in_room->first_content, ch, FALSE, FALSE, eItemNothing );
show_char_to_char(ch->in_room->first_person, ch);
switch (ch->in_room->sector_type)
{
default:
dist++;
break;
case SECT_AIR:
if (number_percent() < 80)
dist++;
break;
case SECT_INSIDE:
case SECT_FIELD:
case SECT_UNDERGROUND:
dist++;
break;
case SECT_FOREST:
case SECT_CITY:
case SECT_DESERT:
case SECT_HILLS:
dist += 2;
break;
case SECT_WATER_SWIM:
case SECT_WATER_NOSWIM:
dist += 3;
break;
case SECT_MOUNTAIN:
case SECT_UNDERWATER:
case SECT_OCEANFLOOR:
dist += 4;
break;
}
if (dist >= max_dist)
{
act(AT_GREY, "Your vision blurs with distance and you see no " "farther $t.", ch, dir_name[dir], NULL, TO_CHAR);
break;
}
if ((pexit = get_exit(ch->in_room, dir)) == NULL)
{
act(AT_GREY, "Your view $t is blocked by a wall.", ch, dir_name[dir], NULL, TO_CHAR);
break;
}
}
char_from_room(ch);
char_to_room(ch, was_in_room);
learn_from_success(ch, gsn_scan, NULL);
return;
}
// Like get_group_name, but will return Holy/Evil, used for do_study
char *sp_get_group_name(int group)
{
if (group == 30)
return "Holy and Evil";
else
return get_group_name(group);
}
/* Allows PCs to learn spells embedded in object. Should prove interesting. - Samson 8-9-98 */
/* Added Int support based off of AD&D rules -- Xerves 7/3/99 */
void do_study(CHAR_DATA * ch, char *argument) /* study by Absalom */
{
char arg[MIL];
OBJ_DATA *obj;
int sn = 0;
// int ls;
int mastery;
int group;
one_argument(argument, arg);
if (arg[0] == '\0')
{
send_to_char("Study what?\n\r", ch);
return;
}
if ((obj = get_obj_carry(ch, arg)) == NULL)
{
send_to_char("You do not have that item.\n\r", ch);
return;
}
if (obj->item_type != ITEM_SPELLBOOK)
{
send_to_char("You can only study spell books.\n\r", ch);
return;
}
act(AT_MAGIC, "$n studies $p.", ch, obj, NULL, TO_ROOM);
act(AT_MAGIC, "You study $p.", ch, obj, NULL, TO_CHAR);
if (obj->item_type == ITEM_SPELLBOOK)
{
sn = obj->value[1];
mastery = obj->value[2];
group = skill_table[sn]->group[0];
mastery = URANGE(0, mastery, 4);
if (mastery == 0)
mastery = skill_table[sn]->masterydiff[0];
if (sn < 0 || sn >= MAX_SKILL || skill_table[sn]->spell_fun == spell_null)
{
bug("Do_study: bad sn %d.", sn);
return;
}
//Put check in here to make sure they can learn it based off of group requirements
if (ch->pcdata->learned[sn])
{
send_to_char("You already know that spell!\n\r", ch);
return;
}
if (skill_table[sn]->type != SKILL_SPELL)
{
send_to_char("You can only study books of magical learning.\n\r", ch);
return;
}
ch->pcdata->ranking[sn] = 1;
ch->pcdata->learned[sn] = 1;
act(AT_MAGIC, "You have learned the spell $t!", ch, skill_table[sn]->name, NULL, TO_CHAR);
act(AT_FIRE, "$p breaks down from constant use and becomes nothing but trash.", ch, obj, NULL, TO_CHAR);
extract_obj(obj);
return;
}
}
/*
* Basically the same guts as do_scan() from above (please keep them in
* sync) used to find the victim we're firing at. -Thoric
*/
// moved to archery.c
//CHAR_DATA *scan_for_victim( CHAR_DATA *ch, EXIT_DATA *pexit, char *name )
/*
* Search inventory for an appropriate projectile to fire.
* Also search open quivers. -Thoric
*/
// Moved to archery.c
//OBJ_DATA *find_projectile( CHAR_DATA *ch, int type )
ch_ret spell_attack(int, int, CHAR_DATA *, void *);
/*
* Perform the actual attack on a victim -Thoric
*/
// Moved to archery.c
//ch_ret ranged_got_target( CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA *weapon,
// OBJ_DATA *projectile, sh_int dist, sh_int dt, char *stxt, sh_int color )
/*
* Generic use ranged attack function -Thoric & Tricops
*/
// Moved to archery.c
//ch_ret ranged_attack( CHAR_DATA *ch, char *argument, OBJ_DATA *weapon,
// OBJ_DATA *projectile, sh_int dt, sh_int range )
/*
* Fire <direction> <target>
*
* Fire a projectile from a missile weapon (bow, crossbow, etc)
*
* Design by Thoric, coding by Thoric and Tricops.
*
* Support code (see projectile_hit(), quiver support, other changes to
* fight.c, etc by Thoric.
*/
// Moved to archery.c
//void do_fire( CHAR_DATA *ch, char *argument )
/*
* Attempt to fire at a victim.
* Returns FALSE if no attempt was made
*/
//moved to archery.c
//bool mob_fire( CHAR_DATA *ch, char *name )
/* -- working on --
* Syntaxes: throw object (assumed already fighting)
* throw object direction target (all needed args for distance
* throwing)
* throw object (assumed same room throw)
void do_throw( CHAR_DATA *ch, char *argument )
{
ROOM_INDEX_DATA *was_in_room;
CHAR_DATA *victim;
OBJ_DATA *throw_obj;
EXIT_DATA *pexit;
sh_int dir;
sh_int dist;
sh_int max_dist = 3;
char arg[MIL];
char arg1[MIL];
char arg2[MIL];
argument = one_argument( argument, arg );
argument = one_argument( argument, arg1 );
argument = one_argument( argument, arg2 );
for ( throw_obj = ch->last_carrying; throw_obj;
throw_obj = throw_obj=>prev_content )
{
--- if ( can_see_obj( ch, throw_obj )
&& ( throw_obj->wear_loc == WEAR_HELD || throw_obj->wear_loc ==
WEAR_WIELDED || throw_obj->wear_loc == WEAR_DUAL_WIELDED )
&& nifty_is_name( arg, throw_obj->name ) )
break;
----
if ( can_see_obj( ch, throw_obj ) && nifty_is_name( arg, throw_obj->name )
break;
}
if ( !throw_obj )
{
send_to_char( "You aren't holding or wielding anything like that.\n\r", ch );
return;
}
----
if ( ( throw_obj->item_type != ITEM_WEAPON)
{
send_to_char("You can only throw weapons.\n\r", ch );
return;
}
----
if (get_obj_weight( throw_obj ) - ( 3 * (get_curr_str(ch) - 15) ) > 0)
{
send_to_char("That is too heavy for you to throw.\n\r", ch);
if (!number_range(0,10))
learn_from_failure( ch, gsn_throw );
return;
}
if ( ch->fighting )
victim = ch->fighting;
else
{
if ( ( ( victim = get_char_room( ch, arg1 ) ) == NULL )
&& ( arg2[0] == '\0' ) )
{
act( AT_GREY, "Throw $t at whom?", ch, obj->short_descr, NULL,
TO_CHAR );
return;
}
}
}*/
void do_slice(CHAR_DATA * ch, char *argument)
{
OBJ_DATA *corpse;
OBJ_DATA *obj;
OBJ_DATA *slice;
bool found;
MOB_INDEX_DATA *pMobIndex;
char buf[MSL];
char buf1[MSL];
found = FALSE;
if (IS_NPC(ch))
{
send_to_char("Huh?\n\r", ch);
return;
}
if (!IS_IMMORTAL(ch) && ch->pcdata->ranking[gsn_slice] <= 0)
{
send_to_char("You are not learned in this skill.\n\r", ch);
return;
}
if (argument[0] == '\0')
{
send_to_char("From what do you wish to slice meat?\n\r", ch);
return;
}
if ((obj = get_eq_char(ch, WEAR_WIELD)) == NULL || (obj->value[3] != 1 && obj->value[3] != 2 && obj->value[3] != 3 && obj->value[3] != 11))
{
send_to_char("You need to wield a sharp weapon.\n\r", ch);
return;
}
if ((corpse = get_obj_here(ch, argument)) == NULL)
{
send_to_char("You can't find that here.\n\r", ch);
return;
}
if (corpse->item_type != ITEM_CORPSE_NPC || corpse->value[3] < 75)
{
send_to_char("That is not a suitable source of meat.\n\r", ch);
return;
}
if ((pMobIndex = get_mob_index((sh_int) - (corpse->value[2]))) == NULL)
{
bug("Can not find mob for value[2] of corpse, do_slice", 0);
return;
}
if (get_obj_index(OBJ_VNUM_SLICE) == NULL)
{
bug("Vnum 24 not found for do_slice!", 0);
return;
}
if (!can_use_skill(ch, number_percent(), gsn_slice) && !IS_IMMORTAL(ch))
{
send_to_char("You fail to slice the meat properly.\n\r", ch);
learn_from_failure(ch, gsn_slice, NULL); /* Just in case they die :> */
if (number_percent() + (get_curr_dex(ch) - 13) < 10)
{
act(AT_BLOOD, "You cut yourself!", ch, NULL, NULL, TO_CHAR);
damage(ch, ch, number_range(2, 10), gsn_slice, 0, -1);
}
return;
}
slice = create_object(get_obj_index(OBJ_VNUM_SLICE), 0);
sprintf(buf, "meat fresh slice %s", pMobIndex->player_name);
STRFREE(slice->name);
slice->name = STRALLOC(buf);
sprintf(buf, "a slice of raw meat from %s", pMobIndex->short_descr);
STRFREE(slice->short_descr);
slice->short_descr = STRALLOC(buf);
sprintf(buf1, "A slice of raw meat from %s lies on the ground.", pMobIndex->short_descr);
STRFREE(slice->description);
slice->description = STRALLOC(buf1);
act(AT_BLOOD, "$n cuts a slice of meat from $p.", ch, corpse, NULL, TO_ROOM);
act(AT_BLOOD, "You cut a slice of meat from $p.", ch, corpse, NULL, TO_CHAR);
obj_to_char(slice, ch);
corpse->value[3] -= 25;
learn_from_success(ch, gsn_slice, NULL);
return;
}
/*------------------------------------------------------------
* Fighting Styles - haus
*/ void do_style(CHAR_DATA * ch, char *argument)
{
char arg[MIL];
/* char buf[MIL];
int percent; */
if (IS_NPC(ch))
return;
one_argument(argument, arg);
if (arg[0] == '\0')
{
ch_printf_color(ch, "&wAdopt which fighting style? (current: %s&w)\n\r",
ch->style == STYLE_BERSERK ? "&Rberserk" :
ch->style == STYLE_DIVINE ? "&Ydivine" :
ch->style == STYLE_WIZARDRY ? "&Ywizardry" :
ch->style == STYLE_AGGRESSIVE ? "&Raggressive" :
ch->style == STYLE_DEFENSIVE ? "&Ydefensive" : ch->style == STYLE_EVASIVE ? "&Yevasive" : "standard");
return;
}
if (HAS_WAIT(ch))
{
send_to_char("You are too busy in battle to do that.\n\r", ch);
return;
}
if (!str_prefix(arg, "evasive") || !str_prefix(arg, "divine") || !str_prefix(arg, "wizardry"))
{
int erank = 0;
char styleb[15];
int astyle = 0;
char buf[MSL];
if (ch->pcdata->ranking[gsn_style_evasive] <= 0 && ch->pcdata->ranking[gsn_style_divine] <= 0
&& ch->pcdata->ranking[gsn_style_wizardry] <= 0)
{
send_to_char("You have not yet learned enough to fight evasively.\n\r", ch);
return;
}
if (!ch->fighting)
WAIT_STATE(ch, 4);
else
ch->fight_timer = 2;
if (!str_prefix(arg, "evasive"))
{
erank = POINT_LEVEL(LEARNED(ch, gsn_style_evasive), MASTERED(ch, gsn_style_evasive));
sprintf(styleb, "evasive");
astyle = STYLE_EVASIVE;
}
if (!str_prefix(arg, "divine"))
{
erank = POINT_LEVEL(LEARNED(ch, gsn_style_divine), MASTERED(ch, gsn_style_divine));
sprintf(styleb, "divine");
astyle = STYLE_DIVINE;
}
if (!str_prefix(arg, "wizardry"))
{
erank = POINT_LEVEL(LEARNED(ch, gsn_style_wizardry), MASTERED(ch, gsn_style_wizardry));
sprintf(styleb, "wizardry");
astyle = STYLE_WIZARDRY;
}
if (number_percent() < erank + 40)
{
/* success */
if (ch->fighting)
{
ch->position = POS_EVASIVE;
sprintf(buf, "$n changes stances to %s.", styleb);
act(AT_ACTION, buf, ch, NULL, NULL, TO_ROOM);
}
ch->style = astyle;;
sprintf(buf, "You change your stance to %s\n\r", styleb);
send_to_char(buf, ch);
return;
}
else
{
/* failure */
ch_printf(ch, "You nearly trip in a lame attempt to change your style to %s.\n\r", styleb);
return;
}
}
else if (!str_prefix(arg, "defensive"))
{
if (ch->pcdata->ranking[gsn_style_defensive] <= 0)
{
send_to_char("You have not yet learned enough to fight defensively.\n\r", ch);
return;
}
if (!ch->fighting)
WAIT_STATE(ch, 4);
else
ch->fight_timer = 2;
if (number_percent() < POINT_LEVEL(LEARNED(ch, gsn_style_defensive), MASTERED(ch, gsn_style_defensive)) + 40)
{
/* success */
if (ch->fighting)
{
ch->position = POS_DEFENSIVE;
learn_from_success(ch, gsn_style_defensive, NULL);
act(AT_ACTION, "$n moves into a defensive posture.", ch, NULL, NULL, TO_ROOM);
}
ch->style = STYLE_DEFENSIVE;
send_to_char("You adopt a defensive fighting style.\n\r", ch);
return;
}
else
{
/* failure */
send_to_char("You nearly trip in a lame attempt to adopt a defensive fighting style.\n\r", ch);
return;
}
}
else if (!str_prefix(arg, "standard"))
{
if (ch->pcdata->ranking[gsn_style_standard] <= 0)
{
send_to_char("You have not yet learned enough to fight in the standard style.\n\r", ch);
return;
}
if (!ch->fighting)
WAIT_STATE(ch, 4);
else
ch->fight_timer = 2;
if (number_percent() < POINT_LEVEL(LEARNED(ch, gsn_style_standard), MASTERED(ch, gsn_style_standard)) + 40)
{
/* success */
if (ch->fighting)
{
ch->position = POS_FIGHTING;
learn_from_success(ch, gsn_style_standard, NULL);
act(AT_ACTION, "$n switches to a standard fighting style.", ch, NULL, NULL, TO_ROOM);
}
ch->style = STYLE_FIGHTING;
send_to_char("You adopt a standard fighting style.\n\r", ch);
return;
}
else
{
/* failure */
send_to_char("You nearly trip in a lame attempt to adopt a standard fighting style.\n\r", ch);
return;
}
}
else if (!str_prefix(arg, "aggressive"))
{
if (ch->pcdata->ranking[gsn_style_aggressive] <= 0)
{
send_to_char("You have not yet learned enough to fight aggressively.\n\r", ch);
return;
}
if (!ch->fighting)
WAIT_STATE(ch, 4);
else
ch->fight_timer = 2;
if (number_percent() < POINT_LEVEL(LEARNED(ch, gsn_style_aggressive), MASTERED(ch, gsn_style_aggressive)) + 40)
{
/* success */
if (ch->fighting)
{
ch->position = POS_AGGRESSIVE;
learn_from_success(ch, gsn_style_aggressive, NULL);
act(AT_ACTION, "$n assumes an aggressive stance.", ch, NULL, NULL, TO_ROOM);
}
ch->style = STYLE_AGGRESSIVE;
send_to_char("You adopt an aggressive fighting style.\n\r", ch);
return;
}
else
{
/* failure */
send_to_char("You nearly trip in a lame attempt to adopt an aggressive fighting style.\n\r", ch);
return;
}
}
else if (!str_prefix(arg, "berserk"))
{
if (ch->pcdata->ranking[gsn_style_berserk] <= 0)
{
send_to_char("You have not yet learned enough to fight as a berserker.\n\r", ch);
return;
}
if (!ch->fighting)
WAIT_STATE(ch, 4);
else
ch->fight_timer = 2;
if (number_percent() < POINT_LEVEL(LEARNED(ch, gsn_style_berserk), MASTERED(ch, gsn_style_berserk)) + 40)
{
/* success */
if (ch->fighting)
{
ch->position = POS_BERSERK;
learn_from_success(ch, gsn_style_berserk, NULL);
act(AT_ACTION, "$n enters a wildly aggressive style.", ch, NULL, NULL, TO_ROOM);
}
ch->style = STYLE_BERSERK;
send_to_char("You adopt a berserk fighting style.\n\r", ch);
return;
}
else
{
/* failure */
send_to_char("You nearly trip in a lame attempt to adopt a berserk fighting style.\n\r", ch);
return;
}
}
send_to_char("Adopt which fighting style?\n\r", ch);
return;
}
/* New check to see if you can use skills to support morphs --Shaddai */
bool can_use_skill(CHAR_DATA * ch, int percent, int gsn)
{
bool check = FALSE;
int suc;
suc = 1;
if (!IS_NPC(ch))
{
if ((percent + skill_table[gsn]->difficulty * 5) > (85 + (ch->pcdata->learned[gsn]*5)))
suc = 0;
}
if (!IS_NPC(ch) && ((ch->pcdata->learned[gsn] < 1 || ch->pcdata->learned[gsn] > MAX_SKPOINTS)
|| (ch->pcdata->ranking[gsn] < 1 || ch->pcdata->ranking[gsn] > MAX_RANKING)))
return FALSE;
if (IS_NPC(ch) && percent < 85)
check = TRUE;
else if (suc == 1)
check = TRUE;
else if (ch->morph && ch->morph->morph && ch->morph->morph->skills &&
ch->morph->morph->skills[0] != '\0' && is_name(skill_table[gsn]->name, ch->morph->morph->skills) && percent < 85)
check = TRUE;
if (ch->morph && ch->morph->morph && ch->morph->morph->no_skills &&
ch->morph->morph->no_skills[0] != '\0' && is_name(skill_table[gsn]->name, ch->morph->morph->no_skills))
check = FALSE;
return check;
}
/*
* Cook was coded by Blackmane and heavily modified by Shaddai
*/
void do_cook(CHAR_DATA * ch, char *argument)
{
OBJ_DATA *food, *fire;
char arg[MIL];
char buf[MSL];
sh_int level;
level = POINT_LEVEL(LEARNED(ch, gsn_cook), MASTERED(ch, gsn_cook));
one_argument(argument, arg);
if (IS_NPC(ch) || ch->pcdata->ranking[gsn_cook] <= 0)
{
send_to_char("That skill is beyond your understanding.\n\r", ch);
return;
}
if (arg[0] == '\0')
{
send_to_char("Cook what?\n\r", ch);
return;
}
if (ms_find_obj(ch))
return;
if ((food = get_obj_carry(ch, arg)) == NULL)
{
send_to_char("You do not have that item.\n\r", ch);
return;
}
if (food->item_type != ITEM_COOK)
{
send_to_char("How can you cook that?\n\r", ch);
return;
}
if (food->value[2] > 2)
{
send_to_char("That is already burnt to a crisp.\n\r", ch);
return;
}
for (fire = ch->in_room->first_content; fire; fire = fire->next_content)
{
if (fire->item_type == ITEM_FIRE)
break;
}
if (!fire)
{
send_to_char("There is no fire here!\n\r", ch);
return;
}
if (number_percent() > level+35)
{
food->timer = food->timer / 2;
food->value[0] = 0;
food->value[2] = 3;
act(AT_MAGIC, "$p catches on fire burning it to a crisp!\n\r", ch, food, NULL, TO_CHAR);
act(AT_MAGIC, "$n catches $p on fire burning it to a crisp.", ch, food, NULL, TO_ROOM);
sprintf(buf, "a burnt %s", food->pIndexData->name);
STRFREE(food->short_descr);
food->short_descr = STRALLOC(buf);
sprintf(buf, "A burnt %s.", food->pIndexData->name);
STRFREE(food->description);
food->description = STRALLOC(buf);
return;
}
if (number_percent() > level +55)
{
food->timer = food->timer * 3;
food->value[2] += 2;
act(AT_MAGIC, "$n overcooks a $p.", ch, food, NULL, TO_ROOM);
act(AT_MAGIC, "You overcook a $p.", ch, food, NULL, TO_CHAR);
sprintf(buf, "an overcooked %s", food->pIndexData->name);
STRFREE(food->short_descr);
food->short_descr = STRALLOC(buf);
sprintf(buf, "An overcooked %s.", food->pIndexData->name);
STRFREE(food->description);
food->description = STRALLOC(buf);
}
else
{
food->timer = food->timer * 4;
food->value[0] *= 2;
act(AT_MAGIC, "$n roasts a $p.", ch, food, NULL, TO_ROOM);
act(AT_MAGIC, "You roast a $p.", ch, food, NULL, TO_CHAR);
sprintf(buf, "a roasted %s", food->pIndexData->name);
STRFREE(food->short_descr);
food->short_descr = STRALLOC(buf);
sprintf(buf, "A roasted %s.", food->pIndexData->name);
STRFREE(food->description);
food->description = STRALLOC(buf);
food->value[2]++;
}
learn_from_success(ch, gsn_cook, NULL);
}
//restores limbs, used at a mob, cost is based on health
void do_restorelimbs(CHAR_DATA *ch, char *argument)
{
CHAR_DATA *mob;
int cost;
char buf[MSL];
/* Search for an act_healer */
for (mob = ch->in_room->first_person; mob; mob = mob->next_in_room)
{
if (IS_NPC(mob) && xIS_SET(mob->act, ACT_RESTORELIMBS))
break;
}
if (mob == NULL)
{
send_to_char("You can't do that here.\n\r", ch);
return;
}
cost = (20+ch->max_hit) * ch->max_hit *.4;
if (argument[0] == '\0')
{
sprintf(buf, "It will cost you %d to restore a limb. Choices for limbs are: rarm larm rleg lleg", cost);
do_say(mob, buf);
return;
}
sprintf(buf, "It will cost you %d to restore a limb.", cost);
if (!str_cmp(argument, "rarm"))
{
if (ch->con_rarm != -1)
{
do_say(mob, "You can only restore broken limbs.");
return;
}
if (ch->gold < cost)
{
do_say(mob, buf);
return;
}
ch->gold -= cost;
ch->con_rarm = 100;
act(AT_WHITE, "$N waves $S hands around and restores $n's right arm.", ch, NULL, mob, TO_ROOM);
act(AT_WHITE, "$N waves $S hands around and restores your right arm.", ch, NULL, mob, TO_CHAR);
return;
}
if (!str_cmp(argument, "larm"))
{
if (ch->con_larm != -1)
{
do_say(mob, "You can only restore broken limbs.");
return;
}
if (ch->gold < cost)
{
do_say(mob, buf);
return;
}
ch->gold -= cost;
ch->con_larm = 100;
act(AT_WHITE, "$N waves $S hands around and restores $n's left arm.", ch, NULL, mob, TO_ROOM);
act(AT_WHITE, "$N waves $S hands around and restores your left arm.", ch, NULL, mob, TO_CHAR);
return;
}
if (!str_cmp(argument, "rleg"))
{
if (ch->con_rleg != -1)
{
do_say(mob, "You can only restore broken limbs.");
return;
}
if (ch->gold < cost)
{
do_say(mob, buf);
return;
}
ch->gold -= cost;
ch->con_rleg = 100;
act(AT_WHITE, "$N waves $S hands around and restores $n's right leg.", ch, NULL, mob, TO_ROOM);
act(AT_WHITE, "$N waves $S hands around and restores your right leg.", ch, NULL, mob, TO_CHAR);
return;
}
if (!str_cmp(argument, "lleg"))
{
if (ch->con_lleg != -1)
{
do_say(mob, "You can only restore broken limbs.");
return;
}
if (ch->gold < cost)
{
do_say(mob, buf);
return;
}
ch->gold -= cost;
ch->con_lleg = 100;
act(AT_WHITE, "$N waves $S hands around and restores $n's left leg.", ch, NULL, mob, TO_ROOM);
act(AT_WHITE, "$N waves $S hands around and restores your left leg.", ch, NULL, mob, TO_CHAR);
return;
}
do_restorelimbs(ch, "");
return;
}
/* Healer, for lower levels and just for fun -- Xerves */
void do_heal(CHAR_DATA * ch, char *argument)
{
CHAR_DATA *mob;
char arg[MIL];
int cost, sn;
SPELL_FUN *spell;
char *words;
/* Search for an act_healer */
for (mob = ch->in_room->first_person; mob; mob = mob->next_in_room)
{
if (IS_NPC(mob) && xIS_SET(mob->act, ACT_HEALER))
break;
}
if (mob == NULL)
{
send_to_char("You can't do that here.\n\r", ch);
return;
}
one_argument(argument, arg);
if (arg[0] == '\0')
{
/* display price list */
act(AT_PLAIN, "$N says 'I offer the following spells:'", ch, NULL, mob, TO_CHAR);
send_to_char("\n &Rlight: &Ccure light wounds &Y200 gold\n\r", ch);
send_to_char(" &Rserious: &Ccure serious wounds &Y300 gold\n\r", ch);
send_to_char(" &Rcritical: &Ccure critical wounds &Y400 gold\n\r", ch);
send_to_char(" &Rheal: &Chealing spell &Y1000 gold\n\r", ch);
send_to_char(" &Rblind: &Ccure blindness &Y1200 gold\n\r", ch);
send_to_char(" &Rpoison: &Ccure poison &Y1200 gold\n\r", ch);
send_to_char(" &Rcurse: &Cremove curse &Y2500 gold\n\r", ch);
send_to_char(" &Rsanctuary: &Csanctuary &Y5000 gold\n\r", ch);
send_to_char(" &Rstrength: &Ckindred strength &Y4000 gold\n\r", ch);
send_to_char(" &Rdexterity: &Cslink &Y4000 gold\n\r", ch);
send_to_char(" &Rwisdom: &Csagacity &Y4000 gold\n\r", ch);
send_to_char(" &Rint: &Cdragon wit &Y4000 gold\n\r", ch);
send_to_char(" &Rcon: &Ctrollish vigor &Y4000 gold\n\r", ch);
send_to_char(" &Rarmor: &Carmor &Y2000 gold\n\r", ch);
send_to_char(" &Rshield: &Cshield &Y2500 gold\n\r", ch);
send_to_char(" &Rrefresh: &Crestore movement &Y500 gold\n\r", ch);
send_to_char(" &Rmana: &Crestore mana &Y800 gold\n\n\r", ch);
send_to_char(" &c&wType heal <type> to be healed.\n\r", ch);
return;
}
if (!str_cmp(arg, "light"))
{
spell = spell_smaug;
sn = skill_lookup("cure light");
words = "judicandus dies";
cost = 200;
}
else if (!str_cmp(arg, "serious"))
{
spell = spell_smaug;
sn = skill_lookup("cure serious");
words = "judicandus gzfuajg";
cost = 300;
}
else if (!str_cmp(arg, "critical"))
{
spell = spell_smaug;
sn = skill_lookup("cure critical");
words = "judicandus qfuhuqar";
cost = 400;
}
else if (!str_cmp(arg, "heal"))
{
spell = spell_smaug;
sn = skill_lookup("heal");
words = "pzar";
cost = 1000;
}
else if (!str_cmp(arg, "blind"))
{
spell = spell_cure_blindness;
sn = skill_lookup("cure blindness");
words = "judicandus noselacri";
cost = 1200;
}
else if (!str_cmp(arg, "poison"))
{
spell = spell_cure_poison;
sn = skill_lookup("cure poison");
words = "judicandus sausabru";
cost = 1200;
}
else if (!str_cmp(arg, "curse"))
{
spell = spell_remove_curse;
sn = skill_lookup("remove curse");
words = "candussido judifgz";
cost = 2500;
}
else if (!str_cmp(arg, "mana"))
{
spell = NULL;
sn = -1;
words = "energizer";
cost = 800;
}
else if (!str_cmp(arg, "refresh"))
{
spell = spell_smaug;
sn = skill_lookup("refresh");
words = "candusima";
cost = 500;
}
else if (!str_cmp(arg, "sanctuary"))
{
spell = spell_smaug;
sn = skill_lookup("sanctuary");
words = "heliamheldra";
cost = 5000;
}
else if (!str_cmp(arg, "strength"))
{
spell = spell_smaug;
sn = skill_lookup("kindred strength");
words = "stremdupha";
cost = 4000;
}
else if (!str_cmp(arg, "wisdom"))
{
spell = spell_smaug;
sn = skill_lookup("sagacity");
words = "wifda";
cost = 4000;
}
else if (!str_cmp(arg, "dexterity"))
{
spell = spell_smaug;
sn = skill_lookup("slink");
words = "zooooom";
cost = 4000;
}
else if (!str_cmp(arg, "int"))
{
spell = spell_smaug;
sn = skill_lookup("dragon wit");
words = "knofdapiel";
cost = 4000;
}
else if (!str_cmp(arg, "con"))
{
spell = spell_smaug;
sn = skill_lookup("trollish vigor");
words = "skupfta";
cost = 4000;
}
else if (!str_cmp(arg, "armor"))
{
spell = spell_smaug;
sn = skill_lookup("armor");
words = "feskunda";
cost = 2000;
}
else if (!str_cmp(arg, "shield"))
{
spell = spell_smaug;
sn = skill_lookup("shield");
words = "rayoprot";
cost = 2500;
}
else
{
act(AT_PLAIN, "$N says ' Type 'heal' for a list of spells.'", ch, NULL, mob, TO_CHAR);
return;
}
if (cost > ch->gold)
{
act(AT_PLAIN, "$N says 'You do not have enough gold for my services.'", ch, NULL, mob, TO_CHAR);
return;
}
WAIT_STATE(ch, PULSE_VIOLENCE);
ch->gold -= cost;
act(AT_PLAIN, "$n utters the words '$T'.", mob, NULL, words, TO_ROOM);
if (spell == NULL)
{
ch->mana += dice(10, 5);
if (ch->mana > ch->max_mana)
ch->mana = ch->max_mana;
send_to_char("A warm glow passes through you.\n\r", ch);
return;
}
if (sn == -1)
return;
spell(sn, mob->level, mob, ch);
}