/* * MusicMUD Daemon, version 1.0 * Copyright (C) 1998-2003 Abigail Brady * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include <stdlib.h> #include <stdio.h> #include <time.h> #include <string.h> #include <unistd.h> #include <sys/stat.h> #include <ctype.h> #include "Mission.h" #include "musicmud.h" #include "util.h" #include "pflags.h" #include "death.h" #include "misc.h" #include "msi.h" #include "hooks.h" #include "events.h" #include "trap.h" #include "verbs.h" #include "units.h" #include "match.h" #include "nations.h" //! recursively find the value of everything carried by /what/. if /insured/ is true, vanish anything with a value. int value_of(MudObject *what, int insured) { MudObject *o; int i; int v; if (is_player(what) || is_mobile(what)) v = 0; else { v = object_value(what); } foreach(what->children, o, i) if (!is_player(o) && !is_mobile(o)) { int v2 = value_of(o, insured); v += v2; if (insured && v2) { vanish(o); i--; } } return v; } MudObject *do_die(MudObject *what, int charge, const char *why, int uncovered) { int killcorpse = !what->nuke_me; dotrap(E_BEFOREDIED, what, what); /* ::: before_died o1== victim; */ if (killcorpse && what->nuke_me) killcorpse = 1; else killcorpse = 0; if (is_player(what)) { string a = "@auto_"; a += what->id; MudObject *body = planet->get(a.c_str()); if (body) { restore_stuff(what); what->oprintf(cansee, "%#M wakes up with a start.\n", what); what->printf("You wake up with a start.\n"); what->interpret("look"); return 0; } } MudObject *corpse=0; bool insured = what->get_int("insurance") > now; if (uncovered) insured = 0; if (what->get_priv(PFL_IMMORTAL)) { what->printf("If you were mortal, you would die.\n"); return 0; } if (what->get("tourn") || (is_mobile(what) && mud->get_int("tournament",0))) { if (why && why[0]!='|') broadcast(!getflag(FL_NOSLAIN) && maxlev(LEV_CAPTAIN), "^Y[^Rdeath^Y] ^n%s died (%s^n)\n", name(what), why); } if (why && why[0]!='|') broadcast(!getflag(FL_NOSLAIN) && minlev(LEV_CAPTAIN), "^Y[^Rdeath^Y] ^n%s died (%s^n) %s (%s^n)\n", name(what), why, format_roomname(what->owner, what).c_str(), what->owner->id); { extern MudObject *qui; MudObject *who2 = qui; qui = what; if (why) log(PFL_NONE, LEV_INTERNAL, "death", "%s in %s", lose_colour(why).c_str(), what->owner->id); qui = who2; } int valstuff = value_of(what, insured); if (is_player(what)) { valstuff += (int)(totalcash(what)*0.9); wipe_cash(what); } if (!insured) valstuff = 0; if (is_mobile(what) && !killcorpse) { corpse = make_corpse(what, what->owner); if (corpse) { if (what->id[0]!='@') { corpse->set("corpseof", what->id); } } } // if (!is_mobile(what)) { if (!what->owner->get_flag(FL_DEATH)) dumpstuff(what, what->owner); else dumpstuff(what, planet->get("empty")); // } if (streq(what->get("body"), "droid")) { what->oprintf(cansee, "%#M %[terminates/terminate].\n", what); what->printf("^RYOU HAVE TERMINATED^n.\n"); } else { what->oprintf(cansee, "%#M %[dies/die].\n", what); what->printf("^RYOU HAVE DIED^n.\n"); } if (is_player(what)) { if (what->get("tourn")) { set_owner(what, MUD_TOURNAMENTHEAVEN); } else { MudObject *hosp = get_zonepropobj(what->owner, "hospital"); if (!hosp) hosp = MUD_DEFHOSPITAL; if (hosp) { set_owner(what, hosp); what->set_flag(FL_SLEEPING, 1); what->oprintf(cansee, "%#M's body is dragged in.\n"); } } } if (is_mobile(what)) { set_owner(what, MUD_MOBILEHEAVEN); } what->unset("!plan"); what->unset("!what"); what->unset("!when"); what->set_flag(FL_RANTER, 0); what->set_flag(FL_TIMER, 0); if (what->get_int(KEY_STRENGTH)<40) what->set(KEY_STRENGTH, 40); what->unset(KEY_PISSED); MudObject *cur = currency(what); if (!is_player(what)) { if (what->get_object("cloneof") && !what->mission) what->nuke_me = 1; /* ::: after_died o1==victim; after corpse created; mobile is now in 'dead'; etc */ dotrap(E_AFTERDIED, what, what); return corpse; } if (is_player(what)) { MudObject *miss = what->get_object("mission"); if (miss) { if (miss->get_int("m_id")==-1) { } else { what->printf("Your mission is still uncompleted.\n"); } } if (insured) { valstuff = convertcash(valstuff, NULL, cur); if (valstuff) { what->printf("Your bank account has been credited with %s to cover items lost.\n", formatcash(valstuff, cur, 1)); bank_credit(what, cur, valstuff); } } charge = convertcash(charge, NULL, cur); if (insured && charge) { what->printf("Your insurance covers your medical costs.\n"); } else { if (is_player(what) && charge) { bank_debit(what, cur, charge); what->printf("The hospital charges you %s in costs.\n", formatcash(charge, cur, 1)); } } } dotrap(E_AFTERDIED, what, what); mount(what); // remove $mount property. if (is_player(what) && !what->get("tourn")) { MudObject *blank = clone_object(MUD_BLANKET, what, NULL); if (blank) { blank->set("$wornby", what->id); blank->set("$wornon", blank->get("wornon")); } } return corpse; } /* * corpse rottings * * 1. cloned droids don't leave corpses. * 2. zoned mobiles leave corpses that never decay. * * 3. cloned mobiles leave corpses that * a. are fine * b. rotted * c. skeleton * d. vanish */ MudObject *make_corpse(MudObject *mob, MudObject *loc) //! create a corpse for /mob/, and place it in /loc/ { Mission *mission = mob->mission; MudObject *tc = MUD_CORPSE; int droid = 0; if (streq(mob->get("body"), "droid")) { tc = MUD_DROID; droid = 1; } MudObject *corpse = clone_object(tc, loc, NULL); if (!corpse) return 0; corpse->set("altshort", mob->get("short")); if (!droid) { corpse->setf("short_desc", "The disfigured ^ocorpse^n of %M", mob); corpse->setf("mobname", "%M", mob); } else corpse->setf("short_desc", "The broken form of %M", mob); corpse->set("zone", mob->get("zone")); if (!droid && (!corpse->get("zone") || streq(corpse->get("zone"),"@auto"))) { corpse->set("plan.decay", "60 trap decay;1200 trap decay;600 trap decay"); corpse->set_flag(FL_TIMER, 1); corpse->interpret("file_plan decay"); } else { if (mission) corpse->set_mission(mission); } if (mob->get_int("size")>=0) { corpse->set("size", mob->get_int("size")); } if (mob->get_int("mass")>=0) { corpse->set("mass", mob->get_int("mass")); } corpse->setf("desc", "%#M is dead.", mob); if (const char *a=mob->get("corpsedisc")) { corpse->set("disc.0", a); corpse->set("disc.count", 1); } corpse->set_flag(FL_NOSAVE, 1); MudObject *wpn = mob->get_object(KEY_WIELD); if (wpn && wpn->owner != mob) wpn = 0; MudObject *wornfrom = archetype(mob); if (mob->get("wornfrom")) wornfrom = mob->get_object("wornfrom"); MudObject *orwep = 0; if (!mob->get_object(KEY_WIELD) && wornfrom && wornfrom->get_object(KEY_WIELD)) { MudObject *o = orwep = wornfrom->get_object(KEY_WIELD); MudObject *c = clone_object(o, mob, NULL); if (c) { c->set("zone", corpse->get("zone")); c->set("$lootfrom", mob->id); if (droid && mission) c->set_mission(mission); } wpn = c; } if (wornfrom) { MudObject *o; int i; foreach(wornfrom->children, o, i) if (iswornby(o, wornfrom) && !worn_on(mob, wornon(o), o->get_int("wornlevel", 0))) { MudObject *c = orwep ==o ? wpn : clone_object(o, corpse, NULL); if (c) { c->set("zone", corpse->get("zone")); c->set("$wornby", corpse->id); c->set("$wornon", o->get("$wornon")); c->set("$lootfrom", mob->id); if (droid && mission) c->set_mission(mission); } } } MudObject *o; int i; World<MudObject> on = *mob->children; foreach(&on, o, i) { if (iswornby(o, mob)) { set_owner(o, corpse); o->set("$wornby", corpse->id); o->set("$wornon", o->get("$wornon")); } } if (wpn) { set_owner(wpn, corpse); corpse->set(KEY_WIELD, wpn->id); } if (anycash(mob)) { MudObject *t = clone_object(MUD_CASH, corpse, NULL); if (t) { moveallcash(mob, t); describe_pot(t); if (mission) t->set_mission(mission); } } /* So we reset with the zone properly */ return corpse; }