/**************************************************************************** ** Dead Corpses system. pDirt ** ** Project : pDirt (Aber IV Daemon) ** Module : corpse.c ** Author : Marty (Peter Eussen) ** Date : 26-29 August 1997 ** Description : This module handles the creation of corpses after a mobile ** has died, plus the decaying of the corpses. ** Copyright : This piece of code is part of the pDirt distribution. ** Version : 0.1 ****************************************************************************/ #define CORPSE_C #include <stdlib.h> #include "kernel.h" #include "tables.h" #include "cflags.h" #include "sendsys.h" #include "clone.h" #include "mobile.h" #include "objsys.h" /** This indicates how long a corpse should remain in the room before fading ** away into nothing. Time is in seconds. **/ #define DECAYTIME (60 * 5) /** The definition of a linked list to store all the corpses. New additions ** are added at the back. ** I have to use the obj_id() of an object since the cloned object shift ** within the object array and therefore an index to the object array isnt ** going to work. **/ typedef struct _corpselist { int mob; /* Which mob did it belong to? */ long obj_id; /* Whats the Object ID of the corpse */ time_t decay_at; /* Decay at what time? */ struct _corpselist *next; /* Who's next? */ } CORPSELIST; static CORPSELIST *decaylist = NULL; /* Begin of the list */ static CORPSELIST *lastinlist = NULL; /* End of the list */ void decay_corpses(void) { CORPSELIST *p = decaylist, *q; int obj; /* Since new ones are added at the back we can traverse the list from front * to the back and stop whenever the list is empty or the decay time of the * current corpse hasn't been reached yet. */ while (p != NULL && p->decay_at < global_clock) { q = p->next; obj = lookup_entry(p->obj_id,&id_table); if (obj != NOT_IN_TABLE) /* Corpse has been removed by someone */ { /* messages */ sendf(oloc(obj),"You watch as the corpse of %s dissolves into nothing.\n", pname(p->mob)); destruct_object(obj,NULL); } /* Update list and free memory */ if (p == decaylist) decaylist = q; if (p == lastinlist) lastinlist = q; free(p); p = q; } } /* Create a corpse for mobile 'mob', who was killed by 'by'. We need the 'by' * to build the message that is shown to everyone in the mud when they pass * along it. */ void add_corpse_for(int mob,int by) { CORPSELIST *p; int obj,cobj; char line[90]; p = NEW(CORPSELIST,1); if (p != NULL) { p->mob = mob; cobj = clone_object(base_corpse,-1,NULL); p->obj_id = obj_id(cobj); p->next = NULL; p->decay_at = global_clock + DECAYTIME; if (cobj > 0) { /* Add corpse to the list */ if (decaylist == NULL) { decaylist = p; lastinlist = p; } else { lastinlist->next = p; lastinlist = p; } /* Put all the inventory in the corpse, except for the weapon */ /* for (obj = pfirst_obj(mob); obj != SET_END; obj = pnext_obj(mob)) { if (obj == pwpn(mob)) { setoloc(obj,ploc(mob),IN_ROOM); setpwpn(mob,-1); } else setoloc(obj,cobj, IN_CONTAINER); } */ dumpstuff(mob,ploc(mob)); for (obj = 0; obj < 4; obj++) if (olongt(cobj,obj) != NULL) { free(olongt(cobj,obj)); olongt(cobj,obj) = NULL; } sprintf(line,"The dead rotting corpse of %s lies here.. slain by %s.", pname(mob),pname(by)); olongt(cobj,0) = COPY(line); setoloc(cobj,ploc(mob),IN_ROOM); destroy_mobile(mob); return; } } /* We get to here if either the malloc of a list entry failed or we weren't * able to clone any new corpses.. in which case we better do something so * we fall back to the old way... which is dropping the stuff and removing * the mobile. */ dumpstuff(mob,ploc(mob)); destroy_mobile(mob); free(p); }