blob: 282ebcc82be8ab2f6a858afa1d106668f9a96a59 [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
30#pragma pedantic
31
32#define NEED_PROTOTYPES
33#include <thing/properties.h>
34#include <rooms.h>
35#include <container.h>
36#undef NEED_PROTOTYPES
37#include <defines.h>
38#include <config.h>
39#include <properties.h>
40#include <moving.h>
41#include <daemon.h>
42
43protected void create()
44{
Bugfixacdf07a2016-10-13 20:25:25 +020045 Set(P_ITEMS,({}));
46 Set(P_ITEMS,SECURED,F_MODE_AS);
47
48 OBJECTD->QueryObject(); // querying general objects
MG Mud User88f12472016-06-24 23:31:02 +020049}
50
Bugfixacdf07a2016-10-13 20:25:25 +020051protected void create_super()
52{
MG Mud User88f12472016-06-24 23:31:02 +020053 set_next_reset(-1);
54}
55
56/* Kram zum Aufraeumen von multiplen gleichen Items im Container. */
Bugfixacdf07a2016-10-13 20:25:25 +020057private object removeable_ob(object ob)
MG Mud User88f12472016-06-24 23:31:02 +020058{
Bugfixacdf07a2016-10-13 20:25:25 +020059 if(!query_once_interactive(ob) && !living(ob))
60 {
61 return ob;
62 }
MG Mud User88f12472016-06-24 23:31:02 +020063
Bugfixacdf07a2016-10-13 20:25:25 +020064 return 0;
MG Mud User88f12472016-06-24 23:31:02 +020065}
66
67protected varargs void remove_multiple(int limit, mixed fun)
68{
Bugfixacdf07a2016-10-13 20:25:25 +020069 object *inh = all_inventory(ME)-({0});
MG Mud User88f12472016-06-24 23:31:02 +020070
Bugfixacdf07a2016-10-13 20:25:25 +020071 inh=filter(inh,#'removeable_ob);
72 foreach(mixed item : QueryProp(P_ITEMS))
73 {
74 inh-=({item[0]});
75 }
76
77 if(!stringp(fun) && !closurep(fun))
78 {
79 fun="description_id";
80 }
Zesstracd62c192019-11-23 17:15:31 +010081 object **sorted_inh=unique_array(inh,fun,0);
82 foreach(object *arr : sorted_inh)
Bugfixacdf07a2016-10-13 20:25:25 +020083 {
84 if(sizeof(arr)<=limit)
MG Mud User88f12472016-06-24 23:31:02 +020085 {
Bugfixacdf07a2016-10-13 20:25:25 +020086 continue;
MG Mud User88f12472016-06-24 23:31:02 +020087 }
Bugfixacdf07a2016-10-13 20:25:25 +020088 catch(call_other(arr[limit ..], "remove"); publish);
89 }
MG Mud User88f12472016-06-24 23:31:02 +020090}
91
92
93/* Item handling */
Bugfixacdf07a2016-10-13 20:25:25 +020094public varargs object AddItem(mixed filename, int refresh, mixed props)
MG Mud User88f12472016-06-24 23:31:02 +020095{
Bugfixacdf07a2016-10-13 20:25:25 +020096 string file;
97 object ob;
98 int i;
MG Mud User88f12472016-06-24 23:31:02 +020099
Bugfixacdf07a2016-10-13 20:25:25 +0200100 if(pointerp(filename))
101 {
102 for(i=sizeof(filename);i--;)
103 {
Zesstra6fa58d42018-11-08 22:21:21 +0100104 filename[i] = (string)master()->make_path_absolute( filename[i] );
MG Mud User88f12472016-06-24 23:31:02 +0200105 }
Bugfixacdf07a2016-10-13 20:25:25 +0200106
107 file=filename[random(sizeof(filename))];
108 }
109 else
110 {
Zesstra6fa58d42018-11-08 22:21:21 +0100111 file=filename=(string)master()->make_path_absolute(filename);
Bugfixacdf07a2016-10-13 20:25:25 +0200112 }
113
114 if(props==1)
115 {
116 catch(ob=load_object(file); publish);
117 }
118 else
119 {
120 catch(ob=clone_object(file); publish);
121 }
122
123 if(objectp(ob))
124 {
125 ob->move(ME,M_NOCHECK|M_NO_ATTACK);
126 // mit Absicht keine Pruefung aufs Move, wenns nicht geht, solls 2s
127 // spaeter auf der Ebene buggen, weil praktisch niemand im create() das
128 // Ergebnis vom AddItem() prueft.
129 }
MG Mud User88f12472016-06-24 23:31:02 +0200130
Bugfixacdf07a2016-10-13 20:25:25 +0200131 // In P_ITEMS vermerken, es sei denn, REFRESH_NONE ist gegeben, in dem
132 // Fall ist die Speicherung voellig unnoetig.
133 // TODO: Pruefen, ob das wirklich problemlos geht. Bis dahin werden auch
134 // TODO::REFRESH_NONE-Items vermerkt. (s. clean_up() in /std/room.c)
135 //if (!(refresh&REFRESH_NONE)) {
136 SetProp(P_ITEMS,QueryProp(P_ITEMS)+
137 ({
138 ({
139 ob, // RITEM_OBJECT
140 filename, // RITEM_FILE
141 refresh // RITEM_REFRESH
142 })+
143 ((mappingp(props) || props==1) ? ({props}) : ({}))
144 }));
145 //}
MG Mud User88f12472016-06-24 23:31:02 +0200146
Bugfixacdf07a2016-10-13 20:25:25 +0200147 if(ob && mappingp(props))
148 walk_mapping(props,symbol_function("SetProp",ob));
149
150 return ob;
MG Mud User88f12472016-06-24 23:31:02 +0200151}
152
153
Bugfixacdf07a2016-10-13 20:25:25 +0200154private void ri_rem_ob(object ob)
MG Mud User88f12472016-06-24 23:31:02 +0200155{
Bugfixacdf07a2016-10-13 20:25:25 +0200156 object *inv;
MG Mud User88f12472016-06-24 23:31:02 +0200157
Bugfix4cbed652016-10-13 22:03:08 +0200158 if(objectp(ob) && environment(ob)==this_object())
Bugfixacdf07a2016-10-13 20:25:25 +0200159 {
160 inv=deep_inventory(ob);
Bugfix4cbed652016-10-13 22:03:08 +0200161
162 foreach(object o : inv)
Bugfixacdf07a2016-10-13 20:25:25 +0200163 {
Bugfix4cbed652016-10-13 22:03:08 +0200164 o->remove(1);
165 if(objectp(o))
Bugfixacdf07a2016-10-13 20:25:25 +0200166 {
Bugfix4cbed652016-10-13 22:03:08 +0200167 destruct(o);
Bugfixacdf07a2016-10-13 20:25:25 +0200168 }
169 }
Bugfix4cbed652016-10-13 22:03:08 +0200170
Bugfixacdf07a2016-10-13 20:25:25 +0200171 ob->remove(1);
Bugfix4cbed652016-10-13 22:03:08 +0200172
Bugfixacdf07a2016-10-13 20:25:25 +0200173 if(ob)
174 {
175 destruct(ob);
176 }
177 }
178}
179
Bugfix946e4052018-10-25 17:16:45 +0200180private int ri_filter(<int|<string|string*>|object|mapping>* ritem,
Bugfix4cbed652016-10-13 22:03:08 +0200181 string|string* file)
Bugfixacdf07a2016-10-13 20:25:25 +0200182{
Bugfix4cbed652016-10-13 22:03:08 +0200183 object ob;
184
Bugfixacdf07a2016-10-13 20:25:25 +0200185 ob=ritem[RITEM_OBJECT];
Bugfix4cbed652016-10-13 22:03:08 +0200186
Bugfixacdf07a2016-10-13 20:25:25 +0200187 if(stringp(file) && ritem[RITEM_FILE]==file)
Bugfix4cbed652016-10-13 22:03:08 +0200188 {
189 ri_rem_ob(ob);
190 return 0;
191 }
Bugfixacdf07a2016-10-13 20:25:25 +0200192 else if(pointerp(ritem[RITEM_FILE]) && pointerp(file) &&
Bugfix4cbed652016-10-13 22:03:08 +0200193 sizeof(file & ritem[RITEM_FILE])==sizeof(ritem[RITEM_FILE]))
194 {
195 ri_rem_ob(ob);
196 return 0;
197 }
Bugfixacdf07a2016-10-13 20:25:25 +0200198
199 return 1;
200}
201
202
Bugfix4cbed652016-10-13 22:03:08 +0200203public void RemoveItem(string|string* filename)
Bugfixacdf07a2016-10-13 20:25:25 +0200204{
Arathorn5b13ba92019-11-25 21:59:55 +0100205 < <int|<string|string*>|object|mapping>* >* items=QueryProp(P_ITEMS);
Bugfixacdf07a2016-10-13 20:25:25 +0200206
Bugfix4cbed652016-10-13 22:03:08 +0200207 if(!pointerp(items) || !sizeof(items))
208 {
Bugfixacdf07a2016-10-13 20:25:25 +0200209 return;
Bugfix4cbed652016-10-13 22:03:08 +0200210 }
Bugfixacdf07a2016-10-13 20:25:25 +0200211
212 if(pointerp(filename))
213 {
Bugfix4cbed652016-10-13 22:03:08 +0200214 foreach(string fn: &filename)
Bugfixacdf07a2016-10-13 20:25:25 +0200215 {
Zesstra6fa58d42018-11-08 22:21:21 +0100216 fn=master()->make_path_absolute(fn);
Bugfixacdf07a2016-10-13 20:25:25 +0200217 }
218 }
219 else
220 {
Zesstra6fa58d42018-11-08 22:21:21 +0100221 filename=master()->make_path_absolute( filename );
Bugfixacdf07a2016-10-13 20:25:25 +0200222 }
Bugfix4cbed652016-10-13 22:03:08 +0200223
224 SetProp(P_ITEMS,filter(items, #'ri_filter/*'*/,filename));
Bugfixacdf07a2016-10-13 20:25:25 +0200225}
226
Bugfixacdf07a2016-10-13 20:25:25 +0200227private mixed _do_refresh(mixed item)
228{
229 string file;
230 object ob;
231
232 if(!pointerp(item) || item[RITEM_REFRESH]==REFRESH_NONE)
233 {
234 return item;
235 }
236
237 if(pointerp(item[RITEM_FILE]))
238 {
239 file=item[RITEM_FILE][random(sizeof(item[RITEM_FILE]))];
240 }
241 else
242 {
243 file=item[RITEM_FILE];
244 }
245
246 switch(item[RITEM_REFRESH])
247 {
248 case REFRESH_MOVE_HOME:
249 if(objectp(item[RITEM_OBJECT]) &&
250 environment(item[RITEM_OBJECT])!=ME)
251 {
252 item[RITEM_OBJECT]->move(ME,M_GO|M_NO_ATTACK);
253 break;
254 }
255
MG Mud User88f12472016-06-24 23:31:02 +0200256 // fall through
257 case REFRESH_DESTRUCT:
Bugfixacdf07a2016-10-13 20:25:25 +0200258 if(objectp(item[RITEM_OBJECT]))
259 break; // else FALL THROUGH
260
MG Mud User88f12472016-06-24 23:31:02 +0200261 case REFRESH_REMOVE:
Bugfixacdf07a2016-10-13 20:25:25 +0200262 if(objectp(item[RITEM_OBJECT]) &&
263 environment(item[RITEM_OBJECT])==ME)
264 break; // else FALL THROUGH
265
MG Mud User88f12472016-06-24 23:31:02 +0200266 default:
Bugfixacdf07a2016-10-13 20:25:25 +0200267 if(sizeof(item)>RITEM_PROPS && item[RITEM_PROPS]==1)
268 {
269 ob=load_object(file);
270 }
271 else
272 {
273 ob=clone_object(file);
274 }
MG Mud User88f12472016-06-24 23:31:02 +0200275
Bugfixacdf07a2016-10-13 20:25:25 +0200276 ob->move(ME,M_NOCHECK|M_NO_ATTACK);
277 break;
278 }
279
280 if(ob)
281 {
282 item[RITEM_OBJECT]=ob;
283
284 if(sizeof(item)>RITEM_PROPS && mappingp(item[RITEM_PROPS]))
285 walk_mapping(item[RITEM_PROPS],symbol_function("SetProp",ob));
286 }
287
288 return item;
MG Mud User88f12472016-06-24 23:31:02 +0200289}
290
291
292// reset handling: check how the items should be refreshed.
293void reset()
294{
Bugfixacdf07a2016-10-13 20:25:25 +0200295 mixed *items;
MG Mud User88f12472016-06-24 23:31:02 +0200296
Bugfixacdf07a2016-10-13 20:25:25 +0200297 if(!pointerp(items=QueryProp(P_ITEMS)))
298 {
299 SetProp(P_ITEMS,({}));
300 return;
301 }
302
303 SetProp(P_ITEMS,map(items,#'_do_refresh)-({0}));
MG Mud User88f12472016-06-24 23:31:02 +0200304}
305