/* * MusicMUD Daemon, version 1.0 * Copyright (C) 1999-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, writ<e to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include <string.h> #include <ctype.h> #include <unistd.h> #include "musicmud.h" #include "misc.h" #include "util.h" #include "rooms.h" #include "Player.h" #include "events.h" #include "trap.h" #include "pflags.h" #include "death.h" #include "Mission.h" #include "zoneload.h" #include "msi.h" #include "paths.h" #include "privs.h" #include "vsprintf.h" #include "prep.h" #include "units.h" #include "shared.h" #include "musictok.h" #include "format.h" #include "pos.h" #include "body.h" #include "levels.h" #include "missions.h" #include "nations.h" int mission_counter = 0; int overflow_counter = 1000; set<int> used; Mission::Mission(const char *i) : MudObject(i), mission_objs() { bool set = 0; for (int i=1;i<=900;i++) if (used.find((i+mission_counter)%900)==used.end()) { mission_counter = (i+mission_counter)%900; Mission::set("m_id", mission_counter+100); set = 1; break; } if (!set) { MudObject::set("m_id", overflow_counter); overflow_counter++; } set_flag(FL_MISSION, 1); used.insert(get_int("m_id")); } void Mission::add(MudObject *a) { mission_objs.add(*a); } void Mission::remove(MudObject *a) { mission_objs.remove(*a); } Mission::~Mission() { used.erase(get_int("m_id")); if (get_object("toreset")) { get_object("toreset")->reset(); } MudObject *o; int i; foreach((&mission_objs), o, i) { if (!o->get_flag(FL_SILENTQUIT)) { if (o->get("timeoutmsg")) o->oprintf(cansee, "%#M %s.\n", o, o->get("timeoutmsg")); else o->oprintf(cansee, "%#M departs.\n", o); } o->mission = 0; vanish(o); } } void empty_ship(MudObject *ship) { if (!ship) return; if (ship->get_object("ship")) ship = ship->get_object("ship"); int roomcount = ship->array_size("room"); for (int i=0;i<roomcount;i++) { MudObject *room = ship->array_get_object("room", i); if (!room) continue; MudObject *o; int i; foreach(room->children, o, i) { if (is_player(o) || (is_mobile(o) && (o->mission != ship->mission))) { set_owner(o, ship->owner); i--; o->printf("You are escorted from the ship.\n"); o->oprintf(cansee, "%#M %[is/are] escorted from the ship.\n", o); o->interpret("look"); } } } return; } void mission_cleanup(MudObject *m) { MudObject *o; int i; if (IS_OF(m, Mission)) { Mission *mission = (Mission*)m; foreach((&mission->mission_objs), o, i) { if (o->follows) o->interpret("leave"); } foreach((&mission->mission_objs), o, i) { empty_ship(m); } } m->nuke_me = 1; } bool quest_done(const MudObject *who, const string &id) { return who->quests.find(id)!=who->quests.end(); } bool quest_done(const MudObject *who, MudObject *qu) { string id = ssprintf("Quest%i", qu->get_int("miniid")+32); if (qu->get_flag(FL_QUEST) && qu->get("mname")) id = qu->get("mname"); if (qu->get_flag(FL_MISSION)) { id = qu->get("minitag"); } return who->quests.find(id)!=who->quests.end(); } void quest_set(MudObject *who, const string &id) { who->quests.insert(id); } void quest_unset(MudObject *who, const string &id) { who->quests.erase(id); } string nicepname(const char *id) { MudObject * p = planet->get(id); if (p) { return name(p)?:""; } return ssprintf("^p%#s^n", id); } void questrec(MudObject *who, MudObject *quest) { if (who->get_priv(PFL_IMMORTAL)) return; int at = quest->get_int("!acceptedat"); if (at != -1) { time_t secs = now - at; int rec = quest->get_int("$recordtime"); if (rec==-1) { quest->set("$recordtime", secs); quest->set("$recordholder", who->id); } else if (rec>secs) { quest->set("$recordtime", secs); quest->set("$recordholder", who->id); } } } void grant_quest(MudObject *who, MudObject *q, bool reward) { if (!is_player(who)) return; if (!q->get_flag(FL_QUEST)) { log(PFL_SEEINFO, 0, "mission", "trying to call grant_quest on a non-Quest %s", q->id); return; } const char *name = 0; if (q) name = q->get("mname"); if (!q) name = "???"; if (quest_done(who, q)) { who->printf("You have completed the ^G%s^n mission again.\n", name); broadcast(avoid(who), "%#M %[has/have] completed the ^G%s^n mission again.\n", who, name); } else { who->printf("Congratulations, you have completed the ^G%s^n mission.\n", name); broadcast(avoid(who), "%#M ^Y%[has/have] completed the ^G%s^Y mission.\n", who, name); } if (reward) { int value = q->get_int("questpoints", 0) * 200; if (!value) value = 500; MudObject *cur = currency(q); value = convertcash(value, 0, cur); cash_credit(who, cur, value); who->printf("You have been rewarded with %s.\n", formatcash(value, cur, 0)); } quest_set(who, q->get("mname")); if (q) questrec(who, q); if (q) { q->set_flag(FL_DONE, 1); q->set("$doneby", who->id); if (q->owner == who) vanish(q); } who->interpret("calc_level"); who->interpret("save"); } void fail_mission(MudObject *p, MudObject *m) { if (m->owner == p && is_player(p)) { if (m->get("mname")) { p->printf("You have mucked up the ^M%s^n mission.\n", m->get("mname")); log(p, PFL_SEEINFO, 0, "mission", "failed %s mission", m->get("mname")); } else { if (m->get("type")) log(p, PFL_SEEINFO, 0, "mission", "failed a %s mission", m->get("type")); p->printf("You have mucked up the mission.\n"); } if (m->get("zone")) p->printf("If you want to try it again, leave the area and dispose of all objects from it.\n"); set_owner(m, "empty"); if (p->get_object(KEY_ACCEPTED)==m) p->unset(KEY_ACCEPTED); } else { set_owner(m, "empty"); if (p->get("mname")) log(PFL_SEEINFO, 0, "mission", "%s mission failed", m->get("mname")); else if (p->get("type")) log(PFL_SEEINFO, 0, "mission", "a %s mission failed", m->get("type")); } } void grudge_mission(MudObject *p, MudObject *q) { grant_quest(p, q, 0); } void complete_mission(MudObject *p, MudObject *m) { if (!m) { p->printf("This is a bug in ^Wcomplete_mission^n, please report it.\n"); return; } if (m->get_flag(FL_QUEST)) { grant_quest(p, m, 1); return; } Mission *mis = dynamic_cast<Mission*>(m); if (!mis) { log(PFL_SEEINFO, 0, "mission", "trying to call complete_mission on a non-Mission %s", m->id); return; } empty_ship(m); int acc = p->get_object("mission")==m; if (!is_player(p)) { mission_cleanup(m); return; } if (acc) { int reward = (m->get_int("reward", 100)); p->unset("mission"); MudObject *cur = currency(m); reward = convertcash(reward, 0, cur); cash_credit(p, cur, reward); string quest_id = m->get("minitag"); if (!quest_done(p, quest_id)) { quest_set(p, quest_id); p->printf("You have been rewarded with ^Y1^n mission point and %s.\n", formatcash(reward, cur, 1)); log(p, PFL_SEEINFO, 0, "mission", "completed a ^G%s^n mission for the first time", m->get("type")); p->interpret("calc_level"); p->interpret("save"); } else { log(p, PFL_SEEINFO, 0, "mission", "completed a ^G%s^n mission again", m->get("type")); p->printf("You have been rewarded with ^Y%i^n %s.\n", reward, formatcash(reward, cur, 1)); } } else { log(PFL_SEEINFO, 0, "mission", "completed a ^G%s^n mission without having accepted it. not rewarding.", m->get("type")); } mission_cleanup(m); }