blob: 4a8041e5abdda606e13f175cfacea312bbeb19ce [file] [log] [blame]
Zesstra18626972017-01-31 10:38:27 +01001AddSpell()
2==========
3
4FUNKTION
5--------
Zesstra18626972017-01-31 10:38:27 +01006
Zesstradee2e562018-02-28 23:51:56 +01007 varargs int AddSpell(int rate, int damage,
8 string|<int|spell>* TextForEnemy, string|<int|string>* TextForOthers,
9 string|string* dam_type, string|closure func, int|mapping spellarg)
Zesstra18626972017-01-31 10:38:27 +010010
11DEFINIERT IN
12------------
Zesstra18626972017-01-31 10:38:27 +010013
Zesstracc3ff952018-03-05 22:04:49 +010014 /std/npc/combat.c
Zesstra18626972017-01-31 10:38:27 +010015
16ARGUMENTE
17---------
Zesstra18626972017-01-31 10:38:27 +010018
Zesstracc3ff952018-03-05 22:04:49 +010019 rate - Relative Haeufigkeit der Anwendung (*),
20 muss >= 0 sein
21
22 damage - Der Schadenswert fuer Defend(),
23 muss > 0 sein
24
25 TextForEnemy - Text, den der Feind erhalten soll
26 String <text> oder
27 Array der Form ({<text>,<messagetype>})
28 (Siehe ReceiveMsg())
29
30 TextForOthers - Text, den andere im Raum erhalten sollen
31 String <text> oder
32 Array der Form ({<text>,<messagetype>})
33 (Siehe ReceiveMsg())
34
35 dam_type - Schadenstyp(en) fuer Defend(),
36 (Default: ({DT_MAGIC}) fuer Magische und ({DT_BLUDGEON})
37 fuer physikalische Angriffe)
38
39 func - Funktionsname oder Closure, die nach Anwendung
40 aufgerufen werden soll
41 (Optional, bekommt als Argumente object enemy,
42 int real_damage, string* dam_type)
43
Zesstraeb3f95e2018-12-14 02:00:50 +010044 sinfo - Skillinfomapping, muss SI_SPELL mit den SP_* fuer
45 den Aufruf von Defend() enthalten
46 Default ist ([SI_SPELL: ([SP_PHYSICAL_ATTACK: 0]),
Zesstra4b5561a2019-01-07 21:13:41 +010047 SI_MAGIC_TYPE: ({ MT_ANGRIFF }) ])
Zesstra18626972017-01-31 10:38:27 +010048
49BESCHREIBUNG
50------------
Zesstra18626972017-01-31 10:38:27 +010051
Zesstracc3ff952018-03-05 22:04:49 +010052 Ermoeglicht einfache Angriffs-Zaubersprueche fuer NPCs. Das Ausfuehren von
53 Spells verursacht bei dem NPC keine KP-Kosten.
Zesstra18626972017-01-31 10:38:27 +010054
Zesstracc3ff952018-03-05 22:04:49 +010055 Mit P_SPELLRATE wird die generelle Wahrscheinlichkeit der Ausfuehrung
56 solcher Spells im Heartbeat angegeben, mit 'rate' kann man die relative
57 Wahrscheinlichkeit der Spells untereinander steuern.
Zesstra18626972017-01-31 10:38:27 +010058
Zesstracc3ff952018-03-05 22:04:49 +010059 (*) Relative Haeufigkeit heisst, dass sich alle 'rate' der Spells
60 aufaddieren und ein einzelnes 'rate' dann in Relation zur Gesamtsumme
61 steht. D.h. drei Spells mit 80, 10, 10 (Summe 100) haben die selben
62 Aufruf-Wahrscheinlichkeiten wie drei Spells mit 120, 15, 15 oder drei
63 Spells mit 160, 20, 20.
Zesstra18626972017-01-31 10:38:27 +010064
Zesstracc3ff952018-03-05 22:04:49 +010065 Ein Spell wird immer in folgender Reihenfolge abgearbeitet:
66
67 1. Die Texte werden an die Beteiligten ausgegeben.
68 2. Es wird ggf. SpellDefend gerufen (wenn kein SP_PHYSICAL_ATTACK).
69 Abbruch bei Schutz.
70 3. Im Opfer wird Defend() mit den angegebenen Werten aufgerufen.
71 Abbruch bei Tod/Zerstoerung des Opfers.
72 4. Eine Funktion, so definiert, wird ausgefuehrt.
Zesstra18626972017-01-31 10:38:27 +010073
74BEMERKUNGEN
75-----------
Zesstra18626972017-01-31 10:38:27 +010076
Zesstracc3ff952018-03-05 22:04:49 +010077 TextForOthers wird vor der Ausgabe der Meldung durch replace_personal()
78 geschickt, d.h. es koennen Platzhalter wie @WER1, @WEMQP1 und aehnliche
79 verwendet werden (siehe auch die Manpage von replace_personal()).
80 Da Ersetzungen nur fuer das Gegnerobjekt beruecksichtigt werden, koennen
81 nur Platzhalter mit Endziffer 1 verwendet werden. Die Ersetzungen werden
82 so gesteuert, dass die eingefuegten Namen nach Satzanfaengen automatisch
83 gross geschrieben werden.
84 Frueher wurden statt replace_personal() die Platzhalter @WER, @WESSEN,
85 @WEM, @WEN verwendet. Diese funktionieren weiterhin, sollten aber nicht
86 mehr in neuem Code benutzt werden.
Zesstra18626972017-01-31 10:38:27 +010087
Zesstracc3ff952018-03-05 22:04:49 +010088 In der von AddSpell gerufenen Methode "func" koennen speziellere
89 Sachen mit dem aktuellen Feind angestellt werden. Die Methode
90 muss im selben Objekt definiert sein, sofern der Funktionsname und
91 keine Closure uebergeben wird.
Zesstra18626972017-01-31 10:38:27 +010092
Zesstraeb3f95e2018-12-14 02:00:50 +010093 Das Mapping <sinfo> beschreibt den Spell fuer das im Gegner aufgerufene
94 SpellDefend() und Defend(). Es muss ein SI_SPELL fuer das Defend() im
95 Gegner enthalten. Etwaige SI_SKILLDAMAGE, SI_SKILLDAMAGE_TYPE, und
96 SI_CLOSURE werden im Mapping durch die Argumente <damage>, <dam_type> und
97 <func> ueberschrieben.
98 Es wird empfohlen, SI_MAGIC_TYPE zu nutzen, denn dann werden etwaige
99 magische Resistenzen des Ziels beruecksichtigt.
Zesstra18626972017-01-31 10:38:27 +0100100
Zesstraeb3f95e2018-12-14 02:00:50 +0100101 Frueher war das Argument <sinfo> nur das Mapping, was an Defend() uebergeben
102 wird unter in Skillinfomapping unter dem Key SI_SPELL liegt. Wenn <sinfo>
103 kein SI_SPELL enthaelt, wird aus Gruenden der Kompatibilitaet ein
104 Skillinfomapping konstruiert, welches das hier uebergebene <sinfo> unterhalb
105 des Schluessels SI_SPELL enthaelt: ([ SI_SPELL: sinfo])
106
107 Will man einen physischen Angriff ausloesen, MUSS in sinfo ein Mapping sein
108 und unter SI_SPELL ein Mapping mit dem Key SP_PHYSICAL_ATTACK (Wert != 0)
109 sein.
110 Bei Uebergeben einer 0 oder Weglassen von <sinfo> wird an Defend der Default
111 ([SP_PHYSICAL_ATTACK: 0]) (da es Spells sind) uebergeben.
112
113 Wenn damage < 0 oder rate <= 0, wird der Spell NICHT eingetragen, sondern
114 die Funktion bricht mit Rueckgabe von 0 ab. Ist damage==0, muss eine <func>
115 angegeben werden.
Zesstra18626972017-01-31 10:38:27 +0100116
117BEISPIELE
118---------
Zesstracc3ff952018-03-05 22:04:49 +0100119code-block::
Zesstra18626972017-01-31 10:38:27 +0100120
Zesstracc3ff952018-03-05 22:04:49 +0100121 // #1 Einfacher NPC mit drei Spells, Gesamtrate = 100, also sind die
122 // Raten direkt als Prozent Aufrufwahrscheinlichkeit lesbar.
123 AddSpell(80, 400,
124 "Der Hexer greift Dich mit einem kleinen Feuerball an.\n",
125 "Der Hexer greift @WEN mit einem kleinen Feuerball an.\n",
Zesstra18626972017-01-31 10:38:27 +0100126 ({DT_FIRE, DT_MAGIC}));
Zesstracc3ff952018-03-05 22:04:49 +0100127 AddSpell(10, 800,
128 "Der Hexer greift Dich mit einem riesigen Feuerball an.\n",
Zesstra18626972017-01-31 10:38:27 +0100129 "Der Hexer greift @WEN mit einem riesigen Feuerball an.\n",
Zesstracc3ff952018-03-05 22:04:49 +0100130 ({DT_FIRE, DT_MAGIC}));
131 AddSpell(8, 100,
132 "Der Hexer piekst Dir in die Augen!",
133 "Der Hexer piekst @WEM in die Augen!", ({DT_PIERCE}),
134 "augen_stechen");
Zesstraeb3f95e2018-12-14 02:00:50 +0100135 AddSpell(2, 5, 0, 0, 0, "salto_mortalis");
Zesstra18626972017-01-31 10:38:27 +0100136
Zesstracc3ff952018-03-05 22:04:49 +0100137 (Kleiner Feuerball mit 80% Wahrscheinlichkeit, riesiger mit 10%,
138 "augen_stechen" mit 8%, "salto_mortalis" mit 2%)
Zesstra18626972017-01-31 10:38:27 +0100139
Zesstracc3ff952018-03-05 22:04:49 +0100140code-block::
141
142 // Die Funktion "augen_stechen" kann dann so aussehen:
143 void augen_stechen(object enemy, int damage, mixed dam_types )
144 {
145 if (damage>10 && !enemy->QueryProp(P_BLIND))
146 {
147 enemy->SetProp(P_BLIND, 1);
148 if(enemy->QueryProp(P_BLIND))
149 tell_object(enemy, "Du bist nun blind!\n");
Zesstra18626972017-01-31 10:38:27 +0100150 }
Zesstracc3ff952018-03-05 22:04:49 +0100151 }
Zesstra18626972017-01-31 10:38:27 +0100152
Zesstracc3ff952018-03-05 22:04:49 +0100153code-block::
Zesstra18626972017-01-31 10:38:27 +0100154
Zesstracc3ff952018-03-05 22:04:49 +0100155 // Zur Funktion "salto_mortalis" gibt es keine Meldungen, dennoch
156 // wird Defend mit: enemy->Defend(5, ({DT_MAGIC}), 1, this_object())
157 // gerufen!
158 void salto_mortalis(object enemy, int damage, mixed dam_types )
159 {
160 // dem geneigten Leser ueberlassen, den Gegner zu toeten
161 }
Zesstra18626972017-01-31 10:38:27 +0100162
Zesstracc3ff952018-03-05 22:04:49 +0100163 // #2 Physische Angriffe: die Ruestungen sollen beruecksichtigt werden!
164 // SP_PHYSICAL_ATTACK muss in einem Mapping auf 1 gesetzt werden,
165 // damit Ruestungen physisch wirken (ansonsten werden nur ihre
166 // DefendFuncs() ausgewertet). Es muss auch eine physische Schadensart
167 // enthalten sein!
168 // SpellDefend() wird bei diesem Flag nicht mehr am Gegner gerufen.
Zesstra18626972017-01-31 10:38:27 +0100169
Zesstracc3ff952018-03-05 22:04:49 +0100170 AddSpell(100, 200+random(200),
171 "Die kleine Ratte beisst Dich!\n",
172 "@WER wird von einer kleinen Ratte gebissen!\n",
Zesstraeb3f95e2018-12-14 02:00:50 +0100173 ({DT_PIERCE, DT_POISON}), 0,
174 ([ SI_SPELL: ([SP_PHYSICAL_ATTACK:1]) ]) );
Zesstra18626972017-01-31 10:38:27 +0100175
Zesstracc3ff952018-03-05 22:04:49 +0100176 // #3 Selektive physische Angriffe (siehe auch man Defend_bsp):
177 // Will man erreichen, dass einige Ruestungen wirken, andere aber
178 // nicht oder nur teilweise, kann man das ueber die Spellparameter
179 // ausfuehrlich steuern:
Zesstra18626972017-01-31 10:38:27 +0100180
Zesstracc3ff952018-03-05 22:04:49 +0100181 // erstmal fuer alle Ruestungsarten einen Schutz von 0% einstellen:
182 mapping armours = map_indices(VALID_ARMOUR_CLASS, #'!);
183 armours[AT_TROUSERS] = 120; // 120% Schutz durch Hosen
184 armours[AT_BOOT] = 30; // 30% Schutz durch Stiefel
185
186 AddSpell(20,200+random(200),
187 "Die kleine Ratte beisst Dir blitzschnell in die Wade!\n",
188 "@WER wird von einer kleinen Ratte in die Wade gebissen!\n",
Zesstraeb3f95e2018-12-14 02:00:50 +0100189 ({DT_PIERCE, DT_POISON}), 0,
190 ([ SI_SPELL: ([SP_PHYSICAL_ATTACK:1, SP_NO_ACTIVE_DEFENSE:1,
191 SP_REDUCE_ARMOUR: armours])
192 ]) );
Zesstracc3ff952018-03-05 22:04:49 +0100193
194 // SP_NO_ACTIVE_DEFENSE = 1 schaltet aktive Abwehr (Karate/Klerus) ab
195 // SP_REDUCE_ARMOUR enthaelt eine Liste von Ruestungstypen mit ihren
196 // neuen Wirkungsgraden in Prozent. Nicht enthaltene Ruestungen haben
197 // weiterhin 100% Schutzwirkung.
Zesstra18626972017-01-31 10:38:27 +0100198
199SIEHE AUCH
200----------
Zesstra18626972017-01-31 10:38:27 +0100201
Zesstracc3ff952018-03-05 22:04:49 +0100202 Sonstiges: :doc:`SpellAttack`, :doc:`SpellDefend`, :doc:`Defend`,
203 :doc:`QueryDefend`, :doc:`SelectEnemy`, :doc:`ReceiveMsg`,
204 :doc:`../sefun/replace_personal`
205
206 Properties: :doc:`../props/P_DISABLE_ATTACK`, :doc:`../props/P_SPELLRATE`, :doc:`../props/P_AGGRESSIVE`
207
Zesstra18626972017-01-31 10:38:27 +0100208
Zesstradee2e562018-02-28 23:51:56 +0100209Letzte Aenderung: 15.02.2018, Bugfix