/* * 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. * */ /* The wonderful message subsitition routine ! */ #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 "levels.h" #include "units.h" #include "match.h" #include "body.h" #include "nations.h" void fixup_lookplace(MudObject *who, int &lookplace) { if (!cansee(who)) lookplace = 0; if (!who->owner) { lookplace = 0; return; } if (who->owner->get_flag(FL_ONFIRE) && !wf_wears_with_flag(who, FL_NIGHTVISION)) { lookplace = 0; return; } if (!has_light(who->owner) && !wf_wears_with_flag(who, FL_NIGHTVISION)) { lookplace = 0; return; } } int yes (const char *what) { return streq (what, "yes") || streq (what, "true") || streq (what, "on") || streq (what, "t") || streq (what, "1") || (*what == 'y') || (*what=='Y'); } int no (const char *what) { return streq (what, "no") || streq (what, "false") || streq (what, "off") || streq (what, "f") || streq (what, "0") || (*what == 'N') || (*what=='n'); } bool sstrstr(const char *haystack, const char*needle) { if (haystack && needle) return (strcasestr(haystack, needle)!=NULL); else return false; } static MudObject *find_pot(MudObject *where) { iforeach(o, *where->children) { if (o->get_flag(FL_CASH)) return o; } if (MudObject *o = clone_object(MUD_CASH, where)) { o->set("value", 0); return o; } return 0; } string describe_cash(MudObject *pot); void dumpstuff(MudObject *what, MudObject *where) { NewWorld dumped; MudObject *empty = planet->get("empty"); string c; if (anycash(what)) { c = describe_cash(what); if (empty != where) { MudObject *p = find_pot(where); moveallcash(what, p); } wipe_cash(what); } while (what->children->getsize()) { MudObject *o = what->children->get(0); dumped.add(*o); set_owner(o, where); if (where == empty || o->get_flag(FL_FRAGILE) || o->get_flag(FL_NOGIVE)) { vanish(o); } } if (c.length()) { if (dumped) { what->printf("You drop %W and %s.\n", &dumped, c); what->oprintf("%#M %[drops/drop] %W and %s.\n", what, &dumped, c); } else { what->printf("You drop %s.\n", c); what->oprintf("%#M %[drops/drop] %s.\n", what, c); } } else { if (dumped) { what->printf("You drop %s.\n", &dumped); what->oprintf("%#M %[drops/drop] %s.\n", what, &dumped); } } } void set_owner(MudObject * what, MudObject *dest) { if (dest && is_in(dest, what)) { log(PFL_SEEINFO, 0, "debug", "attempt at moving %s into %s", what->id, dest->id); return; } if (what->owner && what->owner->get_object(KEY_WIELD)==what) { what->owner->unset(KEY_WIELD); } what->set("owner", dest?dest->id:0); if (what->get(KEY_WORNBY)) { what->unset(KEY_WORNBY); } if (what->get(KEY_SITON)) what->unset(KEY_SITON); what->unset("$camefrom"); what->unset("$camefromloc"); } void set_owner(MudObject *what, const char *dest) { set_owner(what, planet->get(dest)); } MudObject *get_player(MudObject *me, const char *who) { if (!me) { return planet->get(who); } if (streq(who, "me")) return me; if (me->get_int(KEY_BUNNIED)>now&&(streq(who, "bunnies") || streq(who, "bunny"))) { return MUD_BUNNIES; } MudObject *o = planet->get(who); if (o && ((is_player(o) && o->get_flag(FL_LOGGEDIN)) || is_mobile(o)) && visible_to(me, o)) return o; int i; if (me->owner) { foreach(me->owner->children, o, i) { if ((is_player(o) || is_mobile(o)) && (names_match(o->get("short"), who) || names_match(o->get("altshort"), who) || names_match(name(o), who)) && visible_to(me, o)) return o; } } foreach(players, o, i) { if (o->get_flag(FL_LOGGEDIN) && (names_match(o->get("short"), who) || names_match(o->get("altshort"), who)) && visible_to(me, o)) return o; } return 0; } bool visible_to(const MudObject *to, const MudObject *what) { if (to==what) return true; int privs = privs_of(to); int ilev = invis(what); if (is_player(what)) { int sight = to->get_int("sight", 1); if (sight < 1) return false; } if (ilev == -1) return true; if (privs == -1) privs = 0; return privs >= ilev; } int invis(const MudObject *of) { int i = of->get_int("invis"); if (i!=-1) return i; return 0; } int strength_of(const MudObject *player) { return player->get_int(KEY_STRENGTH); } void set_strength(MudObject *player, int strength) { player->set(KEY_STRENGTH, strength); } int privs_of(const MudObject *who, int def) { int privs = who->get_int("privs", def); int level = who->get_int("level", def); int remorted = who->get_int("remort", def); if (remorted>0) return level>=LEV_COMMANDER?LEV_COMMANDER-1:level; if (privs > level) return privs; return level; } MudObject *saton(MudObject *who) { if (!who->get_flag(FL_SITTING)) { return 0; } MudObject *chair = who->get_object(KEY_SITON); if (!chair) return 0; return chair; } MudObject *sleepon(MudObject *who) { if (!who->get_flag(FL_SLEEPING)) { return 0; } MudObject *chair = who->get_object(KEY_SITON); if (!chair) return 0; return chair; } bool random_chance(long odds) { long foo = (random() >> 3); return (foo % odds) == 0; } long random_number(long limit) { if (limit < 1) return 0; long foo = (random() >> 3); return (foo % limit); } void vanish_contents(MudObject *who) { MudObject *o; int i; foreach(who->children, o, i) { vanish(o); if (o->owner != who) i--; } } bool is_big_mobile(MudObject *what) { if (!what) return false; if (!is_mobile(what)) return false; if (!mass_in_grams(what)) return true; return false; } MudObject *zoneof(MudObject *where) { if (!where) return 0; const char *txt = where->get("zone"); if (!txt) return 0; return planet->get(ssprintf("%s_zone", txt).c_str()); } int state(const MudObject *what) { return what->get_int(KEY_STATE, 0); } MudObject *find_ship(MudObject *dock) { if (!dock) return 0; MudObject *o; int i; foreach(dock->children, o, i) { if (o->get_flag(FL_SHIP)) return o; } return 0; } bool has_ship_space(const char *where, MudObject *ignore=0) { MudObject *d = planet->get(where); if (!d) return false; if (d->get_flag(FL_PRIVATE)) return 0; if (d->get_object("reserved") && d->get_object("reserved") != ignore) { return 0; } int goodness = d->get_int("docksize", 0); int needed = ignore?ignore->get_int("dockneeded", 0):0; if (goodness!=needed) return 0; MudObject *ship = find_ship(d); if (!ship || (!ignore && ship == ignore)) return 1; return 0; } MudObject *find_dock(MudObject *docklist, MudObject *ignore) { char name[256]; if (docklist->get_object("dock")) docklist = docklist->get_object("dock"); int max = docklist->get_int("dock.count"); int i; for (i=0;i<max;i++) { sprintf(name, "dock.%i", i); MudObject *d = docklist->get_object(name); if (d && d->get_object("reserved") && ignore) { if (d->get_object("reserved")==ignore) return d; } } for (i=0;i<max;i++) { sprintf(name, "dock.%i", i); const char *d = docklist->get(name); if (!d) return 0; if (has_ship_space(d, ignore)) return planet->get(d); } return 0; } bool is_droppable(MudObject *o) { if (is_player(o->owner) && o->owner && !o->owner->get_flag(FL_LOGGEDIN)) return 1; if (o->get_flag(FL_FIXED) || o->get_flag(FL_EXIT)) return 0; if (mount(o->owner)==o) return 0; if (o->owner && o->owner->get_flag(FL_NOINVWORN)) { /* I really don't like this behaviour -- Daz */ if (o->get_object("$wornby")==o->owner) return 0; if (o->owner && o->owner->get_object(KEY_WIELD)==o) return 0; } return 1; } static void rec_pit(MudObject *who, MudObject *pit, World<MudObject> *blah) { MudObject *o; int i; foreach(blah, o, i) { dotrap(E_ONDROPINPIT, who, o, pit); /* ::: drop_in_pit o1==object being pitted, o2==the pit; after messaging. called on contents of containers too. */ vanish(o); rec_pit(who, pit, o->children); } } NewWorld try_remove_obs(MudObject *who, NewWorld stuff) { MudObject *o; int i; NewWorld what = stuff; NewWorld notworn, already; for (int wl=5;wl>=0;wl--) { foreach((&what), o, i) { if (o->get_int("wornlevel",0)!=wl) { continue; } if (!is_worn(o)) { notworn.add(*o); what.remove(*o); i--; continue; } if (worn_on(who, wornon(o), o->get_int("wornlevel",0)+1)) { already.add(*o); what.remove(*o); i--; continue; } if (dotrap(E_BEFOREREMOVE, who, o)) { /* ::: before_remove o1==clothing; after it is known to be worn, and not under any other clothing that needs removing first. return 1 to abort */ what.remove(*o); i--; continue; } o->unset(KEY_WORNBY); } } fixup_lapels(who, &what); if (what.getsize()) { who->printf("You take off %s.\n", magiclist(what).c_str()); who->oprintf(cansee, "%#M %[takes off/take off] %s.\n", who, magiclist(what).c_str()); } if (already.getsize()) { who->printf("You are wearing clothes on top of %s.\n", magiclist(already).c_str()); } foreach((&what), o, i) { dotrap(E_AFTERREMOVE, who, o); /* ::: after_remove o1==clothing; after worn and messaging */ } NewWorld ok; foreach((&stuff), o, i) { if (!iswornby(o, who)) { ok.add(o); } } return ok; } void drop_obs(MudObject *who, NewWorld what, bool dothrow, bool docareful, TeleObject thrownat) { MudObject *o; int i; NewWorld autodie; MudObject * where = thrownat?thrownat.where:who->owner; MudObject *pit = !dothrow ? find_pit(where) : 0; MudObject *fl = floor(where); if (docareful) pit = 0; what = try_remove_obs(who, what); foreach((&what), o, i) { if (!is_droppable(o)) { who->printf("You cannot drop %Y.\n", o); what.remove(*o); i--; continue; } if (!dothrow && dotrap(E_ONDROPINHERE, who, where, o)) { /* ::: drop_in_here o1==this room, o2==object being dropped; before anything other than droppability testing, return 1 to abort */ what.remove(*o); i--; continue; } if (!pit) { if (!dothrow && dotrap(E_ONDROP, who, o, where)) { /* ::: drop o1==object being dropped, o2==this room; return 1 to abort */ what.remove(*o); i--; } else if (dothrow && (dotrap(E_ONTHROW, who, o, where)|| thrownat && (dotrap(E_BEFORETHROWAT, who, o, thrownat) ||dotrap(E_BEFORETHROWNWITH, who, thrownat, o)))) { /* ::: throw o1==missile, o2==this room; return 1 to abort */ /* ::: before_throw_at o1==missile, o2==target; return 1 to abort */ /* ::: before_thrown_with o1==target, o2==missile; return 1 to abort */ what.remove(*o); i--; } else set_owner(o, where); } else { if (dotrap(E_BEFOREPIT, who, o, pit)) { /* ::: before_pit o1==object about to be pitted, o2==the pit; return 1 to abort. not recursive - doesn't get called on objects inside containers that are to be pitted. */ what.remove(*o); i--; } else set_owner(o, "empty"); } } if (pit) { if (what.getsize()) { who->printf("You drop ^Z%s into %Y.\n", magiclist(what).c_str(), pit); who->oprintf(cansee, "%#M %[drops/drop] ^Z%s into %Y.\n", who, magiclist(what).c_str(), pit); rec_pit(who, pit, &what); } goto minis; return; } if (what.getsize()) { if (docareful && fl) { who->printf("You put ^Z%s on %P.\n", magiclist(what).c_str(), fl); who->oprintf(cansee, "%#M %[puts/put] ^Z%s on %P.\n", who, magiclist(what).c_str(), fl); } else if (dothrow) { if (thrownat) { if (thrownat!=who) { who->printf("You throw ^Z%s at %M.\n", magiclist(what).c_str(), &thrownat); thrownat->printf("%#M %[throws/throw] ^Z%s at you.\n", who, magiclist(what).c_str()); who->oprintf(cansee && avoid(thrownat), "%#M %[throws/throw] ^Z%s at %M.\n", who, magiclist(what).c_str(), &thrownat); } else { who->printf("You throw ^Z%s at yourself.\n", magiclist(what).c_str()); who->oprintf(cansee, "%#M %[throws/throw] ^Z%s at %s.\n", who, magiclist(what).c_str(), himself_or_herself(who)); } } else { who->printf("You throw ^Z%s.\n", magiclist(what).c_str()); who->oprintf(cansee, "%#M %[throws/throw] ^Z%s.\n", who, magiclist(what).c_str()); } } else { who->printf("You drop ^Z%s.\n", magiclist(what).c_str()); who->oprintf(cansee, "%#M %[drops/drop] ^Z%s.\n", who, magiclist(what).c_str()); } } foreach((&what), o, i) { if (!dothrow) dotrap(E_AFTERDROP, who, o); /* ::: after_drop o1==object dropped; after messaging, before specials */ else { /* ::: after_throw o1==missile; after messaging, before specials */ dotrap(E_AFTERTHROW, who, o); if (thrownat) { /* ::: after_throw_at o1==missile, o2==target; after messaging before specials */ dotrap(E_AFTERTHROWAT, who, o, thrownat); /* ::: after_thrown_with o1==target, o2==missile; after messaging before specials */ dotrap(E_AFTERTHROWNWITH, who, thrownat, o); } } } if (where->get_flag(FL_ONWATER) || where->get_flag(FL_UNDERWATER) || (where->get_flag(FL_BYWATER)&&who->get_flag(FL_SWIMMING))) { NewWorld floats; NewWorld sink; MudObject *seabed = where->get_object("seabed"); MudObject *surface = where->get_object("surface"); foreach((&what), o, i) { if (o->get_flag(FL_CANFLOAT)) { floats.add(*o); } else { sink.add(*o); } } if (floats.getsize()) { floats.get(0)->oprintf(cansee, "%#s %s%s.\n", magiclist(floats).c_str(), plural(floats)?"float": "floats", surface?" up to the surface of the water": where->get_flag(FL_ONWATER)?" on the surface of the water": ""); } if (sink.getsize()) { if (where->get_flag(FL_UNDERWATER)) sink.get(0)->oprintf(cansee, "%#s %s%s.\n", magiclist(sink).c_str(), plural(sink)?"sink": "sinks", seabed?"":" without a trace"); else sink.get(0)->oprintf(cansee, "%#s %s beneath the water%s.\n", magiclist(sink).c_str(), plural(sink)?"sink": "sinks", seabed?"":" without a trace"); } foreach((&floats), o, i) { if (surface) set_owner(o, surface); } foreach((&sink), o, i) { if (seabed) set_owner(o, seabed); else vanish(o); } } if (dothrow && where->get_flag(FL_NOGRAVITY) && who->owner->get_flag(FL_OUTDOORS) && who->owner->get_flag(FL_AIRLESS)) { if (what.getsize()) { what.get(0)->oprintf(cansee, "%#s %s off into space.\n", magiclist(what).c_str(), plural(what)?"drift":"drifts"); } foreach((&what), o, i) { vanish(o); } } foreach((&what), o, i) { if (o->get_flag(FL_NOGIVE)) { autodie.add(*o); } } if (autodie.getsize()) { autodie.get(0)->oprintf(cansee, "%#s self-destruct%s.\n", magiclist(what).c_str(), plural(what)?"":"s"); } foreach((&autodie), o, i) { vanish(o); } if (!docareful) { NewWorld frag; if (thrownat && thrownat->get_flag(FL_FRAGILE)) { frag.add(*thrownat); } foreach((&what), o, i) { if (o->get_flag(FL_FRAGILE)) { frag.add(*o); } } if (frag.getsize()) { frag.get(0)->oprintf(cansee, "%#s %s apart.\n", magiclist(frag).c_str(), plural(frag)?"smash":"smashes"); } foreach((&frag), o, i) { int j; MudObject *o2; foreach(o->children, o2, j) { set_owner(o2, o->owner); } vanish(o); } } minis: foreach((&what), o, i) { if (is_mission(o)) { o->oprintf(cansee, "%#Y %[vanishes/vanish].\n", o); set_owner(o, "@musicmud"); o->nuke_me = 0; o->unset(KEY_ACCEPTER); who->unset("mission"); return; } } } static bool strceq(const char *a, const char *b) { if (a==b) return true; if (!a || !b) return false; return strcasecmp(a,b)==0; } MudObject *find_object(MudObject *context, const char *name, bool shortcut) { if (!name) return 0; if (shortcut && strceq(name, "me")) return context; if (shortcut && strceq(name, "here")) return context->owner; if (shortcut && strceq(name, "home")) return context->get_object("start"); if (MudObject *m=planet->get(name)) return m; return 0; } MudObject *find_exit(MudObject *room, const char *name) { if (!name) return 0; MudObject *o; int i; foreach(room->children, o, i) { if (streq(o->get("short"), name) && (o->get_flag(FL_EXIT) || o->get_flag(FL_PARTEXIT))) return o; } return 0; } MudObject *saveloc(MudObject *who) { MudObject *where = who->owner; if (MudObject *h=where->get_object("home")) return h; if (where->get_flag(FL_STICKYROOM)) return where; if (where->owner && where->owner->get_flag(FL_STICKYROOM)) return where; if (MudObject* h=get_zonepropobj(where, "home")) return h; return MUD_DEFHOME; } MudObject *wornfrom(const MudObject *who) { if (!is_mobile(who)) return 0; MudObject *wf = archetype(who); if (who->get("wornfrom")) wf = who->get_object("wornfrom"); return wf; } MudObject *weapon(MudObject *who) { if (MudObject *o=who->get_object(KEY_WIELD)) { if (o->owner == who) return o; } else if (MudObject *wf=wornfrom(who)) { if (MudObject *o = wf->get_object(KEY_WIELD)) return o; } return 0; } MudObject *floor(MudObject *where) { if (!where->get_flag(FL_ROOM) && !where->get_flag(FL_SHIP)) return 0; MudObject *o; int i; foreach(where->children, o, i) { if (o->get_flag(FL_FLOOR)) return o; } for (i=0;i<where->array_size("tele");i++) { MudObject *o = where->array_get_object("tele", i); if (o && o->get_flag(FL_FLOOR)) return o; } if (where->get("floor")) { return where->get_object("floor"); } if (MudObject *fz = zoneof(where)) { if (fz->get("floor")) return fz->get_object("floor"); } if (where->get_flag(FL_NOGRAVITY) && where->get_flag(FL_OUTDOORS)) return 0; if (where->get_flag(FL_OUTDOORS)) { if (where->get_int("terrain")==6) return MUD_SURFACE; else return MUD_GROUND; } return MUD_FLOOR; } string abilities(MudObject *o) { wtype_t wty = (wtype_t)o->get_int("wtype"); int dam = o->get_int("damage"); const char *damstr = " little damage"; if (dam>5) damstr = " some damage"; if (dam>10) damstr = " a fair bit of damage"; if (dam>15) damstr = " quite a bit of damage"; if (dam>20) damstr = " a lot of damage"; if (dam>25) damstr = " lots of damage"; string wtstr=""; if (wty == W_IMPACT) wtstr = "impact weapon; does"; if (wty == W_CUTTING) wtstr = "cutting weapon; does"; if (wty == W_STABBING) wtstr = "stabbing weapon; does"; string provides=""; string protect=""; string ability=""; if (o->get_flag(FL_RADIATIONSUIT)) protect += " radiation,"; if (o->get_flag(FL_COLDPROTECT)) protect += " extreme cold,"; if (o->get_flag(FL_HEATPROTECT)) protect += " extreme heat,"; if (o->get_flag(FL_GILLS)) ability += " to breathe underwater,"; if (o->get_flag(FL_SPACESUIT)) ability += " to survive in a vacuum,"; if (o->get_flag(FL_NIGHTVISION)) ability += " to see in the dark,"; if (protect.length()) { provides = "protects from" + protect; } if (ability.length()) { if (provides.length()) { provides += " and "; } provides += "allows user"; provides += ability; } int arm = o->get_int("armour", 0); if (arm>0) { if (provides.length()) { provides += " and "; } const char *how = "minimal"; if (arm>2) how = "some"; if (arm>5) how = "fair"; if (arm>10) how = "good"; if (arm>20) how = "very good"; provides += how; provides += " protection in combat,"; } if (wtstr.length()) { if (provides.length()) provides = ssprintf("%s%s, %s", wtstr.c_str(), damstr, provides.c_str()); else provides = ssprintf("%s%s", wtstr.c_str(), damstr); } return provides; } const char *looknice(const char *c, NewWorld *blah) { if (!c) return "nowhere"; for (int i=0;i<pairs_n;i++) { if (streq(pairs[i].left, c)) return pairs[i].lnice; if (streq(pairs[i].right, c)) return pairs[i].rnice; } if (strncmp(c, "finger.", 7)==0) { int which = atoi(c+7); if (which >= 0 && which < 8) { return fingers[which]; } return "unknown finger"; } if (streq(c, "body,legs")) { return "body and legs"; } if (streq(c, "body,arms")) { return "body and arms"; } if (streq(c, "allover")) { if (!blah || blah->getsize()>1) { return "clothes"; } else { return "body"; } } return c; } const char *looknice(MudObject *o, NewWorld *blah) { return looknice(wornon(o), blah); } int serving(MudObject *what) { int sv = what->get_int("serving"); if (sv != -1) return sv; MudObject *em = what->get_object("empty"); if (em) return em->get_int("volume"); return -1; } int abv(MudObject *what) { if (what->get_object("substance")) what = what->get_object("substance"); int abv = what->get_int("abv"); if (abv != -1) return abv; int al = what->get_int("alcohol", 0); MudObject *em = what->get_object("empty"); if (!em) return 0; int vol = serving(what); if (vol < 1) return 0; return (al * 10000 / vol); } TeleWorld clothes(MudObject *who) { TeleWorld w; MudObject *o; int i; foreach(who->children, o, i) { if (iswornby(o, who)) w.add(*o, who); } MudObject *wf = wornfrom(who); if (wf) foreach(wf->children, o, i) { if (iswornby(o, wf) && !worn_on(who, wornon(o), o->get_int("wornlevel", 0))) { w.add(*o, who); } } return w; } void itell(MudObject *who, const char *str) { who->ilc++; char *a = strdup(str); char *p; char *b = strtok_r(a, ";", &p) ; while (b) { who->interpret(b); b = strtok_r(NULL, ";", &p); } strfree(a); who->ilc--; } const char *get_zoneprop(MudObject *orig, MudObject *where, const char *prop, NewWorld *sofar=0) { NewWorld s; if (!sofar) sofar = &s; sofar->add(where); if (where->get(prop)) { return where->get(prop); } if (MudObject *f=where->get_object("fwd")) { if (!sofar->get(f->id)) { return get_zoneprop(orig, f, prop, sofar); } } if (MudObject *s=where->get_object("ship")) { if (!sofar->get(s->id)) { return get_zoneprop(orig, s, prop, sofar); } } if (where->get_flag(FL_SHIP) && !sofar->get(where->owner->id)) { return get_zoneprop(orig, where->owner, prop, sofar); } MudObject *r = where; while (r && !r->get_flag(FL_ROOM)) { r = r -> owner; } if (r != where && r && !sofar->get(r->id)) { return get_zoneprop(r, r, prop, sofar); } if (const char *z=where->get("zone")) { MudObject *zo=getzone(z); if (zo && !sofar->get(zo->id)) return get_zoneprop(orig, zo, prop, sofar); } return where->get(prop); } int get_zonepropint(MudObject *orig, MudObject *where, const char *prop, int def, NewWorld *sofar=0) { NewWorld s; if (!sofar) sofar = &s; sofar->add(where); if (where->ints.find(prop)!=where->ints.end()) { return where->get_int(prop); } if (MudObject *f=where->get_object("fwd")) { if (!sofar->get(f->id)) { return get_zonepropint(orig, f, prop, def, sofar); } } if (MudObject *s=where->get_object("ship")) { if (!sofar->get(s->id)) { return get_zonepropint(orig, s, prop, def, sofar); } } if (where->get_flag(FL_SHIP) && !sofar->get(where->owner->id)) { return get_zonepropint(orig, where->owner, prop, def, sofar); } MudObject *r = where; while (r && !r->get_flag(FL_ROOM)) { r = r -> owner; } if (r != where && r && !sofar->get(r->id)) { return get_zonepropint(orig, r, prop, def, sofar); } if (const char *z=where->get("zone")) { MudObject *zo=getzone(z); if (zo && !sofar->get(zo->id)) return get_zonepropint(orig, zo, prop, def, sofar); } return def; } int get_zonepropint(MudObject *where, const char *prop, int def) { return get_zonepropint(where, where, prop, def); } const char *get_zoneprop(const char *o, const char *prop, const char *def) { MudObject *wh = planet->get(o); const char *r = get_zoneprop(wh, wh, prop); return r?r:def; } const char *get_zoneprop(MudObject *wh, const char *prop, const char *def) { const char *r = get_zoneprop(wh, wh, prop); return r?r:def; } bool has_rights(MudObject *who, MudObject *where) { return !dotrap(E_ONFORBIDDOCKING, who, where); /* ::: forbid_docking o1==which dock; return 1 to forbid /pl/ from docking a ship at /o1/ */ } int gid = 1; string genid(MudObject *fr) { if (fr) return ssprintf("@ship_%s_%i", fr->id, gid++); else return get_clone_name(); } void recurse_clone(MudObject *player, MudObject *from, MudObject *to, MudObject *ship, Mission *m) { MudObject *o; int i; from->set("!fakeid", to->id); foreach(from->children, o, i) if (!is_player(o) && (o->get_object("start")==from)) { MudObject *r = clone_object(o, to, player?genid(player).c_str():0); r->set("ship", ship->id); if (m) r->set_mission(m); else r->set("zone", "@ship"); recurse_clone(player, o, r, ship, m); } } static void fixup_prop(MudObject *from, const char *prop) { const char *ln2 = from->get(prop); if (ln2 && ln2[0]==':') { MudObject *ln = planet->get(ln2+1); if (ln && ln->get_object("!fakeid")) { from->setf(prop, ":%s", ln->get_object("!fakeid")->id); } } else { MudObject *ln = from->get_object(prop); if (ln && ln->get_object("!fakeid")) { from->set(prop, ln->get_object("!fakeid")->id); } } } void fixup_exits(MudObject *from) { fixup_prop(from, "link"); fixup_prop(from, "door"); fixup_prop(from, "doorsat"); fixup_prop(from, "ship"); for (int i=0;i<from->array_size("room");i++) { fixup_prop(from, ssprintf("room.%i", i).c_str()); } MudObject *o; int i; foreach(from->children, o, i) fixup_exits(o); } void remove_fakeids(MudObject *from) { from->unset("!fakeid"); MudObject *o; int i; foreach(from->children, o, i) remove_fakeids(o); }