/***************************************************************************
* 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 Envy Diku Mud, you must comply with *
* the original Diku license in 'license.doc', the Merc license in *
* 'license.txt', as well as the Envy license in 'license.nvy'. *
* 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-1998 Russ Taylor *
* ROM has been brought to you by the ROM consortium *
* Russ Taylor (rtaylor@hypercube.org) *
* Gabrielle Taylor (gtaylor@hypercube.org) *
* Brian Moore (zump@rom.org) *
* By using this code, you have agreed to follow the terms of the *
* ROM license, in the file Rom24/doc/rom.license *
* *
* Code Adapted and Improved by Abandoned Realms Mud *
* and Aabahran: The Forsaken Lands Mud by Virigoth *
* *
* Continued Production of this code is available at www.flcodebase.com *
***************************************************************************/
#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "merc.h"
#include "magic.h"
#include "song.h"
#include "cabal.h"
#include "recycle.h"
#include "interp.h"
#include "s_skill.h"
#include "jail.h"
#include "bounty.h"
void lagprot_yell(CHAR_DATA* ch, CHAR_DATA* victim, int gsn, int shield)
{
/* this composes the yells for differnt shields. */
char buf[MIL];
switch (shield)
{
/* PROTECTIVE SHIELD */
case LAG_SHIELD_PROT:
sprintf(buf, "Don't even think about trying to use %s on me, %s!",
IS_GEN(gsn)? effect_table[GN_POS(gsn)].name : skill_table[gsn].name,
PERS(ch,victim));
break;
/* FORCE FIELD*/
case LAG_SHIELD_FFIELD:
sprintf(buf, "Your feeble %s cannot penetrate my forcefield %s!",
IS_GEN(gsn)? effect_table[GN_POS(gsn)].name : skill_table[gsn].name,
PERS(ch,victim));
break;
/* ARMOR */
case LAG_SHIELD_ARMOR:
sprintf(buf, "Your feeble %s cannot penetrate my armor %s!",
IS_GEN(gsn)? effect_table[GN_POS(gsn)].name : skill_table[gsn].name,
PERS(ch,victim));
break;
/* NON-CORPOREAL */
case LAG_SHIELD_NONCORP:
sprintf(buf, "You can't %s me %s you clumsy fool!",
IS_GEN(gsn)? effect_table[GN_POS(gsn)].name : skill_table[gsn].name,
PERS(ch,victim));
break;
/* BALANCE */
case LAG_SHIELD_BALANCE:
/* IRON WILL */
case LAG_SHIELD_IWILL:
sprintf(buf, "Your %s is no match for my abilities %s!",
IS_GEN(gsn)? effect_table[GN_POS(gsn)].name : skill_table[gsn].name,
PERS(ch,victim));
break;
/* DEFAULT */
default:
sprintf(buf, "Help! %s is trying to %s me!",
PERS(ch,victim),
IS_GEN(gsn)? effect_table[GN_POS(gsn)].name : skill_table[gsn].name);
}//END SWITCH
j_yell(victim,buf);
}
void lagprot_msg(CHAR_DATA* ch, CHAR_DATA* victim, int sn, int shield, bool fYell)
{
/* does the different combat messages. */
//3 message buffers to be displayed at the end.
char to_char[MIL];
char to_vict[MIL];
char to_room[MIL];
char* noun;
char* verb_tch;
char* verb_tvic;
char* verb_trm;
int verb_pos = lagattack_lookup(sn);
if (verb_pos == -1)
{
bug("lagport_msg run with incorrect skill!", 0);
return;
}
noun = lagattack_table[verb_pos].noun;
verb_tch = lagattack_table[verb_pos].to_char;
verb_tvic = lagattack_table[verb_pos].to_vict;
verb_trm = lagattack_table[verb_pos].to_room;
switch (shield)
{
/* PROTECTIVE SHIELD */
case LAG_SHIELD_PROT:
sprintf(to_char, "Your %s is ineffective as %s a protective shield.", noun, verb_tch);
sprintf(to_vict, "$n's %s %s protective shield.",noun, verb_tvic);
sprintf(to_room, "$n's %s %s $N's protective shield.",noun, verb_trm);
break;
/* FORCE FIELD*/
case LAG_SHIELD_FFIELD:
sprintf(to_char, "Your %s is ineffective as %s an elastic shield of force.", noun, verb_tch);
sprintf(to_vict, "$n's %s %s force field.",noun, verb_tvic);
sprintf(to_room, "$n's %s %s $N's force field.",noun, verb_trm);
break;
/* REFLECTIVE FIELD*/
case LAG_SHIELD_RFIELD:
sprintf(to_char, "Your %s is weakened as %s the reflective shield.", noun, verb_tch);
sprintf(to_vict, "$n's %s %s reflective field.",noun, verb_tvic);
sprintf(to_room, "$n's %s %s $N's reflective field.",noun, verb_trm);
break;
/* FORCE FIELD*/
case LAG_SHIELD_ARMOR:
sprintf(to_char, "Your %s is ineffective as %s the Juggernaut Plate.", noun, verb_tch);
sprintf(to_vict, "$n's %s %s Juggernaut Plate.",noun, verb_tvic);
sprintf(to_room, "$n's %s %s $N's Juggernaut Plate.",noun, verb_trm);
break;
/* NON-CORPOREAL */
case LAG_SHIELD_NONCORP:
sprintf(to_char, "Your %s is inneffective against $N.", noun);
sprintf(to_vict, "$n's %s is usless against you.",noun);
sprintf(to_room, "$N seems uneffected by $n's %s",noun);
break;
/* BALANCE */
case LAG_SHIELD_BALANCE:
/* IRON WILL */
case LAG_SHIELD_IWILL:
sprintf(to_char, lagattack_table[verb_pos].ba_char);
sprintf(to_vict, lagattack_table[verb_pos].ba_vict);
sprintf(to_room, lagattack_table[verb_pos].ba_room);
break;
}//END SWITCH
//Upcase the first letter just in case.
to_char[0] = UPPER(to_char[0]);
to_vict[0] = UPPER(to_vict[0]);
to_room[0] = UPPER(to_room[0]);
//show messages
act(to_char, ch, NULL, victim, TO_CHAR);
act(to_vict, ch, NULL, victim, TO_VICT);
act(to_room, ch, NULL, victim, TO_NOTVICT);
if (fYell)
lagprot_yell(ch, victim, sn, shield);
}//END
/* executes checks for lag protection */
/* returns type of shield that is on victim. */
int get_lagprot(CHAR_DATA* ch)
{
int shield_type = LAG_SHIELD_NONE;
//check if person has a shield first.
if ( IS_AFFECTED2(ch, AFF_PROTECT_SHIELD) )
shield_type = LAG_SHIELD_PROT;
else if(is_affected(ch, gsn_forcefield))
shield_type = LAG_SHIELD_FFIELD;
else if(is_affected(ch, gen_ref_shield))
shield_type = LAG_SHIELD_RFIELD;
else if(is_armor_enhanced(ch) > ENHANCE_BASIC)
shield_type = LAG_SHIELD_ARMOR;
else if (is_affected(ch, gsn_iron_will)
&& ch->mana > 0)
shield_type = LAG_SHIELD_IWILL;
else if (is_affected(ch, gsn_mist_form))
shield_type = LAG_SHIELD_NONCORP;
else if (get_skill(ch, gsn_balance) > 1
&& ch->class == gcn_monk
&& is_empowered_quiet(ch,1)
&& ch->mana > 0)
shield_type = LAG_SHIELD_BALANCE;
else if (get_skill(ch, gsn_balance) > 1
&& ch->class == gcn_blademaster
&& is_empowered_quiet(ch,1)
&& ch->mana > 0)
shield_type = LAG_SHIELD_BALANCE;
return shield_type;
}
/* preforms ALL lagsshield checks, displays messges and yells */
/* set yell to TRUE to yell */
/* pass how good the bash attack was using chance */
/* Pass amount of lag by address as it is changed in the function */
/* pass damage by address as it is changed as well. */
/* pass if lag attack was successful or not by fSuccess (needed for skills that only work if hit like balance.)*/
/* returns TRUE if cahracter was shielded. */
bool do_lagprot(CHAR_DATA* ch, CHAR_DATA* victim, int chance, int* do_dam, int* lag, int sn, bool fSuccess, bool fYell)
{
int shield = LAG_SHIELD_NONE;
int dam = *do_dam;
int vic_lag = *lag;
if ( (shield = get_lagprot(victim)) != LAG_SHIELD_NONE)
{
bool fProt = FALSE;
/* BALANCE */
if (shield == LAG_SHIELD_BALANCE && fSuccess)
{
if (number_percent() < get_skill(victim, gsn_balance))
{
if (sn == gsn_bash)
{
check_improve(victim,gsn_balance,TRUE,60);
victim->mana -= URANGE(0,10, victim->mana);
}
else if (sn == gsn_bodyslam)
{
check_improve(victim,gsn_balance,TRUE,70);
victim->mana -= URANGE(0,15,victim->mana);
}
else if (sn == gsn_grapple)
{
check_improve(victim,gsn_balance,TRUE,40);
victim->mana -= URANGE(0,7,victim->mana);
}
else if (sn == gsn_thrust)
{
check_improve(victim,gsn_balance,TRUE,90);
victim->mana -= URANGE(0,18,victim->mana);
}
else
{
check_improve(victim,gsn_balance,TRUE,50);
victim->mana -= URANGE(0,10,victim->mana);
}
fProt = TRUE;
vic_lag = 0;
}
}//END BALANCE
/* IRON WILL */
else if (shield == LAG_SHIELD_IWILL && fSuccess)
{
if (number_percent() < 100 + (victim->level - ch->level) * 5)
{
if (sn == gsn_bash)
victim->mana -= URANGE(0,20,victim->mana);
else if (sn == gsn_bodyslam)
victim->mana -= URANGE(0,30,victim->mana);
else if (sn == gsn_grapple)
victim->mana -= URANGE(0,15,victim->mana);
else if (sn == gsn_thrust)
victim->mana -= URANGE(0,40,victim->mana);
else
victim->mana -= URANGE(0,20,victim->mana);
fProt = TRUE;
vic_lag = 0;
}
}//END IRON WILL
/* NORMAL SHIELDS */
else if (shield == LAG_SHIELD_ARMOR)
{
if (number_percent() < 25){
fProt = TRUE;
vic_lag = 0;
dam = 0;
}
}
else if (shield == LAG_SHIELD_RFIELD)
{
fProt = TRUE;
vic_lag = UMAX(PULSE_VIOLENCE, 2 * vic_lag / 3);
dam = dam / 2;
}
else if (shield == LAG_SHIELD_FFIELD)
{
fProt = TRUE;
vic_lag = 0;
dam = 0;
}
else if (shield == LAG_SHIELD_PROT)
{
fProt = TRUE;
vic_lag = 0;
dam = 0;
}
if (fProt)
lagprot_msg(ch, victim, sn, shield, fYell);
*lag = vic_lag;
*do_dam = dam;
return fProt;
}//END LAGPROTECTION
return FALSE;
}//end do_lagprot
void a_yell( CHAR_DATA *ch, CHAR_DATA *victim )
{
char buf[MSL];
if (ch == NULL || victim == NULL)
return;
if (ch->fighting != victim && victim->fighting != ch && (!IS_NPC(ch) || ch->master != NULL)){
if (!IS_NPC(victim)){
sprintf(buf,"%s attacked %s at %d", IS_NPC(ch) ? ch->short_descr : ch->name,
victim->name,ch->in_room->vnum);
log_string(buf);
wiznet(buf,NULL,NULL,WIZ_FIGHTING,0,0);
continuum(victim, CONTINUUM_ATTACK);
/* MURDER CRIME CHECK */
if (ch->in_room && is_crime(ch->in_room, CRIME_MURDER, victim)){
set_crime(ch, victim, ch->in_room->area, CRIME_MURDER);
/* check of simulacra for justices */
if (is_affected(ch, gsn_doppelganger)){
char buf[MIL];
sprintf( buf, "Warning! Someone seems to be masquerading as %s!",
PERS2(ch));
cabal_echo_flag( CABAL_JUSTICE | CABAL_HEARGUARD, buf );
}
}
/* ATTACKING JUSTICE IN LAWFUL AREA IS ALWAYS AN OBSTRUCTION */
else if (victim->pCabal && IS_CABAL(victim->pCabal, CABAL_JUSTICE) && IS_AREA(ch->in_room->area, AREA_LAWFUL)){
set_crime(ch, victim, ch->in_room->area, CRIME_OBSTRUCT);
}
/* CONTINENCY */
check_contingency(ch, NULL, CONT_ATTACK);
check_contingency(victim, NULL, CONT_ATTACKED);
}//END PC CHECK
else {
bool fCrime = FALSE;
/* ASSAULT CRIME CHECK */
if (ch->in_room && is_crime(ch->in_room, CRIME_ASSAULT, victim)){
set_crime(ch, victim, ch->in_room->area, CRIME_ASSAULT);
fCrime = TRUE;
}
/* ATTACKING JUSTICE MOBS IN LAWFUL AREA IS ALWYAS A CRIME */
else if (victim->pCabal && IS_CABAL(victim->pCabal, CABAL_JUSTICE) && IS_AREA(ch->in_room->area, AREA_LAWFUL)){
set_crime(ch, victim, ch->in_room->area, CRIME_OBSTRUCT);
fCrime = TRUE;
}
/* attackign charmed mobs requiers a yell as well */
else if (IS_NPC(victim) && IS_AFFECTED(victim, AFF_CHARM))
fCrime = TRUE;
if (IS_SET(victim->off_flags,GUILD_GUARD) && victim->pCabal && IS_CABAL(victim->pCabal, CABAL_JUSTICE)){
sprintf(buf, "%s: Alert! The jail is being attacked!", ch->in_room->area->name);
cabal_echo_flag( CABAL_JUSTICE, buf );
sprintf(buf, "Alert! The jail is being attacked by %s!",PERS(ch,victim));
}
else if (IS_SET(victim->off_flags,GUILD_GUARD))
sprintf(buf, "Alert! The guild is being attacked by %s!",PERS(ch,victim));
else
sprintf(buf, "Help! I'm being attacked by %s!",PERS(ch,victim));
//mark the cabal capture item timer if this is a cabal guard and members present
if (victim->pCabal)
set_capture_item_timer( victim );
if (fCrime){
REMOVE_BIT(victim->comm,COMM_NOCHANNELS);
REMOVE_BIT(victim->comm,COMM_NOYELL);
j_yell(victim,buf);
SET_BIT(victim->comm,COMM_NOYELL);
SET_BIT(victim->comm,COMM_NOCHANNELS);
}
}//END NPC CHECK
}
}
void do_gain(CHAR_DATA *ch, char *argument)
{
char arg[MIL];
CHAR_DATA *trainer;
if (IS_NPC(ch))
return;
if (ch->class == gcn_adventurer){
send_to_char("Adventurers cannot convert train and practice sessions.\n\r", ch);
return;
}
for ( trainer = ch->in_room->people; trainer != NULL; trainer = trainer->next_in_room)
if (IS_NPC(trainer) && IS_SET(trainer->act,ACT_GAIN))
break;
if (trainer == NULL || !can_see(ch,trainer))
{
send_to_char("You can't do that here.\n\r",ch);
return;
}
if (is_exiled(ch, trainer->in_room->area->vnum )){
char buf[MIL];
sprintf( buf, "No one in %s will deal with you %s!", trainer->in_room->area->name, PERS2(ch));
do_say( trainer, buf );
return;
}
one_argument(argument,arg);
if (arg[0] == '\0')
{
do_say(trainer,"Pardon me?");
return;
}
if (!str_prefix(arg,"convert"))
{
if (ch->practice < 10)
{
act("$N tells you '`2You are not yet ready.``'", ch,NULL,trainer,TO_CHAR);
return;
}
act("$N helps you apply your practice to training.", ch,NULL,trainer,TO_CHAR);
ch->practice -= 10;
ch->train +=1 ;
return;
}
if (!str_prefix(arg,"study"))
{
if (ch->train < 1)
{
act("$N tells you '`2You do not have enough training sessions.``'", ch,NULL,trainer,TO_CHAR);
return;
}
act("$N helps you apply your training to practices.", ch,NULL,trainer,TO_CHAR);
ch->practice += 10;
ch->train -=1 ;
return;
}
act("$N tells you '`2I do not understand...``'",ch,NULL,trainer,TO_CHAR);
}
void do_spells(CHAR_DATA *ch, char *argument)
{
char arg[MIL], spell_list[LEVEL_IMMORTAL + 2][MSL], spell_columns[LEVEL_IMMORTAL + 2], buf[MSL];
int sn, level, sk_level, min_lev = 1, max_lev = LEVEL_HERO+1, mana;
bool fAll = FALSE, found = FALSE;
CSKILL_DATA* cSkill;
if (IS_NPC(ch))
return;
if (argument[0] != '\0')
{
fAll = TRUE;
if (str_prefix(argument,"all"))
{
argument = one_argument(argument,arg);
if (!is_number(arg))
{
send_to_char("Arguments must be numerical or all.\n\r",ch);
return;
}
max_lev = atoi(arg);
if (max_lev < 1 || max_lev > LEVEL_HERO)
{
sendf(ch,"Levels must be between 1 and %d.\n\r",LEVEL_HERO);
return;
}
if (argument[0] != '\0')
{
argument = one_argument(argument,arg);
if (!is_number(arg))
{
send_to_char("Arguments must be numerical or all.\n\r",ch);
return;
}
min_lev = max_lev;
max_lev = atoi(arg);
if (max_lev < 1 || max_lev > LEVEL_HERO)
{
sendf(ch,"Levels must be between 1 and %d.\n\r",LEVEL_HERO);
return;
}
if (min_lev > max_lev)
{
send_to_char("That would be silly.\n\r",ch);
return;
}
}
}
}
for (level = 0; level < LEVEL_IMMORTAL + 2; level++)
{
spell_columns[level] = 0;
spell_list[level][0] = '\0';
}
for (sn = 0; sn < MAX_SKILL; sn++)
{
if (skill_table[sn].name == NULL )
break;
cSkill = ch->pCabal ? get_cskill( ch->pCabal, sn ) : NULL;
if (cSkill){
level = cSkill->pSkill->level;
sk_level = sklevel(ch,sn);
}
else
level = sk_level = sklevel(ch,sn);
if ( (sk_level < LEVEL_IMMORTAL + 2 || sk_level == CABAL_COST_FAILED)
&& level >= min_lev
&& level <= max_lev
&& skill_table[sn].spell_fun != spell_null
&& ch->pcdata->learned[sn] > 0)
{
mana = _mana_cost(ch, sn);
found = TRUE;
if (ch->level < sk_level){
if (sk_level == CABAL_COST_FAILED)
sprintf(buf,"%-16s <`!%3d/%d``> m/cp ",skill_table[sn].name, mana, get_cskill_cost(ch, ch->in_room, cSkill));
else
sprintf(buf,"%-18s n/a ", skill_table[sn].name);
}
else
{
if (cSkill)
sprintf(buf,"%-17s %3d/%d m/cp ",skill_table[sn].name, mana, get_cskill_cost(ch, ch->in_room, cSkill));
else
sprintf(buf,"%-19s %3d mana ",skill_table[sn].name,mana);
}
if (spell_list[level][0] == '\0')
sprintf(spell_list[level],"\n\rLevel %2d: %s",level,buf);
else
{
if ( ++spell_columns[level] % 2 == 0)
strcat(spell_list[level],"\n\r ");
strcat(spell_list[level],buf);
}
}
}
if (!IS_NPC(ch) && ch->pcdata->newskills != NULL )
{
SKILL_DATA *nsk;
for (nsk = ch->pcdata->newskills; nsk != NULL; nsk = nsk->next )
{
if ((level=nsk->level) < LEVEL_IMMORTAL + 2 && level >= min_lev && level <= max_lev
&&skill_table[nsk->sn].spell_fun != spell_null)
{
found = TRUE;
if (ch->level < nsk->level)
sprintf(buf,"%-18s n/a ", skill_table[nsk->sn].name);
else
{
mana = UMAX(skill_table[nsk->sn].min_mana, 100/(2 + ch->level - nsk->level));
sprintf(buf,"%-19s %3d mana ",skill_table[nsk->sn].name,mana);
}
if (spell_list[level][0] == '\0')
sprintf(spell_list[level],"\n\rLevel %2d: %s",level,buf);
else
{
if ( ++spell_columns[level] % 2 == 0)
strcat(spell_list[level],"\n\r ");
strcat(spell_list[level],buf);
}
}
}
}
if (!found)
{
send_to_char("No spells found.\n\r",ch);
return;
}
for (level = 0; level < LEVEL_IMMORTAL + 2; level++)
if (spell_list[level][0] != '\0')
send_to_char(spell_list[level],ch);
send_to_char("\n\r",ch);
}
void do_songs(CHAR_DATA *ch, char *argument)
{
char arg[MIL], spell_list[LEVEL_IMMORTAL + 2][MSL], spell_columns[LEVEL_IMMORTAL + 2], buf[MSL];
int sn, level, min_lev = 1, max_lev = LEVEL_HERO+1, mana;
bool fAll = FALSE, found = FALSE;
if (IS_NPC(ch))
return;
if (argument[0] != '\0')
{
fAll = TRUE;
if (str_prefix(argument,"all"))
{
argument = one_argument(argument,arg);
if (!is_number(arg))
{
send_to_char("Arguments must be numerical or all.\n\r",ch);
return;
}
max_lev = atoi(arg);
if (max_lev < 1 || max_lev > LEVEL_IMMORTAL + (IS_IMMORTAL(ch) ? 1 : (-1)))
{
sendf(ch,"Levels must be between 1 and %d.\n\r",LEVEL_IMMORTAL+(IS_IMMORTAL(ch) ? 1 : (-1)));
return;
}
if (argument[0] != '\0')
{
argument = one_argument(argument,arg);
if (!is_number(arg))
{
send_to_char("Arguments must be numerical or all.\n\r",ch);
return;
}
min_lev = max_lev;
max_lev = atoi(arg);
if (max_lev < 1 || max_lev > LEVEL_IMMORTAL + (IS_IMMORTAL(ch) ? 1 : (-1)))
{
sendf(ch,"Levels must be between 1 and %d.\n\r",LEVEL_IMMORTAL+(IS_IMMORTAL(ch) ? 1 : (-1)));
return;
}
if (min_lev > max_lev)
{
send_to_char("That would be silly.\n\r",ch);
return;
}
}
}
}
for (level = 0; level < LEVEL_IMMORTAL + 2; level++)
{
spell_columns[level] = 0;
spell_list[level][0] = '\0';
}
for (sn = 0; sn < MAX_SONG; sn++)
{
if (song_table[sn].name == NULL )
break;
if ((level=sglevel(ch,sn)) < LEVEL_IMMORTAL + 2 && level >= min_lev && level <= max_lev
&& song_table[sn].song_fun != song_null && ch->pcdata->songlearned[sn] > 0)
{
found = TRUE;
if (ch->level < sglevel(ch,sn))
sprintf(buf,"%-23s n/a ", song_table[sn].name);
else
{
mana = UMAX(song_table[sn].min_mana, 100/(2 + ch->level - sglevel(ch,sn)));
sprintf(buf,"%-24s %3d mana ",song_table[sn].name,mana);
}
if (spell_list[level][0] == '\0')
sprintf(spell_list[level],"\n\rLevel %2d: %s",level,buf);
else
{
if ( ++spell_columns[level] % 2 == 0)
strcat(spell_list[level],"\n\r ");
strcat(spell_list[level],buf);
}
}
}
if (!found)
{
send_to_char("No songs found.\n\r",ch);
return;
}
for (level = 0; level < LEVEL_IMMORTAL + 2; level++)
if (spell_list[level][0] != '\0')
send_to_char(spell_list[level],ch);
send_to_char("\n\r",ch);
}
void do_skills(CHAR_DATA *ch, char *argument)
{
char arg[MIL], skill_list[LEVEL_IMMORTAL + 2][MSL], skill_columns[LEVEL_IMMORTAL + 2], buf[MSL];
int sn, level, sk_level, min_lev = 1, max_lev = LEVEL_HERO+1;
bool fAll = FALSE, found = FALSE;
CSKILL_DATA* cSkill;
if (IS_NPC(ch))
return;
if (argument[0] != '\0')
{
fAll = TRUE;
if (str_prefix(argument,"all"))
{
argument = one_argument(argument,arg);
if (!is_number(arg))
{
send_to_char("Arguments must be numerical or all.\n\r",ch);
return;
}
max_lev = atoi(arg);
if (max_lev < 1 || max_lev > LEVEL_HERO)
{
sendf(ch,"Levels must be between 1 and %d.\n\r", LEVEL_HERO);
return;
}
if (argument[0] != '\0')
{
argument = one_argument(argument,arg);
if (!is_number(arg))
{
send_to_char("Arguments must be numerical or all.\n\r",ch);
return;
}
min_lev = max_lev;
max_lev = atoi(arg);
if (max_lev < 1 || max_lev > LEVEL_HERO)
{
sendf(ch,"Levels must be between 1 and %d.\n\r",LEVEL_HERO);
return;
}
if (min_lev > max_lev)
{
send_to_char("That would be silly.\n\r",ch);
return;
}
}
}
}
for (level = 0; level < LEVEL_IMMORTAL + 2; level++)
{
skill_columns[level] = 0;
skill_list[level][0] = '\0';
}
for (sn = 0; sn < MAX_SKILL; sn++)
{
if (skill_table[sn].name == NULL )
break;
cSkill = ch->pCabal ? get_cskill( ch->pCabal, sn ) : NULL;
if (cSkill){
level = cSkill->pSkill->level;
sk_level = sklevel(ch,sn);
}
else
level = sk_level = sklevel(ch,sn);
if ( (sk_level < LEVEL_IMMORTAL + 2 || sk_level == CABAL_COST_FAILED)
&& level >= min_lev
&& level <= max_lev
&& skill_table[sn].spell_fun == spell_null
&& ch->pcdata->learned[sn] > 0)
{
found = TRUE;
if (ch->level < sk_level){
if (sk_level == CABAL_COST_FAILED){
sprintf(buf,"%-17s <`!%3d``> ",skill_table[sn].name,
URANGE(0, ch->pcdata->learned[sn] + ch->pcdata->to_learned[sn], 110));
}
else
sprintf(buf,"%-18s n/a ", skill_table[sn].name);
}
else if (ch->pcdata->to_learned[sn] != 0)
sprintf(buf,"%-18s `%s%3d`` ",
skill_table[sn].name,
ch->pcdata->to_learned[sn] > 0 ? "@" : "1",
URANGE(0, ch->pcdata->learned[sn] + ch->pcdata->to_learned[sn], 110));
else
sprintf(buf,"%-18s %3d ",skill_table[sn].name,
URANGE(0, ch->pcdata->learned[sn] + ch->pcdata->to_learned[sn], 110));
if (skill_list[level][0] == '\0')
sprintf(skill_list[level],"\n\rLevel %2d: %s",level,buf);
else
{
if ( ++skill_columns[level] % 2 == 0)
strcat(skill_list[level],"\n\r ");
strcat(skill_list[level],buf);
}
}
}
/* add on any skill sets */
if (HAS_SS(ch->class)){
int ss = 0;
/* put in each group of ss's at their level */
if ( (ss = ss_lookup(class_table[ch->class].ss)) != 0){
int i = 0;
int picks = 0;
/* check if we even have selections at this level */
for (i = 0; ss_table[ss].level > 0 && i < MAX_SELECT; i++){
int level = ss_table[ss].level[i];
if (ss_table[ss].picks[i] == 0
|| IS_NULLSTR(ss_table[ss].group[i]))
break;
/* check for level range dicatated by the command */
if (level < min_lev || level > max_lev)
continue;
/* check if we have any picks out of this group */
if ( (picks = can_group_select(ch, ss_group_lookup(ss_table[ss].group[i]), level)) == 0)
continue;
found = TRUE;
if (ch->level >= level)
sprintf(buf,"%-17s [%3d] ",ss_table[ss].group[i], picks);
else
sprintf(buf,"%-17s [%3s] ",ss_table[ss].group[i], " n/a");
if (skill_list[level][0] == '\0')
sprintf(skill_list[level],"\n\rLevel %2d: %s",level,buf);
else
{
if ( ++skill_columns[level] % 2 == 0)
strcat(skill_list[level],"\n\r ");
strcat(skill_list[level],buf);
}
}
}
}
if (!IS_NPC(ch) && ch->pcdata->newskills != NULL )
{
SKILL_DATA *nsk;
for (nsk = ch->pcdata->newskills; nsk != NULL; nsk = nsk->next )
{
if ((level=nsk->level) < LEVEL_IMMORTAL + 2
&& level >= min_lev && level <= max_lev
&& skill_table[nsk->sn].spell_fun == spell_null
&& nsk->learned > 0)
{
found = TRUE;
if (ch->level < nsk->level)
sprintf(buf,"%-18s n/a ", skill_table[nsk->sn].name);
else
sprintf(buf,"%-18s %3d ", skill_table[nsk->sn].name, nsk->learned);
if (skill_list[level][0] == '\0')
sprintf(skill_list[level],"\n\rLevel %2d: %s",level,buf);
else
{
if ( ++skill_columns[level] % 2 == 0)
strcat(skill_list[level],"\n\r ");
strcat(skill_list[level],buf);
}
}
}
}
if (!found)
{
send_to_char("No skills found.\n\r",ch);
return;
}
for (level = 0; level < LEVEL_IMMORTAL + 2; level++)
if (skill_list[level][0] != '\0')
send_to_char(skill_list[level],ch);
send_to_char("\n\r",ch);
}
int exp_per_level(CHAR_DATA *ch, int level)
{
int temp;
if (IS_NPC(ch))
return 1000;
temp = (pc_race_table[ch->race].class_mult + class_table[ch->class].extra_exp);
return temp+temp*(level-1)*0.2;
}
long total_exp(CHAR_DATA *ch)
{
int temp, i, total;
if (IS_NPC(ch))
return (ch->level+1)*1000;
temp = (pc_race_table[ch->race].class_mult + class_table[ch->class].extra_exp);
total = temp;
for (i = 1; i <= ch->level; i++)
total += exp_per_level(ch,i);
return total;
}
void check_improve( CHAR_DATA *ch, int sn, bool success, int bonus_gain ){
SKILL_DATA* nsk = NULL;
CSKILL_DATA* cSkill = NULL;
//const
const int base_gain = int_app[get_curr_stat(ch,STAT_INT)].learn;
const int smart_mod = 2;//given to races that learn faster
const int dnd_mul = 300;//%multiplier of gain for dnd system spells
int limit = 100; //how far can the skill be improved.
int rating = 0;
sh_int *learned = 0;
int* progress = 0;
int gain = base_gain;
//npcs do not learn
if (IS_NPC(ch))
return;
//spells cast on self do not case learning either
else if (is_affected(ch, gsn_nolearn))
return;
//do not learn skills we cannot use yet
else if (ch->level < sklevel(ch, sn) )
return;
/* get info on the skill we are going to learn */
/* first check if we should look at dynamic skills */
if ( ch->pCabal && (cSkill = get_cskill(ch->pCabal, sn)) != NULL){
rating = cSkill->pSkill->rating;
learned = &ch->pcdata->learned[sn];
}
else if ( (nsk = nskill_find(ch->pcdata->newskills,sn)) == NULL){
rating = skill_table[sn].rating[ch->class];
learned = &ch->pcdata->learned[sn];
}
else{
rating = nsk->rating;
learned = &nsk->learned;
}
//get skill limit
limit = get_skillmax( ch, sn );
/* easy abort cases */
if (rating == 0 || *learned < 2 || *learned >= limit)
return;
else if (ch->level <= 10 && *learned >= 80)
return;
else
progress = &ch->pcdata->progress[sn];
/* calculate progress gain */
//penalty from the skill_table 1 = normal, 9 = very hard
//ratings of 10 (racial skills are treated as 1)
if (rating == 10)
rating = 1;
rating = URANGE(1, rating, 9);
gain = 2 * base_gain / (1 + rating);
//multiply the basic gain by lag for this skill if any
gain = gain * UMAX(1, skill_table[sn].beats / PULSE_VIOLENCE);
//Double for skills that cannot be used in combat
if (skill_table[sn].minimum_position > POS_FIGHTING)
gain += gain;
//due to legacy issues, we treat bonus of 1 as 0
if (bonus_gain == 1)
bonus_gain -=1;
gain += bonus_gain;
gain += UMAX(0, get_curr_stat(ch,STAT_WIS) - 20);
if (ch->race == grn_half_elf || IS_PERK( ch, PERK_SICKLY))
gain += smart_mod;
if (ch->pcdata->condition[COND_HUNGER] <= 5)
gain /=2;
//failure gain
if (!success)
gain = 15 * gain / 10;
gain = UMAX(1, gain);
if (IS_DNDS(ch)
&& cSkill == NULL
&& skill_table[sn].spell_fun != spell_null
&& !IS_GNBIT(sn, GN_NO_DND)){
gain = dnd_mul * gain / 100;
}
if (skill_table[sn].spell_fun == spell_null)
gain = gain * (100 + ch->aff_mod[MOD_SKILL_LEARN]) / 100;
else
gain = gain * (100 + ch->aff_mod[MOD_SPELL_LEARN]) / 100;
//force increase
if (bonus_gain == -99)
*progress = 0;
//decrease progress
*progress -= gain;
/* check for increase of skill */
if (*progress < 1){
*learned += 1;
*progress = get_skill_reps( *learned );
*progress += (rand() % 11) * *progress / 100;
sendf(ch,"You have become better at %s!\n\r", skill_table[sn].name);
gain_exp(ch, number_range( rating, rating * 15));
if (*learned == limit){
sendf(ch, "You have now mastered <%s>!\n\r",skill_table[sn].name);
*progress = 0;
}
}
}
void check_improve_old( CHAR_DATA *ch, int sn, bool success, int multiplier )
{
SKILL_DATA* nsk = NULL;
CSKILL_DATA* cSkill = NULL;
//const
const int base_chance = int_app[get_curr_stat(ch,STAT_INT)].learn;
const int level_mod = 50; //(percent of lvl bonus)
const int wis_mod = 50; //(percent of lvl bonus)
const int smart_mod = 10;//given to smart races.
const int dnd_mul = 600;//multiplier of chance for dnd spell system spells
int limit = 100; //how far can the skill be improved.
int mod = 0;
int rating = 0;
sh_int *learned = 0;
int chance;
bool dcheck = TRUE;
if (IS_NPC(ch))
return;
else if (is_affected(ch, gsn_nolearn))
return;
if (sn > 5000){
dcheck = FALSE;
sn -= 5000;
}
if (ch->level < sklevel(ch,sn) )
return;
limit = get_skillmax( ch, sn );
/* get info on the skill we are going to learn */
/* first check if we should look at dynamic skills */
if ( ch->pCabal && (cSkill = get_cskill(ch->pCabal, sn)) != NULL){
rating = cSkill->pSkill->rating;
learned = &ch->pcdata->learned[sn];
}
else if ( (nsk = nskill_find(ch->pcdata->newskills,sn)) == NULL){
rating = skill_table[sn].rating[ch->class];
learned = &ch->pcdata->learned[sn];
}
else{
rating = nsk->rating;
learned = &nsk->learned;
}
/* check for skill stats now */
if (rating == 0
|| *learned < 2
|| *learned >= limit)
return;
if (ch->level <= 10 && *learned >= 80)
return;
/* check if this is a dnd spell caster */
if (multiplier == -99){
sendf(ch,"You have become better at %s!\n\r", skill_table[sn].name);
*learned += 1;
gain_exp(ch, rating);
return;
}
chance = base_chance;
//benefit from multiplier.
chance = (9 + UMAX(1, multiplier)) * chance / 10;
//penalty from the skill_table
chance = (11 - ( rating >= 10? 6: rating)) * chance / 10;
//level bonus
chance += level_mod * ch->level / 100;
//smart races bonus
if (ch->race == race_lookup("half-elf")
|| ch->race == race_lookup("faerie")
|| IS_PERK( ch, PERK_SICKLY)
)
chance += smart_mod;
//wisdom bonus
chance += wis_mod * get_curr_stat(ch,STAT_WIS) / 100;
if (ch->pcdata->condition[COND_HUNGER] <= 5)
chance /=2;
if (!success)
chance = 12 * chance / 10;
chance = UMAX(1, chance);
if (IS_DNDS(ch)
&& cSkill == NULL
&& skill_table[sn].spell_fun != spell_null
&& !IS_GNBIT(sn, GN_NO_DND)){
chance += dnd_mul * chance / 100;
}
if (number_range(1,1000) > chance){
if (number_percent() < 5 && dcheck)
check_improve(ch,sn+5000,success,multiplier);
return;
}
if (skill_table[sn].spell_fun == spell_null)
mod = ch->aff_mod[MOD_SKILL_LEARN];
else
mod = ch->aff_mod[MOD_SPELL_LEARN];
if (success){
chance = URANGE(5,limit - *learned, 95);
chance = chance * (100 + mod) / 100;
if (number_percent() < chance){
sendf(ch,"You have become better at %s!\n\r", skill_table[sn].name);
*learned += 1;
gain_exp(ch, number_range( rating, rating * 15));
}
}
else{
chance = URANGE(5, *learned / 2, 30);
chance = chance * (100 + mod) / 100;
if (number_percent() < chance){
sendf(ch,"You learn from your mistakes, and your %s skill improves.\n\r",skill_table[sn].name);
*learned += number_range(1,3);
*learned = UMIN(*learned, limit);
gain_exp(ch, rating * 20);
}
}
if (*learned == limit)
sendf(ch, "You have now mastered <%s>!\n\r",skill_table[sn].name);
}
int group_lookup( const char *name )
{
int gn;
for ( gn = 0; gn < MAX_GROUP; gn++ )
{
if ( group_table[gn].name == NULL )
break;
if ( LOWER(name[0]) == LOWER(group_table[gn].name[0]) && !str_prefix( name, group_table[gn].name ) )
return gn;
}
return -1;
}
void gn_add( CHAR_DATA *ch, int gn)
{
int i;
ch->pcdata->group_known[gn] = TRUE;
for ( i = 0; i < MAX_IN_GROUP; i++)
{
if (group_table[gn].spells[i] == NULL)
break;
group_add(ch,group_table[gn].spells[i],FALSE);
}
}
void group_add( CHAR_DATA *ch, const char *name, bool deduct)
{
int sn = skill_lookup(name), gn = group_lookup(name);
if (IS_NPC(ch))
return;
if (sn != -1)
{
if (ch->pcdata->learned[sn] == 0 || ch->pcdata->learned[sn] == 1 )
{
if (deduct)
ch->pcdata->learned[sn] = 100;
else
ch->pcdata->learned[sn] = 1;
}
return;
}
if (gn != -1)
{
if (ch->pcdata->group_known[gn] == FALSE)
ch->pcdata->group_known[gn] = TRUE;
gn_add(ch,gn);
}
}
void do_envenom(CHAR_DATA *ch, char *argument)
{
OBJ_DATA *obj;
AFFECT_DATA af;
bool fAdv = get_skill(ch, skill_lookup("lotus scourge")) > 1;
int percent, skill, np = number_percent();
if ((skill = get_skill(ch,gsn_envenom)) == 0)
{
send_to_char("Are you crazy? You'd poison yourself!\n\r",ch);
return;
}
if (argument[0] == '\0')
{
send_to_char("Envenom what item?\n\r",ch);
return;
}
obj = get_obj_list(ch,argument,ch->carrying);
if (obj== NULL)
{
send_to_char("You don't have that item.\n\r",ch);
return;
}
if (ch->mana < 50)
{
send_to_char("Rest up a bit first.\n\r",ch);
return;
}
ch->mana -= 50;
if (fAdv){
send_to_char("Using the lore of the Lotus Scourge you prepare a deadly toxin.\n\r", ch);
}
if (obj->item_type == ITEM_FOOD || obj->item_type == ITEM_DRINK_CON)
{
if (UMAX(1,np + 2*(get_curr_stat(ch,STAT_LUCK) - 16)) < skill)
{
act("$n treats $p with deadly poison.",ch,obj,NULL,TO_ROOM);
act("You treat $p with deadly poison.",ch,obj,NULL,TO_CHAR);
if (!obj->value[3])
{
obj->value[3] = 1;
check_improve(ch,gsn_envenom,TRUE,1);
}
else
send_to_char("It's already poisoned.\n\r",ch);
WAIT_STATE2(ch,skill_table[gsn_envenom].beats);
return;
}
act("You fail to poison $p.",ch,obj,NULL,TO_CHAR);
if (!obj->value[3])
check_improve(ch,gsn_envenom,FALSE,1);
WAIT_STATE2(ch,skill_table[gsn_envenom].beats);
return;
}
if (obj->item_type == ITEM_THROW)
{
if (obj->value[3] < 0 || attack_table[obj->value[3]].damage == DAM_BASH)
{
send_to_char("You can only envenom edged weapons.\n\r",ch);
return;
}
if (IS_WEAPON_STAT(obj,WEAPON_POISON))
{
act("$p is already envenomed.",ch,obj,NULL,TO_CHAR);
return;
}
percent = number_percent();
percent -= 3 * (get_curr_stat(ch,STAT_LUCK) - 10);
if (percent < 4 * skill / 5)
{
af.where = TO_WEAPON;
af.type = gsn_poison;
af.level = fAdv ? ch->level + 5 : ch->level;
af.duration = fAdv ? ch->level : ch->level * percent / 75;
af.location = 0;
af.modifier = 0;
af.bitvector = WEAPON_POISON;
affect_to_obj(obj,&af);
act("$n coats $p with deadly venom.",ch,obj,NULL,TO_ROOM);
act("You coat $p with venom.",ch,obj,NULL,TO_CHAR);
check_improve(ch,gsn_envenom,TRUE,3);
WAIT_STATE2(ch,skill_table[gsn_envenom].beats);
return;
}
else
{
act("You fail to envenom $p.",ch,obj,NULL,TO_CHAR);
check_improve(ch,gsn_envenom,FALSE,3);
WAIT_STATE2(ch,skill_table[gsn_envenom].beats);
return;
}
}
act("You can't poison $p.",ch,obj,NULL,TO_CHAR);
}
void do_berserk( CHAR_DATA *ch, char *argument)
{
int chance, hp_percent;
if ((chance = 3 * get_skill(ch,gsn_berserk) / 4) == 0)
{
send_to_char( "Huh?\n\r", ch );
return;
}
if ((IS_NPC(ch) && !IS_SET(ch->off_flags,OFF_BERSERK))
|| (!IS_NPC(ch) && ch->level < skill_table[gsn_berserk].skill_level[ch->class]))
{
send_to_char("You turn red in the face, but nothing happens.\n\r",ch);
return;
}
if (IS_AFFECTED(ch,AFF_BERSERK) || is_affected(ch,gsn_berserk) || is_affected(ch,skill_lookup("frenzy")))
{
send_to_char("You get a little madder.\n\r",ch);
return;
}
if (IS_AFFECTED(ch,AFF_CALM) || is_affected(ch,gsn_prayer))
{
send_to_char("You can't get worked up in your calm state.\n\r",ch);
return;
}
if (!IS_NPC(ch) && ch->mana < 50)
{
send_to_char("You can't get up enough energy.\n\r",ch);
return;
}
if (ch->position == POS_FIGHTING && chance > 1)
chance += 35;
hp_percent = 100 * ch->hit/ch->max_hit;
if (number_percent() < chance)
{
AFFECT_DATA af;
WAIT_STATE2(ch,PULSE_VIOLENCE);
ch->move = UMAX(ch->move - 50, 0);
if (!IS_NPC(ch))
ch->mana -= 50;
ch->hit += 2 * ch->level;
act("Your pulse races as you are consumed by rage!",ch,NULL,NULL,TO_CHAR);
act("$n gets a wild look in $s eyes.",ch,NULL,NULL,TO_ROOM);
check_improve(ch,gsn_berserk,TRUE,1);
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/8);
af.bitvector = AFF_BERSERK;
af.location = APPLY_DAMROLL;
affect_to_char(ch,&af);
af.location = APPLY_HITROLL;
af.modifier = UMAX(1, ch->level / 16);
affect_to_char(ch,&af);
af.modifier = 40;
af.location = APPLY_AC;
affect_to_char(ch,&af);
af.modifier = ch->level;
af.location = APPLY_HIT;
affect_to_char(ch, &af);
}
else
{
WAIT_STATE2(ch,3 * PULSE_VIOLENCE);
ch->mana -= 25;
send_to_char("Your pulse speeds up, but nothing happens.\n\r",ch);
check_improve(ch,gsn_berserk,FALSE,1);
}
}
void do_bash( CHAR_DATA *ch, char *argument )
{
char arg[MIL], buf[MSL];
CHAR_DATA *victim;
//Data
int chance = 4 * get_skill(ch,gsn_bash) /5;
int dam = number_range(10 + ch->level/2, ch->size * ch->level / 2);
int vic_lag = PULSE_VIOLENCE;
int ch_lag = skill_table[gsn_bash].beats;
//bools
bool fSuccess = FALSE;
bool fYell = FALSE;
one_argument(argument,arg);
if (chance == 0)
{
send_to_char("Bashing? What's that?\n\r",ch);
return;
}
if (arg[0] == '\0')
{
victim = ch->fighting;
if (victim == NULL)
{
send_to_char("But you aren't fighting anyone!\n\r",ch);
return;
}
}
else if ((victim = get_char_room(ch, NULL, arg)) == NULL)
{
send_to_char("They aren't here.\n\r",ch);
return;
}
if ( victim == ch )
{
send_to_char("Self mutilation is not your style.\n\r",ch);
return;
}
if (is_safe(ch,victim))
return;
//Get chance to bash.
chance += ch->carry_weight/200 - victim->carry_weight/200;
chance += get_curr_stat(ch,STAT_STR) - get_curr_stat(victim,STAT_DEX);
chance += GET_AC2(victim,AC_BASH) /25;
chance -= get_skill(victim,gsn_dodge)/20;
chance += (ch->level - victim->level);
chance += (get_curr_stat(ch,STAT_LUCK) - get_curr_stat(victim,STAT_LUCK));
if ( ch->race == race_lookup("avian")
|| victim->race == race_lookup("faerie") )
chance -=5;
if ( victim->class == class_lookup("thief") )
chance -= 5;
if (is_affected(victim,gsn_horse))
chance -= 5;
if (!IS_NPC(victim) && victim->pcdata->pStallion && number_percent() < get_skill(victim, gsn_mounted)){
chance -= 12;
check_improve(victim, gsn_mounted, TRUE, 0);
}
chance += affect_by_size(ch,victim);
//check if target should yell.
fYell = (ch->fighting != victim && victim->fighting != ch);
//sound attack to justice /imm
a_yell(ch,victim);
// sendf( ch, "chance: %d", chance );
if (number_percent() < chance)
{
vic_lag = URANGE(1, number_range(1, ch->size - victim->size + 3), 4) * PULSE_VIOLENCE;
fSuccess = TRUE;
}
else
{
dam = 0;
}
//predict interdict
if (predictCheck(ch, victim, "bash", skill_table[gsn_bash].name))
return;
//MANTIS CHECK
if (is_affected(victim,gsn_mantis) && fSuccess)
{
act("You use $n's momentum against him, and throw $m to the ground!",ch,NULL,victim,TO_VICT);
act("$N reverses your attack, and throws you to the ground!",ch,NULL,victim,TO_CHAR);
act("$N reversed $n's attack, and throws $m to the ground.",ch,NULL,victim,TO_NOTVICT);
WAIT_STATE2(ch, URANGE(1, number_range(1, victim->size), 3) * PULSE_VIOLENCE);
damage(victim,ch,dam,gsn_mantis,DAM_BASH,TRUE);
affect_strip(victim,gsn_mantis);
return;
}//END MANTIS
//check for lag protect
if (!do_lagprot(ch, victim, chance, &dam, &vic_lag, gsn_bash, fSuccess, fYell))
{
if (fYell)
{
sprintf(buf, "Help! %s is trying to bash me!",PERS(ch,victim));
j_yell(victim,buf);
}
if (fSuccess)
{
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);
}
else
{
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);
}
}//END IF NO PROTECTION
if (!fSuccess || dam == 0 || vic_lag == 0)
{
check_improve(ch, gsn_bash, FALSE, 1);
ch_lag = 3 * ch_lag / 2;
}
else
check_improve(ch, gsn_bash, TRUE, 1);
WAIT_STATE2(ch, ch_lag);
if (vic_lag != 0 && dam != 0)
WAIT_STATE2(victim, vic_lag);
if (ch->race == race_lookup("fire") && number_percent() < 3 * ch->level / 2)
damage(ch,victim,3 * dam / 2,gsn_bash ,DAM_FIRE,TRUE);
else
damage(ch,victim,dam,gsn_bash,DAM_BASH,TRUE);
if (ch && victim && ch->fighting == victim && dam > 0)
check_ccombat_actions( victim, ch, CCOMBAT_BASHED);
}
/* does the actual dirt kicking: */
/* wait = true will lag the dirt kicker */
/* wait = false will not lag the dirt kicker */
void do_dirting ( CHAR_DATA *ch, int wait, char *argument) {
char arg[MIL], buf[MSL];
CHAR_DATA *victim;
int chance;
one_argument(argument,arg);
if ( (chance = get_skill(ch,gsn_dirt)) == 0)
{
send_to_char("You get your feet dirty.\n\r",ch);
return;
}
if (arg[0] == '\0')
{
victim = ch->fighting;
if (victim == NULL)
{
send_to_char("But you aren't in combat!\n\r",ch);
return;
}
}
else if ((victim = get_char_room(ch, NULL, arg)) == NULL)
{
send_to_char("They aren't here.\n\r",ch);
return;
}
if (is_safe(ch,victim))
return;
if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim )
{
sendf(ch, "%s is your beloved master.\n\r", PERS(victim,ch) );
return;
}
if (IS_AFFECTED(victim,AFF_BLIND))
{
act("$E's already been blinded.",ch,NULL,victim,TO_CHAR);
return;
}
if ( victim == ch )
return;
chance += get_curr_stat(ch,STAT_DEX) - get_curr_stat(victim,STAT_DEX);
chance += (ch->level - victim->level);
chance -= get_skill(victim,gsn_dodge)/10;
chance += UMAX(0, victim->size - SIZE_MEDIUM) * 5;
chance += (get_curr_stat(ch,STAT_LUCK) - get_curr_stat(victim,STAT_LUCK));
switch(ch->in_room->sector_type)
{
case(SECT_INSIDE): chance -= 25; break;
case(SECT_CITY): chance -= 15; 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 += 25; break;
}
if (chance == 0)
{
send_to_char("There isn't any dirt to kick.\n\r",ch);
return;
}
if (wait == TRUE) {
WAIT_STATE2(ch,skill_table[gsn_dirt].beats);
}
a_yell(ch,victim);
//predict interdict
if (predictCheck(ch, victim, "dirt", skill_table[gsn_dirt].name))
return;
chance = chance - 25 + UMIN(ch->level,25);
if (is_affected(victim, gsn_mist_form))
{
act("You kick a few stones right through the mist.", ch, NULL, victim, TO_CHAR);
act("$n kicks a bit of dirt right through $N.", ch, NULL, victim, TO_NOTVICT);
act("$N kick a handfull of dirt through your non-corporeal form.", ch, NULL, victim, TO_CHAR);
chance = 0;
}
if (number_percent() < chance)
{
bool fDirtProt = (IS_EVIL(victim) && victim->race == race_lookup("slith") && number_percent() < 15 + victim->level);
AFFECT_DATA af;
if (ch->fighting != victim && victim->fighting != ch)
{
sprintf(buf, "Help! %s kicked dirt into my eyes!",PERS(ch,victim));
j_yell(victim,buf);
}
act("$n is blinded by the dirt in $s eyes!",victim,NULL,NULL,TO_ROOM);
act("$n kicks dirt in your eyes!",ch,NULL,victim,TO_VICT);
damage(ch,victim,number_range(2,5),gsn_dirt,DAM_NONE,TRUE);
send_to_char("You can't see a thing!\n\r",victim);
check_improve(ch,gsn_dirt,TRUE,1);
if (fDirtProt)
{
send_to_char("Your lizard ancestry serves you well and you easly recover.\n\r", victim);
return;
}
af.where = TO_AFFECTS;
af.type = gsn_dirt;
af.level = ch->level;
af.duration = 0;
af.location = APPLY_HITROLL;
if (!IS_NPC(victim) && number_percent() < get_skill(victim,gsn_blind_fighting)){
if (is_affected(victim, gsn_battletrance))
af.modifier = 0;
else
af.modifier = -3;
}
else
af.modifier = -6;
af.bitvector = AFF_BLIND;
affect_to_char(victim,&af);
af.location = APPLY_AC;
if (!IS_NPC(victim) && number_percent() < get_skill(victim,gsn_blind_fighting)){
if (is_affected(victim, gsn_battletrance))
af.modifier = 0;
else
af.modifier = +5;
}
else
af.modifier = +15;
affect_to_char(victim,&af);
}
else
{
if (ch->fighting != victim && victim->fighting != ch)
{
sprintf(buf, "Help! %s tried to kick dirt into my eyes!",PERS(ch,victim));
j_yell(victim,buf);
}
damage(ch,victim,0,gsn_dirt,DAM_NONE,TRUE);
check_improve(ch,gsn_dirt,FALSE,1);
if (ch->fighting == NULL) {
if (wait == TRUE) {
WAIT_STATE2(ch,skill_table[gsn_dirt].beats);
}
}
}
}
void do_dirt( CHAR_DATA *ch, char *argument ) {
do_dirting (ch, TRUE, argument);
}
void trip( CHAR_DATA *ch, CHAR_DATA* victim, int chance)
{
bool fTrample = !IS_NPC(ch) && get_skill(ch, gsn_trample) > 1;
int position = victim->position;
if ((IS_AFFECTED(victim,AFF_FLYING)
&& !is_affected(victim,gsn_thrash))
|| (!IS_NPC(victim) && victim->pcdata->pStallion != NULL && get_skill(victim, gsn_mounted)))
{
act("$S feet aren't on the ground.",ch,NULL,victim,TO_CHAR);
act("Luckily your feet aren't on the ground.",ch,NULL,victim,TO_VICT);
return;
}
if (check_ccombat_actions( victim, ch, CCOMBAT_TRIPPED))
return;
if (number_percent() < get_skill(victim, gsn_balance)
&& is_empowered_quiet(victim,1) && victim->mana > 0)
{
act("$n tries to trip you, but you keep your balance!",ch,NULL,victim,TO_VICT);
act("You try to trip $N, but $E keeps $S balance!",ch,NULL,victim,TO_CHAR);
act("$n tries to trip $N, but $E keeps $S balance.",ch,NULL,victim,TO_NOTVICT);
check_improve(victim,gsn_balance,TRUE,50);
victim->mana -= URANGE(0,25,victim->mana);
}
else
{
act("$n trips you and you go down!",ch,NULL,victim,TO_VICT);
act("You trip $N and $E goes down!",ch,NULL,victim,TO_CHAR);
act("$n trips $N, sending $M to the ground.",ch,NULL,victim,TO_NOTVICT);
if (!is_affected(victim, gsn_iron_will)
|| victim->mana < 1
|| number_percent() < (95 + (victim->level - ch->level) * 3)){
if (fTrample && ch->size >= victim->size)
WAIT_STATE2(victim, ch->size * PULSE_VIOLENCE);
else
WAIT_STATE2(victim, UMIN(2,number_range(1, victim->size)) * PULSE_VIOLENCE);
position = POS_RESTING;
}
else{
send_to_char("Through your force of will you remain upright.\n\r", ch);
act("$n somehow remains upright.", victim, NULL, NULL, TO_ROOM);
victim->mana -= URANGE(0,25,victim->mana);
}
}
if (fTrample && ch->size >= victim->size)
damage(ch,victim, number_range(10, 20) * ch->size, gsn_trample, DAM_BASH, TRUE);
else
damage(ch,victim, number_range(2, 2 + 2 * victim->size), gsn_trip,DAM_BASH,TRUE);
if (ch && ch->fighting && victim && victim->in_room){
victim->position = position;
check_ccombat_actions( ch, victim, CCOMBAT_TRIP);
}
}
void do_trip( CHAR_DATA *ch, char *argument )
{
char arg[MIL], buf[MSL];
CHAR_DATA *victim;
int chance;
one_argument(argument,arg);
if ( (chance = get_skill(ch,gsn_trip)) == 0)
{
send_to_char("Tripping? What's that?\n\r",ch);
return;
}
if (!is_empowered(ch,0))
return;
if (arg[0] == '\0')
{
victim = ch->fighting;
if (victim == NULL)
{
send_to_char("But you aren't fighting anyone!\n\r",ch);
return;
}
}
else if ((victim = get_char_room(ch, NULL, arg)) == NULL)
{
send_to_char("They aren't here.\n\r",ch);
return;
}
if ((IS_AFFECTED(victim,AFF_FLYING) && !is_affected(victim,gsn_thrash))
|| (!IS_NPC(victim) && victim->pcdata->pStallion != NULL && get_skill(victim, gsn_mounted)))
{
act("$S feet aren't on the ground.",ch,NULL,victim,TO_CHAR);
act("Luckily your feet aren't on the ground.",ch,NULL,victim,TO_VICT);
return;
}
if ( victim == ch )
return;
if (is_safe(ch,victim))
return;
if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim )
{
sendf(ch, "%s is your beloved master.\n\r", PERS(victim,ch) );
return;
}
chance += (get_curr_stat(ch,STAT_DEX) - get_curr_stat(victim,STAT_DEX))*3;
chance += (ch->level - victim->level);
//bigger guys are easier to trip
chance += UMAX(0, victim->size - SIZE_MEDIUM) * 5;
chance += (get_curr_stat(ch,STAT_LUCK) - get_curr_stat(victim,STAT_LUCK));
if (is_affected(victim,gsn_horse))
chance -= 20;
if (IS_AFFECTED2(victim,AFF_BLUR))
chance /= 2;
a_yell(ch,victim);
//predict interdict
if (predictCheck(ch, victim, "trip", skill_table[gsn_trip].name))
return;
if (number_percent() < chance)
{
if (is_affected(victim,gsn_mantis) && !(IS_AFFECTED(ch,AFF_FLYING) && !is_affected(ch,gsn_thrash)))
{
if (ch->fighting != victim && victim->fighting != ch)
{
sprintf(buf, "Help! %s just tried to tripped me!",PERS(ch,victim));
j_yell(victim,buf);
}
act("You reversed $n's trip, and $e goes down!",ch,NULL,victim,TO_VICT);
act("$N reverses your trip, and you go down!",ch,NULL,victim,TO_CHAR);
act("$N reversed $n's trip, sending $m to the ground.",ch,NULL,victim,TO_NOTVICT);
if (!(is_affected(ch, gsn_iron_will) && ch->mana > 0) || number_percent() < 50 + victim->level - ch->level){
ch->position = POS_RESTING;
WAIT_STATE2(ch, UMIN(2,number_range(ch->size,1)) * PULSE_VIOLENCE);
}
else{
send_to_char("Through your force of will you remain upright.\n\r", ch);
act("$n somehow remains upright.", victim, NULL, NULL, TO_ROOM);
victim->mana -= URANGE(0,25,victim->mana);
ch->mana -= URANGE(0,25,ch->mana);
}
damage(victim,ch,number_range(2, 2 + 2 * ch->size),gsn_trip,DAM_BASH,TRUE);
affect_strip(victim,gsn_mantis);
return;
}
if (ch->fighting != victim && victim->fighting != ch)
{
sprintf(buf, "Help! %s just tripped me!",PERS(ch,victim));
j_yell(victim,buf);
}
if (ch->class == class_lookup("monk"))
{
act("$n trips you with a leg sweep and you go down!",ch,NULL,victim,TO_VICT);
act("You trip $N with a leg sweep and $E goes down!",ch,NULL,victim,TO_CHAR);
act("$n trips $N with a leg sweep, sending $M to the ground.",ch,NULL,victim,TO_NOTVICT);
if (!(is_affected(victim, gsn_iron_will) && victim->mana > 0) || number_percent() < (25 + victim->level - ch->level)){
WAIT_STATE2(victim, UMIN(2,number_range(victim->size,1)) * PULSE_VIOLENCE);
victim->position = POS_RESTING;
}
else{
send_to_char("Through your force of will you remain upright.\n\r", ch);
act("$n somehow remains upright.", victim, NULL, NULL, TO_ROOM);
victim->mana -= URANGE(0,25,victim->mana);
}
damage(ch,victim,number_range(2, 2 + 2 * victim->size),gsn_trip,DAM_BASH,TRUE);
}
else
trip(ch, victim, chance);
WAIT_STATE2(ch,skill_table[gsn_trip].beats);
check_improve(ch,gsn_trip,TRUE,1);
}
else
{
if (ch->fighting != victim && victim->fighting != ch)
{
sprintf(buf, "Help! %s tried to trip me!",PERS(ch,victim));
j_yell(victim,buf);
}
damage(ch,victim,0,gsn_trip,DAM_BASH,TRUE);
check_improve(ch,gsn_trip,FALSE,1);
WAIT_STATE2(ch,2 * skill_table[gsn_trip].beats / 3);
}
}
void do_lash( CHAR_DATA *ch, char *argument )
{
char arg[MIL];
CHAR_DATA *victim;
AFFECT_DATA af; // affect data (for air_thrash)
one_argument(argument,arg);
if (arg[0] == '\0')
{
victim = ch->fighting;
}
else if ((victim = get_char_room(ch, NULL, arg)) == NULL)
{
return;
}
act("$n lashes at you with $s weapon and you go down!",ch,NULL,victim,TO_VICT);
act("You lash at $N with your weapon and $N goes down!",ch,NULL,victim,TO_CHAR);
act("$n lashes at $N with $s, sending $M to the ground.",ch,NULL,victim,TO_NOTVICT);
/* air thrash the victim if flying */
if (IS_AFFECTED(victim, AFF_FLYING) && !is_affected(victim, gsn_thrash)) {
af.where = TO_AFFECTS;
af.type = gsn_thrash;
af.level = ch->level;
af.duration = 0;
af.modifier = 0;
af.location = 0;
af.bitvector = 0;
affect_to_char(victim,&af);
act("You can't seem to get back into the air",victim,NULL,NULL,TO_CHAR);
act("$n can't seem to get back into the air",victim,NULL,NULL,TO_ROOM);
}
}
void do_backstab( CHAR_DATA *ch, char *argument )
{
char arg[MIL], buf[MSL];
CHAR_DATA *victim;
OBJ_DATA *obj, *obj2;
int chance, dual_chance, wpnswitch;
one_argument( argument, arg );
if ((chance = get_skill(ch,gsn_backstab)) == 0)
{
send_to_char("You don't know how to backstab.\n\r",ch);
return;
}
if (arg[0] == '\0')
{
send_to_char("Backstab whom?\n\r",ch);
return;
}
if (ch->fighting != NULL)
{
send_to_char("You can't backstab while fighting.\n\r",ch);
return;
}
if ((victim = get_char_room(ch, NULL, arg)) == NULL)
{
send_to_char("They aren't here.\n\r",ch);
return;
}
if (victim->fighting != NULL)
{
sendf(ch, "%s won't hold still long enough.\n\r", PERS(victim,ch));
return;
}
if (IS_NPC(victim) && IS_SET(victim->act, ACT_TOO_BIG) )
{
sendf(ch, "%s is too alert for you to attempt such an act.\n\r", PERS(victim,ch));
return;
}
if ( victim == ch )
return;
if ( is_safe( ch, victim ) )
return;
if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim )
{
sendf(ch, "%s is your beloved master.\n\r", PERS(victim,ch) );
return;
}
obj = get_eq_char( ch, WEAR_WIELD );
obj2 = get_eq_char( ch, WEAR_SECONDARY);
wpnswitch = FALSE;
if (obj == NULL
|| (obj->value[0] != WEAPON_DAGGER
&& obj->value[0] != WEAPON_EXOTIC
&& obj->value[0] != WEAPON_SPEAR))
{
wpnswitch = TRUE;
if (obj2 == NULL
|| (obj2->value[0] != WEAPON_DAGGER
&& obj2->value[0] != WEAPON_EXOTIC
&& obj2->value[0] != WEAPON_SPEAR))
{
send_to_char( "You need to wield a piercing weapon to backstab.\n\r", ch );
return;
}
}
if (IS_AFFECTED(ch, AFF_SLOW) && !IS_AFFECTED(ch, AFF_HASTE))
{
send_to_char("You can't seem to get up enough speed.\n\r",ch);
return;
}
if ( !IS_NPC(ch) && victim->hit < (victim->max_hit * 0.85) )
{
sendf(ch, "%s is hurt and suspicious ... you can't sneak up.\n\r", PERS(victim,ch) );
return;
}
dual_chance = chance;
chance += get_curr_stat(ch,STAT_DEX)+get_curr_stat(ch,STAT_INT)/2;
chance -= get_curr_stat(victim,STAT_DEX)+get_curr_stat(ch,STAT_WIS)/2;
if (IS_SET(ch->off_flags,OFF_FAST) || IS_AFFECTED(ch,AFF_HASTE))
chance += 10;
if (IS_SET(victim->off_flags,OFF_FAST) || IS_AFFECTED(victim,AFF_HASTE))
chance -= 10;
chance += (ch->level - victim->level);
chance += 2*(get_curr_stat(ch,STAT_LUCK) - get_curr_stat(victim,STAT_LUCK));
if (!IS_AWAKE(victim) )
chance += 10;
WAIT_STATE2( ch, skill_table[gsn_backstab].beats );
a_yell(ch,victim);
//predict interdict
if (predictCheck(ch, victim, "backstab", skill_table[gsn_backstab].name))
return;
if ( number_percent( ) < chance || !IS_AWAKE(victim) )
{
check_improve(ch,gsn_backstab,TRUE,1);
//MANTIS CHECK
if ( (is_affected(victim,gsn_mantis) || get_skill(victim, gsn_shadowmaster) > 1) && IS_AWAKE(victim)){
act("You sense $n's movement and throw $m to the ground!",ch,NULL,victim,TO_VICT);
act("$N senses your attack, and throws you to the ground!",ch,NULL,victim,TO_CHAR);
act("$N senses $n's attack, and throws $m to the ground.",ch,NULL,victim,TO_NOTVICT);
WAIT_STATE2(ch, URANGE(2, 1 + number_range(1, victim->size), 4) * PULSE_VIOLENCE);
do_visible(ch, "");
sprintf(buf, "Help! %s just tried to backstab me!",PERS(ch,victim));
j_yell(victim,buf);
affect_strip(victim,gsn_mantis);
damage(victim,ch,10,gsn_mantis,DAM_BASH,TRUE);
return;
}//END MATIS
sprintf(buf, "Help! %s backstabbed me!",PERS(ch,victim));
j_yell(victim,buf);
if (!wpnswitch)
one_hit( ch, victim, gsn_backstab, FALSE );
if (wpnswitch)
{
if (number_percent( ) < get_skill(ch, gsn_dual_wield))
one_hit( ch, victim, gsn_backstab, TRUE );
else
damage( ch, victim, 0, gsn_backstab, DAM_NONE, TRUE);
}
dual_chance -= chance;
if ((chance = get_skill(ch, gsn_dual_backstab)) != 0 && (!wpnswitch)
&& (obj != NULL
&& (obj->value[0] == WEAPON_DAGGER
|| obj->value[0] == WEAPON_EXOTIC
|| obj->value[0] == WEAPON_SPEAR))
&& (obj2 != NULL
&& (obj2->value[0] == WEAPON_DAGGER
|| obj2->value[0] == WEAPON_EXOTIC
|| obj2->value[0] == WEAPON_SPEAR)) )
{
if ((number_percent( ) < 3*(chance - dual_chance) /4
&& number_percent( ) < get_skill(ch, gsn_dual_wield)) )
{
check_improve(ch,gsn_dual_backstab,TRUE,1);
one_hit( ch, victim, gsn_dual_backstab, TRUE );
}
else
check_improve(ch,gsn_dual_backstab,FALSE,1);
}
}
else
{
check_improve(ch,gsn_backstab,FALSE,1);
if (ch->fighting == NULL)
{
sprintf(buf, "Help! %s tried to backstab me!",PERS(ch,victim));
j_yell(victim,buf);
}
damage( ch, victim, 0, gsn_backstab,DAM_NONE,TRUE);
dual_chance -= chance;
if ((chance = get_skill(ch, gsn_dual_backstab)) != 0 && (!wpnswitch)
&& (obj != NULL && (obj->value[0] == 2 || obj->value[0] == 3))
&& (obj2 != NULL && (obj2->value[0] == 2 || obj2->value[0] == 3)))
{
if ((number_percent( ) < (2 * (chance - dual_chance) /3)
&& number_percent( ) < get_skill(ch, gsn_dual_wield)))
{
check_improve(ch,gsn_dual_backstab,TRUE,1);
one_hit( ch, victim, gsn_dual_backstab, TRUE );
}
else
check_improve(ch,gsn_dual_backstab,FALSE,1);
}
}
}
void do_rescue( CHAR_DATA *ch, char *argument )
{
char arg[MIL];
CHAR_DATA *victim, *v_next, *ech, *fch = NULL;
int chance = 0;
int skill = get_skill(ch, gsn_rescue);
one_argument( argument, arg );
if ( arg[0] == '\0' )
{
send_to_char( "Rescue whom?\n\r", ch );
return;
}
if ( ( victim = get_char_room( ch, NULL, arg ) ) == NULL )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
if ( victim == ch )
return;
/* psalm of one god */
if (is_affected(ch, gsn_ogtrium))
skill = 150;
if (!IS_NPC(ch) && skill < 1)
{
send_to_char( "You don't know how to rescue.\n\r", ch );
return;
}
if ( victim->fighting == NULL )
{
sendf(ch, "%s is not fighting right now.\n\r", PERS(victim,ch) );
return;
}
/* special guards */
if (IS_NPC(ch)
&& (ch->pIndexData->vnum == MOB_VNUM_SPECIAL_GUARD
|| ch->pIndexData->vnum == MOB_VNUM_HOUND)
&& !IS_AREA(ch->in_room->area, AREA_LAWFUL)
&& !IS_WANTED(victim->fighting))
return;
if (is_safe(ch, victim->fighting))
return;
for ( ech = victim->in_room->people; ech != NULL; ech = v_next )
{
v_next = ech->next_in_room;
if ( ech->fighting != NULL && ech->fighting == victim)
{
if ( IS_NPC(ch) && ch->leader != NULL && !IS_NPC(ch->leader) && is_safe(ch->leader, ech) )
continue;
else if (is_safe(ch,ech))
continue;
fch = ech;
break;
}
}
if ( ch->fighting == victim )
{
send_to_char( "Too late.\n\r", ch );
return;
}
WAIT_STATE2( ch, skill_table[gsn_rescue].beats );
WAIT_STATE2( victim, 2 * PULSE_VIOLENCE);
if ( fch == NULL )
{
send_to_char( "You cannot rescue them.\n\r", ch );
return;
}
chance = skill;
if (chance > 0);
chance += 2*(get_curr_stat(ch,STAT_LUCK) - 16);
if ( number_percent() > chance)
{
send_to_char( "You failed the rescue.\n\r", 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 );
if (victim->fighting == fch)
stop_fighting( victim, FALSE );
if ( ch->class == class_lookup("paladin") && is_affected(ch,gsn_heroism))
do_charge(ch,fch->name);
set_fighting( ch, fch );
set_fighting( fch, ch );
}
void kick( CHAR_DATA* ch, CHAR_DATA* victim, int chance ){
int dam = number_range( ch->level/2, 8 * ch->level / 5);
chance += get_curr_stat(ch,STAT_DEX) - get_curr_stat(victim,STAT_DEX);
chance += (ch->level - victim->level);
chance += (get_curr_stat(ch,STAT_LUCK) - get_curr_stat(victim,STAT_LUCK));
if ( number_percent( ) < chance )
{
int chance2 = get_skill(ch,gsn_double_kick);
if (is_affected(victim,gsn_mantis))
{
act("You step out of $n's kick, and deliver one of your own!",ch,NULL,victim,TO_VICT);
act("$N steps out of your kick, and delivers one of $S own!",ch,NULL,victim,TO_CHAR);
act("$N steps out of $n's kick, and delivers one of $S own.",ch,NULL,victim,TO_NOTVICT);
damage(victim,ch,dam/2,gsn_kick,DAM_BASH,TRUE);
affect_strip(victim,gsn_mantis);
return;
}
chance2 += get_curr_stat(ch,STAT_DEX) - get_curr_stat(victim,STAT_DEX);
chance2 += (ch->level - victim->level);
chance2 += (get_curr_stat(ch,STAT_LUCK) - get_curr_stat(victim,STAT_LUCK));
damage(ch,victim,dam,gsn_kick,DAM_BASH,TRUE);
if (ch->fighting == victim && number_percent() < 3*get_skill(ch,gsn_double_kick)/4)
{
if (is_affected(ch,gsn_crane))
chance2 += 20;
if (number_percent() < chance2)
{
chance = 3*((ch->level /2) + (3*get_skill(ch,gsn_double_kick)/4) )/4;
if (ch->class == class_lookup("monk") && number_percent() < chance)
{
if (is_affected(ch,gsn_monkey))
{
send_to_char( "You unleash the technique of Fu Manchu.\n\r", ch );
damage(ch,victim,3*dam/4, gsn_double_kick,DAM_BASH,TRUE);
if (victim->position > POS_RESTING && !is_safe(ch, victim))
damage(ch,victim,2*dam/3, gsn_double_kick,DAM_BASH,TRUE);
if (victim->position > POS_RESTING && !is_safe(ch, victim))
damage(ch,victim,2*dam/3, gsn_double_kick,DAM_BASH,TRUE);
}
else if (is_affected(ch,gsn_tiger))
{
send_to_char("You tear with the claws of the tiger.\n\r", ch);
damage(ch,victim,11*dam/10, gsn_double_kick,DAM_PIERCE,TRUE);
}
else if (is_affected(ch,gsn_buddha))
{
send_to_char("You invoke the essence of the soul.\n\r", ch);
damage(ch,victim,20*dam/10, gsn_double_kick,DAM_MENTAL, TRUE);
}
else if (is_affected(ch,gsn_horse))
{
send_to_char("You kick with the strength of the horse.\n\r",ch);
damage(ch,victim,12*dam/10, gsn_double_kick,DAM_BASH,TRUE);
}
else if (is_affected(ch,gsn_dragon))
{
send_to_char("You summon the spirit of the dragon.\n\r",ch);
damage(ch,victim,2*dam/1, gsn_double_kick,DAM_ENERGY,TRUE);
}
else if (is_affected(ch,gsn_drunken))
{
damage(ch,victim,number_range( 2*dam/3, dam),gsn_double_kick,DAM_BASH,TRUE);
if ( number_percent( ) < 3 * chance / 2 )
{
send_to_char("You stagger into your opponent like a blind drunk.\n\r",ch);
act("$n sweeps your legs with a staggering motion!",ch,NULL,victim,TO_VICT);
act("$n sweeps $N's legs with a staggering motion!",ch,NULL,victim,TO_NOTVICT);
if ((IS_AFFECTED(victim,AFF_FLYING)
&& !is_affected(victim,gsn_thrash))
|| (!IS_NPC(victim) && victim->pcdata->pStallion != NULL && get_skill(victim, gsn_mounted)))
{
act("$S feet aren't on the ground.",ch,NULL,victim,TO_CHAR);
act("Luckily your feet aren't on the ground.",ch,NULL,victim,TO_VICT);
}
else
WAIT_STATE2(victim, UMIN(2,number_range(victim->size,1)) * PULSE_VIOLENCE);
}
}
else
damage(ch,victim,number_range( 2*dam/3, dam),gsn_double_kick,DAM_BASH,TRUE);
}
else
damage(ch,victim,number_range( dam/2, dam), gsn_double_kick,DAM_BASH,TRUE);
check_improve(ch,gsn_double_kick,TRUE,10);
}
else
{
damage( ch, victim, 0, gsn_double_kick,DAM_BASH,TRUE);
check_improve(ch,gsn_double_kick,FALSE,10);
}
}
check_improve(ch,gsn_kick,TRUE,10);
}
else
{
damage( ch, victim, 0, gsn_kick,DAM_BASH,TRUE);
check_improve(ch,gsn_kick,FALSE,10);
}
}
void do_kick( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim = ch->fighting;
int chance;
if ( (chance = get_skill(ch,gsn_kick)) == 0)
{
send_to_char("You better leave the martial arts to fighters.\n\r", ch );
return;
}
if (victim == NULL ){
send_to_char( "You aren't fighting anyone.\n\r", ch );
return;
}
WAIT_STATE2( ch, skill_table[gsn_kick].beats );
kick(ch, victim, chance );
}
bool disarm( CHAR_DATA *ch, CHAR_DATA *victim ){
OBJ_DATA *obj, *wield = get_eq_char(ch, WEAR_WIELD);
int skill = get_skill(victim, gsn_double_grip);
bool fStr = FALSE;
bool fSeize = FALSE;
bool fExoSeize = FALSE;
bool fPGrip = FALSE;
if ( ( obj = get_eq_char( victim, WEAR_WIELD ) ) == NULL
&& ( obj = get_eq_char( victim, WEAR_SECONDARY ) ) == NULL )
return FALSE;
if ( IS_STONED(victim)
|| IS_OBJ_STAT(obj,ITEM_NOREMOVE)
|| is_affected(victim, gsn_graft_weapon)){
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 FALSE;
}
if (obj != NULL
&& (obj->value[0] == WEAPON_POLEARM
|| obj->value[0] == WEAPON_STAFF
|| obj->value[0] == WEAPON_AXE)
&& get_skill(victim, skill_lookup("power grip")) > 1)
skill += 15;
else if (is_affected(victim, gsn_ironarm) && get_eq_char(victim, WEAR_SECONDARY) != NULL){
fStr = TRUE;
skill += 15;
}
if (is_affected(victim, gsn_istrength) && has_twohanded(victim) != NULL){
fStr = TRUE;
skill = 200;
}
if ( (is_affected(victim,gsn_double_grip) || fStr)
&& number_percent() < (4 * skill / 3) - 75) {
act("You fail to disarm $N's weapon from $S powerfull grasp.",ch,NULL,victim,TO_CHAR);
act("$n tries to disarm you, but your grip is too strong.",ch,NULL,victim,TO_VICT);
act("$n tries to disarm $N, but $E grips $S weapon tightly.",ch,NULL,victim,TO_NOTVICT);
check_improve(ch,gsn_disarm, FALSE,1);
check_improve(victim,gsn_double_grip, FALSE, 33);
return FALSE;
}
act( "$n disarms you and sends your weapon flying!", ch, NULL, victim, TO_VICT );
act( "You disarm $N!", ch, NULL, victim, TO_CHAR );
act( "$n disarms $N!", ch, NULL, victim, TO_NOTVICT );
if (check_ccombat_actions( ch, victim, CCOMBAT_DISARM ))
return FALSE;
/* check for power grip (MUST be before obj_from_char) */
if (obj != NULL
&& (obj->value[0] == WEAPON_POLEARM
|| obj->value[0] == WEAPON_STAFF
|| obj->value[0] == WEAPON_AXE)
&& is_affected(victim, gsn_double_grip)
&& get_skill(victim, skill_lookup("power grip")) > 1){
fPGrip = TRUE;
}
obj_from_char( obj );
/* check for advanced disarms */
if ( wield != NULL
&& (wield->value[0] == WEAPON_EXOTIC || wield->value[0] == WEAPON_WHIP)){
int sn = skill_lookup("weapon seize");
if (number_percent() < get_skill(ch, sn)){
check_improve(ch, sn, TRUE, 0);
fSeize = TRUE;
/* check for exotic seize */
if (wield->value[0] == WEAPON_EXOTIC
&& get_skill(ch, gsn_exotic_mastery) > 1)
fExoSeize = TRUE;
}
else
check_improve(ch, sn, FALSE, -99);
}
if (!fExoSeize
&& (IS_OBJ_STAT(obj,ITEM_NODROP)
|| IS_OBJ_STAT(obj,ITEM_INVENTORY)
|| fPGrip) ){
obj_to_char( obj, victim );
}
else if (fSeize){
act("With a flick of $p $n grabs the weapon.", ch, wield, NULL, TO_ROOM);
act("With a flick of $p you grab the weapon.", ch, wield, NULL, TO_CHAR);
obj_to_char( obj, ch );
}
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);
}
return TRUE;
}
void do_disarm( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim;
OBJ_DATA *obj;
OBJ_DATA *obj2;
int chance, hth = 0, ch_weapon, vict_weapon, ch_vict_weapon;
bool fIronArm = TRUE;
if ((chance = get_skill(ch,gsn_disarm)) == 0){
send_to_char( "Huh?\n\r", ch );
return;
}
else if ( (obj = getBmWep( ch, TRUE )) == NULL
&& (obj = getBmWep( ch, FALSE )) == NULL
&& ((hth = get_skill(ch,gsn_hand_to_hand)) == 0
|| (IS_NPC(ch) && !IS_SET(ch->off_flags,OFF_DISARM))) )
{
send_to_char( "You must wield a weapon to disarm.\n\r", ch );
return;
}
else if ( ( victim = ch->fighting ) == NULL ){
send_to_char( "You aren't fighting anyone.\n\r", ch );
return;
}
else if ( ( obj2 = get_eq_char( victim, WEAR_WIELD ) ) == NULL
&& ( obj2 = get_eq_char( victim, WEAR_SECONDARY ) ) == NULL ){
sendf(ch, "%s is not wielding a weapon.\n\r", PERS(victim,ch) );
return;
}
ch_weapon = get_weapon_skill_obj(ch, obj);
vict_weapon = get_weapon_skill_obj(victim, obj2);
ch_vict_weapon = get_weapon_skill_obj(ch, obj2);
if (IS_NPC(victim))
vict_weapon = UMAX(victim->level * 2, 75);
if ( obj == NULL){
if (ch->class == class_lookup("monk"))
chance = chance * hth/100;
else
chance = chance * hth/150;
}
else
chance = chance * ch_weapon/100;
chance += get_weapon_obj_rating( obj, WEAPON_WITHDIS ) * 4;
chance += get_weapon_obj_rating( obj2, WEAPON_TOBEDIS ) * 4;
if (ch->class != gcn_blademaster || !is_affected(ch, gsn_ironarm) || get_eq_char(ch, WEAR_SECONDARY) == NULL){
fIronArm = FALSE;
ch_vict_weapon = 100;
}
chance += (ch_vict_weapon - vict_weapon) / 2;
chance += 2 * (get_curr_stat(ch,STAT_DEX)-get_curr_stat(victim,STAT_STR));
chance += 2*(get_curr_stat(ch,STAT_LUCK) - get_curr_stat(victim,STAT_LUCK));
chance += (ch->level - victim->level);
chance -= get_skill(victim,gsn_parry)/10;
if (IS_NPC(victim))
chance -= victim->level/10;
if (ch->class == class_lookup("monk")
&& is_affected(ch,gsn_dragon)
&& is_empowered(ch,0))
chance += 15;
if (number_percent() < chance
&& (victim->level - ch->level) < 10){
WAIT_STATE2( ch, skill_table[gsn_disarm].beats );
check_improve(ch,gsn_disarm,TRUE,1);
if ( fIronArm){
WAIT_STATE2(victim, PULSE_VIOLENCE );
damage(ch, victim, UMIN(victim->hit, number_range(3, 10)), gsn_ironarm, DAM_INTERNAL, TRUE);
}
disarm( ch, victim );
}
else{
WAIT_STATE2(ch,skill_table[gsn_disarm].beats);
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 shield_disarm( CHAR_DATA *ch, CHAR_DATA *victim )
{
OBJ_DATA *obj;
if ( (obj = get_eq_char( victim, WEAR_SHIELD ) )== NULL)
return;
if ( IS_STONED(victim) || IS_OBJ_STAT(obj,ITEM_NOREMOVE))
{
act("$S shield won't budge!",ch,NULL,victim,TO_CHAR);
act("$n tries to disarm your shield, but it won't budge!",ch,NULL,victim,TO_VICT);
act("$n tries to disarm $N's shield, but fails.",ch,NULL,victim,TO_NOTVICT);
return;
}
act( "$n disarms your shield and it falls to the ground!", ch, NULL, victim, TO_VICT );
act( "You disarm $N's shield!", ch, NULL, victim, TO_CHAR );
act( "$n disarms $N's shield!", ch, NULL, victim, TO_NOTVICT );
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);
}
}
void do_shield_disarm( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim;
OBJ_DATA *obj;
int chance, ch_weapon, hth;
if ((chance = 4 * get_skill(ch,gsn_shield_disarm) / 5) == 0)
{
send_to_char( "You don't know how to disarm shields.\n\r", ch );
return;
}
if ( ( victim = ch->fighting ) == NULL )
{
send_to_char( "You aren't fighting anyone.\n\r", ch );
return;
}
if ( ( obj = get_eq_char( victim, WEAR_SHIELD ) ) == NULL )
{
sendf(ch, "%s is not wearing a shield.\n\r", PERS(victim,ch) );
return;
}
//bonus for bless
if (obj && IS_GOOD(victim) && IS_OBJ_STAT(obj,ITEM_BLESS))
chance -= 15;
else if (obj && IS_EVIL(victim) && IS_OBJ_STAT(obj,ITEM_DARK))
chance -= 15;
hth = get_skill(ch,gsn_hand_to_hand);
ch_weapon = get_weapon_skill_obj(ch, obj);
if (IS_NPC(ch))
chance /= 2;
if ( obj == NULL){
if (ch->class == class_lookup("monk"))
chance = chance * hth/100;
else
chance = chance * hth/150;
}
else
chance = chance * ch_weapon/100;
chance += get_weapon_obj_rating( obj, WEAPON_WITHSDIS ) * 4;
chance += get_curr_stat(ch,STAT_DEX) - get_curr_stat(victim,STAT_STR);
chance += (ch->level - victim->level);
chance -= get_skill(victim,gsn_shield_block)/4;
chance += (get_curr_stat(ch,STAT_LUCK) - get_curr_stat(victim,STAT_LUCK));
if (ch->class == class_lookup("monk") && is_affected(ch,gsn_dragon) && is_empowered(ch,0))
chance += 15;
if (number_percent() < chance)
{
WAIT_STATE2( ch, skill_table[gsn_shield_disarm].beats );
shield_disarm( ch, victim );
check_improve(ch,gsn_shield_disarm,TRUE,1);
}
else
{
WAIT_STATE2(ch,skill_table[gsn_shield_disarm].beats);
act("You fail to disarm $N's shield.",ch,NULL,victim,TO_CHAR);
act("$n tries to disarm your shield, but fails.",ch,NULL,victim,TO_VICT);
act("$n tries to disarm $N's shield, but fails.",ch,NULL,victim,TO_NOTVICT);
check_improve(ch,gsn_shield_disarm,FALSE,1);
}
}
void do_lore( CHAR_DATA *ch, char *argument )
{
char arg[MIL];
OBJ_DATA *obj;
int chance;
int sn = skill_lookup("history of armaments");
int sn2 = skill_lookup("arms maintenance");
bool fExtract = FALSE;
one_argument( argument, arg );
if (ch->fighting != NULL)
{
send_to_char("You're too busy fighting!\n\r",ch);
return;
}
if (arg[0] == '\0')
{
send_to_char("Lore what?\n\r",ch);
return;
}
obj = get_obj_list(ch,arg,ch->carrying);
if (obj== NULL || CAN_WEAR(obj,ITEM_WEAR_TATTOO))
{
send_to_char("You don't have that item.\n\r",ch);
return;
}
if ((chance = get_skill(ch,gsn_lore)) <= 1)
{
send_to_char("It looks like what it appears to be.\n\r",ch);
return;
}
if (ch->mana < 30)
{
send_to_char("You don't have enough mana.\n\r",ch);
return;
}
WAIT_STATE(ch,skill_table[gsn_lore].beats);
ch->mana -= 30;
act("You examine $p closely.",ch,obj,NULL,TO_CHAR);
act("$n examines $p closely.",ch,obj,NULL,TO_ROOM);
if (obj->pIndexData->vnum == OBJ_VNUM_CLONE){
fExtract = TRUE;
obj = create_object( get_obj_index(obj->cost), obj->level);
}
if (obj->item_type == ITEM_ARMOR
&& number_percent() < get_skill(ch, sn)){
send_to_char("You dip into your knowledge of weapons and armor.\n\r", ch);
check_improve(ch, sn, TRUE, 5);
spell_identify(skill_lookup("identify"), ch->level, ch, obj, TARGET_OBJ);
sendf(ch, "Rumor has it that you can find it in %s.\n\r", obj->pIndexData->area->name);
if (fExtract)
extract_obj ( obj );
return;
}
else if (obj->item_type == ITEM_WEAPON
&& number_percent() < get_skill(ch, sn2)){
send_to_char("You dip into your knowledge of weapons.\n\r", ch);
check_improve(ch, sn2, TRUE, 5);
spell_identify(skill_lookup("identify"), ch->level, ch, obj, TARGET_OBJ);
sendf(ch, "Rumor has it that you can find it in %s.\n\r", obj->pIndexData->area->name);
if (fExtract)
extract_obj ( obj );
return;
}
else
check_improve(ch, sn, FALSE, 5);
chance += 25;
chance += 5 * (get_curr_stat(ch,STAT_LUCK) - 14);
if (number_percent() > chance)
{
send_to_char("The meaning of this object escapes you at the moment.\n\r",ch);
if (fExtract)
extract_obj ( obj );
return;
}
chance = get_skill(ch,gsn_lore);
chance += get_curr_stat(ch,STAT_WIS) + get_curr_stat(ch,STAT_INT) - 40;
chance += UMAX(0, (ch->level - obj->level) / 2);
chance = UMAX(0, 110 - chance);
chance = number_range(-chance, chance);
if (ch->class == class_lookup("bard"))
chance = 0;
sendf( ch,"Object is type %s, material %s.\n\rWeight is %d, value is %d, level is %d.\n\r",
item_name(obj->item_type),
obj->material,
obj->weight / 10 + (obj->weight * chance / 1000),
obj->cost + (obj->cost * chance / 100),
obj->level + (obj->level * chance / 100));
switch ( obj->item_type )
{
case ITEM_SOCKET:
if (IS_SOC_STAT(obj, SOCKET_ARMOR)
&& IS_SOC_STAT(obj, SOCKET_WEAPON))
act("Armor and Weapon socket.",
ch, obj, NULL, TO_CHAR);
else if (IS_SOC_STAT(obj, SOCKET_ARMOR))
act("Armor only socket.",
ch, obj, NULL, TO_CHAR);
else if (IS_SOC_STAT(obj, SOCKET_WEAPON))
act("Weapon only socket.",
ch, obj, NULL, TO_CHAR);
else
act("Weapon only socket.",
ch, obj, NULL, TO_CHAR);
break;
case ITEM_DRINK_CON:
sendf(ch,"It holds %s-colored %s.\n\r",
liq_table[obj->value[2]].liq_color,
liq_table[obj->value[2]].liq_name);
break;
case ITEM_CONTAINER:
sendf(ch,"Capacity: %d# Maximum weight: %d#\n\r",
obj->value[3] + (obj->value[3] * chance/100),
obj->value[0] + (obj->value[0] * chance/100));
break;
case ITEM_WEAPON:
send_to_char("Weapon type is ",ch);
if (IS_WEAPON_STAT(obj, WEAPON_TWO_HANDS)
|| obj->value[0] == WEAPON_STAFF)
send_to_char("two-handed ", ch);
switch (obj->value[0])
{
case(WEAPON_EXOTIC) : send_to_char("exotic.\n\r",ch); break;
case(WEAPON_SWORD) : send_to_char("sword.\n\r",ch); break;
case(WEAPON_DAGGER) : send_to_char("dagger.\n\r",ch); break;
case(WEAPON_SPEAR) : send_to_char("spear.\n\r",ch); break;
case(WEAPON_STAFF) : send_to_char("staff.\n\r",ch); break;
case(WEAPON_MACE) : send_to_char("mace/club.\n\r",ch); break;
case(WEAPON_AXE) : send_to_char("axe.\n\r",ch); break;
case(WEAPON_FLAIL) : send_to_char("flail.\n\r",ch); break;
case(WEAPON_WHIP) : send_to_char("whip.\n\r",ch); break;
case(WEAPON_POLEARM): send_to_char("polearm.\n\r",ch); break;
default : send_to_char("unknown.\n\r",ch); break;
}
if (obj->pIndexData->new_format)
sendf(ch,"Average damage is %d.\n\r",
(1 + obj->value[2])* obj->value[1]/ 2 +(1 + obj->value[2]) * (obj->value[1]/ 2) * chance / 100);
else
sendf( ch, "Average damage is %d.\n\r",
(obj->value[1] + (obj->value[2]) / 2) +
(obj->value[1] + (obj->value[2]) / 2) * chance/100);
if ( IS_OBJ_STAT(obj, ITEM_SOCKETABLE))
{
if (obj->contains){
act( "$p has the following affixed to it:", ch, obj, NULL, TO_CHAR );
show_list_to_char( obj->contains, ch, TRUE, TRUE );
}
else
act( "$p seems to have a space to attach something to it.", ch, obj, NULL, TO_CHAR );
}
break;
case ITEM_ARMOR:
sendf( ch, "Armor class is %d pierce, %d bash, %d slash, and %d vs. magic.\n\r",
obj->value[0] + obj->value[0] * chance/100,
obj->value[1] + obj->value[1] * chance/100,
obj->value[2] + obj->value[2] * chance/100,
obj->value[3] + obj->value[3] * chance/100);
if ( IS_OBJ_STAT(obj, ITEM_SOCKETABLE))
{
if (obj->contains){
act( "$p has the following affixed to it:", ch, obj, NULL, TO_CHAR );
show_list_to_char( obj->contains, ch, TRUE, TRUE );
}
else
act( "$p seems to have a space to attach something to it.", ch, obj, NULL, TO_CHAR );
}
break;
case ITEM_PROJECTILE:
sendf(ch, "Is a projectile of type %s\n\r",
flag_string(projectile_type, obj->value[0]));
if (obj->pIndexData->new_format)
sendf(ch,"Average damage is %d.\n\r",
(1 + obj->value[2])* obj->value[1]/ 2 +(1 + obj->value[2]) * (obj->value[1]/ 2) * chance / 100);
else
sendf( ch, "Average damage is %d.\n\r",
(obj->value[1] + (obj->value[2]) / 2) +
(obj->value[1] + (obj->value[2]) / 2) * chance/100);
break;
case ITEM_RANGED:
if (obj->value[3] == 0)
sendf(ch, "Can be used to fire: %s.\n\r",
flag_string(projectile_type, obj->value[0]));
else{
OBJ_INDEX_DATA* ammo = get_obj_index( obj->value[3] );
sendf(ch, "Can be used to fire: %s.\n\r",
ammo == NULL ? "NOT FOUND" : ammo->short_descr);
}
sendf(ch, "Has capacity of: %d, and rate of fire: %d\n\r",
chance * obj->value[1] / 100, chance * obj->value[2] / 100);
break;
}
if (obj->pCabal || obj->race || obj->class >= 0){
sendf(ch, "You have a feeling only a %s%s%s%s%s%scan use it.\n\r",
obj->race ? race_table[obj->race].name : "",
obj->race ? " " : "",
obj->class >= 0 ? class_table[obj->class].name : "",
obj->class >= 0 ? " ": "",
obj->pCabal ? obj->pCabal->name : "",
obj->pCabal ? " ": "");
}
if (CAN_WEAR(obj, ITEM_UNIQUE))
send_to_char("Unique item.\n\r",ch);
if (CAN_WEAR(obj, ITEM_RARE))
send_to_char("Rare item.\n\r",ch);
if (CAN_WEAR(obj, ITEM_PARRY))
send_to_char("Can be dual parried.\n\r",ch);
sendf(ch, "Rumor has it that you can find it in %s.\n\r", obj->pIndexData->area->name);
check_improve(ch,gsn_lore,TRUE,1);
if (fExtract)
extract_obj ( obj );
}
void do_lay_on_hands(CHAR_DATA *ch, char *argument)
{
CHAR_DATA *victim;
char arg[MIL];
sh_int chance;
AFFECT_DATA af;
const int cost = ch->class == class_lookup("crusader") ? 100 : 50;
one_argument (argument, arg);
if ((chance = get_skill (ch, gsn_lay_on_hands)) == 0)
{
send_to_char("You do not know the secrets of this skill.\n\r", ch);
return;
}
if (is_affected(ch,gsn_lay_on_hands))
{
send_to_char("You can't sustain another lay on hands at this time.\n\r",ch);
return;
}
victim = get_char_room(ch, NULL, arg);
if ( victim == NULL )
{
send_to_char("They aren't here.\n\r", ch);
return;
}
if ( victim == ch )
{
send_to_char("You can't lay on hands yourself.\n\r",ch);
return;
}
if (ch->mana < cost)
{
send_to_char("You don't have enough mana to perform a lay on hands.\n\r",ch);
return;
}
if (number_percent() > chance)
{
act("Something disturbs your concentration and you fail the lay on hands.", ch,NULL,NULL,TO_CHAR);
act("$n's hands glow with a soft light, but it fades suddenly.",ch,NULL,NULL,TO_ROOM);
ch->mana -= 25;
check_improve(ch,gsn_lay_on_hands,FALSE,1);
}
else
{
if (ch->class == class_lookup("crusader")){
act("You chant an ancient psalm as you press your hands against $N's back.",ch,NULL,victim,TO_CHAR);
act("$n chants an ancient psalm as $e presses $s hands against $N's back.",ch,NULL,victim,TO_NOTVICT);
act("$n chants an ancient psalm as $e presses $s hands against your back.",ch,NULL,victim,TO_VICT);
}
else{
act("Your hands glow with a soft light as you place them on $N's wounds.",ch,NULL,victim,TO_CHAR);
act("$n's hands glow with a soft light as $e places them on your wounds.",ch,NULL,victim,TO_VICT);
act("$n's hands glow with a soft light as $e places them on $N's wounds.",ch,NULL,victim,TO_NOTVICT);
}
ch->mana -= cost;
//Embrace check.
if (is_affected(victim, gsn_embrace_poison))
{
if (embrace_heal_check(gsn_lay_on_hands, ch->level, ch, victim, 0))
affect_strip(victim, gsn_embrace_poison);
}
else
{
int gain = victim->max_hit - victim->hit;
gain = ch->level * 2 + number_range(gain / 4, gain / 2);
gain = UMIN(gain, ch->level * 10);
victim->hit = UMIN(victim->max_hit, victim->hit + gain );
check_dispel( -99, victim, gsn_blindness);
check_dispel( -99, victim, gsn_death_grasp);
check_dispel( -99, victim, gsn_poison);
check_dispel( -99, victim, gsn_plague);
check_dispel( -99, victim, skill_lookup("dysentery"));
check_dispel( -99, victim, gsn_curse);
update_pos( victim );
}//end embrace check
check_improve(ch,gsn_lay_on_hands,TRUE,1);
}
af.type = gsn_lay_on_hands;
af.level = ch->level;
if (IS_NPC(ch))
af.duration = 1;
else
af.duration = ch->class == class_lookup("crusader") ? 12 : 24;
af.location = 0;
af.modifier = 0;
af.bitvector = 0;
affect_to_char(ch,&af);
if (!IS_NPC(ch))
{
ch->pcdata->condition[COND_HUNGER] = 5;
ch->pcdata->condition[COND_THIRST] = 5;
}
WAIT_STATE2(ch,skill_table[gsn_lay_on_hands].beats);
}
void do_detect_hidden( CHAR_DATA *ch, char *argument )
{
int chance;
AFFECT_DATA af;
if ( (chance = get_skill(ch,gsn_detect_hidden)) == 0 )
{
send_to_char("Huh?\n\r",ch);
return;
}
if (ch->mana < 10)
{
send_to_char("You don't have enough mana.\n\r",ch);
return;
}
if ( IS_AFFECTED(ch, AFF_DETECT_HIDDEN) )
{
send_to_char("You are already as alert as you can be. \n\r",ch);
return;
}
WAIT_STATE2(ch,skill_table[gsn_detect_hidden].beats);
if (number_percent() > chance)
{
ch->mana -= 5;
send_to_char("You peer around intently, but the shadows seem unrevealing.\n\r",ch);
check_improve(ch,gsn_detect_hidden,FALSE,1);
return;
}
ch->mana -= 10;
af.where = TO_AFFECTS;
af.type = gsn_detect_hidden;
af.level = ch->level;
af.duration = ch->level;
af.location = 0;
af.modifier = 0;
af.bitvector = AFF_DETECT_HIDDEN;
affect_to_char( ch, &af );
send_to_char( "Your awareness improves.\n\r", ch );
check_improve(ch,gsn_detect_hidden,TRUE,1);
}
void do_cleave( CHAR_DATA *ch, char *argument )
{
char arg[MIL], buf[MSL];
CHAR_DATA *victim;
OBJ_DATA *obj;
int chance, success;
one_argument( argument, arg );
if ((chance = get_skill(ch,gsn_cleave)) == 0)
{
send_to_char("You don't know how to cleave.\n\r",ch);
return;
}
if (ch->fighting != NULL)
{
send_to_char("Not while you're fighting.\n\r",ch);
return;
}
if (arg[0] == '\0')
{
send_to_char("Who do you wish to cleave?\n\r",ch);
return;
}
if ((victim = get_char_room(ch, NULL, arg)) == NULL)
{
send_to_char("They aren't here.\n\r",ch);
return;
}
if (victim->fighting != NULL)
{
sendf(ch, "%s won't hold still long enough.\n\r", PERS(victim,ch));
return;
}
if (IS_NPC(victim) && IS_SET(victim->act, ACT_TOO_BIG) )
{
sendf(ch, "%s is too alert for you to attempt such an act.\n\r", PERS(victim,ch));
return;
}
if ( victim == ch )
return;
if ( is_safe( ch, victim ) )
return;
if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim )
{
sendf(ch, "%s is your beloved master.\n\r", PERS(victim,ch) );
return;
}
obj = get_eq_char( ch, WEAR_WIELD );
if (obj == 0 || (obj->value[0] != WEAPON_SWORD
&& obj->value[0] != WEAPON_AXE
&& obj->value[0] != WEAPON_POLEARM))
{
send_to_char( "How do you expect to cleave with that weapon.\n\r", ch );
return;
}
if (IS_AFFECTED(ch, AFF_SLOW) && !IS_AFFECTED(ch, AFF_HASTE))
{
send_to_char("You can't seem to get up enough speed.\n\r",ch);
return;
}
chance -= get_curr_stat(victim,STAT_DEX)+get_curr_stat(ch,STAT_INT)/2;
chance -= get_curr_stat(victim,STAT_DEX)+get_curr_stat(ch,STAT_WIS)/2;
if (IS_AFFECTED(ch,AFF_HASTE))
chance += 10;
if (IS_SET(victim->off_flags,OFF_FAST) || IS_AFFECTED(victim,AFF_HASTE))
chance -= 10;
chance += (ch->level - victim->level);
//smaller people are easier to cleave
chance += affect_by_size(ch,victim);
chance += get_curr_stat(ch,STAT_LUCK) - get_curr_stat(victim,STAT_LUCK);
success = number_percent( );
//now little bonuses for type of weapon.
if ( (IS_WEAPON_STAT(obj,WEAPON_TWO_HANDS))
|| is_affected(ch,gsn_double_grip) )
success -= 3;
if (obj->value[3] == WEAPON_AXE)
success -= 2;
else if (obj->value[3] == WEAPON_POLEARM)
success -= 5;
if (get_curr_stat(victim, STAT_CON) < 19)
success -= 2;
if ( (ch->alignment > GOOD_THRESH)
&& (IS_OBJ_STAT(obj,ITEM_BLESS)) )
success -=1;
else if ( (ch->alignment < EVIL_THRESH)
&& (IS_OBJ_STAT(obj,ITEM_EVIL)) )
success -=1;
WAIT_STATE2( ch, skill_table[gsn_cleave].beats );
a_yell(ch,victim);
//predict interdict
if (predictCheck(ch, victim, "cleave", skill_table[gsn_cleave].name))
return;
if (is_affected(victim, gsn_cleave)){
sendf(ch, "%s is hurt and suspicious ... you can't sneak up.\n\r", PERS(victim,ch));
success = 999;
}
else{
AFFECT_DATA af;
af.type = gsn_cleave;
af.duration = 3;
af.level = ch->level;
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 0;
affect_to_char(victim, &af);
}
if ( (success < 10 || (IS_IMMORTAL(ch) && ch->wimpy == 69) )
&& !IS_IMMORTAL(victim)
&& IS_AWAKE( victim )
&& !IS_UNDEAD( victim )
&& !is_affected(victim, gsn_mist_form))
{
int dam_type = attack_table[obj->value[3]].damage;
int dam = 3 * ch->level + 3 * UMAX(0, get_skill(ch, gsn_cleave) - 75);
sprintf(buf, "Die! %s, you butchering fool!",PERS(ch,victim));
j_yell(victim,buf);
check_improve(ch,gsn_cleave,TRUE,1);
/* counter */
if (counter_check(ch, victim, get_skill(victim, gsn_counter), dam, dam_type, gsn_cleave)){
return;
}
damage( ch, victim, dam, gsn_cleave,dam_type,TRUE);
if (victim && !is_safe_quiet( ch, victim )){
AFFECT_DATA af;
act("Unable to withstand the shock $n crumples to the ground.", victim, NULL, NULL, TO_ROOM );
act("Unable to withstand the shock you crumple to the ground.", victim, NULL, NULL, TO_CHAR );
act("Your blow has knocked $N unconscious!", ch, NULL, victim, TO_CHAR );
stop_fighting( victim, TRUE);
af.where = TO_AFFECTS;
af.type = gsn_sleep;
af.level = ch->level;
af.duration = 1;
af.location = APPLY_NONE;
af.modifier = 0;
af.bitvector = AFF_SLEEP;
affect_to_char( victim, &af );
do_sleep(victim,"");
}
return;
}
if ( success < chance || !IS_AWAKE(victim) )
{
int dam_type = attack_table[obj->value[3]].damage;
int dam = 3 * ch->level + 3 * UMAX(0, get_skill(ch, gsn_cleave) - 75);
dam += (success < 50 ? ch->level : 0);
sprintf(buf, "Die! %s, you butchering fool!",PERS(ch,victim));
j_yell(victim,buf);
check_improve(ch,gsn_cleave,TRUE,1);
/* counter */
if ( !counter_check(ch, victim, get_skill(victim, gsn_counter), dam, dam_type, gsn_cleave)){
damage( ch, victim, dam, gsn_cleave,dam_type,TRUE);
}
}
else
{
sprintf(buf, "Die! %s, you butchering fool!",PERS(ch,victim));
j_yell(victim,buf);
check_improve(ch,gsn_cleave,FALSE,1);
multi_hit( ch, victim,obj->value[3]+TYPE_HIT);
}
}
void do_assassinate( CHAR_DATA *ch, char *argument )
{
/* Assassinate skill */
/*
The skill uses the study skill as a requirement for a successful
attack.
if no weapon return.
if modifier is <= 5 then assasinate fails automaticly.
each attempt on current studied target decrements
chance to 5%.
The gen_study stores the amount learned about target in "modifier".
- modifier has ceiling of 60.
*/
char arg[MIL], buf[MSL];
CHAR_DATA *victim;
CHAR_DATA* och, *och_next;
AFFECT_DATA* paf = NULL;
OBJ_DATA *obj;
//data
int base_chance = 0;
int chance = 0;
int weapon_skill = 0;
int ass_skill = 0;
//const
const int haste_mod = 30; //bonus percent for haste.
const int level_mod = 3; //multiplier for the lvl difference.
const int dex_med = 18; //median for dexterity of attacker
const int dex_mod = 1; //multiplier for dex.
const int size_mod = 5; //size multiplier.
const int luck_mod = 1; //luck multipler
const int luck_med = 14; //luck median
const float sleep_mod = 1.3;//mulitplier for sleeping
const float see_mod = 1.3; //multiplier for not seeing attacker if not sleeping.
const float group_mod = 1.4; //bonus for being part of same group.
const int weapon_med = 90; //median past which we get bonus for weapon skill
const int dodge_mod = 10; //divisor for target dodge penalty.
const int fight_mod = 75;//multiplier for chance if target incombat.
//flags
bool fNpc = FALSE;
bool fAutoFail = FALSE;
bool fKiss = get_skill(ch, gsn_death_kiss) > 1;
//get our argument.
one_argument( argument, arg );
//check for skill
if ((ass_skill = get_skill(ch,gsn_assassinate)) == 0)
{
send_to_char("You can't expect to assassinate someone without proper training.\n\r",ch);
return;
}
//check argument.
if (arg[0] == '\0')
{
if(is_affected(ch, gen_study))
sendf(ch, "%s\n\r", study_info(ch, FALSE, NULL));
send_to_char("Attempt to assassinate who?\n\r",ch);
return;
}
//look for target.
if ((victim = get_char_room(ch, NULL, arg)) == NULL)
{
send_to_char("They aren't here.\n\r",ch);
return;
}
//too big check
if ((fNpc = IS_NPC(victim)) && IS_SET(victim->act, ACT_TOO_BIG) )
{
sendf(ch, "%s is too alert for you to attempt such an act.\n\r", PERS(victim,ch));
return;
}
if ( victim == ch )
{
send_to_char("Self mutilation is frowned upon by the gods\n\r", ch);
return;
}
//check weapon
if ( ( obj = get_eq_char( ch, WEAR_WIELD ) ) == NULL)
{
send_to_char("You need a weapon first.\n\r", ch);
return;
}
//now we know if we are safe to try to attack.
if ( is_safe( ch, victim ) )
return;
if (IS_AFFECTED(ch, AFF_SLOW) && !IS_AFFECTED(ch, AFF_HASTE))
{
send_to_char("You can't seem to get up enough speed.\n\r",ch);
return;
}
//watchtower check
if (is_affected(victim, gen_watchtower)){
sendf( ch, "%s is shielded within the Watchtower.\n\r", PERS(victim, ch ));
fAutoFail = TRUE;
}
//check if studied at all. (PC only)
if (!fNpc)
{
if ( (paf = affect_find(ch->affected , gen_study)) == NULL)
{
send_to_char("Without preparation you are bound to fail.\n\r", ch);
fAutoFail = TRUE;
}
else if (strcmp(paf->string, victim->name))
{
//if studied check if this is the studied target.
sendf(ch, "You have studied %s and know nothing of use about %s.\n\r", paf->string, victim->name);
fAutoFail = TRUE;
}
else if ( (base_chance = paf->modifier) <= 5)
//check if study is at 5 or less
fAutoFail = TRUE;
}//end if PC
//------------------CHANCE CALCULATION---//
if (fNpc && !fAutoFail)//NPC
{
if (victim->level > ch->level) fAutoFail = TRUE;
else
chance = UMAX(0, (ass_skill - 80) + ((ch->level - victim->level) * 3));
}//end NPC chance
else if (!fAutoFail)//PC
{
//Begin calculating chances. (multipliers first then bonuses)
chance = base_chance;
//we set the chance depending on the ass_skill
if (ass_skill < 50) chance = 10 * chance / 100;
else if (ass_skill < 60) chance = 10 * chance / 100;
else if (ass_skill < 70) chance = 20 * chance / 100;
else if (ass_skill < 75) chance = 35 * chance / 100;
else if (ass_skill < 80) chance = 55 * chance / 100;
else if (ass_skill < 85) chance = 70 * chance / 100;
else if (ass_skill < 90) chance = 85 * chance / 100;
else if (ass_skill < 95) chance = 95 * chance / 100;
else if (ass_skill < 99) chance = 100 * chance / 100;
else if (ass_skill >= 100) chance = 105 * chance / 100;
//sendf(ch,"Chance after first mod: %d\n\r", chance);
//sleeping
if (!IS_AWAKE(victim))
chance *= sleep_mod;
else
//seeing
if (!can_see(victim, ch))
chance *= see_mod;
//sendf(ch,"Chance after 2 mod: %d\n\r", chance);
//group
if (is_same_group(ch, victim))
chance *= group_mod;
//sendf(ch,"Chance after 3 mod: %d\n\r", chance);
//Penalty for in combat (more aware)
if (victim->fighting != NULL)
chance = chance * fight_mod / 100;
//sendf(ch,"Chance after 4 mod: %d\n\r", chance);
//weapon
weapon_skill = get_weapon_skill_obj(ch, obj);
chance = chance * weapon_skill / weapon_med;
//sendf(ch,"Chance after 5 mod: %d\n\r", chance);
//Haste
if (IS_AFFECTED(ch, AFF_HASTE))
chance += haste_mod;
//sendf(ch,"Chance after 6 mod: %d\n\r", chance);
//--------END MULTIPLIERS BEGIN BONUSES-------//
//Level
chance += (ch->level - victim->level) * level_mod;
//sendf(ch,"Chance after 7 mod: %d\n\r", chance);
//Dex
chance += (get_curr_stat(ch, STAT_DEX) - dex_med) * dex_mod;
//sendf(ch,"Chance after 8 mod: %d\n\r", chance);
//size (large victim is harder to assassinae)
chance += affect_by_size(ch,victim) * size_mod;
//sendf(ch,"Chance after 9 mod: %d\n\r", chance);
////luck
chance += (get_curr_stat(ch,STAT_LUCK) - luck_med) * luck_mod;
//sendf(ch,"Chance after 10 mod: %d\n\r", chance);
//dodge
chance -= get_skill(victim, gsn_dodge) / dodge_mod;
//sendf(ch,"Chance after 11 mod: %d\n\r", chance);
//hitroll
if ( GET_HITROLL( ch ) < 30 ){
chance = GET_HITROLL( ch ) * chance / 35;
}
//Now we floor the chance.
chance = URANGE(5, chance, 95);
//sendf(ch,"Chance after floor mod: %d\n\r", chance);
}//END PC CHANCE
//Waitstate
WAIT_STATE2( ch, skill_table[gsn_assassinate].beats );
a_yell(ch,victim);
//predict interdict
if (predictCheck(ch, victim, "assassinate", skill_table[gsn_assassinate].name))
return;
//Calculate the hit
//DEBUG
// sendf(ch, "study: %d, chance: %d, NPC? %d, aF: %d.\n\r", base_chance, chance, fNpc, fAutoFail);
//------ASSASSINATE---//
if ((number_percent() < chance) && !IS_IMMORTAL(victim) && !fAutoFail)
{
//MANTIS CHECK
if (is_affected(victim,gsn_mantis))
{
act("You sense $n's movement and throw $m to the ground!",ch,NULL,victim,TO_VICT);
act("$N senses your attack, and throws you to the ground!",ch,NULL,victim,TO_CHAR);
act("$N senses $n's attack, and throws $m to the ground.",ch,NULL,victim,TO_NOTVICT);
WAIT_STATE2(ch, URANGE(2, 1 + number_range(1, victim->size), 4) * PULSE_VIOLENCE);
do_visible(ch, "");
sprintf(buf, "Help! %s tried to assassinate me!",PERS(ch,victim));
j_yell(victim,buf);
affect_strip(victim,gsn_mantis);
damage(victim,ch,10,gsn_mantis,DAM_BASH,TRUE);
return;
}//END MATIS
/* undead check */
if (!IS_NPC(victim) && IS_UNDEAD( victim ) ){
for ( och = victim->in_room->people; och != NULL; och = och_next ){
och_next = och->next_in_room;
if ( IS_NPC(och) && IS_UNDEAD(och)
&& IS_AFFECTED(och, AFF_CHARM)
&& och->master == victim){
act("$n calmly steps into harms way.", och, NULL, NULL, TO_ROOM);
check_social(och, "snarl", "");
victim = och;
break;
}
}
}
/* justice check */
else if (!IS_NPC(victim)
&& IS_SET(victim->in_room->area->area_flags,AREA_LAWFUL)
&& victim->pCabal
&& IS_CABAL(victim->pCabal, CABAL_JUSTICE)){
for ( och = victim->in_room->people; och != NULL; och = och_next ){
och_next = och->next_in_room;
if ( IS_NPC(och) && och->pIndexData->vnum == MOB_VNUM_SPECIAL_GUARD
&& IS_AFFECTED(och, AFF_CHARM)
&& och->master == victim){
act("$n's eyes gleam with fanatic loyalty as $e throws $mself into harms way!", och, NULL, NULL, TO_ROOM);
REMOVE_BIT(och->comm,COMM_NOCHANNELS);
REMOVE_BIT(och->comm,COMM_NOYELL);
do_yell(och, "For Glory of Law I lay down my life!");
SET_BIT(och->comm,COMM_NOYELL);
SET_BIT(och->comm,COMM_NOCHANNELS);
victim = och;
break;
}
}
}
check_improve(ch,gsn_assassinate,TRUE,1);
//use up the study
if (paf != NULL)
paf->modifier = 1 * paf->modifier / 6;
act("With lethal speed, you strike from the shadows and `1+++ ASSASSINATE +++`` $N!",ch,NULL,victim,TO_CHAR);
sprintf(buf,"With lethal speed, %s strikes from the shadows and `1+++ ASSASSINATES +++`` you!\n\r",PERS(ch,victim));
send_to_char(buf,victim);
act("$n moves with lethal speed, and `1+++ ASSASSINATES +++`` $N!",ch,NULL,victim,TO_NOTVICT);
if (!IS_NPC(ch) && ch->pcdata->alias[0] && !can_see(victim, ch))
act_new("The last thing you see is $t.\n\r", ch, ch->pcdata->alias, victim, TO_VICT, POS_DEAD);
if ( !IS_NPC(victim)
&& victim->pcdata->pbounty
&& !is_affected(victim, gsn_mortally_wounded)
&& can_collect(victim->pcdata->pbounty, ch )){
act( "$n is mortally wounded!!", victim, NULL, NULL, TO_ROOM);
act_new( "You have been mortally wounded!!", victim, NULL, NULL, TO_CHAR, POS_DEAD );
mercy_effect(ch, victim, 4);
}
else
{
act( "$n is DEAD!!", victim, 0, 0, TO_ROOM );
// send_to_char( "You have been ASSASSINATED!!\n\r\n\r", victim );
raw_kill(ch, victim);
}
do_autos(ch);
victim->hit = 1;
victim->mana = 1;
return;
}//end success.
else
{
check_improve(ch,gsn_assassinate,FALSE,1);
if (paf != NULL)
paf->modifier = 3 * paf->modifier / 5;
if (fKiss){
send_to_char("Noticing an error in your studies you pull back to reconsider.\n\r", ch);
return;
}
do_visible(ch, "");
sprintf(buf, "Help! %s tried to assassinate me!",PERS(ch,victim));
j_yell(victim,buf);
multi_hit( ch, victim, obj->value[3]+TYPE_HIT);
}//end fail.
}//END ASSASIANTE
void do_bodyslam( CHAR_DATA *ch, char *argument )
{
char arg[MIL], buf[MSL];
CHAR_DATA *victim;
//Data
int chance = 4 * get_skill(ch,gsn_bodyslam) / 5;
int dam = number_range(10 + ch->level/2, ch->size * ch->level / 2);
int vic_lag = PULSE_VIOLENCE;
int ch_lag = skill_table[gsn_bash].beats;
//bools
bool fSuccess = FALSE;
bool fYell = FALSE;
one_argument(argument,arg);
if ( chance == 0)
{
send_to_char("You don't want to abuse your body like that.\n\r",ch);
return;
}
if (arg[0] == '\0')
{
if ((victim = ch->fighting) == NULL)
{
send_to_char("But you aren't fighting anyone!\n\r",ch);
return;
}
}
else if ((victim = get_char_room(ch, NULL, arg)) == NULL)
{
send_to_char("They aren't here.\n\r",ch);
return;
}
if ( victim == ch )
{
send_to_char("Self mutilation is not your style.\n\r",ch);
return;
}
if (is_safe(ch,victim))
return;
//Get chance to bash.
chance += get_curr_stat(ch,STAT_STR) - get_curr_stat(victim,STAT_DEX);
chance += GET_AC2(victim,AC_BASH) /25;
chance -= get_skill(victim,gsn_dodge)/20;
chance += (ch->level - victim->level);
chance += get_curr_stat(ch,STAT_LUCK) - get_curr_stat(victim,STAT_LUCK);
if (IS_AFFECTED2(ch, AFF_RAGE))
chance += 5;
if ( victim->race == race_lookup("avian")
|| victim->race == race_lookup("faerie") )
chance -=10;
if (is_affected(victim,gsn_horse))
chance -= 5;
if (!IS_NPC(victim) && victim->pcdata->pStallion && number_percent() < get_skill(victim, gsn_mounted)){
chance -= 12;
check_improve(victim, gsn_mounted, TRUE, 0);
}
chance += affect_by_size(ch,victim);
//check if target should yell.
fYell = (ch->fighting != victim && victim->fighting != ch);
//sound attack to justice /imm
a_yell(ch,victim);
//predict interdict
if (predictCheck(ch, victim, "bodyslam", skill_table[gsn_bodyslam].name))
return;
if (number_percent() < chance)
{
fSuccess = TRUE;
vic_lag = URANGE(1, number_range(2, ch->size - victim->size + 3), 4) * PULSE_VIOLENCE;
}
else
{
dam = 0;
}
//MANTIS CHECK
if (is_affected(victim,gsn_mantis) && fSuccess)
{
act("You use $n's momentum against him, and throw $m to the ground!",ch,NULL,victim,TO_VICT);
act("$N reverses your attack, and throws you to the ground!",ch,NULL,victim,TO_CHAR);
act("$N reversed $n's attack, and throws $m to the ground.",ch,NULL,victim,TO_NOTVICT);
WAIT_STATE2(ch, URANGE(1, number_range(1, victim->size), 3) * PULSE_VIOLENCE);
damage(victim,ch,dam,gsn_mantis,DAM_BASH,TRUE);
affect_strip(victim,gsn_mantis);
return;
}//END MATIS
//check for lag protect
if (!do_lagprot(ch, victim, chance, &dam, &vic_lag, gsn_bodyslam, fSuccess, fYell))
{
if (fYell)
{
sprintf(buf, "Help! %s just bodyslammed into me!",PERS(ch,victim));
j_yell(victim,buf);
}
if (fSuccess)
{
act("$n knocks you senseless with a full on bodyslam!",ch,NULL,victim,TO_VICT);
act("You slam into $N, knocking $M senseless!",ch,NULL,victim,TO_CHAR);
act("$n knocks $N senseless with a full on bodyslam.",ch,NULL,victim,TO_NOTVICT);
}
else
{
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 bodyslam, causing $m to fall flat on $s face.",ch,NULL,victim,TO_VICT);
}
}//END IF NO PROTECTION
if (!fSuccess || dam == 0 || vic_lag == 0)
{
check_improve(ch,gsn_bodyslam,FALSE,1);
ch_lag = 3 * ch_lag / 2;
}
else
check_improve(ch,gsn_bodyslam,TRUE,1);
WAIT_STATE2(ch, ch_lag);
if (vic_lag != 0 && dam != 0)
WAIT_STATE2(victim, vic_lag);
if (ch->race == race_lookup("fire") && number_percent() < 3 * ch->level / 2)
damage(ch,victim,3 * dam / 2, gsn_bodyslam, DAM_FIRE,TRUE);
else
damage(ch,victim,dam,gsn_bodyslam,DAM_BASH,TRUE);
if (ch && victim && ch->fighting == victim && dam > 0)
check_ccombat_actions( victim, ch, CCOMBAT_BASHED);
}
void do_grapple( CHAR_DATA *ch, char *argument )
{
char arg[MIL], buf[MSL];
CHAR_DATA *victim;
//Data
int chance = 3 * get_skill(ch,gsn_grapple) / 4;
int dam = get_curr_stat(ch,STAT_STR) + ch->level;
int vic_lag = PULSE_VIOLENCE;
int ch_lag = skill_table[gsn_bash].beats;
//bools
bool fSuccess = FALSE;
bool fYell = FALSE;
one_argument(argument,arg);
if (chance == 0)
{
send_to_char("You don't know how to grapple.\n\r",ch);
return;
}
if ((victim = ch->fighting) == NULL)
{
send_to_char("But you aren't fighting anyone!\n\r",ch);
return;
}
if (is_safe(ch,victim))
return;
//Get chance to grapple
chance += (get_curr_stat(ch,STAT_STR) - get_curr_stat(victim, STAT_STR)) *2;
chance += (get_curr_stat(ch,STAT_DEX) - get_curr_stat(victim,STAT_DEX)) *2;
chance -= get_skill(victim,gsn_dodge)/5;
chance += (ch->level - victim->level);
if (is_affected(victim,gsn_horse))
chance -= 5;
if ( victim->race == race_lookup("avian") )
chance -=10;
if (!IS_NPC(victim) && victim->pcdata->pStallion && number_percent() < get_skill(victim, gsn_mounted)){
chance -= 12;
check_improve(victim, gsn_mounted, TRUE, 0);
}
// bigger people are easier to throw hence - not + affect_by_size
chance -= affect_by_size(ch,victim);
chance += get_curr_stat(ch,STAT_LUCK) - get_curr_stat(victim,STAT_LUCK);
//check if target should yell.
fYell = (ch->fighting != victim && victim->fighting != ch);
//sound attack to justice /imm
a_yell(ch,victim);
if (number_percent() < chance)
{
fSuccess = TRUE;
vic_lag = URANGE(1, number_range(1, victim->size), 3)
* PULSE_VIOLENCE;
}
else
{
dam = 0;
}
//MANTIS CHECK
if (is_affected(victim,gsn_mantis) && fSuccess)
{
act("You reversed $n's grapple, and throw $m to the ground!",ch,NULL,victim,TO_VICT);
act("$N reverses your grapple, and throws you to the ground!",ch,NULL,victim,TO_CHAR);
act("$N reversed $n's grapple, and throws $m to the ground.",ch,NULL,victim,TO_NOTVICT);
WAIT_STATE2(ch, URANGE(1, number_range(1, victim->size), 3) * PULSE_VIOLENCE);
damage(victim,ch,(get_curr_stat(victim,STAT_STR) + victim->level)/2,gsn_grapple,DAM_BASH,TRUE);
affect_strip(victim,gsn_mantis);
return;
}//END MATIS
//check for lag protect
if (!do_lagprot(ch, victim, chance, &dam, &vic_lag, gsn_grapple, fSuccess, fYell))
{
if (fYell)
{
sprintf(buf, "Help! %s just bodyslammed into me!",PERS(ch,victim));
j_yell(victim,buf);
}
if (fSuccess)
{
act("$n maneuvers to grapple you, and throws you to the ground!",ch,NULL,victim,TO_VICT);
act("You maneuver to grapple $N, and throw $M to the ground!",ch,NULL,victim,TO_CHAR);
act("$n maneuvers to grapple $N, and throws $M to the ground.",ch,NULL,victim,TO_NOTVICT);
}
else
{
act("$N manages to evade your grapple.", ch,NULL,victim,TO_CHAR);
act("$N manages to evade $n's grapple.", ch,NULL,victim,TO_NOTVICT);
act("You manage to evade $n's grapple.",ch,NULL,victim,TO_VICT);
}
}//END IF NO PROTECTION
if (!fSuccess || dam == 0 || vic_lag == 0)
{
check_improve(ch,gsn_grapple,FALSE,1);
ch_lag = 3 * ch_lag / 2;
}
else
check_improve(ch,gsn_grapple,TRUE,1);
WAIT_STATE2(ch, ch_lag);
if (vic_lag != 0 && dam != 0)
WAIT_STATE2(victim, vic_lag);
damage(ch,victim,dam,gsn_grapple,DAM_BASH,TRUE);
if (ch && victim && ch->fighting == victim && dam > 0)
check_ccombat_actions( victim, ch, CCOMBAT_BASHED);
}
void do_charge( CHAR_DATA *ch, char *argument )
{
char arg[MIL], buf[MSL];
CHAR_DATA *victim;
OBJ_DATA *obj;
int chance;
int dam = number_range(3 * ch->level / 2, 3 * ch->level);
bool fAdv = FALSE;
one_argument( argument, arg );
if ((chance = get_skill(ch,gsn_charge)) < 2)
{
send_to_char("You don't know how to charge someone.\n\r",ch);
return;
}
if (arg[0] == '\0')
{
send_to_char("Charge at who?\n\r",ch);
return;
}
if (ch->fighting != NULL)
{
send_to_char("Not while you're fighting!\n\r",ch);
return;
}
else if ((victim = get_char_room(ch, NULL, arg)) == NULL)
{
send_to_char("They aren't here.\n\r",ch);
return;
}
if ( victim == ch )
return;
if ( is_safe( ch, victim ) )
return;
if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim )
{
sendf(ch, "%s is your beloved master.\n\r", PERS(victim,ch) );
return;
}
obj = get_eq_char( ch, WEAR_WIELD );
if ((obj == NULL || (obj->value[0] != WEAPON_SWORD
&& obj->value[0] != WEAPON_SPEAR
&& obj->value[0] != WEAPON_AXE
&& obj->value[0] != WEAPON_POLEARM))
&& ch->race != race_lookup("minotaur"))
{
send_to_char( "You need an appropriate weapon to charge.\n\r", ch );
return;
}
if (IS_AFFECTED(ch, AFF_SLOW) && !IS_AFFECTED(ch, AFF_HASTE))
{
send_to_char("You can't seem to get up enough speed.\n\r",ch);
return;
}
chance += get_curr_stat(ch,STAT_DEX) - get_curr_stat(victim,STAT_DEX);
if (!IS_NPC(ch)
&& !is_affected(victim, gsn_charge)
&& ch->pcdata->pStallion
&& number_percent() < get_skill(ch, gsn_mounted)
&& (obj->value[0] == WEAPON_SPEAR || obj->value[0] == WEAPON_POLEARM)){
check_improve(ch, gsn_mounted, TRUE, 0);
fAdv = TRUE;
dam += UMAX(0, get_skill(ch, gsn_mounted) - 75) * 3;
act("Saddled atop $t, $n charges you at full speed!", ch, ch->pcdata->pStallion->short_descr, victim, TO_VICT);
act("Saddled atop $t, $n charges $N at full speed!", ch, ch->pcdata->pStallion->short_descr, victim, TO_NOTVICT);
act("Saddled atop $t, you charge $N at full speed!", ch, ch->pcdata->pStallion->short_descr, victim, TO_CHAR);
}
if (IS_SET(ch->off_flags,OFF_FAST) || IS_AFFECTED(ch,AFF_HASTE) || fAdv)
chance += 10;
if (IS_SET(victim->off_flags,OFF_FAST) || IS_AFFECTED(victim,AFF_HASTE))
chance -= 10;
chance += (ch->level - victim->level);
chance += affect_by_size(ch,victim);
chance += get_curr_stat(ch,STAT_LUCK) - get_curr_stat(victim,STAT_LUCK);
if (!IS_AWAKE(victim) )
chance += 10;
WAIT_STATE2( ch, skill_table[gsn_charge].beats );
a_yell(ch,victim);
//predict interdict
if (predictCheck(ch, victim, "charge", skill_table[gsn_charge].name))
return;
if ( number_percent( ) < chance || !IS_AWAKE(victim)){
check_improve(ch,gsn_charge,TRUE,1);
sprintf(buf, "Help! %s just charged into me!",PERS(ch,victim));
j_yell(victim,buf);
if (ch->race == race_lookup("minotaur"))
WAIT_STATE2(victim, skill_table[gsn_charge].beats);
else if (!is_affected(victim, gsn_charge)){
AFFECT_DATA af;
if (fAdv)
WAIT_STATE2(victim, number_range(2, 3) * PULSE_VIOLENCE);
else
WAIT_STATE2(victim, skill_table[gsn_charge].beats / 2);
af.type = gsn_charge;
af.level = victim->level;
af.duration = number_range(0, 2);
af.where = TO_AFFECTS;
af.bitvector = 0;
af.location = APPLY_NONE;
af.modifier = 0;
affect_to_char(victim, &af);
}
else
act("$N avoids your charge and you fail to stun $M.", ch, NULL, victim, TO_CHAR);
/* counter */
if ( counter_check(ch, victim, get_skill(victim, gsn_counter), dam, DAM_BASH, gsn_charge)){
return;
}
if (ch->race == race_lookup("minotaur") && ch->class == class_lookup("berserker")){
act("You charge into $N with your horns and toss him into the air!",ch,NULL,victim,TO_CHAR);
act("$n charges into $N with $s horns and tosses $m into the air!",ch,NULL,victim,TO_NOTVICT);
act("$n charges into you with $s horns and tosses you into the air!",ch,NULL,victim,TO_VICT);
damage(ch,victim,dam,gsn_charge,DAM_BASH,TRUE);
if (ch->in_room == victim->in_room && obj != NULL && obj->value[0] == WEAPON_AXE)
{
act("You slash at $N with $p while $E is in the air!",ch,obj,victim,TO_CHAR);
act("$n slashes at $N with $p while $E is in the air!",ch,obj,victim,TO_NOTVICT);
act("$n slashes at you with $p while you are in the air!",ch,obj,victim,TO_VICT);
multi_hit(ch,victim,TYPE_UNDEFINED);
}
}
else{
if (ch->race == race_lookup("fire") && number_percent() < 3 * ch->level / 2)
damage(ch,victim,3 * dam / 2, gsn_charge, DAM_FIRE, TRUE);
else
damage(ch,victim,dam,gsn_charge,DAM_BASH,TRUE);
}
}
else
{
check_improve(ch,gsn_charge,FALSE,1);
sprintf(buf, "Help! %s tried to charge into me!",PERS(ch,victim));
j_yell(victim,buf);
damage( ch, victim, 0, gsn_charge,DAM_NONE,TRUE);
}
}
void do_ambush( CHAR_DATA *ch, char *argument )
{
char arg[MIL], buf[MSL];
CHAR_DATA *victim;
int chance;
one_argument( argument, arg );
if ((chance = get_skill(ch,gsn_ambush)) == 0)
{
send_to_char("You don't know how to ambush.\n\r",ch);
return;
}
if (arg[0] == '\0')
{
send_to_char("Ambush who?\n\r",ch);
return;
}
if ((victim = get_char_room(ch, NULL, arg)) == NULL)
{
send_to_char("They aren't here.\n\r",ch);
return;
}
if (ch->fighting != NULL)
{
send_to_char("You can't ambush while you are fighting.\n\r", ch);
return;
}
if (victim->hit < ( 4 * victim->max_hit / 5))
{
sendf(ch, "%s is hurt and suspicious ... you can't sneak up.\n\r", PERS(victim,ch) );
return;
}
if (!IS_NPC(ch)
&& ch->in_room->sector_type != SECT_FOREST
&& ch->in_room->sector_type != SECT_HILLS
&& ch->in_room->sector_type != SECT_SNOW
&& ch->in_room->sector_type != SECT_MOUNTAIN
&& ch->in_room->sector_type != SECT_FIELD){
send_to_char("You're not comfortable enough here to ambush.\n\r",ch);
return;
}
if (IS_NPC(victim) && IS_SET(victim->act, ACT_TOO_BIG) )
{
sendf(ch, "%s is too alert for you to attempt such an act.\n\r", PERS(victim,ch));
return;
}
if ( victim == ch )
return;
if ( is_safe( ch, victim ) )
return;
if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim )
{
sendf(ch, "%s is your beloved master.\n\r", PERS(victim,ch) );
return;
}
if (IS_AFFECTED(ch, AFF_SLOW) && !IS_AFFECTED(ch, AFF_HASTE))
{
send_to_char("You can't seem to get up enough speed.\n\r",ch);
return;
}
chance += get_curr_stat(ch,STAT_DEX) - get_curr_stat(victim,STAT_WIS) /2;
chance -= get_curr_stat(ch,STAT_DEX) - get_curr_stat(victim,STAT_DEX);
if (IS_SET(ch->off_flags,OFF_FAST) || IS_AFFECTED(ch,AFF_HASTE))
chance += 10;
if (IS_SET(victim->off_flags,OFF_FAST) || IS_AFFECTED(victim,AFF_HASTE))
chance -= 10;
chance += (ch->level - victim->level);
chance += affect_by_size(ch,victim);
chance += get_curr_stat(ch,STAT_LUCK) - get_curr_stat(victim,STAT_LUCK);
if (IS_WEREBEAST(ch->race))
chance += 10;
if (!IS_AWAKE(victim) )
chance += 10;
WAIT_STATE2( ch, skill_table[gsn_ambush].beats );
a_yell(ch,victim);
//predict interdict
if (predictCheck(ch, victim, "ambush", skill_table[gsn_ambush].name))
return;
if ( number_percent( ) < chance || !IS_AWAKE(victim))
{
check_improve(ch,gsn_ambush,TRUE,1);
sprintf(buf, "Help! %s just ambushed me!",PERS(ch,victim));
j_yell(victim,buf);
one_hit( ch, victim, gsn_ambush, FALSE );
/* check for fired weapons use */
if (ch->fighting == victim && get_skill(ch, gsn_fired) > 1){
OBJ_DATA* launcher;
if ( (launcher = get_eq_char( ch, WEAR_RANGED )) != NULL
&& IS_WEAPON_STAT( launcher, RANGED_FAST)
&& get_eq_char( ch, WEAR_QUIVER ) != NULL){
do_shoot(ch, "");
}
}
}
else
{
check_improve(ch,gsn_ambush,FALSE,1);
sprintf(buf, "Help! %s tried to ambush me!",PERS(ch,victim));
j_yell(victim,buf);
damage( ch, victim, 0, gsn_ambush,DAM_NONE,TRUE);
}
}
void do_circle( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim;
OBJ_DATA *obj, *obj2, *sheath;
char buf[MIL];
int chance, circ, wpnswitch;
int sh_skill = 4 * get_skill(ch, gsn_sheath) / 5;
if ((chance = get_skill(ch,gsn_circle)) == 0){
send_to_char("You don't know how to circle.\n\r",ch);
return;
}
/* get target */
if (IS_NULLSTR(argument)){
victim = ch->fighting;
if (victim == NULL){
send_to_char("But you aren't in combat!\n\r",ch);
return;
}
}
else if ((victim = get_char_room(ch, NULL, argument)) == NULL){
send_to_char("They aren't here.\n\r",ch);
return;
}
if (victim->fighting == NULL){
send_to_char("Your victim must be distracted by combat.\n\r", ch);
return;
}
if (!IS_NPC(ch) && (victim->fighting == ch || IS_SET(victim->off_flags,OFF_AREA_ATTACK))){
send_to_char("You cannot circle while defending yourself.\n\r",ch);
return;
}
if ( is_safe( ch, victim ) )
return;
wpnswitch = FALSE;
obj = get_eq_char( ch, WEAR_WIELD );
obj2 = get_eq_char( ch, WEAR_SECONDARY);
sheath = get_eq_char( ch, WEAR_SHEATH_L);
if (obj == NULL || (obj->value[0] != WEAPON_DAGGER
&& obj->value[0] != WEAPON_SPEAR)){
wpnswitch = TRUE;
if (obj2 == NULL || (obj2->value[0] != WEAPON_DAGGER
&& obj2->value[0] != WEAPON_SPEAR)){
send_to_char( "You need to wield a piercing weapon to circle.\n\r", ch );
return;
}
}
if (IS_AFFECTED(ch, AFF_SLOW) && !IS_AFFECTED(ch, AFF_HASTE)){
send_to_char("You can't seem to get up enough speed.\n\r",ch);
return;
}
chance = 4 * chance / 5;
chance += get_curr_stat(ch,STAT_DEX) - get_curr_stat(victim,STAT_WIS);
chance += get_curr_stat(ch,STAT_DEX) - get_curr_stat(victim,STAT_DEX);
if (IS_SET(ch->off_flags,OFF_FAST) || IS_AFFECTED(ch,AFF_HASTE))
chance += 10;
if (IS_SET(victim->off_flags,OFF_FAST) || IS_AFFECTED(victim,AFF_HASTE))
chance -= 10;
chance += (ch->level - victim->level);
//larger people are easier to hit
chance -= affect_by_size(ch,victim);
chance += get_curr_stat(ch,STAT_LUCK) - get_curr_stat(victim,STAT_LUCK);
WAIT_STATE2( ch, skill_table[gsn_circle].beats );
if (IS_NPC(ch))
circ = attack_lookup("sidestep") + TYPE_NOBLOCKHIT;
else
circ = gsn_circle;
/* yell */
a_yell(ch, victim);
if (ch->fighting != victim && victim->fighting != ch){
sprintf(buf, "Help! %s just put a dagger in my side!",PERS(ch,victim));
j_yell(victim,buf);
}
if ( number_percent( ) < chance ){
check_improve(ch,gsn_circle,TRUE,1);
if (!wpnswitch){
one_hit( ch, victim, circ, FALSE );
if (ch->fighting != victim)
return;
}
if (wpnswitch){
if (number_percent( ) < get_skill(ch, gsn_dual_wield)){
check_improve(ch,gsn_dual_wield,TRUE,1);
one_hit( ch, victim, circ, TRUE );
if (ch->fighting != victim)
return;
}
else{
check_improve(ch,gsn_dual_wield,FALSE,1);
damage( ch, victim, 0, circ, DAM_NONE, TRUE);
}
}
/* check for double */
if (sheath && sheath->value[0] == WEAPON_DAGGER){
if (!IS_LIMITED(sheath))
sh_skill /= 2;
if (number_percent() < sh_skill){
check_improve(ch, gsn_sheath, TRUE, 1);
act("You draw $p from you sleeve and aim for the spleen.",
ch, sheath, NULL, TO_CHAR);
act("$n steps to the side as $e draws something from $s sleeves.",
ch, sheath, NULL, TO_ROOM);
circ = gsn_sheath;
one_hit( ch, victim, circ, TRUE );
}
else
check_improve(ch, gsn_sheath, FALSE, 2);
}
}
else{
check_improve(ch,gsn_circle,FALSE,1);
damage( ch, victim, 0, circ,DAM_NONE,TRUE);
}
}
void do_warcry( CHAR_DATA *ch, char *argument)
{
int chance;
char buf[MSL];
if ((chance = get_skill(ch,gsn_warcry)) == 0)
{
send_to_char( "Huh?\n\r", ch );
return;
}
if (is_affected(ch,gsn_warcry) || is_affected(ch,skill_lookup("bless")))
{
send_to_char("You already feel righteous.\n\r",ch);
return;
}
if (IS_AFFECTED(ch,AFF_CALM))
{
send_to_char("You can't get worked up in your calm state.\n\r",ch);
return;
}
if (IS_SET(ch->comm,COMM_NOYELL))
{
send_to_char("You cannot yell.\n\r",ch);
return;
}
if (ch->mana < 30)
{
send_to_char("You can't get up enough energy.\n\r",ch);
return;
}
if (ch->position == POS_FIGHTING)
chance += 30;
if (number_percent() < chance)
{
char *god = capitalize(ch->pcdata->deity[0] == '\0' ?
"Athaekeetha" : ch->pcdata->deity);
AFFECT_DATA af;
WAIT_STATE2(ch,PULSE_VIOLENCE);
ch->mana -= 30;
act("You feel righteous as you yell out your warcry.",ch,NULL,NULL,TO_CHAR);
act("$n yells out $s warcry.",ch,NULL,NULL,TO_ROOM);
if (ch->class == class_lookup("warrior"))
{
sprintf(buf, "%s, bless me with your power!", god);
do_yell(ch,buf);
}
else if (ch->class == class_lookup("berserker"))
{
sprintf(buf, "%s, I bring forth your fury!", god);
do_yell(ch,buf);
}
else if (ch->class == class_lookup("ranger"))
{
god = capitalize(ch->pcdata->deity[0] == '\0' ?
"Chueh" : ch->pcdata->deity);
sprintf(buf, "%s heed my call!", god);
do_yell(ch,buf);
}
else if (ch->class == class_lookup("shaman"))
{
god = capitalize(ch->pcdata->deity[0] == '\0' ?
"Crypticant" : ch->pcdata->deity);
sprintf(buf, "%s, bring forth your destruction!", god);
do_yell(ch,buf);
}
else if (ch->class == class_lookup("druid"))
{
god = capitalize(ch->pcdata->deity[0] == '\0' ?
"Chueh" : ch->pcdata->deity);
sprintf(buf, "%s, bless this servant of your cause!", god);
do_yell(ch,buf);
}
else{
sprintf(buf, "%s, grant me your blessing!", god);
do_yell(ch,buf);
}
check_improve(ch,gsn_warcry,TRUE,1);
af.where = TO_AFFECTS;
af.type = gsn_warcry;
af.level = ch->level;
af.duration = ch->level /2;
af.modifier = UMAX(1, ch->level / 8);;
af.location = APPLY_HITROLL;
af.bitvector = 0;
affect_to_char(ch,&af);
af.location = APPLY_DAMROLL;
af.modifier = UMAX(1, ch->level / 16);;
affect_to_char(ch,&af);
af.modifier = 0 - (ch->level /8);
af.location = APPLY_SAVING_SPELL;
affect_to_char(ch,&af);
}
else
{
WAIT_STATE2(ch,2 * PULSE_VIOLENCE);
ch->mana -= 15;
act("You grunt softly.",ch,NULL,NULL,TO_CHAR);
act("$n makes some grunting noises.",ch,NULL,NULL,TO_ROOM);
check_improve(ch,gsn_warcry,FALSE,1);
}
}
void do_barkskin( CHAR_DATA *ch, char *argument)
{
int chance;
if ((chance = get_skill(ch,gsn_barkskin)) == 0)
{
send_to_char( "Huh?\n\r", ch );
return;
}
if (is_affected(ch,gsn_barkskin))
{
send_to_char("Your skin is already as tough as bark.\n\r",ch);
return;
}
if (ch->mana < 50)
{
send_to_char("You don't have enough mana.\n\r",ch);
return;
}
WAIT_STATE2(ch,skill_table[gsn_barkskin].beats);
if (number_percent() < chance)
{
AFFECT_DATA af;
ch->mana -= 50;
act("Your skin becomes covered with bark.",ch,NULL,NULL,TO_CHAR);
act("$n's skin becomes covered with bark.",ch,NULL,NULL,TO_ROOM);
check_improve(ch,gsn_barkskin,TRUE,1);
af.type = gsn_barkskin;
af.level = ch->level;
af.duration = 24;
af.modifier = - (1.5 * ch->level);
af.location = APPLY_AC;
af.bitvector = 0;
affect_to_char(ch,&af);
}
else
{
ch->mana -= 25;
send_to_char("You failed to alter your skin texture.\n\r",ch);
check_improve(ch,gsn_barkskin,FALSE,1);
}
}
void do_endure( CHAR_DATA *ch, char *argument)
{
int chance;
if ((chance = get_skill(ch,gsn_endure)) == 0)
{
send_to_char( "Huh?\n\r", ch );
return;
}
if (is_affected(ch,gsn_endure))
{
send_to_char("You can't endure any more concentration.\n\r",ch);
return;
}
if (ch->mana < 30)
{
send_to_char("You don't have enough mana.\n\r",ch);
return;
}
WAIT_STATE2(ch,skill_table[gsn_endure].beats);
if (number_percent() < chance)
{
AFFECT_DATA af;
ch->mana -= 30;
act("You meditate briefly then resume your position.",ch,NULL,NULL,TO_CHAR);
act("$n meditates briefly then resumes $s position.",ch,NULL,NULL,TO_ROOM);
check_improve(ch,gsn_endure,TRUE,1);
af.type = gsn_endure;
af.level = ch->level;
af.duration = 12;
af.modifier = 0 - (chance * ch->level / 500) - 2;
af.location = APPLY_SAVING_SPELL;
af.bitvector = 0;
affect_to_char(ch,&af);
}
else
{
ch->mana -= 15;
send_to_char("Something disturbs your concentration and you fail to endure.\n\r",ch);
check_improve(ch,gsn_endure,FALSE,1);
}
}
void do_chii( CHAR_DATA *ch, char *argument)
{
int chance, cost = 20;
AFFECT_DATA *paf = NULL;
if ((chance = get_skill(ch,gsn_chii)) == 0)
{
send_to_char( "Huh?\n\r", ch );
return;
}
if (is_affected(ch,gsn_chii))
{
send_to_char("Your body is already in equilibrium.\n\r",ch);
return;
}
if (ch->class == class_lookup("monk"))
{
for ( paf = ch->affected; paf != NULL; paf = paf->next )
if (paf->type == gsn_chii_bolt && paf->modifier >= 3)
{
send_to_char("Your body cannot circulate more chii.\n\r",ch);
return;
}
}
if (paf != NULL)
cost += paf->modifier * 10;
if (ch->mana < cost)
{
send_to_char("You don't have enough mana.\n\r",ch);
return;
}
WAIT_STATE2(ch,skill_table[gsn_chii].beats);
if (number_percent() < chance)
{
AFFECT_DATA af;
ch->mana -= cost;
act("You focus inward and regulate your body's circulation.",ch,NULL,NULL,TO_CHAR);
act("$n closes $s eyes for a moment and regulates $s breathing.",ch,NULL,NULL,TO_ROOM);
check_improve(ch,gsn_chii,TRUE,1);
af.type = gsn_chii;
af.level = ch->level;
af.duration = 24;
af.modifier = - 2 * ch->level / 3;
af.location = APPLY_AC;
af.bitvector = 0;
affect_to_char(ch,&af);
}
else
{
ch->mana -= 10;
send_to_char("Something disturbs your meditation.\n\r",ch);
check_improve(ch,gsn_chii,FALSE,1);
}
}
void do_swing( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim, *vch, *vch_next;
OBJ_DATA *obj, *obj2;
int success, chance;
if ((chance = get_skill(ch, gsn_swing)) == 0)
{
send_to_char("You'd feel silly swinging your weapon about like a barbarian.\n\r",ch);
return;
}
if ((victim = ch->fighting) == NULL)
{
send_to_char("But you aren't fighting anyone!\n\r",ch);
return;
}
obj = get_eq_char( ch, WEAR_WIELD );
obj2 = get_eq_char( ch, WEAR_SECONDARY );
if (obj == NULL && !IS_NPC(ch) )
{
send_to_char("You need a weapon to swing around.\n\r",ch);
return;
}
if (IS_AFFECTED(ch, AFF_SLOW) && !IS_AFFECTED(ch, AFF_HASTE))
{
send_to_char("You can't seem to get up enough speed.\n\r",ch);
return;
}
if (IS_AFFECTED2(ch, AFF_RAGE) || is_affected(ch, gsn_windmill))
{
send_to_char("You are already fighting with reckless abandonment.\n\r",ch);
return;
}
WAIT_STATE2( ch, skill_table[gsn_swing].beats );
act("You let loose a flurry of wild swings.",ch,NULL,NULL,TO_CHAR);
act("$n lets loose a flurry of wild swings!",ch,NULL,NULL,TO_ROOM);
for (vch = ch->in_room->people; vch !=NULL; vch = vch_next)
{
vch_next = vch->next_in_room;
if (vch->fighting == ch && vch != victim)
{
chance += get_curr_stat(ch,STAT_DEX) - get_curr_stat(vch,STAT_DEX);
if (IS_SET(ch->off_flags,OFF_FAST) || IS_AFFECTED(ch,AFF_HASTE))
chance += 10;
if (IS_SET(vch->off_flags,OFF_FAST) || IS_AFFECTED(vch,AFF_HASTE))
chance -= 10;
chance += (ch->level - vch->level);
success = number_percent ( );
if ( success < chance )
{
check_improve(ch,gsn_swing,TRUE,1);
one_hit(ch, vch, IS_NPC(ch) ? TYPE_UNDEFINED : TYPE_HIT + obj->value[3], FALSE);
if (success < chance /2 && obj2 != NULL && success < get_skill(ch,gsn_dual_wield))
{
check_improve(ch,gsn_swing,TRUE,1);
if (IS_NPC(ch) && !obj2)
one_hit(ch, vch, TYPE_HIT + ch->dam_type, TRUE);
else
one_hit(ch, vch, TYPE_HIT + obj2->value[3], TRUE);
}
}
else
{
check_improve(ch, gsn_swing, FALSE, 1);
damage(ch, vch, 0, IS_NPC(ch) ? TYPE_UNDEFINED : TYPE_HIT + obj->value[3], DAM_NONE, TRUE);
}
}
}
}
void do_headbutt( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim;
AFFECT_DATA af;
int chance, success;
//cosnt
const int str_med = 18;
const int str_mod = 10;
//bool
bool fRage = FALSE;
if ( (chance = get_skill(ch,gsn_headbutt)) == 0)
{
send_to_char("Ouch!.\n\r", ch );
return;
}
if ( ( victim = ch->fighting ) == NULL )
{
send_to_char( "You aren't fighting anyone.\n\r", ch );
return;
}
chance = 4 * chance /5;
success = number_percent( );
chance += get_curr_stat(ch,STAT_DEX) - get_curr_stat(victim,STAT_DEX);
chance += (ch->level - victim->level);
chance += get_curr_stat(ch,STAT_LUCK) - get_curr_stat(victim,STAT_LUCK);
if (IS_AFFECTED2(ch, AFF_RAGE))
{fRage = TRUE;success -= 20;}
//smaller people are easier to haymaker
success -= affect_by_size(ch, victim) * 2;
chance += affect_by_size(ch,victim);
WAIT_STATE2( ch, skill_table[gsn_headbutt].beats );
if ( success < chance)
{
int shield = get_lagprot(victim);
if (shield == LAG_SHIELD_PROT || shield == LAG_SHIELD_FFIELD)
{
//check for force of the blow.
if(number_percent() < ((fRage ? 20 : 0) + (get_curr_stat(ch, STAT_STR) - str_med) * str_mod))
{
act("Lacking the momentum neccessary you fail to penetrate $N's shield.", ch, NULL, victim, TO_CHAR);
act("$n's headbutt bounces off of the shield!", ch, NULL, victim, TO_ROOM);
success = 100;
}
else
{
act("Striking with great force your $N's shield.", ch, NULL, victim, TO_CHAR);
act("$n's headbutt goes right through the shield!", ch, NULL, victim, TO_ROOM);
}
}
damage(ch,victim,number_range( ch->level / 2, UMAX(0, 70 - success)), gsn_headbutt,DAM_BASH,TRUE);
check_improve(ch,gsn_headbutt,TRUE,8);
if (IS_SET(victim->act, ACT_UNDEAD)
|| victim->class == class_lookup("vampire")
|| victim->class == class_lookup("lich")
|| check_immune(victim, DAM_BASH, FALSE) == IS_IMMUNE)
{
act("$N seems to shake off the blow!", ch, NULL, victim, TO_NOTVICT);
act("You easly shake off the blow.", ch, NULL, victim, TO_VICT);
act("$N seems to not even notice the blow.", ch, NULL, victim, TO_ROOM);
chance = 0;
}
if (success < chance)
{
act("You feel dizzy from the massive blow to the head.",victim, NULL, NULL, TO_CHAR);
act("$n looks dizzy from the blow to the head.", victim, NULL, NULL, TO_ROOM);
if (!is_affected(victim, gsn_headbutt))
{
af.type = gsn_headbutt;
af.level = ch->level;
af.duration = 0;
af.modifier = 0;
af.location = APPLY_NONE;
af.bitvector = 0;
affect_to_char(victim,&af);
}
}
}//end if success
else
{
damage( ch, victim, 0, gsn_headbutt,DAM_BASH,TRUE);
check_improve(ch,gsn_headbutt,FALSE,8);
}
}//end do_headbutt
void do_keen_sight( CHAR_DATA *ch, char *argument )
{
int chance;
AFFECT_DATA af;
if ( (chance = get_skill(ch,gsn_keen_sight)) == 0 )
{
send_to_char("Huh?\n\r",ch);
return;
}
if (ch->mana < 10)
{
send_to_char("You don't have enough mana.\n\r",ch);
return;
}
if ( is_affected(ch, gsn_keen_sight) )
{
send_to_char("You vision is already as sharp as it can get.\n\r",ch);
return;
}
WAIT_STATE2(ch,skill_table[gsn_keen_sight].beats);
if (number_percent() > chance)
{
ch->mana -= 5;
send_to_char("You squint your eyes, but fail to adjust your vision.\n\r",ch);
check_improve(ch,gsn_keen_sight,FALSE,1);
return;
}
ch->mana -= 10;
af.where = TO_AFFECTS2;
af.type = gsn_keen_sight;
af.level = ch->level;
af.duration = ch->level;
af.location = 0;
af.modifier = 0;
af.bitvector = AFF_KEEN_SIGHT;
affect_to_char( ch, &af );
send_to_char( "Your vision sharpens.\n\r", ch );
check_improve(ch,gsn_keen_sight,TRUE,1);
}
void do_pilfer( CHAR_DATA *ch, char *argument ){
CHAR_DATA *victim;
OBJ_DATA *obj;
char arg[MIL];
int chance, roll = number_percent();
if ( (chance = get_skill(ch,gsn_pilfer)) == 0)
{
send_to_char("You are not skilled enough to pilfer.\n\r", ch );
return;
}
if ( ( victim = ch->fighting ) == NULL )
{
send_to_char( "You aren't fighting anyone.\n\r", ch );
return;
}
one_argument( argument, arg );
if ( arg[0] == '\0' )
{
send_to_char( "Pilfer what?\n\r", ch );
return;
}
if ( IS_NPC(victim) && IS_SET(victim->act,ACT_TOO_BIG) )
{
sendf(ch, "%s is too alert for you to pilfer from them.\n\r", PERS2(victim));
return;
}
if (!can_see(victim,ch))
chance += 25;
chance += (get_curr_stat(ch,STAT_DEX) - get_curr_stat(victim,STAT_DEX));
chance += (ch->level - victim->level);
chance += (get_curr_stat(ch,STAT_LUCK) - get_curr_stat(victim,STAT_LUCK));
if (!can_see(ch,victim))
chance /= 3;
chance = URANGE(0,chance,75);
WAIT_STATE2( ch, skill_table[gsn_pilfer].beats );
if ( roll < chance && !(ch->level + 8 < victim->level))
{
damage(ch,victim,number_range( 2*ch->level/3,3*ch->level/2), gsn_pilfer,DAM_NONE,TRUE);
if ( ( obj = get_obj_carry( victim, arg, ch ) ) == NULL ){
send_to_char( "You can't find it.\n\r", ch );
return;
}
if ( !can_drop_obj( ch, obj ) || IS_SET(obj->extra_flags, ITEM_INVENTORY) )
{
send_to_char( "You can't knock it loose.\n\r", ch );
return;
}
act("You knock $p loose from $N's inventory.",ch,obj,victim,TO_CHAR);
act("$n knocks $p loose from $N's inventory.",ch,obj,victim,TO_NOTVICT);
act("$n knock $p loose from your inventory.",ch,obj,victim,TO_VICT);
obj_from_char( obj );
obj_to_room( obj, victim->in_room );
if (IS_NPC(victim) && victim->wait == 0 && can_see_obj(victim,obj))
get_obj(victim,obj,NULL);
check_improve(ch,gsn_pilfer,TRUE,1);
}
else if ( roll < chance*2 )
{
damage(ch,victim,number_range( ch->level/2, 6*ch->level/5), gsn_pilfer,DAM_NONE,TRUE);
check_improve(ch,gsn_pilfer,TRUE,1);
}
else
{
damage( ch, victim, 0, gsn_pilfer,DAM_NONE,TRUE);
check_improve(ch,gsn_pilfer,FALSE,1);
}
}
void do_thrust( CHAR_DATA *ch, char *argument )
{
char arg[MIL], buf[MSL];
CHAR_DATA *victim;
//Data
int chance = 4 * get_skill(ch,gsn_thrust) /5;
int dam = number_range(10 + ch->level/2,(2 * ch->level));
int vic_lag = PULSE_VIOLENCE;
int ch_lag = skill_table[gsn_thrust].beats;
//bools
bool fSuccess = FALSE;
bool fYell = FALSE;
bool fElder = get_skill(ch, gsn_unholy_gift) > 1;
//modifiers.
int size = 0;
if (is_affected(ch, gsn_wolf_form)){
do_tackle( ch, argument );
return;
}
one_argument(argument,arg);
if (chance == 0)
{
send_to_char("Thrust? What's that?\n\r",ch);
return;
}
if (arg[0] == '\0')
{
victim = ch->fighting;
if (victim == NULL)
{
send_to_char("But you aren't fighting anyone!\n\r",ch);
return;
}
}
else if ((victim = get_char_room(ch, NULL, arg)) == NULL)
{
send_to_char("They aren't here.\n\r",ch);
return;
}
if ( victim == ch )
{
send_to_char("Self mutilation is not your style.\n\r",ch);
return;
}
if (is_safe(ch,victim))
return;
chance += get_curr_stat(ch,STAT_STR) - get_curr_stat(victim,STAT_DEX);
chance += GET_AC2(victim,AC_BASH) /25;
chance -= get_skill(victim,gsn_dodge)/20;
chance += ch->level - victim->level;
size = affect_by_size(ch,victim);
if (fElder && size < 0)
size = 0;
chance += size;
if (is_affected(victim,gsn_horse))
chance -= 10;
if ( victim->race == race_lookup("avian")
|| victim->race == race_lookup("faerie") )
chance -= 10;
if ( victim->class == class_lookup("thief") )
chance -= 5;
if (!IS_NPC(victim) && victim->pcdata->pStallion){
if(number_percent() < get_skill(victim, gsn_mounted)){
chance -= 12;
check_improve(victim, gsn_mounted, TRUE, 0);
}
}
//check if target should yell.
fYell = (ch->fighting != victim && victim->fighting != ch);
a_yell(ch,victim);
//predict interdict
if (predictCheck(ch, victim, "thrust", skill_table[gsn_thrust].name))
return;
act("You extend an open palm toward $N. and a powerful force hurls at $M!",ch,NULL,victim,TO_CHAR);
act("$n extends an open palm toward $N.",ch,NULL,victim,TO_NOTVICT);
act("$n extends an open palm toward you, and a powerful force hurls at you!",ch,NULL,victim,TO_VICT);
if (number_percent() < chance)
{
vic_lag = number_range(2,4) * PULSE_VIOLENCE;
fSuccess = TRUE;
}
else
{
dam = 0;
}
//MANTIS CHECK
if (is_affected(victim,gsn_mantis) && fSuccess)
{
act("You use $n's momentum against him, and throw $m to the ground!",ch,NULL,victim,TO_VICT);
act("$N reverses your attack, and throws you to the ground!",ch,NULL,victim,TO_CHAR);
act("$N reversed $n's attack, and throws $m to the ground.",ch,NULL,victim,TO_NOTVICT);
WAIT_STATE2(ch, URANGE(1, number_range(1, victim->size), 3) * PULSE_VIOLENCE);
damage(victim,ch,dam,gsn_mantis,DAM_BASH,TRUE);
affect_strip(victim,gsn_mantis);
return;
}//END MANTIS
//check for lag protect
if (!do_lagprot(ch, victim, chance, &dam, &vic_lag, gsn_thrust, fSuccess, fYell))
{
if (fYell)
{
sprintf(buf, "Help! %s just knocked me flying!",PERS(ch,victim));
j_yell(victim,buf);
}
if (fSuccess)
{
act("$n knocks you flying with a powerful thrust!",ch,NULL,victim,TO_VICT);
act("Your thrust knocks $N flying!",ch,NULL,victim,TO_CHAR);
act("$n knocks $N flying with a powerful thrust.",ch,NULL,victim,TO_NOTVICT);
}
else
{
act("$N evades your thrust!", ch,NULL,victim,TO_CHAR);
act("$N evades $n's thrust.", ch,NULL,victim,TO_NOTVICT);
act("You evade $n's thrust.",ch,NULL,victim,TO_VICT);
}
}//END IF NO PROTECTION
if (!fSuccess || dam == 0 || vic_lag == 0)
{
check_improve(ch, gsn_thrust, FALSE, 1);
ch_lag = 3 * ch_lag / 2;
}
else{
check_improve(ch, gsn_thrust, TRUE, 1);
if (!IS_NPC(victim))
victim->pcdata->pStallion = NULL;
}
WAIT_STATE2(ch, ch_lag);
if (vic_lag != 0 && dam != 0)
WAIT_STATE2(victim, vic_lag);
damage(ch,victim,dam,gsn_thrust,DAM_BASH,TRUE);
if (ch && victim && ch->fighting == victim && dam > 0)
check_ccombat_actions( victim, ch, CCOMBAT_BASHED);
}
void disarm_offhand( CHAR_DATA *ch, CHAR_DATA *victim ){
OBJ_DATA *obj, *wield;
bool fSeize = FALSE;
bool fExoSeize = FALSE;
if ( ( obj = get_eq_char( victim, WEAR_SECONDARY ) ) == NULL )
return;
if ( IS_STONED(victim) || IS_OBJ_STAT(obj,ITEM_NOREMOVE) || is_affected(victim, gsn_graft_weapon))
{
act("$S's secondary weapon won't budge!",ch,NULL,victim,TO_CHAR);
act("$n tries to disarm you, but your secondary weapon won't budge!",ch,NULL,victim,TO_VICT);
act("$n tries to disarm $N, but fails.",ch,NULL,victim,TO_NOTVICT);
return;
}
act( "$n disarms you and sends your secondary weapon flying!", ch, NULL, victim, TO_VICT );
act( "You disarm $N!", ch, NULL, victim, TO_CHAR );
act( "$n disarms $N!", ch, NULL, victim, TO_NOTVICT );
obj_from_char( obj );
/* check for advanced disarms */
if ( (wield = get_eq_char(ch, WEAR_WIELD)) != NULL
&& (wield->value[0] == WEAPON_EXOTIC || wield->value[0] == WEAPON_WHIP)){
int sn = skill_lookup("weapon seize");
if (number_percent() < get_skill(ch, sn)){
check_improve(ch, sn, TRUE, 0);
fSeize = TRUE;
/* check for exotic seize */
if (wield->value[0] == WEAPON_EXOTIC
&& get_skill(ch, gsn_exotic_mastery) > 1)
fExoSeize = TRUE;
}
else
check_improve(ch, sn, FALSE, -99);
}
if (!fExoSeize
&& (IS_OBJ_STAT(obj,ITEM_NODROP) || IS_OBJ_STAT(obj,ITEM_INVENTORY)) )
obj_to_char( obj, victim );
else if (fSeize){
act("With a flick of $p $n grabs the weapon.", ch, wield, NULL, TO_ROOM);
act("With a flick of $p you grab the weapon.", ch, wield, NULL, TO_CHAR);
obj_to_char( obj, ch );
}
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);
}
}
void do_offhand_disarm( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim;
OBJ_DATA *obj;
OBJ_DATA *obj2;
int chance, hth = 0, ch_weapon, vict_weapon, ch_vict_weapon;
if ((chance = get_skill(ch,gsn_offhand_disarm)) == 0)
{
send_to_char( "Huh?\n\r", ch );
return;
}
if ( (obj = get_eq_char( ch, WEAR_WIELD )) == NULL
&& ( obj = get_eq_char( ch, WEAR_SECONDARY )) == NULL
&& ((hth = get_skill(ch,gsn_hand_to_hand)) == 0
|| (IS_NPC(ch) && !IS_SET(ch->off_flags,OFF_DISARM))))
{
send_to_char( "You must wield a weapon to disarm.\n\r", ch );
return;
}
if ( ( victim = ch->fighting ) == NULL )
{
send_to_char( "You aren't fighting anyone.\n\r", ch );
return;
}
if ( ( obj2 = get_eq_char( victim, WEAR_SECONDARY ) ) == NULL )
{
sendf(ch, "%s is not wielding a secondary weapon.\n\r", PERS(victim,ch) );
return;
}
ch_weapon = get_weapon_skill_obj(ch, obj);
vict_weapon = get_weapon_skill_obj(victim, obj2);
ch_vict_weapon = get_weapon_skill_obj(ch, obj2);
if (IS_NPC(victim))
vict_weapon = UMAX(victim->level * 2, 75);
if ( get_eq_char(ch,WEAR_WIELD) == NULL)
chance = chance * hth/150;
else
chance = chance * ch_weapon/100;
chance += get_weapon_obj_rating( obj, WEAPON_WITHDIS ) * 4;
chance += get_weapon_obj_rating( obj2, WEAPON_TOBEDIS ) * 4;
chance += (ch_vict_weapon - vict_weapon) / 2;
chance += 2*(get_curr_stat(ch,STAT_DEX) - get_curr_stat(victim,STAT_STR));
chance += (ch->level - victim->level);
chance -= get_skill(victim,gsn_dual_parry)/10;
if (IS_NPC(victim))
chance -= victim->level/10;
chance += 2*(get_curr_stat(ch,STAT_LUCK) - get_curr_stat(victim,STAT_LUCK));
if (ch->class == class_lookup("monk") && is_affected(ch,gsn_dragon) && is_empowered(ch,0))
chance += 25;
if (number_percent() < chance && (victim->level - ch->level) < 10)
{
int skill = get_skill(victim, gsn_double_grip);
bool fStr = FALSE;
if (is_affected(victim, gsn_istrength) && has_twohanded(victim) != NULL){
fStr = TRUE;
skill = 110;
}
WAIT_STATE2( ch, skill_table[gsn_offhand_disarm].beats );
if ( (is_affected(victim,gsn_double_grip) || fStr)
&& number_percent() < ((4 * skill / 3) - 75) ){
act("You fail to disarm $N's weapon from $S powerfull grasp.",ch,NULL,victim,TO_CHAR);
act("$n tries to disarm you, but your grip is too strong.",ch,NULL,victim,TO_VICT);
act("$n tries to disarm $N, but $E grips $S weapon tightly.",ch,NULL,victim,TO_NOTVICT);
check_improve(ch,gsn_offhand_disarm,FALSE,1);
check_improve(victim,gsn_double_grip, FALSE, -99);
return;
}
disarm_offhand( ch, victim );
check_improve(ch,gsn_offhand_disarm,TRUE,1);
}
else
{
WAIT_STATE2(ch,skill_table[gsn_offhand_disarm].beats);
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_offhand_disarm,FALSE,1);
}
}
//03-25 xxxxx Viri: Modifed do_spells(..) to peoperly calculate manna costs
//using _mana_cost(..) from magic.c.
//05-02-00 Viri: rewrote do_assasinate
//05-30-00 Viri: Added get_lagshield