/*
* Various utilities for handling traps
*/
#include <stdio.h>
#include <stdlib.h>
/* #include <unistd.h> */
#include <sys/types.h>
#include <string.h>
#include "global.h"
#include "bug.h"
#include "utils.h"
#include "spells.h"
#include "comm.h"
#include "db.h"
#include "opinion.h"
#include "constants.h"
#include "fight.h"
#include "reception.h"
#include "spell_parser.h"
#include "multiclass.h"
#include "handler.h"
#include "act_info.h"
#define _TRAP_C
#include "trap.h"
void do_settrap(struct char_data *ch, const char *argument, int cmd)
{
if (DEBUG)
log_info("called %s with %s, %s, %d", __PRETTY_FUNCTION__, SAFE_NAME(ch),
VNULL(argument), cmd);
/*
* parse for directions
*/
/*
* trap that affects all directions is an AE trap
*/
/*
* parse for type
*/
/*
* parse for level
*/
}
int CheckForMoveTrap(struct char_data *ch, int dir)
{
struct obj_data *i = NULL;
if (DEBUG > 2)
log_info("called %s with %s, %d", __PRETTY_FUNCTION__, SAFE_NAME(ch), dir);
for (i = real_roomp(ch->in_room)->contents; i; i = i->next_content) {
if ((ITEM_TYPE(i) == ITEM_TRAP) &&
(IS_SET(GET_TRAP_EFF(i), TRAP_EFF_MOVE)) && (GET_TRAP_CHARGES(i) > 0))
if (IS_SET(GET_TRAP_EFF(i), TrapDir[dir]))
return (TriggerTrap(ch, i));
}
return (FALSE);
}
int CheckForInsideTrap(struct char_data *ch, struct obj_data *i)
{
struct obj_data *t = NULL;
if (DEBUG > 2)
log_info("called %s with %s, %s", __PRETTY_FUNCTION__, SAFE_NAME(ch), SAFE_ONAME(i));
for (t = i->contains; t; t = t->next_content) {
if ((ITEM_TYPE(t) == ITEM_TRAP) &&
(IS_SET(GET_TRAP_EFF(t), TRAP_EFF_OBJECT)) && (GET_TRAP_CHARGES(t) > 0)) {
return (TriggerTrap(ch, t));
}
}
return (FALSE);
}
int CheckForAnyTrap(struct char_data *ch, struct obj_data *i)
{
if (DEBUG > 2)
log_info("called %s with %s, %s", __PRETTY_FUNCTION__, SAFE_NAME(ch), SAFE_ONAME(i));
if ((ITEM_TYPE(i) == ITEM_TRAP) && (GET_TRAP_CHARGES(i) > 0))
return (TriggerTrap(ch, i));
return (FALSE);
}
int CheckForGetTrap(struct char_data *ch, struct obj_data *i)
{
if (DEBUG > 2)
log_info("called %s with %s, %s", __PRETTY_FUNCTION__, SAFE_NAME(ch), SAFE_ONAME(i));
if ((ITEM_TYPE(i) == ITEM_TRAP) &&
(IS_SET(GET_TRAP_EFF(i), TRAP_EFF_OBJECT)) && (GET_TRAP_CHARGES(i) > 0)) {
return (TriggerTrap(ch, i));
}
return (FALSE);
}
int TriggerTrap(struct char_data *ch, struct obj_data *i)
{
int adj = 0;
int fireperc = 0;
int roll = 0;
struct char_data *v = NULL;
if (DEBUG > 2)
log_info("called %s with %s, %s", __PRETTY_FUNCTION__, SAFE_NAME(ch), SAFE_ONAME(i));
if (ITEM_TYPE(i) == ITEM_TRAP) {
if (i->obj_flags.value[TRAP_CHARGES]) {
adj = GET_TRAP_LEV(i) - GetMaxLevel(ch);
adj -= dex_app[(int)GET_DEX(ch)].reaction * 5;
fireperc = 95 + adj;
roll = number(1, 100);
if (roll < fireperc) { /* trap is sprung */
act("You hear a strange noise...", TRUE, ch, 0, 0, TO_ROOM);
act("You hear a strange noise...", TRUE, ch, 0, 0, TO_CHAR);
GET_TRAP_CHARGES(i) -= 1;
if (IS_SET(GET_TRAP_EFF(i), TRAP_EFF_ROOM)) {
for (v = real_roomp(ch->in_room)->people; v; v = v->next_in_room) {
FindTrapDamage(v, i);
}
} else {
FindTrapDamage(ch, i);
}
return (TRUE);
}
}
}
return (FALSE);
}
void FindTrapDamage(struct char_data *v, struct obj_data *i)
{
if (DEBUG > 2)
log_info("called %s with %s, %s", __PRETTY_FUNCTION__, SAFE_NAME(v), SAFE_ONAME(i));
/*
* trap types < 0 are special
*/
if (GET_TRAP_DAM_TYPE(i) >= 0) {
TrapDamage(v, GET_TRAP_DAM_TYPE(i), 3 * GET_TRAP_LEV(i), i);
} else {
TrapDamage(v, GET_TRAP_DAM_TYPE(i), 0, i);
}
}
void TrapDamage(struct char_data *v, int damtype, int amnt, struct obj_data *t)
{
struct char_data *tmp_ch = NULL;
if (DEBUG > 2)
log_info("called %s with %s, %d, %d, %s", __PRETTY_FUNCTION__, SAFE_NAME(v), damtype,
amnt, SAFE_ONAME(t));
amnt = SkipImmortals(v, amnt);
if (amnt == -1)
return;
if (IS_AFFECTED(v, AFF_SANCTUARY))
amnt = MAX((int)(amnt / 2), 0); /* Max 1/2 damage when sanct'd */
amnt = PreProcDam(v, damtype, amnt);
if (saves_spell(v, SAVING_PETRI))
amnt = MAX((int)(amnt / 2), 0);
DamageStuff(v, damtype, amnt);
amnt = MAX(amnt, 0);
GET_HIT(v) -= amnt;
update_pos(v);
TrapDam(v, damtype, amnt, t);
InformMess(v);
if (GET_POS(v) == POSITION_DEAD) {
if (!IS_NPC(v)) {
if (real_roomp(v->in_room)->name)
log_info("%s killed by a trap at %s", GET_NAME(v),
real_roomp(v->in_room)->name);
/*
* remove the hatreds of this character
*/
}
for (tmp_ch = character_list; tmp_ch; tmp_ch = tmp_ch->next) {
if (DoesHate(tmp_ch, v)) {
RemHated(tmp_ch, v);
}
}
die(v);
}
}
void TrapDam(struct char_data *v, int damtype, int amnt, struct obj_data *t)
{
char desc[20] = "\0\0\0\0\0\0\0";
if (DEBUG > 2)
log_info("called %s with %s, %d, %d, %s", __PRETTY_FUNCTION__, SAFE_NAME(v), damtype,
amnt, SAFE_ONAME(t));
/*
* easier than dealing with message(ug)
*/
switch (damtype) {
case TRAP_DAM_PIERCE:
strcpy(desc, "pierced");
break;
case TRAP_DAM_SLASH:
strcpy(desc, "sliced");
break;
case TRAP_DAM_BLUNT:
strcpy(desc, "pounded");
break;
case TRAP_DAM_FIRE:
strcpy(desc, "seared");
break;
case TRAP_DAM_COLD:
strcpy(desc, "frozen");
break;
case TRAP_DAM_ACID:
strcpy(desc, "corroded");
break;
case TRAP_DAM_ENERGY:
strcpy(desc, "blasted");
break;
case TRAP_DAM_SLEEP:
strcpy(desc, "knocked out");
break;
case TRAP_DAM_TELEPORT:
strcpy(desc, "transported");
break;
default:
strcpy(desc, "blown away");
break;
}
if ((damtype != TRAP_DAM_TELEPORT) && (damtype != TRAP_DAM_SLEEP)) {
if (amnt > 0) {
act("$n is %s by $p!", TRUE, v, t, 0, TO_ROOM, desc);
act("You are %s by $p!", TRUE, v, t, 0, TO_CHAR, desc);
} else {
act("$n is almost %s by $p!", TRUE, v, t, 0, TO_ROOM, desc);
act("You are almost %s by $p!", TRUE, v, t, 0, TO_CHAR, desc);
}
}
if (damtype == TRAP_DAM_TELEPORT) {
TrapTeleport(v);
} else if (damtype == TRAP_DAM_SLEEP) {
TrapSleep(v);
}
}
void TrapTeleport(struct char_data *v)
{
int to_room = 0;
struct room_data *room = NULL;
if (DEBUG > 2)
log_info("called %s with %s", __PRETTY_FUNCTION__, SAFE_NAME(v));
if (saves_spell(v, SAVING_SPELL)) {
cprintf(v, "You feel strange, but the effect fades.\r\n");
return;
}
do {
to_room = number(0, top_of_world);
room = real_roomp(to_room);
if (room) {
if (IS_SET(room->room_flags, PRIVATE))
room = 0;
}
} while (!room);
act("$n slowly fade out of existence.", FALSE, v, 0, 0, TO_ROOM);
char_from_room(v);
char_to_room(v, to_room);
act("$n slowly fade in to existence.", FALSE, v, 0, 0, TO_ROOM);
do_look(v, "", 0);
if (IS_SET(real_roomp(to_room)->room_flags, DEATH) && GetMaxLevel(v) < LOW_IMMORTAL) {
death_cry(v);
zero_rent(v);
extract_char(v);
}
}
void TrapSleep(struct char_data *v)
{
struct affected_type af;
if (DEBUG > 2)
log_info("called %s with %s", __PRETTY_FUNCTION__, SAFE_NAME(v));
if (!saves_spell(v, SAVING_SPELL)) {
af.type = SPELL_SLEEP;
af.duration = dice(2, 6);
af.modifier = 0;
af.location = APPLY_NONE;
af.bitvector = AFF_SLEEP;
affect_join(v, &af, FALSE, FALSE);
if (GET_POS(v) > POSITION_SLEEPING) {
act("You feel very sleepy ..... zzzzzz", FALSE, v, 0, 0, TO_CHAR);
act("$n goes to sleep.", TRUE, v, 0, 0, TO_ROOM);
GET_POS(v) = POSITION_SLEEPING;
}
} else {
cprintf(v, "You feel sleepy, but you recover\r\n");
}
}
void InformMess(struct char_data *v)
{
if (DEBUG > 2)
log_info("called %s with %s", __PRETTY_FUNCTION__, SAFE_NAME(v));
switch (GET_POS(v)) {
case POSITION_MORTALLYW:
act("$n is mortally wounded, and will die soon, if not aided.", TRUE, v, 0, 0,
TO_ROOM);
act("You are mortally wounded, and will die soon, if not aided.", FALSE, v, 0, 0,
TO_CHAR);
break;
case POSITION_INCAP:
act("$n is incapacitated and will slowly die, if not aided.", TRUE, v, 0, 0,
TO_ROOM);
act("You are incapacitated and you will slowly die, if not aided.", FALSE, v, 0, 0,
TO_CHAR);
break;
case POSITION_STUNNED:
act("$n is stunned, but will probably regain consciousness.", TRUE, v, 0, 0,
TO_ROOM);
act("You're stunned, but you will probably regain consciousness.", FALSE, v, 0, 0,
TO_CHAR);
break;
case POSITION_DEAD:
act("$n is dead! R.I.P.", TRUE, v, 0, 0, TO_ROOM);
act("You are dead! Sorry...", FALSE, v, 0, 0, TO_CHAR);
break;
default: /* >= POSITION SLEEPING */
break;
}
}