blob: 71841e57a5378a25e20c677b302a8206df8cd570 [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,
Arathornb6667492020-01-08 21:48:54 +01008 string|<int|string>* TextForEnemy, string|<int|string>* TextForOthers,
Zesstradee2e562018-02-28 23:51:56 +01009 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
Arathornb6667492020-01-08 21:48:54 +010025 TextForEnemy - Text, den der Feind erhalten soll.
Zesstracc3ff952018-03-05 22:04:49 +010026 String <text> oder
27 Array der Form ({<text>,<messagetype>})
28 (Siehe ReceiveMsg())
29
Arathornb6667492020-01-08 21:48:54 +010030 TextForOthers - Text, den andere im Raum erhalten sollen.
31 String <text> ode
Zesstracc3ff952018-03-05 22:04:49 +010032 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
Arathornb6667492020-01-08 21:48:54 +010040 aufgerufen werden soll.
Zesstracc3ff952018-03-05 22:04:49 +010041 (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
Arathornb6667492020-01-08 21:48:54 +010045 den Aufruf von Defend() enthalten.
46 Hierfuer muss <newskills.h> includiert werden.
Zesstraeb3f95e2018-12-14 02:00:50 +010047 Default ist ([SI_SPELL: ([SP_PHYSICAL_ATTACK: 0]),
Zesstra4b5561a2019-01-07 21:13:41 +010048 SI_MAGIC_TYPE: ({ MT_ANGRIFF }) ])
Zesstra18626972017-01-31 10:38:27 +010049
50BESCHREIBUNG
51------------
Zesstra18626972017-01-31 10:38:27 +010052
Zesstracc3ff952018-03-05 22:04:49 +010053 Ermoeglicht einfache Angriffs-Zaubersprueche fuer NPCs. Das Ausfuehren von
54 Spells verursacht bei dem NPC keine KP-Kosten.
Zesstra18626972017-01-31 10:38:27 +010055
Zesstracc3ff952018-03-05 22:04:49 +010056 Mit P_SPELLRATE wird die generelle Wahrscheinlichkeit der Ausfuehrung
57 solcher Spells im Heartbeat angegeben, mit 'rate' kann man die relative
58 Wahrscheinlichkeit der Spells untereinander steuern.
Zesstra18626972017-01-31 10:38:27 +010059
Zesstracc3ff952018-03-05 22:04:49 +010060 (*) Relative Haeufigkeit heisst, dass sich alle 'rate' der Spells
61 aufaddieren und ein einzelnes 'rate' dann in Relation zur Gesamtsumme
62 steht. D.h. drei Spells mit 80, 10, 10 (Summe 100) haben die selben
63 Aufruf-Wahrscheinlichkeiten wie drei Spells mit 120, 15, 15 oder drei
64 Spells mit 160, 20, 20.
Zesstra18626972017-01-31 10:38:27 +010065
Zesstracc3ff952018-03-05 22:04:49 +010066 Ein Spell wird immer in folgender Reihenfolge abgearbeitet:
67
68 1. Die Texte werden an die Beteiligten ausgegeben.
69 2. Es wird ggf. SpellDefend gerufen (wenn kein SP_PHYSICAL_ATTACK).
70 Abbruch bei Schutz.
71 3. Im Opfer wird Defend() mit den angegebenen Werten aufgerufen.
72 Abbruch bei Tod/Zerstoerung des Opfers.
73 4. Eine Funktion, so definiert, wird ausgefuehrt.
Zesstra18626972017-01-31 10:38:27 +010074
75BEMERKUNGEN
76-----------
Zesstra18626972017-01-31 10:38:27 +010077
Zesstracc3ff952018-03-05 22:04:49 +010078 TextForOthers wird vor der Ausgabe der Meldung durch replace_personal()
79 geschickt, d.h. es koennen Platzhalter wie @WER1, @WEMQP1 und aehnliche
80 verwendet werden (siehe auch die Manpage von replace_personal()).
81 Da Ersetzungen nur fuer das Gegnerobjekt beruecksichtigt werden, koennen
82 nur Platzhalter mit Endziffer 1 verwendet werden. Die Ersetzungen werden
83 so gesteuert, dass die eingefuegten Namen nach Satzanfaengen automatisch
84 gross geschrieben werden.
85 Frueher wurden statt replace_personal() die Platzhalter @WER, @WESSEN,
86 @WEM, @WEN verwendet. Diese funktionieren weiterhin, sollten aber nicht
87 mehr in neuem Code benutzt werden.
Zesstra18626972017-01-31 10:38:27 +010088
Zesstracc3ff952018-03-05 22:04:49 +010089 In der von AddSpell gerufenen Methode "func" koennen speziellere
90 Sachen mit dem aktuellen Feind angestellt werden. Die Methode
91 muss im selben Objekt definiert sein, sofern der Funktionsname und
92 keine Closure uebergeben wird.
Zesstra18626972017-01-31 10:38:27 +010093
Zesstraeb3f95e2018-12-14 02:00:50 +010094 Das Mapping <sinfo> beschreibt den Spell fuer das im Gegner aufgerufene
95 SpellDefend() und Defend(). Es muss ein SI_SPELL fuer das Defend() im
96 Gegner enthalten. Etwaige SI_SKILLDAMAGE, SI_SKILLDAMAGE_TYPE, und
97 SI_CLOSURE werden im Mapping durch die Argumente <damage>, <dam_type> und
98 <func> ueberschrieben.
99 Es wird empfohlen, SI_MAGIC_TYPE zu nutzen, denn dann werden etwaige
100 magische Resistenzen des Ziels beruecksichtigt.
Zesstra18626972017-01-31 10:38:27 +0100101
Zesstraeb3f95e2018-12-14 02:00:50 +0100102 Frueher war das Argument <sinfo> nur das Mapping, was an Defend() uebergeben
103 wird unter in Skillinfomapping unter dem Key SI_SPELL liegt. Wenn <sinfo>
104 kein SI_SPELL enthaelt, wird aus Gruenden der Kompatibilitaet ein
105 Skillinfomapping konstruiert, welches das hier uebergebene <sinfo> unterhalb
106 des Schluessels SI_SPELL enthaelt: ([ SI_SPELL: sinfo])
107
108 Will man einen physischen Angriff ausloesen, MUSS in sinfo ein Mapping sein
109 und unter SI_SPELL ein Mapping mit dem Key SP_PHYSICAL_ATTACK (Wert != 0)
110 sein.
111 Bei Uebergeben einer 0 oder Weglassen von <sinfo> wird an Defend der Default
112 ([SP_PHYSICAL_ATTACK: 0]) (da es Spells sind) uebergeben.
113
114 Wenn damage < 0 oder rate <= 0, wird der Spell NICHT eingetragen, sondern
115 die Funktion bricht mit Rueckgabe von 0 ab. Ist damage==0, muss eine <func>
116 angegeben werden.
Zesstra18626972017-01-31 10:38:27 +0100117
118BEISPIELE
119---------
Zesstracc3ff952018-03-05 22:04:49 +0100120code-block::
Zesstra18626972017-01-31 10:38:27 +0100121
Zesstracc3ff952018-03-05 22:04:49 +0100122 // #1 Einfacher NPC mit drei Spells, Gesamtrate = 100, also sind die
123 // Raten direkt als Prozent Aufrufwahrscheinlichkeit lesbar.
124 AddSpell(80, 400,
125 "Der Hexer greift Dich mit einem kleinen Feuerball an.\n",
126 "Der Hexer greift @WEN mit einem kleinen Feuerball an.\n",
Zesstra18626972017-01-31 10:38:27 +0100127 ({DT_FIRE, DT_MAGIC}));
Zesstracc3ff952018-03-05 22:04:49 +0100128 AddSpell(10, 800,
129 "Der Hexer greift Dich mit einem riesigen Feuerball an.\n",
Zesstra18626972017-01-31 10:38:27 +0100130 "Der Hexer greift @WEN mit einem riesigen Feuerball an.\n",
Zesstracc3ff952018-03-05 22:04:49 +0100131 ({DT_FIRE, DT_MAGIC}));
132 AddSpell(8, 100,
133 "Der Hexer piekst Dir in die Augen!",
134 "Der Hexer piekst @WEM in die Augen!", ({DT_PIERCE}),
135 "augen_stechen");
Zesstraeb3f95e2018-12-14 02:00:50 +0100136 AddSpell(2, 5, 0, 0, 0, "salto_mortalis");
Zesstra18626972017-01-31 10:38:27 +0100137
Zesstracc3ff952018-03-05 22:04:49 +0100138 (Kleiner Feuerball mit 80% Wahrscheinlichkeit, riesiger mit 10%,
139 "augen_stechen" mit 8%, "salto_mortalis" mit 2%)
Zesstra18626972017-01-31 10:38:27 +0100140
Zesstracc3ff952018-03-05 22:04:49 +0100141code-block::
142
143 // Die Funktion "augen_stechen" kann dann so aussehen:
144 void augen_stechen(object enemy, int damage, mixed dam_types )
145 {
146 if (damage>10 && !enemy->QueryProp(P_BLIND))
147 {
148 enemy->SetProp(P_BLIND, 1);
149 if(enemy->QueryProp(P_BLIND))
150 tell_object(enemy, "Du bist nun blind!\n");
Zesstra18626972017-01-31 10:38:27 +0100151 }
Zesstracc3ff952018-03-05 22:04:49 +0100152 }
Zesstra18626972017-01-31 10:38:27 +0100153
Zesstracc3ff952018-03-05 22:04:49 +0100154code-block::
Zesstra18626972017-01-31 10:38:27 +0100155
Zesstracc3ff952018-03-05 22:04:49 +0100156 // Zur Funktion "salto_mortalis" gibt es keine Meldungen, dennoch
157 // wird Defend mit: enemy->Defend(5, ({DT_MAGIC}), 1, this_object())
158 // gerufen!
159 void salto_mortalis(object enemy, int damage, mixed dam_types )
160 {
161 // dem geneigten Leser ueberlassen, den Gegner zu toeten
162 }
Zesstra18626972017-01-31 10:38:27 +0100163
Zesstracc3ff952018-03-05 22:04:49 +0100164 // #2 Physische Angriffe: die Ruestungen sollen beruecksichtigt werden!
165 // SP_PHYSICAL_ATTACK muss in einem Mapping auf 1 gesetzt werden,
166 // damit Ruestungen physisch wirken (ansonsten werden nur ihre
167 // DefendFuncs() ausgewertet). Es muss auch eine physische Schadensart
168 // enthalten sein!
169 // SpellDefend() wird bei diesem Flag nicht mehr am Gegner gerufen.
Zesstra18626972017-01-31 10:38:27 +0100170
Zesstracc3ff952018-03-05 22:04:49 +0100171 AddSpell(100, 200+random(200),
172 "Die kleine Ratte beisst Dich!\n",
173 "@WER wird von einer kleinen Ratte gebissen!\n",
Zesstraeb3f95e2018-12-14 02:00:50 +0100174 ({DT_PIERCE, DT_POISON}), 0,
175 ([ SI_SPELL: ([SP_PHYSICAL_ATTACK:1]) ]) );
Zesstra18626972017-01-31 10:38:27 +0100176
Zesstracc3ff952018-03-05 22:04:49 +0100177 // #3 Selektive physische Angriffe (siehe auch man Defend_bsp):
178 // Will man erreichen, dass einige Ruestungen wirken, andere aber
179 // nicht oder nur teilweise, kann man das ueber die Spellparameter
180 // ausfuehrlich steuern:
Zesstra18626972017-01-31 10:38:27 +0100181
Zesstracc3ff952018-03-05 22:04:49 +0100182 // erstmal fuer alle Ruestungsarten einen Schutz von 0% einstellen:
183 mapping armours = map_indices(VALID_ARMOUR_CLASS, #'!);
184 armours[AT_TROUSERS] = 120; // 120% Schutz durch Hosen
185 armours[AT_BOOT] = 30; // 30% Schutz durch Stiefel
186
187 AddSpell(20,200+random(200),
188 "Die kleine Ratte beisst Dir blitzschnell in die Wade!\n",
189 "@WER wird von einer kleinen Ratte in die Wade gebissen!\n",
Zesstraeb3f95e2018-12-14 02:00:50 +0100190 ({DT_PIERCE, DT_POISON}), 0,
191 ([ SI_SPELL: ([SP_PHYSICAL_ATTACK:1, SP_NO_ACTIVE_DEFENSE:1,
192 SP_REDUCE_ARMOUR: armours])
193 ]) );
Zesstracc3ff952018-03-05 22:04:49 +0100194
195 // SP_NO_ACTIVE_DEFENSE = 1 schaltet aktive Abwehr (Karate/Klerus) ab
196 // SP_REDUCE_ARMOUR enthaelt eine Liste von Ruestungstypen mit ihren
197 // neuen Wirkungsgraden in Prozent. Nicht enthaltene Ruestungen haben
198 // weiterhin 100% Schutzwirkung.
Zesstra18626972017-01-31 10:38:27 +0100199
200SIEHE AUCH
201----------
Zesstra18626972017-01-31 10:38:27 +0100202
Zesstracc3ff952018-03-05 22:04:49 +0100203 Sonstiges: :doc:`SpellAttack`, :doc:`SpellDefend`, :doc:`Defend`,
204 :doc:`QueryDefend`, :doc:`SelectEnemy`, :doc:`ReceiveMsg`,
205 :doc:`../sefun/replace_personal`
206
207 Properties: :doc:`../props/P_DISABLE_ATTACK`, :doc:`../props/P_SPELLRATE`, :doc:`../props/P_AGGRESSIVE`
208
Zesstra18626972017-01-31 10:38:27 +0100209
Zesstradee2e562018-02-28 23:51:56 +0100210Letzte Aenderung: 15.02.2018, Bugfix