/* * MusicMUD - Minmissions Module * 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 <set> #include <list> #include "musicmud.h" #include "verbs.h" #include "util.h" #include "pflags.h" #include "Mission.h" #include "misc.h" #include "hooks.h" #include "trap.h" #include "events.h" #include "prep.h" #include "shared.h" #include "hooks.h" #include "nations.h" namespace minis { #define ARRAY_SIZE(a) (sizeof(a)/(sizeof((a)[0]))) #define MODULE "minis" //! Data about a minimission struct mini_t { string tag; int reward; const char *type; const char *zone; int flags; MudObject* obj; bool operator<(const mini_t &c) const { return strcmp(type, c.type)<0; } bool can() const { if (obj) return dotrap(E_ONMINICAN, obj, obj); /* ::: minican o1==the minimission template; return 1 to indicate that a minimission of this type can be created at the moment */ return 0; } void init(Mission *o) const { if (obj) { dotrap(E_ONMINICREATE, obj, obj, o); /* ::: minicreate o1==the minimission template, o2==the minimission; set up an instance of this minimission using o2 */ return; } } }; mini_t make_mini(MudObject *from) { mini_t m; if (const char *c=from->get("minitag")) m.tag = c; else m.tag = ssprintf("Quest%i", from->get_int("miniid")+32); m.reward = from->get_int("reward"); m.type = from->get("mname"); m.zone = from->get("mzone"); m.flags = from->get_flag(FL_PRIVATE); m.obj = from; return m; } static const char *niceboard(const char *q) { if (streq(q, "*") || !q) return "anywhere"; MudObject *z = getzone(q); if (z) return get_zoneprop(z, "planet", "somewhere"); return "somewhere"; } set<mini_t> get_minis(int p=1) { set<mini_t> minis; if (MudObject*m=planet->get("mini_zone")) { MudObject *o; int i; foreach(m->children, o, i) { if (o->get_object("start")!=m) continue; mini_t m = make_mini(o); if (p || !(m.flags&1)) minis.insert(m); } } return minis; } int count_minis() { return get_minis(0).size(); } int done_minis(const MudObject *o) { set<mini_t> m = get_minis(0); int y =0; for (set<mini_t>::iterator i=m.begin();i!=m.end();i++) { if (quest_done(o, i->tag)) { y++; } } return y; } static bool mini_lookup(const char *name, mini_t *min) { set<mini_t> m = get_minis(); for (set<mini_t>::iterator i=m.begin();i!=m.end();i++) { if (streq(i->type, name)) { *min = *i; return 1; } } return 0; } static bool verb_minis(MudObject *who, int argc, const char **argv) { MudObject *whose = who; if (argc > 1) { whose = get_player(who, argv[1]); if (!whose) { who->printf("Can't find : %s.\n", argv[1]); return true; } if (whose != who && !who->get_priv(PFL_SEESTATS)) { who->printf("You cannot do that on others.\n"); return true; } if (is_mobile(whose)) { who->printf("%#M is a mobile, and is too lazy to do missions.\n", whose); return true; } } set<mini_t> minis = get_minis(); set<mini_t>::iterator mi = minis.begin(); list<Mission*> missions; MudObject *o; int i; foreach(planet, o, i) if (Mission *m=dynamic_cast<Mission*>(o)) missions.push_back(m); if (who->get_priv(PFL_MINIMISSIONS)) { who->printf("%-15s %-12s %-12s %5s %7s %s %s\n", "ID", "Type", "Board", "Count", "Reward", "Done ", "Can?"); who->printf("^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-\n"); while (mi != minis.end()) { int count = 0; for (list<Mission*>::iterator mit = missions.begin();mit!=missions.end();mit++) { if ((*mit)->get_object("instance")==mi->obj) { count++; } } who->printf("%-15s %-12s %-12s %3i %7s %s%s %s\n", mi->obj->id, mi->type, niceboard(mi->zone), count++, formatvalue(mi->reward, currency(who), 0), quest_done(whose, mi->tag)?"done ":" ", mi->can()?"yes ":"no ", (mi->flags & 1)?"(^rNot open^n)":""); mi++; } return true; } who->printf(" %-12s %-12s %7s %s\n", "Type", "Board", "Reward", "Done "); who->printf("^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-\n"); while (mi != minis.end()) { if (mi->flags & 1) { mi++; continue; } who->printf(" %-12s %-12s %6s %s\n", mi->type, niceboard(mi->zone), formatvalue(mi->reward, currency(who), 0), quest_done(whose, mi->tag)?"done ":" "); mi++; } return true; } static Mission *allocate(MudObject *who, MudObject *board, mini_t *mini) { mini_t mymini; set<mini_t> minis = get_minis(); if (!mini) { set<mini_t> possibles; set<mini_t>::iterator it = minis.begin(); while (it != minis.end()) { if (it->flags & 1) { it++; continue; } if (it->can()) possibles.insert(*it); it++; } it = possibles.begin(); while (it != possibles.end()) { it++; } if (possibles.empty()) return 0; int n = random_number(possibles.size()); it = possibles.begin(); while (n) { it++; n--; } mymini = *it; mini = &mymini; } if (!mini->can()) { who->printf("Can't allocate a minimission of that type.\n"); return 0; } Mission *m = new Mission(get_clone_name().c_str()); planet->add(*m); m->set("mass", 50); m->set("short", "mission"); m->set("name", "a ^omission^n"); m->set_flag(FL_DESTROYONRESET, 1); m->set("minitag", mini->tag); m->set("deadline", now); m->set("treatas","mini_ticktock_1"); m->set("reward", mini->reward); m->set("type", mini->type); m->set("bzone", mini->zone); if (mini->obj) m->set("instance", mini->obj->id); set_owner(m, board); mini->init(m); if (!m->get("desc")) { who->printf("It didn't stick. Destroying.\n"); set_owner(m, mud); m->nuke_me = 1; return 0; } return m; } static bool verb_mmadd(MudObject *who, int argc, const char **argv) { if (who->get_flag(FL_SLEEPING)) { who->printf("You toss and turn in your sleep.\n"); who->oprintf(cansee, "%#M tosses and turns in %s sleep.\n",who, his_or_her(who)); return true; } MudObject *board = get_flagged_object(who->owner, FL_MISSIONSBOARD); if (!board) { who->printf("No board here.\n"); return true; } if (MudObject *b=board->get_object("board")) { board = b; } who->interpret("mmtimeout"); mini_t m; mini_t *pm = 0; if (argc > 1) { if (!mini_lookup(argv[1], &m)) { who->printf("Unknown mini type.\n"); return true; } pm = &m; } if (board->children->getsize()>board->get_int("max", 4) && !pm) { who->printf("Board full.\n"); return true; } if (Mission *mis=allocate(who, board, pm)) { who->interpret("emote places a notice on the ^omissions^n board."); who->printf("The briefing is: \n%s\n", mis->get("desc")); } return true; } } using namespace minis; #define CLEANUP COUNT_MINIS = 0; DONE_MINIS = 0; #include "verbmodule.h" void startup() { COUNT_MINIS = count_minis; DONE_MINIS = done_minis; AUTO_VERB(mmadd, 5, 0, PFL_MINIMISSIONS); AUTO_VERB(minis, 5, 0, PFL_NONE); }