blob: 08882833c8c79d2abeffae8618419a1b511f21bc [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// MorgenGrauen MUDlib
2//
3// transport.c -- Basisklasse fuer Schiffe und aehnliche Transporter
4//
5// $Id: transport.c 9400 2015-12-11 21:56:14Z Zesstra $
Zesstra@Morgengrauen2315aa12016-10-30 22:36:26 +01006#pragma strong_types,rtt_checks
MG Mud User88f12472016-06-24 23:31:02 +02007#pragma range_check
8#pragma no_clone
MG Mud User88f12472016-06-24 23:31:02 +02009
10inherit "/std/thing/moving";
11inherit "/std/room";
12
13#include <properties.h>
14#include <moving.h>
15#include <defines.h>
16#include <language.h>
17#include <transport.h>
18#include <regexp.h>
Zesstra179db0d2016-11-26 13:13:41 +010019#include <hook.h>
20
MG Mud User88f12472016-06-24 23:31:02 +020021
22/* transport.c
23 *
24 * Ueberarbeitete und
25 * erweiterte Version : Tilly@MorgenGrauen, 10.01.02
26 * Basierend auf : transport.c@SilberLand (Woody@SilberLand), 05.12.99
27 * Basierend auf : Hates und Rumatas generisches Transport Objekt
28 * MorgenGrauen 15.02.93
29 */
30
31/*
32 ********************* Variablen *********************
33 */
34
35// TODO: langfristig waer ja private schoen...
36//
37// Datenstruktur von 'route' (bei HP_ROOM)
38// 0 ({string ID, : HP_ROOM
39// 1 string room, : Dateiname Zielraum
40// 2 int stay, : Dauer Haltezeit
41// 3 int next, : Dauer naechste Fahrtzeit
42// 4 string code, : Haltestellenname fuer QueryArrived
43// 5 mixed dest, : Haltestellen-IDs fuer HasRoute (reise nach)
44// 6 mixed deststr }): unbenutzt.
45//
46// Datenstruktur von 'route' (bei HP_MSG, HP_FUN)
47// 0 ({string ID, : HP_MSG
48// 1 string message, : Meldung oder string fun : Funktionsname
49// 2 int next}) : Dauer bis zum naechsten Ereignis
50nosave mixed *route; /* Liste der Haltepunkte. */
51nosave int rpos; /* Momentane Position in obiger Liste. */
52nosave string roomCode; /* Code des aktuellen Raumes (oder 0). */
Zesstrae805e3a2018-02-12 19:48:06 +010053// Letzter Spielerkontakt. Das muss != 0 sein (sonst funktioniert der
54// Mechanismus zum Fortsetzen der Route nach einer Pause nicht ordentlich,
55// daher wird es auf 1 initialisiert.
56nosave int meet_last_player = 1;
Zesstra7842b8e2019-07-04 21:55:39 +020057// Dauer der Route
58nosave int route_time;
Zesstra179db0d2016-11-26 13:13:41 +010059
60private void unsubscribe_init();
61private int subscribe_init();
Zesstra72843372018-02-12 21:34:49 +010062void changeHp();
MG Mud User88f12472016-06-24 23:31:02 +020063
64/*
65 ********** Management der builtin-properties **********
66 */
67
68string _query_short()
Zesstra866a3442022-05-07 12:34:13 +020069{
70 if (roomCode) return Query(P_SHORT, F_VALUE);
71 return 0;
72}
73
74// Waehrend der Reise echt unsichtbar und nicht-interagierbar machen, ausser
75// fuer PL innerhalb des Transporters.
76// Ansonsten koennten z.B. Spieler, die im Hafen einen angelegten Transporter
77// betrachten, ihn dadurch als Referenzobjekt haben und Details am
78// unsichtbaren, reisenden Transporter betrachten.
79visible int _query_invis()
80{
81 if(!roomCode && (!PL || environment(PL) != ME))
82 return 1;
83 return Query(P_INVIS, F_VALUE);
MG Mud User88f12472016-06-24 23:31:02 +020084}
85
86mixed _query_transparent()
Zesstra866a3442022-05-07 12:34:13 +020087{
MG Mud User88f12472016-06-24 23:31:02 +020088 if (roomCode) return Query(P_TRANSPARENT);
Zesstra866a3442022-05-07 12:34:13 +020089 return 0;
MG Mud User88f12472016-06-24 23:31:02 +020090}
91
Zesstra179db0d2016-11-26 13:13:41 +010092static mixed *_set_route(mixed *r) { return route = r; }
93static mixed *_query_route() { return route; }
94static int _query_mnpc_last_meet() { return meet_last_player; }
MG Mud User88f12472016-06-24 23:31:02 +020095
96/*
97 **************** Zugriffsfunktionen ***************
98 */
99
Zesstra179db0d2016-11-26 13:13:41 +0100100public void Halt()
MG Mud User88f12472016-06-24 23:31:02 +0200101{
Zesstra179db0d2016-11-26 13:13:41 +0100102 // stop, but keep rpos counter.
MG Mud User88f12472016-06-24 23:31:02 +0200103 while (remove_call_out( "changeHp" )>-1);
104 while (remove_call_out( "disconnect" )>-1);
105}
106
107// Aktualisiert/Setzt die Route im TravelD, wenn erlaubt (d.h. kein
108// P_NO_TRAVELING)
109private void ReportRoute()
110{
111 if(!QueryProp(P_NO_TRAVELING))
112 {
113 mixed tmp = filter(route, function int (mixed arr)
114 {
115 return arr[0] == HP_ROOM;
116 } );
117 string *route = map(tmp, function string (mixed arr)
118 { return arr[1]; }
119 );
120 TRAVELD->AddRoute(object_name(this_object()),route);
121 }
122}
123
Zesstra179db0d2016-11-26 13:13:41 +0100124public varargs void Start(int pos)
MG Mud User88f12472016-06-24 23:31:02 +0200125{
126 Halt();
Zesstra5d2ace02017-06-20 23:21:36 +0200127 // negative pos sind ein Fehler
128 if (pos<0)
129 raise_error(sprintf("Start(): Positionszaehler < 0: %d\n",pos));
130
131 // wenn pos zu gross fuer die Route ist, rpos auf Ende der Route setzen
132 // (i.e. sizeof(route)-1), damit bei der naechsten Bewegung am Anfang der
133 // Route begonnen wird.
134 rpos = min(pos, sizeof(route)-1);
135
MG Mud User88f12472016-06-24 23:31:02 +0200136 // Tell TRAVELD our current route
137 ReportRoute();
Zesstrac786fee2018-02-12 20:31:29 +0100138 // changeHp() inkrementiert zu Beginn rpos um 1. D.h. damit wir keinen
139 // Haltepunkt ueberspringen, muss dieses vorweg kompensiert werden. Da dies
140 // wiederum den Transporter aber ggf. buggen laesst (rpos<0), darf das
141 // changeHp() hier nicht asynchron per call_out gerufen werden.
142 --rpos;
143 changeHp();
MG Mud User88f12472016-06-24 23:31:02 +0200144}
145
Zesstra179db0d2016-11-26 13:13:41 +0100146// continues the current route at the point we stopped.
147public int Continue()
148{
149 if (find_call_out("changeHp") == -1
150 && find_call_out("disconnect") == -1)
151 {
Zesstra019987a2017-10-24 22:36:08 +0200152 // Nach einer Pause wird die Route am aktuellen Haltepunkt fortgesetzt
153 // (im Regelfall also am Ende der Route). Am Routenende wird auch
154 // geprueft, wann der letzte Spielerkontakt war. Das darf nach einem
155 // Continue() aber nicht passieren, sonst wuerde der Transporter ggf.
156 // sofort wieder anhalten.
157 meet_last_player*=-1; // neg. vorzeichen als Markierung
Zesstra179db0d2016-11-26 13:13:41 +0100158 unsubscribe_init();
159 Start(rpos);
160 return 1;
161 }
162 return 0;
163}
164
165// pauses the transporter temporarily in a way that it continues along its
166// route as soon as a living enters one of the stop points. If that is not
167// possible, we do nothing.
168public int Pause()
169{
170 // ok, stop
171 if (subscribe_init() == 1)
172 {
173 Halt();
174 return 1;
175 }
176 return 0;
177}
178
MG Mud User88f12472016-06-24 23:31:02 +0200179void SetTravelCmds()
180{
181 if (pointerp(QueryProp(P_LEAVECMDS)))
182 AddCmd(QueryProp(P_LEAVECMDS),"GoOutside");
183 if (pointerp(QueryProp(P_ENTERCMDS)))
184 AddCmd(QueryProp(P_ENTERCMDS),"GoInside");
185 if (pointerp(QueryProp(P_TRAVEL_CMDS)))
186 AddCmd(QueryProp(P_TRAVEL_CMDS),"GoInAndOutside");
187 return;
188}
189
190mixed HasRoute(mixed dest)
191{
Arathornb3051452021-05-13 21:13:03 +0200192 int i,s;
MG Mud User88f12472016-06-24 23:31:02 +0200193 object ob;
194 mixed harb;
195
196 s = sizeof(route);
197
198 for (i = rpos;i <= rpos+s-1;i++)
199 {
200 if (route[i%s][0] == HP_ROOM)
201 {
202 if (member(route[i%s][5],dest) != -1 &&
203 objectp(ob=load_object(route[i%s][1])) &&
204 pointerp(harb=ob->QueryProp(P_HARBOUR)) &&
205 sizeof(harb))
206 {
207 return ({ route[i%s][1], harb[0] });
208 }
209 }
210 }
211 return 0;
212}
213
214public varargs void AddRoute(string room, int stay, int next,
215 string harbour_desc, string|string* dest_ids, string deststr)
216{
217 // Daten aus dem Zielanleger abfragen.
218 <string|string*>* harbour = room->QueryProp(P_HARBOUR)||({});
219 string* harbour_ids = ({});
220
221 // IDs des Zielanlegers fuer Syntaxpruefung
222 if ( sizeof(harbour)==2 )
223 {
224 if ( pointerp(harbour[1]) )
225 harbour_ids = harbour[1];
226 else
227 harbour_ids = ({harbour[1]});
228 }
229
230 // <dest_ids> in ein Array umwandeln, ist dann ggf. leer
231 if ( !dest_ids )
232 {
233 dest_ids = ({});
234 }
235 if ( stringp(dest_ids) )
236 {
237 dest_ids = ({dest_ids});
238 }
239
240 // explizit angegebene IDs stehen jetzt in <dest_ids>, die IDs des
241 // Zielhafens aus P_HARBOUR werden addiert.
242 dest_ids += harbour_ids;
243
244 // Ist <dest> immer noch leer, versuchen wir, aus <harbour_desc> ein paar
245 // Stichwoerter zu erzeugen, die man als Zielangabe in der Syntax
246 // "reise nach <ziel>" verwenden kann.
247 if ( !sizeof(dest_ids) )
248 {
249 // Grossgeschriebene Begriffe in <harbour_desc> in <dest> eintragen. Dazu:
250 // 1) <code> erstmal so zerschneiden, dass alle ueblichen Satzzeichen
251 // rausfliegen (es gibt Transporter, die sowas in <harbour_desc>
252 // uebergeben).
253 dest_ids = regexplode(harbour_desc, "[(),.;:&\+_ ]",
254 RE_OMIT_DELIM|RE_GLOBAL);
255 // 2a) So filtern, dass nur grossgeschriebene Woerter uebrig bleiben,
256 // von 1) uebriggebliebene Leerstrings gleich mit wegwerfen.
257 // 2b) Ergebnis kleinschreiben, damit die Syntaxpruefung damit arbeiten
258 // kann.
259 dest_ids = map( filter(dest_ids, function int (string key) {
260 return (key!="" && key[0]>='A' && key[0]<='Z');
261 }), #'lower_case);
262 }
263 // Sollte <dest> jetzt immer noch leer sein, wurde an allen drei Stellen
264 // nichts oder nur Muell uebergeben.
265 if ( !sizeof(dest_ids) )
266 {
267 raise_error("Transporterfehlfunktion in AddRoute(): Identifikations"
268 "matrix unzureichend definiert. Transporter unbenutzbar fuer "
269 "Spieler. Bitte mindestens eine Ziel-ID via P_HARBOUR oder als "
270 "Argument to AddRoute().");
271 }
272 route += ({ ({ HP_ROOM, room, stay, next, harbour_desc, dest_ids,
273 deststr }) });
Zesstra7842b8e2019-07-04 21:55:39 +0200274 route_time += stay + next;
MG Mud User88f12472016-06-24 23:31:02 +0200275}
276
Zesstra7842b8e2019-07-04 21:55:39 +0200277varargs void AddMsg(string msg, int next)
MG Mud User88f12472016-06-24 23:31:02 +0200278{
Zesstra7842b8e2019-07-04 21:55:39 +0200279 route += ({ ({ HP_MSG, msg, next }) });
280 route_time += next;
MG Mud User88f12472016-06-24 23:31:02 +0200281}
282
Zesstra7842b8e2019-07-04 21:55:39 +0200283void AddFun(string fun, int next)
284{
285 route += ({ ({ HP_FUN, fun, next }) });
286 route_time += next;
287}
MG Mud User88f12472016-06-24 23:31:02 +0200288
289string QueryArrived() { return roomCode; }
290
291mixed* QueryPosition()
292{
293 return ({ route[rpos][1],route[(rpos+1)<sizeof(route)?(rpos+1):0][1] });
294}
295
296object* QueryPassengers()
297{
298 return filter(all_inventory(),#'query_once_interactive);
299}
300
301varargs string *QueryHarbours(int textflag)
302{
303 string *ret = ({});
304
305 foreach( mixed* entry : route )
306 {
307 if ( entry[0] == HP_ROOM )
308 {
309 if ( textflag )
310 {
311 string *hp_ids = entry[1]->QueryProp(P_HARBOUR)[1];
312 if (pointerp(hp_ids) && sizeof(hp_ids))
313 {
314 string *h = map( explode(hp_ids[0]," "), #'capitalize);
315 ret += ({ implode(h, " ") });
316 }
317 }
318 else
319 {
320 ret += ({ entry[1] });
321 }
322 }
323 }
324 return ret;
325}
326
327// beim zerstoeren sollte auch die route und der Transporter aus dem traveld
328// abgemeldet werden.
329public varargs int remove(int silent)
330{
331 TRAVELD->RemoveTransporter(this_object());
332 return ::remove(silent);
333}
334
335void RemoveRoute()
336{
337 Halt();
338 route = ({ });
339 rpos = 0;
Zesstra7842b8e2019-07-04 21:55:39 +0200340 route_time = 0;
MG Mud User88f12472016-06-24 23:31:02 +0200341 TRAVELD->RemoveTransporter(this_object());
342}
343
344varargs int Enter(object who)
345{
346 string *emsg;
347 mixed efail;
348
349 if (!objectp(who)) who = this_player();
350 if (environment(who) == this_object())
351 {
352 tell_object(who,"Da bist Du doch bereits, schon vergessen?\n");
353 return 1;
354 }
355 if (!QueryArrived()) return 0;
356 if (QueryProp(P_MAX_PASSENGERS) &&
357 (sizeof(QueryPassengers()) >= QueryProp(P_MAX_PASSENGERS)))
358 {
359 if (pointerp(efail=QueryProp(P_ENTERFAIL)))
360 {
361 if (sizeof(efail) == 2)
362 tell_room(this_object(),who->Name(WER,2)+" "+process_string(efail[1])+
363 ".\n",({who}));
364 tell_object(who,process_string(efail[0])+".\n");
365 }
366 else if (stringp(efail))
367 tell_object(who,process_string(efail)+".\n");
368 else if (closurep(efail)) funcall(efail);
369 return 1;
370 }
371
372 tell_object(who,"Du betrittst "+name(WEN,1)+".\n");
373 if (pointerp(emsg=QueryProp(P_ENTERMSG)) && sizeof(emsg) == 2)
374 return who->move(this_object(),M_GO,"",process_string(emsg[0]),
375 process_string(emsg[1]));
376 return who->move(this_object(),M_GO,
377 name(WEN,1),"betritt","kommt herein");
378}
379
380varargs int Leave(object who)
381{
382 string *lmsg;
383 mixed lfail;
384
385 if (!objectp(who)) who = this_player();
386 if (environment(who) != this_object())
387 {
388 if (QueryArrived())
389 {
390 tell_object(who,"Dafuer muesstest Du erstmal dort sein.\n");
391 return 1;
392 }
393 return 0;
394 }
395 if (!QueryArrived())
396 {
397 if (lfail=QueryProp(P_LEAVEFAIL))
398 {
399 if (pointerp(lfail) && sizeof(lfail))
400 {
401 if (sizeof(lfail) == 2)
402 tell_room(this_object(),who->Name(WER,2)+" "+process_string(
403 lfail[1])+".\n",({who}));
404 tell_object(who,process_string(lfail[0])+".\n");
405 }
406 else if (stringp(lfail))
407 tell_object(who,process_string(lfail)+".\n");
408 else if (closurep(lfail)) funcall(lfail);
409 return 1;
410 }
411 tell_object(who,"Fehler beim Verlassen des Transporters.\n"
412 "Bitte zustaendigen Magier verstaendigen.\n");
413 return 1;
414 }
415
416 if (who->QueryProp(P_TRAVEL_INFO)) who->SetProp(P_TRAVEL_INFO,0);
417 tell_object(who,"Du verlaesst "+name(WEN,1)+".\n");
418 if (pointerp(lmsg=QueryProp(P_LEAVEMSG)) && sizeof(lmsg) == 2)
419 return who->move(environment(),M_GO,"",process_string(lmsg[0]),
420 process_string(lmsg[1]));
421 return who->move(environment(),M_GO,
422 name(WEN,1),"verlaesst","kommt herein");
423}
424
425/*
426 ****************** Internal Functions ******************
427 */
428
429static int GoInside(string str)
430{
431 _notify_fail("Was moechtest Du denn genau?\n");
432 if (stringp(str) && id(str)) {
433 Enter();
434 return 1;
435 }
436 return 0;
437}
438
439static int GoOutside(string str)
440{
441 _notify_fail("Was moechtest Du denn genau?\n");
442 if (stringp(str) && id(str)) {
443 Leave();
444 return 1;
445 }
446 return 0;
447}
448
449static int GoInAndOutside(string str)
450{
451 string to;
452
453 _notify_fail("Was moechtest Du denn genau?\n");
454 if (!sizeof(str)) return 0;
455 if ((sscanf(str,"auf %s",to) == 1 || sscanf(str,"in %s",to) == 1) && id(to))
456 return Enter(),1;
457 if ((sscanf(str,"von %s",to) == 1 || sscanf(str,"aus %s",to) == 1) && id(to))
458 return Leave(),1;
459 return 0;
460}
461
462protected void create()
463{
464 ::create();
465
466 route = ({});
467
468 SetProp(P_LEAVEFAIL,"Das ist momentan viel zu gefaehrlich");
469 SetProp(P_ENTERFAIL,"Dort ist kein Platz mehr fuer Dich");
470 SetProp(P_TRANSPARENT,1);
471
472 AddId("Transporter");
Zesstra179db0d2016-11-26 13:13:41 +0100473
MG Mud User88f12472016-06-24 23:31:02 +0200474 call_out("SetTravelCmds",1);
475}
476
477static varargs void disconnect(int change, int change_time)
478{
479 object room;
480 mixed *departmsg;
481
482 departmsg = QueryProp(P_DEPARTMSG);
483
484 if ((room = environment()) && pointerp(departmsg))
485 {
486 tell_room(this_object(),process_string(departmsg[0]));
487 tell_room(room,process_string(departmsg[1]));
488 }
489
490 roomCode = 0;
491
492 if (change) call_out("changeHp",change_time);
493}
494
495static varargs void connect(string room, string code)
496{
497 mixed *arrivemsg, *t;
Arathornb3051452021-05-13 21:13:03 +0200498 object *trav;
MG Mud User88f12472016-06-24 23:31:02 +0200499 int i;
500
501 if (roomCode) disconnect();
502
503 roomCode = code?code:"";
504
505 if (catch(move(room,M_SILENT|M_NOCHECK);publish))
506 {
507 roomCode = 0;
508 return;
509 }
510
511 arrivemsg = QueryProp(P_ARRIVEMSG);
512
513 if (pointerp(arrivemsg))
514 {
515 tell_room(this_object(),process_string(arrivemsg[0]));
516 tell_room(room,process_string(arrivemsg[1]));
517 }
518
519 trav = filter(all_inventory(this_object()),#'living);
520
521 i = sizeof(trav);
522 while(i--)
523 {
524 if (pointerp(t = trav[i]->QueryProp(P_TRAVEL_INFO))&&
525 t[0]==this_object()&&t[2]==room)
526 {
527 if (trav[i]->InFight())
528 tell_object(trav[i],break_string("Du solltest Deinen Kampf "
529 "schnell beenden,denn eigentlich wolltest Du hier "
530 "aussteigen.",78));
531 else
532 Leave(trav[i]);
533 if (environment(trav[i])!=this_object())
534 trav[i]->SetProp(P_TRAVEL_INFO,0);
535 }
536 }
537 trav = filter(all_inventory(find_object(room))-trav,#'living);
538 i=sizeof(trav);
539 while(i--)
540 {
541 if (objectp(trav[i]) && pointerp(t = trav[i]->QueryProp(P_TRAVEL_INFO))&&
542 t[0] == environment(trav[i]) && t[1] == this_object())
543 {
544 if ( trav[i]->InFight() )
545 tell_object(trav[i],
546 break_string("Du solltest Deinen Kampf schnell beenden, denn "
547 "eigentlich wolltest Du mit "+name(WEM,1)+
548 " reisen.",78));
549 else
550 Enter(trav[i]);
551 if (environment(trav[i]) == this_object())
552 {
553 t[0] = this_object();
554 trav[i]->SetProp(P_TRAVEL_INFO,t);
555 }
556 }
557 }
558}
559
560// this object never performs any clean-up, the driver should not call it
561// again.
562int clean_up(int arg) { return 0; }
563
Zesstra5b71ebb2018-03-07 20:50:35 +0100564public varargs void init(object origin)
Zesstra179db0d2016-11-26 13:13:41 +0100565{
Zesstra5b71ebb2018-03-07 20:50:35 +0100566 "*"::init(origin);
Zesstra179db0d2016-11-26 13:13:41 +0100567 // if we have player contact (even if the player is just in the same
568 // environment), we update the time.
569 if (this_player() && query_once_interactive(this_player()))
Bugfix4df578b2019-03-13 18:36:59 +0100570 {
571 meet_last_player = time();
572 // Wenn jemand in uns ist, auch falls noetig die Route fortsetzen,
573 // denn wir haben natuerlich nicht H_HOOK_INIT in uns selbst abonniert.
Arathorn303ade72022-12-09 21:53:06 +0100574 // Aber auch nur, wenn nicht jemand schon nen zeitverzögertes
575 // Continue per Hook getriggert hat.
576 if(environment(PL)==ME && find_call_out(#'Continue)==-1)
Bugfix4df578b2019-03-13 18:36:59 +0100577 Continue();
578 }
Zesstra179db0d2016-11-26 13:13:41 +0100579}
580
581// we try to continue our route once some living triggers init.
582private mixed InitHookCallback(object source, int hookid, mixed hookdata)
583{
Arathorn303ade72022-12-09 21:53:06 +0100584 if (hookid == H_HOOK_INIT && previous_object() == source &&
585 find_call_out(#'Continue)==-1)
586 call_out(#'Continue, 0);
Zesstra179db0d2016-11-26 13:13:41 +0100587 return ({H_NO_MOD, hookdata});
588}
589
590// subscribes to H_HOOK_INIT in all rooms along the route
Zesstra658871d2019-07-04 21:34:02 +0200591// == 1 for success, < -1 if not (at least one hook failed, all registration
592// were already subscribed).
Zesstra179db0d2016-11-26 13:13:41 +0100593private int subscribe_init()
594{
595 // subscribe to the H_HOOK_INIT of all rooms in the route...
Zesstra179db0d2016-11-26 13:13:41 +0100596 foreach(mixed* arr : route)
597 {
598 if (arr[0] == HP_ROOM)
599 {
Bugfix7c642a72021-05-16 13:05:52 +0200600 int res = arr[1]->HRegisterToHook(H_HOOK_INIT, #'InitHookCallback,
601 H_HOOK_LIBPRIO(1), H_LISTENER,
602 0);
603 // 1 == Erfolg, -3 == bereits registriert
604 if(res != 1 && res != -3)
Zesstra658871d2019-07-04 21:34:02 +0200605 {
606 // von allen H_HOOK_INIT wieder abmelden...
607 unsubscribe_init();
608 return -1;
609 }
Zesstra179db0d2016-11-26 13:13:41 +0100610 }
611 }
Zesstra658871d2019-07-04 21:34:02 +0200612 return 1;
Zesstra179db0d2016-11-26 13:13:41 +0100613}
614
615// unsubscribes from all the H_HOOK_INIT.
616private void unsubscribe_init()
617{
618 foreach(mixed* arr : route)
619 {
620 if (arr[0] == HP_ROOM)
621 arr[1]->HUnregisterFromHook(H_HOOK_INIT, #'InitHookCallback);
622 }
623}
624
625private int maybe_pause()
626{
Zesstra7842b8e2019-07-04 21:55:39 +0200627 // we check for time of last player contact. If we did not meet any players
628 // for 2 round-trips, we try to pause.
629 if (meet_last_player < time() - (2*route_time) )
Zesstra179db0d2016-11-26 13:13:41 +0100630 {
Zesstra677b5722019-07-04 22:10:01 +0200631 // we don't stop if players are currently at one of our stops
632 foreach(mixed* arr : route)
633 {
634 if (arr[0] == HP_ROOM)
635 {
636 object room = find_object(arr[1]);
637 if(room &&
638 sizeof(filter(all_inventory(room), #'interactive)))
639 return 0; // no pause
640 }
641 }
642 // and we don't stop if players currently are in the transporter.
643 if (sizeof(filter(all_inventory(this_object()), #'interactive)))
644 return 0;
645 // ok, pause machen
646 return Pause();
Zesstra179db0d2016-11-26 13:13:41 +0100647 }
648 return 0;
649}
650
MG Mud User88f12472016-06-24 23:31:02 +0200651void changeHp()
652{
Zesstrafffd2a82017-10-24 22:03:27 +0200653 // Nicht am Ende der Route? Eins weiter.
654 if (rpos < sizeof(route) - 1)
655 ++rpos;
656 else
MG Mud User88f12472016-06-24 23:31:02 +0200657 {
Zesstra019987a2017-10-24 22:36:08 +0200658 // Routenende
659 // Nach einem expliziten Continue() ist meet_last_player < 0. Dann wird
660 // nicht geprueft, ob wir sofort wieder anhalten. Auch muss dann die Route
661 // nicht uebermittelt werden (hat Start() schon gemacht).
662 if (meet_last_player >= 0)
663 {
664 // TRAVELD die aktuelle Route uebermitteln
665 ReportRoute();
666 // everytime, we pass the end of our route, we check if we should
667 // pause our service.
668 if (maybe_pause())
669 return;
670 }
671 else
672 // Wieder pruefen im naechsten Durchlauf.
673 meet_last_player=abs(meet_last_player);
674
Zesstrafffd2a82017-10-24 22:03:27 +0200675 // wenn keine Pause, wieder zum Anfang der Route bewegen.
676 rpos = 0;
MG Mud User88f12472016-06-24 23:31:02 +0200677 }
Zesstrafffd2a82017-10-24 22:03:27 +0200678
MG Mud User88f12472016-06-24 23:31:02 +0200679 if (route[rpos][0] == HP_MSG)
680 {
681 call_out("changeHp",route[rpos][2]);
682 tell_room(this_object(),route[rpos][1]);
683 }
684 else if (route[rpos][0] == HP_FUN)
685 {
686 call_out("changeHp",route[rpos][2]);
687 call_other(this_object(),route[rpos][1]);
688 }
689 else
690 {
691 call_out("disconnect",route[rpos][2],1,route[rpos][3]);
692 connect(route[rpos][1],route[rpos][4]);
693 }
694}
695