blob: 718528a4f1a35edf049c1ee1ba66435dc1f16dfc [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// MorgenGrauen MUDlib
2//
3// room.c -- room base object
4//
5// $Id: room.c 9475 2016-02-19 21:16:17Z Zesstra $
6#pragma strong_types
7#pragma save_types
8#pragma range_check
9#pragma no_clone
10#pragma pedantic
11
12inherit "/std/thing/properties";
13inherit "/std/thing/language";
14inherit "/std/hook_provider";
15inherit "/std/room/light";
16inherit "/std/container/inventory";
17inherit "/std/room/moving";
18inherit "/std/room/restrictions";
19inherit "/std/room/description";
20inherit "/std/room/exits";
21inherit "/std/room/commands";
22inherit "/std/room/items";
Zesstra44030452018-11-12 22:34:02 +010023inherit "/std/container/vitems";
MG Mud User88f12472016-06-24 23:31:02 +020024inherit "/std/room/doors";
25
26#include <thing/properties.h>
27#include <config.h>
28#include <properties.h>
29#include <rooms.h>
30#include <language.h>
31#include <wizlevels.h>
32#include <moving.h>
33#include <defines.h>
34#include <doorroom.h>
35#include <functionlist.h>
Zesstra@Morgengrauen0f34a7e2016-10-30 22:33:25 +010036#include <hook.h>
MG Mud User88f12472016-06-24 23:31:02 +020037
38void reset()
39{
40 items::reset();
Zesstra44030452018-11-12 22:34:02 +010041 vitems::reset();
MG Mud User88f12472016-06-24 23:31:02 +020042 exits::reset();
43 doors::reset();
44}
45
46static int
47_query_noget()
48{
49 return 1;
50}
51
MG Mud User88f12472016-06-24 23:31:02 +020052void maybe_replace_program()
53{
54 string *list, first;
55 object first_ob;
56
MG Mud User88f12472016-06-24 23:31:02 +020057 if (object_name(this_object())=="/std/room" ||
58 !(first_ob=find_object(first=(list=inherit_list(this_object()))[1])) ||
59 (sizeof(list)!=1+sizeof(inherit_list(first_ob))) ||
60 (1!=sizeof(list=functionlist(this_object(),
61 RETURN_FUNCTION_NAME|NAME_INHERITED))) ||
62 list[0]!="create")
63 return;
MG Mud User88f12472016-06-24 23:31:02 +020064 replace_program(first);
65}
66
67protected void create()
68{
69 maybe_replace_program();
70 /* Set effective userid to userid */
71 /* so that we may clone other things */
72 seteuid(getuid(this_object()));
73 properties::create();
74 restrictions::create();
75 commands::create();
76 light::create();
77 description::create();
78 exits::create();
79 items::create();
80 doors::create();
Zesstra@Morgengrauen0f34a7e2016-10-30 22:33:25 +010081 offerHook(H_HOOK_INIT, 1);
MG Mud User88f12472016-06-24 23:31:02 +020082
83 SetProp(P_NAME,0);
84 SetProp(P_NAME_ADJ,({}));
85 Set(P_SHORT,0);
86 Set(P_LONG,0);
87 Set(P_TRANSPARENT,0);
88 Set(P_ADJECTIVES,({}));
89 Set(P_IDS,({}));
90 Set(P_WEIGHT,PROTECTED,F_MODE);
91 Set(P_TOTAL_WEIGHT,PROTECTED,F_MODE);
92 Set(" clean counter ",2);
93}
94
95protected void create_super() {
96 set_next_reset(-1);
97}
98
99private int
100check_clean_count()
101{
102 int cc;
103
104 cc=Query(" clean counter ");
105 if (--cc<=0)
106 return 1;
107 Set(" clean counter ",cc);
108 return 0;
109}
110
111int
112clean_up(int arg)
113{
Zesstra8a4fe3b2018-02-12 21:20:24 +0100114 // Never try again when P_NEVER_CLEAN is set.
115 if (Query(P_NEVER_CLEAN)) return 0;
MG Mud User88f12472016-06-24 23:31:02 +0200116
Zesstra8a4fe3b2018-02-12 21:20:24 +0100117 // do not cleanup, if this room is used as blueprint for clones or inherited
118 // (arg>1) or if there are valid hook consumers waiting for something to
119 // happen here. This is temporary and could change, so return 1;
120 if (arg>1 || HHasConsumers())
121 return 1;
MG Mud User88f12472016-06-24 23:31:02 +0200122
Zesstra8a4fe3b2018-02-12 21:20:24 +0100123 // if there are any items we have produced ourselfes check them
124 mixed itema = QueryProp(P_ITEMS);
125 if(pointerp(itema))
MG Mud User88f12472016-06-24 23:31:02 +0200126 {
127 mixed names;
128 int i;
129 i = sizeof(names = all_inventory(this_object()));
130 while(i--)
131 {
132 if (query_once_interactive(names[i]))
133 {
Zesstrae12be202018-02-12 21:10:38 +0100134 Set(" clean counter ",2);
135 return 1;
MG Mud User88f12472016-06-24 23:31:02 +0200136 }
137 if(objectp(names[i])) names[i] = explode(object_name(names[i]),"#")[0];
138 }
139
140 for(i = sizeof(itema)-1; i >= 0; i--)
141 {
142 // Semantik:
143 // 1. Wenn RITEM_OBJECT ein array ist, kann evtl ge'clean'ed werden.
144 // 2. Wenn es ein REFRESH_NONE Item ist und es entweder nicht mehr
145 // existiert oder nicht in diesem Raum ist, kein clean_up (es wuerde
146 // beim neuladen des Raumes ja wieder erzeugt;
147 // falls es aber hier ist, wird es mitvernichtet, dann ists ok)
148 // 3. Wenn es ein REFRESH_DESTRUCT ist und noch existiert, aber nicht
149 // hier ist, KEIN clean_up.
150 if (!pointerp(itema[i][RITEM_OBJECT])
Zesstrae12be202018-02-12 21:10:38 +0100151 && ((itema[i][RITEM_REFRESH] == REFRESH_NONE
152 && (!itema[i][RITEM_OBJECT]
153 || environment(itema[i][RITEM_OBJECT])!=this_object()))
154 || (itema[i][RITEM_REFRESH] == REFRESH_DESTRUCT
155 && itema[i][RITEM_OBJECT]
156 && environment(itema[i][RITEM_OBJECT]) != this_object())))
157 return 1;
MG Mud User88f12472016-06-24 23:31:02 +0200158 names -= (pointerp(itema[i][RITEM_FILE]) ?
Zesstrae12be202018-02-12 21:10:38 +0100159 itema[i][RITEM_FILE] : ({ itema[i][RITEM_FILE] }));
MG Mud User88f12472016-06-24 23:31:02 +0200160 }
161 // if there are objects left in the room do not clean up but try again later
162 if(sizeof(names) && !check_clean_count()) return 1;
163 }
164 else
165 // is there any object lying around?
166 if(first_inventory(this_object()) && !check_clean_count()) return 2;
167
168 // do clean_up
169 //log_file("clean_up_log",sprintf(
Zesstrae12be202018-02-12 21:10:38 +0100170 // "%s:%s: %O\n",ctime(time())[11..18],__HOST_NAME__,this_object()));
171
MG Mud User88f12472016-06-24 23:31:02 +0200172 remove();
173 // wenn der Raum sich im remove() nicht zerstoert, hat er dafuer vermutlich
174 // nen Grund. Evtl. klappts ja naechstes Mal.
175
176 return(1);
177}
178
179/* Instead of printing the exits with the long description, we implement */
180/* the command "exits" to show them. */
181int
182show_exits() {
183 mixed ex;
184 if( this_player()->CannotSee() ) return 1;
185 if ((ex=QueryProp(P_HIDE_EXITS)) && intp(ex)) return 1;
186 if (ex = GetExits(this_player())) write(ex);
187 return 1;
188}
189
190int
191toggle_exits(string str)
192{
193 int ex;
194
195 /* Nur das aktuelle Environment des Spielers ist zustaendig fuer die
196 Auflistung der Ausgaenge. Anderenfalls wird das Kommando von Raeumen
197 im Raum (z.B. Transportern) abgefangen und es werden dessen Ausgaenge
198 aufgelistet.
199 Sprich: keine Auflistung von Aussen. */
200 if (environment(this_player()) != this_object()) return 0;
201 if (!str) return show_exits();
202 if (str!="auto") return 0;
203 ex = this_player()->QueryProp(P_SHOW_EXITS);
204 this_player()->SetProp(P_SHOW_EXITS, !ex);
205 if (ex) write("Ausgaenge werden nicht mehr automatisch angezeigt.\n");
206 else write("Ausgaenge werden automatisch angezeigt.\n");
207 return 1;
208}
209
Zesstra5b71ebb2018-03-07 20:50:35 +0100210public varargs void init(object origin)
MG Mud User88f12472016-06-24 23:31:02 +0200211{
Zesstra@Morgengrauen0f34a7e2016-10-30 22:33:25 +0100212 if (HookFlow(H_HOOK_INIT, 0)[H_RETCODE] == H_CANCELLED)
213 return;
MG Mud User88f12472016-06-24 23:31:02 +0200214 Set(" clean counter ",2);
Zesstra5b71ebb2018-03-07 20:50:35 +0100215 exits::init(origin);
216 commands::init(origin);
217 description::init(origin);
218 doors::init(origin);
MG Mud User88f12472016-06-24 23:31:02 +0200219
220 add_action("toggle_exits", "exits");
221 add_action("toggle_exits", "ausgang");
222 add_action("toggle_exits", "ausgaenge");
223 add_action("toggle_exits", "aus");
224}
225
226int _query_para(){
227 int re;
228 if(re=Query(P_PARA))return re;
229 if(sizeof(regexp(({object_name(this_object())}),".*\\^0$")))
230 return -1;
231 return to_int(
232 regreplace(object_name(this_object()),".*\\^\([1-9][0-9]*\)$","\\1",1));
233}
234
235//dies ist ein Raum, war gewuenscht von mehreren Leuten.
236status IsRoom() {return(1);}