blob: f0260cf5ecbfd61175ee3645b8cdaa9d517ac36c [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// MorgenGrauen MUDlib
2//
3// /std/npc/items.c -- Item-Verwaltung fuer NPCs
4//
5// $Id: items.c 8146 2012-10-30 18:18:14Z Zesstra $
6//
7// (c) by Padreic (Padreic@mg.mud.de)
8#pragma strong_types
9#pragma save_types
10#pragma range_check
11#pragma no_clone
12#pragma pedantic
13
14#define NEED_PROTOTYPES
15#include <thing/properties.h>
16#include <thing/description.h>
17#include <living/combat.h>
18#undef NEED_PROTOTYPES
19#include <npc.h>
20#include <properties.h>
21#include <combat.h>
22#include <config.h>
23#include <moving.h>
24#include <sys_debug.h>
25
26protected void create()
27{
28 // dieses flag ist nur bis zum ersten move gesetzt. Nimmt danach also auch
29 Set(NPC_NEEDS_ITEM_INIT, 1); // keinen Speicher mehr in Anspruch.
30 // Set(P_ITEMS, ({})); // keine initialisierung spart Speicher
31}
32
33protected void create_super() {
34 set_next_reset(-1);
35}
36
37protected object* maybe_own_stuff() {
38 object* obs = all_inventory(environment());
39 object haufen = present("\nhaufen "+name(WEM),environment());
40 if( objectp(haufen) ) obs += all_inventory(haufen);
41 object leiche = present("\nleiche "+name(WEM),environment());
42 if( objectp(leiche) ) obs += all_inventory(leiche);
43 return obs;
44}
45
46// clont alle Objekte die geclont werden muessen...
47protected void _clone_items()
48{
49 int i, j, mode, refresh;
50 object ob, *inv1;
51 mixed props, *items;
52 string file, *inv2;
53
54 if (!pointerp(items=QueryProp(P_ITEMS))) return;
55 if (environment()) { // Liste mit filenamen (inv2) erstellen.
56 inv1 = maybe_own_stuff();
57 inv2 = map(inv1, #'load_name);
58 }
59 else inv2=({}); // inv1 wird gar nicht mehr benoetigt
60
61 for (i=sizeof(items)-1; i>=0; i--) {
62 ob = items[i][RITEM_OBJECT];
63 file = items[i][RITEM_FILE];
64 mode = items[i][RITEM_REFRESH];
65 refresh = mode & 0x0000ffff;
66 props = items[i][RITEM_PROPS];
67 if (props && intp(props)) { // unique Gegenstand?
68 ob=find_object(file);
69 if (ob) {
70 // kann ob aufgenommen werden? Wenn das Objekt in inv1 drin ist, ist es
71 // im Env oder in einer Leiche oder einem Haufen.
72 if (member(inv1,ob) > -1) {
73 if (environment()) {
74 if (environment(ob) == environment())
75 tell_room(environment(),
76 capitalize(name(WER))+" hebt "+ob->name(WEN)+" auf.\n");
77 else
78 tell_room(environment(),break_string(
79 capitalize(name(WER))+" nimmt "+ob->name(WEN)+ " aus "
80 +environment(ob)->name(WEM) + ".",78));
81 }
82 ob->remove(); // zerstoeren und neuladen.
83 if (ob) destruct(ob);
84 if (catch(ob=load_object(file);publish))
85 raise_error(sprintf(
86 "_clone_items(): %O does not exist or is not loadable\n", file));
87 ob->move(this_object(), M_NOCHECK);
88 items[i][RITEM_OBJECT]=ob;
89 }
90 else switch( refresh ) {
91 case REFRESH_DESTRUCT:
92 if (environment(ob)) {
93 ob=0; // nicht zuecken, tragen, initialisieren...
94 break;
95 }
96 case REFRESH_ALWAYS:
97 case REFRESH_REMOVE:
98 ob->remove();
99 if (ob) destruct(ob);
100 if (catch(ob=load_object(file);publish))
101 raise_error(sprintf("_clone_items(): "
102 "%O does not exist or is not loadable\n", file));
103 ob->move(this_object(), M_NOCHECK);
104 items[i][RITEM_OBJECT]=ob;
105 break;
106 case REFRESH_NONE:
107 default: ob=0; // nicht zuecken, tragen, initialisieren...
108 }
109 }
110 else {
111 if (catch(ob=load_object(file);publish)) raise_error(sprintf(
112 "_clone_items(): %O does not exist or is not loadable\n", file));
113 if (objectp(ob)) ob->move(this_object(), M_NOCHECK);
114 items[i][RITEM_OBJECT]=ob;
115 }
116 } // if (props ...) // also nicht unique
117 else {
118 switch( refresh ) {
119 case REFRESH_DESTRUCT: // erfuellt auch REFRESH_REMOVE Bedingung...
120 if (ob) {
121 ob=0; // nicht zuecken, tragen, initialisieren...
122 break;
123 }
124 case REFRESH_REMOVE:
125 if (ob) {
126 if(present(ob, this_object())) {
127 ob=0; // nicht zuecken, tragen, initialisieren...
128 break;
129 }
130 else {
131 if ((member(inv2, file))==-1) {
132 ob=0;
133 }
134 }
135 }
136 case REFRESH_NONE: // wird entfernt nach dem ersten clonen!!!
137 case REFRESH_ALWAYS:
138 // schauen ob der Gegenstand im environment liegt.
139 if ((j=member(inv2, file))!=-1) {
140 ob=inv1[j]; // inv1 kann leer sein, aber dann ist inv2 auch leer
141 inv1[j]=0; // wichtig falls mehrere gleiche AddItems
142 inv2[j]=0; // = 0 setzen um Array kopieren zu vermeiden
143 if (environment()) {
144 if (environment() == environment(ob))
145 tell_room(environment(),
146 capitalize(name(WER))+" hebt "+ob->name(WEN)+" auf.\n");
147 else
148 tell_room(environment(),break_string(
149 capitalize(name(WER))+" nimmt "+ob->name(WEN)+" aus "
150 +environment(ob)->name(WEM) + ".",78));
151 }
152 }
153 if (ob) {
154 ob->remove();
155 if (ob) destruct(ob);
156 }
157 if (catch(ob=clone_object(file);publish)) raise_error(sprintf(
158 "_clone_items(): %O does not exist or is not loadable\n", file));
159 ob->move(this_object(), M_NOCHECK);
160 switch( refresh ) {
161 case REFRESH_NONE:
162 items[i] = 0; // Speicher freimachen
163 break;
164 case REFRESH_ALWAYS:
165 items[i][RITEM_OBJECT] = 0; // Objekt "vergessen"
166 break;
167 default:
168 items[i][RITEM_OBJECT] = ob;
169 }
170 break;
171 default: ob=0; // nicht zuecken, tragen, initialisieren...
172 }
173 } // if (props ...) else
174 if (ob) {
175 if (mappingp(props)) walk_mapping(props, symbol_function("SetProp", ob));
176 // Eigentlich will man hier sowas wie command("zuecke schwert")
177 // machen, aber das handling der id's kann nicht sicherstellen,
178 // dass der NPC die richtige Waffe erwischt, deshalb machen wir
179 // das tragen hier von Hand.
180 if (mode & CLONE_WEAR) {
181 if( mode & CLONE_NO_CHECK ) {
182 object *armours;
183 ob->DoUnwear(); // evtl. dem Vorgaenger abnehmen.
184 UseHands(ob, ob->QueryProp(P_NR_HANDS));
185 armours=QueryProp(P_ARMOURS)+({ ob });
186 SetProp(P_ARMOURS, armours);
187 SetProp(P_TOTAL_AC, QueryProp(P_TOTAL_AC)+ob->QueryProp(P_AC));
188 ob->SetProp(P_WORN, this_object());
189 } else {
190 command( "trage \n"+object_name(ob) );
191 }
192 }
193 if (mode & CLONE_WIELD) {
194 if( mode & CLONE_NO_CHECK ) {
195 ob->DoUnwield(); // evtl. dem Vorgaenger abnehmen.
196 UseHands(ob, ob->QueryProp(P_NR_HANDS));
197 SetProp(P_WEAPON, ob);
198 SetProp(P_TOTAL_WC, ob->QueryProp(P_WC));
199 ob->SetProp(P_WIELDED, this_object());
200 } else {
201 command( "zuecke \n"+object_name(ob) );
202 }
203 }
204 } // if (ob)
205 } // for i
206 items-=({ 0 }); // REFRESH_NONEs von nicht unique Objekten
207 if (!sizeof(items)) items=0; // Speicher sparen...
208 SetProp(P_ITEMS, items);
209 Set(NPC_NEEDS_ITEM_INIT, 0);
210}
211
212public varargs object AddItem(mixed filename, int refresh, mixed props)
213{
214 // Aus Array ein Element auswaehlen
215 if (pointerp(filename))
216 filename = filename[random(sizeof(filename))];
217
218 // Kein String? -> Fehler
219 if (!stringp(filename)){
220 raise_error("AddItem: filename or array of filenames expected.\n");
221 } else {
222 // Pfad normieren und eventuell vorhandenes ".c" entfernen
223 filename = MASTER->_get_path(
224 filename[<2..]==".c"?filename=filename[0..<3]
225 : filename,"?");
226 // Property setzen
227 SetProp(P_ITEMS, (QueryProp(P_ITEMS)||({}))+
228 ({ ({ 0, filename, refresh, props }) }));
229
230 if (environment()) _clone_items();
231 }
232 return 0;
233}
234
235void reset()
236// fuer REFRESH_ Objekte...
237{
238 _clone_items();
239}
240