/* /lib/germ.c * From the Dead Souls Object Library * Germs which cause disease * created by Descartes of Borg 940905 * Version: @(#) germ.c 1.12@(#) * Last modified: 97/01/01 */ #include <lib.h> #include <rooms.h> #include <daemons.h> inherit LIB_ITEM; private int Communicable = 1; mixed Cure = 0; private static function Infect = 0; private static int LastHeartBeat = time(); private mixed LifeSpan = 60; private int CannotInfect = 0; private string Type = "cold"; private string GermName = "generic germ"; private string array ImmuneRaces = ({ "android", "tree", "plant", "elemental", "fish", "gargoyle", "god", "golem", "insect", "slug", "snake", "wraith", "zombie", "bot", "strider", "vehicle", "mech" }); mixed eventMultiply(); void init(){ ::init(); set_heart_beat(1); } /* *************** /lib/germ.c data functions *************** */ int isGerm(){ return 1; } int GetCommunicable(){ return Communicable; } int GetCannotInfect(){ return CannotInfect; } int SetCannotInfect(int i){ if(!i) i = 0; CannotInfect = i; return CannotInfect; } int SetGermName(string str){ if(str) GermName = str; return 1; } string GetGermName(){ return GermName; } /* * int SetCommunicable(int x); * int x - how infectious the germ is * * description: * Makes the germ multiply and infect on its own. The more * communicable, the easier it infects hosts and the easier * it multiplies. * Non-communicable germs must be forced to infect hosts * * returns the degree to which it is communicable */ int SetCommunicable(int x){ if( x > 100 ) x = 100; return (Communicable = x); } mixed GetCure(){ return Cure; } /* mixed SetCure(mixed val) * mixed val - function to test whether germ is cured * or int indicating how hard it is to cure * -1 means incurable * * description * If a function, then that function will be used to * determine if a given cure attempt is successful. * That function should return 1 for success, 0 for failure * If an int and -1, the germ is incurable * If an int > 0, then that much of a cure of the right * type is needed to cure the disease * * returns the successfully set value */ mixed SetCure(mixed val){ if(intp(val)){ Cure=val; return; } return (Cure = val); } function GetInfect(){ return Infect; } /* function SetInfect(function f) * function f - Function to be called whenever this germ * infects a host * * Sets a function to be called whenever a host is infected * * returns the function to be called */ function SetInfect(function f){ Infect = f; return f; } int GetLifeSpan(){ return LifeSpan; } /* int SetLifeSpan(int x) * int x - the length of time the germ can live outside * a host * * description * Sets the amount of time that can pass for the germ * to exist without a host * * returns the new life span */ int SetLifeSpan(mixed x){ if(functionp(x)){ x = evaluate(x); } if(!intp(x)) x = 60; //if( x > 600 ) x = 600; return (LifeSpan = x); } string GetType(){ return Type; } /* string SetType(string type) * string type - the nature of the infection * * description * determines what sort of cure is needed * valid values are: * viral * bacterial * parasite * returns the new germ type */ string SetType(string type){ Type=type; if(!Type || Type == "") Type = "foo"; return Type; } /* *************** /lib/germ.c events *************** */ /** * This event is triggered from within the player object by some * attempt by a cleric or other some such thing to cure the player. */ mixed eventCure(object who, int x, string type){ if( type != GetType() ){ // Can't cure this return 0; } if( Cure == -1 ){ // This is incureable return 0; } if( functionp(Cure) ){ mixed tmp = evaluate(Cure, who, x, type); if( tmp != 1 ){ return tmp; } Cure = 0; } else if( intp(Cure) ){ Cure -= x; } else { error("Bad argument 2 to eventCure()."); } if( Cure > 0 ){ return 0; } set_heart_beat(0); if(this_object()) this_object()->eventMove(ROOM_FURNACE); eventDestruct(); return 1; } mixed eventEncounter(object who){ if( !living(who) ){ return 1; } if( !query_heart_beat() ){ set_heart_beat(5); } if(this_object() && environment(this_object())) eventMultiply(); return 1; } mixed eventInfect(object ob){ mixed tmp; object *presbane; string race; string *bane = ({}); if(!ob) return; if(RELOAD_D->GetWarmBootInProgress()) return 0; if(environment() && base_name(environment()) == ROOM_VOID) return 0; if(!this_object()) return 0; if(!ob) return 0; if(!ob->CanReceive(this_object())) return 0; race = ob->GetRace(); //presbane = present("bane",ob); presbane = filter(all_inventory(ob), (: inherits(LIB_BANE,$1) :) ); if(sizeof(presbane)){ foreach(object foo in presbane){ bane += foo->QueryBane(); } } if(sizeof(bane)){ if(member_array(GetKeyName(),bane) != -1) return 0; if(member_array("all",bane) != -1) return 0; foreach(string foo in GetId()){ if(member_array(foo,bane) != -1) return 0; } } if(present(this_object()->GetKeyName(),ob) ) return 0; if(race && member_array(race, ImmuneRaces) != -1) return 0; if(ob->GetUndead() == 1) return 0; if(ob->GetAquatic() == 1) return 0; if(ob->GetNonCarbonBased() == 1) return 0; if( functionp(Infect) ){ if(!this_object()) return 0; tmp = evaluate(Infect, ob); if( tmp == 1 ){ eventMove(ob); if(this_object() && environment(this_object()) != ob){ eventMove(ROOM_FURNACE); set_heart_beat(0); } else set_heart_beat(5); return tmp; } } if(!eventMove(ob)) eventMove(ROOM_FURNACE); set_heart_beat(5); return 1; } mixed eventMultiply(){ object ob, germ, winner; object *targs; if( Communicable > random(1000) && !CannotInfect){ if( (ob = environment()) && living(ob) ){ if(environment(environment())) ob = environment(environment()); } if(!ob) return 0; //move to the host's environment if(!present(this_object()->GetName(),ob) ){ germ = new(base_name(this_object())); if( germ && living(ob) ) germ->eventInfect(ob); else if(!germ->eventMove(ob)) germ->eventMove(ROOM_FURNACE); } //find someone to infect if(!sizeof(get_livings(ob))) return 0; targs = filter(get_livings(ob), (: !query_carrying($1,base_name(this_object())) :) ); if(sizeof(targs)) winner = targs[random(sizeof(targs))]; if(this_object() && winner) new(base_name(this_object()))->eventInfect(winner); } return 1; } void eventSuffer(object ob){ } /* *************** /lib/germ.c driver applies *************** */ static void create(){ item::create(); AddSave(({ "Communicable", "LifeSpan", "Type" })); SetInvis(1); SetMass(0); SetValue(0); SetPreventDrop(""); SetPreventGet(""); SetPreventPut(""); } static void heart_beat(){ object env; int interval; if(!env = environment()) eventMove(ROOM_FURNACE); interval = time() - LastHeartBeat; LastHeartBeat = time(); if( Communicable ){ eventMultiply(); } if( env && living(env) && environment(env) && member_array(env->GetRace(),ImmuneRaces) == -1){ eventSuffer(env); } if(LifeSpan == -1) return; LifeSpan -= interval; if( LifeSpan < 5 ){ if(this_object()) this_object()->eventMove(ROOM_FURNACE); eventDestruct(); return; } }