/* * MusicMUD - Dynamic Reset System * 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 "musicmud.h" #include "verbs.h" #include "misc.h" #include "util.h" #include "events.h" #include "trap.h" #include "pflags.h" #include "startup.h" #include "flagnames.h" #define MODULE "dynreset" static MudObject *link(MudObject *ext) { MudObject *dest = ext->get_object("link"); if (!dest) { return 0; } if (ext->get_flag(FL_NEVEROBSERVED)) return 0; return dest; } static void mark_observed(MudObject *o, MudObject *tainter, int linksaway=2) { if (o->get_flag(FL_OBSERVED)) return; if (o->get_flag(FL_NEVEROBSERVED)) return; o->set_flag(FL_OBSERVED, 1); o->set("!tainter", tainter->id); MudObject *m; int i; foreach(o->children, m, i) { mark_observed(m, tainter); } if (linksaway) { foreach(o->children, m, i) { if (MudObject *d=link(m)) { mark_observed(d, tainter, linksaway-1); } } } } static bool object_touched(MudObject *o) { if (o->get_flag(FL_SHIP)) return false; if (o->get_flag(FL_DONE) || o->get_flag(FL_TAMPERED)) { #ifdef DEBUG_DYNRESET log(PFL_SEEINFO, 0, "debug", "%s done/tampered", o->id); #endif return true; } for (Flag i=FL_FIRST;i<FL_MAX;i++) if (i != FL_OBSERVED && i != FL_TIMER) if (o->get_flag(i) != o->get_rflag(i)) { #ifdef DEBUG_DYNRESET log(PFL_SEEINFO, 0, "debug", "%s flag on %s has changed", flag_names[i], o->id); #endif return true; } int is = o->get_int("initstate"); int st = state(o); if (is != -1 && st != -1 && st != is) { #ifdef DEBUG_DYNRESET log(PFL_SEEINFO, 0, "debug", "initstate(%i) of %s differs from current state(%i)", is, o->id, st); #endif return true; } if (!o->get_flag(FL_WANDER)) { if (o->owner && o->get("start") && (planet->get(o->get("start")) != o->owner)) { #ifdef DEBUG_DYNRESET log(PFL_SEEINFO, 0, "debug", "non-wandering %s has moved from start location", o->id); #endif return true; } } if (o->owner == MUD_MOBILEHEAVEN) return true; int max = o->get_int("initstrength", o->get_int("maxstrength")); int s = o->get_int("!strength"); if (max != -1 && s != -1 && max != s) { #ifdef DEBUG_DYNRESET log(PFL_SEEINFO, 0, "debug", "strength of %s has changed", o->id); #endif return true; } return false; } static const char *relationship(MudObject *what, MudObject *who) { if (!what || !who) return "is observed by"; if (who->owner == what) return "contains"; MudObject *k = what; while (k) { if (k==who) return "is carried by"; k = k->owner; } return "is observed by"; } static MudObject *get_mudzone(const char *txt) { char name[256]; sprintf(name, "%s_zone", txt); return planet->get(name); } static string ingreen(MudObject *o) { string s = "^G"; if (o->id) s += o->id; s += "^g"; return s; } static string mname(MudObject *o) { string s = "^M"; if (o->get("mname")) s += o->get("mname"); s += "^i"; return s; } static bool verb_dynreset(MudObject *a, int argc, const char **) { int zones_reset = 0, unsafe=0; if ((!a->get_priv(PFL_RESET) && a->get_int("$blissed")<=now) && !a->ilc) { a->printf("You can't do that.\n"); return true; } FILE *f = 0; if (is_mobile(a)) { f = xopen(DATA_INFO, "dynreset2.i", "w+"); a->file_divert(f); } { MudObject *o; int i; foreach(planet, o, i) o->set_flag(FL_OBSERVED, 0); } { Player *p; int i; foreach(players, p, i) if (p->owner && p->get_flag(FL_LOGGEDIN)) { mark_observed(p->owner, p); } } NewWorld resetted; NewWorld quests; MudObject *zone; int i; foreach(zones, zone, i) if (!zone->get_flag(FL_NORESET)) { if (!streq(zone->id, "@auto") && !streq(zone->id, "@ship")) { bool do_it = true; bool touched = false; MudObject *o, *failer = 0, *touchee = 0; int i2; foreach(zone->children, o, i2) { if (o->get_flag(FL_NORESET)) continue; if (!o->get_flag(FL_NOSAVE)) { bool this_touched = object_touched(o); if (this_touched) { touched = true; if (!touchee) touchee = o; } if (touched) { MudObject *mz = get_mudzone(zone->id); if (mz) { MudObject * q = mz->get_object("quest"); if (q) { q->set_flag(FL_TAMPERED, 1); } } } } if (o->get_flag(FL_OBSERVED)) { failer = o; do_it = false; } if (o->get_flag(FL_ALWAYSOBSERVED)) { failer = o; do_it = false; } if (!do_it && touched) break; } if (!touched) { //a->printf("untouched\n"); } else { a->printf("%-20s : ", zone->id); if (do_it) { if (argc>1) { doreset(zone->id, true); zones_reset++; a->printf("^Greset because of %s (%s %i)^n\n", touchee->id, touchee->owner->id, state(touchee)); resetted.add(*zone); MudObject *mz = get_mudzone(zone->id); if (mz) { MudObject * q = mz->get_object("quest"); if (q && !q->get_flag(FL_PRIVATE) && !quests.contains(q)) quests.add(*q); } } else { a->printf("^Gsafe^n\n"); } } else { if (failer) { const char *tstr = failer->get("!tainter"); MudObject *someone = 0; if (tstr) { someone = planet->get(tstr); } a->printf("^Runsafe^n (%s %s %s)\n", failer->id, relationship(failer, someone), someone ? someone->get("name") : "Someone"); } else a->printf("^Runsafe^n\n"); unsafe++; } } a->send_data(); } } if (resetted.getsize()) broadcast(!getflag(FL_NORESET) && minlev(LEV_COMMANDER), "^Y[^GDYNRESET^g: %s by %s^Y]\n", magiclist(resetted, ingreen).c_str(), a->get("name")); MudObject *smith = MUD_ANNOUNCER; if (smith && quests.getsize()) { smith->interpretf("%s The %s mission%s now available.", MUD_ANNCHMIS, magiclist(quests, mname).c_str(), quests.getsize()==1?" is":"s are"); } a->printf("%i out of %i zones reset. (%i unsafe to reset.)\n", zones_reset, zones->getsize(), unsafe); MudObject *o; foreach(planet, o, i) o->set_bflag(FL_OBSERVED, 0); if (f) { if (zones_reset) rename(DATA_INFO"/dynreset2.i", DATA_INFO"/dynreset.i"); a->file_undivert(); xclose(f); } return true; } #include "verbmodule.h" void startup() { AUTO_VERB(dynreset, 4, 0, PFL_NONE); }