blob: 8f7fd64b7e41c7dbe44880995daee48d2b119798 [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;
Zesstra9c053fb2020-03-29 19:18:25 +020025
MG Mud User88f12472016-06-24 23:31:02 +020026 // 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
Vanion50652322020-03-10 21:13:25 +010044 if ( !(tmp = ({int})QueryProp(P_TOTAL_WEIGHT)) )
45 tmp = ({int})QueryProp(P_WEIGHT);
Zesstra9c053fb2020-03-29 19:18:25 +020046
MG Mud User88f12472016-06-24 23:31:02 +020047 // Ist das Objekt nicht zu schwer?
Vanion50652322020-03-10 21:13:25 +010048 if ( (tmp = ({int})dest->MayAddWeight(tmp)) < 0) {
MG Mud User88f12472016-06-24 23:31:02 +020049 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
Zesstra9c053fb2020-03-29 19:18:25 +020072protected object move_norm_dest(object|string dest)
MG Mud User88f12472016-06-24 23:31:02 +020073{
Zesstra9c053fb2020-03-29 19:18:25 +020074 if (objectp(dest))
75 return dest;
MG Mud User88f12472016-06-24 23:31:02 +020076
Zesstra9c053fb2020-03-29 19:18:25 +020077 int parawelt;
78 // Wenn dieses Objekt gerade in einem Lebewesen ist, dann soll das Ziel der
79 // Bewegung implizit in dieselbe Para-Welt erfolgen wie das Living.
80 // parawelt ist die Ziel-Parallelweltnummer
81 if (!environment() || !living(environment()) ||
82 !intp(parawelt =({int})environment()->Query(P_PARA)))
83 parawelt=0;
MG Mud User88f12472016-06-24 23:31:02 +020084
MG Mud User88f12472016-06-24 23:31:02 +020085 // Wenn das Objekt von einem in der Parawelt befindlichen Spieler
86 // oder NPC bewegt wird, sollte es auch wieder in der Parawelt landen.
87 // Um Rechenzeit zu sparen, wird angenommen, dass bei Bewegungen in
88 // das Inv oder Env des Spielers 'dest' als Objekt uebergeben wird,
89 // wohingegen bei Bewegungen in Nachbarraeume (die eigentlich nur
90 // interessant sind) 'dest' als Filename angegeben wird.
Zesstra9c053fb2020-03-29 19:18:25 +020091 if (parawelt && !environment(dest))
92 {
MG Mud User88f12472016-06-24 23:31:02 +020093 // Falls der Zielraum nicht schon explizit in der Parallelwelt ist,
94 // neuen Zielraum suchen. Aber nur, wenn das Ziel kein Clone ist. Sonst
95 // buggt, wenn man versucht, nach raum#42^para zu bewegen.
Zesstra9c053fb2020-03-29 19:18:25 +020096 if (!IS_PARA(dest) && strrstr(dest,"#")==-1)
97 {
98 string fn=dest+"^"+parawelt;
99 string vc;
100 int valid;
MG Mud User88f12472016-06-24 23:31:02 +0200101 // Der Parawelt-Raum wird nur zum Ziel, wenn er a) existiert
102 // und b) auch von Spielern betreten werden darf. Letzteres
103 // Kriterium kann nur mit im Objekt gesetzter Property
104 // P_TESTPLAYER umgangen werden.
105 if ( (find_object(fn) || ((file_size(fn+".c")>0||
106 (file_size(vc=implode(explode(fn,"/")[0..<2],"/")+
107 "/virtual_compiler.c")>0 &&
Zesstra9c053fb2020-03-29 19:18:25 +0200108 !catch(valid=({int})vc->QueryValidObject(fn);publish)
109 && valid>0)) &&
110 !catch(load_object(fn);publish))) &&
MG Mud User88f12472016-06-24 23:31:02 +0200111 (!fn->QueryProp(P_NO_PLAYERS) || QueryProp(P_TESTPLAYER)) )
112 dest = fn;
113 }
114 }
MG Mud User88f12472016-06-24 23:31:02 +0200115 // dest auf Objekt normieren.
116 if (stringp(dest))
117 dest = load_object(dest);
Zesstra9c053fb2020-03-29 19:18:25 +0200118 return dest;
119}
120
121public varargs int move( object|string dest, int method )
122{
123 if (!objectp(dest) && !stringp(dest))
124 raise_error(sprintf("Wrong argument 1 to move(). 'dest' must be a "
125 "string or object! Argument was: %.100O\n",
126 dest));
127
128 // Jetzige Umgebung merken
129 object oldenv = environment();
130
131 dest = move_norm_dest(dest);
132
MG Mud User88f12472016-06-24 23:31:02 +0200133 // testen, ob das Objekt bewegt werden will
Zesstra9c053fb2020-03-29 19:18:25 +0200134 int valid = PreventMove(dest, oldenv, method);
135 if (valid)
136 {
MG Mud User88f12472016-06-24 23:31:02 +0200137 // auf gueltigen Fehler pruefen, wer weiss, was Magier da evtl.
138 // versehentliche zurueckgeben.
Zesstra9c053fb2020-03-29 19:18:25 +0200139 if (VALID_MOVE_ERROR(valid))
140 return(valid);
MG Mud User88f12472016-06-24 23:31:02 +0200141 else
Zesstra9c053fb2020-03-29 19:18:25 +0200142 return ME_DONT_WANT_TO_BE_MOVED;
MG Mud User88f12472016-06-24 23:31:02 +0200143 }
144
145 // Sensitive Objekte muessen entfernt werden
Zesstra9c053fb2020-03-29 19:18:25 +0200146 mixed *sens = QueryProp(P_SENSITIVE);
MG Mud User88f12472016-06-24 23:31:02 +0200147 if (sens && environment())
148 {
149 environment()->RemoveSensitiveObject( this_object() );
150 if (!objectp(ME))
151 return ME_WAS_DESTRUCTED;
152 }
153 // Bewegen
154 move_object(ME, dest);
155
156 //falls (sich) das objekt im init() zerstoert (wurde). (Die u. stehenden
157 //Funktionsaufrufe werden dann vom Driver eh groesstenteils ignoriert.)
158 if (!objectp(this_object())) return(ME_WAS_DESTRUCTED);
159
160 // Objekt informieren. ;-)
161 NotifyMove(environment(), oldenv, method);
162
163 // Alte Umgebung informieren
164 if (oldenv) oldenv->NotifyLeave(this_object(), dest);
165
166 // Wenn das Objekt eine Umgebung hat, selbige informieren
167 if (environment()) {
168 if (sens)
169 {
170 environment()->InsertSensitiveObject(this_object(),sens);
171 if (!objectp(ME)) return ME_WAS_DESTRUCTED;
172 }
173 environment()->NotifyInsert(this_object(), oldenv);
174 }
175 //wurde das Objekt vielleicht noch zerstoert?
176 if (!objectp(ME)) return(ME_WAS_DESTRUCTED);
Zesstra9c053fb2020-03-29 19:18:25 +0200177
MG Mud User88f12472016-06-24 23:31:02 +0200178 //scheint wohl alles ok zu sein.
179 return MOVE_OK;
180}
181
182// Das Objekt zerstoeren
Zesstra02e8b682018-11-28 22:28:15 +0100183public varargs int remove(int silent)
184{
MG Mud User88f12472016-06-24 23:31:02 +0200185 if (environment() ) {
186 if(QueryProp(P_SENSITIVE))
187 environment()->RemoveSensitiveObject(this_object());
188 environment()->NotifyRemove(this_object());
189 }
190 if (objectp(this_object()))
191 destruct(this_object());
192 return 1;
193}
194
195public string NotifyDestruct(object caller) {
196 // Lichtsystem mit der aenderung versorgen. :-/
197 foreach(object env : all_environment() || ({})) {
198 // Ja. Man ruft die _set_xxx()-Funktionen eigentlich nicht direkt auf.
199 // Aber das Lichtsystem ist schon *so* rechenintensiv und gerade der
200 // P_LAST_CONTENT_CHANGE-Cache wird *so* oft benoetigt, dass es mir
201 // da um jedes bisschen Rechenzeit geht.
202 // Der Zweck heiligt ja bekanntlich die Mittel. ;-)
203 //
204 // Tiamak
205 env->_set_last_content_change();
206 }
207 return 0;
208}
209