blob: 780ac41ba9ea9906535cb66d2f1f132a3609ca46 [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// MorgenGrauen MUDlib
2//
3// thing/moving.c -- object moving
4//
5// $Id: moving.c 8892 2014-08-04 19:48:28Z Zesstra $
6
7#pragma strict_types
8#pragma save_types
9#pragma range_check
10#pragma no_clone
11#pragma pedantic
12
13#include <defines.h>
14#include <moving.h>
15#include <properties.h>
16#define NEED_PROTOTYPES
17#include <thing/properties.h>
18
19// Das Objekt bewegen.
20// Rueckgabe 1 ist Erfolg, <=0 ist Fehler
21
22// a) P_NODROP/P_NOGET-Behandlung.
23// b) zum Ueberschreiben
24protected int PreventMove(object dest, object oldenv, int method) {
25 int tmp;
26
27 // M_NOCHECK? -> Bewegung eh erlaubt (und Rueckgabewert wuerde ignoriert)
28 if ((method&M_NOCHECK)) {
29 // Bei M_NOCHECK zwar Prevent* aufrufen, aber das Resultat ignorieren
30 if (oldenv) oldenv->PreventLeave(this_object(),dest);
31 dest->PreventInsert(this_object());
32
33 return 0; // das wars, rest ist egal.
34 }
35
36 // P_NODROP verhindert weggeben
37 if ((method & (M_PUT|M_GIVE)) && QueryProp(P_NODROP))
38 return ME_CANT_BE_DROPPED;
39
40 // P_NOGET verhindert nehmen
41 if ((method & (M_GET|M_GIVE)) && QueryProp(P_NOGET))
42 return ME_CANT_BE_TAKEN;
43
44 // Gewicht ermitteln
45 if ( !(tmp = (int)QueryProp(P_TOTAL_WEIGHT)) )
46 tmp = (int)QueryProp(P_WEIGHT);
47
48 // Ist das Objekt nicht zu schwer?
49 if ( (tmp = (int)dest->MayAddWeight(tmp)) < 0) {
50 if ( tmp == -2 ) return ME_TOO_HEAVY_FOR_ENV;
51 return ME_TOO_HEAVY;
52 }
53
54 // Ist das Zielobjekt schon voll?
55 if ( !dest->MayAddObject(this_object()) )
56 return TOO_MANY_OBJECTS;
57
58 // Darf hinausbewegt werden?
59 if ( oldenv && oldenv->PreventLeave(this_object(), dest) )
60 return ME_CANT_LEAVE_ENV;
61
62 // Darf hineinbewegt werden?
63 if ( dest->PreventInsert(this_object()) )
64 return ME_CANT_BE_INSERTED;
65
66 return(0);
67}
68
69// zum Ueberschreiben...
70protected void NotifyMove(object dest, object oldenv, int method) {
71}
72
73varargs int move( object|string dest, int method )
74{
75 object oldenv;
76 int tmp;
77 string fn,vc;
78 mixed sens;
79
80 if (!objectp(dest) && !stringp(dest))
81 raise_error(sprintf("Wrong argument 1 to move(). 'dest' must be a "
82 "string or object! Argument was: %.100O\n",
83 dest));
84
85 // Jetzige Umgebung merken
86 oldenv = environment();
87
88 // Bewegung in Para-Welt-Raeume?
89 // tmp ist die Ziel-Parallelweltnummer
90 if (!environment()||!living(environment())||
91 !intp(tmp =(int)environment()->Query(P_PARA)))
92 tmp=0;
93
94 // Wenn das Objekt von einem in der Parawelt befindlichen Spieler
95 // oder NPC bewegt wird, sollte es auch wieder in der Parawelt landen.
96 // Um Rechenzeit zu sparen, wird angenommen, dass bei Bewegungen in
97 // das Inv oder Env des Spielers 'dest' als Objekt uebergeben wird,
98 // wohingegen bei Bewegungen in Nachbarraeume (die eigentlich nur
99 // interessant sind) 'dest' als Filename angegeben wird.
100 if (tmp&&!objectp(dest)&&!environment(dest)) {
101 // Falls der Zielraum nicht schon explizit in der Parallelwelt ist,
102 // neuen Zielraum suchen. Aber nur, wenn das Ziel kein Clone ist. Sonst
103 // buggt, wenn man versucht, nach raum#42^para zu bewegen.
104 if (!IS_PARA(dest) && strrstr(dest,"#")==-1) {
105 fn=dest+"^"+tmp;
106
107 // Der Parawelt-Raum wird nur zum Ziel, wenn er a) existiert
108 // und b) auch von Spielern betreten werden darf. Letzteres
109 // Kriterium kann nur mit im Objekt gesetzter Property
110 // P_TESTPLAYER umgangen werden.
111 if ( (find_object(fn) || ((file_size(fn+".c")>0||
112 (file_size(vc=implode(explode(fn,"/")[0..<2],"/")+
113 "/virtual_compiler.c")>0 &&
114 !catch(tmp=(int)call_other(vc,"QueryValidObject",fn);
115 publish) && tmp>0)) &&
116 !catch(load_object( fn );publish))) &&
117 (!fn->QueryProp(P_NO_PLAYERS) || QueryProp(P_TESTPLAYER)) )
118 dest = fn;
119 }
120 }
121
122 // dest auf Objekt normieren.
123 if (stringp(dest))
124 dest = load_object(dest);
125
126 // testen, ob das Objekt bewegt werden will
127 if (tmp=PreventMove(dest, oldenv, method)) {
128 // auf gueltigen Fehler pruefen, wer weiss, was Magier da evtl.
129 // versehentliche zurueckgeben.
130 if (VALID_MOVE_ERROR(tmp))
131 return(tmp);
132 else
133 return(ME_DONT_WANT_TO_BE_MOVED);
134 }
135
136 // Sensitive Objekte muessen entfernt werden
137 sens = QueryProp(P_SENSITIVE);
138
139 if (sens && environment())
140 {
141 environment()->RemoveSensitiveObject( this_object() );
142 if (!objectp(ME))
143 return ME_WAS_DESTRUCTED;
144 }
145 // Bewegen
146 move_object(ME, dest);
147
148 //falls (sich) das objekt im init() zerstoert (wurde). (Die u. stehenden
149 //Funktionsaufrufe werden dann vom Driver eh groesstenteils ignoriert.)
150 if (!objectp(this_object())) return(ME_WAS_DESTRUCTED);
151
152 // Objekt informieren. ;-)
153 NotifyMove(environment(), oldenv, method);
154
155 // Alte Umgebung informieren
156 if (oldenv) oldenv->NotifyLeave(this_object(), dest);
157
158 // Wenn das Objekt eine Umgebung hat, selbige informieren
159 if (environment()) {
160 if (sens)
161 {
162 environment()->InsertSensitiveObject(this_object(),sens);
163 if (!objectp(ME)) return ME_WAS_DESTRUCTED;
164 }
165 environment()->NotifyInsert(this_object(), oldenv);
166 }
167 //wurde das Objekt vielleicht noch zerstoert?
168 if (!objectp(ME)) return(ME_WAS_DESTRUCTED);
169
170 //scheint wohl alles ok zu sein.
171 return MOVE_OK;
172}
173
174// Das Objekt zerstoeren
175varargs int remove(int silent)
176{
177 if (environment() ) {
178 if(QueryProp(P_SENSITIVE))
179 environment()->RemoveSensitiveObject(this_object());
180 environment()->NotifyRemove(this_object());
181 }
182 if (objectp(this_object()))
183 destruct(this_object());
184 return 1;
185}
186
187public string NotifyDestruct(object caller) {
188 // Lichtsystem mit der aenderung versorgen. :-/
189 foreach(object env : all_environment() || ({})) {
190 // Ja. Man ruft die _set_xxx()-Funktionen eigentlich nicht direkt auf.
191 // Aber das Lichtsystem ist schon *so* rechenintensiv und gerade der
192 // P_LAST_CONTENT_CHANGE-Cache wird *so* oft benoetigt, dass es mir
193 // da um jedes bisschen Rechenzeit geht.
194 // Der Zweck heiligt ja bekanntlich die Mittel. ;-)
195 //
196 // Tiamak
197 env->_set_last_content_change();
198 }
199 return 0;
200}
201