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; |
| 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 |
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); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 46 | |
| 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? |
| 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... |
| 69 | protected void NotifyMove(object dest, object oldenv, int method) { |
| 70 | } |
| 71 | |
Zesstra | 02e8b68 | 2018-11-28 22:28:15 +0100 | [diff] [blame] | 72 | public varargs int move( object|string dest, int method ) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 73 | { |
| 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())|| |
Vanion | 5065232 | 2020-03-10 21:13:25 +0100 | [diff] [blame^] | 90 | !intp(tmp =({int})environment()->Query(P_PARA))) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 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 && |
Vanion | 5065232 | 2020-03-10 21:13:25 +0100 | [diff] [blame^] | 113 | !catch(tmp=({int})call_other(vc,"QueryValidObject",fn); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 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 |
Zesstra | 02e8b68 | 2018-11-28 22:28:15 +0100 | [diff] [blame] | 174 | public varargs int remove(int silent) |
| 175 | { |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 176 | 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 | |
| 186 | public 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 | |