/* ************************************************************************
* File: act.offensive.c Part of CircleMUD *
* Usage: player-level commands of an offensive nature *
* *
* All rights reserved. See license.doc for complete information. *
* *
* Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
* CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. *
************************************************************************ */
#include <stdio.h>
#include <string.h>
#include "structs.h"
#include "utils.h"
#include "comm.h"
#include "interpreter.h"
#include "handler.h"
#include "db.h"
#include "spells.h"
#include "newmagic.h"
#include "awake.h"
/* extern variables */
extern struct room_data *world;
extern struct index_data *mob_index;
extern struct descriptor_data *descriptor_list;
extern int pk_allowed;
extern const char *lookdirs[];
extern const char *spirit_powers[];
extern int convert_look[];
/* extern functions */
void raw_kill(struct char_data * ch);
extern void set_attacking(struct char_data *, struct char_data *, const char *, int);
extern void range_combat(struct char_data *ch, char target[MAX_INPUT_LENGTH],
struct obj_data *weapon, int range, int dir);
extern int find_weapon_range(struct char_data *ch, struct obj_data *weapon);
extern void roll_individual_initiative(struct char_data *ch);
extern bool has_ammo(struct char_data *ch, int pos);
extern void damage_door(struct char_data *ch, int room, int dir, int power, int type);
ACMD(do_assist)
{
struct char_data *helpee, *opponent;
if (IS_PERSONA(ch)) {
send_to_char("That is not a valid command.\r\n", ch);
return;
}
if (FIGHTING(ch)) {
send_to_char("You're already fighting! How can you assist someone else?\r\n", ch);
return;
}
one_argument(argument, arg);
if (!*arg)
send_to_char("Whom do you wish to assist?\r\n", ch);
else if (!(helpee = get_char_room_vis(ch, arg)))
send_to_char(NOPERSON, ch);
else if (helpee == ch)
send_to_char("You can't help yourself any more than this!\r\n", ch);
else {
for (opponent = world[ch->in_room].people; opponent && (FIGHTING(opponent) != helpee);
opponent = opponent->next_in_room);
if (!opponent)
act("But nobody is fighting $M!", FALSE, ch, 0, helpee, TO_CHAR);
else if (!CAN_SEE(ch, opponent))
act("You can't see who is fighting $M!", FALSE, ch, 0, helpee, TO_CHAR);
else if (!pk_allowed && !IS_NPC(opponent)) /* prevent accidental pkill */
act("Use 'murder' if you really want to attack $N.", FALSE, ch, 0, opponent, TO_CHAR);
else {
send_to_char("You join the fight!\r\n", ch);
act("$N assists you!", FALSE, helpee, 0, ch, TO_CHAR);
act("$n assists $N.", FALSE, ch, 0, helpee, TO_NOTVICT);
// here we add the chars to the respective lists
set_fighting(ch, opponent);
if (!FIGHTING(opponent))
set_fighting(opponent, ch);
}
}
}
#define IS_EXPLOSIVE(ch, pos) \
(GET_EQ(ch, pos) && GET_WIELDED(ch, pos - WEAR_WIELD) && \
GET_OBJ_TYPE(GET_EQ(ch, pos)) == ITEM_WEAPON && \
(GET_OBJ_VAL(GET_EQ(ch, pos), 3) == TYPE_ROCKET || \
GET_OBJ_VAL(GET_EQ(ch, pos), 3) == TYPE_GRENADE_LAUNCHER || \
GET_OBJ_VAL(GET_EQ(ch, pos), 3) == TYPE_HAND_GRENADE))
int messageless_find_door(struct char_data *ch, char *type, char *dir, char *cmdname)
{
int door;
if (*dir) {
if ((door = search_block(dir, lookdirs, FALSE)) == -1)
return -1;
door = convert_look[door];
if (EXIT(ch, door)) {
if (EXIT(ch, door)->keyword) {
if (isname(type, EXIT(ch, door)->keyword) &&
!IS_SET(EXIT(ch, door)->exit_info, EX_DESTROYED))
return door;
else return -1;
} else return door;
} else return -1;
} else { /* try to locate the keyword */
if (!*type)
return -1;
for (door = 0; door < NUM_OF_DIRS; door++)
if (EXIT(ch, door))
if (EXIT(ch, door)->keyword)
if (isname(type, EXIT(ch, door)->keyword) &&
!IS_SET(EXIT(ch, door)->exit_info, EX_DESTROYED))
return door;
return -1;
}
}
bool perform_hit(struct char_data *ch, char *argument, char *cmdname)
{
// extern struct index_data *mob_index;
struct char_data *vict = NULL;
struct obj_data *wielded = NULL;
int dir, type = DAMOBJ_CRUSH;
if (ROOM_FLAGGED(ch->in_room, ROOM_PEACEFUL)) {
send_to_char("This room just has a peaceful, easy feeling...\r\n", ch);
return TRUE;
}
two_arguments(argument, arg, buf2);
if (!*arg)
{
sprintf(buf, "%s what?\r\n", cmdname);
send_to_char(ch, CAP(buf));
return TRUE;
}
else if (!(vict = get_char_room_vis(ch, arg)))
{
if ((dir = messageless_find_door(ch, arg, buf2, cmdname)) < 0)
return FALSE;
if (!str_cmp(cmdname, "kill") || !str_cmp(cmdname, "murder"))
{
send_to_char(ch, "How would you go about %sing an object?\r\n",
cmdname);
return TRUE;
}
else if (FIGHTING(ch))
{
send_to_char("Maybe you'd better wait...\r\n", ch);
return TRUE;
}
else if (!LIGHT_OK(ch))
{
send_to_char("How do you expect to do that when you can't see anything?\r\n", ch);
return TRUE;
}
else if (!EXIT(ch,dir)->keyword)
{
return FALSE;
}
else if (!isname(arg, EXIT(ch, dir)->keyword))
{
return FALSE;
}
else if (!IS_SET(EXIT(ch, dir)->exit_info, EX_CLOSED))
{
send_to_char("You can only damage closed doors!\r\n", ch);
return TRUE;
}
else if (IS_EXPLOSIVE(ch, WEAR_WIELD) || IS_EXPLOSIVE(ch, WEAR_HOLD))
{
send_to_char("You might want to think that over.\r\n", ch);
return TRUE;
}
if (IS_AFFECTED(ch, AFF_CHARM) && IS_SPIRIT(ch) && ch->master &&
!IS_NPC(ch->master))
GET_ACTIVE(ch)--;
if (GET_EQ(ch, WEAR_WIELD) && GET_WIELDED(ch, 0))
wielded = GET_EQ(ch, WEAR_WIELD);
else if (GET_EQ(ch, WEAR_HOLD) && GET_WIELDED(ch, 1))
wielded = GET_EQ(ch, WEAR_HOLD);
if (wielded) {
if (GET_OBJ_TYPE(wielded) == ITEM_FIREWEAPON) {
if (!has_ammo(ch, wielded->worn_on))
return TRUE;
WAIT_STATE(ch, PULSE_VIOLENCE * 2);
if (EXIT(ch, dir)->keyword) {
sprintf(buf, "$n attacks the %s.", fname(EXIT(ch, dir)->keyword));
act(buf, TRUE, ch, 0, 0, TO_ROOM);
sprintf(buf, "You draw $p and aim at the %s!", fname(EXIT(ch, dir)->keyword));
act(buf, FALSE, ch, wielded, 0, TO_CHAR);
} else {
act("$n attacks the door.", TRUE, ch, 0, 0, TO_ROOM);
act("You draw $p and aim at the door!", FALSE, ch, wielded, 0, TO_CHAR);
}
damage_door(ch, ch->in_room, dir, GET_OBJ_VAL(wielded, 1) * 2 +
(int)(GET_OBJ_VAL(wielded, 0) / 6), DAMOBJ_PIERCE);
return TRUE;
} else if (GET_OBJ_VAL(wielded, 3) >= TYPE_PISTOL) {
if (!has_ammo(ch, wielded->worn_on))
return TRUE;
WAIT_STATE(ch, PULSE_VIOLENCE * 2);
if (EXIT(ch, dir)->keyword) {
sprintf(buf, "$n attacks the %s.", fname(EXIT(ch, dir)->keyword));
act(buf, TRUE, ch, 0, 0, TO_ROOM);
sprintf(buf, "You draw $p and aim at the %s!", fname(EXIT(ch, dir)->keyword));
act(buf, FALSE, ch, wielded, 0, TO_CHAR);
} else {
act("$n attacks the door.", TRUE, ch, 0, 0, TO_ROOM);
act("You draw $p and aim at the door!", FALSE, ch, wielded, 0, TO_CHAR);
}
damage_door(ch, ch->in_room, dir, GET_OBJ_VAL(wielded, 0) * 2 +
(int)(GET_OBJ_VAL(wielded, 0) / 6), DAMOBJ_PROJECTILE);
return TRUE;
} else switch (GET_OBJ_VAL(wielded, 3)) {
case TYPE_PIERCE: case TYPE_STAB: case TYPE_SHURIKEN:
type = DAMOBJ_PIERCE;
break;
case TYPE_STING: case TYPE_SLASH: case TYPE_CLAW:
case TYPE_THRASH: case TYPE_ARROW: case TYPE_THROWING_KNIFE:
type = DAMOBJ_SLASH;
break;
case TYPE_HIT: case TYPE_BLUDGEON: case TYPE_POUND:
case TYPE_MAUL: case TYPE_PUNCH:
type = DAMOBJ_CRUSH;
break;
default:
if (EXIT(ch, dir)->keyword) {
sprintf(buf, "You can't damage the %s with $p!",
fname(EXIT(ch, dir)->keyword));
act(buf, FALSE, ch, wielded, 0, TO_CHAR);
} else act("You can't damage the door with $p!",
FALSE, ch, wielded, 0, TO_CHAR);
return TRUE;
}
WAIT_STATE(ch, PULSE_VIOLENCE * 2);
if (EXIT(ch, dir)->keyword) {
sprintf(buf, "$n attacks the %s.", fname(EXIT(ch, dir)->keyword));
act(buf, TRUE, ch, 0, 0, TO_ROOM);
sprintf(buf, "You draw $p and aim at the %s!", fname(EXIT(ch, dir)->keyword));
act(buf, FALSE, ch, wielded, 0, TO_CHAR);
} else {
act("$n attacks the door.", TRUE, ch, 0, 0, TO_ROOM);
act("You draw $p and aim at the door!", FALSE, ch, wielded, 0, TO_CHAR);
}
damage_door(ch, ch->in_room, dir, GET_OBJ_VAL(wielded, 1) * 2 +
(int)(GET_OBJ_VAL(wielded, 0) / 6), type);
} else {
WAIT_STATE(ch, PULSE_VIOLENCE * 2);
if (EXIT(ch, dir)->keyword) {
send_to_char(ch, "You take a swing at the %s!\r\n",
fname(EXIT(ch, dir)->keyword));
sprintf(buf, "$n attacks the %s.", fname(EXIT(ch, dir)->keyword));
act(buf, TRUE, ch, 0, 0, TO_ROOM);
} else {
act("You take a swing at the door!", FALSE, ch, 0, 0, TO_CHAR);
act("$n attacks the door.", FALSE, ch, 0, 0, TO_ROOM);
}
damage_door(ch, ch->in_room, dir, (int)(GET_STR(ch) / 3), DAMOBJ_CRUSH);
}
return TRUE;
}
if (vict == ch) {
send_to_char("You hit yourself...OUCH!.\r\n", ch);
act("$n hits $mself, and says OUCH!", FALSE, ch, 0, vict, TO_ROOM);
} else if (IS_AFFECTED(ch, AFF_CHARM) && (ch->master == vict))
act("$N is just such a good friend, you simply can't hit $M.",
FALSE, ch, 0, vict, TO_CHAR);
else {
if (IS_ASTRAL(ch) && !IS_DUAL(vict) && !IS_ASTRAL(vict) &&
!PLR_FLAGGED(vict, PLR_PERCEIVE)) {
send_to_char("Nah...that wouldn't work.\r\n", ch);
return TRUE;
}
if (IS_ASTRAL(vict) && PLR_FLAGGED(ch, PLR_PERCEIVE)) {
send_to_char("You can't initiate attacks on astral beings in your "
"current form.\r\n", ch);
return TRUE;
}
if (!pk_allowed) {
if ((!IS_NPC(vict) || IS_PROJECT(vict)) &&
(!IS_NPC(ch) || IS_PROJECT(ch)) && !str_cmp(cmdname, "murder")) {
send_to_char("Use 'murder' to hit another player.\r\n", ch);
return TRUE;
}
if (IS_AFFECTED(ch, AFF_CHARM) && ch->master &&
!IS_NPC(ch->master) && !IS_NPC(vict))
return FALSE; /* you can't order a charmed pet to attack a player */
}
if (IS_EXPLOSIVE(ch, WEAR_WIELD) || IS_EXPLOSIVE(ch, WEAR_HOLD)) {
send_to_char("You might want to think that over.\r\n", ch);
return TRUE;
}
if (IS_AFFECTED(ch, AFF_CHARM) && IS_SPIRIT(ch) && ch->master && !IS_NPC(ch->master))
GET_ACTIVE(ch)--;
if (!FIGHTING(ch)) {
set_fighting(ch, vict);
if (!FIGHTING(vict))
set_fighting(vict, ch);
WAIT_STATE(ch, PULSE_VIOLENCE + 2);
act("$n attacks $N.", TRUE, ch, 0, vict, TO_NOTVICT);
if (GET_EQ(ch, WEAR_WIELD) && GET_WIELDED(ch, 0)) {
act("You draw $p and aim at $N!", FALSE, ch, GET_EQ(ch, WEAR_WIELD), vict, TO_CHAR);
act("$n draws $p and aims straight at you!", FALSE, ch, GET_EQ(ch, WEAR_WIELD), vict, TO_VICT);
} else if (GET_EQ(ch, WEAR_HOLD) && GET_WIELDED(ch, 1)) {
act("You draw $p and aim at $N!", FALSE, ch, GET_EQ(ch, WEAR_HOLD), vict, TO_CHAR);
act("$n draws $p and aims straight at you!", FALSE, ch, GET_EQ(ch, WEAR_HOLD), vict, TO_VICT);
} else {
act("You take a swing at $N!", FALSE, ch, 0, vict, TO_CHAR);
act("$n prepares to take a swing at you!", FALSE, ch, 0, vict, TO_VICT);
}
} else if (vict != FIGHTING(ch)) {
char name[80];
strcpy(name, GET_NAME(FIGHTING(ch)));
stop_fighting(ch);
set_fighting(ch, vict);
if (!FIGHTING(vict))
set_fighting(vict, ch);
WAIT_STATE(ch, PULSE_VIOLENCE + 2);
sprintf(buf, "$n stops fighting %s and attacks $N!", name);
act(buf, TRUE, ch, 0, vict, TO_NOTVICT);
act("You focus on attacking $N.", FALSE, ch, 0, vict, TO_CHAR);
sprintf(buf, "$n stops fighting %s and aims at you!", name);
act(buf, TRUE, ch, 0, vict, TO_VICT);
} else send_to_char("You do the best you can!\r\n", ch);
}
return TRUE;
}
ACMD(do_hit)
{
if (IS_PERSONA(ch)) {
send_to_char("That is not a valid command.\r\n", ch);
return;
}
if (!perform_hit(ch, argument, (char *)(subcmd == SCMD_HIT ? "hit" :
(subcmd == SCMD_KILL ? "kill" : "murder"))))
send_to_char("You can't seem to find the target you're looking for.\r\n", ch);
}
/* so they have to type out 'kill' */
ACMD(do_kil)
{
send_to_char("You need to type it out if you wanna kill something.\n\r",ch);
}
ACMD(do_kill)
{
struct char_data *vict;
if ((!access_level(ch, LVL_OWNER)) || IS_NPC(ch)) {
do_hit(ch, argument, cmd, subcmd);
return;
}
one_argument(argument, arg);
if (!*arg) {
send_to_char("Kill who?\r\n", ch);
} else {
if (!(vict = get_char_room_vis(ch, arg)))
send_to_char("They aren't here.\r\n", ch);
else if (ch == vict)
send_to_char("Your mother would be so sad.. :(\r\n", ch);
else {
act("You chop $M to pieces! Ah! The blood!", FALSE, ch, 0, vict, TO_CHAR);
act("$N chops you to pieces!", FALSE, vict, 0, ch, TO_CHAR);
act("$n brutally slays $N!", FALSE, ch, 0, vict, TO_NOTVICT);
sprintf(buf2, "%s rawkilled by %s. {%s (%d)}", GET_NAME(vict),
GET_NAME(ch), world[vict->in_room].name,
world[vict->in_room].number);
if (!IS_NPC(vict))
mudlog(buf2, vict, LOG_DEATHLOG, TRUE);
raw_kill(vict);
}
}
}
ACMD(do_shoot)
{
struct obj_data *weapon = NULL;
char direction[MAX_INPUT_LENGTH];
char target[MAX_INPUT_LENGTH];
int dir, i, pos = 0, range = -1;
if (IS_PERSONA(ch)) {
send_to_char("That is not a valid command.\r\n", ch);
return;
}
if (!GET_WIELDED(ch, 0) && !GET_WIELDED(ch, 1)) {
send_to_char("Wielding a weapon generally helps.\r\n", ch);
return;
}
for (i = WEAR_WIELD; i <= WEAR_HOLD; i++)
if (GET_WIELDED(ch, i - WEAR_WIELD) && (weapon = GET_EQ(ch, i)) &&
(GET_OBJ_TYPE(weapon) == ITEM_FIREWEAPON || (GET_OBJ_TYPE(weapon) == ITEM_WEAPON &&
GET_OBJ_VAL(weapon, 3) >= TYPE_GRENADE_LAUNCHER)))
if (find_weapon_range(ch, weapon) > range)
pos = i;
if (!pos) {
send_to_char("Normally guns or bows are used to do that.\r\n", ch);
return;
}
if (perform_hit(ch, argument, "shoot"))
return;
weapon = GET_EQ(ch, pos);
range = find_weapon_range(ch, weapon);
two_arguments(argument, target, direction);
if (!*target) {
send_to_char("Syntax: shoot <target>\r\n"
" shoot <target> <direction>\r\n", ch);
return;
}
if ((dir = search_block(direction, lookdirs, FALSE)) == -1) {
send_to_char("What direction?\r\n", ch);
return;
}
dir = convert_look[dir];
if (dir == MATRIX) {
send_to_char("What direction?\r\n", ch);
return;
}
if (!CAN_GO(ch, dir)) {
send_to_char("There seems to be something in the way...\r\n", ch);
return;
}
range_combat(ch, target, weapon, range, dir);
}
ACMD(do_throw)
{
struct obj_data *weapon = NULL;
int i, dir;
char arg2[MAX_INPUT_LENGTH];
char arg1[MAX_INPUT_LENGTH];
two_arguments(argument, arg1, arg2);
if (IS_PERSONA(ch)) {
send_to_char("That is not a valid command.\r\n", ch);
return;
}
if (!GET_WIELDED(ch, 0) && !GET_WIELDED(ch, 1)) {
send_to_char("You're not wielding anything!\r\n", ch);
return;
}
for (i = WEAR_WIELD; i <= WEAR_HOLD; i++)
if (GET_WIELDED(ch, i - WEAR_WIELD) && (weapon = GET_EQ(ch, i)) &&
(GET_OBJ_VAL(weapon, 3) == TYPE_SHURIKEN ||
GET_OBJ_VAL(weapon, 3) == TYPE_THROWING_KNIFE ||
GET_OBJ_VAL(weapon, 3) == TYPE_HAND_GRENADE))
break;
if (i > WEAR_HOLD || !weapon) {
send_to_char("You should wield a throwing weapon first!\r\n", ch);
return;
}
if (GET_OBJ_VAL(weapon, 3) == TYPE_HAND_GRENADE) {
if (!*arg1) {
send_to_char("Syntax: throw <direction>\r\n", ch);
return;
}
if ((dir = search_block(arg1, lookdirs, FALSE)) == -1) {
send_to_char("What direction?\r\n", ch);
return;
}
dir = convert_look[dir];
} else {
if (!*arg1 || !*arg2) {
send_to_char("Syntax: throw <target> <direction>\r\n", ch);
return;
}
if ((dir = search_block(arg2, lookdirs, FALSE)) == -1) {
send_to_char("What direction?\r\n", ch);
return;
}
dir = convert_look[dir];
}
if (dir == MATRIX) {
send_to_char("What direction?\r\n", ch);
return;
}
if (!CAN_GO(ch, dir)) {
send_to_char("There seems to be something in the way...\r\n", ch);
return;
}
if (GET_OBJ_VAL(weapon, 3) == TYPE_HAND_GRENADE)
range_combat(ch, NULL, weapon, 1, dir);
else range_combat(ch, arg1, weapon, 1, dir);
}
ACMD(do_backstab)
{
struct char_data *vict;
int percent, prob;
if (IS_PERSONA(ch)) {
send_to_char("That is not a valid command.\r\n", ch);
return;
}
if (!(prob = GET_SKILL(ch, SKILL_BACKSTAB))) {
send_to_char("You need to learn the skill first.\r\n", ch);
return;
}
one_argument(argument, buf);
if (!(vict = get_char_room_vis(ch, buf))) {
send_to_char("Backstab who?\r\n", ch);
return;
}
if (vict == ch) {
send_to_char("How can you sneak up on yourself?\r\n", ch);
return;
}
if (!GET_EQ(ch, WEAR_WIELD)) {
send_to_char("You need to wield a weapon to make it a success.\r\n", ch);
return;
}
if (GET_OBJ_VAL(GET_EQ(ch, WEAR_WIELD), 3) != TYPE_PIERCE) {
send_to_char("Only piercing weapons can be used for backstabbing.\r\n", ch);
return;
}
if (FIGHTING(vict)) {
send_to_char("You can't backstab a fighting person -- they're too alert!\r\n", ch);
return;
}
if (MOB_FLAGGED(vict, MOB_AWARE)) {
act("You notice $N lunging at you!", FALSE, vict, 0, ch, TO_CHAR);
act("$e notices you lunging at $m!", FALSE, vict, 0, ch, TO_VICT);
act("$n notices $N lunging at $m!", FALSE, vict, 0, ch, TO_NOTVICT);
set_fighting(vict, ch);
return;
}
percent = number(1, 101); /* 101% is a complete failure */
ATTACK(ch, vict);
if (AWAKE(vict) && (percent > prob))
damage(ch, vict, 0, SKILL_BACKSTAB, PHYSICAL);
else set_fighting(ch, vict);
}
int has_power(struct char_data *ch, int power)
{
if (!IS_SPIRIT(ch) || GET_MOB_VNUM(ch) < 25 || GET_MOB_VNUM(ch) > 41)
return 0;
if (power == PWR_MANIFEST)
return 1;
else switch (GET_MOB_VNUM(ch)) {
case 25: // air elemental
if (power == PWR_ENGULF || power == PWR_BREATHE)
return 1;
break;
case 26: // earth elemental
case 28: // water elemental
if (power == PWR_ENGULF)
return 1;
break;
case 27: // fire elemental
if (power == PWR_AURA || power == PWR_ENGULF || power == PWR_PROJECT ||
power == PWR_GUARD)
return 1;
break;
case 29: // city spirit
if (power == PWR_ACCIDENT || power == PWR_ALIENATE ||
power == PWR_CONCEAL || power == PWR_CONFUSE || power == PWR_FEAR ||
power == PWR_FIND || power == PWR_GUARD)
return 1;
break;
case 30: // hearth spirit
if (power == PWR_ACCIDENT || power == PWR_ALIENATE ||
power == PWR_CONCEAL || power == PWR_CONFUSE || power == PWR_FIND ||
power == PWR_GUARD)
return 1;
break;
case 31: // field spirit
if (power == PWR_ACCIDENT || power == PWR_CONCEAL ||
power == PWR_FIND || power == PWR_GUARD)
return 1;
break;
case 32: // desert spirit
if (power == PWR_CONCEAL || power == PWR_FIND || power == PWR_GUARD)
return 1;
break;
case 33: // forest spirit
if (power == PWR_ACCIDENT || power == PWR_CONCEAL ||
power == PWR_CONFUSE || power == PWR_FEAR ||
power == PWR_GUARD)
return 1;
break;
case 34: // mountain spirit
if (power == PWR_ACCIDENT || power == PWR_CONCEAL ||
power == PWR_FIND || power == PWR_GUARD)
return 1;
break;
case 35: // prairie spirit
if (power == PWR_ACCIDENT || power == PWR_ALIENATE ||
power == PWR_CONCEAL || power == PWR_FIND || power == PWR_GUARD)
return 1;
break;
case 36: // mist spirit
if (power == PWR_ACCIDENT || power == PWR_CONCEAL ||
power == PWR_CONFUSE || power == PWR_GUARD)
return 1;
break;
case 37: // storm spirit
if (power == PWR_CONCEAL || power == PWR_CONFUSE || power == PWR_FEAR ||
power == PWR_PROJECT)
return 1;
break;
case 38: // lake spirit
if (power == PWR_ACCIDENT || power == PWR_ENGULF ||
power == PWR_FEAR || power == PWR_FIND || power == PWR_GUARD)
return 1;
break;
case 39: // river spirit
case 40: // sea spirit
case 41: // swamp spirit
if (GET_MOB_VNUM(ch) != 39 && power == PWR_CONFUSE)
return 1;
if (GET_MOB_VNUM(ch) == 40 && power == PWR_ALIENATE)
return 1;
if (GET_MOB_VNUM(ch) == 41 && power == PWR_BIND)
return 1;
if (power == PWR_ACCIDENT || power == PWR_CONCEAL ||
power == PWR_ENGULF || power == PWR_FEAR || power == PWR_FIND ||
power == PWR_GUARD)
return 1;
break;
}
return 0;
}
void process_command(struct char_data *ch, char *message)
{
int i;
if (IS_SPIRIT(ch) && GET_MOB_VNUM(ch) >= 25 && GET_MOB_VNUM(ch) <= 41) {
any_one_arg(message, arg);
for (i = 0; i < NUM_SPIRIT_POWERS; i++)
if (is_abbrev(arg, spirit_powers[i]))
break;
if (i >= NUM_SPIRIT_POWERS || !has_power(ch, i))
command_interpreter(ch, message);
else switch (i) {
case PWR_ACCIDENT:
// perform_accident(ch, message);
break;
case PWR_ALIENATE:
// perform_alienate(ch, message);
break;
case PWR_AURA:
// perform_aura(ch);
break;
case PWR_BIND:
// perform_bind(ch, message);
break;
case PWR_BREATHE:
// perform_breathe(ch, message);
break;
case PWR_CONCEAL:
// perform_conceal(ch, message);
break;
case PWR_CONFUSE:
// perform_confuse(ch, message);
break;
case PWR_ENGULF:
// perform_engulf(ch, message);
break;
case PWR_FEAR:
// perform_fear(ch, message);
break;
case PWR_FIND:
// perform_find(ch, message);
break;
case PWR_GUARD:
// perform_guard(ch, message);
break;
case PWR_MANIFEST:
// perform_manifest(ch);
break;
case PWR_PROJECT:
// perform_project(ch, message);
break;
}
} else command_interpreter(ch, message);
}
ACMD(do_order)
{
char name[100], message[256];
char buf[256];
bool found = FALSE;
int org_room;
struct char_data *vict;
struct follow_type *k;
if (IS_PERSONA(ch)) {
send_to_char("That is not a valid command.\r\n", ch);
return;
}
half_chop(argument, name, message);
if (!*name || !*message)
send_to_char("Order who to do what?\r\n", ch);
else if (!(vict = get_char_room_vis(ch, name)) && !is_abbrev(name, "followers"))
send_to_char("That person isn't here.\r\n", ch);
else if (ch == vict)
send_to_char("You obviously suffer from schizophrenia.\r\n", ch);
else {
if (IS_AFFECTED(ch, AFF_CHARM)) {
send_to_char("Your superior would not aprove of you giving orders.\r\n", ch);
return;
}
if (vict) {
sprintf(buf, "$N orders you to '%s'", message);
act(buf, FALSE, vict, 0, ch, TO_CHAR);
act("$n gives $N an order.", FALSE, ch, 0, vict, TO_NOTVICT);
if ((vict->master != ch) || !IS_AFFECTED(vict, AFF_CHARM))
act("$n has an indifferent look.", FALSE, vict, 0, 0, TO_ROOM);
else {
send_to_char(OK, ch);
process_command(vict, message);
}
} else { /* This is order "followers" */
sprintf(buf, "$n issues the order '%s'.", message);
act(buf, FALSE, ch, 0, vict, TO_ROOM);
org_room = ch->in_room;
for (k = ch->followers; k; k = k->next) {
if (org_room == k->follower->in_room)
if (IS_AFFECTED(k->follower, AFF_CHARM)) {
found = TRUE;
process_command(k->follower, message);
}
}
if (found)
send_to_char(OK, ch);
else send_to_char("Nobody here is a loyal subject of yours!\r\n", ch);
}
}
}
ACMD(do_flee)
{
int i, attempt, wasin = ch->in_room;
struct char_data *temp;
if (IS_PERSONA(ch)) {
send_to_char("That is not a valid command.\r\n", ch);
return;
}
for (i = 0; i < 6; i++) {
attempt = number(0, NUM_OF_DIRS - 2); /* Select a random direction */
if (CAN_GO(ch, attempt) && (!IS_NPC(ch) ||
!ROOM_FLAGGED(world[ch->in_room].dir_option[attempt]->to_room, ROOM_NOMOB))) {
act("$n panics, and attempts to flee!", TRUE, ch, 0, 0, TO_ROOM);
if (do_simple_move(ch, attempt, CHECK_SPECIAL | LEADER, NULL)) {
send_to_char("You flee head over heels.\r\n", ch);
for (temp = world[wasin].people; temp; temp = temp->next_in_room)
if (FIGHTING(temp) == ch && CAN_SEE(temp, ch) &&
success_test(GET_QUI(temp), GET_QUI(ch)) >=
success_test(GET_QUI(ch), GET_QUI(temp)))
hit(temp, ch, TYPE_MELEE);
// if (FIGHTING(ch) && !IS_NPC(ch)) {
// loss = GET_REP(ch) * number(number(0, 1), 2);
// gain_exp(ch, -loss);
// }
} else act("$n tries to flee, but can't!", TRUE, ch, 0, 0, TO_ROOM);
return;
}
}
send_to_char("PANIC! You couldn't escape!\r\n", ch);
}
ACMD(do_bash)
{
struct char_data *vict;
byte percent, prob;
if (IS_PERSONA(ch)) {
send_to_char("That is not a valid command.\r\n", ch);
return;
}
one_argument(argument, arg);
if (!(prob = GET_SKILL(ch, SKILL_BASH))) {
send_to_char("You need to learn how to bash first.\r\n", ch);
return;
}
if (!(vict = get_char_room_vis(ch, arg))) {
if (FIGHTING(ch)) {
vict = FIGHTING(ch);
} else {
send_to_char("Bash who?\r\n", ch);
return;
}
}
if (vict == ch) {
send_to_char("Aren't we funny today...\r\n", ch);
return;
}
if (!GET_EQ(ch, WEAR_WIELD)) {
send_to_char("You need to wield a weapon to make it a success.\r\n", ch);
return;
}
percent = number(1, 101); /* 101% is a complete failure */
if (percent > prob) {
damage(ch, vict, 0, SKILL_BASH, PHYSICAL);
GET_POS(ch) = POS_SITTING;
} else {
damage(ch, vict, 1, SKILL_BASH, PHYSICAL);
GET_POS(vict) = POS_SITTING;
WAIT_STATE(vict, PULSE_VIOLENCE);
}
WAIT_STATE(ch, PULSE_VIOLENCE * 2);
}
ACMD(do_rescue)
{
struct char_data *vict, *tmp_ch;
byte percent, prob;
if (IS_PERSONA(ch)) {
send_to_char("That is not a valid command.\r\n", ch);
return;
}
one_argument(argument, arg);
if (!(prob = GET_SKILL(ch, SKILL_RESCUE))) {
send_to_char("You need to learn how to rescue first.\r\n", ch);
return;
}
if (!(vict = get_char_room_vis(ch, arg))) {
send_to_char("Who do you want to rescue?\r\n", ch);
return;
}
if (vict == ch) {
send_to_char("What about fleeing instead?\r\n", ch);
return;
}
if (FIGHTING(ch) == vict) {
send_to_char("How can you rescue someone you are trying to kill?\r\n", ch);
return;
}
for (tmp_ch = world[ch->in_room].people; tmp_ch &&
(FIGHTING(tmp_ch) != vict); tmp_ch = tmp_ch->next_in_room);
if (!tmp_ch) {
act("But nobody is fighting $M!", FALSE, ch, 0, vict, TO_CHAR);
return;
}
{
percent = number(1, 101); /* 101% is a complete failure */
if (percent > prob) {
send_to_char("You fail the rescue!\r\n", ch);
return;
}
send_to_char("Banzai! To the rescue...\r\n", ch);
act("You are rescued by $N, you are confused!", FALSE, vict, 0, ch, TO_CHAR);
act("$n heroically rescues $N!", FALSE, ch, 0, vict, TO_NOTVICT);
if (FIGHTING(vict) == tmp_ch)
stop_fighting(vict);
if (FIGHTING(tmp_ch))
stop_fighting(tmp_ch);
if (FIGHTING(ch))
stop_fighting(ch);
set_fighting(ch, tmp_ch);
set_fighting(tmp_ch, ch);
WAIT_STATE(vict, 2 * PULSE_VIOLENCE);
}
}
ACMD(do_kick)
{
struct char_data *vict;
int dir;
any_one_arg(argument, arg);
if (!*arg) {
send_to_char("Kick who or what?\r\n", ch);
return;
}
for (dir = 0; dir < (NUM_OF_DIRS - 1); dir++)
if (EXIT(ch, dir) && EXIT(ch, dir)->keyword &&
isname(arg, EXIT(ch, dir)->keyword) &&
!IS_SET(EXIT(ch, dir)->exit_info, EX_DESTROYED))
break;
if (dir >= (NUM_OF_DIRS - 1)) {
if (!(vict = get_char_room_vis(ch, arg)))
send_to_char("They aren't here.\r\n", ch);
else if (vict == ch) {
send_to_char("Are you flexible enough to do that?\r\n", ch);
act("$n tries to kick $s own ass... not too bright, is $e?",
TRUE, ch, 0, 0, TO_ROOM);
} else {
act("You sneak up behind $N and kick $M straight in the ass!",
FALSE, ch, 0, vict, TO_CHAR);
act("$n sneaks up behind you and kicks you in the ass!\r\n"
"That's gonna leave a mark...", FALSE, ch, 0, vict, TO_VICT);
act("$n sneaks up behind $N and gives $M a swift kick in the ass!",
TRUE, ch, 0, vict, TO_NOTVICT);
}
return;
}
if (FIGHTING(ch))
send_to_char("Maybe you'd better wait...\r\n", ch);
else if (!IS_SET(EXIT(ch, dir)->exit_info, EX_CLOSED))
send_to_char("You can only damage closed doors!\r\n", ch);
else if (!LIGHT_OK(ch))
send_to_char("How do you expect to do that when you can't see anything?\r\n", ch);
else if (IS_SET(ROOM_FLAGS(ch->in_room), ROOM_PEACEFUL))
send_to_char("Nah - leave it in peace.\r\n", ch);
else {
WAIT_STATE(ch, PULSE_VIOLENCE * 2);
if (EXIT(ch, dir)->keyword) {
send_to_char(ch, "You show the %s the bottom of %s!\r\n",
fname(EXIT(ch, dir)->keyword), GET_EQ(ch, WEAR_FEET) ?
GET_EQ(ch, WEAR_FEET)->short_description : "your foot");
sprintf(buf, "$n kicks the %s.", fname(EXIT(ch, dir)->keyword));
act(buf, TRUE, ch, 0, 0, TO_ROOM);
} else {
send_to_char(ch, "You show the door the bottom of %s!\r\n",
GET_EQ(ch, WEAR_FEET) ?
GET_EQ(ch, WEAR_FEET)->short_description : "your foot");
act("$n kicks the door.", TRUE, ch, 0, 0, TO_ROOM);
}
damage_door(ch, ch->in_room, dir, (int)(GET_STR(ch) / 2), DAMOBJ_CRUSH);
}
}