/*************************************************************************** * 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. * ***************************************************************************/ #include <glib.h> #if defined(macintosh) #include <types.h> #else #include <sys/types.h> #endif #include <ctype.h> #include <stdio.h> #include <string.h> #include <time.h> #include <merc.h> #include <recycle.h> #include <olc.h> #include <interp.h> #include <fight.h> #include <tables.h> extern GMemChunk *affect_mem_chunk; AFFECT_DATA *affect_free; /* * Create new Instance of "affect" */ AFFECT_DATA *new_affect(void) { static AFFECT_DATA af_zero; AFFECT_DATA *af; if (affect_free == NULL) af = g_chunk_new (AFFECT_DATA, affect_mem_chunk); else { af = affect_free; affect_free = affect_free->next; } *af = af_zero; VALIDATE(af); return af; } void free_affect(AFFECT_DATA *af) { if (!IS_VALID(af)) return; INVALIDATE(af); af->next = affect_free; affect_free = af; } /* * Find the ac value of an obj, including position effect. */ int apply_ac( OBJ_DATA *obj, int iWear ) { if ( obj->item_type != ITEM_ARMOR ) return 0; switch ( iWear ) { case WEAR_BODY: return 3 * obj->value[0]; case WEAR_HEAD: return 2 * obj->value[0]; case WEAR_LEGS: return 2 * obj->value[0]; case WEAR_FEET: return obj->value[0]; case WEAR_HANDS: return obj->value[0]; case WEAR_ARMS: return obj->value[0]; case WEAR_SHIELD: return obj->value[0]; case WEAR_FINGER_L: return obj->value[0]; case WEAR_FINGER_R: return obj->value[0]; case WEAR_NECK_1: return obj->value[0]; case WEAR_NECK_2: return obj->value[0]; case WEAR_ABOUT: return 2 * obj->value[0]; case WEAR_WAIST: return obj->value[0]; case WEAR_WRIST_L: return obj->value[0]; case WEAR_WRIST_R: return obj->value[0]; case WEAR_HOLD: return obj->value[0]; case WEAR_FACE: return obj->value[0]; case WEAR_SCABBARD_L:return 0; case WEAR_SCABBARD_R:return 0; } return 0; } /* * Apply or remove an affect to a character. */ void affect_modify( CHAR_DATA *ch, AFFECT_DATA *paf, bool fAdd ) { OBJ_DATA *wield; int mod; mod = paf->modifier; if ( fAdd ) { SET_BIT( ch->affected_by, paf->bitvector ); } else { REMOVE_BIT( ch->affected_by, paf->bitvector ); mod = 0 - mod; } if ( IS_NPC(ch) ) { switch ( paf->location ) { default: break; case APPLY_NONE: break; case APPLY_MANA: ch->max_mana += mod; break; case APPLY_HIT: ch->max_hit += mod; break; case APPLY_MOVE: ch->max_move += mod; break; case APPLY_AC: ch->armor += mod; break; case APPLY_HITROLL: ch->hitroll += mod; break; case APPLY_DAMROLL: ch->damroll += mod; break; case APPLY_SAVING_PARA: ch->saving_throw += mod; break; case APPLY_SAVING_ROD: ch->saving_throw += mod; break; case APPLY_SAVING_PETRI: ch->saving_throw += mod; break; case APPLY_SAVING_BREATH: ch->saving_throw += mod; break; case APPLY_SAVING_SPELL: ch->saving_throw += mod; break; case APPLY_POLY: ch->polyaff += mod; break; case APPLY_BLOOD_MAX: ch->pcdata->stats[UNI_BLOOD_MAX] += mod; break; case APPLY_BLOOD_POT: ch->pcdata->stats[UNI_BLOOD_POT] += mod; break; } return; } if ( IS_CLASS(ch, CLASS_HIGHLANDER) ) { switch ( paf->location ) { default: break; case APPLY_NONE: break; } return; } switch ( paf->location ) { default: bug( "Affect_modify: unknown location %d.", paf->location ); return; case APPLY_NONE: break; case APPLY_STR: ch->pcdata->mod_str += mod; break; case APPLY_DEX: ch->pcdata->mod_dex += mod; break; case APPLY_INT: ch->pcdata->mod_int += mod; break; case APPLY_WIS: ch->pcdata->mod_wis += mod; break; case APPLY_CON: ch->pcdata->mod_con += mod; break; /* case APPLY_SEX: ch->sex += mod; break; */ case APPLY_SEX: break; case APPLY_CLASS: break; case APPLY_LEVEL: break; case APPLY_AGE: break; case APPLY_HEIGHT: break; case APPLY_WEIGHT: break; case APPLY_MANA: ch->max_mana += mod; break; case APPLY_HIT: ch->max_hit += mod; break; case APPLY_MOVE: ch->max_move += mod; break; case APPLY_GOLD: break; case APPLY_EXP: break; case APPLY_AC: ch->armor += mod; break; case APPLY_HITROLL: ch->hitroll += mod; break; case APPLY_DAMROLL: ch->damroll += mod; break; case APPLY_SAVING_PARA: ch->saving_throw += mod; break; case APPLY_SAVING_ROD: ch->saving_throw += mod; break; case APPLY_SAVING_PETRI: ch->saving_throw += mod; break; case APPLY_SAVING_BREATH: ch->saving_throw += mod; break; case APPLY_SAVING_SPELL: ch->saving_throw += mod; break; case APPLY_POLY: ch->polyaff += mod; break; case APPLY_BLOOD_MAX: ch->pcdata->stats[UNI_BLOOD_MAX] += mod; break; } /* * Check for weapon wielding. * Guard against recursion (for weapons with affects). */ if ( ( wield = get_eq_char( ch, WEAR_WIELD ) ) != NULL && wield->item_type == ITEM_WEAPON && get_obj_weight(wield) > str_app[get_curr_str(ch)].wield ) { static int depth; if ( depth == 0 ) { depth++; act( "You drop $p.", ch, wield, NULL, TO_CHAR ); act( "$n drops $p.", ch, wield, NULL, TO_ROOM ); obj_from_char( wield ); obj_to_room( wield, ch->in_room ); depth--; } } return; } void affect_remove_obj( OBJ_DATA *obj, AFFECT_DATA *paf) { int where, vector; if ( obj->affected == NULL ) { bug( "Affect_remove_object: no affect.", 0 ); return; } obj->value[0] = 0; if (obj->carried_by != NULL && obj->wear_loc != -1) affect_modify( obj->carried_by, paf, FALSE ); where = paf->where; vector = paf->bitvector; /* remove flags from the object if needed */ if (paf->bitvector) switch( paf->where) { case TO_OBJECT: REMOVE_BIT(obj->extra_flags,paf->bitvector); break; case TO_WEAPON: if (obj->item_type == ITEM_WEAPON) REMOVE_BIT(obj->value[4],paf->bitvector); obj->value[0] = 0; break; } if ( paf == obj->affected ) { obj->affected = paf->next; } else { AFFECT_DATA *prev; for ( prev = obj->affected; prev != NULL; prev = prev->next ) { if ( prev->next == paf ) { prev->next = paf->next; break; } } if ( prev == NULL ) { bug( "Affect_remove_object: cannot find paf.", 0 ); return; } } free_affect(paf); if (obj->carried_by != NULL && obj->wear_loc != -1) return; } /* give an affect to an object */ void affect_to_obj(OBJ_DATA *obj, AFFECT_DATA *paf) { AFFECT_DATA *paf_new; paf_new = new_affect(); *paf_new = *paf; paf_new->next = obj->affected; obj->affected = paf_new; /* apply any affect vectors to the object's extra_flags if (paf->bitvector) switch (paf->where) { case TO_OBJECT: SET_BIT(obj->extra_flags,paf->bitvector); break; case TO_WEAPON: if (obj->item_type == ITEM_WEAPON) SET_BIT(obj->value[4],paf->bitvector); break; } */ return; } /* * Give an affect to a char. */ void affect_to_char( CHAR_DATA *ch, AFFECT_DATA *paf ) { AFFECT_DATA *paf_new; paf_new = new_affect(); *paf_new = *paf; paf_new->next = ch->affected; ch->affected = paf_new; affect_modify( ch, paf_new, TRUE ); return; } void affect_modify_room( ROOM_INDEX_DATA *room, AFFECT_DATA *paf, bool fAdd ) { if ( fAdd ) SET_BIT( room->affected_by, paf->bitvector ); else REMOVE_BIT( room->affected_by, paf->bitvector ); return; } /*give affect to room YEA BUDDIE! Spiral in da HOUSE! */ void affect_to_room( ROOM_INDEX_DATA *room, AFFECT_DATA *paf ) { AFFECT_DATA *paf_new; paf_new = new_affect(); *paf_new = *paf; paf_new->next = room->affected; room->affected = paf_new; affect_modify_room( room, paf_new, TRUE ); return; } void affect_remove_room( ROOM_INDEX_DATA *room, AFFECT_DATA *paf ) { if ( room->affected == NULL ) { bug( "Affect_remove: no affect.", 0 ); return; } affect_modify_room( room, paf, FALSE ); 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: cannot find paf.", 0 ); return; } } free_affect(paf); return; } /* * Remove an affect from a char. */ void affect_remove( CHAR_DATA *ch, AFFECT_DATA *paf ) { if ( ch->affected == NULL ) { bug( "Affect_remove: no affect.", 0 ); return; } affect_modify( ch, paf, FALSE ); if ( paf == ch->affected ) { ch->affected = paf->next; } else { AFFECT_DATA *prev; for ( prev = ch->affected; prev != NULL; prev = prev->next ) { if ( prev->next == paf ) { prev->next = paf->next; break; } } if ( prev == NULL ) { bug( "Affect_remove: cannot find paf.", 0 ); return; } } free_affect(paf); return; } /* * Strip all affects of a given sn. */ void affect_strip( CHAR_DATA *ch, int sn ) { AFFECT_DATA *paf; AFFECT_DATA *paf_next; for ( paf = ch->affected; paf != NULL; paf = paf_next ) { paf_next = paf->next; if ( paf->type == sn ) affect_remove( ch, paf ); } return; } /* * Return true if a char is affected by a spell. */ bool is_affected( CHAR_DATA *ch, int sn ) { AFFECT_DATA *paf; for ( paf = ch->affected; paf != NULL; paf = paf->next ) { if ( paf->type == sn ) return TRUE; } return FALSE; } /* * Add or enhance an affect. */ void affect_join( CHAR_DATA *ch, AFFECT_DATA *paf ) { AFFECT_DATA *paf_old; bool found; found = FALSE; for ( paf_old = ch->affected; paf_old != NULL; paf_old = paf_old->next ) { if ( paf_old == NULL ) return; if ( paf_old->type == paf->type ) { paf->duration += paf_old->duration; paf->modifier += paf_old->modifier; affect_remove( ch, paf_old ); break; } } affect_to_char( ch, paf ); return; } /* * Return ascii name of an item type. */ char *item_type_name( OBJ_DATA *obj ) { switch ( obj->item_type ) { case ITEM_LIGHT: return "light"; case ITEM_SCROLL: return "scroll"; case ITEM_WAND: return "wand"; case ITEM_STAFF: return "staff"; case ITEM_WEAPON: return "weapon"; case ITEM_TREASURE: return "treasure"; case ITEM_ARMOR: return "armor"; case ITEM_POTION: return "potion"; case ITEM_FURNITURE: return "furniture"; case ITEM_TRASH: return "trash"; case ITEM_CONTAINER: return "container"; case ITEM_DRINK_CON: return "drink container"; case ITEM_KEY: return "key"; case ITEM_FOOD: return "food"; case ITEM_MONEY: return "money"; case ITEM_BOAT: return "boat"; case ITEM_CORPSE_NPC: return "npc corpse"; case ITEM_CORPSE_PC: return "pc corpse"; case ITEM_FOUNTAIN: return "fountain"; case ITEM_PILL: return "pill"; case ITEM_PORTAL: return "portal"; case ITEM_EGG: return "egg"; case ITEM_VOODOO: return "voodoo doll"; case ITEM_STAKE: return "stake"; case ITEM_MISSILE: return "missile"; case ITEM_AMMO: return "ammo"; case ITEM_QUEST: return "quest token"; case ITEM_QUESTCARD: return "quest card"; case ITEM_QUESTMACHINE: return "quest generator"; case ITEM_SYMBOL: return "magical symbol"; case ITEM_BOOK: return "book"; case ITEM_PAGE: return "page"; case ITEM_TOOL: return "tool"; case ITEM_COOKIE: return "cookie"; case ITEM_TFILET: return "filet"; case ITEM_FIRE: return "fire"; } bug( "Item_type_name: unknown type %d.", obj->item_type ); return "(unknown)"; } /* * Return ascii name of an affect location. */ char *affect_loc_name( int location ) { switch ( location ) { case APPLY_NONE: return "none"; case APPLY_STR: return "strength"; case APPLY_DEX: return "dexterity"; case APPLY_INT: return "intelligence"; case APPLY_WIS: return "wisdom"; case APPLY_CON: return "constitution"; case APPLY_SEX: return "sex"; case APPLY_CLASS: return "class"; case APPLY_LEVEL: return "level"; case APPLY_AGE: return "age"; case APPLY_MANA: return "mana"; case APPLY_HIT: return "hp"; case APPLY_MOVE: return "moves"; case APPLY_GOLD: return "gold"; case APPLY_EXP: return "experience"; case APPLY_AC: return "armor class"; case APPLY_HITROLL: return "hit roll"; case APPLY_DAMROLL: return "damage roll"; case APPLY_SAVING_PARA: return "save vs paralysis"; case APPLY_SAVING_ROD: return "save vs rod"; case APPLY_SAVING_PETRI: return "save vs petrification"; case APPLY_SAVING_BREATH: return "save vs breath"; case APPLY_SAVING_SPELL: return "save vs spell"; case APPLY_POLY: return "polymorph form"; case APPLY_BLOOD_MAX: return "Blood Max"; case APPLY_BLOOD_POT: return "Blood Potence"; } bug( "Affect_location_name: unknown location %d.", location ); return "(unknown)"; } AFFECT_DATA *find_affect( CHAR_DATA *ch, int bitvector) { AFFECT_DATA *paf; AFFECT_DATA *paf_next; for ( paf = ch->affected; paf != NULL; paf = paf_next ) { paf_next = paf->next; if ( paf->bitvector == bitvector ) return paf; } return NULL; }