/* ************************************************************************ * 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); } }