Drunks Database (#1200)

(an instance of Generic Database made by Dred)

     A database that keeps track of all drunks globally and also stores all messages displayed to them as they drink and sober up.

Go to location of this object, Cluttered Closet.



VERB SOURCE CODE:

get_drunk:
if (!$perm_utils:controls(caller_perms(), this))
    return E_PERM;
endif
who = args[1];
for d in (this.limits)
    drunks = this:find(tostr("upto", d));
    if (fnd = $list_utils:assoc(who, drunks))
        return {d, @fnd};
    endif
endfor
return 0;
.


add_drunk:
if (!$perm_utils:controls(caller_perms(), this))
    return E_PERM;
endif
who = args[1];
amt = args[2];
if (data = this:get_drunk(who))
    data[3] = data[3] + amt;
    ind = data[1];
    this:rem_d(tostr("upto", ind), who);
    if (ind == this.limits[length(this.limits)])
    elseif (tonum(data[3]) > tonum(ind))
        f = ind in this.limits;
        ind = this.limits[f + 1];
    endif
    this:add_d(tostr("upto", ind), data[2..length(data)]);
else
    this.drunks = setadd(this.drunks, who);
    this:add_d(tostr("upto", this.limits[1]), {who, amt, time()});
    this:sobering();
endif
.


add_d rem_d:
if (!$perm_utils:controls(caller_perms(), this))
    return E_PERM;
endif
key = args[1];
data = args[2];
drunks = this:find(key);
if (verb == "add_d")
    drunks = setadd(drunks, data);
else
    ind = $list_utils:iassoc(data, drunks);
    drunks = listdelete(drunks, ind);
endif
this:insert(key, drunks);
.


rem_drunk:
if (!$perm_utils:controls(caller_perms(), this))
    return E_PERM;
endif
who = args[1];
amt = args[2];
if (data = this:get_drunk(who))
    data[3] = data[3] - amt;
    ind = data[1];
    this:rem_d(tostr("upto", ind), who);
    if (data[3] <= 0)
        this.drunks = setremove(this.drunks, who);
        return;
    elseif (ind == this.limits[1])
    elseif (ind == "inf")
        ind = (data[3] <= 1500) ? "1500" | "inf";
    elseif (tonum(data[3]) < tonum(newind = this.limits[(ind in this.limits) - 1]))
        ind = newind;
    endif
    this:add_d(tostr("upto", ind), data[2..length(data)]);
endif
.


drink_eff:
if (!$perm_utils:controls(caller_perms(), this))
    return E_PERM;
endif
drink = args[1];
con_verb = args[2];
amt = args[3];
delay = args[4];
if ($object_utils:isa(drink, this.drinkable_root) && drink.nonalc)
    return;
endif
this:add_drunk(player, amt);
if (result = this:get_drunk(player))
    lvl = result[1];
    if (result[3] > 80)
        fork (delay)
            this:display_eff(player, this.levels[lvl in this.limits]);
        endfork
    endif
else
    "Eeek. Shouldn't happen.";
endif
.


display_eff:
":display_eff(OBJ who to, STR category key to get data from, [NUM flag to display 
definitely. None or 0 to use percentage]) => displays effects messages.";
if (caller != this)
    return E_PERM;
endif
who = args[1];
which = args[2];
flag = (length(args) > 2) ? args[3] | 0;
if (((random(10) <= 6) || flag) && $object_utils:connected(who))
    effx = this:find(which);
    oeffx = this:find(tostr("o", which));
    if (mess = effx[random(length(effx))])
        who:tell(mess);
    endif
    if ($object_utils:has_callable_verb(who.location, "announce") && (mess = oeffx[random(length(oeffx))]))
        who.location:announce($string_utils:pronoun_sub(mess, who));
    endif
endif
.


sobering:
if (!$perm_utils:controls(caller_perms(), this))
    return E_PERM;
endif
if ($code_utils:task_valid(this.sober_task))
    return;
endif
fork task (0)
    while (this.active && this.drunks)
        for lush in (this.drunks)
            if (result = this:get_drunk(lush))
                if ((time() - result[4]) > this.sober_delay)
                    this:rem_drunk(lush, this.sober_amt);
                    if ((!(newres = this:get_drunk(lush))) || (newres[1] != result[1]))
                        this:display_eff(lush, "sober", 1);
                    endif
                endif
            else
                this.drunks = setremove(this.drunks, lush);
            endif
            $command_utils:suspend_if_needed(0);
        endfor
        suspend(this.sober_delay);
    endwhile
endfork
this.sober_task = task;
.



PROPERTY DATA:
      u
      upto1
      l
      s
      o
      ol
      os
      limits
      levels
      drunks
      sober_task
      sober_delay
      active
      sober_amt
      drinkable_root