blob: dcd09c17235fa40acf596268d85340b02a3bd676 [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001#pragma strict_types,save_types,rtt_checks
2#pragma pedantic,range_check
3#pragma no_inherit,no_clone
4#pragma no_shadow
5
6#define _NEED_DROPMASTER_IMPLEMENTATION_
7#include <dropmaster.h>
8#include <defines.h>
9#include <wizlevels.h>
10
11struct random_event_s {
12 string *names;
13 int reduction;
14 int *rnd_values;
15 int *default_rnd_values;
16 string creator;
17};
18
19// Mapping mit einem random_event_s als Wert pro Schluessel
20// Schluessel: 0: globaler Eintrag, ansonsten BP-Namen oder Teile von Pfaden
21// (/d/<eben>/<magier>/<gebiet>/)
22private mapping randomEvents;
23
24private struct random_event_s SanitizeRE(struct random_event_s re)
25{
26 // rnd_values, default_rnd_values und names muessen gleich lang sein -> auf
27 // das kuerzeste kuerzen. Achtung: macht implizit eine Kopie - WICHTIG!
28 int size = sizeof(re->rnd_values);
29 if (pointerp(re->names))
30 size = min(size, sizeof(re->names));
31 if (pointerp(re->default_rnd_values)) {
32 size = min(size, sizeof(re->default_rnd_values));
33 re->default_rnd_values = re->default_rnd_values[0..size-1];
34 }
35 if (pointerp(re->names))
36 re->names = re->names[0..size-1];
37
38 re->rnd_values = re->rnd_values[0..size-1];
39
40 return re;
41}
42
43// key==0 signifies the global key
44public varargs void CreateRandomEvent(string key, int *rnd_val,
45 string *rnd_names, int red)
46{
47 struct random_event_s re = (<random_event_s>);
48
49 if (!member(randomEvents,key)) {
50 re->rnd_values = copy(rnd_val) || DFLT_RND_VALUES;
51 // wenn rnd_val == 0 ist, ist das OK, dann wird spaeter immer
52 // DFLT_RND_VALUES genommen.
53 re->default_rnd_values = copy(rnd_val);
54 // names darf auch 0 sein, wenn Defaultwerte genommen werden sollen.
55 re->names = copy(rnd_names);
56 re->reduction = red || RND_REDUCTION;
57 re->creator = object_name(extern_call() ? previous_object() : this_object());
58
59 randomEvents[key] = SanitizeRE(re);
60 }
61}
62
63public varargs int ChangeRandomEvent(string key, int *rnd_val, int *rnd_val_dflt,
64 string *rnd_names, int red)
65{
66 if (process_call()) return -1;
67 if (!member(randomEvents, key)) return -2;
68 struct random_event_s re = randomEvents[key];
69 // Schreibzugriff erlauben? Nur fuer Erschafferobjekte und EM.
70 // Bemerkung: RM+ haben Zugriff, weil sie Schreibzugriff auf das
71 // Erschafferobjekt haben.
72 if (extern_call()
73 && re->creator != object_name(previous_object())
74 && !ARCH_SECURITY)
75 return -1;
76
77 if (pointerp(rnd_val))
78 re->rnd_values = rnd_val;
79 if (pointerp(rnd_val_dflt))
80 re->default_rnd_values = rnd_val_dflt;
81 if (pointerp(rnd_names))
82 re->names = rnd_names;
83 if (red)
84 re->reduction = red;
85
86 SanitizeRE(re);
87
88 return 1;
89}
90
91public int DeleteRandomEvent(string key)
92{
93 if (process_call()) return -1;
94 if (!member(randomEvents, key)) return -2;
95 struct random_event_s re = randomEvents[key];
96 // Schreibzugriff erlauben? Nur fuer Erschafferobjekte und EM.
97 // Bemerkung: RMs haben Zugriff, weil sie Schreibzugriff auf das
98 // Erschafferobjekt haben.
99 if (extern_call()
100 && re->creator != object_name(previous_object())
101 && !ARCH_SECURITY)
102 return -1;
103
104 m_delete(randomEvents, key);
105 return 1;
106}
107
108void create()
109{
110 seteuid(getuid(this_object()));
111 restore_object(DROPSAVE);
112 if(!randomEvents || !mappingp(randomEvents))
113 {
114 randomEvents = ([]);
115 }
116 if (!member(randomEvents, GLOBAL_KEY))
117 CreateRandomEvent(GLOBAL_KEY, DFLT_RND_VALUES, DFLT_RND_NAMES, RND_REDUCTION);
118 set_next_reset(3600 + random(10800));
119}
120
121void saveme(){
122 save_object(DROPSAVE);
123}
124
125varargs int remove()
126{
127 saveme();
128 destruct(ME);
129 return 1;
130}
131
132public varargs int dropRare(int rarelevel, string key) {
133 if (!member(randomEvents, key))
134 return 0;
135
136 struct random_event_s re = randomEvents[key];
137 if (rarelevel < 0 || rarelevel >= sizeof(re->rnd_values))
138 return 0;
139 if (random(re->rnd_values[rarelevel]) == 0)
140 {
141 // Defaultwert wiederherstellen.
142 if (pointerp(re->default_rnd_values))
143 re->rnd_values[rarelevel] = re->default_rnd_values[rarelevel];
144 else
145 re->rnd_values[rarelevel] = DFLT_RND_VALUES[rarelevel];
146 // und droppen.
147 return 1;
148 }
149 else
150 {
151 // Wahrscheinlichkeit erhoehen, indem rnd_values reduziert wird.
152 re->rnd_values[rarelevel] -= re->reduction;
153 // negative rnd_values sind ok, random() ist dann immer 0.
154 }
155 // fall-through
156 return 0;
157}
158
159// Droppt genau 1 oder 0 Items aus dem gegebenen Set. Benutzt hierbei das
160// mittels <key> definierte Randomevent und den zur jeweiligen ID gegebenen
161// <rarelevel>.
162// <set> muss in der Form
163// { {ID,RARELEVEL}, {ID,RARELEVEL}, ... }
164// gegeben werden. <ID> muss dabei != 0 sein und wird im Erfolgsfall
165// zurueckgeben.
166mixed dropSetItem(mixed set, string key) {
167
168 if (pointerp(set))
169 {
170 set=filter(set, function int (mixed el) {
171 return pointerp(el) && sizeof(el)>=2 && intp(el[1]);
172 } );
173 set=sort_array(set, function int (mixed a, mixed b) {
174 return a[1]>b[1];
175 });
176
177 foreach(mixed el: set) {
178 if(dropRare(el[1], key)){
179 return el[0];
180 }
181 }
182 }
183
184 return 0;
185}
186
187void reset()
188{
189 set_next_reset(3600*72);
190 // ein wenig aufraeumen
191
192 // Alle Events rauswerfen, deren Erschafferobjekt nicht mehr exisiert
193 // (Nachteil: nicht-geladene VC-Objekte werden nicht beruecksichtigt).
194 foreach(string key, struct random_event_s re: randomEvents) {
195 if (!find_object(re->creator)
196 && file_size(re->creator + ".c") <= 0)
197 m_delete(randomEvents, key);
198 }
199
200 saveme();
201}
202