blob: fef87c540e14cefc7f18525d7a5d458347b80ee8 [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// MorgenGrauen MUDlib
2//
3// armour/wear.c -- armour standard object
4//
5// $Id: combat.c 6243 2007-03-15 21:10:21Z Zesstra $
6
7#pragma strict_types
8#pragma save_types
9#pragma no_clone
10#pragma pedantic
11#pragma range_check
12
13inherit "/std/clothing/wear";
14
15#define NEED_PROTOTYPES
16
17#include <thing/properties.h>
18#include <living/combat.h>
19#include <living/attributes.h>
20#include <language.h>
21#include <defines.h>
22#include <armour.h>
23
24// Uebernimmt viele wesentliche Eigenschaften aus der Kleidung, daher werden
25// hier auch nur div. Funktionen ueberschrieben, die sich leicht
26// unterschiedlich zur Kleidung verhalten.
27
28// Globale Variablen
29private nosave int logged;
30
31protected void create() {
32 ::create();
33 // P_DAMAGED laesst sich zwar (noch) von aussen setzen, aber bitte nur ueber
34 // die hier definierte Setmethode.
35 // TODO: Direktes Setzen von P_DAMAGED entfernen.
36 Set(P_DAMAGED, PROTECTED, F_MODE_AS);
37}
38
39/* Wenn eine Ruestung vom gleichen Typ im Array ist, gebe diese zurueck. */
40private object TestType(object *armours) {
41 mixed type;
42
43 // Den eigenen Typ feststellen
44 type = QueryProp(P_ARMOUR_TYPE);
45
46 // Zerstoerte Objekte aussortieren
47 armours-=({0});
48
49 foreach(object armour: armours)
50 {
51 if (type==(armour->QueryProp(P_ARMOUR_TYPE)))
52 {
53 // Ruestung vom gleichen Typ gefunden -> zurueckgeben
54 return armour;
55 }
56 }
57 // Keine Ruestung vom gleichen Typ gefunden, also 0 zurueckgeben
58 return 0;
59}
60
61// liefert 1 zurueck, wenn der Spieler die ruestung anziehen darf, 0 sonst.
62protected int _check_wear_restrictions(int silent, int all) {
63 mixed type,res;
64 object *armours;
65
66 type = QueryProp(P_ARMOUR_TYPE);
67
68 // Das DoWear() der Kleidung prueft auf genuegend freie Haende,
69 // prueft aber den Fall nicht ab, ob man hier ein Schild hat, was laut Prop
70 // weniger als eine Hand belegt. Daher hier nachholen und korrigieren. Und
71 // direkt mal loggen, damit das gefixt wird.
72 if ( (type==AT_SHIELD) && QueryProp(P_NR_HANDS)<1 ) {
73 SetProp(P_NR_HANDS,1);
74 log_file("INVALID_SHIELD",
75 sprintf("Fixme: AT_SHIELD item without valid P_NR_HANDS: %O\n",
76 object_name()));
77 }
78
79 armours=(object*)PL->QueryProp(P_ARMOURS) - ({0});
80
81 // Von jedem Ruestungstyp ausser AT_MISC kann man immer nur ein
82 // Teil tragen
83 if ( (type!=AT_MISC) && (res=TestType(armours)) && objectp(res)) {
84 msg(break_string(sprintf(
85 "Du traegst bereits %s als Schutz der Sorte %s.",
86 res->name(WEN,1), type),78,
87 (all?(Name(WER)+": "):0)), all);
88 return(-1);
89 }
90
91 // Ruestungen vom Typ AT_ILLEGAL oder solche mit einem fuer ihren
92 // Ruestungstyp zu hohen Schutzwert koennen nicht angezogen werden
93 if ( (type==AT_ILLEGAL) || (QueryProp(P_AC)>VALID_ARMOUR_CLASS[type])) {
94 write("Ungueltiger Ruestungstyp, bitte Erzmagier verstaendigen.\n");
95 "/p/daemon/ruestungen"->RegisterArmour();
96 return(-2);
97 }
98
99 // Ruestungen, die ein oder mehrere Attribut veraendern und gegen
100 // das gesetzte Limit verstossen, haben keine Wirkung bezueglich der
101 // Attribute. Dies gibt aber nur ne Meldung aus, angezogen werden darf sie
102 // trotzdem.
103 if (mappingp(res=QueryProp(P_M_ATTR_MOD)) && PL->TestLimitViolation(res) ) {
104 write(break_string(sprintf(
105 "Irgendetwas an Deiner Ausruestung verhindert, dass Du Dich mit "
106 "%s so richtig wohl fuehlst.",name(WEM,1)),78,
107 (all?(Name(WER)+": "):0)));
108 }
109
110 // dann mal aus der Kleidung geerbte Pruefungen ausfuehren und Ergebnis
111 // liefern.
112 return ::_check_wear_restrictions(silent,all);
113}
114
115protected void _informwear(int silent, int all) {
116
117 // Ruestungen koennen Resistenzen beeinflussen
118 PL->AddResistanceModifier(QueryProp(P_RESISTANCE_STRENGTHS),
119 QueryProp(P_ARMOUR_TYPE));
120
121 // Ruestungen koennen Attribute aendern/blockieren. Also muessen diese
122 // nach dem Anziehen aktualisiert werden
123 PL->register_modifier(ME);
124 PL->UpdateAttributes();
125
126 // P_TOTAL_AC im Traeger updaten (fuer Query()s)
127 PL->QueryProp(P_TOTAL_AC);
128
129 // Alle Ruestungen werden im awmaster registriert, sobald sie von
130 // einem Spieler gezueckt werden
131 if (!logged && query_once_interactive(PL)) {
132 call_other("/secure/awmaster","RegisterArmour",ME);
133 logged=1;
134 }
135 // noch das aus der Kleidung rufen, damit die Anziehmeldungen auch kommen.
136 // ausserdem laeuft das Anstosses von InformWear() von dort.
137 ::_informwear(silent,all);
138}
139
140
141protected int _check_unwear_restrictions(object worn_by, int silent,
142 int all) {
143 // liefert >=0 zureck, wenn die Kleidung/Ruestung ausgezogen werden kann,
144 // <0 sonst.
145
146 // Schilde belegen (mindestens) eine Hand. Hngl. Wenn man diesen bloeden
147 // Check nicht machen muesste, koennte man sich die ganze Funktion sparen.
148 // Hmpfgrmpfl. Achja, raise_error(), weil das eigentlich ja nicht vorkommen
149 // sollte und gefixt werden soll. Das geht naemlich nur, wenn jemand diese
150 // Prop geaendert, waehrend der Spieler das Schild getragen hatte.
151 if ( (QueryProp(P_ARMOUR_TYPE)==AT_SHIELD) &&
152 QueryProp(P_NR_HANDS)<1 ) {
153 raise_error(sprintf("Fixme: AT_SHIELD beim Ausziehen ohne P_NR_HANDS: %O",
154 object_name()));
155 }
156
157 // Ausziehcheck der Kleidung machen
158 return ::_check_unwear_restrictions(worn_by,silent,all);
159}
160
161protected void _informunwear(object worn_by, int silent, int all) {
162 mixed res;
163 // Gesetzte Resistenzen loeschen
164 worn_by->RemoveResistanceModifier(res=QueryProp(P_ARMOUR_TYPE));
165
166 // Ruestungen koennen Attribute aendern/blockieren. Also muessen diese
167 // nach dem Ausziehen aktualisiert werden
168 worn_by->deregister_modifiers(ME);
169 worn_by->UpdateAttributes();
170
171 // P_TOTAL_AC im Traeger updaten
172 worn_by->QueryProp(P_TOTAL_AC);
173
174 // die geerbte Funktion aus der Kleindung gibt noch meldungen aus und ruft
175 // Informunwear().
176 ::_informunwear(worn_by,silent,all);
177}
178
179// Funktion, die das "trage"/"ziehe * an"-Kommando auswertet
180varargs int do_wear(string str, int silent) {
181 int all;
182
183 // Hat der Spieler "trage alles" eingegeben?
184 all=(str=="alles" || str=="alle ruestungen");
185
186 return(_do_wear(str,silent,all));
187}
188
189// Die Funktion, die das "ziehe * aus"-Kommando auswertet
190varargs int do_unwear(string str, int silent) {
191 int all;
192
193 all=(str=="alles" || str=="alle ruestungen");
194 return(_do_unwear(str,silent,all));
195}
196
197
198// Objekte, die die Beschaedigung einer Ruestung durch direktes Setzen von
199// P_DAMAGED durchfuehren, werden im awmaster geloggt
200static mixed _set_item_damaged(mixed arg) {
201 if (arg && !intp(arg))
202 {
203 return Query(P_DAMAGED, F_VALUE);
204 }
205
206 if (previous_object(1))
207 call_other("/secure/awmaster","RegisterDamager",
208 previous_object(1),QueryProp(P_DAMAGED),arg);
209
210 return Set(P_DAMAGED, arg, F_VALUE);
211}
212
213// Will man eine Ruestung beschaedigen oder reparieren, so macht man das
214// am besten ueber die Funktion Damage(argument). Positive Argumente
215// bedeuten eine Beschaedigung, negative eine Reparatur. Der Rueckgabewert
216// ist die wirklich durchgefuehrte Aenderung des Beschaedigungswertes
217int Damage(int new_dam) {
218 int ac,maximum,old_dam;
219 object w;
220
221 if (!new_dam || !intp(new_dam)) {
222 return 0;
223 }
224
225 if ( (ac=QueryProp(P_AC))<=0 && (new_dam>0) ) {
226 // Sonst wuerde Beschaedigung zur Reparatur fuehren
227 return 0;
228 }
229
230 // Min-AC und MAX_AC beachten
231 if ((ac-new_dam) < MIN_ARMOUR_CLASS) {
232 new_dam = ac-MIN_ARMOUR_CLASS;
233 }
234 else if ((ac-new_dam) >
235 (maximum=VALID_ARMOUR_CLASS[QueryProp(P_ARMOUR_TYPE)])) {
236 new_dam = ac-maximum;
237 }
238
239 // Nie mehr als 100% reparieren
240 if ( ((old_dam=QueryProp(P_DAMAGED))<-new_dam) && (new_dam<0) ) {
241 new_dam=-old_dam;
242 }
243
244 // Aenderungen an der Ruestungsklasse und dem Beschaedigungswert
245 // durchfuehren
246 SetProp(P_AC,(ac-new_dam));
247 // eigene Set-Methode umgehen
248 Set(P_DAMAGED,(old_dam+new_dam),F_VALUE);
249
250 // P_TOTAL_AC im Traeger updaten, wenn vorhanden
251 if (objectp(w=QueryProp(P_WORN)))
252 w->QueryProp(P_TOTAL_AC);
253
254 // Rueckgabewert: Durchgefuehrte Aenderung an P_DAMAGE
255 return new_dam;
256}
257
258public status IsArmour() {return 1;}
259public status IsClothing() {return 0;}
260