blob: a59d9542af45857cb265f62d99a1ad9b86e0185d [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// MorgenGrauen MUDlib
2//
3// player/moving.c -- player moving
4//
5// $Id: moving.c 9434 2016-01-12 12:34:05Z Zesstra $
6#pragma strong_types
7#pragma save_types
8#pragma range_check
9#pragma no_clone
MG Mud User88f12472016-06-24 23:31:02 +020010
11inherit "std/living/moving";
12
13#define NEED_PROTOTYPES
14#include <player/base.h>
15#include <living/description.h>
16#include <player/viewcmd.h>
17#include <player.h>
18#undef NEED_PROTOTYPES
19
20#include <thing/properties.h>
21#include <properties.h>
22#include <language.h>
23#include <defines.h>
24#include <moving.h>
25#include <wizlevels.h>
26#include <events.h>
27#include <pathd.h>
28
Bugfixfcba8642021-03-16 21:10:30 +010029private nosave < <int|string>* >* connections = ({});
MG Mud User88f12472016-06-24 23:31:02 +020030
31public void create()
32{
33 SetProp( P_MSGIN, "kommt an" );
34 SetProp( P_MSGOUT, "geht" );
35 SetProp( P_MMSGIN, "tritt aus einer Schwefelwolke" );
36 SetProp( P_MMSGOUT, "verschwindet mit Knall und Schwefelduft" );
37 Set( P_MSGIN, SAVE, F_MODE );
38 Set( P_MSGOUT, SAVE, F_MODE );
39 Set( P_MMSGIN, SAVE, F_MODE );
40 Set( P_MMSGOUT, SAVE, F_MODE );
MG Mud User88f12472016-06-24 23:31:02 +020041
42 ::create();
43}
44
45
46static mixed _to_remove( object ob )
47{
48 return ob->QueryProp(P_AUTOLOADOBJ) || ob->QueryProp(P_NODROP);
49}
50
51
52// autoload and nodrop object may not fall into the environment
53static varargs int remove( int silent )
54{
Zesstra9ea7e9a2021-11-01 11:33:34 +010055 // Andere wollen auch informiert werden ueber den (ggf. impliziten)
56 // Logout.
57 // Achtung: *kein* CNP_FLAG_SILENT - das hat eine andere Bedeutung als das
58 // argument silent hier!
59 if ( interactive(ME) )
60 call_notify_player_change(CNP_FLAG_QUIT);
61
62 // Inventar aufraeumen
MG Mud User88f12472016-06-24 23:31:02 +020063 object* dest_obj = filter( deep_inventory(ME) - ({0}), "_to_remove" );
64 filter_objects( dest_obj, "remove" );
65 filter( dest_obj - ({0}), #'destruct );
66
67 if ( !QueryProp(P_INVIS) && !silent )
68 catch( say( name(WER, 1) + " verlaesst diese Welt.\n", ME );publish );
MG Mud User88f12472016-06-24 23:31:02 +020069 if ( ME && !silent )
70 tell_object( ME, "Bis bald!\n" );
71
Zesstra9ea7e9a2021-11-01 11:33:34 +010072 // Logmeldung, wenn jemand einen Spieler zerstoert.
MG Mud User88f12472016-06-24 23:31:02 +020073 // Im Falle des Resets ist previous_object() == ME, aber
74 // previous_object(0) == 0. Ausserdem ist der Caller-Stack leer. Also
75 // schauen, ob es ein PO gibt, was nicht gleich dem Objekt selber ist, TI
76 // pruefen und
77 if ( this_interactive() != ME
78 && objectp(previous_object()) && previous_object() != ME
79 && object_name(previous_object())[0..7] != "/secure/"
80 && member(object_name(ME), ':') > -1 )
81 log_file( "PLAYERDEST",
82 sprintf( "%s: %O vernichtet von PO %O, TI %O, TP %O\n",
83 dtime(time()), ME, previous_object(),
84 this_interactive(), this_player() ) );
85
Zesstra9ea7e9a2021-11-01 11:33:34 +010086 return ::remove(silent);
MG Mud User88f12472016-06-24 23:31:02 +020087}
88
89public string NotifyDestruct(object caller) {
90
91 if (previous_object() != master()
92 || object_name(this_object()) == __FILE__[..<3])
93 return 0;
94
95 // Das Zerstoeren von Spielern wird ggf. geloggt.
96 if ( objectp(caller) && caller != this_object()
97 && getuid(caller) != ROOTID ) {
98 log_file( "PLAYERDEST",
99 sprintf( "%s: %O VERNICHTET von PO %O, TI %O, TP %O\n",
100 dtime(time()), this_object(), caller,
101 this_interactive(), this_player() ) );
102 }
103 // erstmal nix weiter tun, destruct gestatten.
104 return 0;
105}
106
107protected int PreventMove(object dest, object oldenv, int method) {
108 string hcroom;
109 mixed res;
110
111 // gestorbene HC-Spieler duerfen nicht mehr aus dem Nirvana, nicht umgehbar
112 // durch M_NOCHECK
113 if ( interactive(ME) && (query_hc_play()>1) ) {
114 if (objectp(dest))
115 hcroom=object_name(dest);
116 if (sizeof(hcroom)<7 || hcroom[0..5]!="/room/") {
117 return ME_CANT_BE_INSERTED;
118 }
119 }
120
121 // alle anderen Pruefungen sind mit M_NOCHECK egal.
122 if ( (method & M_NOCHECK) )
123 return(::PreventMove(dest,oldenv,method));
124
125 // Spieler duerfen in Raeume mit gesetztem P_NO_PLAYERS nicht hinein
126 if ( dest->QueryProp(P_NO_PLAYERS) && interactive(ME) &&
127 !(method & M_NOCHECK) &&
128 !IS_LEARNER(ME) && (!stringp(res = QueryProp(P_TESTPLAYER))
129 || !IS_LEARNER( lower_case(res) )) ){
130 tell_object( ME, "Da darfst Du als Spieler nicht hin.\n" );
131 return ME_NOT_ALLOWED;
132 }
133
134 return ::PreventMove(dest,oldenv,method);
135}
136
137// Fuck. Ausnahmsweise wegen VC brauch ich nen anderes BLUE_NAME
138#define OLD_BLUE_NAME(ob) (explode(object_name(ob),"#")[0])
139// Krams nach dem Move machen und nebenbei zum Ueberschreiben.
140protected void NotifyMove(object dest, object oldenv, int method) {
141
142 // erstmal ggf. Rauminhalt an Spieler ausgeben.
143 if ( interactive(ME) && !(method & M_NO_SHOW) ) {
144 if (!CannotSee(1))
145 tell_object( ME, "" + env_descr(1) );
146 else if ( QueryProp(P_BRIEF) < 2 )
147 tell_object( ME, "Finsternis.\n" );
148 }
149
150 //dann geerbten Kram machen
151 ::NotifyMove(dest,oldenv,method);
152
153 // Schlussendlich noch fuer den PathD bewegung protokollieren.
154 // (dest nicht geprueft, da ein Spieler nicht ausserhalb jedes Env bewegt
155 // werden kann)
156 if ( interactive() && environment() && query_verb() && objectp(oldenv)) {
157 connections += ({ ({ OLD_BLUE_NAME(oldenv), OLD_BLUE_NAME(dest),
158 query_verb() + " " + (_unparsed_args(2) || ""),
159 method, dest->QueryProp(P_PARA) }) });
160
Zesstra49cfed82018-09-20 20:33:16 +0200161 if ( sizeof(connections) > 30
MG Mud User88f12472016-06-24 23:31:02 +0200162 && find_call_out("flush_connections") == -1 )
163 call_out( "flush_connections", 0, connections );
164 }
165}
166
167public void flush_connections() {
168 catch(PATHD->add_paths(connections);publish);
169 connections = ({});
170}
171
172/*** Query-Methoden fuer Froesche... ;^) ***/
173static string _query_msgin()
174{
175 return QueryProp(P_FROG) ? "huepft herein" : Query(P_MSGIN);
176}
177
178
179static string _query_msgout()
180{
181 return QueryProp(P_FROG) ? "huepft" : Query(P_MSGOUT);
182}