[...]

 

xMOO object hierarchy!

" the furniture object needs much better messages (as I didn't work out how to store the multitude of sit/stand/lean/rest/sleep in/on/beside/etc messages, much less shifting [lean -> stand, rest -> sleep, &c] messages), 'cause right now it generates a generic message that doesn't refer to existing stance. " this also needs better display: using messages are not printed in room or when looking at furniture. players aren't grouped by furniture. " maybe also incorporate the .squeeze & other shifting/next to/shoving/fall actions from yudJ's exceptionally social furniture " this ALSO needs to mess w/ player actions (when sleeping can't use non-@* commands aside from 'wake'; when sitting can't move, close doors; etc), but that's more of a general stance issue. @prop $xplayer.stance "stand" r @prop $xplayer.furniture {#-1, ""} r @verb $xplayer:"sit stand lean rest sleep lie" none none none rd @program $xplayer:sit if (this.stance != verb || `this.furniture[1] != #-1 ! E_RANGE => 0') oldstance = this.stance; player:set_stance(verb); $you:say_action(this:stance_action(oldstance, verb)); else player:tell("You're already doing that."); endif . @verb $xplayer:wake any none none rd @program $xplayer:wake if (dobjstr && dobjstr != "up") this:my_explain_syntax(caller, verb, args); return; endif if (this.stance != "sleep") player:tell("You're not sleeping!"); else player:set_stance("stand"); $you:say_action(this:stance_action("sleep", "stand")); endif . @verb $xplayer:my_explain_syntax tnt @program $xplayer:my_explain_syntax {caller, verb, ?args = {}, ?msg = ""} = args; r = 0; if (verb == "wake") player:tell("Try this instead: wake[ up]."); r = 1; endif if(msg) player:tell(msg); r = 1; endif return r; . @verb $xplayer:stance_action tnt @program $xplayer:stance_action ":stance_action(, )"; ""; "what does when stance changes from to "; {old, new} = args; if (old == "sleep") if (new == "sit") return "%N % up and % %r into a sitting position."; elseif (new == "stand") return "%N % and % up."; elseif (new == "lean") return "%N % up and % over."; elseif (new == "rest") return "%N % up, but % resting."; elseif (new == "lie") return "%N % up."; else return ""; endif else if (new == "sit") return "%N % down."; elseif (new == "stand") return "%N % up."; elseif (new == "lean") return "%N % over."; elseif (new == "rest") return "%N % down on the ground and %."; elseif (new == "lie") return "%N % down on the ground."; else return "%N % up on the ground and % off."; endif endif . @verb $xplayer:set_stance tnt @program $xplayer:set_stance if (player != this) return E_PERM; endif {stance, ?furniture = #-1, ?prep = ""} = args; this.stance = stance; if (length(this.furniture) == 2 && `valid(this.furniture[1]) ! E_TYPE => 0') `this.furniture[1]:drop_user(this) ! ANY'; endif if (furniture != #-1 && prep) "add this to furn using list?"; this.furniture = {furniture, prep}; else this.furniture = {#-1, ""}; endif . @verb $xplayer:moveto tnt @program $xplayer:moveto if (this.stance != "stand") $you:say_action(this:stance_action(this.stance, "stand")); this:set_stance("stand"); endif pass (@args); . @create $thing called "generic furniture",furniture @chmod furniture +rf @prop furniture.valid_actions {} "looks like {{"sit", {"on"}}, {"rest", {"on"}}, {"sleep", {"on"}}} @prop furniture.capacity 0 @prop furniture.users {} ".sit_failed_msg, .sit_succeeded_msg, .osit_failed_msg, .osit_succeeded_msg ".stand_failed_msg, .stand_succeeded_msg, .ostand_failed_msg, ostand_succeeded_msg ".sit_to_stand_msg, .sit_to_rest_msg, etc if(`player.furniture[1] == #-1 ! ANY => 1') "not interacting with other furniture"; return this:(verb)+"_msg"; else "note that this is called even if player is shifting from another piece of furniture."; shiftverb = tostr(`player.furniture[2] ! ANY => ""', "_to_", verb, "_msg"); if($object_utils:has_callable_verb(this, shiftverb)) return this:(shiftverb); else return this:(verb)+"_msg"; endif endif @verb furniture:drop_user tnt rxd @program furniture:drop_user user = args[1]; this.users = setremove(this.users, user); . @verb furniture:"g*et ta*ke" this none none rxd @program furniture:get if (this.users) player:tell("You can't pick that up; there are people on it."); else pass(@args); endif . @verb furniture:"sit stand lean rest sleep lie" any any any rd @program $furniture:sit actions = $list_utils:assoc(verb, this.valid_actions); if (player.location != this.location) player:tell("I don't see that here."); return; endif if(prepstr) prepstr = $code_utils:short_prep(prepstr); elseif (!prepstr && actions) try prepstr = actions[2][1]; except (E_RANGE) "malformed actions list-- verb with no preps"; player:tell("You can't ", verb, " on that."); return; endtry endif this:_check_users(); if (actions == {} || (actions && !(prepstr in actions[2]))) if(!prepstr) prepstr = "on"; endif player:tell("You can't ", verb, " ", prepstr, " that."); return; elseif (!this:is_unlocked_for(player)) player:tell("You can't use that."); return; elseif (length(this.users) >= this.capacity) player:tell("You can't fit there."); return; elseif (player in this.users && `player.stance == verb && player.furniture[2] == prepstr ! E_PROPNF => 0') player:tell("You're already doing that."); return; endif player:set_stance(verb, this, prepstr); this.users = setadd(this.users, player); $you:say_action(tostr("%N %<", verb == "lie" ? "lies/lie" | verb + "s", "> ", prepstr, " ", this:title(), ".")); . @verb furniture:_check_users tnt @program furniture:_check_users ":_check_users()"; ""; "Goes through the list of current users and checks to see if 1) they're in the same room as the furniture and 2) they're using this furniture. If not, the furniture silently drops them from the users list. This is run right before anyone tries to use the furniture."; ""; "(this is needed because despite my best efforts, certain things still send the furniture state into disarray-- most notably, a wizard using the furniture [since $wiz:moveto is very direct] or someone disconnecting into Limbo while using the furniture-- at which point the user will continue taking up a capacity slot.)"; for u in (this.users) if(u.location != this.location || `u.furniture[1] != this ! E_PROPNF, E_RANGE => 1') this:drop_user(u); endif endfor . "(this is "generic detailed room") @program $detailed_room:tell_contents {contents, ctype} = args; if (!this.dark && contents != {} && ctype == 4) players = things = {}; for x in (contents) if (is_player(x)) players = {@players, x}; else things = {@things, x}; endif endfor if (!this.integrate) for t in (things) if ($object_utils:has_readable_property(t, "look_msg")) player:tell($string_utils:pronoun_sub(t.look_msg, player, t, this)); else player:tell("You see ", t:title(), " here."); endif if ($object_utils:isa(t, $furniture) && (d = $set_utils:intersection({player, @players}, t.users))) "ideally, this shouldn't need the player if/else block, and players who have the same stance & prep should be grouped together w/ $string_utils:title_list (along w/ player if so)."; for p in (d) if(p == player) player:tell($string_utils:pronoun_sub(tostr(" %N % ", p.stance == "lie" ? "ly" | p.stance, p.stance == "sit" ? "ting " | "ing ", p.furniture[2], " it."), $you, t)); else player:tell($string_utils:pronoun_sub(tostr(" %N % here, ", p.stance == "lie" ? "ly" | p.stance, p.stance == "sit" ? "ting " | "ing ", p.furniture[2], " %t."), p, t)); endif endfor players = $set_utils:difference(players, t.users); endif endfor endif for p in (players) player:tell($string_utils:pronoun_sub(tostr("%N % ", p.stance == "lie" ? "ly" | p.stance, (p.stance == "sit" ? "ting" | "ing"), " here."), p)); endfor else pass(@args); endif . --- "huh integration for things like 'sit down' or moving onto objects that don't exist @verb $xplayer:last_huh tnt rxd @program $xplayer:last_huh {verb, args} = args; if (verb in {"sit", "stand", "lie", "lean", "rest", "sleep"}) $xplayer_huh:(verb)(@args); return 1; else return 0; endif . $xplayer_huh:"sit stand" tnt rxd if