MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 1 | // 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 User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 11 | |
| 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 |
| 23 | protected int PreventMove(object dest, object oldenv, int method) { |
| 24 | int tmp; |
Zesstra | 9c053fb | 2020-03-29 19:18:25 +0200 | [diff] [blame] | 25 | |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 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 |
bugfix | d94d093 | 2020-04-08 11:27:13 +0200 | [diff] [blame] | 29 | if (oldenv) ({int})oldenv->PreventLeave(this_object(),dest); |
| 30 | ({int})dest->PreventInsert(this_object()); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 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 |
Vanion | 5065232 | 2020-03-10 21:13:25 +0100 | [diff] [blame] | 44 | if ( !(tmp = ({int})QueryProp(P_TOTAL_WEIGHT)) ) |
| 45 | tmp = ({int})QueryProp(P_WEIGHT); |
Zesstra | 9c053fb | 2020-03-29 19:18:25 +0200 | [diff] [blame] | 46 | |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 47 | // Ist das Objekt nicht zu schwer? |
Vanion | 5065232 | 2020-03-10 21:13:25 +0100 | [diff] [blame] | 48 | if ( (tmp = ({int})dest->MayAddWeight(tmp)) < 0) { |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 49 | if ( tmp == -2 ) return ME_TOO_HEAVY_FOR_ENV; |
| 50 | return ME_TOO_HEAVY; |
| 51 | } |
| 52 | |
| 53 | // Ist das Zielobjekt schon voll? |
bugfix | d94d093 | 2020-04-08 11:27:13 +0200 | [diff] [blame] | 54 | if ( !({int})dest->MayAddObject(this_object()) ) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 55 | return TOO_MANY_OBJECTS; |
| 56 | |
| 57 | // Darf hinausbewegt werden? |
bugfix | d94d093 | 2020-04-08 11:27:13 +0200 | [diff] [blame] | 58 | if ( oldenv && ({int})oldenv->PreventLeave(this_object(), dest) ) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 59 | return ME_CANT_LEAVE_ENV; |
| 60 | |
| 61 | // Darf hineinbewegt werden? |
bugfix | d94d093 | 2020-04-08 11:27:13 +0200 | [diff] [blame] | 62 | if ( ({int})dest->PreventInsert(this_object()) ) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 63 | return ME_CANT_BE_INSERTED; |
| 64 | |
| 65 | return(0); |
| 66 | } |
| 67 | |
| 68 | // zum Ueberschreiben... |
| 69 | protected void NotifyMove(object dest, object oldenv, int method) { |
| 70 | } |
| 71 | |
Zesstra | 9c053fb | 2020-03-29 19:18:25 +0200 | [diff] [blame] | 72 | protected object move_norm_dest(object|string dest) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 73 | { |
Zesstra | 9c053fb | 2020-03-29 19:18:25 +0200 | [diff] [blame] | 74 | if (objectp(dest)) |
| 75 | return dest; |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 76 | |
Zesstra | 9c053fb | 2020-03-29 19:18:25 +0200 | [diff] [blame] | 77 | 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 User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 84 | |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 85 | // 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. |
Zesstra | 9c053fb | 2020-03-29 19:18:25 +0200 | [diff] [blame] | 91 | if (parawelt && !environment(dest)) |
| 92 | { |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 93 | // 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. |
Zesstra | 9c053fb | 2020-03-29 19:18:25 +0200 | [diff] [blame] | 96 | if (!IS_PARA(dest) && strrstr(dest,"#")==-1) |
| 97 | { |
| 98 | string fn=dest+"^"+parawelt; |
| 99 | string vc; |
| 100 | int valid; |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 101 | // 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 && |
Zesstra | 9c053fb | 2020-03-29 19:18:25 +0200 | [diff] [blame] | 108 | !catch(valid=({int})vc->QueryValidObject(fn);publish) |
| 109 | && valid>0)) && |
| 110 | !catch(load_object(fn);publish))) && |
bugfix | d94d093 | 2020-04-08 11:27:13 +0200 | [diff] [blame] | 111 | (!({int})fn->QueryProp(P_NO_PLAYERS) || ({int|string})QueryProp(P_TESTPLAYER)) ) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 112 | dest = fn; |
| 113 | } |
| 114 | } |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 115 | // dest auf Objekt normieren. |
| 116 | if (stringp(dest)) |
| 117 | dest = load_object(dest); |
Zesstra | 9c053fb | 2020-03-29 19:18:25 +0200 | [diff] [blame] | 118 | return dest; |
| 119 | } |
| 120 | |
| 121 | public varargs int move( object|string dest, int method ) |
| 122 | { |
Zesstra | 9c053fb | 2020-03-29 19:18:25 +0200 | [diff] [blame] | 123 | // Jetzige Umgebung merken |
| 124 | object oldenv = environment(); |
| 125 | |
| 126 | dest = move_norm_dest(dest); |
| 127 | |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 128 | // testen, ob das Objekt bewegt werden will |
Zesstra | 9c053fb | 2020-03-29 19:18:25 +0200 | [diff] [blame] | 129 | int valid = PreventMove(dest, oldenv, method); |
| 130 | if (valid) |
| 131 | { |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 132 | // auf gueltigen Fehler pruefen, wer weiss, was Magier da evtl. |
| 133 | // versehentliche zurueckgeben. |
Zesstra | 9c053fb | 2020-03-29 19:18:25 +0200 | [diff] [blame] | 134 | if (VALID_MOVE_ERROR(valid)) |
| 135 | return(valid); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 136 | else |
Zesstra | 9c053fb | 2020-03-29 19:18:25 +0200 | [diff] [blame] | 137 | return ME_DONT_WANT_TO_BE_MOVED; |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 138 | } |
| 139 | |
| 140 | // Sensitive Objekte muessen entfernt werden |
Zesstra | 9c053fb | 2020-03-29 19:18:25 +0200 | [diff] [blame] | 141 | mixed *sens = QueryProp(P_SENSITIVE); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 142 | if (sens && environment()) |
| 143 | { |
bugfix | d94d093 | 2020-04-08 11:27:13 +0200 | [diff] [blame] | 144 | ({void})environment()->RemoveSensitiveObject( this_object() ); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 145 | 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 |
bugfix | d94d093 | 2020-04-08 11:27:13 +0200 | [diff] [blame] | 159 | if (oldenv) ({void})oldenv->NotifyLeave(this_object(), dest); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 160 | |
| 161 | // Wenn das Objekt eine Umgebung hat, selbige informieren |
| 162 | if (environment()) { |
| 163 | if (sens) |
| 164 | { |
bugfix | d94d093 | 2020-04-08 11:27:13 +0200 | [diff] [blame] | 165 | ({void})environment()->InsertSensitiveObject(this_object(),sens); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 166 | if (!objectp(ME)) return ME_WAS_DESTRUCTED; |
| 167 | } |
bugfix | d94d093 | 2020-04-08 11:27:13 +0200 | [diff] [blame] | 168 | ({void})environment()->NotifyInsert(this_object(), oldenv); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 169 | } |
| 170 | //wurde das Objekt vielleicht noch zerstoert? |
| 171 | if (!objectp(ME)) return(ME_WAS_DESTRUCTED); |
Zesstra | 9c053fb | 2020-03-29 19:18:25 +0200 | [diff] [blame] | 172 | |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 173 | //scheint wohl alles ok zu sein. |
| 174 | return MOVE_OK; |
| 175 | } |
| 176 | |
| 177 | // Das Objekt zerstoeren |
Zesstra | 02e8b68 | 2018-11-28 22:28:15 +0100 | [diff] [blame] | 178 | public varargs int remove(int silent) |
| 179 | { |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 180 | if (environment() ) { |
| 181 | if(QueryProp(P_SENSITIVE)) |
bugfix | d94d093 | 2020-04-08 11:27:13 +0200 | [diff] [blame] | 182 | ({void})environment()->RemoveSensitiveObject(this_object()); |
| 183 | ({void})environment()->NotifyRemove(this_object()); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 184 | } |
| 185 | if (objectp(this_object())) |
| 186 | destruct(this_object()); |
| 187 | return 1; |
| 188 | } |
| 189 | |
| 190 | public 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 |
bugfix | d94d093 | 2020-04-08 11:27:13 +0200 | [diff] [blame] | 200 | ({int})env->_set_last_content_change(); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 201 | } |
| 202 | return 0; |
| 203 | } |
| 204 | |