blob: ab62f591779b9f224394b11c0d7db59dbcde6c2c [file] [log] [blame]
// MorgenGrauen MUDlib
//
// player/moving.c -- player moving
//
// $Id: moving.c 9434 2016-01-12 12:34:05Z Zesstra $
#pragma strong_types
#pragma save_types
#pragma range_check
#pragma no_clone
#pragma pedantic
inherit "std/living/moving";
#define NEED_PROTOTYPES
#include <player/base.h>
#include <living/description.h>
#include <player/viewcmd.h>
#include <player.h>
#undef NEED_PROTOTYPES
#include <thing/properties.h>
#include <properties.h>
#include <language.h>
#include <defines.h>
#include <moving.h>
#include <wizlevels.h>
#include <events.h>
#include <pathd.h>
private nosave string *connections;
public void create()
{
SetProp( P_MSGIN, "kommt an" );
SetProp( P_MSGOUT, "geht" );
SetProp( P_MMSGIN, "tritt aus einer Schwefelwolke" );
SetProp( P_MMSGOUT, "verschwindet mit Knall und Schwefelduft" );
Set( P_MSGIN, SAVE, F_MODE );
Set( P_MSGOUT, SAVE, F_MODE );
Set( P_MMSGIN, SAVE, F_MODE );
Set( P_MMSGOUT, SAVE, F_MODE );
connections = ({});
::create();
}
static mixed _to_remove( object ob )
{
return ob->QueryProp(P_AUTOLOADOBJ) || ob->QueryProp(P_NODROP);
}
// autoload and nodrop object may not fall into the environment
static varargs int remove( int silent )
{
object* dest_obj = filter( deep_inventory(ME) - ({0}), "_to_remove" );
filter_objects( dest_obj, "remove" );
filter( dest_obj - ({0}), #'destruct );
if ( !QueryProp(P_INVIS) && !silent )
catch( say( name(WER, 1) + " verlaesst diese Welt.\n", ME );publish );
if ( ME && !silent )
tell_object( ME, "Bis bald!\n" );
// Im Falle des Resets ist previous_object() == ME, aber
// previous_object(0) == 0. Ausserdem ist der Caller-Stack leer. Also
// schauen, ob es ein PO gibt, was nicht gleich dem Objekt selber ist, TI
// pruefen und
if ( this_interactive() != ME
&& objectp(previous_object()) && previous_object() != ME
&& object_name(previous_object())[0..7] != "/secure/"
&& member(object_name(ME), ':') > -1 )
log_file( "PLAYERDEST",
sprintf( "%s: %O vernichtet von PO %O, TI %O, TP %O\n",
dtime(time()), ME, previous_object(),
this_interactive(), this_player() ) );
// Logout-event ausloesen
EVENTD->TriggerEvent(EVT_LIB_LOGOUT, ([
E_OBJECT: ME,
E_PLNAME: getuid(ME),
E_ENVIRONMENT: environment() ]) );
return ::remove();
}
public string NotifyDestruct(object caller) {
if (previous_object() != master()
|| object_name(this_object()) == __FILE__[..<3])
return 0;
// Das Zerstoeren von Spielern wird ggf. geloggt.
if ( objectp(caller) && caller != this_object()
&& getuid(caller) != ROOTID ) {
log_file( "PLAYERDEST",
sprintf( "%s: %O VERNICHTET von PO %O, TI %O, TP %O\n",
dtime(time()), this_object(), caller,
this_interactive(), this_player() ) );
}
// erstmal nix weiter tun, destruct gestatten.
return 0;
}
protected int PreventMove(object dest, object oldenv, int method) {
string hcroom;
mixed res;
// gestorbene HC-Spieler duerfen nicht mehr aus dem Nirvana, nicht umgehbar
// durch M_NOCHECK
if ( interactive(ME) && (query_hc_play()>1) ) {
if (objectp(dest))
hcroom=object_name(dest);
if (sizeof(hcroom)<7 || hcroom[0..5]!="/room/") {
return ME_CANT_BE_INSERTED;
}
}
// alle anderen Pruefungen sind mit M_NOCHECK egal.
if ( (method & M_NOCHECK) )
return(::PreventMove(dest,oldenv,method));
// Spieler duerfen in Raeume mit gesetztem P_NO_PLAYERS nicht hinein
if ( dest->QueryProp(P_NO_PLAYERS) && interactive(ME) &&
!(method & M_NOCHECK) &&
!IS_LEARNER(ME) && (!stringp(res = QueryProp(P_TESTPLAYER))
|| !IS_LEARNER( lower_case(res) )) ){
tell_object( ME, "Da darfst Du als Spieler nicht hin.\n" );
return ME_NOT_ALLOWED;
}
return ::PreventMove(dest,oldenv,method);
}
// Fuck. Ausnahmsweise wegen VC brauch ich nen anderes BLUE_NAME
#define OLD_BLUE_NAME(ob) (explode(object_name(ob),"#")[0])
// Krams nach dem Move machen und nebenbei zum Ueberschreiben.
protected void NotifyMove(object dest, object oldenv, int method) {
// erstmal ggf. Rauminhalt an Spieler ausgeben.
if ( interactive(ME) && !(method & M_NO_SHOW) ) {
if (!CannotSee(1))
tell_object( ME, "" + env_descr(1) );
else if ( QueryProp(P_BRIEF) < 2 )
tell_object( ME, "Finsternis.\n" );
}
//dann geerbten Kram machen
::NotifyMove(dest,oldenv,method);
// Schlussendlich noch fuer den PathD bewegung protokollieren.
// (dest nicht geprueft, da ein Spieler nicht ausserhalb jedes Env bewegt
// werden kann)
if ( interactive() && environment() && query_verb() && objectp(oldenv)) {
connections += ({ ({ OLD_BLUE_NAME(oldenv), OLD_BLUE_NAME(dest),
query_verb() + " " + (_unparsed_args(2) || ""),
method, dest->QueryProp(P_PARA) }) });
if ( sizeof(connections) > 50
&& find_call_out("flush_connections") == -1 )
call_out( "flush_connections", 0, connections );
}
}
public void flush_connections() {
catch(PATHD->add_paths(connections);publish);
connections = ({});
}
/*** Query-Methoden fuer Froesche... ;^) ***/
static string _query_msgin()
{
return QueryProp(P_FROG) ? "huepft herein" : Query(P_MSGIN);
}
static string _query_msgout()
{
return QueryProp(P_FROG) ? "huepft" : Query(P_MSGOUT);
}