/*
* $Id: martial_art.c,v 1.64 1999/01/05 08:12:00 kostik Exp $
*/
/***************************************************************************
* ANATOLIA 2.1 is copyright 1996-1997 Serdar BULUT, Ibrahim CANPUNAR *
* ANATOLIA has been brought to you by ANATOLIA consortium *
* Serdar BULUT {Chronos} bulut@rorqual.cc.metu.edu.tr *
* Ibrahim Canpunar {Asena} canpunar@rorqual.cc.metu.edu.tr *
* Murat BICER {KIO} mbicer@rorqual.cc.metu.edu.tr *
* D.Baris ACAR {Powerman} dbacar@rorqual.cc.metu.edu.tr *
* By using this code, you have agreed to follow the terms of the *
* ANATOLIA license, in the file Anatolia/anatolia.licence *
***************************************************************************/
/***************************************************************************
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* *
* Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* *
* In order to use any part of this Merc Diku Mud, you must comply with *
* both the original Diku license in 'license.doc' as well the Merc *
* license in 'license.txt'. In particular, you may not remove either of *
* these copyright notices. *
* *
* Much time and thought has gone into this software and you are *
* benefitting. We hope that you share your changes too. What goes *
* around, comes around. *
***************************************************************************/
/***************************************************************************
* ROM 2.4 is copyright 1993-1995 Russ Taylor *
* ROM has been brought to you by the ROM consortium *
* Russ Taylor (rtaylor@pacinfo.com) *
* Gabrielle Taylor (gtaylor@pacinfo.com) *
* Brian Moore (rom@rom.efn.org) *
* By using this code, you have agreed to follow the terms of the *
* ROM license, in the file Rom24/doc/rom.license *
***************************************************************************/
#include <sys/types.h>
#include <stdio.h>
#include "merc.h"
#include "fight.h"
#ifdef SUNOS
# include <stdarg.h>
# include "compat/compat.h"
#endif
DECLARE_DO_FUN(do_yell );
DECLARE_DO_FUN(do_sleep );
DECLARE_DO_FUN(do_sit );
DECLARE_DO_FUN(do_bash_door );
static inline bool check_yell (CHAR_DATA *ch, CHAR_DATA *victim,
bool fighting);
void one_hit (CHAR_DATA *ch, CHAR_DATA *victim,
int dt, int loc);
void set_fighting (CHAR_DATA *ch, CHAR_DATA *victim);
/*
* Disarm a creature.
* Caller must check for successful attack.
*/
void disarm(CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA *obj)
{
OBJ_DATA *obj2;
int skill;
if (IS_OBJ_STAT(obj, ITEM_NOREMOVE)) {
act("$S weapon won't budge!", ch, NULL, victim, TO_CHAR);
act("$n tries to disarm you, but your weapon won't budge!",
ch, NULL, victim, TO_VICT);
act("$n tries to disarm $N, but fails.",
ch, NULL, victim, TO_NOTVICT);
return;
}
if ((skill = get_skill(victim, gsn_grip))) {
skill += (get_curr_stat(victim, STAT_STR) -
get_curr_stat(ch, STAT_STR)) * 5;
if (number_percent() < skill) {
act("$N grips and prevent you to disarm $M!",
ch, NULL, victim, TO_CHAR);
act("$n tries to disarm you, but you grip and escape!",
ch, NULL, victim, TO_VICT);
act("$n tries to disarm $N, but fails.",
ch, NULL, victim, TO_NOTVICT);
check_improve(victim, gsn_grip, TRUE, 1);
return;
}
else
check_improve(victim,gsn_grip,FALSE,1);
}
act_puts("$n DISARMS you and sends your weapon flying!",
ch, NULL, victim, TO_VICT, POS_FIGHTING);
act_puts("You disarm $N!", ch,NULL, victim, TO_CHAR, POS_FIGHTING);
act_puts("$n disarms $N!", ch, NULL, victim, TO_NOTVICT, POS_FIGHTING);
obj_from_char(obj);
if (IS_OBJ_STAT(obj, ITEM_NODROP) || IS_OBJ_STAT(obj,ITEM_INVENTORY))
obj_to_char(obj, victim);
else {
obj_to_room(obj, victim->in_room);
if (IS_NPC(victim)
&& victim->wait == 0
&& can_see_obj(victim,obj))
get_obj(victim, obj, NULL);
}
if ((obj2 = get_eq_char(victim, WEAR_SECOND_WIELD)) != NULL) {
act_puts("You wield your second weapon as your first!.",
ch, NULL, victim, TO_VICT, POS_FIGHTING);
act_puts("$N wields his second weapon as first!",
ch, NULL, victim, TO_CHAR, POS_FIGHTING);
act_puts("$N wields his second weapon as first!",
ch, NULL, victim, TO_NOTVICT, POS_FIGHTING);
unequip_char(victim, obj2);
equip_char(victim, obj2, WEAR_WIELD);
}
}
void do_berserk(CHAR_DATA *ch, const char *argument)
{
int chance, hp_percent;
if ((chance = get_skill(ch, gsn_berserk)) == 0) {
char_puts("You turn red in the face, but nothing happens.\n",
ch);
return;
}
if (IS_AFFECTED(ch, AFF_BERSERK)
|| is_affected(ch, gsn_berserk)
|| is_affected(ch, gsn_frenzy)) {
char_puts("You get a little madder.\n", ch);
return;
}
if (IS_AFFECTED(ch, AFF_CALM)) {
char_puts("You're feeling too mellow to berserk.\n", ch);
return;
}
if (ch->mana < 50) {
char_puts("You can't get up enough energy.\n", ch);
return;
}
/* modifiers */
/* fighting */
if (ch->position == POS_FIGHTING)
chance += 10;
/* damage -- below 50% of hp helps, above hurts */
hp_percent = 100 * ch->hit/ch->max_hit;
chance += 25 - hp_percent/2;
if (number_percent() < chance) {
AFFECT_DATA af;
WAIT_STATE(ch,PULSE_VIOLENCE);
ch->mana -= 50;
ch->move /= 2;
/* heal a little damage */
ch->hit += ch->level * 2;
ch->hit = UMIN(ch->hit,ch->max_hit);
char_puts("Your pulse races as you are consumned by rage!\n",
ch);
act_puts("$n gets a wild look in $s eyes.",
ch, NULL, NULL, TO_ROOM, POS_FIGHTING);
check_improve(ch, gsn_berserk, TRUE, 2);
af.where = TO_AFFECTS;
af.type = gsn_berserk;
af.level = ch->level;
af.duration = number_fuzzy(ch->level / 8);
af.modifier = UMAX(1,ch->level/5);
af.bitvector = AFF_BERSERK;
af.location = APPLY_HITROLL;
affect_to_char(ch,&af);
af.location = APPLY_DAMROLL;
affect_to_char(ch,&af);
af.modifier = UMAX(10,10 * (ch->level/5));
af.location = APPLY_AC;
affect_to_char(ch,&af);
}
else {
WAIT_STATE(ch,2 * PULSE_VIOLENCE);
ch->mana -= 25;
ch->move /= 2;
char_puts("Your pulse speeds up, but nothing happens.\n",
ch);
check_improve(ch, gsn_berserk, FALSE, 2);
}
}
void do_bash(CHAR_DATA *ch, const char *argument)
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
int chance, wait;
bool fighting;
int damage_bash;
if (MOUNTED(ch)) {
char_puts("You can't bash while riding!\n", ch);
return;
}
argument = one_argument(argument, arg);
if ((chance = get_skill(ch, gsn_bash)) == 0) {
char_puts("Bashing? What's that?\n", ch);
return;
}
if (arg[0] != '\0' && !str_cmp(arg, "door")) {
do_bash_door(ch, argument);
return;
}
/*WAIT_STATE(ch, SKILL(gsn_bash)->beats);*/
if (arg[0] == '\0') {
victim = ch->fighting;
if (victim == NULL) {
char_puts("But you aren't fighting anyone!\n",ch);
return;
}
}
else if ((victim = get_char_room(ch, arg)) == NULL) {
char_puts("They aren't here.\n",ch);
return;
}
if (victim->position < POS_FIGHTING) {
act("You'll have to let $M get back up first.",
ch, NULL, victim, TO_CHAR);
return;
}
if (victim == ch) {
char_puts("You try to bash your brains out, but fail.\n",
ch);
return;
}
if (MOUNTED(victim)) {
char_puts("You can't bash a riding one!\n", ch);
return;
}
if (IS_AFFECTED(ch,AFF_CHARM) && ch->master == victim) {
act("But $N is your friend!", ch, NULL, victim, TO_CHAR);
return;
}
if (is_affected(victim, gsn_protective_shield)) {
act_puts("Your bash seems to slide around $N.",
ch, NULL, victim, TO_CHAR, POS_FIGHTING);
act_puts("$n's bash slides off your protective shield.",
ch, NULL, victim, TO_VICT, POS_FIGHTING);
act_puts("$n's bash seems to slide around $N.",
ch, NULL, victim, TO_NOTVICT, POS_FIGHTING);
return;
}
if (is_safe(ch, victim))
return;
/* modifiers */
/* size and weight */
chance += ch->carry_weight / 25;
chance -= victim->carry_weight / 20;
if (ch->size < victim->size)
chance += (ch->size - victim->size) * 25;
else
chance += (ch->size - victim->size) * 10;
/* stats */
chance += get_curr_stat(ch, STAT_STR);
chance -= get_curr_stat(victim, STAT_DEX) * 4/3;
if (IS_AFFECTED(ch, AFF_FLYING))
chance -= 10;
/* speed */
if (IS_NPC(ch) && IS_SET(ch->pIndexData->off_flags, OFF_FAST))
chance += 10;
if (IS_NPC(victim) && IS_SET(victim->pIndexData->off_flags, OFF_FAST))
chance -= 20;
/* level */
chance += (ch->level - victim->level) * 2;
/*RESET_WAIT_STATE(ch);*/
fighting = (ch->fighting != NULL);
/* now the attack */
if (number_percent() < chance) {
act("$n sends you sprawling with a powerful bash!",
ch, NULL, victim, TO_VICT);
act("You slam into $N, and send $M flying!",
ch, NULL, victim, TO_CHAR);
act("$n sends $N sprawling with a powerful bash.",
ch, NULL, victim, TO_NOTVICT);
check_improve(ch, gsn_bash, TRUE, 1);
wait = 3;
switch(number_bits(2)) {
case 0: wait = 1; break;
case 1: wait = 2; break;
case 2: wait = 4; break;
case 3: wait = 3; break;
}
WAIT_STATE(victim, wait * PULSE_VIOLENCE);
WAIT_STATE(ch, SKILL(gsn_bash)->beats);
victim->position = POS_RESTING;
damage_bash = (ch->damroll / 2) +
number_range(4, 4 + 4* ch->size + chance/10);
damage(ch, victim, damage_bash, gsn_bash, DAM_BASH, TRUE);
}
else {
damage(ch, victim, 0, gsn_bash, DAM_BASH, TRUE);
act("You fall flat on your face!",
ch, NULL, victim, TO_CHAR);
act("$n falls flat on $s face.",
ch, NULL, victim, TO_NOTVICT);
act("You evade $n's bash, causing $m to fall flat on $s face.",
ch, NULL, victim, TO_VICT);
check_improve(ch, gsn_bash, FALSE, 1);
ch->position = POS_RESTING;
WAIT_STATE(ch, SKILL(gsn_bash)->beats * 3/2);
}
if (check_yell(ch, victim, fighting))
doprintf(do_yell, victim,
"Help! %s is bashing me!", PERS(ch, victim));
}
void do_dirt(CHAR_DATA *ch, const char *argument)
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
bool fighting;
int chance;
if (MOUNTED(ch)) {
char_puts("You can't dirt while riding!\n", ch);
return;
}
one_argument(argument, arg);
if ((chance = get_skill(ch, gsn_dirt)) == 0) {
char_puts("You get your feet dirty.\n", ch);
return;
}
WAIT_STATE(ch, SKILL(gsn_dirt)->beats);
if (arg[0] == '\0') {
victim = ch->fighting;
if (victim == NULL) {
char_puts("But you aren't in combat!\n", ch);
return;
}
}
else if ((victim = get_char_room(ch, arg)) == NULL) {
char_puts("They aren't here.\n", ch);
return;
}
if (IS_AFFECTED(ch, AFF_FLYING)) {
char_puts("While flying?\n", ch);
return;
}
if (IS_AFFECTED(victim, AFF_BLIND)) {
act("$e's already been blinded.", ch, NULL, victim, TO_CHAR);
return;
}
if (victim == ch) {
char_puts("Very funny.\n", ch);
return;
}
if (MOUNTED(victim)) {
char_puts("You can't dirt a riding one!\n", ch);
return;
}
if (IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim) {
act("But $N is such a good friend!", ch, NULL, victim, TO_CHAR);
return;
}
if (is_safe(ch, victim))
return;
/* modifiers */
/* dexterity */
chance += get_curr_stat(ch, STAT_DEX);
chance -= 2 * get_curr_stat(victim, STAT_DEX);
/* speed */
if ((IS_NPC(ch) && IS_SET(ch->pIndexData->off_flags, OFF_FAST))
|| IS_AFFECTED(ch, AFF_HASTE))
chance += 10;
if ((IS_NPC(victim) && IS_SET(victim->pIndexData->off_flags, OFF_FAST))
|| IS_AFFECTED(victim, AFF_HASTE))
chance -= 25;
/* level */
chance += (ch->level - victim->level) * 2;
if (chance % 5 == 0)
chance += 1;
/* terrain */
switch(ch->in_room->sector_type) {
case(SECT_INSIDE): chance -= 20; break;
case(SECT_CITY): chance -= 10; break;
case(SECT_FIELD): chance += 5; break;
case(SECT_FOREST): break;
case(SECT_HILLS): break;
case(SECT_MOUNTAIN): chance -= 10; break;
case(SECT_WATER_SWIM): chance = 0; break;
case(SECT_WATER_NOSWIM): chance = 0; break;
case(SECT_AIR): chance = 0; break;
case(SECT_DESERT): chance += 10; break;
}
if (chance == 0) {
char_puts("There isn't any dirt to kick.\n",ch);
return;
}
fighting = (ch->fighting != NULL);
/* now the attack */
if (number_percent() < chance) {
AFFECT_DATA af;
act("$n is blinded by the dirt in $s eyes!",
victim, NULL, NULL, TO_ROOM);
char_puts("You can't see a thing!\n", victim);
check_improve(ch, gsn_dirt, TRUE, 2);
af.where = TO_AFFECTS;
af.type = gsn_dirt;
af.level = ch->level;
af.duration = 0;
af.location = APPLY_HITROLL;
af.modifier = -4;
af.bitvector = AFF_BLIND;
affect_to_char(victim, &af);
damage(ch, victim, number_range(2, 5),
gsn_dirt, DAM_NONE, FALSE);
}
else {
damage(ch, victim, 0, gsn_dirt, DAM_NONE, TRUE);
check_improve(ch, gsn_dirt, FALSE, 2);
}
if (check_yell(ch, victim, fighting))
doprintf(do_yell, victim,
"Help! %s just kicked dirt into my eyes!",
PERS(ch,victim));
}
void do_trip(CHAR_DATA *ch, const char *argument)
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
bool fighting;
int chance;
if (MOUNTED(ch)) {
char_puts("You can't trip while riding!\n", ch);
return;
}
one_argument(argument, arg);
if ((chance = get_skill(ch,gsn_trip)) == 0) {
char_puts("Tripping? What's that?\n", ch);
return;
}
if (arg[0] == '\0') {
victim = ch->fighting;
if (victim == NULL) {
char_puts("But you aren't fighting anyone!\n",ch);
return;
}
}
else if ((victim = get_char_room(ch, arg)) == NULL) {
char_puts("They aren't here.\n",ch);
return;
}
if (MOUNTED(victim)) {
char_puts("You can't trip a riding one!\n", ch);
return;
}
if (IS_AFFECTED(victim, AFF_FLYING)) {
act("$S feet aren't on the ground.", ch, NULL, victim, TO_CHAR);
return;
}
if (victim->position < POS_FIGHTING) {
act("$N is already down.", ch, NULL, victim, TO_CHAR);
return;
}
if (victim == ch) {
char_puts("You fall flat on your face!\n", ch);
WAIT_STATE(ch, 2 * SKILL(gsn_trip)->beats);
act("$n trips over $s own feet!", ch, NULL, NULL, TO_ROOM);
return;
}
if (IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim) {
act("$N is your beloved master.", ch, NULL, victim, TO_CHAR);
return;
}
if (is_safe(ch, victim))
return;
/* modifiers */
/* size */
if (ch->size < victim->size)
/* bigger = harder to trip */
chance += (ch->size - victim->size) * 10;
/* dex */
chance += get_curr_stat(ch, STAT_DEX);
chance -= get_curr_stat(victim, STAT_DEX) * 3 / 2;
if (IS_AFFECTED(ch,AFF_FLYING))
chance -= 10;
/* speed */
if ((IS_NPC(ch) && IS_SET(ch->pIndexData->off_flags, OFF_FAST))
|| IS_AFFECTED(ch, AFF_HASTE))
chance += 10;
if ((IS_NPC(victim) && IS_SET(victim->pIndexData->off_flags, OFF_FAST))
|| IS_AFFECTED(victim, AFF_HASTE))
chance -= 20;
/* level */
chance += (ch->level - victim->level) * 2;
RESET_WAIT_STATE(ch);
fighting = (ch->fighting != NULL);
/* now the attack */
if (number_percent() < chance) {
act("$n trips you and you go down!", ch, NULL, victim, TO_VICT);
act("You trip $N and $N goes down!",
ch, NULL, victim, TO_CHAR);
act("$n trips $N, sending $M to the ground.",
ch, NULL, victim, TO_NOTVICT);
check_improve(ch, gsn_trip, TRUE, 1);
WAIT_STATE(victim, 2 * PULSE_VIOLENCE);
WAIT_STATE(ch, SKILL(gsn_trip)->beats);
victim->position = POS_RESTING;
damage(ch, victim, number_range(2, 2 + 2*victim->size),
gsn_trip, DAM_BASH, TRUE);
}
else {
damage(ch, victim, 0, gsn_trip, DAM_BASH, TRUE);
WAIT_STATE(ch, SKILL(gsn_trip)->beats*2/3);
check_improve(ch, gsn_trip, FALSE, 1);
}
if (check_yell(ch, victim, fighting))
doprintf(do_yell, victim,
"Help! %s just tripped me!", PERS(ch, victim));
}
bool backstab_ok(CHAR_DATA *ch, CHAR_DATA *victim)
{
if (victim->fighting) {
if (ch)
char_puts("You can't backstab a fighting person.\n",
ch);
return FALSE;
}
if (victim->hit < 7 * victim->max_hit / 10 && IS_AWAKE(victim)) {
if (ch)
act("$N is hurt and suspicious... "
"you couldn't sneak up.",
ch, NULL, victim, TO_CHAR);
return FALSE;
}
if (current_time - victim->last_fight_time < 300 && IS_AWAKE(victim)) {
if (ch)
act("$N is suspicious... you couldn't sneak up.",
ch, NULL, victim, TO_CHAR);
return FALSE;
}
return TRUE;
}
void backstab(CHAR_DATA *ch, CHAR_DATA *victim, int chance)
{
if (!IS_AWAKE(victim)
|| number_percent() < chance) {
check_improve(ch, gsn_backstab, TRUE, 1);
if (number_percent() <
get_skill(ch, gsn_dual_backstab) * 8 / 10) {
check_improve(ch, gsn_dual_backstab, TRUE, 1);
one_hit(ch, victim, gsn_backstab, WEAR_WIELD);
one_hit(ch, victim, gsn_dual_backstab, WEAR_WIELD);
}
else {
check_improve(ch, gsn_dual_backstab, FALSE, 1);
one_hit(ch, victim, gsn_backstab,WEAR_WIELD);
}
}
else {
check_improve(ch, gsn_backstab, FALSE, 1);
damage(ch, victim, 0, gsn_backstab, DAM_NONE, TRUE);
}
if (!IS_NPC(victim) && victim->position == POS_FIGHTING)
doprintf(do_yell, victim,
"Die, %s! You are backstabbing scum!",
PERS(ch,victim));
}
void do_backstab(CHAR_DATA *ch, const char *argument)
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
OBJ_DATA *obj;
int chance;
one_argument(argument, arg);
if (MOUNTED(ch)) {
char_puts("You can't backstab while riding!\n", ch);
return;
}
if ((chance = get_skill(ch, gsn_backstab)) == 0) {
char_puts("You don't know how to backstab.\n",ch);
return;
}
if ((obj = get_eq_char(ch, WEAR_WIELD)) == NULL) {
char_puts("You need to wield a weapon to backstab.\n", ch);
return;
}
if (attack_table[obj->value[3]].damage != DAM_PIERCE) {
char_puts("You need to wield a piercing weapon "
"to backstab.\n", ch);
return;
}
if (arg[0] == '\0') {
char_puts("Backstab whom?\n", ch);
return;
}
WAIT_STATE(ch, SKILL(gsn_backstab)->beats);
if ((victim = get_char_room(ch, arg)) == NULL) {
char_puts("They aren't here.\n", ch);
return;
}
if (victim == ch) {
char_puts("How can you sneak up on yourself?\n", ch);
return;
}
if (is_safe(ch, victim))
return;
if (!backstab_ok(ch, victim))
return;
backstab(ch, victim, chance);
}
void do_cleave(CHAR_DATA *ch, const char *argument)
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
OBJ_DATA *obj;
int chance;
if (MOUNTED(ch)) {
char_puts("You can't cleave while riding!\n", ch);
return;
}
one_argument(argument, arg);
if (ch->master != NULL && IS_NPC(ch))
return;
if ((chance = get_skill(ch, gsn_cleave)) == 0) {
char_puts("You don't know how to cleave.\n",ch);
return;
}
if (arg[0] == '\0') {
char_puts("Cleave whom?\n", ch);
return;
}
WAIT_STATE(ch, SKILL(gsn_cleave)->beats);
if ((victim = get_char_room(ch, arg)) == NULL) {
char_puts("They aren't here.\n", ch);
return;
}
if (victim == ch) {
char_puts("How can you sneak up on yourself?\n", ch);
return;
}
if ((obj = get_eq_char(ch, WEAR_WIELD)) == NULL) {
char_puts("You need to wield a weapon to cleave.\n", ch);
return;
}
if ((obj->value[0] != WEAPON_AXE) && (obj->value[0] != WEAPON_SWORD)) {
char_puts("You must wield axe or sword to cleave.\n", ch);
return;
}
if (victim->fighting != NULL) {
char_puts("You can't cleave a fighting person.\n", ch);
return;
}
if ((victim->hit < (0.9 * victim->max_hit))
&& (IS_AWAKE(victim))) {
act("$N is hurt and suspicious ... you can't sneak up.",
ch, NULL, victim, TO_CHAR);
return;
}
if (is_safe(ch, victim))
return;
if (!IS_AWAKE(victim)
|| IS_NPC(ch)
|| number_percent() < chance) {
check_improve(ch, gsn_cleave, TRUE, 1);
one_hit(ch, victim, gsn_cleave,WEAR_WIELD);
}
else {
check_improve(ch, gsn_cleave, FALSE, 1);
damage(ch, victim, 0, gsn_cleave, DAM_NONE, TRUE);
}
if (!IS_NPC(victim) && victim->position==POS_FIGHTING)
doprintf(do_yell,victim,"Die, %s, you butchering fool!",PERS(ch,victim));
}
void do_ambush(CHAR_DATA *ch, const char *argument)
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
int chance;
if (MOUNTED(ch)) {
char_puts("You can't ambush while riding!\n", ch);
return;
}
one_argument(argument, arg);
if ((chance = get_skill(ch, gsn_ambush)) == 0) {
char_puts("You don't know how to ambush.\n", ch);
return;
}
if (arg[0] == '\0') {
char_puts("Ambush whom?\n", ch);
return;
}
WAIT_STATE(ch, SKILL(gsn_ambush)->beats);
if ((victim = get_char_room(ch, arg)) == NULL) {
char_puts("They aren't here.\n", ch);
return;
}
if (victim == ch) {
char_puts("How can you ambush yourself?\n", ch);
return;
}
if (!IS_AFFECTED(ch, AFF_CAMOUFLAGE) || can_see(victim, ch)) {
char_puts("But they can see you.\n", ch);
return;
}
if (is_safe(ch, victim))
return;
if (!IS_AWAKE(victim)
|| IS_NPC(ch)
|| number_percent() < chance) {
check_improve(ch, gsn_ambush, TRUE, 1);
one_hit(ch, victim, gsn_ambush,WEAR_WIELD);
}
else {
check_improve(ch, gsn_ambush, FALSE, 1);
damage(ch, victim, 0, gsn_ambush, DAM_NONE, TRUE);
}
if (!IS_NPC(victim) && victim->position==POS_FIGHTING)
doprintf(do_yell,victim,"Help! I've been ambushed by %s!",PERS(ch,victim));
}
void do_rescue(CHAR_DATA *ch, const char *argument)
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
CHAR_DATA *fch;
one_argument(argument, arg);
if (arg[0] == '\0') {
char_puts("Rescue whom?\n", ch);
return;
}
WAIT_STATE(ch, SKILL(gsn_rescue)->beats);
if ((victim = get_char_room(ch, arg)) == NULL) {
char_puts("They aren't here.\n", ch);
return;
}
if (victim == ch) {
char_puts("What about fleeing instead?\n", ch);
return;
}
if (!IS_NPC(ch) && IS_NPC(victim)) {
char_puts("Doesn't need your help!\n", ch);
return;
}
if (ch->fighting == victim) {
char_puts("Too late.\n", ch);
return;
}
if ((fch = victim->fighting) == NULL) {
char_puts("That person is not fighting right now.\n", ch);
return;
}
if (IS_NPC(ch) && ch->master != NULL && IS_NPC(victim))
return;
if (ch->master != NULL && is_safe(ch->master, fch))
return;
if (is_safe(ch, fch))
return;
if (number_percent() > get_skill(ch,gsn_rescue)) {
char_puts("You fail the rescue.\n", ch);
check_improve(ch, gsn_rescue, FALSE, 1);
return;
}
act("You rescue $N!", ch, NULL, victim, TO_CHAR );
act("$n rescues you!", ch, NULL, victim, TO_VICT );
act("$n rescues $N!", ch, NULL, victim, TO_NOTVICT);
check_improve(ch, gsn_rescue, TRUE, 1);
stop_fighting(fch, FALSE);
stop_fighting(victim, FALSE);
set_fighting(ch, fch);
set_fighting(fch, ch);
}
void do_kick(CHAR_DATA *ch, const char *argument)
{
CHAR_DATA *victim;
int kick_dam;
int chance;
if (MOUNTED(ch)) {
char_puts("You can't kick while riding!\n", ch);
return;
}
if ((chance = get_skill(ch, gsn_kick)) == 0) {
char_puts("You better leave the martial arts to fighters.\n",
ch);
return;
}
if ((victim = ch->fighting) == NULL) {
char_puts("You aren't fighting anyone.\n", ch);
return;
}
if (IS_AFFECTED(ch, AFF_FLYING))
chance = chance * 110 / 100;
WAIT_STATE(ch, SKILL(gsn_kick)->beats);
if (IS_NPC(ch) || number_percent() < chance) {
kick_dam = number_range(1, ch->level);
if ((ch->class == CLASS_SAMURAI)
&& (get_eq_char(ch, WEAR_FEET) == NULL))
kick_dam *= 2;
kick_dam += ch->damroll / 2;
damage(ch, victim, kick_dam, gsn_kick, DAM_BASH, TRUE);
check_improve(ch, gsn_kick, TRUE, 1);
}
else {
damage(ch, victim, 0, gsn_kick, DAM_BASH, TRUE);
check_improve(ch, gsn_kick, FALSE, 1);
}
}
void do_circle(CHAR_DATA *ch, const char *argument)
{
CHAR_DATA *victim;
CHAR_DATA *rch;
int chance;
OBJ_DATA *obj;
if (MOUNTED(ch)) {
char_puts("You can't circle while riding!\n", ch);
return;
}
if ((chance = get_skill(ch, gsn_circle)) == 0) {
char_puts("You don't know how to circle.\n", ch);
return;
}
if ((victim = ch->fighting) == NULL) {
char_puts("You aren't fighting anyone.\n", ch);
return;
}
if ((obj = get_eq_char(ch, WEAR_WIELD)) == NULL
|| attack_table[obj->value[3]].damage != DAM_PIERCE) {
char_puts("You must wield a piercing weapon to circle stab.\n",
ch);
return;
}
if (is_safe(ch, victim))
return;
WAIT_STATE(ch, SKILL(gsn_circle)->beats);
for (rch = ch->in_room->people; rch; rch = rch->next_in_room) {
if (rch->fighting == ch) {
char_puts("You can't circle while defending yourself.\n",
ch);
return;
}
}
if (number_percent() < chance) {
one_hit(ch, victim, gsn_circle, WEAR_WIELD);
check_improve(ch, gsn_circle, TRUE, 1);
}
else {
damage(ch, victim, 0, gsn_circle, TYPE_UNDEFINED, TRUE);
check_improve(ch, gsn_circle, FALSE, 1);
}
}
void do_disarm(CHAR_DATA *ch, const char *argument)
{
CHAR_DATA *victim;
OBJ_DATA *wield;
OBJ_DATA *vwield;
int chance, ch_weapon, vict_weapon;
int loc = WEAR_WIELD;
char arg[MAX_INPUT_LENGTH];
int hth = 0;
if (ch->master != NULL && IS_NPC(ch))
return;
if ((chance = get_skill(ch, gsn_disarm)) == 0) {
char_puts("You don't know how to disarm opponents.\n", ch);
return;
}
if ((wield = get_eq_char(ch, WEAR_WIELD)) == NULL
&& (hth = get_skill(ch, gsn_hand_to_hand)) == 0) {
char_puts("You must wield a weapon to disarm.\n", ch);
return;
}
if ((victim = ch->fighting) == NULL) {
char_puts("You aren't fighting anyone.\n", ch);
return;
}
argument = one_argument(argument, arg);
if (arg[0] && !str_prefix(arg, "second"))
loc = WEAR_SECOND_WIELD;
if ((vwield = get_eq_char(victim, loc)) == NULL) {
char_puts("Your opponent is not wielding a weapon.\n", ch);
return;
}
/* find weapon skills */
ch_weapon = get_weapon_skill(ch, get_weapon_sn(wield));
vict_weapon = get_weapon_skill(victim, get_weapon_sn(vwield));
/* modifiers */
/* skill */
if (wield == NULL)
chance = chance * hth/150;
else
chance = chance * ch_weapon/100;
chance += (ch_weapon/2 - vict_weapon) / 2;
/* dex vs. strength */
chance += get_curr_stat(ch,STAT_DEX);
chance -= 2 * get_curr_stat(victim,STAT_STR);
/* level */
chance += (ch->level - victim->level) * 2;
/* and now the attack */
WAIT_STATE(ch, SKILL(gsn_disarm)->beats);
if (number_percent() < chance) {
disarm(ch, victim, vwield);
check_improve(ch, gsn_disarm, TRUE, 1);
}
else {
act("You fail to disarm $N.", ch, NULL, victim, TO_CHAR);
act("$n tries to disarm you, but fails.",
ch, NULL, victim, TO_VICT);
act("$n tries to disarm $N, but fails.",
ch, NULL, victim, TO_NOTVICT);
check_improve(ch, gsn_disarm, FALSE, 1);
}
}
void do_nerve(CHAR_DATA *ch, const char *argument)
{
CHAR_DATA *victim;
char arg[MAX_INPUT_LENGTH];
int chance;
if (MOUNTED(ch)) {
char_puts("You can't nerve while riding!\n", ch);
return;
}
one_argument(argument,arg);
if ((chance = get_skill(ch, gsn_nerve)) == 0) {
char_puts("Huh?\n", ch);
return;
}
if (ch->fighting == NULL) {
char_puts("You aren't fighting anyone.\n", ch);
return;
}
victim = ch->fighting;
if (is_affected(ch,gsn_nerve)) {
char_puts("You cannot weaken that character any more.\n",
ch);
return;
}
if (is_safe(ch,victim))
return;
WAIT_STATE(ch, SKILL(gsn_nerve)->beats);
if (IS_NPC(ch)
|| number_percent() < (chance + ch->level
+ get_curr_stat(ch,STAT_DEX))/2) {
AFFECT_DATA af;
af.where = TO_AFFECTS;
af.type = gsn_nerve;
af.level = ch->level;
af.duration = ch->level * PULSE_VIOLENCE/PULSE_TICK;
af.location = APPLY_STR;
af.modifier = -3;
af.bitvector = 0;
affect_to_char(victim,&af);
act("You weaken $N with your nerve pressure.",
ch, NULL, victim, TO_CHAR);
act("$n weakens you with $s nerve pressure.",
ch, NULL, victim, TO_VICT);
act("$n weakens $N with $s nerve pressure.",
ch, NULL, victim, TO_NOTVICT);
check_improve(ch, gsn_nerve, TRUE, 1);
}
else {
char_puts("You press the wrong points and fail.\n",ch);
act("$n tries to weaken you with nerve pressure, but fails.",
ch, NULL, victim, TO_VICT);
act("$n tries to weaken $N with nerve pressure, but fails.",
ch, NULL, victim, TO_NOTVICT);
check_improve(ch, gsn_nerve, FALSE, 1);
}
multi_hit(victim,ch,TYPE_UNDEFINED);
}
void do_endure(CHAR_DATA *ch, const char *argument)
{
AFFECT_DATA af;
int chance;
if (IS_NPC(ch)) {
char_puts("You have no endurance whatsoever.\n", ch);
return;
}
if ((chance = get_skill(ch, gsn_endure)) == 0) {
char_puts("You lack the concentration.\n", ch);
return;
}
if (is_affected(ch,gsn_endure)) {
char_puts("You cannot endure more concentration.\n", ch);
return;
}
WAIT_STATE(ch, SKILL(gsn_endure)->beats);
af.where = TO_AFFECTS;
af.type = gsn_endure;
af.level = ch->level;
af.duration = ch->level / 4;
af.location = APPLY_SAVING_SPELL;
af.modifier = - chance / 10;
af.bitvector = 0;
affect_to_char(ch, &af);
char_puts("You prepare yourself for magical encounters.\n", ch);
act("$n concentrates for a moment, then resumes $s position.",
ch, NULL, NULL, TO_ROOM);
check_improve(ch, gsn_endure, TRUE, 1);
}
void do_tame(CHAR_DATA *ch, const char *argument)
{
CHAR_DATA *victim;
char arg[MAX_INPUT_LENGTH];
int chance;
if ((chance = get_skill(ch, gsn_tame)) == 0) {
char_puts("Huh?\n", ch);
return;
}
one_argument(argument, arg);
if (arg[0] == '\0') {
char_puts("You are beyond taming.\n", ch);
act("$n tries to tame $mself but fails miserably.",
ch, NULL, NULL, TO_ROOM);
return;
}
WAIT_STATE(ch, SKILL(gsn_tame)->beats);
if ((victim = get_char_room(ch,arg)) == NULL) {
char_puts("They're not here.\n", ch);
return;
}
if (IS_NPC(ch)) {
char_puts("Why don't you tame yourself first?", ch);
return;
}
if (!IS_NPC(victim)) {
act("$N is beyond taming.", ch, NULL, victim, TO_CHAR);
return;
}
if (!IS_SET(victim->pIndexData->act, ACT_AGGRESSIVE)) {
act("$N is not usually aggressive.", ch, NULL, victim, TO_CHAR);
return;
}
if (number_percent() < chance + 15 + 4*(ch->level - victim->level)) {
SET_BIT(victim->affected_by, AFF_CALM);
char_puts("You calm down.\n", victim);
act("You calm $N down.", ch, NULL, victim, TO_CHAR);
act("$n calms $N down.", ch, NULL, victim, TO_NOTVICT);
stop_fighting(victim, TRUE);
check_improve(ch, gsn_tame, TRUE, 1);
}
else {
char_puts("You failed.\n",ch);
act("$n tries to calm down $N but fails.",
ch, NULL, victim, TO_NOTVICT);
act("$n tries to calm you down but fails.",
ch, NULL, victim, TO_VICT);
check_improve(ch, gsn_tame, FALSE, 1);
}
}
void do_assassinate(CHAR_DATA *ch, const char *argument)
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
int chance;
if (MOUNTED(ch)) {
char_puts("You can't assassinate while riding!\n", ch);
return;
}
one_argument(argument, arg);
if (ch->master != NULL && IS_NPC(ch))
return;
if ((chance = get_skill(ch, gsn_assassinate)) == 0) {
char_puts("You don't know how to assassinate.\n", ch);
return;
}
if (IS_AFFECTED(ch, AFF_CHARM)) {
char_puts("You don't want to kill your beloved master.\n", ch);
return;
}
if (arg[0] == '\0') {
char_puts("Assassinate whom?\n", ch);
return;
}
WAIT_STATE(ch, SKILL(gsn_assassinate)->beats);
if ((victim = get_char_room(ch, arg)) == NULL) {
char_puts("They aren't here.\n", ch);
return;
}
if (victim == ch) {
char_puts("Suicide is against your way.\n", ch);
return;
}
if (IS_IMMORTAL(victim) && !IS_NPC(victim)) {
char_puts("Your hands pass through.\n", ch);
return;
}
if (victim->fighting != NULL) {
char_puts("You can't assassinate a fighting person.\n", ch);
return;
}
if ((get_eq_char(ch, WEAR_WIELD) != NULL)
|| (get_eq_char(ch, WEAR_HOLD ) != NULL)) {
char_puts("You need both hands free to assassinate somebody.\n",
ch);
return;
}
if (victim->hit < victim->max_hit
&& can_see(victim, ch) && IS_AWAKE(victim)) {
act("$N is hurt and suspicious ... you can't sneak up.",
ch, NULL, victim, TO_CHAR);
return;
}
/*
if (IS_SET(victim->imm_flags, IMM_WEAPON)) {
act("$N seems immune to your assassination attempt.",
ch, NULL, victim, TO_CHAR);
act("$N seems immune to $n's assassination attempt.",
ch, NULL, victim, TO_ROOM);
return;
}
*/
if (is_safe(ch, victim))
return;
if (number_percent() < chance
&& !IS_CLAN_GUARD(victim)
&& !IS_IMMORTAL(victim))
one_hit(ch, victim, gsn_assassinate,WEAR_WIELD);
else {
check_improve(ch, gsn_assassinate, FALSE, 1);
damage(ch, victim, 0, gsn_assassinate, DAM_NONE, TRUE);
}
if (!IS_NPC(victim) && victim->position==POS_FIGHTING)
doprintf(do_yell,victim,"Help! %s tries to assasinate me!",PERS(ch,victim));
}
void do_caltrops(CHAR_DATA *ch, const char *argument)
{
CHAR_DATA *victim = ch->fighting;
int chance;
if ((chance = get_skill(ch, gsn_caltrops)) == 0) {
char_puts("Caltrops? Is that a dance step?\n", ch);
return;
}
if (victim == NULL) {
char_puts("You must be in combat.\n",ch);
return;
}
if (is_safe(ch,victim))
return;
act("You throw a handful of sharp spikes at the feet of $N.",
ch, NULL, victim, TO_CHAR);
act("$n throws a handful of sharp spikes at your feet!",
ch, NULL, victim, TO_VICT);
WAIT_STATE(ch, SKILL(gsn_caltrops)->beats);
if (!IS_NPC(ch) && number_percent() >= chance) {
damage(ch, victim, 0, gsn_caltrops, DAM_PIERCE, TRUE);
check_improve(ch, gsn_caltrops, FALSE, 1);
return;
}
damage(ch, victim, ch->level, gsn_caltrops, DAM_PIERCE, TRUE);
if (JUST_KILLED(victim))
return;
if (!is_affected(victim, gsn_caltrops)) {
AFFECT_DATA tohit, todam, todex;
tohit.where = TO_AFFECTS;
tohit.type = gsn_caltrops;
tohit.level = ch->level;
tohit.duration = -1;
tohit.location = APPLY_HITROLL;
tohit.modifier = -5;
tohit.bitvector = 0;
affect_to_char(victim, &tohit);
todam.where = TO_AFFECTS;
todam.type = gsn_caltrops;
todam.level = ch->level;
todam.duration = -1;
todam.location = APPLY_DAMROLL;
todam.modifier = -5;
todam.bitvector = 0;
affect_to_char(victim, &todam);
todex.type = gsn_caltrops;
todex.level = ch->level;
todex.duration = -1;
todex.location = APPLY_DEX;
todex.modifier = -5;
todex.bitvector = 0;
affect_to_char(victim, &todex);
act("$N starts limping.", ch, NULL, victim, TO_CHAR);
act("You start to limp.", ch, NULL, victim, TO_VICT);
check_improve(ch, gsn_caltrops, TRUE, 1);
}
}
DECLARE_DO_FUN(do_throw_spear);
void do_throw(CHAR_DATA *ch, const char *argument)
{
CHAR_DATA *victim;
char arg[MAX_INPUT_LENGTH];
int chance;
if (MOUNTED(ch)) {
char_puts("You can't throw while riding!\n", ch);
return;
}
argument = one_argument(argument,arg);
if (!str_cmp(arg, "spear")) {
do_throw_spear(ch, argument);
return;
}
if ((chance = get_skill(ch, gsn_throw)) == 0) {
char_puts("A clutz like you couldn't throw down a worm.\n",
ch);
return;
}
if (IS_AFFECTED(ch, AFF_FLYING)) {
char_puts("Your feet should touch the ground to balance\n",
ch);
return;
}
if ((victim = ch->fighting) == NULL) {
char_puts("You aren't fighting anyone.\n", ch);
return;
}
if (IS_AFFECTED(ch,AFF_CHARM) && ch->master == victim) {
act("But $N is your friend!", ch, NULL, victim, TO_CHAR);
return;
}
if (is_safe(ch,victim))
return;
WAIT_STATE(ch, SKILL(gsn_throw)->beats);
if (is_affected(victim, gsn_protective_shield)) {
act_puts("You fail to reach $s arm.",ch,NULL,victim, TO_CHAR,
POS_FIGHTING);
act_puts("$n fails to throw you.", ch, NULL, victim, TO_VICT,
POS_FIGHTING);
act_puts("$n fails to throw $N.", ch, NULL, victim, TO_NOTVICT,
POS_FIGHTING);
return;
}
if (ch->size < victim->size)
chance += (ch->size - victim->size) * 10;
else
chance += (ch->size - victim->size) * 25;
/* stats */
chance += get_curr_stat(ch,STAT_STR);
chance -= get_curr_stat(victim,STAT_DEX) * 4/3;
if (IS_AFFECTED(victim, AFF_FLYING))
chance += 10;
/* speed */
if (IS_NPC(ch) && IS_SET(ch->pIndexData->off_flags, OFF_FAST))
chance += 10;
if (IS_NPC(victim) && IS_SET(victim->pIndexData->off_flags, OFF_FAST))
chance -= 20;
/* level */
chance += (ch->level - victim->level) * 2;
if (number_percent() < chance) {
act("You throw $N to the ground with stunning force.",
ch, NULL, victim, TO_CHAR);
act("$n throws you to the ground with stunning force.",
ch, NULL, victim, TO_VICT);
act("$n throws $N to the ground with stunning force.",
ch, NULL, victim, TO_NOTVICT);
WAIT_STATE(victim,2 * PULSE_VIOLENCE);
damage(ch, victim,ch->level + get_curr_stat(ch, STAT_STR),
gsn_throw, DAM_BASH, TRUE);
check_improve(ch, gsn_throw, TRUE, 1);
}
else {
act("You fail to grab your opponent.",
ch, NULL, NULL, TO_CHAR);
act("$N tries to throw you, but fails.",
victim, NULL, ch, TO_CHAR);
act("$n tries to grab $N's arm.",
ch, NULL, victim, TO_NOTVICT);
check_improve(ch, gsn_throw, FALSE, 1);
}
}
void do_strangle(CHAR_DATA *ch, const char *argument)
{
CHAR_DATA *victim;
AFFECT_DATA af;
int chance;
if (MOUNTED(ch)) {
char_puts("You can't strangle while riding!\n", ch);
return;
}
if ((chance = get_skill(ch, gsn_strangle)) == 0) {
char_puts("You lack the skill to strangle.\n", ch);
return;
}
if (IS_AFFECTED(ch, AFF_CHARM)) {
char_puts("You don't want to grap your beloved masters' neck.\n",
ch);
return;
}
WAIT_STATE(ch, SKILL(gsn_strangle)->beats);
if ((victim = get_char_room(ch,argument)) == NULL) {
char_puts("You do not see that person here.\n", ch);
return;
}
if (ch == victim) {
char_puts("Even you are not that stupid.\n", ch);
return;
}
if (is_affected(victim, gsn_strangle))
return;
if (is_safe(ch, victim))
return;
SET_FIGHT_TIME(victim);
SET_FIGHT_TIME(ch);
if (number_percent() < chance * 6 /10
&& !IS_CLAN_GUARD(victim)
&& !IS_IMMORTAL(victim)) {
act("You grab hold of $N's neck and put $M to sleep.",
ch, NULL, victim, TO_CHAR);
act("$n grabs hold of your neck and puts you to sleep.",
ch, NULL, victim, TO_VICT);
act("$n grabs hold of $N's neck and puts $M to sleep.",
ch, NULL, victim, TO_NOTVICT);
check_improve(ch, gsn_strangle, TRUE, 1);
af.type = gsn_strangle;
af.where = TO_AFFECTS;
af.level = ch->level;
af.duration = ch->level / 20 + 1;
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = AFF_SLEEP;
affect_join (victim,&af);
if (IS_AWAKE(victim))
victim->position = POS_SLEEPING;
}
else {
damage(ch,victim, 0, gsn_strangle, DAM_NONE, TRUE);
check_improve(ch, gsn_strangle, FALSE, 1);
if (!IS_NPC(victim)) doprintf(do_yell, victim,
"Help! I'm being strangled by %s", PERS(ch,victim));
}
}
void do_blackjack(CHAR_DATA *ch, const char *argument)
{
CHAR_DATA *victim;
AFFECT_DATA af;
int chance;
if (MOUNTED(ch)) {
char_puts("You can't blackjack while riding!\n", ch);
return;
}
if ((chance = get_skill(ch, gsn_blackjack)) == 0) {
char_puts("Huh?\n", ch);
return;
}
WAIT_STATE(ch, SKILL(gsn_blackjack)->beats);
if ((victim = get_char_room(ch,argument)) == NULL) {
char_puts("You do not see that person here.\n", ch);
return;
}
if (ch == victim) {
char_puts("You idiot?! Blackjack your self?!\n", ch);
return;
}
if (IS_AFFECTED(ch, AFF_CHARM)) {
char_puts("You don't want to hit your beloved masters' head with a full filled jack.\n",
ch);
return;
}
if (IS_AFFECTED(victim,AFF_SLEEP)) {
act("$E is already asleep.", ch, NULL, victim, TO_CHAR);
return;
}
if (is_safe(ch,victim))
return;
SET_FIGHT_TIME(victim);
SET_FIGHT_TIME(ch);
chance /= 2;
chance += URANGE(0, (get_curr_stat(ch, STAT_DEX)-20)*2, 10);
chance += can_see(victim, ch) ? 0 : 5;
if (IS_NPC(victim) && victim->pIndexData->pShop != NULL)
chance -= 40;
if (number_percent() < chance
&& !IS_CLAN_GUARD(victim)
&& !IS_IMMORTAL(victim)) {
act("You hit $N's head with a lead filled sack.",
ch, NULL, victim, TO_CHAR);
act("You feel a sudden pain erupts through your skull!",
ch, NULL, victim, TO_VICT);
act("$n whacks $N at the back of $S head with a heavy looking sack! *OUCH*",
ch, NULL, victim, TO_NOTVICT);
check_improve(ch, gsn_blackjack, TRUE, 1);
af.type = gsn_blackjack;
af.where = TO_AFFECTS;
af.level = ch->level;
af.duration = ch->level / 15 + 1;
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = AFF_SLEEP;
affect_join (victim,&af);
if (IS_AWAKE(victim))
victim->position = POS_SLEEPING;
}
else {
damage(ch, victim, ch->level/2, gsn_blackjack, DAM_NONE, TRUE);
check_improve(ch, gsn_blackjack, FALSE, 1);
if (!IS_NPC(victim))
doprintf(do_yell, victim,
"Help! I'm being blackjacked by %s", PERS(ch, victim));
}
}
void do_bloodthirst(CHAR_DATA *ch, const char *argument)
{
int chance, hp_percent;
if ((chance = get_skill(ch, gsn_bloodthirst)) == 0) {
char_puts("You're not that thirsty.\n", ch);
return;
}
if (IS_AFFECTED(ch, AFF_BLOODTHIRST)) {
char_puts("Your thirst for blood continues.\n", ch);
return;
}
if (IS_AFFECTED(ch, AFF_CALM)) {
char_puts("You're feeling to mellow to be bloodthirsty.\n",
ch);
return;
}
if (ch->fighting == NULL) {
char_puts("You need to be fighting.\n", ch);
return;
}
/* modifiers */
hp_percent = 100 * ch->hit/ch->max_hit;
chance += 25 - hp_percent/2;
if (number_percent() < chance) {
AFFECT_DATA af;
WAIT_STATE(ch, PULSE_VIOLENCE);
char_puts("You hunger for blood!\n", ch);
act("$n gets a bloodthirsty look in $s eyes.",
ch, NULL, NULL, TO_ROOM);
check_improve(ch, gsn_bloodthirst, TRUE, 2);
af.where = TO_AFFECTS;
af.type = gsn_bloodthirst;
af.level = ch->level;
af.duration = 2 + ch->level / 18;
af.modifier = 5 + ch->level / 4;
af.bitvector = AFF_BLOODTHIRST;
af.location = APPLY_HITROLL;
affect_to_char(ch, &af);
af.location = APPLY_DAMROLL;
affect_to_char(ch, &af);
af.modifier = - UMIN(ch->level - 5,35);
af.location = APPLY_AC;
affect_to_char(ch, &af);
}
else {
WAIT_STATE(ch,3 * PULSE_VIOLENCE);
char_puts("You feel bloodthirsty for a moment, but it passes.\n",
ch);
check_improve(ch, gsn_bloodthirst, FALSE, 2);
}
}
void do_spellbane(CHAR_DATA *ch, const char *argument)
{
AFFECT_DATA af;
int chance;
if ((chance = get_skill(ch, gsn_spellbane)) == 0) {
char_puts("Huh?\n", ch);
return;
}
if (is_affected(ch, gsn_spellbane)) {
#if 0
char_puts("You are already deflecting spells.\n", ch);
return;
#endif
affect_strip(ch, gsn_spellbane);
}
WAIT_STATE(ch, SKILL(gsn_spellbane)->beats);
af.where = TO_AFFECTS;
af.type = gsn_spellbane;
af.level = ch->level;
af.duration = -1;
af.location = APPLY_SAVING_SPELL;
af.modifier = -ch->level/4;
af.bitvector = 0;
affect_to_char(ch, &af);
act("Your hatred of magic surrounds you.", ch, NULL, NULL, TO_CHAR);
act("$n fills the air with $s hatred of magic.",
ch, NULL, NULL, TO_ROOM);
check_improve(ch, gsn_spellbane, TRUE, 1);
}
void do_resistance(CHAR_DATA *ch, const char *argument)
{
int chance;
int mana;
if ((chance = get_skill(ch, gsn_resistance)) == 0) {
char_puts("Huh?\n", ch);
return;
}
if (is_affected(ch, gsn_resistance)) {
char_puts("You are as resistant as you will get.\n", ch);
return;
}
mana = SKILL(gsn_resistance)->min_mana;
if (ch->mana < mana) {
char_puts("You cannot muster up the energy.\n", ch);
return;
}
WAIT_STATE(ch, SKILL(gsn_resistance)->beats);
if (number_percent() < chance) {
AFFECT_DATA af;
af.where = TO_AFFECTS;
af.type = gsn_resistance;
af.level = ch->level;
af.duration = ch->level / 6;
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = 0;
affect_to_char(ch, &af);
ch->mana -= mana;
act("You feel tough!", ch, NULL, NULL, TO_CHAR);
act("$n looks tougher.", ch, NULL, NULL, TO_ROOM);
check_improve(ch, gsn_resistance, TRUE, 1);
}
else {
ch->mana -= mana/2;
char_puts("You flex your muscles, "
"but you don't feel tougher.\n", ch);
act("$n flexes $s muscles, trying to look tough.",
ch, NULL, NULL, TO_ROOM);
check_improve(ch, gsn_resistance, FALSE, 1);
}
}
void do_trophy(CHAR_DATA *ch, const char *argument)
{
int trophy_vnum;
OBJ_DATA *trophy;
AFFECT_DATA af;
OBJ_DATA *part;
char arg[MAX_INPUT_LENGTH];
int level;
int chance;
int mana;
char_puts("Sorry this command has been disabled until further notice\n",ch);
return;
if ((chance = get_skill(ch, gsn_trophy)) == 0) {
char_puts("Huh?\n", ch);
return;
}
if (is_affected(ch, gsn_trophy)) {
char_puts("But you've already got one trophy!\n", ch);
return;
}
mana = SKILL(gsn_trophy)->min_mana;
if (ch->mana < mana) {
char_puts("You feel too weak to concentrate on a trophy.\n",
ch);
return;
}
one_argument(argument, arg);
if (arg[0] == '\0') {
char_puts("Make a trophy of what?\n", ch);
return;
}
if ((part = get_obj_carry(ch, arg)) == NULL) {
char_puts("You do not have that body part.\n", ch);
return;
}
if (number_percent() < chance * 2 / 3) {
char_puts("You failed and destroyed it.\n", ch);
extract_obj(part);
return;
}
WAIT_STATE(ch, SKILL(gsn_trophy)->beats);
if (part->pIndexData->vnum == OBJ_VNUM_SLICED_ARM
|| part->pIndexData->vnum == OBJ_VNUM_SLICED_LEG
|| part->pIndexData->vnum == OBJ_VNUM_SEVERED_HEAD
|| part->pIndexData->vnum == OBJ_VNUM_TORN_HEART
|| part->pIndexData->vnum == OBJ_VNUM_GUTS)
trophy_vnum = OBJ_VNUM_BATTLE_PONCHO;
else if (part->pIndexData->vnum == OBJ_VNUM_BRAINS) {
char_puts("Why don't you just eat those instead?\n", ch);
return;
}
else {
char_puts("You can't make a trophy out of that!\n", ch);
return;
}
if (IS_NULLSTR(part->owner)) {
char_puts("Invalid body part.\n", ch);
return;
}
if (!IS_NPC(ch) && number_percent() < chance) {
af.where = TO_AFFECTS;
af.type = gsn_trophy;
af.level = ch->level;
af.duration = ch->level/2;
af.modifier = 0;
af.bitvector = 0;
af.location = 0;
affect_to_char(ch,&af);
if (trophy_vnum != 0) {
level = UMIN(part->level + 5, MAX_LEVEL);
trophy = create_named_obj(get_obj_index(trophy_vnum),
level, part->owner);
trophy->timer = ch->level * 2;
trophy->cost = 0;
trophy->level = ch->level;
ch->mana -= mana;
af.where = TO_OBJECT;
af.type = gsn_trophy;
af.level = level;
af.duration = -1;
af.location = APPLY_DAMROLL;
af.modifier = ch->level / 5;
af.bitvector = 0;
affect_to_obj(trophy, &af);
af.location = APPLY_HITROLL;
af.modifier = ch->level / 5;
af.bitvector = 0;
affect_to_obj(trophy, &af);
af.location = APPLY_INT;
af.modifier = level>20?-2:-1;
affect_to_obj(trophy, &af);
af.location = APPLY_STR;
af.modifier = level>20?2:1;
affect_to_obj(trophy, &af);
trophy->value[0] = ch->level;
trophy->value[1] = ch->level;
trophy->value[2] = ch->level;
trophy->value[3] = ch->level;
obj_to_char(trophy, ch);
check_improve(ch, gsn_trophy, TRUE, 1);
act("You make a poncho from $p!",
ch, part, NULL, TO_CHAR);
act("$n makes a poncho from $p!",
ch, part, NULL, TO_ROOM);
extract_obj(part);
return;
}
}
else {
char_puts("You destroyed it.\n", ch);
extract_obj(part);
ch->mana -= mana/2;
check_improve(ch, gsn_trophy, FALSE, 1);
}
}
void do_truesight(CHAR_DATA *ch, const char *argument)
{
int chance;
if ((chance = get_skill(ch, gsn_truesight)) == 0) {
char_puts("Huh?\n", ch);
return;
}
if (is_affected(ch, gsn_truesight)) {
char_puts("Your eyes are as sharp as they can get.\n", ch);
return;
}
WAIT_STATE(ch, SKILL(gsn_truesight)->beats);
if (number_percent() < chance) {
AFFECT_DATA af;
af.where = TO_AFFECTS;
af.type = gsn_truesight;
af.level = ch->level;
af.duration = ch->level/2 + 5;
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = AFF_DETECT_HIDDEN;
affect_to_char(ch, &af);
af.bitvector = AFF_DETECT_INVIS;
affect_to_char(ch, &af);
af.bitvector = AFF_DETECT_IMP_INVIS;
affect_to_char(ch,&af);
af.bitvector = AFF_ACUTE_VISION;
affect_to_char(ch,&af);
af.bitvector = AFF_DETECT_MAGIC;
affect_to_char(ch,&af);
act("You look around sharply!",ch,NULL,NULL,TO_CHAR);
act("$n looks more enlightened.",ch,NULL,NULL,TO_ROOM);
check_improve(ch,gsn_truesight,TRUE,1);
}
else {
char_puts("You look about sharply, but you don't see "
"anything new.\n" ,ch);
act("$n looks around sharply but doesn't seem enlightened.",
ch,NULL,NULL,TO_ROOM);
check_improve(ch, gsn_truesight, FALSE, 1);
}
}
void do_warcry(CHAR_DATA *ch, const char *argument)
{
AFFECT_DATA af;
int chance;
int mana;
if ((chance = get_skill(ch, gsn_warcry)) == 0) {
char_puts("Huh?\n", ch);
return;
}
if (is_affected(ch,gsn_bless) || is_affected(ch, gsn_warcry)) {
char_puts("You are already blessed.\n",ch);
return;
}
mana = SKILL(gsn_warcry)->min_mana;
if (ch->mana < mana) {
char_puts("You can't concentrate enough right now.\n",ch);
return;
}
WAIT_STATE(ch, SKILL(gsn_warcry)->beats);
if (number_percent() > chance) {
char_puts("You grunt softly.\n", ch);
act("$n makes some soft grunting noises.",
ch, NULL, NULL, TO_ROOM);
ch->mana -= mana/2;
check_improve(ch, gsn_warcry, FALSE, 1);
return;
}
ch->mana -= mana;
check_improve(ch, gsn_warcry, TRUE, 1);
af.where = TO_AFFECTS;
af.type = gsn_warcry;
af.level = ch->level;
af.duration = 6+ch->level;
af.location = APPLY_HITROLL;
af.modifier = ch->level / 8;
af.bitvector = 0;
affect_to_char(ch, &af);
af.location = APPLY_SAVING_SPELL;
af.modifier = 0 - ch->level / 8;
affect_to_char(ch, &af);
char_puts("You feel righteous as you yell out your warcry.\n", ch);
}
void do_guard(CHAR_DATA *ch, const char *argument)
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
int chance;
if ((chance = get_skill(ch, gsn_guard)) == 0) {
char_puts("Huh?\n", ch);
return;
}
one_argument(argument, arg);
if (arg[0] == '\0') {
char_puts("Guard whom?\n", ch);
return;
}
if ((victim = get_char_room(ch, arg)) == NULL) {
char_puts("They aren't here.\n", ch);
return;
}
if (IS_NPC(victim)) {
act("$N doesn't need any of your help!", ch, NULL, victim, TO_CHAR);
return;
}
if (!str_cmp(arg, "none") || !str_cmp(arg, "self") || victim == ch) {
if (ch->guarding == NULL) {
char_puts("You can't guard yourself!\n", ch);
return;
}
act("You stop guarding $N.", ch, NULL, ch->guarding, TO_CHAR);
act("$n stops guarding you.", ch, NULL, ch->guarding, TO_VICT);
act("$n stops guarding $N.", ch, NULL, ch->guarding, TO_NOTVICT);
ch->guarding->guarded_by = NULL;
ch->guarding = NULL;
return;
}
if (ch->guarding == victim) {
act("You're already guarding $N!", ch, NULL, victim, TO_CHAR);
return;
}
if (ch->guarding != NULL) {
char_puts("But you're already guarding someone else!\n", ch);
return;
}
if (victim->guarded_by != NULL) {
act("$N is already being guarded by someone.",
ch, NULL, victim, TO_CHAR);
return;
}
if (victim->guarding == ch) {
act("But $N is guarding you!", ch, NULL, victim, TO_CHAR);
return;
}
if (!is_same_group(victim, ch)) {
act("But you aren't in the same group as $N.",
ch, NULL, victim, TO_CHAR);
return;
}
if (IS_AFFECTED(ch,AFF_CHARM)) {
act("You like your master too much to bother guarding $N!",
ch, NULL, victim, TO_VICT);
return;
}
if (victim->fighting != NULL) {
char_puts("Why don't you let them stop fighting first?\n",
ch);
return;
}
if (ch->fighting != NULL) {
char_puts("Better finish your own battle before you "
"worry about guarding someone else.\n", ch);
return;
}
act("You are now guarding $N.", ch, NULL, victim, TO_CHAR);
act("You are being guarded by $n.", ch, NULL, victim, TO_VICT);
act("$n is now guarding $N.", ch, NULL, victim, TO_NOTVICT);
ch->guarding = victim;
victim->guarded_by = ch;
}
CHAR_DATA *check_guard(CHAR_DATA *ch, CHAR_DATA *mob)
{
int chance;
if (ch->guarded_by == NULL ||
get_char_room(ch,ch->guarded_by->name) == NULL)
return ch;
else {
chance = (get_skill(ch->guarded_by,gsn_guard) -
(1.5 * (ch->level - mob->level)));
if (number_percent() < chance) {
act("$n jumps in front of $N!",
ch->guarded_by, NULL, ch, TO_NOTVICT);
act("$n jumps in front of you!",
ch->guarded_by, NULL, ch, TO_VICT);
act("You jump in front of $N!",
ch->guarded_by, NULL, ch, TO_CHAR);
check_improve(ch->guarded_by, gsn_guard, TRUE, 3);
return ch->guarded_by;
}
else {
check_improve(ch->guarded_by, gsn_guard, FALSE, 3);
return ch;
}
}
}
void do_explode(CHAR_DATA *ch, const char *argument)
{
CHAR_DATA *victim = ch->fighting;
CHAR_DATA *vch, *vch_next;
int dam=0,hp_dam,dice_dam,mana;
int hpch,level= ch->level;
char arg[MAX_INPUT_LENGTH];
int chance;
if ((chance = get_skill(ch, gsn_explode)) == 0) {
char_puts("Flame? What is that?\n", ch);
return;
}
WAIT_STATE(ch, SKILL(gsn_explode)->beats);
if (victim == NULL) {
one_argument(argument, arg);
if (arg == NULL) {
char_puts("You play with the exploding material.\n",
ch);
return;
}
if ((victim = get_char_room(ch,arg)) == NULL) {
char_puts("They aren't here.\n", ch);
return;
}
}
mana = SKILL(gsn_explode)->min_mana;
if (ch->mana < mana) {
char_puts("You can't find that much energy to fire\n", ch);
return;
}
ch->mana -= mana;
act("$n burns something.", ch, NULL, victim, TO_NOTVICT);
act("$n burns a cone of exploding material over you!",
ch, NULL, victim, TO_VICT);
act("Burn them all!.", ch, NULL, NULL, TO_CHAR);
if (number_percent() >= chance) {
damage(ch, victim, 0, gsn_explode, DAM_FIRE, TRUE);
check_improve(ch, gsn_explode, FALSE, 1);
return;
}
hpch = UMAX(10, ch->hit);
hp_dam = number_range(hpch/9+1, hpch/5);
dice_dam = dice(level,20);
if (!is_safe(ch,victim)) {
dam = UMAX(hp_dam + dice_dam /10, dice_dam + hp_dam / 10);
fire_effect(victim->in_room, level, dam/2, TARGET_ROOM);
}
for (vch = victim->in_room->people; vch != NULL; vch = vch_next) {
vch_next = vch->next_in_room;
if (is_safe_spell(ch,vch,TRUE)
|| (IS_NPC(vch) && IS_NPC(ch)
&& (ch->fighting != vch || vch->fighting != ch)))
continue;
if (vch == victim) { /* full damage */
fire_effect(vch, level, dam, TARGET_CHAR);
damage(ch, vch, dam, gsn_explode, DAM_FIRE, TRUE);
}
else { /* partial damage */
fire_effect(vch, level/2, dam/4, TARGET_CHAR);
damage(ch, vch, dam/2, gsn_explode, DAM_FIRE,TRUE);
}
}
if (number_percent() >= chance) {
fire_effect(ch, level/4, dam/10, TARGET_CHAR);
damage(ch, ch, (ch->hit / 10), gsn_explode, DAM_FIRE, TRUE);
}
}
void do_target(CHAR_DATA *ch, const char *argument)
{
CHAR_DATA *victim;
int chance;
if ((chance = get_skill(ch, gsn_target)) == 0) {
char_puts("You don't know how to change the target "
"while fighting a group.\n" ,ch);
return;
}
if (ch->fighting == NULL) {
char_puts("You aren't fighting yet.\n",ch);
return;
}
if (argument[0] == '\0') {
char_puts("Change target to whom?\n",ch);
return;
}
if ((victim = get_char_room(ch, argument)) == NULL) {
char_puts("You don't see that item.\n",ch);
return;
}
/* check victim is fighting with him */
if (victim->fighting != ch) {
char_puts ("Target is not fighting with you.\n",ch);
return;
}
WAIT_STATE(ch, SKILL(gsn_target)->beats);
if (number_percent() < chance / 2) {
check_improve(ch, gsn_target, TRUE, 1);
ch->fighting = victim;
act("$n changes $s target to $N!",
ch, NULL, victim, TO_NOTVICT);
act("You change your target to $N!",
ch, NULL, victim, TO_CHAR);
act("$n changes target to you!", ch, NULL, victim, TO_VICT);
return;
}
char_puts("You tried, but you couldn't. "
"But for honour try again!.\n", ch);
check_improve(ch, gsn_target, FALSE, 1);
}
void do_tiger(CHAR_DATA *ch, const char *argument)
{
int chance, hp_percent;
int mana;
if ((chance = get_skill(ch, gsn_tiger_power)) == 0) {
char_puts("Huh?\n", ch);
return;
}
act("$n calls the power of 10 tigers!.", ch, NULL, NULL, TO_ROOM);
if (IS_AFFECTED(ch, AFF_BERSERK) || is_affected(ch, gsn_berserk)
|| is_affected(ch, gsn_tiger_power) || is_affected(ch, gsn_frenzy)) {
char_puts("You get a little madder.\n", ch);
return;
}
if (IS_AFFECTED(ch,AFF_CALM)) {
char_puts("You're feeling too mellow to call 10 tigers.\n",
ch);
return;
}
if (ch->in_room->sector_type != SECT_FIELD
&& ch->in_room->sector_type != SECT_FOREST
&& ch->in_room->sector_type != SECT_MOUNTAIN
&& ch->in_room->sector_type != SECT_HILLS) {
char_puts("No tigers can hear your call.\n", ch);
return;
}
mana = SKILL(gsn_tiger_power)->min_mana;
if (ch->mana < mana) {
char_puts("You can't get up enough energy.\n", ch);
return;
}
/* modifiers */
/* fighting */
if (ch->position == POS_FIGHTING)
chance += 10;
hp_percent = 100 * ch->hit/ch->max_hit;
chance += 25 - hp_percent/2;
ch->move /= 2;
if (number_percent() < chance) {
AFFECT_DATA af;
WAIT_STATE(ch, SKILL(gsn_tiger_power)->beats);
ch->mana -= mana;
/* heal a little damage */
ch->hit += ch->level * 2;
ch->hit = UMIN(ch->hit, ch->max_hit);
char_puts("10 tigers come for your call, as you call them!\n",
ch);
act("10 tigers come across $n, and connect with $n.",
ch, NULL, NULL, TO_ROOM);
check_improve(ch, gsn_tiger_power, TRUE, 2);
af.where = TO_AFFECTS;
af.type = gsn_tiger_power;
af.level = ch->level;
af.duration = number_fuzzy(ch->level / 8);
af.modifier = UMAX(1,ch->level/5);
af.bitvector = AFF_BERSERK;
af.location = APPLY_HITROLL;
affect_to_char(ch,&af);
af.location = APPLY_DAMROLL;
affect_to_char(ch,&af);
af.modifier = UMAX(10,10 * (ch->level/5));
af.location = APPLY_AC;
affect_to_char(ch,&af);
}
else {
WAIT_STATE(ch, 2 * SKILL(gsn_tiger_power)->beats);
ch->mana -= mana/2;
char_puts("Your feel stregthen up, but nothing happens.\n",
ch);
check_improve(ch, gsn_tiger_power, FALSE, 2);
}
}
void do_hara(CHAR_DATA *ch, const char *argument)
{
int chance;
AFFECT_DATA af;
if (MOUNTED(ch)) {
char_puts("You can't harakiri while riding!\n", ch);
return;
}
if ((chance = get_skill(ch,gsn_hara_kiri)) == 0) {
char_puts("You try to kill yourself, but you can't resist this ache.\n",ch);
return;
}
if (is_affected(ch, gsn_hara_kiri)) {
char_puts("If you want to kill yourself go and try to kill He-Man.\n",ch);
return;
}
/* fighting */
if (ch->position == POS_FIGHTING) {
char_puts("Try your chance during fighting.\n", ch);
return;
}
if (number_percent() < chance) {
AFFECT_DATA af;
WAIT_STATE(ch, SKILL(gsn_hara_kiri)->beats);
ch->hit = 1;
ch->mana = 1;
ch->move = 1;
if (ch->pcdata->condition[COND_HUNGER] < 40)
ch->pcdata->condition[COND_HUNGER] = 40;
if (ch->pcdata->condition[COND_THIRST] < 40)
ch->pcdata->condition[COND_THIRST] = 40;
char_puts("Yo cut your finger and wait till all your blood "
"finishes.\n",ch);
act_puts("$n cuts his body and look in a deadly figure.",
ch, NULL, NULL, TO_ROOM, POS_FIGHTING);
check_improve(ch, gsn_hara_kiri, TRUE, 2);
do_sleep(ch, str_empty);
SET_BIT(ch->plr_flags,PLR_HARA_KIRI);
af.where = TO_AFFECTS;
af.type = gsn_hara_kiri;
af.level = ch->level;
af.duration = 10;
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = 0;
affect_to_char(ch, &af);
}
else {
WAIT_STATE(ch, 2 * SKILL(gsn_hara_kiri)->beats);
af.where = TO_AFFECTS;
af.type = gsn_hara_kiri;
af.level = ch->level;
af.duration = 0;
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = 0;
affect_to_char(ch, &af);
char_puts("You couldn't cut your finger. "
"It is not so easy as you know.\n", ch);
check_improve(ch, gsn_hara_kiri, FALSE, 2);
}
}
/*
* critical strike
*/
int critical_strike(CHAR_DATA *ch, CHAR_DATA *victim, int dam)
{
int diceroll;
AFFECT_DATA baf;
int chance;
if (get_eq_char(ch, WEAR_WIELD) != NULL
&& get_eq_char(ch, WEAR_SECOND_WIELD) != NULL
&& number_percent() > ((ch->hit * 100) / ch->max_hit))
return 0;
if ((chance = get_skill(ch, gsn_critical)) == 0)
return dam;
diceroll = number_range(0, 100);
if (victim -> level > ch -> level)
diceroll += (victim->level - ch->level) * 2;
if (victim -> level < ch -> level)
diceroll -= (ch->level - victim->level);
if (diceroll <= chance /2) {
check_improve(ch, gsn_critical, TRUE, 2);
dam += dam * diceroll/200;
}
if (diceroll > chance / 13)
return dam;
diceroll = number_percent();
if (diceroll <= 75) {
act_puts("You take $N down with a weird judo move!",
ch, NULL, victim, TO_CHAR, POS_DEAD);
act("$n takes you down with a weird judo move!",
ch, NULL, victim, TO_VICT);
act("$n takes $N down with a weird judo move!",
ch, NULL, victim, TO_NOTVICT);
check_improve(ch, gsn_critical, TRUE, 3);
WAIT_STATE(victim, 2 * PULSE_VIOLENCE);
dam += (dam * number_range(2, 5)) / 5;
return dam;
}
else if (diceroll > 75 && diceroll < 95) {
act_puts("You blind $N with your attack!",
ch, NULL, victim, TO_CHAR, POS_DEAD);
act("You are blinded by $n's attack!",
ch, NULL, victim, TO_VICT);
act("$N is blinded by $n's attack!",
ch, NULL, victim, TO_NOTVICT);
check_improve(ch, gsn_critical, TRUE, 4);
if (!IS_AFFECTED(victim, AFF_BLIND)) {
baf.where = TO_AFFECTS;
baf.type = gsn_critical;
baf.level = ch->level;
baf.location = APPLY_HITROLL;
baf.modifier = -4;
baf.duration = number_range(1, 3);
baf.bitvector = AFF_BLIND;
affect_to_char(victim, &baf);
}
dam += dam * number_range(1, 2);
return dam;
}
act_puts("You cut out $N's {Rheart{x! I bet that hurt!",
ch, NULL, victim, TO_CHAR ,POS_RESTING);
act_puts("$n cuts out your {Rheart{x! OUCH!!",
ch, NULL, victim, TO_VICT ,POS_RESTING);
act_puts("$n cuts out $N's {Rheart{x! I bet that hurt!",
ch, NULL, victim, TO_NOTVICT ,POS_RESTING);
check_improve(ch, gsn_critical, TRUE, 5);
dam += dam * number_range(2, 5);
return dam;
}
void do_shield(CHAR_DATA *ch, const char *argument)
{
CHAR_DATA *victim;
int chance,ch_weapon,vict_shield;
OBJ_DATA *shield,*axe;
if (IS_NPC(ch))
return;
if ((victim = ch->fighting) == NULL) {
char_puts("You aren't fighting anyone.\n", ch);
return;
}
if ((axe = get_eq_char(ch,WEAR_WIELD)) == NULL) {
char_puts("You must be wielding a weapon.\n", ch);
return;
}
if ((chance = get_skill(ch, gsn_shield_cleave)) == 0) {
char_puts("You don't know how to cleave opponents's shield.\n",
ch);
return;
}
if ((shield = get_eq_char(victim, WEAR_SHIELD)) == NULL) {
char_puts("Your opponent must wield a shield.\n", ch);
return;
}
if (check_material(shield,"platinum")
|| shield->pIndexData->limit != -1)
return;
if (axe->value[0] == WEAPON_AXE)
chance *= 1.2;
else if (axe->value[0] != WEAPON_SWORD) {
char_puts("Your weapon must be an axe or a sword.\n", ch);
return;
}
/* find weapon skills */
ch_weapon = get_weapon_skill(ch, get_weapon_sn(axe));
vict_shield = get_skill(ch, gsn_shield_block);
/* modifiers */
/* skill */
chance = chance * ch_weapon / 200;
if (vict_shield)
chance = chance * 100 / vict_shield;
/* dex vs. strength */
chance += get_curr_stat(ch, STAT_DEX);
chance -= 2 * get_curr_stat(victim, STAT_STR);
/* level */
/* chance += (ch->level - victim->level) * 2; */
chance += ch->level - victim->level;
chance += axe->level - shield->level;
/* and now the attack */
SET_BIT(ch->affected_by, AFF_WEAK_STUN);
WAIT_STATE(ch, SKILL(gsn_shield_cleave)->beats);
if (number_percent() < chance) {
act("You cleaved $N's shield into two.",
ch, NULL, victim, TO_CHAR);
act("$n cleaved your shield into two.",
ch, NULL, victim, TO_VICT);
act("$n cleaved $N's shield into two.",
ch, NULL, victim, TO_NOTVICT);
check_improve(ch, gsn_shield_cleave, TRUE, 1);
extract_obj(get_eq_char(victim, WEAR_SHIELD));
}
else {
act("You fail to cleave $N's shield.",
ch, NULL, victim, TO_CHAR);
act("$n tries to cleave your shield, but fails.",
ch, NULL, victim, TO_VICT);
act("$n tries to cleave $N's shield, but fails.",
ch, NULL, victim, TO_NOTVICT);
check_improve(ch, gsn_shield_cleave, FALSE, 1);
}
}
void do_weapon(CHAR_DATA *ch, const char *argument)
{
CHAR_DATA *victim;
OBJ_DATA *wield,*axe;
int chance,ch_weapon,vict_weapon;
if (IS_NPC(ch))
return;
if ((victim = ch->fighting) == NULL) {
char_puts("You aren't fighting anyone.\n", ch);
return;
}
if ((axe = get_eq_char(ch, WEAR_WIELD)) == NULL) {
char_puts("You must be wielding a weapon.\n",ch);
return;
}
if ((chance = get_skill(ch, gsn_weapon_cleave)) == 0) {
char_puts("You don't know how to cleave opponents's weapon.\n",ch);
return;
}
if ((wield = get_eq_char(victim, WEAR_WIELD)) == NULL) {
char_puts("Your opponent must wield a weapon.\n", ch);
return;
}
if (check_material(wield,"platinum") || wield->pIndexData->limit != -1)
return;
if (axe->value[0] == WEAPON_AXE)
chance *= 1.2;
else if (axe->value[0] != WEAPON_SWORD) {
char_puts("Your weapon must be an axe or a sword.\n",ch);
return;
}
/* find weapon skills */
ch_weapon = get_weapon_skill(ch, get_weapon_sn(axe));
vict_weapon = get_weapon_skill(victim, get_weapon_sn(wield));
/* modifiers */
/* skill */
chance = chance * ch_weapon / 200;
chance = chance * 100 / vict_weapon;
/* dex vs. strength */
chance += get_curr_stat(ch, STAT_DEX) + get_curr_stat(ch, STAT_STR);
chance -= get_curr_stat(victim, STAT_STR) +
2 * get_curr_stat(victim, STAT_DEX);
chance += ch->level - victim->level;
chance += axe->level - wield->level;
/* and now the attack */
SET_BIT(ch->affected_by,AFF_WEAK_STUN);
WAIT_STATE(ch, SKILL(gsn_weapon_cleave)->beats);
if (number_percent() < chance) {
act("You cleaved $N's weapon into two.",
ch, NULL, victim, TO_CHAR);
act("$n cleaved your weapon into two.",
ch, NULL, victim, TO_VICT);
act("$n cleaved $N's weapon into two.",
ch, NULL, victim, TO_NOTVICT);
check_improve(ch, gsn_weapon_cleave, TRUE, 1);
extract_obj(get_eq_char(victim, WEAR_WIELD));
}
else {
act("You fail to cleave $N's weapon.",
ch, NULL, victim, TO_CHAR);
act("$n tries to cleave your weapon, but fails.",
ch, NULL, victim, TO_VICT);
act("$n tries to cleave $N's weapon, but fails.",
ch, NULL, victim, TO_NOTVICT);
check_improve(ch, gsn_weapon_cleave, FALSE, 1);
}
}
void do_tail(CHAR_DATA *ch, const char *argument)
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *victim;
int chance, wait;
int damage_tail;
if (MOUNTED(ch)) {
char_puts("You can't tail while riding!\n", ch);
return;
}
one_argument(argument, arg);
if ((chance = get_skill(ch, gsn_tail)) == 0) {
char_puts("Huh?\n", ch);
return;
}
WAIT_STATE(ch, SKILL(gsn_cleave)->beats);
if (arg[0] == '\0') {
victim = ch->fighting;
if (victim == NULL) {
char_puts("But you aren't fighting anyone!\n", ch);
return;
}
}
else if ((victim = get_char_room(ch,arg)) == NULL) {
char_puts("They aren't here.\n", ch);
return;
}
/*
if (victim->position < POS_FIGHTING) {
act("You'll have to let $M get back up first.",
ch, NULL, victim, TO_CHAR);
return;
}
*/
if (victim == ch) {
char_puts("You try to hit yourself by your tail, but failed.\n",
ch);
return;
}
if (IS_AFFECTED(ch,AFF_CHARM) && ch->master == victim) {
act("But $N is your friend!", ch, NULL, victim, TO_CHAR);
return;
}
if (is_affected(victim, gsn_protective_shield)) {
act_puts("Your tail seems to slide around $N.",
ch, NULL, victim, TO_CHAR, POS_FIGHTING);
act_puts("$n's tail slides off your protective shield.",
ch, NULL, victim, TO_VICT, POS_FIGHTING);
act_puts("$n's tail seems to slide around $N.",
ch, NULL, victim, TO_NOTVICT, POS_FIGHTING);
return;
}
if (is_safe(ch, victim))
return;
/* modifiers */
/* size and weight */
chance -= ch->carry_weight / 20;
chance += victim->carry_weight / 25;
if (ch->size < victim->size)
chance += (ch->size - victim->size) * 25;
else
chance += (ch->size - victim->size) * 10;
/* stats */
chance += get_curr_stat(ch, STAT_STR) + get_curr_stat(ch, STAT_DEX);
chance -= get_curr_stat(victim, STAT_DEX) * 2;
if (IS_AFFECTED(ch, AFF_FLYING))
chance -= 10;
/* speed */
if (IS_NPC(ch) && IS_SET(ch->pIndexData->off_flags, OFF_FAST))
chance += 20;
if (IS_NPC(victim) && IS_SET(victim->pIndexData->off_flags, OFF_FAST))
chance -= 30;
/* level */
chance += (ch->level - victim->level) * 2;
RESET_WAIT_STATE(ch);
/* now the attack */
if (number_percent() < (chance / 4)) {
act("$n sends you sprawling with a powerful tail!",
ch, NULL, victim, TO_VICT);
act("You sprawle $N with your tail , and send $M flying!",
ch, NULL, victim, TO_CHAR);
act("$n sends $N sprawling with a powerful tail.",
ch, NULL, victim, TO_NOTVICT);
check_improve(ch, gsn_tail, TRUE, 1);
wait = 3;
switch(number_bits(2)) {
case 0: wait = 1; break;
case 1: wait = 2; break;
case 2: wait = 4; break;
case 3: wait = 3; break;
}
WAIT_STATE(victim, wait * PULSE_VIOLENCE);
WAIT_STATE(ch, SKILL(gsn_tail)->beats);
victim->position = POS_RESTING;
damage_tail = ch->damroll +
(2 * number_range(4,4 + 10* ch->size + chance/10));
damage(ch, victim, damage_tail, gsn_tail, DAM_BASH, TRUE);
}
else {
damage(ch,victim,0,gsn_tail,DAM_BASH, TRUE);
act("You lost your position and fall down!",
ch, NULL, victim, TO_CHAR);
act("$n lost $s position and fall down!.",
ch, NULL, victim, TO_NOTVICT);
act("You evade $n's tail, causing $m to fall down.",
ch, NULL, victim, TO_VICT);
check_improve(ch,gsn_tail,FALSE,1);
ch->position = POS_RESTING;
WAIT_STATE(ch, SKILL(gsn_tail)->beats * 3/2);
}
}
void do_concentrate(CHAR_DATA *ch, const char *argument)
{
int chance;
int mana;
if (MOUNTED(ch)) {
char_puts("You can't concentrate while riding!\n", ch);
return;
}
if ((chance = get_skill(ch,gsn_concentrate)) == 0) {
char_puts("You try to concentrate on what is going on.\n",
ch);
return;
}
if (is_affected(ch,gsn_concentrate)) {
char_puts("You are already concentrated for the fight.\n",
ch);
return;
}
mana = SKILL(gsn_concentrate)->min_mana;
if (ch->mana < mana) {
char_puts("You can't get up enough energy.\n", ch);
return;
}
/* fighting */
if (ch->fighting) {
char_puts("Concentrate on your fighting!\n", ch);
return;
}
WAIT_STATE(ch, SKILL(gsn_concentrate)->beats);
if (number_percent() < chance) {
AFFECT_DATA af;
ch->mana -= mana;
ch->move /= 2;
do_sit(ch,str_empty);
char_puts("You sit down and relax, "
"concentrating on the next fight.!\n", ch);
act_puts("$n concentrates for the next fight.",
ch, NULL, NULL, TO_ROOM, POS_FIGHTING);
check_improve(ch,gsn_concentrate,TRUE,2);
af.where = TO_AFFECTS;
af.type = gsn_concentrate;
af.level = ch->level;
af.duration = number_fuzzy(ch->level / 8);
af.modifier = UMAX(1,ch->level/8);
af.bitvector = 0;
af.location = APPLY_HITROLL;
affect_to_char(ch,&af);
af.location = APPLY_DAMROLL;
affect_to_char(ch,&af);
af.modifier = UMAX(1,ch->level/-10);
af.location = APPLY_AC;
affect_to_char(ch,&af);
}
else {
ch->mana -= mana/2;
char_puts("You try to concentrate for the next fight but fail.\n",
ch);
check_improve(ch, gsn_concentrate, FALSE, 2);
}
}
void do_bandage(CHAR_DATA *ch, const char *argument)
{
int heal;
int chance;
if ((chance = get_skill(ch,gsn_bandage)) == 0) {
char_puts("Huh?\n", ch);
return;
}
if (IS_AFFECTED(ch, AFF_REGENERATION)) {
char_puts("You have already using your bandage.\n", ch);
return;
}
WAIT_STATE(ch, SKILL(gsn_bandage)->beats);
if (number_percent() < chance) {
AFFECT_DATA af;
char_puts("You place your bandage to your shoulder!\n", ch);
act("$n places a bandage to $s shulder.",
ch, NULL, NULL, TO_ROOM);
check_improve(ch, gsn_bandage, TRUE, 2);
heal = dice(4, 8) + ch->level / 2;
ch->hit = UMIN(ch->hit + heal, ch->max_hit);
update_pos(ch);
char_puts("You feel better!\n", ch);
af.where = TO_AFFECTS;
af.type = gsn_bandage;
af.level = ch->level;
af.duration = ch->level / 10;
af.modifier = UMIN(15,ch->level/2);
af.bitvector = AFF_REGENERATION;
af.location = 0;
affect_to_char(ch,&af);
}
else {
char_puts("You failed to place your bandage to your shoulder.\n",
ch);
check_improve(ch, gsn_bandage, FALSE, 2);
}
}
void do_katana(CHAR_DATA *ch, const char *argument)
{
OBJ_DATA *katana;
AFFECT_DATA af;
OBJ_DATA *part;
char arg[MAX_INPUT_LENGTH];
int chance;
int mana;
one_argument(argument, arg);
if ((chance = get_skill(ch, gsn_katana)) == 0) {
char_puts("Huh?\n", ch);
return;
}
if (is_affected(ch, gsn_katana)) {
char_puts("But you've already got one katana!\n", ch);
return;
}
mana = SKILL(gsn_katana)->min_mana;
if (ch->mana < mana) {
char_puts("You feel too weak to concentrate on a katana.\n",
ch);
return;
}
if (arg[0] == '\0') {
char_puts("Make a katana from what?\n", ch);
return;
}
if ((part = get_obj_carry(ch, arg)) == NULL) {
char_puts("You do not have chunk of iron.\n", ch);
return;
}
if (part->pIndexData->vnum != OBJ_VNUM_CHUNK_IRON) {
char_puts("You do not have the right material.\n", ch);
return;
}
if (number_percent() < chance / 3 * 2) {
char_puts("You failed and destroyed it.\n", ch);
extract_obj(part);
return;
}
WAIT_STATE(ch, SKILL(gsn_katana)->beats);
if (number_percent() < chance) {
af.where = TO_AFFECTS;
af.type = gsn_katana;
af.level = ch->level;
af.duration = ch->level;
af.modifier = 0;
af.bitvector = 0;
af.location = 0;
affect_to_char(ch,&af);
katana = create_obj(get_obj_index(OBJ_VNUM_KATANA_SWORD),
ch->level);
katana->cost = 0;
katana->level = ch->level;
ch->mana -= mana;
af.where = TO_OBJECT;
af.type = gsn_katana;
af.level = ch->level;
af.duration = -1;
af.location = APPLY_DAMROLL;
af.modifier = ch->level / 10;
af.bitvector = 0;
affect_to_obj(katana, &af);
af.location = APPLY_HITROLL;
affect_to_obj(katana, &af);
katana->value[2] = ch->level / 10;
katana->ed = ed_new2(katana->pIndexData->ed, ch->name);
obj_to_char(katana, ch);
check_improve(ch, gsn_katana, TRUE, 1);
act("You make a katana from $p!",ch,part,NULL,TO_CHAR);
act("$n makes a katana from $p!",ch,part,NULL,TO_ROOM);
extract_obj(part);
return;
}
else {
char_puts("You destroyed it.\n", ch);
extract_obj(part);
ch->mana -= mana/2;
check_improve(ch, gsn_katana, FALSE, 1);
}
}
void do_crush(CHAR_DATA *ch, const char *argument)
{
CHAR_DATA *victim;
int chance, wait;
int damage_crush;
if (MOUNTED(ch))
return;
if ((chance = get_skill(ch, gsn_crush)) == 0) {
char_puts("You don't know how to crush.\n", ch);
return;
}
if ((victim = ch->fighting) == NULL)
return;
if (victim->position < POS_FIGHTING)
return;
if (IS_AFFECTED(ch,AFF_CHARM) && ch->master == victim)
return;
if (is_affected(victim, gsn_protective_shield)) {
act_puts("Your crush seems to slide around $N.",
ch, NULL, victim, TO_CHAR, POS_FIGHTING);
act_puts("$n's crush slides off your protective shield.",
ch, NULL, victim, TO_VICT, POS_FIGHTING);
act_puts("$n's crush seems to slide around $N.",
ch, NULL, victim, TO_NOTVICT, POS_FIGHTING);
return;
}
if (is_safe(ch, victim))
return;
/* modifiers */
/* size and weight */
chance += ch->carry_weight / 25;
chance -= victim->carry_weight / 20;
if (ch->size < victim->size)
chance += (ch->size - victim->size) * 25;
else
chance += (ch->size - victim->size) * 10;
/* stats */
chance += get_curr_stat(ch, STAT_STR);
chance -= get_curr_stat(victim, STAT_DEX) * 4/3;
if (IS_AFFECTED(ch, AFF_FLYING))
chance -= 10;
/* speed */
if (IS_NPC(ch) && IS_SET(ch->pIndexData->off_flags, OFF_FAST))
chance += 10;
if (IS_NPC(victim) && IS_SET(victim->pIndexData->off_flags, OFF_FAST))
chance -= 20;
/* level */
chance += (ch->level - victim->level) * 2;
/* now the attack */
if (number_percent() < chance) {
act("$n squezes you with a powerful crush!",
ch, NULL, victim, TO_VICT);
act("You slam into $N, and crushes $M!",
ch, NULL, victim, TO_CHAR);
act("$n squezes $N with a powerful crush.",
ch, NULL, victim, TO_NOTVICT);
wait = 3;
switch(number_bits(2)) {
case 0: wait = 1; break;
case 1: wait = 2; break;
case 2: wait = 4; break;
case 3: wait = 3; break;
}
WAIT_STATE(victim, wait * PULSE_VIOLENCE);
WAIT_STATE(ch, SKILL(gsn_crush)->beats);
victim->position = POS_RESTING;
damage_crush = (ch->damroll / 2) +
number_range(4, 4 + 4*ch->size + chance/10);
damage(ch, victim, damage_crush, gsn_crush, DAM_BASH, TRUE);
}
else {
damage(ch, victim, 0, gsn_crush, DAM_BASH, TRUE);
act("You fall flat on your face!",
ch, NULL, victim, TO_CHAR);
act("$n falls flat on $s face.",
ch, NULL, victim, TO_NOTVICT);
act("You evade $n's crush, causing $m to fall flat on $s face.",
ch, NULL, victim, TO_VICT);
ch->position = POS_RESTING;
WAIT_STATE(ch, SKILL(gsn_crush)->beats * 3/2);
}
}
void do_sense(CHAR_DATA *ch, const char *argument)
{
int chance;
int mana;
if ((chance = get_skill(ch, gsn_sense_life)) == 0) {
char_puts("Huh?\n", ch);
return;
}
if (is_affected(ch, gsn_sense_life)) {
char_puts("You can already feel life forms.\n", ch);
return;
}
mana = SKILL(gsn_sense_life)->min_mana;
if (ch->mana < mana) {
char_puts("You cannot seem to concentrate enough.\n", ch);
return;
}
WAIT_STATE(ch, SKILL(gsn_sense_life)->beats);
if (number_percent() < chance) {
AFFECT_DATA af;
af.where = TO_AFFECTS;
af.type = gsn_sense_life;
af.level = ch->level;
af.duration = ch->level;
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = AFF_DETECT_LIFE;
affect_to_char(ch, &af);
ch->mana -= mana;
act("You start to sense life forms in the room!",
ch, NULL, NULL, TO_CHAR);
act("$n looks more sensitive.", ch, NULL, NULL, TO_ROOM);
check_improve(ch, gsn_sense_life, TRUE, 1);
}
else {
ch->mana -= mana/2;
char_puts("You failed.\n" ,ch);
check_improve(ch, gsn_sense_life, FALSE, 1);
}
}
void do_poison_smoke(CHAR_DATA *ch, const char *argument)
{
int chance;
int mana;
CHAR_DATA *vch;
CHAR_DATA *vch_next;
if ((chance = get_skill(ch, gsn_poison_smoke)) == 0) {
char_puts("Huh?\n", ch);
return;
}
mana = SKILL(gsn_poison_smoke)->min_mana;
if (ch->mana < mana) {
char_puts("You can't get up enough energy.\n", ch);
return;
}
ch->mana -= mana;
WAIT_STATE(ch, SKILL(gsn_poison_smoke)->beats);
if (number_percent() > chance) {
char_puts("You failed.\n", ch);
check_improve(ch, gsn_poison_smoke, FALSE, 1);
return;
}
char_puts("A cloud of poison smoke fills the room.\n", ch);
act("A cloud of poison smoke fills the room.", ch, NULL, NULL, TO_ROOM);
check_improve(ch, gsn_poison_smoke, TRUE, 1);
for (vch = ch->in_room->people; vch; vch = vch_next) {
vch_next = vch->next_in_room;
if (is_safe_spell(ch, vch, TRUE))
continue;
spell_poison(gsn_poison, ch->level, ch, vch, TARGET_CHAR);
if (vch != ch)
multi_hit(vch, ch, TYPE_UNDEFINED);
}
}
void do_blindness_dust(CHAR_DATA *ch, const char *argument)
{
CHAR_DATA *vch;
CHAR_DATA *vch_next;
int chance;
int mana;
if ((chance = get_skill(ch, gsn_blindness_dust)) == 0) {
char_puts("Huh?\n", ch);
return;
}
mana = SKILL(gsn_blindness_dust)->min_mana;
if (ch->mana < mana) {
char_puts("You can't get up enough energy.\n", ch);
return;
}
ch->mana -= mana;
WAIT_STATE(ch, SKILL(gsn_blindness_dust)->beats);
if (number_percent() > chance) {
char_puts("You failed.\n",ch);
check_improve(ch,gsn_blindness_dust,FALSE,1);
return;
}
char_puts("A cloud of dust fills in the room.\n", ch);
act("A cloud of dust fills the room.", ch, NULL, NULL, TO_ROOM);
check_improve(ch, gsn_blindness_dust, TRUE, 1);
for (vch = ch->in_room->people; vch; vch = vch_next) {
vch_next = vch->next_in_room;
if (is_safe_spell(ch, vch, TRUE))
continue;
spell_blindness(gsn_blindness, ch->level, ch, vch, TARGET_CHAR);
if (vch != ch)
multi_hit(vch, ch, TYPE_UNDEFINED);
}
}
bool check_yell(CHAR_DATA *ch, CHAR_DATA *victim, bool fighting)
{
return (!IS_NPC(ch) && !IS_NPC(victim) &&
victim->position > POS_STUNNED && !fighting);
}