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