/* * MusicMUD - Equipment 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 <stdio.h> #include "musicmud.h" #include "verbs.h" #include "State.h" #include "events.h" #include "flags.h" #include "misc.h" #include "pflags.h" #include "vsprintf.h" #include "trap.h" #include "shared.h" #include "match.h" #include "msi.h" #include "href.h" #include "body.h" #include "nations.h" #include <list> #include <vector> #include <algorithm> #define WORNLEVEL 5 #define MODULE "equipment" static inline bool is_fillable(MudObject *o) { return o->get_flag(FL_WATERTIGHT); } static string tobodyloc(string a) { for (int i=0;i<pairs_n;i++) { if (streq(pairs[i].lnice, a.c_str())) return pairs[i].left; if (streq(pairs[i].rnice, a.c_str())) return pairs[i].right; } for (int i=0;i<8;i++) { if (streq(fingers[i], a.c_str())) { return ssprintf("finger.%i", i); } } return a; } static const char *fwornon(MudObject *o) { const char *a = wornon(o); if (streq(a, "body,legs")) return "body"; return a; } static void show_containers(MudObject *who, MudObject *qui, string spaces, int brief) { NewWorld empties; MudObject *o; int i; foreach(qui->children, o, i) { if (!o->get_flag(FL_CONTAINER)) continue; if ((!o->get_flag(FL_STATED) && !o->get_flag(FL_TRANSPARENT)) && state(o)!=0) continue; NewWorld blah; int j; MudObject *p; foreach(o->children, p, j) if (!p->get_flag(FL_EXIT)) { blah.add(*p); } if (blah.getsize()) { if (brief) who->printf("^Z%#M %[holds/hold] %W.\n", o, &blah); else who->printf("%s^Z%M %[holds/hold] %W.\n", spaces.c_str(), o, &blah); } else { if (o->array_size("$fill") == 1) { MudObject *fill = o->array_get_object("$fill", 0); if (fill) { if (brief) who->printf("^Z%#M %[holds/hold] %s.\n", o, fill->get("short")); else who->printf("%s^Z%M %[holds/hold] %s.\n", spaces.c_str(), o, fill->get("short")); continue; } } empties.add(*o); } show_containers(who, o, spaces+" ", brief); } if (empties.getsize()) { if (!brief) who->printf("%s^Z%W %s empty.\n", spaces.c_str(), &empties, plural(empties)?"are":"is"); else who->printf("^Z%#W %s empty.\n", &empties, plural(empties)?"are":"is"); } } string andize(const vector<string> &v) { string tmp; size_t n = 0; iforeach(s, v) { n++; if (tmp.length()) if (n==v.size()) tmp += " and "; else tmp += ", "; tmp += *s; } return tmp; } static bool verb_equipment(MudObject *who, int argc, const char **argv) { MudObject *o; int i; int count=0; int brief = 0, isinv = 0; MudObject *qui = who; // int isinv = argv[0][0]=='i'; if (argv[0][0]=='i') { isinv = 1; } if (argv[0][0]=='q') { isinv = 1; brief = 1; } fixup_lapels(who, NULL); if (who==qui) if (who->get_flag(FL_SLEEPING)) { who->printf("^YIt's all gone!! ^nOh no, you were dreaming.\n"); return true; } if (who->get_priv(PFL_GOTO) && argc > 1) { qui = get_player(who, argv[1]); if (!qui) { who->printf("View the equipment of who?\n"); return true; } } if (!isinv || !who->get_flag(FL_NOINVWORN)) { MudObject *m = mount(qui); const char *white = brief?"":"^W"; if (m) { const char *riding = m->get("riding_verb"); if (!riding) riding = "riding"; string c, e; make_href(who, m, c, e); who->printf("%s%#P%s %[is/are] %s %s%M%s%s.^n\n", white, qui, white, riding, c.c_str(), m, e.c_str(), white); } if (!brief) { who->spec_printf("^W%#P^W %[is/are] wearing...^n\n", qui); #define ARRAY_SIZE(a) (sizeof(a)/(sizeof((a)[0]))) static const char *order[] = { "allover", "head","ears","leftear","rightear","eyes","lefteye","righteye","neck", "back","body","lapel", "arms","leftarm","rightarm", "wrists","leftwrist","rightwrist", "hands","lefthand","righthand", "thumbs","leftthumb","rightthumb", "finger.0", "finger.2","finger.4","finger.6", "finger.1","finger.3","finger.5","finger.7", "legs","leftleg","rightleg", "feet","leftfoot","rightfoot","*", }; TeleWorld worn2 = clothes(qui); NewWorld realworn; for (i=0;i<worn2.getsize();i++) realworn.add(*worn2.get_nth(i)); NewWorld worn = realworn; for (size_t j=0;j<ARRAY_SIZE(order);j++) { for (int k=0;k<=WORNLEVEL;k++) { foreach((&worn), o, i) { if (!streq(fwornon(o), order[j])) continue; if (o->get_int("wornlevel", 0)!=k) continue; string provides; if (!isinv) { provides = abilities(o); if (provides.length()) { provides = " (^Z" + provides; provides.erase(provides.length()-1); provides += ")"; } } const char *nam = o->get("name"); if (nam && strncmp(nam, "a pair of ", strlen("a pair of "))==0) { nam += strlen("a pair of "); } if (nam && strncmp(nam, "some ", strlen("some "))==0) { nam += strlen("some "); } string c, e; make_href(who, o, c, e); const char *on = streq(looknice(o, &realworn), "clothes")?"over":"on"; who->printf(" ^Z%s%s%s %s %s %s%s\n", c.c_str(), nam, e.c_str(), on, who==qui?"your":his_or_her(qui), looknice(o, &realworn), provides.c_str()); worn.remove(*o); i--; count++; } } } foreach((&worn), o, i) { string provides; if (!isinv) { provides = abilities(o); if (provides.length()) { provides = " (^Z" + provides; provides.erase(provides.length()-1); provides += ")"; } } const char *on = streq(looknice(o, &realworn), "clothes")?"over":"on"; who->printf(" ^Z%M %s %s %s%s\n", o, on, who==qui?"your":his_or_her(qui), looknice(o, &realworn), provides.c_str()); } if (!count) { who->cancel_printf(); if (!isinv) { who->printf("^W%#P^W %[is/are] not wearing anything.^n\n", qui); } } } else { TeleWorld worn2 = clothes(qui); NewWorld realworn; for (i=0;i<worn2.getsize();i++) realworn.add(*worn2.get_nth(i)); NewWorld worn = realworn; if (worn.getsize()) who->printf("%#P %[is/are] wearing %w.\n", qui, &worn); else who->printf("%#P %[is/are] not wearing anything.\n", qui); } if (MudObject *wielded = qui->get_object(KEY_WIELD)) { if (wielded->owner == qui) { string wtstr=""; if (!isinv) { wtype_t wty = (wtype_t)wielded->get_int("wtype"); int dam = wielded->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"; if (wty == W_IMPACT) wtstr = " (^Zimpact weapon; does"; if (wty == W_CUTTING) wtstr = " (^Zcutting weapon; does"; if (wty == W_STABBING) wtstr = " (^Zstabbing weapon; does"; if (wtstr.length()) { wtstr += damstr; wtstr += ")"; } } string c, e; make_href(who, wielded, c, e); who->printf("%s%#P%s %[is/are] wielding %s%M%s%s^n.\n", white, qui, white, c.c_str(), wielded, e.c_str(), wtstr.c_str()); count++; } } } if (isinv) { NewWorld stuff; MudObject *wi = qui->get_object(KEY_WIELD); MudObject *mo = mount(qui); foreach(qui->children, o, i) { if (!iswornby(o, qui) && o != wi && o != mo) { stuff.add(*o); } } if (brief) { list<MudObject*> l; World<MudObject> nat = nations(0); iforeach(n, nat) if (hascurr(n)) { int amt = cash(qui, n); if (amt) { MudObject *nu = new MudObject("^tmp"); nu->set("name", formatcash(amt, n, 0)); l.push_back(nu); stuff.add(nu); } } if (stuff.getsize()) { who->printf("%#P %[is/are] carrying %w.\n", qui, &stuff); } else { who->printf("%#P %[is/are] not carrying anything.\n", qui, &stuff); } iforeach(m, l) delete *m; } else { who->spec_printf("^W%#P^W %[is/are] carrying...^n\n", qui); if (int s=qui->array_size("$card")) { extern int unisuits[]; vector<int> str[4]; for (int i=0;i<s;i++) { int card = qui->array_get_int("$card", i); if (card>=0 && card<=51) { int suit = card/13; str[suit].insert(str[suit].end(), card%13); } } for (int i=0;i<4;i++) { if (str[i].size()) { sort(str[i].begin(), str[i].end()); string rst = ""; vector<int>::iterator it; const char *val = "A23456789TJQK"; for (it=str[i].begin();it!=str[i].end();it++) { rst += val[*it]; } who->printf(" ^Z^%c^#%i;^n %s\n", i&1?'R':'W',unisuits[i], rst.c_str()); } } count++; } map<string, int> m; map<string, string> plu; foreach((&stuff), o, i) { const char *n = name(o); if (!n) continue; if (m.find(n)!=m.end()) { m[n] = m[n] + 1; } else m[n] = 1; if (name(o, 1) && plu.find(n)==plu.end()) { plu[n] = name(o, 1); } } map<string, int>::iterator it = m.begin(); while (it != m.end()) { string ph = it->first; const char *num = ""; if (it->second != 1) { ph = plural_phrase(remove_articles(ph.c_str())); if (plu.find(it->first)!=plu.end()) { ph = plu.find(it->first)->second; } num = numbertostring(it->second); } who->printf(" ^Z%s%s%s\n", num, *num?" ":"", ph.c_str()); it++; count++; } World<MudObject> nat = nations(0); vector<string> s; iforeach(n, nat) if (hascurr(n)) { int amt = cash(qui, n); if (amt) s.push_back(formatcash(amt, n, 0)); } if (s.size()) { string a = andize(s); who->printf(" ^Z%s in cash\n", a); count++; } who->cancel_printf(); } if (!brief) { if (who==qui) who->spec_printf("^WYour containers...^n\n"); else who->spec_printf("^W%#P^W's containers...^n\n", qui); } show_containers(who, qui, " ", brief); who->cancel_printf(); if (!brief && !count) { who->printf("^W%#P^W %[is/are] not carrying anything.^n\n", qui); } #ifdef INVSLOTS who->printf("%#P %[has/have] %i free inventory slots.\n", qui, freehands(qui)); #endif } return true; } extern MudObject *worn_on(MudObject *by, const char *what, int wol); extern MudObject *worn_provides(MudObject *who, const char *what); static int havelimb(MudObject *who, const char *whichlimb) { return who->get_int(ssprintf("b.%s", whichlimb).c_str(), 1); } static void wear_obs(MudObject *who, NewWorld what, string loc) { NewWorld already; NewWorld cant, cantthere; NewWorld already2, a3; MudObject *o; int i; int healing = 0; for (int wl=0;wl<=WORNLEVEL;wl++) { foreach((&what), o, i) { int wol = o->get_int("wornlevel", 0); if (wol != wl) continue; if (is_worn(o)) { already.add(*o); what.remove(*o); i--; continue; } if (dotrap(E_BEFOREWEAR, who, o)) { /* ::: before_wear o1==clothing; after already wearing check. return 1 to abort. */ what.remove(*o); i--; continue; } if (who->get_object(KEY_WIELD)==o && o->get_int("damage")==-1) { who->printf("You can't wear %Y as you are already wielding %s.\n", o, it_them(o)); what.remove(*o); i--; continue; } const char *wo = o->get("wornon"); if (!wo) { cant.add(*o); what.remove(*o); i--; continue; } if (loc.length()) { // If we specified a place to wear it. const char *can = wo; wo = 0; if (streq(can, loc.c_str())) { wo = can; } for (int j=0;j<pairs_n;j++) { if (streq(can, pairs[j].single) && streq(loc.c_str(), pairs[j].left)) wo = pairs[j].left; if (streq(can, pairs[i].single) && streq(loc.c_str(), pairs[j].right)) wo = pairs[j].right; } if (streq(can, "limb")) { if (streq(loc.c_str(), "leftarm")) wo = "leftarm"; if (streq(loc.c_str(), "leftleg")) wo = "leftleg"; if (streq(loc.c_str(), "rightarm")) wo = "rightarm"; if (streq(loc.c_str(), "rightleg")) wo = "rightleg"; } if (streq(can, "legs") && wol==0 && streq(loc.c_str(), "head")) { wo = "head"; /* NB : Underpants can be worn on the head */ } if (streq(can, "finger")) { for (int fn=0;fn<8;fn++) { static char f[10]; sprintf(f, "finger.%i", fn); if (streq(f, loc.c_str())) { wo = f; break; } } } if (!wo) { cantthere.add(*o); what.remove(*o); i--; continue; } } if (streq(wo, "limb")) { if (!worn_on(who, "leftarm", wol)) wo = "leftarm"; else if (!worn_on(who, "rightarm", wol)) wo = "rightarm"; else if (!worn_on(who, "leftleg", wol)) wo = "leftleg"; else if (!worn_on(who, "rightleg", wol)) wo = "rightleg"; } for (int p = 0;p<pairs_n;p++) { if (streq(wo, pairs[p].single)) { if (!worn_on(who, pairs[p].left, wol) && havelimb(who, wo)) wo = pairs[p].left; else wo = pairs[p].right; } if (streq(wo, pairs[p].both)) { int hl = havelimb(who, pairs[p].left); int hr = havelimb(who, pairs[p].right); if (!hl && !hr) { who->printf("You have no %s.\n", looknice(pairs[p].both)); what.remove(*o); i--; goto dontwear; } if (!hl) { who->printf("You have no %s.\n", looknice(pairs[p].left)); what.remove(*o); i--; goto dontwear; } if (!hr) { who->printf("You have no %s.\n", looknice(pairs[p].right)); what.remove(*o); i--; goto dontwear; } } } char f[10]; if (streq(wo, "finger")) { for (int fn=0;fn<8;fn++) { sprintf(f, "finger.%i", fn); if (!worn_on(who, f, wol) && havelimb(who, wo)) { wo = f; break; } } if (streq(wo, "finger")) { wo = "finger.0"; } } MudObject *b = worn_on(who, "body", 0); if (streq(wo, "lapel") && !b) { cant.add(*o); what.remove(*o); i--; continue; } const char *needs = o->get("needs"); if (needs) { b = worn_provides(who, needs); if (!b) { cant.add(*o); what.remove(*o); i--; continue; } } if ((!streq(wo, "lapel") && worn_on(who, wo, wol))) { already2.add(*o); what.remove(*o); MudObject *o = worn_on(who, wo, wol); if (!a3.get(o->id)) { a3.add(*o); } i--; continue; } int h = o->get_int("heal", 0); healing += h; if (h != 0) { vanish(o); } else { o->set(KEY_WORNBY, who->id); o->set("$wornon", wo); } } dontwear:; } if (what.getsize()) { if (loc.length()) { who->printf("You put %s on your %s.\n", magiclist(what).c_str(), looknice(loc.c_str())); who->oprintf(cansee, "%#M %[puts/put] %s on %s %s.\n", who, magiclist(what).c_str(), his_or_her(who), looknice(loc.c_str())); } else { who->printf("You put on %s.\n", magiclist(what).c_str()); who->oprintf(cansee, "%#M %[puts on/put on] %s.\n", who, magiclist(what).c_str()); } set_prons(who, what); } foreach((&what), o, i) { dotrap(E_AFTERWEAR, who, o); /* ::: after_wear o1==clothing; after worn and messaging */ } if (cant.getsize()) { who->printf("You can't wear %s.\n", magiclist(cant).c_str()); } if (cantthere.getsize()) { who->printf("You can't wear %s on your %s.\n", magiclist(cantthere).c_str(), looknice(loc.c_str())); } if (already.getsize()) { who->printf("You are already wearing %s.\n", magiclist(already).c_str()); } if (already2.getsize() && a3.getsize()) { if (loc.length()) { who->printf("You are already wearing %s on your %s.\n", magiclist(a3).c_str(), looknice(loc.c_str())); } else { who->printf("You are already wearing %s where you would put %s.\n", magiclist(a3).c_str(), magiclist(already2).c_str()); } } #define MIN(a,b) ((a<b)?(a):(b)) #define KEY_MAXSTRENGTH "maxstrength" if (healing) { set_strength(who, MIN(who->get_int(KEY_STRENGTH, 0)+healing, who->get_int(KEY_MAXSTRENGTH))); who->printf("You feel slightly healed.\n"); } } static bool is_worn(const TeleObject &o) { return is_worn(o.what); } static bool is_wearable(const TeleObject &o) { if (o->get("wornon") && !is_worn(o) && o->get_int("heal",0)==0) { return 1; } return 0; } static bool verb_wear(MudObject *who, int argc, const char **argv) { if (wf_wears_with_flag(who, FL_HANDSTIED)) { who->printf("Your hands are tied!\n"); return true; } if (argc < 2) { who->printf("Wear what?\n"); return true; } int next=0; NewWorld what = match(who, argc-1, argv+1, is_wearable, LOOK_INV|IGNORE_EXITS, &next); string where = ""; if (streq(argv[next+1], "on")) { where = tobodyloc(the_rest(argc, argv, next+2)); } if (!what.getsize()) { if (what.all_nothing==1) { who->printf("You aren't carrying anything.\n"); } else if (what.all_nothing==0) { who->printf("You aren't carrying anything like that.\n"); } else if (what.all_nothing==103) { who->printf("Wear any what?\n"); } else { who->printf("You have nothing to wear.\n"); } return true; } wear_obs(who, what, where); return true; } static void remove_obs(MudObject *who, NewWorld what) { MudObject *o; int i; NewWorld notworn, already; for (int wl=WORNLEVEL;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()); set_prons(who, what); } if (notworn.getsize()) { who->printf("You aren't wearing %s.\n", magiclist(notworn).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 */ } } static bool verb_remove(MudObject *who, int argc, const char **argv) { if (argc < 2) { who->printf("Remove what?\n"); return true; } if (wf_wears_with_flag(who, FL_HANDSTIED)) { who->printf("Your hands are tied!\n"); return true; } NewWorld what = match(who, argc-1, argv+1, is_worn, LOOK_INV|IGNORE_EXITS); if (!what.getsize()) { if (what.all_nothing==1) { who->printf("You aren't wearing anything.\n"); } else if (what.all_nothing==0) { who->printf("You aren't wearing anything like that.\n"); } else if (what.all_nothing==103) { who->printf("Remove any what?\n"); } else { who->printf("You aren't wearing anything.\n"); } return true; } remove_obs(who, what); return true; } TeleObject tsaton(MudObject *o) { MudObject *s = o->get_object(KEY_SITON); int n = o->get_int(KEY_SITONN, 0); return TeleObject(o->owner, s, n); } static NewWorld sitters(const TeleObject &what) { NewWorld w; if (!what) return w; MudObject *o; int i; foreach(what.where->children, o, i) { if (tsaton(o)==what) w.add(*o); } return w; } static int sitters_n(const TeleObject &what) { return sitters(what).getsize(); } static int sitters_max(MudObject *what) { if (what->get_flag(FL_ONEPERSON)) return 1; if (what->get_flag(FL_TWOPERSON)) return 2; return -1; } static bool is_sittable(const TeleObject &what) { return sitters_n(what) < sitters_max(what.what); } static bool verb_sit(MudObject *player, int argc, const char **argv) { if (player->get("_fighting")) { player->printf("You can't sit during a fight!\n"); return true; } if (player->get_flag(FL_NOLEGS)==1) { player->printf("You can't sit as you have no legs.\n"); return true; } if (player->get_flag(FL_SITTING)==1) { player->printf("You are already sitting.\n"); return true; } if (MudObject *m=mount(player)) { if (m->get_flag(FL_NOSADDLE)) { player->interpret("dismount"); } else { player->printf("You are already sitting %s %Y.\n", m->get("saddleof")?m->get("saddleof"):"in the saddle of", m); return true; } } if (player->get_flag(FL_SLEEPING)==1) { player->printf("You toss and turn in your sleep.\n"); return true; } if (player->get_flag(FL_FLYING)) { player->printf("Try landing first.\n"); return true; } if (dotrap(E_ONSITINROOM, player, player->owner, 0, 0)) /* ::: sit_in_room o1==room; before anything; return 1 to abort */ return true; MudObject *o=0; int n=0; MudObject *fl = floor(player->owner); if (argc>1) { TeleWorld m = multi_match(player, argc-1, argv+1, is_sittable, LOOK_ROOM|IGNORE_EXITS); if (m.getsize()>1) { player->printf("You can only sit on one thing at a time.\n"); return true; } else if (m.getsize()==0) { player->printf("Sit on what?\n"); return true; } o = m.get_nth(0); n = m.get_nthnth(0); } if (o && o->get_flag(FL_FLOOR)) { o = 0; n = 0; } if (player->owner->get_flag(FL_NOGRAVITY)) { player->printf("You can't sit in 0g.\n"); return true; } if (player->owner->get_flag(FL_ONWATER)) { player->printf("You can't sit on water.\n"); return true; } if (player->owner->get_flag(FL_UNDERWATER)) { player->printf("You can't sit under water.\n"); return true; } if (!o && !fl) { player->printf("You can't sit on nothing.\n"); return true; } const char *and_y = ""; const char *and_s = ""; if (player->get_flag(FL_SWIMMING)) { if (!canwalk(player)) { player->printf("You can't get out of the water.\n"); return true; } and_y = "get up out of the water and "; and_s = "gets up out of the water and "; player->set_flag(FL_SWIMMING, 0); } if (!o) { player->printf("You %ssit down on %Y.\n", and_y, fl); player->oprintf(cansee, "%#M %ssits down on %Y.\n", player, and_s, fl); player->unset(KEY_SITON); player->unset(KEY_SITONN); } else { if (sitters_max(o) != -1 && sitters_n(TeleObject(player->owner, o, n))>=sitters_max(o)) { NewWorld sit = sitters(TeleObject(player->owner, o, n)); player->printf("%#Y is already occupied by %s.\n", o, magiclist(sit).c_str()); return true; } else if (!o->get_flag(FL_CANSITON) && !o->get_flag(FL_CANSLEEPON) && !o->get_flag(FL_FRAGILE)) { player->printf("You can't sit on %Y!\n", o); return true; } else if (o->owner == player || is_in(o, player)) { player->printf("You can't sit on something you are carrying.\n"); return true; } else if (o == player) { player->printf("You can't sit on yourself.\n"); return true; } else { if (dotrap(E_BEFORESIT, player, o, 0, 0)) /* ::: before_sit o1==the seat; before messaging, return 1 to abort */ return true; player->printf("You %ssit down on %Y.\n", and_y, o); player->oprintf(cansee, "%#M %ssits down on %P.\n", player, and_s, o); if (dotrap(E_ONSIT, player, o, 0, 0)) /* ::: sit o1==the seat; after messaging, return 1 to abort */ return true; if (o->get_flag(FL_FRAGILE)) { o->oprintf(cansee, "%#Y breaks.\n", o); vanish(o); } else { player->set(KEY_SITON, o->id); player->set(KEY_SITONN, n); } } } player->set_flag(FL_SITTING, 1); return true; } static bool verb_swim(MudObject *player, int argc, const char **argv) { if (player->get("_fighting")) { player->printf("You can't swim during a fight!\n"); return true; } if (player->get_flag(FL_SWIMMING)) { player->printf("You are already swimming.\n"); return true; } if (MudObject *m=mount(player)) { player->printf("You can't swim whilst you are mounted.\n", m); return true; } if (player->get_flag(FL_SLEEPING)==1) { player->printf("You toss and turn in your sleep.\n"); return true; } if (!player->owner->get_flag(FL_BYWATER) && !player->owner->get_flag(FL_ONWATER) && !player->owner->get_flag(FL_UNDERWATER)) { player->printf("You can't swim here.\n"); return true; } if (!canswim(player)) { player->printf("You can't swim.\n"); return true; } player->printf("You start swimming.\n"); player->oprintf(cansee, "%#M starts swimming.\n", player); player->set_flag(FL_SITTING, 0); player->set_flag(FL_SWIMMING, 1); player->set_flag(FL_FLYING, 0); return true; } static bool verb_sleep(MudObject *player, int argc, const char **argv) { if (player->get("_fighting")) { player->printf("You can't sleep during a fight!\n"); return true; } if (player->get_flag(FL_SLEEPING)==1) { player->printf("You are already sleeping.\n"); return true; } if (MudObject *m=mount(player)) { player->printf("You can't sleep whilst riding %Y.\n", m); return true; } if (player->owner) { if (player->owner->get_flag(FL_NOGRAVITY)) { player->printf("You can't sleep in 0g.\n"); return true; } if (player->owner->get_flag(FL_ONWATER) && !player->get_flag(FL_GILLS)) { player->printf("You can't sleep on water.\n"); return true; } if (player->owner->get_flag(FL_UNDERWATER) && !player->get_flag(FL_GILLS)) { player->printf("You can't sleep under water.\n"); return true; } if (player->get_flag(FL_FLYING)) { player->printf("You can't sleep on the wing.\n"); return true; } } TeleObject o; MudObject *fl = floor(player->owner); if (argc>1) { TeleWorld m = multi_match(player, argc-1, argv+1, NULL, LOOK_ROOM); if (m.getsize()>1) { player->printf("You can only sleep on one thing at a time.\n"); return true; } else if (m.getsize()==0) { player->printf("Sleep on what?\n"); return true; } o = m.get(0); } if (o && o->get_flag(FL_FLOOR)) { o = 0; } if (player->get_flag(FL_SWIMMING) && player->get_flag(FL_GILLS)) { player->set_flag(FL_SLEEPING, 1); player->set_flag(FL_SITTING, 0); player->set_flag(FL_SWIMMING, 1); player->printf("You fall asleep.\n"); player->oprintf(cansee, "%#M falls asleep.\n", player); return true; } if (player->get_flag(FL_SWIMMING)) { player->printf("You get up out of the water.\n"); player->oprintf(cansee, "%#M gets up out of the water.\n", player); } if (o && !o->get_flag(FL_CANSLEEPON)) { player->printf("You can't sleep on %Y.\n", *o); return true; } else if (o && o.where != player->owner) { player->printf("You can't sleep on something you are carrying.\n"); return true; } else if (o.what == player) { player->printf("You can't sleep on yourself.\n"); return true; } if (!o && !fl) { player->printf("You can't sleep on nothing.\n"); return true; } if (!o) { if (!player->get_flag(FL_NOLEGS)) { player->printf("You roll out a sleeping bag and fall asleep.\n"); player->oprintf(cansee, "%#M falls asleep.\n", player); } else { player->printf("You fall asleep.\n"); player->oprintf(cansee, "%#M falls asleep.\n", player); } } else { player->printf("You fall asleep on %Y.\n", *o); player->oprintf(cansee, "%#M falls asleep on %P.\n", player, *o); } if (o) { player->set(KEY_SITON, o.what->id); player->set(KEY_SITONN, o.nth); } else { player->unset(KEY_SITON); player->unset(KEY_SITONN); } player->set_flag(FL_SLEEPING, 1); player->set_flag(FL_SITTING, 0); player->set_flag(FL_SWIMMING, 0); /* ::: after_sleep o1==room slept in; after everything */ if (dotrap(E_AFTERSLEEP, player, player->owner)) return true; return true; } static bool verb_wake(MudObject *player, int, const char **argv) { if (!player->get_flag(FL_SLEEPING)) { player->printf("You are already quite awake.\n"); return true; } MudObject *fl = floor(player->owner); if (player->get_flag(FL_SWIMMING) || player->get_flag(FL_NOLEGS) || !fl) { player->printf("You wake up.\n"); player->oprintf(cansee, "%#M wakes up.\n", player); } else { player->printf("You wake up and clamber to your feet.\n"); player->oprintf(cansee, "%#M wakes up and clambers to %s feet.\n", player, his_or_her(player)); } player->set_bflag(FL_SLEEPING, 0); return true; } //! the position and disposition of an object struct Pos { MudObject *o; int n; enum stat { P_STANDING, P_SITTING, P_LYING, P_SWIMMING, P_FLYING, } p; int asleep; Pos () { o = 0; n = 0; p = P_STANDING; asleep = 0; } Pos (MudObject *who) { o = who->get_object(KEY_SITON); n = who->get_int(KEY_SITONN, 0); p = P_STANDING; if (who->get_flag(FL_SITTING)) p = P_SITTING; if (who->get_flag(FL_SLEEPING)) p = P_LYING; if (who->get_flag(FL_SWIMMING)) p = P_SWIMMING; if (who->get_flag(FL_FLYING)) p = P_FLYING; if (who->get_flag(FL_SLEEPING)) asleep = 1; else asleep = 0; } bool operator==(const struct Pos &p) { return (o == p.o && n == p.n); } void set(MudObject *player) { if (o) { player->set(KEY_SITON, o->id); player->set(KEY_SITONN, n); } else { player->unset(KEY_SITON); player->unset(KEY_SITONN); } } }; static bool verb_fly(MudObject *who, int argc, const char **argv) { const char *b = body(who); if (streq(b, "avian")) { if (who->get_flag(FL_FLYING)) { who->printf("You are already flying.\n"); return true; } who->printf("You take off.\n"); who->oprintf(secret(who) && cansee, "%#M %[takes/take] off.\n", who); who->set_flag(FL_FLYING, 1); who->set_flag(FL_SWIMMING, 0); who->set_flag(FL_SITTING, 0); who->unset(KEY_SITON); who->unset(KEY_SITONN); return true; } who->interpret("flys"); return true; } static bool verb_land(MudObject *who, int argc, const char **argv) { if (!who->get_flag(FL_FLYING)) { who->printf("You aren't flying.\n"); return true; } MudObject *where = who->owner; if (where->get_flag(FL_UNDERWATER) || where->get_flag(FL_ONWATER)) { who->printf("Nothing to land on.\n"); return true; } who->set_flag(FL_FLYING, 0); who->printf("You land.\n"); who->oprintf(secret(who) && cansee, "%#M %[lands/land].\n", who); return true; } static bool verb_stand(MudObject *player, int argc, const char **argv) { if (MudObject *m=mount(player)) { player->printf("You can't stand up whilst riding %Y.\n", m); return true; } MudObject *where = player->owner; if (!where) { player->printf("You aren't anywhere.\n"); return true; } if (player->get_flag(FL_NOLEGS)) { player->printf("You have no legs.\n"); return true; } if (where->get_flag(FL_NOGRAVITY)) { player->printf("There's no gravity here.\n"); return true; } Pos p; MudObject *fl = floor(player->owner); if (argc>1) { TeleWorld m = multi_match(player, argc-1, argv+1, NULL, LOOK_ROOM); if (m.getsize()>1) { player->printf("You can only stand on one thing at a time.\n"); return true; } else if (m.getsize()==0) { player->printf("Stand on what?\n"); return true; } p.o = m.get_nth(0); p.n = m.get_nthnth(0); } if (p.o && p.o->get_flag(FL_FLOOR)) { p.o = 0; p.n = 0; } if (!p.o && !fl) { player->printf("There's nowhere to stand.\n"); return true; } if (dotrap(E_BEFORESTAND, player, p.o?:fl)) /* ::: before_stand o1==the floor/other object we are about to stand on; return 1 to abort */ return true ; Pos oldpos(player); if (!player->get_flag(FL_SITTING) && !player->get_flag(FL_SWIMMING) && !player->get_flag(FL_SLEEPING) && !player->get_flag(FL_FLYING) && oldpos == p) { player->printf("You are already standing on %P.\n", p.o?p.o:fl); return true; } if (p.o && !p.o->get_flag(FL_CANSLEEPON) && !p.o->get_flag(FL_CANSITON) && !p.o->get_flag(FL_TABLE) && !p.o->get_flag(FL_FRAGILE)) { player->printf("You can't stand on %M.\n", p.o); return true; } if (player->get_flag(FL_SWIMMING)) { if (!where->get_flag(FL_BYWATER)) { player->printf("There's nowhere to stand.\n"); return true; } if (!canwalk(player)) { player->printf("You can't get out of the water.\n"); return true; } player->printf("You get up out of the water."); player->oprintf(cansee, "%#M %[gets/get] up out of the water.\n", player); player->set_flag(FL_SWIMMING, 0); player->set_flag(FL_SLEEPING, 0); } if (oldpos.p == Pos::P_FLYING) { player->printf("You land on %M.\n", p.o?p.o:fl); player->oprintf(secret(player) && cansee, "You land on %M.\n", p.o?p.o:fl); } else { if (oldpos.asleep) { if (p.o) { player->printf("You wake up and stand on %P.\n", p.o?p.o:fl); player->oprintf(cansee, "%#M %[wakes/wake] up and %[stands/stand] on %P.\n", player, p.o?p.o:fl); } else { player->printf("You wake and stand up.\n"); player->oprintf(cansee, "%#M %[wakes and stands up/wake and stand up].\n", player); } } else { if (p.o || (oldpos.o && oldpos.p==Pos::P_STANDING)) { player->printf("You stand on %P.\n", p.o?p.o:fl); player->oprintf(cansee, "%#M %[stands/stand] on %P.\n", player, p.o?p.o:fl); } else { player->printf("You stand up.\n"); player->oprintf(cansee, "%#M %[stands/stand] up.\n", player); } } } if (p.o && p.o->get_flag(FL_FRAGILE)) { p.o->oprintf(cansee, "%#Y %[breaks/break].\n", p.o); vanish(p.o); Pos flr; flr.set(player); } else { p.set(player); } player->set_flag(FL_SLEEPING, 0); player->set_flag(FL_FLYING, 0); player->set_flag(FL_SITTING, 0); if (dotrap(E_AFTERSTAND, player, p.o?:fl)) /* ::: after_stand o1==the floor/other object we have stood on. */ return true; return true; } #include "verbmodule.h" void startup() { AUTO_VERB(sit, 3, 0, PFL_NONE); AUTO_VERB(sleep, 3, 0, PFL_NONE); ADD_ALIAS(rest, 3, sleep); AUTO_VERB(stand, 3, 0, PFL_NONE); AUTO_VERB(wake, 2, 0, PFL_NONE); AUTO_VERB(swim, 3, 0, PFL_NONE); AUTO_VERB(fly, 3, 0, PFL_AWAKE); AUTO_VERB(land, 3, 0, PFL_AWAKE); #define verb_inventory verb_equipment #define verb_qinv verb_equipment AUTO_VERB(equipment, 2, 0, PFL_NONE); AUTO_VERB(inventory, 3, 0, PFL_NONE); AUTO_VERB(qinv, 4, 0, PFL_NONE); ADD_ALIAS(i, 1, inventory); AUTO_VERB(remove, 4, 0, PFL_AWAKE); AUTO_VERB(wear, 4, 0, PFL_AWAKE); ADD_ALIAS(don, 3, wear); ADD_ALIAS(doff, 3, remove); }