/*
* $Id: raffects.c,v 1.22 1999/04/16 20:49:43 fjoe Exp $
*/
/***************************************************************************
* ANATOLIA 2.1 is copyright 1996-1997 Serdar BULUT, Ibrahim CANPUNAR *
* ANATOLIA has been brought to you by ANATOLIA consortium *
* Serdar BULUT {Chronos} bulut@rorqual.cc.metu.edu.tr *
* Ibrahim Canpunar {Asena} canpunar@rorqual.cc.metu.edu.tr *
* Murat BICER {KIO} mbicer@rorqual.cc.metu.edu.tr *
* D.Baris ACAR {Powerman} dbacar@rorqual.cc.metu.edu.tr *
* By using this code, you have agreed to follow the terms of the *
* ANATOLIA license, in the file Anatolia/anatolia.licence *
***************************************************************************/
/***************************************************************************
* 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 Merc Diku Mud, you must comply with *
* both the original Diku license in 'license.doc' as well the Merc *
* license in 'license.txt'. 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-1995 Russ Taylor *
* ROM has been brought to you by the ROM consortium *
* Russ Taylor (rtaylor@pacinfo.com) *
* Gabrielle Taylor (gtaylor@pacinfo.com) *
* Brian Moore (rom@rom.efn.org) *
* By using this code, you have agreed to follow the terms of the *
* ROM license, in the file Rom24/doc/rom.license *
***************************************************************************/
#include <sys/time.h>
#include <stdio.h>
#include "merc.h"
#include "raffects.h"
#include "fight.h"
DECLARE_DO_FUN(do_wake );
/*
* Apply or remove an affect to a room.
*/
void affect_modify_room(ROOM_INDEX_DATA *room, AFFECT_DATA *paf, bool fAdd)
{
int mod;
mod = paf->modifier;
if (fAdd)
{
switch (paf->where)
{
case TO_ROOM_AFFECTS:
SET_BIT(room->affected_by, paf->bitvector);
break;
case TO_ROOM_FLAGS:
SET_BIT(room->room_flags, paf->bitvector);
break;
case TO_ROOM_CONST:
break;
}
}
else
{
switch (paf->where)
{
case TO_ROOM_AFFECTS:
REMOVE_BIT(room->affected_by, paf->bitvector);
break;
case TO_ROOM_FLAGS:
REMOVE_BIT(room->room_flags, paf->bitvector);
break;
case TO_ROOM_CONST:
break;
}
mod = 0 - mod;
}
switch (paf->location)
{
default:
bug("Affect_modify_room: unknown location %d.", paf->location);
return;
case APPLY_ROOM_NONE: break;
case APPLY_ROOM_HEAL: room->heal_rate += mod; break;
case APPLY_ROOM_MANA: room->mana_rate += mod; break;
}
return;
}
/*
* Give an affect to a room.
*/
void affect_to_room(ROOM_INDEX_DATA *room, AFFECT_DATA *paf)
{
AFFECT_DATA *paf_new;
ROOM_INDEX_DATA *pRoomIndex;
if (! room->affected)
{
if (top_affected_room)
{
for (pRoomIndex = top_affected_room;
pRoomIndex->aff_next != NULL;
pRoomIndex = pRoomIndex->aff_next)
continue;
pRoomIndex->aff_next = room;
}
else top_affected_room = room;
room->aff_next = NULL;
}
paf_new = aff_new();
*paf_new = *paf;
paf_new->next = room->affected;
room->affected = paf_new;
affect_modify_room(room , paf_new, TRUE);
return;
}
void affect_check_room(ROOM_INDEX_DATA *room,int where,int vector)
{
AFFECT_DATA *paf;
if (vector == 0)
return;
for (paf = room->affected; paf != NULL; paf = paf->next)
if (paf->where == where && paf->bitvector == vector)
{
switch (where)
{
case TO_ROOM_AFFECTS:
SET_BIT(room->affected_by,vector);
break;
case TO_ROOM_FLAGS:
SET_BIT(room->room_flags, vector);
break;
case TO_ROOM_CONST:
break;
}
return;
}
}
/*
* Remove an affect from a room.
*/
void affect_remove_room(ROOM_INDEX_DATA *room, AFFECT_DATA *paf)
{
int where;
int vector;
if (room->affected == NULL)
{
bug("Affect_remove_room: no affect.", 0);
return;
}
affect_modify_room(room, paf, FALSE);
where = paf->where;
vector = paf->bitvector;
if (paf == room->affected)
{
room->affected = paf->next;
}
else
{
AFFECT_DATA *prev;
for (prev = room->affected; prev != NULL; prev = prev->next)
{
if (prev->next == paf)
{
prev->next = paf->next;
break;
}
}
if (prev == NULL)
{
bug("Affect_remove_room: cannot find paf.", 0);
return;
}
}
if (!room->affected)
{
ROOM_INDEX_DATA *prev;
if (top_affected_room == room)
{
top_affected_room = room->aff_next;
}
else
{
for(prev = top_affected_room; prev->aff_next; prev = prev->aff_next)
{
if (prev->aff_next == room)
{
prev->aff_next = room->aff_next;
break;
}
}
if (prev == NULL)
{
bug("Affect_remove_room: cannot find room.", 0);
return;
}
}
room->aff_next = NULL;
}
aff_free(paf);
affect_check_room(room,where,vector);
return;
}
/*
* Strip all affects of a given sn.
*/
void affect_strip_room(ROOM_INDEX_DATA *room, int sn)
{
AFFECT_DATA *paf;
AFFECT_DATA *paf_next;
for (paf = room->affected; paf != NULL; paf = paf_next)
{
paf_next = paf->next;
if (paf->type == sn)
affect_remove_room(room, paf);
}
return;
}
/*
* Return true if a room is affected by a spell.
*/
bool is_affected_room(ROOM_INDEX_DATA *room, int sn)
{
AFFECT_DATA *paf;
for (paf = room->affected; paf != NULL; paf = paf->next)
{
if (paf->type == sn)
return TRUE;
}
return FALSE;
}
/*
* Add or enhance an affect.
*/
void affect_join_room(ROOM_INDEX_DATA *room, AFFECT_DATA *paf)
{
AFFECT_DATA *paf_old;
bool found;
found = FALSE;
for (paf_old = room->affected; paf_old != NULL; paf_old = paf_old->next)
{
if (paf_old->type == paf->type)
{
paf->level = (paf->level += paf_old->level) / 2;
paf->duration += paf_old->duration;
paf->modifier += paf_old->modifier;
affect_remove_room(room, paf_old);
break;
}
}
affect_to_room(room, paf);
return;
}
bool is_safe_rspell_nom(int level, CHAR_DATA *victim)
{
/* ghosts are safe */
if (!IS_NPC(victim) && IS_SET(victim->plr_flags, PLR_GHOST))
return TRUE;
/* link dead players who do not have rushing adrenalin are safe */
if (!IS_NPC(victim) && !IS_PUMPED(victim) && victim->desc == NULL)
return TRUE;
if (victim->level < 5 && !IS_NPC(victim))
return TRUE;
if (!IS_NPC(victim)
&& ((level >= victim->level + 5) || (victim->level >= level + 5)))
return TRUE;
return FALSE;
}
bool is_safe_rspell(int level, CHAR_DATA *victim)
{
if (is_safe_rspell_nom(level,victim))
{
act("The gods protect you.",victim,NULL,NULL,TO_CHAR);
act("The gods protect $n from the spell of room.",victim,NULL,NULL,TO_ROOM);
return TRUE;
}
else return FALSE;
}
void raffect_to_char(ROOM_INDEX_DATA *room, CHAR_DATA *ch)
{
AFFECT_DATA *paf;
if (IS_ROOM_AFFECTED(room, RAFF_LSHIELD))
{
int sn;
CHAR_DATA *vch;
if ((sn = sn_lookup("lightning shield")) == -1)
{ bug("Bad sn for lightning shield",0); return; }
for (vch=room->people;vch;vch=vch->next_in_room)
{
if (is_room_owner(vch,room)) break;
}
if (!vch)
{
bug("Owner of lightning shield left the room.",0);
free_string(room->owner);
room->owner = str_dup(str_empty);
affect_strip_room(room,sn);
}
else
{
char_puts("The protective shield of room blocks you.\n",ch);
act("$N has entered the room.",vch,NULL,ch,TO_CHAR);
do_wake(vch,str_empty);
if ((paf = affect_find(room->affected,sn)) == NULL)
{ bug("Bad paf for lightning shield",0); return; }
if (!is_safe_rspell(paf->level,ch))
{
damage(vch,ch,dice(paf->level,4)+12,sn,DAM_LIGHTNING, TRUE);
free_string(room->owner);
room->owner = str_dup(str_empty);
affect_remove_room(room , paf);
}
}
}
if (IS_ROOM_AFFECTED(room, RAFF_SHOCKING))
{
int sn;
if ((sn = sn_lookup("shocking trap")) == -1)
{ bug("Bad sn for shocking shield",0); return; }
char_puts("The shocking waves of room shocks you.\n",ch);
if ((paf = affect_find(room->affected,sn)) == NULL)
{ bug("Bad paf for shocking shield",0); return; }
if (!is_safe_rspell(paf->level,ch))
{
if (check_immune(ch, DAM_LIGHTNING) != IS_IMMUNE)
damage(ch,ch,dice(paf->level,4)+12,TYPE_HUNGER,DAM_TRAP_ROOM, TRUE);
affect_remove_room(room , paf);
}
}
if (IS_ROOM_AFFECTED(room, RAFF_THIEF_TRAP))
{
char_puts("The trap ,set by someone, blocks you.\n",ch);
if ((paf = affect_find(room->affected,gsn_settraps)) == NULL)
{ bug("Bad paf for settraps",0); return; }
if (!is_safe_rspell(paf->level,ch))
{
if (check_immune(ch, DAM_PIERCE) != IS_IMMUNE)
damage(ch,ch,dice(paf->level,5)+12,TYPE_HUNGER,DAM_TRAP_ROOM, TRUE);
affect_remove_room(room , paf);
}
}
if (IS_ROOM_AFFECTED(room, RAFF_SLOW)
|| IS_ROOM_AFFECTED(room, RAFF_SLEEP))
char_puts("There is some mist flowing in the air.\n",ch);
}
void raffect_back_char(ROOM_INDEX_DATA *room, CHAR_DATA *ch)
{
if (IS_ROOM_AFFECTED(room, RAFF_LSHIELD)) {
int sn;
if ((sn = sn_lookup("lightning shield")) == -1)
{ bug("Bad sn for lightning shield",0); return; }
if (is_room_owner(ch,room))
{
free_string(room->owner);
room->owner = str_dup(str_empty);
affect_strip_room(room,sn);
}
}
}
void do_raffects(CHAR_DATA *ch, const char *argument)
{
AFFECT_DATA *paf, *paf_last = NULL;
if (ch->in_room->affected == NULL) {
char_puts("The room is not affected by any spells.\n",ch);
return;
}
char_puts("The room is affected by the following spells:\n", ch);
for (paf = ch->in_room->affected; paf != NULL; paf = paf->next) {
if (paf_last != NULL && paf->type == paf_last->type)
if (ch->level >= 20)
char_puts(" ", ch);
else
continue;
else
char_printf(ch, "Spell: {c%-15s{x",
skill_name(paf->type));
if (ch->level >= 20) {
char_printf(ch, ": modifies {c%s{x by {c%d{x ",
flag_string(rapply_flags, paf->location),
paf->modifier);
if (paf->duration == -1 || paf->duration == -2)
char_puts("permanently.", ch);
else
char_printf(ch, "for {c%d{x hours.",
paf->duration);
}
char_puts("\n", ch);
paf_last = paf;
}
}