blob: 9961bfeaec28f5e07c94149fc283bb6bad2236b9 [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{
45 Set( P_ITEMS, ({}) );
46 Set( P_ITEMS, SECURED, F_MODE_AS );
47
48 OBJECTD->QueryObject(); // querying general objects
49}
50
51protected void create_super() {
52 set_next_reset(-1);
53}
54
55/* Kram zum Aufraeumen von multiplen gleichen Items im Container. */
56private object removeable_ob( object ob )
57{
58 if ( !query_once_interactive(ob) && !living(ob) )
59 return ob;
60
61 return 0;
62}
63
64protected varargs void remove_multiple(int limit, mixed fun)
65{
66 object *inh = all_inventory(this_object()) - ({0});
67
68 inh = filter( inh, #'removeable_ob );
69 foreach(mixed item : QueryProp(P_ITEMS))
70 inh -= ({ item[0] });
71
72 if (!stringp(fun) && !closurep(fun))
73 fun = "description_id";
74 inh = unique_array(inh, fun, 0);
75 foreach(mixed arr: inh)
76 {
77 if (sizeof(arr) <= limit)
78 continue;
79 catch(call_other(arr[limit ..], "remove"); publish);
80 }
81}
82
83
84/* Item handling */
85public varargs object AddItem( mixed filename, int refresh, mixed props )
86{
87 string file;
88 object ob;
89 int i;
90
91 if( pointerp(filename) ) {
92 for( i = sizeof(filename); i--; )
93 filename[i] = (string)master()->_get_path( filename[i], "?" );
94
95 file = filename[random( sizeof(filename) )];
96 }
97 else
98 file = filename = (string)master()->_get_path( filename, "?" );
99
100 if ( props == 1 )
101 catch(ob = load_object( file); publish);
102 else
103 catch(ob = clone_object(file); publish);
104
105 if (objectp(ob)) {
106 ob->move( this_object(), M_NOCHECK|M_NO_ATTACK );
107 // mit Absicht keine Pruefung aufs Move, wenns nicht geht, solls 2s
108 // spaeter auf der Ebene buggen, weil praktisch niemand im create() das
109 // Ergebnis vom AddItem() prueft.
110 }
111
112 // In P_ITEMS vermerken, es sei denn, REFRESH_NONE ist gegeben, in dem
113 // Fall ist die Speicherung voellig unnoetig.
114 // TODO: Pruefen, ob das wirklich problemlos geht. Bis dahin werden auch
115 // TODO::REFRESH_NONE-Items vermerkt. (s. clean_up() in /std/room.c)
116 //if (!(refresh & REFRESH_NONE)) {
117 SetProp( P_ITEMS, QueryProp(P_ITEMS) +
118 ({ ({ ob, // RITEM_OBJECT
119 filename, // RITEM_FILE
120 refresh // RITEM_REFRESH
121 }) +
122 ((mappingp(props) || props == 1) ? ({ props }) : ({})) }) );
123 //}
124
125 if ( ob && mappingp(props) )
126 walk_mapping( props, symbol_function( "SetProp", ob ) );
127
128 return ob;
129}
130
131
132private void ri_rem_ob( object ob )
133{
134 object *inv;
135 int i;
136
137 if ( objectp(ob) && present(ob, this_object()) ) {
138 inv = deep_inventory(ob);
139
140 for ( i = sizeof(inv); i--; )
141 if ( inv[i] ) {
142 inv[i]->remove(1);
143
144 if ( inv[i] )
145 destruct(inv[i]);
146 }
147
148 ob->remove(1);
149
150 if ( ob )
151 destruct(ob);
152 }
153}
154
155
156private int ri_filter( mixed *ritem, mixed file )
157{
158 object ob, *inv;
159 int i;
160
161 ob = ritem[RITEM_OBJECT];
162
163 if ( stringp(file) && ritem[RITEM_FILE] == file )
164 return ri_rem_ob(ob), 0;
165 else if ( pointerp(ritem[RITEM_FILE]) && pointerp(file) &&
166 sizeof(file & ritem[RITEM_FILE]) == sizeof(ritem[RITEM_FILE]) )
167 return ri_rem_ob(ob), 0;
168
169 return 1;
170}
171
172
173public void RemoveItem( mixed filename )
174{
175 mixed *items;
176 int i;
177
178 if ( !pointerp(items = QueryProp(P_ITEMS)) || !sizeof(items) )
179 return;
180
181 if ( pointerp(filename) )
182 for ( i = sizeof(filename); i--; )
183 filename[i] = (string)master()->_get_path( filename[i], "?" );
184 else
185 filename = (string)master()->_get_path( filename, "?" );
186
187 SetProp( P_ITEMS, filter( items, #'ri_filter/*'*/, filename ) );
188}
189
190
191private mixed _do_refresh( mixed item )
192{
193 string file;
194 object ob;
195
196 if ( !pointerp(item) || item[RITEM_REFRESH] == REFRESH_NONE )
197 return item;
198
199 if ( pointerp(item[RITEM_FILE]) )
200 file = item[RITEM_FILE][random( sizeof(item[RITEM_FILE]) )];
201 else
202 file = item[RITEM_FILE];
203
204 switch( item[RITEM_REFRESH] ){
205 case REFRESH_MOVE_HOME:
206 if ( objectp(item[RITEM_OBJECT]) &&
207 environment(item[RITEM_OBJECT]) != ME ) {
208 item[RITEM_OBJECT]->move( ME, M_GO|M_NO_ATTACK );
209 break;
210 }
211
212 // fall through
213 case REFRESH_DESTRUCT:
214 if ( objectp(item[RITEM_OBJECT]) )
215 break; // else FALL THROUGH
216
217 case REFRESH_REMOVE:
218 if ( objectp(item[RITEM_OBJECT]) &&
219 environment(item[RITEM_OBJECT]) == ME )
220 break; // else FALL THROUGH
221
222 default:
223 if ( sizeof(item) > RITEM_PROPS && item[RITEM_PROPS] == 1 ) {
224 ob = load_object(file);
225 }
226 else
227 ob = clone_object(file);
228
229 ob->move( ME, M_NOCHECK|M_NO_ATTACK );
230 break;
231 }
232
233 if ( ob ){
234 item[RITEM_OBJECT] = ob;
235
236 if ( sizeof(item) > RITEM_PROPS && mappingp(item[RITEM_PROPS]) )
237 walk_mapping( item[RITEM_PROPS], symbol_function( "SetProp", ob ) );
238 }
239
240 return item;
241}
242
243
244// reset handling: check how the items should be refreshed.
245void reset()
246{
247 mixed *items;
248
249 if ( !pointerp(items = QueryProp(P_ITEMS)) ){
250 SetProp( P_ITEMS, ({}) );
251 return;
252 }
253
254 SetProp( P_ITEMS, map( items, #'_do_refresh/*'*/ ) - ({0}) );
255}
256