blob: 46e93640eaf41ae3382c222b1baf7096baa71f1f [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001#include <properties.h>
2#include <defines.h>
3#include <moving.h>
4#include <language.h>
5
6#define NEED_PROTOTYPES
7#include <doorroom.h>
8
9inherit "/std/thing";
10
11#pragma strong_types
12
13private mapping door_status;
14private int id_zaehler;
15// Format: "filename1:filename2":status
16
17int oeffnen (string str);
18
19mapping QueryAllDoors() {return door_status;}
20
21int QueryDoorStatus(string dest) {
22 string source,dkey;
23 object env;
24
25 if (!dest) return 0;
26 if (!objectp(env=previous_object())) return 0;
27 source=object_name(env);
28 dkey=(source<dest)?(source+":"+dest):(dest+":"+source);
29 return door_status[dkey];
30}
31
32void SetDoorStatus(string dest, int x) {
33 string source,dkey;
34 object env;
35
36 if (!dest) return;
37 if (!objectp(env=previous_object())) return;
38 source=object_name(env);
39 dkey=(source<dest)?(source+":"+dest):(dest+":"+source);
40 door_status[dkey]=x;
41}
42
43protected void create() {
44 door_status=([]);
45 id_zaehler=0;
46 if (IS_CLONE(this_object())) remove();
47}
48
49varargs int remove(int silent) {return 0;}
50
51varargs int NewDoor(string|string* cmds, string dest, string|string* ids,
52 mapping|<int|string|string*>* props)
53{
54 object env;
55 string source,dkey,sec_id;
56 mixed *info2,zw;
57 mapping info;
58 int i;
59
60 if (!objectp(env=previous_object())) return 0;
61 if (!cmds || !dest) return 0;
62 if (!ids) ids=({"tuer"});
63 if (stringp(cmds)) cmds=({cmds});
64 if (stringp(ids)) ids=({ids});
65 if (!pointerp(cmds) || !pointerp(ids)) return 0;
66 if (dest[0..0]!="/") dest="/"+dest;
67 id_zaehler++;
68 sec_id=sprintf("secure_id:door%d",id_zaehler);
69
70 info=([D_DEST : dest,
71 D_CMDS : cmds,
72 D_IDS : ({ sec_id }) + ids,
73 D_FLAGS : (DOOR_CLOSED|DOOR_RESET_CL),
74 D_LONG : "Eine Tuer.\n",
75 D_SHORT : "Eine %se Tuer. ",
76 D_NAME : "Tuer",
77 D_GENDER : FEMALE]);
78 source=object_name(env);
79 dkey=(source<dest)?(source+":"+dest):(dest+":"+source);
80
81 if (pointerp(props)) {
82 for (i=0;i<sizeof(props)-1;i+=2)
83 if (intp(props[i]) && props[i]>=D_MINPROPS && props[i]<=D_MAXPROPS)
84 info[props[i]]=props[i+1];
85 }
86 else if(mappingp(props)){
87 info += props;
88 }
89
90 if (!door_status[dkey]) {
91 // Nur initialisieren, wenn Tuer noch nicht existiert.
92 if (info[D_FLAGS] & DOOR_OPEN)
93 door_status[dkey]=D_STATUS_OPEN;
94 if (info[D_FLAGS] & DOOR_CLOSED)
95 door_status[dkey]=
96 ((info[D_FLAGS] & DOOR_NEEDKEY) ? D_STATUS_LOCKED : D_STATUS_CLOSED);
97 }
98 info2=env->QueryProp(P_DOOR_INFOS);
99 if (!pointerp(info2))
100 info2=({info});
101 else
102 info2+=({info});
103 env->SetProp(P_DOOR_INFOS,info2);
104
105 if(mappingp(info[D_LONG]) && pointerp(zw=m_indices(info[D_LONG])) &&
106 sizeof(zw) && intp(zw[0]))
107 env->AddSpecialDetail(ids,"special_detail_doors");
108 else if(info[D_LONG] && info[D_LONG]!="")
109 env->AddDetail(ids,info[D_LONG]);
110
111 return 1;
112}
113
114void init_doors () {
115 object env;
116 mixed *info;
117 string source,dest,dkey;
118 int i;
119
120 if (!objectp(env=previous_object())) return;
121 info=env->QueryProp(P_DOOR_INFOS);
122 if (!pointerp(info)) return;
123
124 source=object_name(env);
125 for (i=sizeof(info)-1;i>=0;i--) {
126 if (!mappingp(info[i])) continue;
127 dest=info[i][D_DEST];
128 dkey=(source<dest)?(source+":"+dest):(dest+":"+source);
129 env->set_doors(info[i][D_CMDS],(door_status[dkey]>0));
130 }
131}
132
133string look_doors () {
134 object env;
135 mixed *info, ds;
136 string source,dkey,dest,res;
137 int i, st;
138
139 if (!objectp(env=previous_object())) return "";
140 info=env->QueryProp(P_DOOR_INFOS);
141 if (!pointerp(info)) return "";
142 init_doors(); // Aktueller Zustand soll auch bei den Exits angezeigt werden
143
144 source=object_name(env);res="";
145 for (i=sizeof(info)-1;i>=0;i--) {
146 if (!mappingp(info[i])) continue;
147 dest=info[i][D_DEST];
148 dkey=(source<dest)?(source+":"+dest):(dest+":"+source);
149 if (stringp(info[i][D_SHORT])) {
150 res+=sprintf(info[i][D_SHORT],
151 ((door_status[dkey]>=D_STATUS_OPEN)?"geoeffnet":
152 ((door_status[dkey]!=D_STATUS_CLOSED)?"ab":"")+"geschlossen"));
153 if (sizeof(res) && res[<1]!='\n')
154 res+=" ";
155 }
156 else if(mappingp(ds=info[i][D_SHORT])){
157 st=door_status[dkey];
158 if((st==D_STATUS_LOCKED) && !ds[D_STATUS_LOCKED])
159 st=D_STATUS_CLOSED;
160 if(stringp(ds[st])){
161 res += ds[st];
162 if(sizeof(ds[st]) && res[<1]!='\n')res+=" ";
163 }
164 }
165 }
166 if (res && res!="")
167 return break_string(res,78,0,1);
168 return res;
169}
170
171static void door_message(object room, string dname, int dgender, string msg) {
172 object ob;
173
174 // printf("%O,%O,%O,%O\n",room,dname,dgender,msg);
175 if (!room || !dname || !msg) return;
176 ob=this_object();
177 ob->SetProp(P_NAME,dname);
178 ob->SetProp(P_GENDER,dgender);
179 ob->SetProp(P_ARTICLE,1);
180 tell_room(room,capitalize(ob->name(WER))+msg+"\n");
181}
182
183static void door_message_other(string source, string dest, string msg) {
184 mixed info;
185 object env;
186 int i;
187
188 // printf("%O %O %O\n",source,dest,msg);
189 if (!source || !dest || !msg) return;
190 if (!objectp(env=find_object(dest))) return;
191 if (!pointerp(info=env->QueryProp(P_DOOR_INFOS))) return;
192 for (i=sizeof(info)-1;i>=0;i--) {
193 if (!mappingp(info[i])) continue;
194 if (info[i][D_DEST]!=source) continue; // Andere Tuer zu diesem Raum
195 door_message(env,info[i][D_NAME],info[i][D_GENDER],msg);
196 }
197}
198
199void reset_doors () {
200 object env;
201 mixed *info;
202 string source,dest,dkey,msg;
203 int i,j;
204
205 if (!objectp(env=previous_object())) return;
206 info=env->QueryProp(P_DOOR_INFOS);
207 if (!pointerp(info)) return;
208
209 source=object_name(env);
210 for (i=sizeof(info)-1;i>=0;i--) {
211 if (!mappingp(info[i])) continue;
212 dest=info[i][D_DEST];
213 dkey=(source<dest)?(source+":"+dest):(dest+":"+source);
214
215// if (door_status[dkey]>-2 && door_status[dkey]<2) {
216// if (door_status[dkey]>0)
217// door_status[dkey]=2;
218// else
219// door_status[dkey]=-2;
220// continue; // nur jeder 2. Reset wird ausgefuehrt.
221// }
222
223 if (info[i][D_FLAGS] & DOOR_RESET_CL) {
224 // Tuer muss bei Reset geschlossen werden
225 if (door_status[dkey] >= D_STATUS_OPEN) {
226 if(!msg=info[i][D_RESET_MSG])msg=" schliesst sich.";
227 door_message(env,info[i][D_NAME],info[i][D_GENDER],msg);
228 door_message_other(source,dest,msg);
229 }
230 if (door_status[dkey]!=D_STATUS_LOCKED)
231 door_status[dkey]=
232 ((info[i][D_FLAGS] & DOOR_NEEDKEY) ? D_STATUS_LOCKED : D_STATUS_CLOSED);
233 }
234 if (info[i][D_FLAGS] & DOOR_RESET_OP) {
235 // Tuer muss bei Reset geoeffnet werden
236 if (door_status[dkey] < D_STATUS_OPEN) {
237 if(!msg=info[i][D_RESET_MSG])msg=" oeffnet sich.";
238 door_message(env,info[i][D_NAME],info[i][D_GENDER],msg);
239 door_message_other(source,dest,msg);
240 }
241 door_status[dkey]=D_STATUS_OPEN;
242 }
243 }
244 init_doors();
245}
246
247static varargs int exec_func2(string dest, mixed func) {
248 if (!stringp(dest) || !stringp(func)) return 1;
249 call_other(dest,func);
250 return 1;
251}
252
253varargs int go_door (string str) {
254 object env,pl,ob;
255 mixed *info;
256 string source,dest,dkey;
257 int i;
258
259 if (!str) return 0;
260 if (!objectp(env=previous_object())) return 0;
261 if (!objectp(pl=this_player())) return 0;
262 info=env->QueryProp(P_DOOR_INFOS);
263 if (!pointerp(info)) return 0;
264
265 source=object_name(env);
266 ob=this_object();
267 ob->SetProp(P_ARTICLE,1);
268 for (i=sizeof(info)-1;i>=0;i--) {
269 if (!mappingp(info[i])) continue;
270 if (member(info[i][D_CMDS],str)<0) continue;
271 dest=info[i][D_DEST];
272 dkey=(source<dest)?(source+":"+dest):(dest+":"+source);
273 ob->SetProp(P_NAME,info[i][D_NAME]);
274 ob->SetProp(P_GENDER,info[i][D_GENDER]);
275 notify_fail(capitalize(ob->name(WER,1))+" ist geschlossen.\n");
276 if((door_status[dkey]<=0) &&
277 !info[i][D_OPEN_WITH_MOVE]) continue; // Tuer geschlossen
278 if(door_status[dkey]<=0){
279 // In diesem Fall versuchen, die Tuer zu oeffnen.
280 oeffnen(info[i][D_IDS][0]);
281 }
282 notify_fail(capitalize(ob->name(WER,1))+" ist geschlossen.\n");
283 if (door_status[dkey]<=0) continue; // Tuer immer noch zu.
284 if (stringp(info[i][D_TESTFUNC]))
285 if (call_other(env,info[i][D_TESTFUNC]))
286 return 1; // Durchgang von der Tuer nicht erlaubt.
287 if (stringp(info[i][D_FUNC]))
288 call_other(env,info[i][D_FUNC]);
289 if (stringp(info[i][D_MSGS])) {
290 if (pl->move(dest,M_GO,info[i][D_MSGS])>0)
291 return exec_func2(dest,info[i][D_FUNC2]);
292 else
293 return 1;
294 }
295 if (pointerp(info[i][D_MSGS]) && sizeof(info[i][D_MSGS])>=3) {
296 if (pl->move(dest,M_GO,info[i][D_MSGS][0],
297 info[i][D_MSGS][1],info[i][D_MSGS][2]))
298 return exec_func2(dest,info[i][D_FUNC2]);
299 else
300 return 1;
301 }
302 if (pl->move(dest,M_GO,"nach "+capitalize(str)))
303 return exec_func2(dest,info[i][D_FUNC2]);
304 return 1;
305 }
306 return 0;
307}
308
309int oeffnen (string str) {
310 object env,schl,ob;
311 mixed *info,s2;
312 string source,dkey,dest,s1;
313 int i;
314
315 notify_fail("WAS willst Du oeffnen?\n");
316 if (!str || !this_player()) return 0;
317 notify_fail("Das kannst Du nicht oeffnen.\n");
318 str=lower_case(str);
319 if (sscanf(str,"%s mit %s",s1,s2)!=2)
320 {s1=str;s2=0;}
321 if (s2) {
322 if (!(schl=present(lower_case(s2),this_player()))) {
323 notify_fail("So einen Schluessel hast Du nicht.\n");
324 return 0;
325 } else {
326 s2=schl->QueryDoorKey();
327 if (stringp(s2)) s2=({s2});
328 }
329 }
330
331 if (!objectp(env=previous_object())) return 0;
332 info=env->QueryProp(P_DOOR_INFOS);
333 if (!pointerp(info)) return 0;
334
335 source=object_name(env);
336 ob=this_object();
337 ob->SetProp(P_ARTICLE,1);
338 for (i=sizeof(info)-1;i>=0;i--) {
339 if (!mappingp(info[i])) continue;
340 if (member(info[i][D_IDS],s1)<0) continue; // Falsche Tuer
341 ob->SetProp(P_NAME,info[i][D_NAME]);
342 ob->SetProp(P_GENDER,info[i][D_GENDER]);
343 dest=info[i][D_DEST];
344 dkey=(source<dest)?(source+":"+dest):(dest+":"+source);
345 notify_fail(capitalize(ob->name(WER,1))+" ist doch schon geoeffnet!\n");
346 if (door_status[dkey]>0)
347 continue; // Eine andere Tuer koennte gemeint sein.
348 if ((info[i][D_FLAGS] & DOOR_NEEDKEY)
349 && door_status[dkey] == D_STATUS_LOCKED) { // abgeschlossen
350 notify_fail("Du brauchst einen Schluessel, um "+ob->name(WEN,1)+" zu oeffnen.\n");
351 if (!schl) continue; // Eine andere Tuer koennte gemeint sein.
352 notify_fail(capitalize(schl->name(WER))+" passt nicht!\n");
353 if (!pointerp(s2)) continue;
354 if (member(s2,dkey)<0) continue; // Koennte an einer anderen passen.
355 }
356 door_status[dkey]=1;
357 init_doors();
358 write("Du oeffnest "+ob->name(WEN)+".\n");
359 say(capitalize(ob->name(WER))+" wird von "+this_player()->name(WEM)+
360 " geoeffnet.\n");
361 door_message_other(source,dest," wird von der anderen Seite geoeffnet.");
362 return 1;
363 }
364 return 0;
365}
366
367int schliessen (string str) {
368 object env,schl,ob;
369 mixed *info,s2;
370 string source,dkey,dest,s1;
371 int i,abg;
372
373 notify_fail("WAS willst Du schliessen?\n");
374 if (!str || !this_player()) return 0;
375 notify_fail("Das kannst Du nicht schliessen.\n");
376 str=lower_case(str);
377 if (sscanf(str,"%s mit %s",s1,s2)!=2)
378 {s1=str;s2=0;}
379 if (s2) {
380 if (!(schl=present(lower_case(s2),this_player()))) {
381 notify_fail("So einen Schluessel hast Du nicht.\n");
382 return 0;
383 } else {
384 s2=schl->QueryDoorKey();
385 if (stringp(s2)) s2=({s2});
386 }
387 }
388
389 if (!objectp(env=previous_object())) return 0;
390 info=env->QueryProp(P_DOOR_INFOS);
391 if (!pointerp(info)) return 0;
392
393 source=object_name(env);
394 ob=this_object();
395 ob->SetProp(P_ARTICLE,1);
396 abg=0;
397 for (i=sizeof(info)-1;i>=0;i--) {
398 if (!mappingp(info[i])) continue;
399 if (member(info[i][D_IDS],s1)<0) continue; // Falsche Tuer
400 ob->SetProp(P_NAME,info[i][D_NAME]);
401 ob->SetProp(P_GENDER,info[i][D_GENDER]);
402 dest=info[i][D_DEST];
403 dkey=(source<dest)?(source+":"+dest):(dest+":"+source);
404 if (schl) {
405 notify_fail(capitalize(ob->name(WER,1))+" ist doch schon abgeschlossen!\n");
406 if (door_status[dkey]<=0
407 && door_status[dkey] == D_STATUS_LOCKED)
408 continue; // Eine andere Tuer koennte gemeint sein.
409 if (info[i][D_FLAGS] & DOOR_CLOSEKEY) { // Schluessel noetig?
410 notify_fail(capitalize(schl->name(WER))+" passt nicht!\n");
411 if (!pointerp(s2)) continue;
412 if (member(s2,dkey)<0) continue; // Koennte an einer anderen passen.
413 door_status[dkey]=D_STATUS_LOCKED;
414 abg=1; // Tuer wird richtig abgeschlossen
415 }
416 else {
417 // ohne Schluessel abschliessbar
418 door_status[dkey]=
419 ((info[i][D_FLAGS] & DOOR_NEEDKEY) ? D_STATUS_LOCKED : D_STATUS_CLOSED);
420 }
421 }
422 else {
423 notify_fail(capitalize(ob->name(WER,1))+" ist doch schon geschlossen!\n");
424 if (door_status[dkey] < D_STATUS_OPEN)
425 continue; // Eine andere Tuer koennte gemeint sein.
426 if ((info[i][D_FLAGS] & DOOR_NEEDKEY) &&
427 !(info[i][D_FLAGS] & DOOR_CLOSEKEY))
428 door_status[dkey]=D_STATUS_LOCKED; // Abschliessbar, aber dazu schluessel unnoetig
429 else
430 door_status[dkey]=D_STATUS_CLOSED;
431 }
432 init_doors();
433 write("Du schliesst "+ob->name(WEN)+
434 (abg?" ab":"")+".\n");
435 say(capitalize(ob->name(WER))+" wird von "+this_player()->name(WEM)+
436 (abg?" ab":" ")+"geschlossen.\n");
437 door_message_other(source,dest," wird von der anderen Seite "+
438 (abg?"ab":"")+"geschlossen.");
439 return 1;
440 }
441 return 0;
442}
443string special_detail_doors(string key){
444 object env;
445 mixed *info;
446 mapping dl;
447 int i, st;
448 string source, dest, dkey;
449
450 if(!objectp(env=previous_object()))return 0;
451 if(!pointerp(info=env->QueryProp(P_DOOR_INFOS)))return 0;
452 source=object_name(env);
453
454 for(i=sizeof(info)-1;i>=0;i--){
455 if(!mappingp(info[i]))continue;
456 if(member(info[i][D_IDS],key)<0)continue;
457 if(stringp(info[i][D_LONG]))return info[i][D_LONG];
458 if(!mappingp(info[i][D_LONG]))continue;
459 dl=info[i][D_LONG];
460 dest=info[i][D_DEST];
461 dkey=(source<dest)?(source+":"+dest):(dest+":"+source);
462 st=door_status[dkey];
463 if((st==D_STATUS_LOCKED) && !dl[D_STATUS_LOCKED])
464 st=D_STATUS_CLOSED; /* Falls keine eigene Beschreibung
465 * fuer abgeschlossene Tuer vorhanden */
466 return dl[st];
467 }
468 return 0;
469}