blob: c27736f3d8748fd228a7a07fe8a590d6331c582c [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// MorgenGrauen MUDlib
2//
3// container/items.c -- creating extra items in room
4//
5// $Id: items.c 8811 2014-05-09 17:30:37Z Zesstra $
6
7// extra items handling
8//
9// AddItem(string filename, int refresh)
10// Clones an item and puts it into the room. <refresh> may be
11// on of the following:
12// REFRESH_NONE: No refresh done until reboot.
13// REFRESH_DESTRUCT: Refresh on reset if item was destructed.
14// REFRESH_REMOVE: Refresh on reset if item was removed from room.
15// REFRESH_ALWAYS: Create a new clone on every reset.
16//
17// The commands are implemented as properties P_ITEMS as mapping. They are
18// stored locally (_set_xx) as mapping to speed up the routines
19// in this module.
20//
21// Format of key and data in the P_ITEMS mapping:
22//
23// ([ key1 : refresh1; obp1; arr1, ..., keyn : refreshn; obpn; arrn ])
24
25#include <sys_debug.h>
26#pragma strict_types
27#pragma save_types
28#pragma range_check
29#pragma no_clone
MG Mud User88f12472016-06-24 23:31:02 +020030
31#define NEED_PROTOTYPES
32#include <thing/properties.h>
33#include <rooms.h>
34#include <container.h>
35#undef NEED_PROTOTYPES
36#include <defines.h>
37#include <config.h>
38#include <properties.h>
39#include <moving.h>
40#include <daemon.h>
41
42protected void create()
43{
Bugfixacdf07a2016-10-13 20:25:25 +020044 Set(P_ITEMS,({}));
45 Set(P_ITEMS,SECURED,F_MODE_AS);
46
47 OBJECTD->QueryObject(); // querying general objects
MG Mud User88f12472016-06-24 23:31:02 +020048}
49
Bugfixacdf07a2016-10-13 20:25:25 +020050protected void create_super()
51{
MG Mud User88f12472016-06-24 23:31:02 +020052 set_next_reset(-1);
53}
54
55/* Kram zum Aufraeumen von multiplen gleichen Items im Container. */
Bugfixacdf07a2016-10-13 20:25:25 +020056private object removeable_ob(object ob)
MG Mud User88f12472016-06-24 23:31:02 +020057{
Bugfixacdf07a2016-10-13 20:25:25 +020058 if(!query_once_interactive(ob) && !living(ob))
59 {
60 return ob;
61 }
MG Mud User88f12472016-06-24 23:31:02 +020062
Bugfixacdf07a2016-10-13 20:25:25 +020063 return 0;
MG Mud User88f12472016-06-24 23:31:02 +020064}
65
66protected varargs void remove_multiple(int limit, mixed fun)
67{
Bugfixacdf07a2016-10-13 20:25:25 +020068 object *inh = all_inventory(ME)-({0});
MG Mud User88f12472016-06-24 23:31:02 +020069
Bugfixacdf07a2016-10-13 20:25:25 +020070 inh=filter(inh,#'removeable_ob);
71 foreach(mixed item : QueryProp(P_ITEMS))
72 {
73 inh-=({item[0]});
74 }
75
76 if(!stringp(fun) && !closurep(fun))
77 {
78 fun="description_id";
79 }
Zesstracd62c192019-11-23 17:15:31 +010080 object **sorted_inh=unique_array(inh,fun,0);
81 foreach(object *arr : sorted_inh)
Bugfixacdf07a2016-10-13 20:25:25 +020082 {
83 if(sizeof(arr)<=limit)
MG Mud User88f12472016-06-24 23:31:02 +020084 {
Bugfixacdf07a2016-10-13 20:25:25 +020085 continue;
MG Mud User88f12472016-06-24 23:31:02 +020086 }
Bugfixacdf07a2016-10-13 20:25:25 +020087 catch(call_other(arr[limit ..], "remove"); publish);
88 }
MG Mud User88f12472016-06-24 23:31:02 +020089}
90
91
92/* Item handling */
Bugfixacdf07a2016-10-13 20:25:25 +020093public varargs object AddItem(mixed filename, int refresh, mixed props)
MG Mud User88f12472016-06-24 23:31:02 +020094{
Bugfixacdf07a2016-10-13 20:25:25 +020095 string file;
96 object ob;
97 int i;
MG Mud User88f12472016-06-24 23:31:02 +020098
Bugfixacdf07a2016-10-13 20:25:25 +020099 if(pointerp(filename))
100 {
101 for(i=sizeof(filename);i--;)
102 {
Vanion50652322020-03-10 21:13:25 +0100103 filename[i] = ({string})master()->make_path_absolute( filename[i] );
MG Mud User88f12472016-06-24 23:31:02 +0200104 }
Bugfixacdf07a2016-10-13 20:25:25 +0200105
106 file=filename[random(sizeof(filename))];
107 }
108 else
109 {
Vanion50652322020-03-10 21:13:25 +0100110 file=filename=({string})master()->make_path_absolute(filename);
Bugfixacdf07a2016-10-13 20:25:25 +0200111 }
112
113 if(props==1)
114 {
115 catch(ob=load_object(file); publish);
116 }
117 else
118 {
119 catch(ob=clone_object(file); publish);
120 }
121
122 if(objectp(ob))
123 {
124 ob->move(ME,M_NOCHECK|M_NO_ATTACK);
125 // mit Absicht keine Pruefung aufs Move, wenns nicht geht, solls 2s
126 // spaeter auf der Ebene buggen, weil praktisch niemand im create() das
127 // Ergebnis vom AddItem() prueft.
128 }
MG Mud User88f12472016-06-24 23:31:02 +0200129
Bugfixacdf07a2016-10-13 20:25:25 +0200130 // In P_ITEMS vermerken, es sei denn, REFRESH_NONE ist gegeben, in dem
131 // Fall ist die Speicherung voellig unnoetig.
132 // TODO: Pruefen, ob das wirklich problemlos geht. Bis dahin werden auch
133 // TODO::REFRESH_NONE-Items vermerkt. (s. clean_up() in /std/room.c)
134 //if (!(refresh&REFRESH_NONE)) {
135 SetProp(P_ITEMS,QueryProp(P_ITEMS)+
136 ({
137 ({
138 ob, // RITEM_OBJECT
139 filename, // RITEM_FILE
140 refresh // RITEM_REFRESH
141 })+
142 ((mappingp(props) || props==1) ? ({props}) : ({}))
143 }));
144 //}
MG Mud User88f12472016-06-24 23:31:02 +0200145
Bugfixacdf07a2016-10-13 20:25:25 +0200146 if(ob && mappingp(props))
147 walk_mapping(props,symbol_function("SetProp",ob));
148
149 return ob;
MG Mud User88f12472016-06-24 23:31:02 +0200150}
151
152
Bugfixacdf07a2016-10-13 20:25:25 +0200153private void ri_rem_ob(object ob)
MG Mud User88f12472016-06-24 23:31:02 +0200154{
Bugfixacdf07a2016-10-13 20:25:25 +0200155 object *inv;
MG Mud User88f12472016-06-24 23:31:02 +0200156
Bugfix4cbed652016-10-13 22:03:08 +0200157 if(objectp(ob) && environment(ob)==this_object())
Bugfixacdf07a2016-10-13 20:25:25 +0200158 {
159 inv=deep_inventory(ob);
Bugfix4cbed652016-10-13 22:03:08 +0200160
161 foreach(object o : inv)
Bugfixacdf07a2016-10-13 20:25:25 +0200162 {
Bugfix4cbed652016-10-13 22:03:08 +0200163 o->remove(1);
164 if(objectp(o))
Bugfixacdf07a2016-10-13 20:25:25 +0200165 {
Bugfix4cbed652016-10-13 22:03:08 +0200166 destruct(o);
Bugfixacdf07a2016-10-13 20:25:25 +0200167 }
168 }
Bugfix4cbed652016-10-13 22:03:08 +0200169
Bugfixacdf07a2016-10-13 20:25:25 +0200170 ob->remove(1);
Bugfix4cbed652016-10-13 22:03:08 +0200171
Bugfixacdf07a2016-10-13 20:25:25 +0200172 if(ob)
173 {
174 destruct(ob);
175 }
176 }
177}
178
Bugfix946e4052018-10-25 17:16:45 +0200179private int ri_filter(<int|<string|string*>|object|mapping>* ritem,
Bugfix4cbed652016-10-13 22:03:08 +0200180 string|string* file)
Bugfixacdf07a2016-10-13 20:25:25 +0200181{
Bugfix4cbed652016-10-13 22:03:08 +0200182 object ob;
183
Bugfixacdf07a2016-10-13 20:25:25 +0200184 ob=ritem[RITEM_OBJECT];
Bugfix4cbed652016-10-13 22:03:08 +0200185
Bugfixacdf07a2016-10-13 20:25:25 +0200186 if(stringp(file) && ritem[RITEM_FILE]==file)
Bugfix4cbed652016-10-13 22:03:08 +0200187 {
188 ri_rem_ob(ob);
189 return 0;
190 }
Bugfixacdf07a2016-10-13 20:25:25 +0200191 else if(pointerp(ritem[RITEM_FILE]) && pointerp(file) &&
Bugfix4cbed652016-10-13 22:03:08 +0200192 sizeof(file & ritem[RITEM_FILE])==sizeof(ritem[RITEM_FILE]))
193 {
194 ri_rem_ob(ob);
195 return 0;
196 }
Bugfixacdf07a2016-10-13 20:25:25 +0200197
198 return 1;
199}
200
201
Bugfix4cbed652016-10-13 22:03:08 +0200202public void RemoveItem(string|string* filename)
Bugfixacdf07a2016-10-13 20:25:25 +0200203{
Arathorn5b13ba92019-11-25 21:59:55 +0100204 < <int|<string|string*>|object|mapping>* >* items=QueryProp(P_ITEMS);
Bugfixacdf07a2016-10-13 20:25:25 +0200205
Bugfix4cbed652016-10-13 22:03:08 +0200206 if(!pointerp(items) || !sizeof(items))
207 {
Bugfixacdf07a2016-10-13 20:25:25 +0200208 return;
Bugfix4cbed652016-10-13 22:03:08 +0200209 }
Bugfixacdf07a2016-10-13 20:25:25 +0200210
211 if(pointerp(filename))
212 {
Bugfix4cbed652016-10-13 22:03:08 +0200213 foreach(string fn: &filename)
Bugfixacdf07a2016-10-13 20:25:25 +0200214 {
Zesstra6fa58d42018-11-08 22:21:21 +0100215 fn=master()->make_path_absolute(fn);
Bugfixacdf07a2016-10-13 20:25:25 +0200216 }
217 }
218 else
219 {
Zesstra6fa58d42018-11-08 22:21:21 +0100220 filename=master()->make_path_absolute( filename );
Bugfixacdf07a2016-10-13 20:25:25 +0200221 }
Bugfix4cbed652016-10-13 22:03:08 +0200222
223 SetProp(P_ITEMS,filter(items, #'ri_filter/*'*/,filename));
Bugfixacdf07a2016-10-13 20:25:25 +0200224}
225
Bugfixacdf07a2016-10-13 20:25:25 +0200226private mixed _do_refresh(mixed item)
227{
228 string file;
229 object ob;
230
231 if(!pointerp(item) || item[RITEM_REFRESH]==REFRESH_NONE)
232 {
233 return item;
234 }
235
236 if(pointerp(item[RITEM_FILE]))
237 {
238 file=item[RITEM_FILE][random(sizeof(item[RITEM_FILE]))];
239 }
240 else
241 {
242 file=item[RITEM_FILE];
243 }
244
245 switch(item[RITEM_REFRESH])
246 {
247 case REFRESH_MOVE_HOME:
248 if(objectp(item[RITEM_OBJECT]) &&
249 environment(item[RITEM_OBJECT])!=ME)
250 {
251 item[RITEM_OBJECT]->move(ME,M_GO|M_NO_ATTACK);
252 break;
253 }
254
MG Mud User88f12472016-06-24 23:31:02 +0200255 // fall through
256 case REFRESH_DESTRUCT:
Bugfixacdf07a2016-10-13 20:25:25 +0200257 if(objectp(item[RITEM_OBJECT]))
258 break; // else FALL THROUGH
259
MG Mud User88f12472016-06-24 23:31:02 +0200260 case REFRESH_REMOVE:
Bugfixacdf07a2016-10-13 20:25:25 +0200261 if(objectp(item[RITEM_OBJECT]) &&
262 environment(item[RITEM_OBJECT])==ME)
263 break; // else FALL THROUGH
264
MG Mud User88f12472016-06-24 23:31:02 +0200265 default:
Bugfixacdf07a2016-10-13 20:25:25 +0200266 if(sizeof(item)>RITEM_PROPS && item[RITEM_PROPS]==1)
267 {
268 ob=load_object(file);
269 }
270 else
271 {
272 ob=clone_object(file);
273 }
MG Mud User88f12472016-06-24 23:31:02 +0200274
Bugfixacdf07a2016-10-13 20:25:25 +0200275 ob->move(ME,M_NOCHECK|M_NO_ATTACK);
276 break;
277 }
278
279 if(ob)
280 {
281 item[RITEM_OBJECT]=ob;
282
283 if(sizeof(item)>RITEM_PROPS && mappingp(item[RITEM_PROPS]))
284 walk_mapping(item[RITEM_PROPS],symbol_function("SetProp",ob));
285 }
286
287 return item;
MG Mud User88f12472016-06-24 23:31:02 +0200288}
289
290
291// reset handling: check how the items should be refreshed.
292void reset()
293{
Bugfixacdf07a2016-10-13 20:25:25 +0200294 mixed *items;
MG Mud User88f12472016-06-24 23:31:02 +0200295
Bugfixacdf07a2016-10-13 20:25:25 +0200296 if(!pointerp(items=QueryProp(P_ITEMS)))
297 {
298 SetProp(P_ITEMS,({}));
299 return;
300 }
301
302 SetProp(P_ITEMS,map(items,#'_do_refresh)-({0}));
MG Mud User88f12472016-06-24 23:31:02 +0200303}
304