blob: fbee070f08bd0a72710dbc2f7c62558b685469ef [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
bugfixd94d0932020-04-08 11:27:13 +020029 if (oldenv) ({int})oldenv->PreventLeave(this_object(),dest);
30 ({int})dest->PreventInsert(this_object());
MG Mud User88f12472016-06-24 23:31:02 +020031
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?
bugfixd94d0932020-04-08 11:27:13 +020054 if ( !({int})dest->MayAddObject(this_object()) )
MG Mud User88f12472016-06-24 23:31:02 +020055 return TOO_MANY_OBJECTS;
56
57 // Darf hinausbewegt werden?
bugfixd94d0932020-04-08 11:27:13 +020058 if ( oldenv && ({int})oldenv->PreventLeave(this_object(), dest) )
MG Mud User88f12472016-06-24 23:31:02 +020059 return ME_CANT_LEAVE_ENV;
60
61 // Darf hineinbewegt werden?
bugfixd94d0932020-04-08 11:27:13 +020062 if ( ({int})dest->PreventInsert(this_object()) )
MG Mud User88f12472016-06-24 23:31:02 +020063 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))) &&
bugfixd94d0932020-04-08 11:27:13 +0200111 (!({int})fn->QueryProp(P_NO_PLAYERS) || ({int|string})QueryProp(P_TESTPLAYER)) )
MG Mud User88f12472016-06-24 23:31:02 +0200112 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{
Zesstra9c053fb2020-03-29 19:18:25 +0200123 // Jetzige Umgebung merken
124 object oldenv = environment();
125
126 dest = move_norm_dest(dest);
127
MG Mud User88f12472016-06-24 23:31:02 +0200128 // testen, ob das Objekt bewegt werden will
Zesstra9c053fb2020-03-29 19:18:25 +0200129 int valid = PreventMove(dest, oldenv, method);
130 if (valid)
131 {
MG Mud User88f12472016-06-24 23:31:02 +0200132 // auf gueltigen Fehler pruefen, wer weiss, was Magier da evtl.
133 // versehentliche zurueckgeben.
Zesstra9c053fb2020-03-29 19:18:25 +0200134 if (VALID_MOVE_ERROR(valid))
135 return(valid);
MG Mud User88f12472016-06-24 23:31:02 +0200136 else
Zesstra9c053fb2020-03-29 19:18:25 +0200137 return ME_DONT_WANT_TO_BE_MOVED;
MG Mud User88f12472016-06-24 23:31:02 +0200138 }
139
140 // Sensitive Objekte muessen entfernt werden
Zesstra9c053fb2020-03-29 19:18:25 +0200141 mixed *sens = QueryProp(P_SENSITIVE);
MG Mud User88f12472016-06-24 23:31:02 +0200142 if (sens && environment())
143 {
bugfixd94d0932020-04-08 11:27:13 +0200144 ({void})environment()->RemoveSensitiveObject( this_object() );
MG Mud User88f12472016-06-24 23:31:02 +0200145 if (!objectp(ME))
146 return ME_WAS_DESTRUCTED;
147 }
148 // Bewegen
149 move_object(ME, dest);
150
151 //falls (sich) das objekt im init() zerstoert (wurde). (Die u. stehenden
152 //Funktionsaufrufe werden dann vom Driver eh groesstenteils ignoriert.)
153 if (!objectp(this_object())) return(ME_WAS_DESTRUCTED);
154
155 // Objekt informieren. ;-)
156 NotifyMove(environment(), oldenv, method);
157
158 // Alte Umgebung informieren
bugfixd94d0932020-04-08 11:27:13 +0200159 if (oldenv) ({void})oldenv->NotifyLeave(this_object(), dest);
MG Mud User88f12472016-06-24 23:31:02 +0200160
161 // Wenn das Objekt eine Umgebung hat, selbige informieren
162 if (environment()) {
163 if (sens)
164 {
bugfixd94d0932020-04-08 11:27:13 +0200165 ({void})environment()->InsertSensitiveObject(this_object(),sens);
MG Mud User88f12472016-06-24 23:31:02 +0200166 if (!objectp(ME)) return ME_WAS_DESTRUCTED;
167 }
bugfixd94d0932020-04-08 11:27:13 +0200168 ({void})environment()->NotifyInsert(this_object(), oldenv);
MG Mud User88f12472016-06-24 23:31:02 +0200169 }
170 //wurde das Objekt vielleicht noch zerstoert?
171 if (!objectp(ME)) return(ME_WAS_DESTRUCTED);
Zesstra9c053fb2020-03-29 19:18:25 +0200172
MG Mud User88f12472016-06-24 23:31:02 +0200173 //scheint wohl alles ok zu sein.
174 return MOVE_OK;
175}
176
177// Das Objekt zerstoeren
Zesstra02e8b682018-11-28 22:28:15 +0100178public varargs int remove(int silent)
179{
MG Mud User88f12472016-06-24 23:31:02 +0200180 if (environment() ) {
181 if(QueryProp(P_SENSITIVE))
bugfixd94d0932020-04-08 11:27:13 +0200182 ({void})environment()->RemoveSensitiveObject(this_object());
183 ({void})environment()->NotifyRemove(this_object());
MG Mud User88f12472016-06-24 23:31:02 +0200184 }
185 if (objectp(this_object()))
186 destruct(this_object());
187 return 1;
188}
189
190public string NotifyDestruct(object caller) {
191 // Lichtsystem mit der aenderung versorgen. :-/
192 foreach(object env : all_environment() || ({})) {
193 // Ja. Man ruft die _set_xxx()-Funktionen eigentlich nicht direkt auf.
194 // Aber das Lichtsystem ist schon *so* rechenintensiv und gerade der
195 // P_LAST_CONTENT_CHANGE-Cache wird *so* oft benoetigt, dass es mir
196 // da um jedes bisschen Rechenzeit geht.
197 // Der Zweck heiligt ja bekanntlich die Mittel. ;-)
198 //
199 // Tiamak
bugfixd94d0932020-04-08 11:27:13 +0200200 ({int})env->_set_last_content_change();
MG Mud User88f12472016-06-24 23:31:02 +0200201 }
202 return 0;
203}
204