AwakeMUD-0.8.18B/
AwakeMUD-0.8.18B/doc/
AwakeMUD-0.8.18B/lib/
AwakeMUD-0.8.18B/lib/etc/
AwakeMUD-0.8.18B/lib/etc/pfiles/
AwakeMUD-0.8.18B/lib/misc/
AwakeMUD-0.8.18B/lib/text/
AwakeMUD-0.8.18B/lib/text/help/
AwakeMUD-0.8.18B/lib/text/wizhelp/
AwakeMUD-0.8.18B/lib/veh/
AwakeMUD-0.8.18B/lib/world/
AwakeMUD-0.8.18B/lib/world/mob/
AwakeMUD-0.8.18B/lib/world/mtx/
AwakeMUD-0.8.18B/lib/world/qst/
AwakeMUD-0.8.18B/lib/world/shp/
AwakeMUD-0.8.18B/lib/world/veh/
/* ************************************************************************
*   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 "newmagic.h"
#include "awake.h"
#include "constants.h"

/* extern variables */
extern struct room_data *world;
extern struct index_data *mob_index;
extern struct descriptor_data *descriptor_list;
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, struct obj_data *wielded);
extern void damage_door(struct char_data *ch, int room, int dir, int power, int type);
extern void perform_wear(struct char_data *, struct obj_data *, int);
extern void perform_get_from_container(struct char_data *, struct obj_data *, struct obj_data *, int);
extern int can_wield_both(struct char_data *, struct obj_data *, struct obj_data *);
extern void draw_weapon(struct char_data *);

ACMD(do_assist)
{
  struct char_data *helpee, *opponent;

  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)
      opponent = FIGHTING(helpee);
    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 {
      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) && AWAKE(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;
  struct veh_data *veh = NULL;
  int dir, type = DAMOBJ_CRUSH;

  if (world[ch->in_room].peaceful)
  {
    send_to_char("This room just has a peaceful, easy feeling...\r\n", ch);
    return TRUE;
  }
  two_arguments(argument, arg, buf2);

  if (ch->in_veh)
  {
    send_to_char(ch, "You can only drive by or use mounts inside a vehicle.\r\n");
    return TRUE;
  }
  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)) && !(veh = get_veh_list(arg, world[ch->in_room].vehicles, ch)))
  {
    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) {
      draw_weapon(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)) 
          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 aim $p 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 aim $p at the door!", FALSE, ch, wielded, 0, TO_CHAR);
        }
        damage_door(ch, ch->in_room, dir, GET_OBJ_VAL(wielded, 0), DAMOBJ_PIERCE);
        return TRUE;
      } else if (GET_OBJ_VAL(wielded, 3) >= TYPE_PISTOL) {
        if (!has_ammo(ch, wielded))
          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 aim $p 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 aim $p at the door!", FALSE, ch, wielded, 0, TO_CHAR);
        }
        damage_door(ch, ch->in_room, dir, GET_OBJ_VAL(wielded, 0), 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 aim $p 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 aim $p at the door!", FALSE, ch, wielded, 0, TO_CHAR);
      }
      damage_door(ch, ch->in_room, dir, GET_OBJ_VAL(wielded, 0), 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, GET_STR(ch), DAMOBJ_CRUSH);
    }
    return TRUE;
  }

  if (veh)
  {
    if (!PRF_FLAGGED(ch, PRF_PKER) && veh->owner && GET_IDNUM(ch) != veh->owner) {
      PLR_FLAGS(ch).SetBit(PLR_KILLER);
      send_to_char("If you want to be a PLAYER KILLER, so be it...\r\n", ch);
    }
    if (!FIGHTING(ch)) {
      if (!(GET_EQ(ch, WEAR_WIELD) && GET_WIELDED(ch, 0)) &&
          !(GET_EQ(ch, WEAR_HOLD) && GET_WIELDED(ch, 1)))
        draw_weapon(ch);
      
      if (GET_EQ(ch, WEAR_WIELD) && GET_WIELDED(ch, 0)) {
        send_to_char(ch, "You aim %s at %s!\r\n", GET_OBJ_NAME(GET_EQ(ch, WEAR_WIELD)), GET_VEH_NAME(veh));
        sprintf(buf, "%s aims %s right at your ride!\r\n", GET_NAME(ch), GET_OBJ_NAME(GET_EQ(ch, WEAR_WIELD)));
        send_to_veh(buf, veh, NULL, TRUE);
      } else if (GET_EQ(ch, WEAR_HOLD) && GET_WIELDED(ch, 1)) {
        send_to_char(ch, "You aim %s at %s!\r\n", GET_OBJ_NAME(GET_EQ(ch, WEAR_HOLD)), GET_VEH_NAME(veh));
        sprintf(buf, "%s aims %s right at your ride!\r\n", GET_NAME(ch), GET_OBJ_NAME(GET_EQ(ch, WEAR_HOLD)));
        send_to_veh(buf, veh, NULL, TRUE);
      } else {
        send_to_char(ch, "You take a swing at %s!\r\n", GET_VEH_NAME(veh));
        if (get_speed(veh) > 10)
          sprintf(buf, "%s throws %sself out infront of you!\r\n", GET_NAME(ch), thrdgenders[(int)GET_SEX(ch)]);
        else
          sprintf(buf, "%s takes a swing at your ride!\r\n", GET_NAME(ch));
        send_to_veh(buf, veh, NULL, TRUE);
      }
      if (FIGHTING_VEH(ch) == veh) {
        send_to_char(ch, "But you're already attacking it.\r\n");
        return TRUE;
      }
      set_fighting(ch, veh);
      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 (!(GET_EQ(ch, WEAR_WIELD) && GET_WIELDED(ch, 0)) &&
        !(GET_EQ(ch, WEAR_HOLD) && GET_WIELDED(ch, 1)))
      draw_weapon(ch);

    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) && AWAKE(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 aim $p at $N!", FALSE, ch, GET_EQ(ch, WEAR_WIELD), vict, TO_CHAR);
        act("$n aims $p 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 aim $p at $N!", FALSE, ch, GET_EQ(ch, WEAR_HOLD), vict, TO_CHAR);
        act("$n aims $p 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) && AWAKE(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 (!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_VICEPRES)) || 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);
      if (!IS_NPC(vict)) {
        sprintf(buf2, "%s raw killed by %s. {%s (%ld)}", GET_CHAR_NAME(vict),
                GET_NAME(ch), world[vict->in_room].name,
                world[vict->in_room].number);

        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 (!GET_WIELDED(ch, 0) && !GET_WIELDED(ch, 1)) {
    send_to_char("Wielding a weapon generally helps.\r\n", ch);
    return;
  }

  two_arguments(argument, target, direction);

  if (*direction && AFF_FLAGGED(ch, AFF_DETECT_INVIS)) {
    send_to_char(ch, "The ultrasound distorts your vision.\r\n");
    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);

  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 == NUM_OF_DIRS) {
    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 (!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 == NUM_OF_DIRS) {
    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_flee)
{
  int i, attempt;
  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);
      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_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; 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) {
    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 (world[ch->in_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_OBJ_NAME(GET_EQ(ch, WEAR_FEET)) : "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)->text.name : "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);
  }
}

ACMD(do_retract)
{
  skip_spaces(&argument);
  struct obj_data *cyber = NULL;  
  if (*argument)
    cyber = get_obj_in_list_vis(ch, argument, ch->cyberware);
  else {
    for (struct obj_data *obj = ch->cyberware; obj; obj = obj->next_content)
      switch (GET_OBJ_VAL(obj, 0)) {  
        case CYB_HANDRAZOR:  
        case CYB_HANDBLADE:  
        case CYB_HANDSPUR:   
          if (!IS_SET(GET_OBJ_VAL(obj, 3), CYBERWEAPON_RETRACTABLE))  
            continue;  
        case CYB_FOOTANCHOR:  
        case CYB_FIN:  
          cyber = obj;
          break;     
      }
  }  
  if (!cyber) {
    if (!*argument) 
      send_to_char("You don't have any retractable cyberware.\r\n", ch);
    else send_to_char("You don't have that cyberware.\r\n", ch);
  } else if (!(GET_OBJ_VAL(cyber, 0) == CYB_HANDRAZOR || GET_OBJ_VAL(cyber, 0) == CYB_HANDSPUR || GET_OBJ_VAL(cyber, 0) == CYB_HANDBLADE || GET_OBJ_VAL(cyber, 0) == CYB_FOOTANCHOR || GET_OBJ_VAL(cyber, 0) == CYB_FIN))
    send_to_char("That cyberware isn't retractable.\r\n",ch ); 
  else if ((GET_OBJ_VAL(cyber, 0) == CYB_HANDRAZOR || GET_OBJ_VAL(cyber, 0) == CYB_HANDSPUR || GET_OBJ_VAL(cyber, 0) == CYB_HANDBLADE) && !IS_SET(GET_OBJ_VAL(cyber, 3), CYBERWEAPON_RETRACTABLE))
    send_to_char("That cyberweapon isn't retractable.\r\n",ch );
  else {
    if (GET_OBJ_VAL(cyber, 9)) {
      GET_OBJ_VAL(cyber, 9)--;
      sprintf(buf, "$n extends %s.", GET_OBJ_NAME(cyber)+2);
      act(buf, TRUE, ch, 0, 0, TO_ROOM);
      send_to_char(ch, "You extend %s.\r\n", GET_OBJ_NAME(cyber)+2);
    } else {
      GET_OBJ_VAL(cyber, 9)++;
      sprintf(buf, "$n retracts %s.", GET_OBJ_NAME(cyber)+2);
      act(buf, TRUE, ch, 0, 0, TO_ROOM);
      send_to_char(ch, "You retract a %s.\r\n", GET_OBJ_NAME(cyber)+2);
    }
    affect_total(ch);
  }
}