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