Funktion zum Normieren der Argumente von Defend
Defend bekommt aus historischem Code haeufig Argumente
uebergeben, die nicht der aktuellen Konvention entsprechen.
Damit nicht jeder Magier selber ueberlegen muss, wie die Argumente
zu normieren sind und den Code dafuer formulieren muss, stellt
das Living intern jetzt eine Funktion dafuer zur Verfuegung.
Damit wird dann auch immer gleich normiert.
Change-Id: I678b7656d7cea23e26ee2bb4897fece5c30b3ba8
diff --git a/doc/sphinx/lfun/normalize_defend_args.rst b/doc/sphinx/lfun/normalize_defend_args.rst
new file mode 100644
index 0000000..efd6141
--- /dev/null
+++ b/doc/sphinx/lfun/normalize_defend_args.rst
@@ -0,0 +1,82 @@
+normalize_defend_args()
+=======================
+
+FUNKTION
+--------
+
+ protected nomask void normalize_defend_args(int dam,
+ string|string* dam_types, int|mapping si_spell, object enemy)
+
+
+DEFINIERT IN
+------------
+
+ /std/living/combat.c
+
+ARGUMENTE
+---------
+
+ Die Argumente sind die Argumente, welche Defend() uebergeben bekommt (siehe
+ dort!)
+
+BESCHREIBUNG
+------------
+
+ Defend bekommt aus historischem Code haeufig Argumente uebergeben, die nicht
+ der aktuellen Konvention entsprechen (z.B. si_spell als 0 oder 1 statt eines
+ Mappings). Damit nun nicht jedes Objekt seine eigene Anpassung vornehmen
+ muss und dabei evtl. noch etwas vergessen wird, kann man mit dieser Funktion
+ die Argumente genauso "normieren", wie es in der Standardlib in Defend()
+ auch gemacht wuerde.
+
+ Dieses wird ganz dringend empfohlen statt diese Normierung selber
+ vorzunehmen. Und sollte es hier Aenderungen geben, bekommt man diese
+ automatisch mit.
+
+ Nach dem Aufruf dieser Funktion (Argumente als Referenz uebergeben!) liegen
+ die Argumente dann wie folgt vor:
+
+ dam
+ ein Integer (unveraendert)
+ dam_types
+ ein Array von Schadenstypen
+ si_spell
+ ein Mapping - wenn es neu angelegt wurde, enthaelt es die Eintraege
+ SP_PHYSICAL_ATTACK, SP_SHOW_DAMAGE, SP_REDUCE_ARMOUR und EINFO_DEFEND.
+ SP_PHYSICAL_ATTACK und SP_SHOW_DAMAGE sind 1, wenn si_spell 0 wahr, sonst
+ 1.
+ enemy
+ ist das Objekt des Gegners oder this_player()
+
+ Alternativ zum Ueberschreiben von Defend() und Nutzung dieser Funktion ist
+ haeufig auch InternalModifyDefend() gut geeignet. Dort muss *keine* eigene
+ Normierung der uebergebenen Argumente mehr vorgenommen werden!
+
+
+BEISPIELE
+---------
+
+.. code-block:: pike
+
+ // Ein eigenes Defend soll Dinge tun, bevor das geerbte Defend() gerufen
+ // wird. Um den Code zu vereinfachen, sollen die Typen der Argumente aber
+ // schon sicher in einem "normierten Zustand" sein.
+ public int Defend(int dam, string|string* dam_types, int|mapping spell,
+ object enemy)
+ {
+ // Uebergabe per Referenz noetig!
+ normalize_defend_args(&dam, &dam_type, &spell, &enemy);
+ if (member(dam_types, DT_FIRE) > -1
+ && si_spell[SP_NAME] == "Drachenfeuer")
+ dam *= 2; // Schaden verdoppeln
+ return ::Defend(dam, dam_types, si_spell, enemy);
+ }
+
+
+SIEHE AUCH
+----------
+
+ Verwandt:
+ :doc:`InternalModifyDefend`, :doc:`Defend`, :doc:`DefendInfo`
+
+16.01.2019 Zesstra
diff --git a/std/living/combat.c b/std/living/combat.c
index 880f3f6..d14bedc 100644
--- a/std/living/combat.c
+++ b/std/living/combat.c
@@ -959,6 +959,43 @@
return;
}
+protected nomask void normalize_defend_args(int dam, string|string* dam_type,
+ int|mapping spell, object enemy)
+{
+ // this_player(), wenn kein enemy bekannt...
+ enemy ||= this_player();
+
+ // Schadenstyp ueberpruefen
+ if ( !pointerp(dam_type) )
+ dam_type = ({ dam_type });
+
+ // Und das Spellmapping pruefen, erzeugen, ergaenzen etc.
+ if ( intp(spell) )
+ spell = ([ SP_PHYSICAL_ATTACK : !spell,
+ SP_SHOW_DAMAGE : !spell,
+ SP_REDUCE_ARMOUR : ([ ]),
+ EINFO_DEFEND : ([ORIGINAL_DAM:dam,
+ ORIGINAL_DAMTYPE:dam_type ])
+ ]);
+ else if ( mappingp(spell) )
+ {
+ // testen ob eine erweiterte defendinfo vorhanden ist
+ if(!member(spell,EINFO_DEFEND))
+ {
+ // wenn nicht, koennen wir an den fehlenden Infos wenig machen, aber
+ // zumindest ergaenzen wir es und schreiben die (hier) initialen dam und
+ // dam_type rein.
+ spell[EINFO_DEFEND] = ([ORIGINAL_DAM:dam,
+ ORIGINAL_DAMTYPE:dam_type]);
+ }
+ if ( !mappingp(spell[SP_REDUCE_ARMOUR]) )
+ spell[SP_REDUCE_ARMOUR] = ([]);
+ }
+ else // Illegaler spell-Parameter
+ raise_error(sprintf("Ungueltiger Typ des spell-Arguments: %d\n",
+ get_type_info(spell,0)));
+}
+
public int Defend(int dam, string|string* dam_type, int|mapping spell, object enemy)
{
int i,k;
@@ -966,42 +1003,17 @@
object *armours,tmp;
mixed hookData;
mixed hookRes;
-
+
// string what, how;
string enname, myname;
- // this_player(), wenn kein enemy bekannt...
- enemy ||= this_player();
+ normalize_defend_args(&dam, &dam_type, &spell, &enemy);
+
// Testen, ob dieses Lebewesen ueberhaupt angegriffen werden darf
if ( !this_object() || !enemy || QueryProp(P_NO_ATTACK)
|| ( query_once_interactive(enemy) && ! interactive(enemy) ) )
return 0;
- if ( intp(spell) )
- spell = ([ SP_PHYSICAL_ATTACK : !spell,
- SP_SHOW_DAMAGE : !spell,
- SP_REDUCE_ARMOUR : ([ ]) ]);
- else if ( !mappingp(spell) ) // Illegaler spell-Parameter
- return 0;
-
- // testen ob eine erweiterte defendinfo vorhanden ist
- if(!member(spell,EINFO_DEFEND))
- {
- //spell+=([EINFO_DEFEND:([])]); // ggf hinzufuegen
- // use a temporary mapping to avoid recursive
- // val[x][y] = deep_copy(val);
- mapping tmpdefend = ([
- ORIGINAL_AINFO:deep_copy(spell),
- ORIGINAL_DAM:dam,
- ORIGINAL_DAMTYPE:dam_type,
- ]);
- spell[EINFO_DEFEND]=tmpdefend;
- }
-
- // Schadenstyp ueberpruefen
- if ( !pointerp(dam_type) )
- dam_type = ({ dam_type });
-
spell[EINFO_DEFEND][CURRENT_DAMTYPE]=dam_type;
spell[EINFO_DEFEND][CURRENT_DAM]=dam;
@@ -1179,9 +1191,6 @@
}
} // Ende Hook-Behandlung
- if ( !member(spell,SP_REDUCE_ARMOUR) || !mappingp(spell[SP_REDUCE_ARMOUR]) )
- spell[SP_REDUCE_ARMOUR] = ([]);
-
// Es gibt auch Parierwaffen,
if ( objectp(tmp=QueryProp(P_PARRY_WEAPON)) )
{