tinymux/mux/modules/engine/move.cpp
Stephen Dennis de80e7ac31 nls: mark move/walk/help/guest/quota/power notify prose with M_() (#1670)
Phase 3 coverage slice. Player and staff notify paths that still used
T() (cast-only) now use M_() so they extract into the catalogue:

  move   arrive/leave, get/drop, teleport failures, home
  walk   destination, blocked, patrol
  help   missing topic, match list, file errors
  guest  busy/create errors, listing total
  quota  Quota/Used display templates
  powers Power not found, @power echo, Powers: header
  session Poll / Doing

Attribute names, flag/power registry keys, logs, HTML, and softcode
machine tokens stay T()/S_(). Regenerates pot (670 -> 704) and xx.po.
2026-07-28 05:34:30 +00:00

1060 lines
28 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*! \file move.cpp
* \brief Routines for moving about.
*
*/
#include "copyright.h"
#include "autoconf.h"
#include "config.h"
#include "externs.h"
/* ---------------------------------------------------------------------------
* process_leave_loc: Generate messages and actions resulting from leaving a
* place.
*/
static void process_leave_loc(dbref thing, dbref dest, dbref cause, bool canhear, int hush)
{
dbref loc = Location(thing);
if ((loc == NOTHING) || (loc == dest))
{
return;
}
if (dest == HOME)
{
dest = Home(thing);
}
if (Html(thing))
{
notify_html(thing, T("<xch_page clear=links>"));
}
// Run the LEAVE attributes in the current room if we meet any of
// following criteria:
//
// - The current room has wizard privs.
// - Neither the current room nor the moving object are dark.
// - The moving object can hear and does not hav wizard privs.
//
// EXCEPT if we were called with the HUSH_LEAVE key.
//
#ifdef REALITY_LVLS
bool quiet = ( (hush & HUSH_LEAVE) || !IsReal(loc, thing)
#else
bool quiet = ( (hush & HUSH_LEAVE)
#endif // REALITY_LVLS
|| ( !Wizard(loc)
&& ( Dark(thing)
|| Dark(loc))
&& ( !canhear
|| ( Can_Dark(thing)
&& Dark(thing)))));
int oattr = quiet ? 0 : A_OLEAVE;
int aattr = A_ALEAVE;
int pattr = (quiet || (!mudconf.terse_movemsg && Terse(thing))) ? 0 : A_LEAVE;
did_it(thing, loc, pattr, nullptr, oattr, nullptr, aattr, 0, nullptr, 0);
// Do OXENTER for receiving room
//
if ((dest != NOTHING) && !quiet)
{
did_it(thing, dest, 0, nullptr, A_OXENTER, nullptr, 0, 0, nullptr, 0);
}
// Display the 'has left' message if we meet any of the following
// criteria:
//
// - Neither the current room nor the moving object are dark.
// - The object can hear and is not a dark wizard.
//
if ( !quiet
&& !Blind(thing)
&& !Blind(loc))
{
if ( ( !Dark(thing)
&& !Dark(loc))
|| ( canhear
&& !(Can_Dark(thing) && Dark(thing))))
{
#ifdef REALITY_LVLS
notify_except2_rlevel(loc, thing, thing, cause,
#else
notify_except2(loc, thing, thing, cause,
#endif // REALITY_LVLS
tprintf(M_("%s has left."), Moniker(thing)));
}
}
}
/*---------------------------------------------------------------------------
* process_enter_loc: Generate messages and actions resulting from entering
* a place.
*/
static void process_enter_loc(dbref thing, dbref src, dbref cause, bool canhear, int hush)
{
dbref loc = Location(thing);
if ( loc == NOTHING
|| loc == src)
{
return;
}
show_vrml_url(thing, loc);
// Run the ENTER attributes in the current room if we meet any of following
// criteria:
//
// - The current room has wizard privs.
// - Neither the current room nor the moving object are dark.
// - The moving object can hear and does not have wizard privs.
//
// EXCEPT if we were called with the HUSH_ENTER key.
//
#ifdef REALITY_LVLS
bool quiet = ( (hush & HUSH_ENTER) || !IsReal(loc, thing)
#else
bool quiet = ( (hush & HUSH_ENTER)
#endif // REALITY_LVLS
|| ( !Wizard(loc)
&& ( Dark(thing)
|| Dark(loc))
&& ( !canhear
|| ( Can_Dark(thing)
&& Dark(thing)))));
int oattr = quiet ? 0 : A_OENTER;
int aattr = A_AENTER;
int pattr = (quiet || (!mudconf.terse_movemsg && Terse(thing))) ? 0 : A_ENTER;
did_it(thing, loc, pattr, nullptr, oattr, nullptr, aattr, 0, nullptr, 0);
// Do OXLEAVE for sending room.
//
if ( src != NOTHING
&& !quiet)
{
did_it(thing, src, 0, nullptr, A_OXLEAVE, nullptr, 0, 0, nullptr, 0);
}
// Display the 'has arrived' message if we meet all of the following
// criteria:
//
// - The moving object can hear.
// - The object is not a dark wizard.
//
if ( !quiet
&& canhear
&& !Blind(thing)
&& !Blind(loc)
&& !(Dark(thing) && Can_Dark(thing)))
{
#ifdef REALITY_LVLS
notify_except2_rlevel(loc, thing, thing, cause,
#else
notify_except2(loc, thing, thing, cause,
#endif // REALITY_LVLS
tprintf(M_("%s has arrived."), Moniker(thing)));
}
}
/* ---------------------------------------------------------------------------
* move_object: Physically move an object from one place to another.
* Does not generate any messages or actions.
*/
void move_object(dbref thing, dbref dest)
{
dbref src = Location(thing);
// Remove from the source location
//
if (src != NOTHING)
{
s_Contents(src, remove_first(Contents(src), thing));
}
// Special check for HOME
//
if (dest == HOME)
{
dest = Home(thing);
}
// Add to destination location
//
if (dest != NOTHING)
{
s_Contents(dest, insert_first(Contents(dest), thing));
}
else
{
s_Next(thing, NOTHING);
}
s_Location(thing, dest);
// Preload the destination synchronously so look_in() doesn't pay
// cold misses, then defer BFS neighbors for later.
//
if (Good_obj(dest))
{
bool bUnlimited = (mudconf.max_cache_size < 0);
cache_preload_obj(dest, bUnlimited);
if (bUnlimited && mudconf.cache_preload_depth > 0)
{
cache_preload_deferred_bfs(dest, mudconf.cache_preload_depth);
}
}
// Look around and do the penny check
//
look_in(thing, dest, (LK_SHOWEXIT | LK_OBEYTERSE));
if ( isPlayer(thing)
&& mudconf.payfind > 0
&& Pennies(thing) < mudconf.paylimit
&& !Controls(thing, dest)
&& RandomINT32(0, mudconf.payfind-1) == 0)
{
giveto(thing, 1);
notify(thing, tprintf(M_("You found a %s!"), mudconf.one_coin));
}
}
// move_the_exit: Move an exit silently from its location to its destination
//
static void move_the_exit(dbref thing, dbref dest)
{
dbref exitloc = Exits(thing);
s_Exits(exitloc, remove_first(Exits(exitloc), thing));
s_Exits(dest, insert_first(Exits(dest), thing));
s_Exits(thing, dest);
}
/* ---------------------------------------------------------------------------
* send_dropto, process_sticky_dropto, process_dropped_dropto,
* process_sacrifice_dropto: Check for and process droptos.
*/
// send_dropto: Send an object through the dropto of a room
//
static void send_dropto(dbref thing, dbref player)
{
if (!Sticky(thing))
{
move_via_generic(thing, Dropto(Location(thing)), player, 0);
}
else
{
move_via_generic(thing, HOME, player, 0);
}
divest_object(thing);
}
// process_sticky_dropto: Call when an object leaves the room to see if
// we should empty the room
//
static void process_sticky_dropto(dbref loc, dbref player)
{
// Do nothing if checking anything but a sticky room
//
if ( !Good_obj(loc)
|| !Has_dropto(loc)
|| !Sticky(loc))
{
return;
}
// Make sure dropto loc is valid
//
dbref dropto = Dropto(loc);
if ( NOTHING == dropto
|| dropto == loc)
{
return;
}
// Make sure no players hanging out
//
dbref thing;
DOLIST(thing, Contents(loc))
{
if ( Connected(Owner(thing))
&& Hearer(thing))
{
return;
}
}
// Send everything through the dropto
//
dbref next;
s_Contents(loc, reverse_list(Contents(loc)));
SAFE_DOLIST(thing, next, Contents(loc))
{
send_dropto(thing, player);
}
}
// process_dropped_dropto: Check what to do when someone drops an object.
//
static void process_dropped_dropto(dbref thing, dbref player)
{
// If STICKY, send home
//
if (Sticky(thing))
{
move_via_generic(thing, HOME, player, 0);
divest_object(thing);
return;
}
// Process the dropto if location is a room and is not STICKY
//
dbref loc = Location(thing);
if (Has_dropto(loc) && (Dropto(loc) != NOTHING) && !Sticky(loc))
send_dropto(thing, player);
}
/* ---------------------------------------------------------------------------
* move_via_generic: Generic move routine, generates standard messages and
* actions.
*/
void move_via_generic(dbref thing, dbref dest, dbref cause, int hush)
{
if (dest == HOME)
{
dest = Home(thing);
}
dbref src = Location(thing);
bool canhear = Hearer(thing);
process_leave_loc(thing, dest, cause, canhear, hush);
move_object(thing, dest);
did_it(thing, thing, A_MOVE, nullptr, A_OMOVE, nullptr, A_AMOVE, 0, nullptr, 0);
process_enter_loc(thing, src, cause, canhear, hush);
}
/* ---------------------------------------------------------------------------
* move_via_exit: Exit move routine, generic + exit messages + dropto check.
*/
static void move_via_exit(dbref thing, dbref dest, dbref cause, dbref exit, int hush)
{
if (dest == HOME)
{
dest = Home(thing);
}
dbref src = Location(thing);
bool canhear = Hearer(thing);
// Dark wizards don't trigger OSUCC/ASUCC
bool quiet = ( (Can_Dark(thing) && Dark(thing))
|| (hush & HUSH_EXIT));
int aattr = quiet ? 0 : A_ASUCC;
int oattr = quiet ? 0 : A_OSUCC;
int pattr = (!mudconf.terse_movemsg && Terse(thing)) ? 0 : A_SUCC;
did_it(thing, exit, pattr, nullptr, oattr, nullptr, aattr, 0, nullptr, 0);
process_leave_loc(thing, dest, cause, canhear, hush);
move_object(thing, dest);
aattr = quiet ? 0 : A_ADROP;
oattr = quiet ? 0 : A_ODROP;
pattr = (!mudconf.terse_movemsg && Terse(thing)) ? 0 : A_DROP;
did_it(thing, exit, pattr, nullptr, oattr, nullptr, aattr, 0, nullptr, 0);
did_it(thing, thing, A_MOVE, nullptr, A_OMOVE, nullptr, A_AMOVE, 0, nullptr, 0);
process_enter_loc(thing, src, cause, canhear, hush);
process_sticky_dropto(src, thing);
}
/* ---------------------------------------------------------------------------
* move_via_teleport: Teleport move routine, generic + teleport messages +
* divestiture + dropto check.
*/
bool move_via_teleport(dbref thing, dbref dest, dbref cause, int hush)
{
dbref curr;
int count;
const UTF8 *failmsg;
dbref src = Location(thing);
if ( HOME != dest
&& Good_obj(src))
{
curr = src;
for (count = mudconf.ntfy_nest_lim; count > 0; count--)
{
if (!could_doit(thing, curr, A_LTELOUT))
{
if ( thing == cause
|| NOTHING == cause)
{
failmsg = M_("You cant teleport out!");
}
else
{
failmsg = M_("You cant be teleported out!");
notify_quiet(cause, M_("You cant teleport that out!"));
}
did_it(thing, src,
A_TOFAIL, failmsg, A_OTOFAIL, nullptr,
A_ATOFAIL, 0, nullptr, 0);
return false;
}
if (isRoom(curr))
{
break;
}
curr = Location(curr);
}
}
if (isExit(thing))
{
move_the_exit(thing, dest);
return true;
}
if (dest == HOME)
{
dest = Home(thing);
}
bool canhear = Hearer(thing);
if (!(hush & HUSH_LEAVE))
{
did_it(thing, thing, 0, nullptr, A_OXTPORT, nullptr, 0,
0, nullptr, 0);
}
process_leave_loc(thing, dest, NOTHING, canhear, hush);
move_object(thing, dest);
if (!(hush & HUSH_ENTER))
{
did_it(thing, thing, A_TPORT, nullptr, A_OTPORT, nullptr, A_ATPORT,
0, nullptr, 0);
}
did_it(thing, thing, A_MOVE, nullptr, A_OMOVE, nullptr, A_AMOVE,
0, nullptr, 0);
process_enter_loc(thing, src, NOTHING, canhear, hush);
divest_object(thing);
process_sticky_dropto(src, thing);
return true;
}
/* ---------------------------------------------------------------------------
* move_exit: Try to move a player through an exit.
*/
static dbref get_exit_dest(dbref executor, dbref exit)
{
dbref aowner;
int aflags;
UTF8 *atr_gotten = atr_pget(exit, A_EXITVARDEST, &aowner, &aflags);
LBuf result = LBuf_Src("get_exit_dest");
UTF8 *ref = result.get();
mux_exec(atr_gotten, LBUF_SIZE-1, result, &ref, exit, executor, executor,
AttrTrace(aflags, EV_TOP|EV_FCHECK|EV_EVAL), nullptr, 0);
free_lbuf(atr_gotten);
*ref = '\0';
dbref dest = NOTHING;
if (*result == NUMBER_TOKEN)
{
dest = mux_atoi64(result + 1);
}
return dest;
}
void move_exit(dbref player, dbref exit, bool divest, const UTF8 *failmsg, int hush)
{
int oattr, aattr;
bool bDoit = false;
dbref loc = Location(exit);
if (atr_get_raw(exit, A_EXITVARDEST) != nullptr)
{
loc = get_exit_dest(player, exit);
}
if (loc == HOME)
{
loc = Home(player);
}
#ifdef WOD_REALMS
if (Good_obj(loc) && (REALM_DO_HIDDEN_FROM_YOU != DoThingToThingVisibility(player, exit, ACTION_IS_MOVING)))
{
if (isShroud(player))
{
bDoit = true;
int iShroudWarded = get_atr(T("SHROUD_WARDED"));
if (iShroudWarded > 0)
{
int owner, flags;
UTF8 *buff = atr_pget(exit, iShroudWarded, &owner, &flags);
if (buff)
{
if (*buff)
{
bDoit = false;
}
free_lbuf(buff);
}
}
}
if (!bDoit && isUmbra(player))
{
bDoit = true;
int iUmbraWarded = get_atr(T("UMBRA_WARDED"));
if (iUmbraWarded > 0)
{
int owner, flags;
UTF8 *buff = atr_pget(exit, iUmbraWarded, &owner, &flags);
if (buff)
{
if (*buff)
{
bDoit = false;
}
free_lbuf(buff);
}
}
}
if (!bDoit && could_doit(player, exit, A_LOCK))
{
bDoit = true;
}
}
#else
#ifdef REALITY_LVLS
if (Good_obj(loc) && IsReal(exit, player) && could_doit(player, exit, A_LOCK))
#else
if (Good_obj(loc) && could_doit(player, exit, A_LOCK))
#endif
{
bDoit = true;
}
#endif
if (bDoit)
{
switch (Typeof(loc))
{
case TYPE_ROOM:
move_via_exit(player, loc, NOTHING, exit, hush);
if (divest)
divest_object(player);
break;
case TYPE_PLAYER:
case TYPE_THING:
if (Going(loc))
{
notify(player, M_("You cant go that way."));
return;
}
move_via_exit(player, loc, NOTHING, exit, hush);
divest_object(player);
break;
case TYPE_EXIT:
notify(player, M_("You cant go that way."));
return;
}
}
else
{
if ((Can_Dark(player) && Dark(player)) || (hush & HUSH_EXIT))
{
oattr = 0;
aattr = 0;
}
else
{
oattr = A_OFAIL;
aattr = A_AFAIL;
}
did_it(player, exit, A_FAIL, failmsg, oattr, nullptr, aattr, 0, nullptr, 0);
}
}
/* ---------------------------------------------------------------------------
* do_move: Move from one place to another via exits or 'home'.
*/
void do_move(dbref executor, dbref caller, dbref enactor, int eval, int key, UTF8 *direction, const UTF8 *cargs[], int ncargs)
{
UNUSED_PARAMETER(caller);
UNUSED_PARAMETER(enactor);
UNUSED_PARAMETER(eval);
UNUSED_PARAMETER(cargs);
UNUSED_PARAMETER(ncargs);
if (!string_compare(direction, T("home")))
{
dbref loc = Location(executor);
dbref dest = Home(executor);
if ( NOTHING != loc
&& NOTHING != dest
&& loc == dest)
{
notify(executor, M_("You are already home."));
}
else
{
// Go home w/o stuff.
//
if ( ( Fixed(executor)
|| Fixed(Owner(executor)))
&& !(WizRoy(executor)))
{
notify(executor, mudconf.fixed_home_msg);
return;
}
if ( NOTHING != loc
&& !Blind(executor)
&& !Blind(loc)
&& !Dark(executor)
&& !Dark(loc))
{
// Tell all
//
notify_except(loc, executor, executor, tprintf(M_("%s goes home."), Moniker(executor)), 0);
}
// Give the player the messages
//
for (int i = 0; i < 3; i++)
{
notify(executor, M_("Theres no place like home..."));
}
move_via_generic(executor, HOME, NOTHING, 0);
divest_object(executor);
process_sticky_dropto(loc, executor);
}
return;
}
// Find the exit.
//
init_match_check_keys(executor, direction, TYPE_EXIT);
match_exit();
int quiet;
dbref exit = match_result();
switch (exit)
{
case NOTHING: // Try to force the object
notify(executor, M_("You cant go that way."));
break;
case AMBIGUOUS:
notify(executor, M_("I dont know which way you mean!"));
break;
default:
quiet = 0;
if ((key & MOVE_QUIET) && Controls(executor, exit))
quiet = HUSH_EXIT;
move_exit(executor, exit, false, M_("You cant go that way."), quiet);
}
}
/* ---------------------------------------------------------------------------
* do_get: Get an object.
*/
void do_get(dbref executor, dbref caller, dbref enactor, int eval, int key, UTF8 *what, const UTF8 *cargs[], int ncargs)
{
UNUSED_PARAMETER(caller);
UNUSED_PARAMETER(enactor);
UNUSED_PARAMETER(eval);
UNUSED_PARAMETER(cargs);
UNUSED_PARAMETER(ncargs);
dbref playerloc;
if ( !Has_location(executor)
|| !Good_obj(playerloc = Location(executor)))
{
return;
}
// You can only pick up things in rooms and ENTER_OK objects/players.
//
if ( !isRoom(playerloc)
&& !Enter_ok(playerloc)
&& !Controls(executor, playerloc))
{
notify(executor, NOPERM_MESSAGE);
return;
}
// Look for the thing locally.
//
init_match_check_keys(executor, what, TYPE_THING);
match_neighbor();
match_exit();
if (Long_Fingers(executor))
{
match_absolute();
}
dbref thing = match_result();
// Look for the thing in other people's inventories.
//
if (!Good_obj(thing))
{
thing = match_status(executor, match_possessed(executor, executor, what,
thing, true));
if (!Good_obj(thing))
{
return;
}
}
// If we found it, check to see if we can get it.
//
dbref thingloc = Location(thing);
if (Good_obj(thingloc))
{
if (!could_doit(executor, thingloc, A_LGET))
{
notify(executor, NOPERM_MESSAGE);
return;
}
}
// If we can get it, get it.
//
const UTF8 *failmsg;
int oattr, aattr;
bool quiet = false;
switch (Typeof(thing))
{
case TYPE_PLAYER:
case TYPE_THING:
// You can't take what you already have.
//
if (thingloc == executor)
{
notify(executor, M_("You already have that!"));
break;
}
if ( (key & GET_QUIET)
&& Controls(executor, thing))
{
quiet = true;
}
if (thing == executor)
{
notify(executor, M_("You cannot get yourself!"));
}
else if (could_doit(executor, thing, A_LOCK))
{
if (thingloc != playerloc)
{
notify(thingloc, tprintf(M_("%s was taken from you."),
Moniker(thing)));
}
move_via_generic(thing, executor, executor, 0);
notify(thing, M_("Taken."));
oattr = quiet ? 0 : A_OSUCC;
aattr = quiet ? 0 : A_ASUCC;
did_it(executor, thing, A_SUCC, M_("Taken."), oattr, nullptr,
aattr, 0, nullptr, 0);
}
else
{
oattr = quiet ? 0 : A_OFAIL;
aattr = quiet ? 0 : A_AFAIL;
if (thingloc != playerloc)
{
failmsg = M_("You cant take that from there.");
}
else
{
failmsg = M_("You cant pick that up.");
}
did_it(executor, thing, A_FAIL, failmsg, oattr, nullptr, aattr,
0, nullptr, 0);
}
break;
case TYPE_EXIT:
// You can't take what you already have.
//
thingloc = Exits(thing);
if (thingloc == executor)
{
notify(executor, M_("You already have that!"));
break;
}
// You must control either the exit or the location.
//
if ( !Controls(executor, thing)
&& !Controls(executor, playerloc))
{
notify(executor, NOPERM_MESSAGE);
break;
}
// Do it.
//
s_Exits(thingloc, remove_first(Exits(thingloc), thing));
s_Exits(executor, insert_first(Exits(executor), thing));
s_Exits(thing, executor);
if (!Quiet(executor))
{
notify(executor, M_("Exit taken."));
}
break;
default:
notify(executor, M_("You cant take that!"));
break;
}
}
/* ---------------------------------------------------------------------------
* do_drop: Drop an object.
*/
void do_drop(dbref executor, dbref caller, dbref enactor, int eval, int key, UTF8 *name, const UTF8 *cargs[], int ncargs)
{
UNUSED_PARAMETER(caller);
UNUSED_PARAMETER(enactor);
UNUSED_PARAMETER(eval);
UNUSED_PARAMETER(cargs);
UNUSED_PARAMETER(ncargs);
dbref loc = Location(executor);
if (!Good_obj(loc))
{
return;
}
dbref exitloc, thing;
UTF8 *bp;
int oattr, aattr;
bool quiet;
init_match(executor, name, TYPE_THING);
match_possession();
match_carried_exit();
switch (thing = match_result())
{
case NOTHING:
notify(executor, M_("You dont have that!"));
return;
case AMBIGUOUS:
notify(executor, M_("I dont know which you mean!"));
return;
}
switch (Typeof(thing))
{
case TYPE_THING:
case TYPE_PLAYER:
// You have to be carrying it.
//
if ( ( Location(thing) != executor
&& !Wizard(executor))
|| !could_doit(executor, thing, A_LDROP))
{
did_it(executor, thing, A_DFAIL, M_("You cant drop that."),
A_ODFAIL, nullptr, A_ADFAIL, 0, nullptr, 0);
return;
}
// Move it
//
move_via_generic(thing, Location(executor), executor, 0);
notify(thing, M_("Dropped."));
quiet = false;
if ( (key & DROP_QUIET)
&& Controls(executor, thing))
{
quiet = true;
}
{
LBuf buf = LBuf_Src("do_drop.did_it");
bp = buf.get();
safe_tprintf_str(buf, &bp, M_("dropped %s."), Moniker(thing));
oattr = quiet ? 0 : A_ODROP;
aattr = quiet ? 0 : A_ADROP;
did_it(executor, thing, A_DROP, M_("Dropped."), oattr, buf,
aattr, 0, nullptr, 0);
}
// Process droptos
//
process_dropped_dropto(thing, executor);
break;
case TYPE_EXIT:
// You have to be carrying it.
//
if ( Exits(thing) != executor
&& !Wizard(executor))
{
notify(executor, M_("You cant drop that."));
return;
}
if (!Controls(executor, loc))
{
notify(executor, NOPERM_MESSAGE);
return;
}
// Do it.
//
exitloc = Exits(thing);
s_Exits(exitloc, remove_first(Exits(exitloc), thing));
s_Exits(loc, insert_first(Exits(loc), thing));
s_Exits(thing, loc);
if (!Quiet(executor))
{
notify(executor, M_("Exit dropped."));
}
break;
default:
notify(executor, M_("You cant drop that."));
break;
}
}
/* ---------------------------------------------------------------------------
* do_enter, do_leave: The enter and leave commands.
*/
void do_enter_internal(dbref player, dbref thing, bool quiet)
{
int oattr, aattr;
if (!Enter_ok(thing) && !Controls(player, thing))
{
oattr = quiet ? 0 : A_OEFAIL;
aattr = quiet ? 0 : A_AEFAIL;
did_it(player, thing, A_EFAIL, NOPERM_MESSAGE,
oattr, nullptr, aattr, 0, nullptr, 0);
}
else if (player == thing)
{
notify(player, M_("You cant enter yourself!"));
}
else if (could_doit(player, thing, A_LENTER))
{
dbref loc = Location(player);
oattr = quiet ? HUSH_ENTER : 0;
move_via_generic(player, thing, NOTHING, oattr);
divest_object(player);
process_sticky_dropto(loc, player);
}
else
{
oattr = quiet ? 0 : A_OEFAIL;
aattr = quiet ? 0 : A_AEFAIL;
did_it(player, thing, A_EFAIL, M_("You cant enter that."),
oattr, nullptr, aattr, 0, nullptr, 0);
}
}
void do_enter(dbref executor, dbref caller, dbref enactor, int eval, int key, UTF8 *what, const UTF8 *cargs[], int ncargs)
{
UNUSED_PARAMETER(caller);
UNUSED_PARAMETER(enactor);
UNUSED_PARAMETER(eval);
UNUSED_PARAMETER(cargs);
UNUSED_PARAMETER(ncargs);
init_match(executor, what, TYPE_THING);
match_neighbor();
if (Long_Fingers(executor))
match_absolute(); // the wizard has long fingers
dbref thing = noisy_match_result();
bool bQuiet = false;
if (thing == NOTHING)
return;
switch (Typeof(thing))
{
case TYPE_PLAYER:
case TYPE_THING:
if ((key & MOVE_QUIET) && Controls(executor, thing))
bQuiet = true;
do_enter_internal(executor, thing, bQuiet);
break;
default:
notify(executor, NOPERM_MESSAGE);
}
return;
}
void do_leave(dbref executor, dbref caller, dbref enactor, int eval, int key)
{
UNUSED_PARAMETER(caller);
UNUSED_PARAMETER(enactor);
UNUSED_PARAMETER(eval);
dbref loc = Location(executor);
dbref newLoc = loc;
if ( !Good_obj(loc)
|| Going(loc)
|| !Has_location(loc)
|| !Good_obj(newLoc = Location(loc))
|| Going(newLoc))
{
notify(executor, M_("You cant leave."));
return;
}
int quiet = 0;
if ( (key & MOVE_QUIET)
&& Controls(executor, loc))
{
quiet = HUSH_LEAVE;
}
if (could_doit(executor, loc, A_LLEAVE))
{
move_via_generic(executor, newLoc, NOTHING, quiet);
}
else
{
int oattr = quiet ? 0 : A_OLFAIL;
int aattr = quiet ? 0 : A_ALFAIL;
did_it(executor, loc, A_LFAIL, M_("You cant leave."),
oattr, nullptr, aattr, 0, nullptr, 0);
}
}