blob: bb9fd15c4be8137d0cfd30949ec7954af1252390 [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001AddSpell()
Zesstra953f9972017-02-18 15:37:36 +01002**********
MG Mud User88f12472016-06-24 23:31:02 +02003
MG Mud User88f12472016-06-24 23:31:02 +02004
Zesstra953f9972017-02-18 15:37:36 +01005FUNKTION
6========
MG Mud User88f12472016-06-24 23:31:02 +02007
Zesstrabfab6ac2018-08-29 22:36:57 +02008 varargs int AddSpell(int rate, int damage,
Arathornb6667492020-01-08 21:48:54 +01009 string|<int|string>* TextForEnemy, string|<int|string>*
Zesstrabfab6ac2018-08-29 22:36:57 +020010 TextForOthers, string|string* dam_type, string|closure func,
11 int|mapping spellarg)
MG Mud User88f12472016-06-24 23:31:02 +020012
MG Mud User88f12472016-06-24 23:31:02 +020013
Zesstra953f9972017-02-18 15:37:36 +010014DEFINIERT IN
15============
MG Mud User88f12472016-06-24 23:31:02 +020016
Zesstra953f9972017-02-18 15:37:36 +010017 /std/npc/combat.c
MG Mud User88f12472016-06-24 23:31:02 +020018
MG Mud User88f12472016-06-24 23:31:02 +020019
Zesstra953f9972017-02-18 15:37:36 +010020ARGUMENTE
21=========
MG Mud User88f12472016-06-24 23:31:02 +020022
Zesstra953f9972017-02-18 15:37:36 +010023 rate - Relative Haeufigkeit der Anwendung (*),
Zesstrabfab6ac2018-08-29 22:36:57 +020024 muss >= 0 sein
25
Zesstra953f9972017-02-18 15:37:36 +010026 damage - Der Schadenswert fuer Defend(),
Zesstrabfab6ac2018-08-29 22:36:57 +020027 muss > 0 sein
28
Arathornb6667492020-01-08 21:48:54 +010029 TextForEnemy - Text, den der Feind erhalten soll.
Zesstrabfab6ac2018-08-29 22:36:57 +020030 String <text> oder Array der Form ({<text>,<messagetype>})
31 (Siehe ReceiveMsg())
32
Arathornb6667492020-01-08 21:48:54 +010033 TextForOthers - Text, den andere im Raum erhalten sollen.
34 String <text> ode Array der Form ({<text>,<messagetype>}) (Siehe
35 ReceiveMsg())
Zesstrabfab6ac2018-08-29 22:36:57 +020036
Zesstra953f9972017-02-18 15:37:36 +010037 dam_type - Schadenstyp(en) fuer Defend(),
Zesstrabfab6ac2018-08-29 22:36:57 +020038 (Default: ({DT_MAGIC}) fuer Magische und ({DT_BLUDGEON}) fuer
39 physikalische Angriffe)
40
Zesstra953f9972017-02-18 15:37:36 +010041 func - Funktionsname oder Closure, die nach Anwendung
Arathornb6667492020-01-08 21:48:54 +010042 aufgerufen werden soll. (Optional, bekommt als Argumente object
Zesstrabfab6ac2018-08-29 22:36:57 +020043 enemy, int real_damage, string* dam_type)
44
Zesstra077cbc62019-01-07 21:16:39 +010045 sinfo - Skillinfomapping, muss SI_SPELL mit den SP_* fuer
Arathornb6667492020-01-08 21:48:54 +010046 den Aufruf von Defend() enthalten. Hierfuer muss <newskills.h>
47 includiert werden. Default ist ([SI_SPELL: ([SP_PHYSICAL_ATTACK:
48 0]), SI_MAGIC_TYPE: ({ MT_ANGRIFF }) ])
MG Mud User88f12472016-06-24 23:31:02 +020049
MG Mud User88f12472016-06-24 23:31:02 +020050
Zesstra953f9972017-02-18 15:37:36 +010051BESCHREIBUNG
52============
MG Mud User88f12472016-06-24 23:31:02 +020053
Zesstrabfab6ac2018-08-29 22:36:57 +020054 Ermoeglicht einfache Angriffs-Zaubersprueche fuer NPCs. Das
55 Ausfuehren von Spells verursacht bei dem NPC keine KP-Kosten.
MG Mud User88f12472016-06-24 23:31:02 +020056
Zesstrabfab6ac2018-08-29 22:36:57 +020057 Mit P_SPELLRATE wird die generelle Wahrscheinlichkeit der
58 Ausfuehrung solcher Spells im Heartbeat angegeben, mit 'rate' kann
59 man die relative Wahrscheinlichkeit der Spells untereinander
60 steuern.
MG Mud User88f12472016-06-24 23:31:02 +020061
Zesstra953f9972017-02-18 15:37:36 +010062 (*) Relative Haeufigkeit heisst, dass sich alle 'rate' der Spells
Zesstrabfab6ac2018-08-29 22:36:57 +020063 aufaddieren und ein einzelnes 'rate' dann in Relation zur
64 Gesamtsumme steht. D.h. drei Spells mit 80, 10, 10 (Summe 100)
65 haben die selben Aufruf-Wahrscheinlichkeiten wie drei Spells mit
66 120, 15, 15 oder drei Spells mit 160, 20, 20.
MG Mud User88f12472016-06-24 23:31:02 +020067
Zesstra953f9972017-02-18 15:37:36 +010068 Ein Spell wird immer in folgender Reihenfolge abgearbeitet:
Zesstrabfab6ac2018-08-29 22:36:57 +020069
70 1. Die Texte werden an die Beteiligten ausgegeben.
71
Zesstrae959e722025-07-09 22:11:16 +020072 2. Es wird ggf. SpellDefend gerufen (wenn kein SP_PHYSICAL_ATTACK).
73 Abbruch bei Schutz.
Zesstrabfab6ac2018-08-29 22:36:57 +020074
75 3. Im Opfer wird Defend() mit den angegebenen Werten aufgerufen.
76 Abbruch bei Tod/Zerstoerung des Opfers.
77
78 4. Eine Funktion, so definiert, wird ausgefuehrt.
MG Mud User88f12472016-06-24 23:31:02 +020079
MG Mud User88f12472016-06-24 23:31:02 +020080
Zesstra953f9972017-02-18 15:37:36 +010081BEMERKUNGEN
82===========
MG Mud User88f12472016-06-24 23:31:02 +020083
Zesstrabfab6ac2018-08-29 22:36:57 +020084 TextForOthers wird vor der Ausgabe der Meldung durch
85 replace_personal() geschickt, d.h. es koennen Platzhalter wie
86 @WER1, @WEMQP1 und aehnliche verwendet werden (siehe auch die
87 Manpage von replace_personal()). Da Ersetzungen nur fuer das
88 Gegnerobjekt beruecksichtigt werden, koennen nur Platzhalter mit
89 Endziffer 1 verwendet werden. Die Ersetzungen werden so gesteuert,
90 dass die eingefuegten Namen nach Satzanfaengen automatisch gross
91 geschrieben werden. Frueher wurden statt replace_personal() die
92 Platzhalter @WER, @WESSEN, @WEM, @WEN verwendet. Diese
93 funktionieren weiterhin, sollten aber nicht mehr in neuem Code
94 benutzt werden.
MG Mud User88f12472016-06-24 23:31:02 +020095
Zesstra953f9972017-02-18 15:37:36 +010096 In der von AddSpell gerufenen Methode "func" koennen speziellere
Zesstrabfab6ac2018-08-29 22:36:57 +020097 Sachen mit dem aktuellen Feind angestellt werden. Die Methode muss
98 im selben Objekt definiert sein, sofern der Funktionsname und keine
99 Closure uebergeben wird.
MG Mud User88f12472016-06-24 23:31:02 +0200100
Zesstra077cbc62019-01-07 21:16:39 +0100101 Das Mapping <sinfo> beschreibt den Spell fuer das im Gegner
102 aufgerufene SpellDefend() und Defend(). Es muss ein SI_SPELL fuer
103 das Defend() im Gegner enthalten. Etwaige SI_SKILLDAMAGE,
104 SI_SKILLDAMAGE_TYPE, und SI_CLOSURE werden im Mapping durch die
105 Argumente <damage>, <dam_type> und <func> ueberschrieben. Es wird
106 empfohlen, SI_MAGIC_TYPE zu nutzen, denn dann werden etwaige
107 magische Resistenzen des Ziels beruecksichtigt.
MG Mud User88f12472016-06-24 23:31:02 +0200108
Zesstra077cbc62019-01-07 21:16:39 +0100109 Frueher war das Argument <sinfo> nur das Mapping, was an Defend()
110 uebergeben wird unter in Skillinfomapping unter dem Key SI_SPELL
111 liegt. Wenn <sinfo> kein SI_SPELL enthaelt, wird aus Gruenden der
112 Kompatibilitaet ein Skillinfomapping konstruiert, welches das hier
113 uebergebene <sinfo> unterhalb des Schluessels SI_SPELL enthaelt: ([
114 SI_SPELL: sinfo])
115
116 Will man einen physischen Angriff ausloesen, MUSS in sinfo ein
117 Mapping sein und unter SI_SPELL ein Mapping mit dem Key
118 SP_PHYSICAL_ATTACK (Wert != 0) sein. Bei Uebergeben einer 0 oder
119 Weglassen von <sinfo> wird an Defend der Default
120 ([SP_PHYSICAL_ATTACK: 0]) (da es Spells sind) uebergeben.
121
122 Wenn damage < 0 oder rate <= 0, wird der Spell NICHT eingetragen,
123 sondern die Funktion bricht mit Rueckgabe von 0 ab. Ist damage==0,
124 muss eine <func> angegeben werden.
Zesstra953f9972017-02-18 15:37:36 +0100125
126
127BEISPIELE
128=========
129
Zesstrabfab6ac2018-08-29 22:36:57 +0200130code-block:
131
Zesstra953f9972017-02-18 15:37:36 +0100132 // #1 Einfacher NPC mit drei Spells, Gesamtrate = 100, also sind die
133 // Raten direkt als Prozent Aufrufwahrscheinlichkeit lesbar.
134 AddSpell(80, 400,
135 "Der Hexer greift Dich mit einem kleinen Feuerball an.\n",
136 "Der Hexer greift @WEN mit einem kleinen Feuerball an.\n",
Zesstrabfab6ac2018-08-29 22:36:57 +0200137 ({DT_FIRE, DT_MAGIC}));
Zesstra953f9972017-02-18 15:37:36 +0100138 AddSpell(10, 800,
139 "Der Hexer greift Dich mit einem riesigen Feuerball an.\n",
Zesstrabfab6ac2018-08-29 22:36:57 +0200140 "Der Hexer greift @WEN mit einem riesigen Feuerball an.\n",
Zesstra953f9972017-02-18 15:37:36 +0100141 ({DT_FIRE, DT_MAGIC}));
142 AddSpell(8, 100,
143 "Der Hexer piekst Dir in die Augen!",
144 "Der Hexer piekst @WEM in die Augen!", ({DT_PIERCE}),
145 "augen_stechen");
Zesstra077cbc62019-01-07 21:16:39 +0100146 AddSpell(2, 5, 0, 0, 0, "salto_mortalis");
Zesstra953f9972017-02-18 15:37:36 +0100147
148 (Kleiner Feuerball mit 80% Wahrscheinlichkeit, riesiger mit 10%,
Zesstrabfab6ac2018-08-29 22:36:57 +0200149 "augen_stechen" mit 8%, "salto_mortalis" mit 2%)
150
151code-block:
Zesstra953f9972017-02-18 15:37:36 +0100152
153 // Die Funktion "augen_stechen" kann dann so aussehen:
Zesstrabfab6ac2018-08-29 22:36:57 +0200154 void augen_stechen(object enemy, int damage, mixed dam_types )
155 {
156 if (damage>10 && !enemy->QueryProp(P_BLIND))
157 {
Zesstra953f9972017-02-18 15:37:36 +0100158 enemy->SetProp(P_BLIND, 1);
159 if(enemy->QueryProp(P_BLIND))
160 tell_object(enemy, "Du bist nun blind!\n");
161 }
162 }
163
Zesstrabfab6ac2018-08-29 22:36:57 +0200164code-block:
165
Zesstra953f9972017-02-18 15:37:36 +0100166 // Zur Funktion "salto_mortalis" gibt es keine Meldungen, dennoch
167 // wird Defend mit: enemy->Defend(5, ({DT_MAGIC}), 1, this_object())
168 // gerufen!
Zesstrabfab6ac2018-08-29 22:36:57 +0200169 void salto_mortalis(object enemy, int damage, mixed dam_types )
170 {
Zesstra953f9972017-02-18 15:37:36 +0100171 // dem geneigten Leser ueberlassen, den Gegner zu toeten
172 }
173
174 // #2 Physische Angriffe: die Ruestungen sollen beruecksichtigt werden!
175 // SP_PHYSICAL_ATTACK muss in einem Mapping auf 1 gesetzt werden,
176 // damit Ruestungen physisch wirken (ansonsten werden nur ihre
177 // DefendFuncs() ausgewertet). Es muss auch eine physische Schadensart
178 // enthalten sein!
179 // SpellDefend() wird bei diesem Flag nicht mehr am Gegner gerufen.
Zesstrabfab6ac2018-08-29 22:36:57 +0200180
Zesstra953f9972017-02-18 15:37:36 +0100181 AddSpell(100, 200+random(200),
182 "Die kleine Ratte beisst Dich!\n",
183 "@WER wird von einer kleinen Ratte gebissen!\n",
Zesstra077cbc62019-01-07 21:16:39 +0100184 ({DT_PIERCE, DT_POISON}), 0,
185 ([ SI_SPELL: ([SP_PHYSICAL_ATTACK:1]) ]) );
Zesstra953f9972017-02-18 15:37:36 +0100186
187 // #3 Selektive physische Angriffe (siehe auch man Defend_bsp):
188 // Will man erreichen, dass einige Ruestungen wirken, andere aber
189 // nicht oder nur teilweise, kann man das ueber die Spellparameter
190 // ausfuehrlich steuern:
191
192 // erstmal fuer alle Ruestungsarten einen Schutz von 0% einstellen:
193 mapping armours = map_indices(VALID_ARMOUR_CLASS, #'!);
194 armours[AT_TROUSERS] = 120; // 120% Schutz durch Hosen
195 armours[AT_BOOT] = 30; // 30% Schutz durch Stiefel
196
197 AddSpell(20,200+random(200),
198 "Die kleine Ratte beisst Dir blitzschnell in die Wade!\n",
199 "@WER wird von einer kleinen Ratte in die Wade gebissen!\n",
Zesstra077cbc62019-01-07 21:16:39 +0100200 ({DT_PIERCE, DT_POISON}), 0,
201 ([ SI_SPELL: ([SP_PHYSICAL_ATTACK:1, SP_NO_ACTIVE_DEFENSE:1,
202 SP_REDUCE_ARMOUR: armours])
203 ]) );
Zesstra953f9972017-02-18 15:37:36 +0100204
205 // SP_NO_ACTIVE_DEFENSE = 1 schaltet aktive Abwehr (Karate/Klerus) ab
206 // SP_REDUCE_ARMOUR enthaelt eine Liste von Ruestungstypen mit ihren
207 // neuen Wirkungsgraden in Prozent. Nicht enthaltene Ruestungen haben
208 // weiterhin 100% Schutzwirkung.
209
210
211SIEHE AUCH
212==========
213
Zesstra6cadc1b2018-11-15 22:27:32 +0100214 Sonstiges: SpellAttack(), SpellDefend(), Defend(), QueryDefend(),
215 SelectEnemy(), ReceiveMsg(), replace_personal()
MG Mud User88f12472016-06-24 23:31:02 +0200216
Zesstra6cadc1b2018-11-15 22:27:32 +0100217 Properties: P_DISABLE_ATTACK, P_SPELLRATE, P_AGGRESSIVE
Zesstrabfab6ac2018-08-29 22:36:57 +0200218
219Letzte Aenderung: 15.02.2018, Bugfix