#include "musicmud.h" #include "verbs.h" #include "misc.h" #include "actions.h" #include "levels.h" #include "colour.h" #include "flagnames.h" #include "trap.h" #include <algorithm> #define MODULE "chat" class ofunc { public: virtual bool operator()(const Player*a, const Player *b) const = 0; }; class orderer : public ofunc { public: bool operator()(const Player *a, const Player *b) const { if (level_of(a) > level_of(b)) return 1; if (level_of(a) < level_of(b)) return 0; if (strcmp(a->id, b->id)<0) return 1; return 0; } }; template<typename T> std::vector<Player*> players_on(MudObject *who=0) { std::vector<Player*> l; iforeach(i, *players) { if (who && (who!=i && !visible_to(who, i))) continue; if (i->get_flag(FL_LOGGEDIN)) l.push_back(i); } T o; std::sort(l.begin(), l.end(), o); return l; } std::vector<Player*> players_on(MudObject *who=0) { return players_on<orderer>(who); } class Toggler : public Verb { Flag flag; const char *line; public: Toggler(const char *cmd, int minlen, int pr, PFlag pfl, Flag flag, const char *line) : Verb(cmd, minlen, pr, pfl), flag(flag), line(line) { set("module", "chat"); verbs->add(this); } bool invoke(MudObject *who, int argc, const char **argv) { who->printf("Turning %s %s.\n", line, who->get_flag(flag)?"on":"off"); who->set_bflag(flag, !who->get_flag(flag)); return true; } ~Toggler() { verbs->remove(this); } }; class Channel; list<Channel*> channels; static bool verb_commstats(MudObject *o, int argc, const char **argv); string ltrim(const string &s) { const char *t = s.c_str(); while (*t) { if (!isspace(*t)) return t; t++; } return ""; } class Channel : public Verb { PFlag priv; string channel, defcol, colprop; string prestr, poststr; Flag ignorer; Toggler toggler; string obj; friend bool verb_commstats(MudObject *o, int argc, const char **argv); friend void docleanup(); public: Channel(const char *cmd, Flag ignorer, int minlen, int pr, PFlag pfl, const char *defcol, const char *colprop, const char *channel, const char *prestr, const char *poststr, string obj) : Verb(cmd, minlen, pr, pfl, VFL_MAGICSPACE), priv(pfl), channel(channel?:cmd), defcol(defcol?:""), colprop(colprop?:""), prestr(prestr?:""), poststr(poststr?:""), ignorer(ignorer), toggler(((string)"no"+cmd).c_str(), minlen+2, pr, pfl, ignorer, cmd), obj(obj) { verbs->add(this); set("module", "chat"); channels.push_back(this); } const char *checker(MudObject *user, MudObject *seer) { MudObject *o = planet->get(obj); if (!o) return 0; o->unset("!reason"); dotrap(E_ONTRYCOMMLINE, o, o, user, seer); if (const char *r=o->get("!reason")) return r; return 0; } bool invoke(MudObject *who, int argc, const char **argv) { if (const char *s=checker(who, NULL)) { who->printf("%s\n", s); return true; } string txt = the_rest(argc, argv, 1); if (!txt.length()) { who->printf("Say what?\n"); return true; } if (txt[0]==':') { string remainder = ltrim(txt.substr(1)); if (remainder.length()==0) { who->printf("Emote what?\n"); return true; } } if (txt.substr(0, 2)=="::") { string remainder = ltrim(txt.substr(2)); if (remainder.length()==0) { who->printf("Possessive Emote what?\n"); return true; } } parsedact a; if (txt[0]=='#') a = parse_action(who, txt.c_str()+1, 0); if (ignorer != FL_NONE && who->get_flag(ignorer)) { who->printf("You had that turned off.\n"); who->set_bflag(ignorer, 0); } Player *o; int i; foreach(players, o, i) { if (o==who && who->get_flag(FL_NOHEARBACK)) continue; if (!o->get_flag(FL_LOGGEDIN)) continue; if (!has_privs(o)) continue; if (ignorer != FL_NONE && o->get_flag(ignorer)) continue; if (checker(who, o)) continue; if (!filter(who)(o)) continue; const char *name = who->get("name"); const char *say = "says"; if (o->get_flag(FL_PLURAL)) say = "say"; if (!visible_to(o, who)) { name = "^pSomeone^n"; say = "says"; } string rcol = defcol; if (colprop.length() && o->get(colprop.c_str())) { rcol = o->get(colprop.c_str()); } string col = ssprintf("%c{%c", rcol[0], rcol[1]); if (prestr.length() || poststr.length()) { o->printf("%#s%s%s%s\2^}%s\n", name, prestr, col, txt, poststr); continue; } if (txt[0]==':') { if (txt[1]!=':') { o->printf("[%s%s^}] %s %s\2\n", col.c_str(), channel, name, ltrim(txt.substr(1))); } else { o->printf("[%s%s^}] %s's %s\2\n", col.c_str(), channel, name, ltrim(txt.substr(2))); } } else { if (txt[0]=='#') { o->printf("[%s%s^}] ^Z%s\n", col.c_str(), channel, sprinta(o, a.a_rest.c_str(), who, a.targ, a.txt.c_str(), 0, a.prop)); if (a.r_rest.length()) o->printf("[%s%s^}] ^Z%s\n", col.c_str(), channel, sprinta(o, a.r_rest.c_str(), a.targ, who, a.txt.c_str(), 0, a.rprop)); } else { o->printf("[%s%s^}] %s %s ^`%s^Z%s\2^}^'\n", col.c_str(), channel, name, say, col.c_str(), txt.c_str()); } } } return true; } ~Channel() { verbs->remove(this); } }; static bool verb_commstats(MudObject *o, int argc, const char **argv) { std::vector<Player*> p = players_on(o); Header h(o, "Commstats", 1); size_t maxnamelen = 0; iforeach(ip, p) { Player *obj = *ip; maxnamelen >?= colour_strlen(obj->get("name")?:"", obj); } o->printf(" %-*s ", maxnamelen, ""); iforeach(i, channels) { Channel *c = *i; if (c->priv!=PFL_NONE && !o->get_priv(c->priv)) continue; if (privs_of(o) < c->privneeded) continue; if (c->checker(o, 0)) continue; if (c->channel != c->id) continue; o->printf("%s ", c->id); } o->printf("\n"); iforeach(ip, p) { Player *obj = *ip; const char *back = ""; if (obj==o) back = "&-113B"; o->printf(" %-*M %s", maxnamelen, obj, back); iforeach(i, channels) { Channel *c = *i; if (c->priv!=PFL_NONE && !o->get_priv(c->priv)) continue; if (privs_of(o) < c->privneeded) continue; if (c->checker(o, 0)) continue; if (c->channel != c->id) continue; bool can = 1; if (c->priv!=PFL_NONE && !obj->get_priv(c->priv)) can = 0; if (privs_of(obj) < c->privneeded) can = 0; if (c->checker(o, obj)) can = 0; bool on = 1; if (c->ignorer != FL_NONE && obj->get_flag(c->ignorer)) on = 0; const char *str = can?(on?"^Gon^n":"^Roff^n"):"^-^-^-"; int slen = can?on?2:3:3; int widto = strlen(c->id)-slen; int w = widto; w /= 2; widto -= w; o->printf("%-*s%s%s%-*s ", widto, "", str, back, w, ""); } o->printf("^n\n"); } return true; } void docleanup() { iforeach(l, channels) { delete *l; } } #define CLEANUP docleanup(); #include "verbmodule.h" Flag find_flag(const char *name) { if (!name) return FL_NONE; for (Flag l=FL_FIRST;l<FL_MAX;l++) if (strcasecmp(name, flag_names[l])==0) return l; return FL_NONE; } extern "C" void after_reset() { MudObject *ch = planet->get("chat_zone"); if (!ch) return; MudObject *o; int i; foreach(ch->children, o, i) if (o->get_object("start")==ch && o->get("short")) { new Channel(o->get("short"), find_flag(o->get("flag")), o->get_int("minlen", 3), o->get_int("minlev", 0), o->get("priv")?find_priv(o->get("priv")):PFL_NONE, o->get("defcol")?:"^R", o->get("colprop"), o->get("channel"), o->get("prestr"), o->get("poststr"), o->id); } } void startup() { AUTO_VERB(commstats, 5, 0, PFL_NONE); }