#include <hook.h>#include <living/moving.h>#include <living/skills.h>#include <thing/properties.h>#include <thing/description.h>#include <moving.h>#include <new_skills.h>#include <living.h>#include <config.h>#include <language.h>#include <wizlevels.h>#include <defines.h>
gehe zum Quellcode dieser Datei
Makrodefinitionen | |
| #define | NEED_PROTOTYPES |
Funktionen | |
| public void | create () |
| public void | AddPursuer (object ob) |
| public void | RemovePursuer (object ob) |
| public void | _SetPursued (object ob) |
| public void | _RemovePursued (object ob) |
| private void | kampfende (object en) |
| private int | _is_learner (object pl) |
| protected int | PreventMove (object dest, object oldenv, int method) |
| protected void | NotifyMove (object dest, object oldenv, int method) |
| varargs public int | move (mixed dest, int method, string direction, string textout, string textin) |
| public void | TakeFollowers () |
| varargs public int | remove () |
| private int _is_learner | ( | object | pl | ) |
Definiert in Zeile 102 der Datei moving.c.
Benutzt IS_LEARNER.
00102 { 00103 return IS_LEARNER(pl); 00104 }
| public void _RemovePursued | ( | object | ob | ) |
Definiert in Zeile 80 der Datei moving.c.
Benutzt P_PURSUERS, Query() und Set().
00081 { 00082 mixed *pur; 00083 00084 if (!pointerp(pur=Query(P_PURSUERS)) || pur[0]!=ob) 00085 return; 00086 pur[0]=0; 00087 pur[1]-=({0}); 00088 if (!sizeof(pur[1])) 00089 pur=0; 00090 Set(P_PURSUERS,pur); 00091 }

| public void _SetPursued | ( | object | ob | ) |
Definiert in Zeile 66 der Datei moving.c.
Benutzt ME, P_PURSUERS, Query(), RemovePursuer() und Set().
00067 { 00068 mixed *pur; 00069 00070 if (!pointerp(pur=Query(P_PURSUERS))) 00071 pur=({0,({})}); 00072 else 00073 if (objectp(pur[0])) 00074 pur[0]->RemovePursuer(ME); 00075 pur[0]=ob; 00076 pur[1]-=({0}); 00077 Set(P_PURSUERS,pur); 00078 }

| public void AddPursuer | ( | object | ob | ) |
Definiert in Zeile 36 der Datei moving.c.
Benutzt ME, P_PURSUERS, Query() und SetProp().
00037 { 00038 mixed *pur; 00039 00040 if (!objectp(ob)) 00041 return; 00042 00043 if (!pointerp(pur=Query(P_PURSUERS))) 00044 pur=({0,({})}); 00045 else 00046 if (member(pur[1],ob)!=-1) 00047 return; 00048 SetProp(P_PURSUERS,({ pur[0], pur[1]+({ob})-({0}) })); 00049 ob->_SetPursued(ME); 00050 }

| public void create | ( | ) |
Definiert in Zeile 31 der Datei moving.c.
Benutzt H_HOOK_MOVE und offerHook().
00031 { 00032 offerHook(H_HOOK_MOVE,1); 00033 }

| varargs public int move | ( | mixed | dest, | |
| int | method, | |||
| string | direction, | |||
| string | textout, | |||
| string | textin | |||
| ) |
Definiert in Zeile 178 der Datei moving.c.
Benutzt ExitAttack(), H_ALTERED, H_CANCELLED, H_HOOK_MOVE, H_RETCODE, H_RETDATA, HookFlow(), inv(), invis, IS_LEARNER, M_NO_ATTACK, M_NOCHECK, M_SILENT, M_TPORT, ME, ME_CANT_LEAVE_ENV, ME_DONT_WANT_TO_BE_MOVED, ME_WAS_DESTRUCTED, mout, name, Name(), P_MMSGOUT, P_MSGOUT, P_NO_PLAYERS, P_PARA, P_TESTPLAYER, P_TMP_MOVE_HOOK, PreventMove(), QueryEnemies(), QueryProp(), SetProp(), VALID_MOVE_ERROR und WER.
00180 { 00181 int para, nightvis, invis, tmp; 00182 object oldenv, *inv; 00183 string fn,vc; 00184 mixed res; 00185 mixed hookData, hookRes; 00186 00187 if (!objectp(dest) && !stringp(dest)) 00188 raise_error(sprintf("Wrong argument 1 to move(). 'dest' must be a " 00189 "string or object! Argument was: %.100O\n", 00190 dest)); 00191 00192 // altes Env erstmal merken. 00193 oldenv = environment(); 00194 00195 //erstmal den richtigen Zielraum suchen, bevor irgendwelche Checks gemacht 00196 //werden... 00197 // Ist der Spieler in einer Parallelwelt? 00198 if ( (para = QueryProp(P_PARA)) && intp(para) ) { 00199 fn = objectp(dest) ? object_name(dest) : dest; 00200 00201 // Falls der Zielraum nicht schon explizit in der Parallelwelt ist, 00202 // neuen Zielraum suchen. Aber nur, wenn fn kein # enthaelt (also kein 00203 // Clone ist), sonst wuerde eine Bewegung nach raum#42^para versucht, 00204 // was dann buggt. ;-) Problem wird offenbar, wenn ein Para-Lebewesen 00205 // im create() eines VC-Raums in Para in den Raum bewegt wird, da 00206 // dieser dann noch nicht vom Driver umbenannt wurde und raum#42 00207 // heisst. 00208 if ( !sizeof(regexp( ({ fn }), "\\^[1-9][0-9]*$" )) && 00209 strrstr(fn,"#")==-1 ) { 00210 fn += "^" + para; 00211 00212 // Der Parallelwelt-Raum muss existieren und fuer Spieler 00213 // freigegeben sein, damit er zum neuen Ziel wird. Ansonsten 00214 // duerfen nur NPCs, Testspieler und Magier herein. 00215 if ( (find_object(fn) 00216 || ((file_size(fn+".c")>0 || 00217 (file_size(vc=implode(explode(fn,"/")[0..<2],"/")+ 00218 "/virtual_compiler.c")>0 && 00219 !catch(tmp=(int)call_other(vc,"QueryValidObject",fn); 00220 publish) && tmp>0)) && 00221 !catch(load_object(fn);publish) )) && 00222 (!interactive(ME) || !fn->QueryProp(P_NO_PLAYERS) || 00223 (method & M_NOCHECK) || IS_LEARNER(ME) || 00224 (stringp(res = QueryProp(P_TESTPLAYER)) && 00225 IS_LEARNER( lower_case(res) ))) ) 00226 dest = fn; 00227 else 00228 // Wir bleiben in der Normalwelt. 00229 para = 0; 00230 } 00231 } 00232 00233 // jetzt erstmal Hooks abpruefen, da sie ggf. die Daten aendern. 00234 // alten P_TMP_MOVE_HOOK pruefen. 00235 if ( res = QueryProp(P_TMP_MOVE_HOOK) ){ 00236 if ( pointerp(res) && sizeof(res) >= 3 00237 && intp(res[0]) && time()<res[0] 00238 && objectp(res[1]) && stringp(res[2]) ){ 00239 if ( res = call_other( res[1], res[2], dest, method, direction, 00240 textout, textin ) ){ 00241 if ( pointerp(res) && sizeof(res) == 5 ){ 00242 dest = res[0]; 00243 method = res[1]; 00244 direction = res[2]; 00245 textout = res[3]; 00246 textin = res[4]; 00247 } 00248 else if ( intp(res) && res == -1 ) 00249 return ME_CANT_LEAVE_ENV; 00250 } 00251 } else 00252 SetProp( P_TMP_MOVE_HOOK, 0 ); 00253 } 00254 // move hook nach neuem Hooksystem triggern. 00255 hookData=({dest,method,direction,textout,textin}); 00256 hookRes=HookFlow(H_HOOK_MOVE,hookData); 00257 if(hookRes && pointerp(hookRes) && sizeof(hookRes)>H_RETDATA) { 00258 if(hookRes[H_RETCODE]==H_CANCELLED) { 00259 return ME_CANT_LEAVE_ENV; 00260 } 00261 else if(hookRes[H_RETCODE]==H_ALTERED && hookRes[H_RETDATA] && 00262 pointerp(hookRes[H_RETDATA]) && sizeof(hookRes[H_RETDATA])>=5 ){ 00263 dest = hookRes[H_RETDATA][0]; 00264 method = hookRes[H_RETDATA][1]; 00265 direction = hookRes[H_RETDATA][2]; 00266 textout = hookRes[H_RETDATA][3]; 00267 textin = hookRes[H_RETDATA][4]; 00268 } 00269 } 00270 00271 // dest auf Object normieren 00272 if (stringp(dest)) dest=load_object(dest); 00273 00274 // jetzt Checks durchfuehren, ob das Move durchgefuehrt werden darf. 00275 if (tmp=PreventMove(dest, oldenv, method)) { 00276 // auf gueltigen Fehler pruefen, wer weiss, was Magier da evtl. 00277 // versehentlich zurueckgeben. 00278 if (VALID_MOVE_ERROR(tmp)) 00279 return(tmp); 00280 else 00281 return(ME_DONT_WANT_TO_BE_MOVED); 00282 } 00283 00284 if ( invis = QueryProp(P_INVIS) ) 00285 method |= M_SILENT; 00286 00287 if ( objectp(oldenv) ) { 00288 if ( !(method & M_SILENT) ) { 00289 string *mout; 00290 if ( !textout ){ 00291 if ( method & M_TPORT ) 00292 textout = (string) QueryProp(P_MMSGOUT) || 00293 (string) QueryProp(P_MSGOUT); 00294 else 00295 textout = (mout = explode( (string) 00296 QueryProp(P_MSGOUT) || "", 00297 "#" ))[0] 00298 || (string)QueryProp(P_MMSGOUT); 00299 } 00300 00301 if ( !strlen(direction) ) 00302 direction = 0; 00303 00304 inv = all_inventory(environment()) - ({ this_object() }); 00305 inv = filter( inv, #'living/*'*/ ); 00306 inv -= filter_objects( inv, "CannotSee", 1 ); 00307 00308 filter( inv, #'tell_object/*'*/, 00309 Name( WER, 2 ) + " " + textout + 00310 (direction ? " " + direction : "") + 00311 (sizeof(mout) > 1 ? mout[1] : "") + ".\n" ); 00312 } 00313 // Magier sehen auch Bewegungen, die M_SILENT sind 00314 else if ( interactive(ME) ){ 00315 inv = (all_inventory(environment()) & users()) 00316 - ({ this_object() }); 00317 inv = filter( inv, #'_is_learner/*'*/ ); 00318 00319 if ( invis ) 00320 fn = "(" + capitalize(getuid(ME)) + ") verschwindet " 00321 "unsichtbar.\n"; 00322 else 00323 fn = capitalize(getuid(ME)) + " verschwindet ganz leise.\n"; 00324 00325 filter( inv, #'tell_object/*'*/, fn ); 00326 } 00327 00328 // Nackenschlag beim Fluechten: 00329 if ( !(method & M_NO_ATTACK) && objectp(ME) ) 00330 ExitAttack(); 00331 //falls nach ExitAttack() das Living nicht mehr existiert, muss das 00332 //move() auch nicht mehr fortgesetzt werden. Weiter unten gibt es auch 00333 //min. eine Stelle, die nicht prueft und ggf. buggt. Daher erfolgt 00334 //hier ggf. ein Abbruch. 15.11.06 Zesstra 00335 if (!objectp(ME)) return(ME_WAS_DESTRUCTED); 00336 00337 // Nackenschlag kann ME in den Todesraum bewegt haben... 00338 if ( oldenv == environment() ) { 00339 // Fuer alle anwesenden gegner kampfende() aufrufen 00340 filter((QueryEnemies()[0] & all_inventory(oldenv))-({0}), 00341 #'kampfende); 00342 // Bugs im exit() sind ohne catch() einfach mist. 00343 catch(environment()->exit(ME, dest);publish); 00344 } 00345 } 00346 00347 // irgendwas kann das Objekt zerstoert haben, z.B. env->exit(). 00348 if (!objectp(ME)) return(ME_WAS_DESTRUCTED); 00349 00350 if ( oldenv != environment() ) 00351 // Der Nackenschlag oder exit() koennen einen schon bewegt haben. 00352 // Und wenn es in den Todesraum ist. ;^) 00353 return MOVE_OK; 00354 00355 SetProp( P_PREPARED_SPELL, 0 ); // Spruchvorbereitung abgebrochen 00356 SetProp( P_LAST_MOVE, time() ); // Zeitpunkt der letzten Bewegung 00357 00358 move_object(ME, dest); 00359 if (!objectp(ME)) 00360 return(ME_WAS_DESTRUCTED); 00361 00362 dest = environment(); 00363 00364 nightvis = UseSkill(SK_NIGHTVISION); 00365 // Meldungen an nicht-Blinde ausgeben, falls keine 'stille' Bewegung 00366 if ( !(method & M_SILENT) ) { 00367 if ( !textin ) { 00368 if ( method & M_TPORT ) 00369 textin = (string) QueryProp(P_MMSGIN); 00370 else 00371 textin = (string) QueryProp(P_MSGIN); 00372 } 00373 00374 inv = all_inventory(environment()) - ({ this_object() }); 00375 inv = filter( inv, #'living/*'*/ ); 00376 inv -= filter_objects( inv, "CannotSee", 1 ); 00377 filter( inv, #'tell_object/*'*/, 00378 capitalize(name( WER, 0 )) + " " + textin + ".\n" ); 00379 } 00380 // sonst: Magier sehen auch M_SILENT-Bewegungen, hier also nur an Magier 00381 // ausgeben, alle anderen sehen eh nix. 00382 else if ( interactive(ME) ) { 00383 inv = (all_inventory(environment()) & users()) - ({this_object()}); 00384 inv = filter( inv, #'_is_learner/*'*/ ); 00385 if ( invis ) 00386 fn = "(" + capitalize(getuid(ME)) + ") taucht unsichtbar auf.\n"; 00387 else 00388 fn = capitalize(getuid(ME)) + " schleicht leise herein.\n"; 00389 filter( inv, #'tell_object, fn ); 00390 } 00391 00392 // "Objekt" ueber das Move informieren. 00393 NotifyMove(dest, oldenv, method); 00394 00395 // InitAttack() in NotifyMove() kann das Objekt zerstoert haben. 00396 if (!objectp(ME)) 00397 return(ME_WAS_DESTRUCTED); 00398 00399 //scheint wohl geklappt zu haben. 00400 return MOVE_OK; 00401 }

| protected void NotifyMove | ( | object | dest, | |
| object | oldenv, | |||
| int | method | |||
| ) |
Definiert in Zeile 152 der Datei moving.c.
Benutzt call_out(), InitAttack(), IsTeamLeader(), M_NO_ATTACK, ME, P_PURSUERS, P_TEAM_AUTOFOLLOW, Query() und QueryProp().
00152 { 00153 mixed res; 00154 object enem; 00155 00156 // Begruessungsschlag fuer die Gegener 00157 if ( !(method & M_NO_ATTACK) ) 00158 InitAttack(); 00159 00160 if (!objectp(ME)) return; 00161 00162 // Verfolger nachholen. 00163 if ( pointerp(res = Query(P_PURSUERS)) && sizeof(res[1]) ) { 00164 while ( remove_call_out( "TakeFollowers" ) >= 0 ); 00165 00166 call_out( "TakeFollowers", 0 ); 00167 } 00168 00169 // und noch das Team nachholen. 00170 if ( oldenv != dest 00171 && objectp(ME) 00172 && QueryProp(P_TEAM_AUTOFOLLOW) 00173 && objectp( enem = IsTeamLeader() ) ) 00174 enem->StartFollow(oldenv); // Teamverfolgung 00175 00176 }

| protected int PreventMove | ( | object | dest, | |
| object | oldenv, | |||
| int | method | |||
| ) |
Definiert in Zeile 109 der Datei moving.c.
Benutzt M_GO, M_NOCHECK, M_TPORT, ME_CANT_BE_INSERTED, ME_CANT_LEAVE_ENV, ME_CANT_TPORT_IN, ME_CANT_TPORT_OUT, ME_PLAYER, NO_TPORT, NO_TPORT_IN, NO_TPORT_OUT, P_NO_TPORT und QueryProp().
00109 { 00110 00111 // M_NOCHECK? -> Bewegung eh erlaubt (und Rueckgabewert wuerde ignoriert), 00112 // aber PreventInsert/PreventLeave() rufen und ignorieren. 00113 if ((method&M_NOCHECK)) { 00114 // erst PreventLeaveLiving() rufen... 00115 if(environment()) 00116 environment()->PreventLeaveLiving(this_object(), dest); 00117 // dann PreventInsertLiving() im Ziel-Env. 00118 dest->PreventInsertLiving(this_object()); 00119 // und raus... 00120 return(0); 00121 } 00122 00123 // bei Lebewesen muss die Bewegungsmethode M_GO und M_TPORT sein. Dies ist 00124 // gleichzeigt die Restriktion gegen das Nehmen von Lebewesen, da dort 00125 // M_GET/M_GIVE/M_PUT etc. verwendet wuerde. Bei M_GO und M_TPORT findet 00126 // keine Pruefung statt, ob das Objekt ins Ziel 'reinpasst' (Gewicht, Anzahl 00127 // Objekte usw.). 00128 // Ich finde es etwas merkwuerdig gebaut (Zesstra). 00129 if ( !(method & (M_GO | M_TPORT)) ) 00130 return ME_PLAYER; 00131 00132 // alte und neue Umgebung auf NO_TPORT pruefen. 00133 if ( (method & M_TPORT) ) { 00134 if ( environment() && 00135 (environment()->QueryProp(P_NO_TPORT) & (NO_TPORT_OUT|NO_TPORT)) ) 00136 return ME_CANT_TPORT_OUT; 00137 else if ( dest->QueryProp(P_NO_TPORT) & (NO_TPORT_IN|NO_TPORT) ) 00138 return ME_CANT_TPORT_IN; 00139 } 00140 00141 // erst PreventLeaveLiving() testen... 00142 if( environment() && environment()->PreventLeaveLiving(this_object(), dest)) 00143 return ME_CANT_LEAVE_ENV; 00144 // dann PreventInsertLiving() im Ziel-Env 00145 if (dest->PreventInsertLiving(this_object())) 00146 return ME_CANT_BE_INSERTED; 00147 00148 return 0; 00149 }

| varargs public int remove | ( | ) |
| public void RemovePursuer | ( | object | ob | ) |
Definiert in Zeile 52 der Datei moving.c.
Benutzt ME, P_PURSUERS, Query() und SetProp().
Wird benutzt von _SetPursued().
00053 { 00054 mixed *pur; 00055 00056 if (pointerp(pur=Query(P_PURSUERS)) && member(pur[1],ob)!=-1) 00057 { 00058 pur[1]-=({ob,0}); 00059 ob->_RemovePursued(ME); 00060 if (!pur[0]&&!sizeof(pur[1])) 00061 pur=0; 00062 SetProp(P_PURSUERS,pur); 00063 } 00064 }


| public void TakeFollowers | ( | ) |
Definiert in Zeile 403 der Datei moving.c.
Wird benutzt von modify_command().
00404 { 00405 mixed *f,env; 00406 int meth,i,r; 00407 00408 f=Query(P_PURSUERS); 00409 if (!pointerp(f)) 00410 return; 00411 env=environment(); 00412 if(object_name(env) == "/room/netztot") return; 00413 foreach(object follower: f[1]-({0}) ) { 00414 // die pruefung auf objectp ist nicht verrueckt, es kann theo. sein, dass 00415 // Verfolger im PreventFollow() oder in ihrem move/init andere Verfolger 00416 // zerstoeren. 00417 if (objectp(follower) && environment(follower)!=env) { 00418 //meth=M_NOCHECK; 00419 meth=M_GO; 00420 if (follower->Query(P_FOLLOW_SILENT)) 00421 meth|=M_SILENT|M_NO_SHOW; 00422 catch(r=follower->PreventFollow(env);publish); 00423 if (!r) 00424 follower->move(env,meth); 00425 else if (r==2) 00426 RemovePursuer(follower); 00427 } 00428 } 00429 }

1.6.3