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