blob: 3b45872c12995c6e8953bd1aaa8295ad565a29cd [file] [log] [blame]
MG Mud User3c1f5a82016-06-25 09:57:34 +02001/* Gildenobjekt fuer Abenteurer - MorgenGrauen */
2/* Boing, 1993-1998 */
3/* Sprueche:
4 Lichtkugel herbeizaubern: licht
5 Magiepunkte 5, Stufe 4
6 Dauer: Level * 20 Sekunden
7 Identifizieren: identifiziere
8 Magiepunkte 10, Stufe 3
9 Monster einschaetzen: schaetz <name>
10 Magiepunkte 3, Stufe 10
11 Pfeilangriff: pfeil <name>
12 Schaden maximal 20, Magiepunkte 10, Stufe 11
13 Gegenstaende untersuchen: identifiziere <objekt>
14 Wenn P_INFO exisitiert, wird dies ausgegeben
15 Magiepunkte 10, stufe 8
16 Ausweichen: ausweichen
17 Geht nur im Kampf, genau einer Attacke wird ausgewichen.
18 Magiepunkte 10, Stufe 12
19 Kampfschrei: kampfschrei <opfer> bzw. kampfschrei meldung <meldung>
20 Der Kampfschrei wird ausgestossen und verlangsamt den Gegner.
21 Magiepunkte 30, stufe 13
22 Feuerball: feuerball <name>
23 Schaden maximal 40, Magiepunkte 20, Stufe 15
24 Schnelligkeit: schnell
25 Gibt fuer eine bestimmte Zeit zusaetzliche Angriffe
26 Magiepunkte 100, Stufe 17
27 Saeurestrahl: saeurestrahl <name>
28 Schaden maximal 60, Magiepunkte 25, Stufe 30
29*/
30
31#include <properties.h>
32#include <language.h>
33#include <attributes.h>
34#include <combat.h>
35#include <wizlevels.h>
36#include <new_skills.h>
37
38#define LICHTKUGEL "/gilden/files.abenteurer/lichtkugel"
39
40inherit "/std/spellbook";
41
42void create() {
43 ::create();
44 SetProp(P_GLOBAL_SKILLPROPS,
45 ([SI_SPELLFATIGUE:2, // 2 Sekunden kein neuer Spell
46 SI_SKILLLEARN:5, // 0.05% pro 2 A_INT
47 OFFSET(SI_SKILLLEARN):10 // plus 0.1% in jedem Fall
48 ]));
49
50 AddSpell("steinschlag",5,
51 ([SI_SKILLRESTR_LEARN:([P_LEVEL:1]),
52 SI_SKILLDAMAGE:40,
53 OFFSET(SI_SKILLDAMAGE):40,
54 SI_SKILLDAMAGE_TYPE: ({DT_BLUDGEON}),
55 SI_MAGIC_TYPE:({MT_ANGRIFF}),
56 SI_SPELL:([SP_NAME:"steinschlag"])]));
57
58 AddSpell("identifiziere",10,
59 ([SI_SKILLRESTR_LEARN:([P_LEVEL:3]),
60 SI_MAGIC_TYPE: ({ MT_HELLSICHT }),
61 SI_SPELL: ([P_NAME: "identifiziere"]),
62 ]) );
63 AddSpell("licht",5,
64 ([SI_SKILLRESTR_LEARN:([P_LEVEL:6]),
65 SI_SPELL: ([P_NAME: "licht"])
66 ]) );
67 AddSpell("schaetz",3,
68 ([SI_SKILLRESTR_LEARN:([P_LEVEL:8]),
69 SI_MAGIC_TYPE: ({ MT_HELLSICHT }),
70 SI_SPELL: ([SP_NAME: "schaetz"]),
71 ]));
72 AddSpell("pfeil",10,
73 ([SI_SKILLRESTR_LEARN:([P_LEVEL:10]),
74 // Um diesen Spruch lernen zu koennen muss
75 // der Level mindestens 11 sein
76 SI_SKILLDAMAGE:200,
77 // Schaden: Random(200) ...
78 SI_SKILLDAMAGE_TYPE:({DT_MAGIC}),
79 // Damage Type: Magic
80 SI_MAGIC_TYPE: ({ MT_ANGRIFF }),
81 SI_SPELL: ([ SP_NAME: "pfeil" ]),
Zesstra1c7da1d2019-10-24 23:01:15 +020082 // Boni für hintere Kampfreihen
MG Mud User3c1f5a82016-06-25 09:57:34 +020083 SI_SKILLDAMAGE_BY_ROW: ([2:110,3:50,4:10]),
84 OFFSET(SI_SKILLDAMAGE_BY_ROW): ([2:50,3:20,4:5])
85 ]));
86 AddSpell("ausweichen", 10,
87 ([SI_SKILLRESTR_LEARN:([P_LEVEL:13]),
88 SI_SPELL: ([P_NAME: "ausweichen"]),
89 ]));
90 AddSpell("kampfschrei", 30,
91 ([SI_SKILLRESTR_LEARN:([P_LEVEL:16]),
92 SI_MAGIC_TYPE: ({ MT_PSYCHO }),
93 SI_SPELL: ([SP_NAME: "kampfschrei"]),
94 ]));
95 AddSpell("feuerball",20,
96 ([SI_SKILLRESTR_LEARN:([P_LEVEL:18]),
97 SI_SKILLDAMAGE:300,
98 // Schaden: Random(300) ...
99 OFFSET(SI_SKILLDAMAGE):100,
100 // ... plus 100
101 SI_SKILLDAMAGE_TYPE:({DT_FIRE}),
102 // Damage Type: Fire
103 SI_MAGIC_TYPE: ({ MT_ANGRIFF }),
104 SI_SPELL: ([SP_NAME: "feuerball"]),
105 SI_SKILLDAMAGE_BY_ROW: ([2:80,3:150,4:80,5:20]),
106 OFFSET(SI_SKILLDAMAGE_BY_ROW): ([2:30,3:80,4:30,5:10])
107 ]));
108 AddSpell("schnell",100,
109 ([SI_SKILLRESTR_LEARN:([P_LEVEL:21]),
110 SI_SPELL: ([P_NAME: "schnell"]) ]));
111 AddSpell("saeurestrahl",25,
112 ([SI_SKILLRESTR_LEARN:([P_LEVEL:28]),
113 OFFSET(SI_SKILLLEARN):1,
114 FACTOR(SI_SKILLLEARN):20,
115 SI_SKILLDAMAGE:400,
116 // Schaden: Random(400) ...
117 OFFSET(SI_SKILLDAMAGE):200,
118 // ... plus 200
119 SI_SKILLDAMAGE_TYPE:({DT_ACID}),
120 // Damage Type: Saeure
121 SI_MAGIC_TYPE: ({ MT_ANGRIFF }),
122 SI_SPELL: ([SP_NAME: "saeurestrahl"]),
123 SI_SKILLDAMAGE_BY_ROW:([2:60,3:150,4:210,5:150,6:60]),
124 OFFSET(SI_SKILLDAMAGE_BY_ROW):([2:30,3:80,4:120,5:80,6:30])
125 ]));
126
127}
128
129int
130steinschlag(object caster, mapping sinfo) {
131 object victim;
Bugfixd8a984b2022-10-06 11:08:08 +0200132 string vnw, cn;
MG Mud User3c1f5a82016-06-25 09:57:34 +0200133 int suc;
134
135 victim=FindEnemyVictim(sinfo[SI_SKILLARG],caster,
136 "Ueber wem willst Du einen Steinschlag niedergehen lassen?\n");
137 if (!victim)
138 return 0;
139 if ((suc=SpellSuccess(caster,sinfo))<=0)
140 return MISSERFOLG;
141 if (suc < victim->SpellDefend(caster, sinfo))
142 {
143 tell_object(caster, victim->Name() + " wehrt Deinen Spruch ab.\n");
144 return ERFOLG;
145 }
146
147 cn = caster->Name();
148 vnw = victim->name(WEN, 2);
149 say(sprintf("%s laesst kleine Kiesel auf %s fallen.\n",cn, vnw),
150 victim);
151 printf("Du konzentrierst Dich darauf, kleine Kiesel auf %s fallen zu lassen.\n", vnw);
152 tell_object(victim,sprintf("%s laesst kleine Kiesel auf Dich fallen.\n",
153 cn));
154 TryDefaultAttackSpell(victim,caster,sinfo,
155 ([SP_NAME:"steinschlag", SP_PHYSICAL_ATTACK:1,SP_SHOW_DAMAGE:1]));
156 return ERFOLG;
157}
158
159int
160schaetz(object caster, mapping sinfo) {
161 object victim;
162 int hpdiff, wcdiff, acdiff;
163 int hp, vhp, wc, vwc, ac, vac;
164 string result;
165 string vname, vnamegen;
166 int suc;
167
168 victim=FindLivingVictim(sinfo[SI_SKILLARG],caster,
169 "Wen moechtest Du einschaetzen?\n");
170 if (!victim)
171 return 0;
172 if ((suc=SpellSuccess(caster,sinfo))<=0)
173 return MISSERFOLG;
174 if (suc < victim->SpellDefend(caster, sinfo))
175 {
176 tell_object(caster, victim->Name() + " wehrt Deinen Spruch ab.\n");
177 return ERFOLG;
178 }
179
180 hp = caster->QueryProp(P_HP); vhp = victim->QueryProp(P_HP);
181 wc = caster->QueryProp(P_TOTAL_WC); vwc = victim->QueryProp(P_TOTAL_WC);
182 ac = caster->QueryProp(P_TOTAL_AC); vac = victim->QueryProp(P_TOTAL_AC);
183 hpdiff = hp - vhp;
184 wcdiff = wc - vwc;
185 acdiff = ac - vac;
186 vname = victim->name(WER, 1);
187 vnamegen = victim->name(WESSEN, 1);
188
189 if (hpdiff > 10*vhp)
190 result = capitalize(victim->name(WER, 1))+" sollte sich besser schon mal einen Sarg besorgen.\n";
191 else if (hpdiff > 7*vhp)
192 result = "Du bist " + victim->name(WEM, 1) + " haushoch ueberlegen.\n";
193 else if (hpdiff > 4*vhp)
194 result = "Du bist sehr viel staerker als " + vname + ".\n";
195 else if (hpdiff > 2*vhp)
196 result = "Du bist viel staerker als " + vname + ".\n";
197 else if (2*hpdiff > 3*vhp)
198 result = "Du bist spuerbar staerker als " + vname + ".\n";
199 else if (hpdiff > vhp)
200 result = "Du bist staerker als " + vname + ".\n";
201 else if (hpdiff > vhp/5)
202 result = "Du bist etwas staerker als " + vname + ".\n";
203 else if (-hpdiff > 10*hp)
204 result = "Besorg Dir besser schon mal einen Sarg.\n";
205 else if (-hpdiff > 7*hp)
206 result = capitalize(vname) + " ist Dir haushoch ueberlegen.\n";
207 else if (-hpdiff > 4*hp)
208 result = capitalize(vname) + " ist sehr viel staerker als Du.\n";
209 else if (-hpdiff > 2*hp)
210 result = capitalize(vname) + " ist viel staerker als Du.\n";
211 else if (-2*hpdiff > 3*hp)
212 result = capitalize(vname) + " ist spuerbar staerker als Du.\n";
213 else if (-hpdiff > hp)
214 result = capitalize(vname) + " ist staerker als Du.\n";
215 else if (-hpdiff > hp/5)
216 result = capitalize(vname) + " ist etwas staerker als Du.\n";
217 else
218 result = capitalize(vname) + " ist etwa gleich stark wie Du.\n";
219 write(result);
220
221 if (acdiff > 2*vac)
222 result = "Deine Ruestung ist unglaublich viel besser als die "
223 + vnamegen + ".\n";
224 else if (acdiff > vac)
225 result = "Deine Ruestung ist viel besser als die " + vnamegen + ".\n";
226 else if (acdiff >vac/5)
227 result = "Deine Ruestung ist besser als die " + vnamegen + ".\n";
228 else if (-acdiff > 2*ac)
229 result = "Die Ruestung " + vnamegen
230 + " ist unglaublich viel besser als Deine.\n";
231 else if (-acdiff > ac)
232 result = "Die Ruestung " + vnamegen + " ist viel besser als Deine.\n";
233 else if (-acdiff > ac/5)
234 result = "Die Ruestung " + vnamegen + " ist besser als Deine.\n";
235 else
236 result = "Eure Ruestungen sind etwa gleich gut.\n";
237 write(result);
238
239 if (wcdiff > 2*vwc)
240 result = "Deine Waffe ist eigentlich zu gut fuer diesen Gegner.\n";
241 else if (wcdiff > vwc)
242 result = "Deine Waffe ist viel besser als die " +vnamegen + ".\n";
243 else if (wcdiff > vwc/5)
244 result = "Deine Waffe ist besser als die " +vnamegen + ".\n";
245 else if (-wcdiff > 2*wc)
246 result = "Die Waffe " + vnamegen
247 + " laesst Deine ganz mickrig aussehen.\n";
248 else if (-wcdiff > wc)
249 result = "Die Waffe " + vnamegen + " ist viel besser als Deine.\n";
250 else if (-wcdiff > wc/5)
251 result = "Die Waffe " + vnamegen + " ist besser als Deine.\n";
252 else
253 result = "Eure Waffen sind etwa gleich gut.\n";
254 write(result);
255 return ERFOLG;
256}
257
258int kampfschrei(object caster, mapping sinfo)
259{
260 object ob;
261 string cmdline, meldung;
262 int suc, dauer;
263
264 cmdline = this_player()->_unparsed_args();
265 if (cmdline)
266 {
267 if (sscanf(cmdline, "meldung %s", meldung))
268 {
269 caster->Set("ab_kampfschrei", SAVE, F_MODE_AS);
270 caster->SetProp("ab_kampfschrei", meldung);
271 printf("Dein Kampfschrei ist jetzt: %s\n", meldung);
272 return 0;
273 }
274 }
275 ob = FindEnemyVictim(sinfo[SI_SKILLARG], caster,
276 "Wem willst Du Deinen Kampfschrei entgegenschleudern?\n");
277
278 if (!ob)
279 return 0;
280
281 if ((suc=SpellSuccess(caster, sinfo)) <= 0)
282 return MISSERFOLG;
283 if (suc < ob->SpellDefend(caster, sinfo))
284 {
285 tell_object(caster, ob->Name() + " wehrt Deinen Spruch ab.\n");
286 return ERFOLG;
287 }
288
289 meldung = caster->QueryProp("ab_kampfschrei");
290 if (!meldung)
291 meldung = "Aaaaaaaiiiiieeeeeeeeeeeeeeeehhhhhhhhhhhhhhh!!!!!!!\n";
292
293 write(break_string(meldung, 78, "Du kreischst: "));
294 tell_room(environment(caster),
295 break_string(meldung, 78, caster->Name()+" kreischt: "),
296 ({caster}));
297 tell_object(ob, "Du fuehlst Dich wie gelaehmt.\n");
298
299 dauer = 1 + (suc/1000 + random(caster->QueryProp(P_LEVEL)/2))/2;
300 if (dauer>25)
301 dauer = 25;
302 ob->ModifySkillAttribute(SA_SPEED, -50, dauer);
303
304 return ERFOLG;
305}
306
307int ausweichen(object caster, mapping sinfo)
308{
309 if (!caster->InFight())
310 {
311 write("Ausweichen ausserhalb eines Kampfes ist ziemlich sinnlos.\n");
312 return 0;
313 }
314
315 if (caster->QueryProp(P_TMP_DEFEND_HOOK))
316 {
317 write("Das geht momentan nicht, Du wunderst Dich wieso!\n");
318 return 0;
319 }
320
321 if (SpellSuccess(caster,sinfo)<=0)
322 return MISSERFOLG;
323
324 caster->SetProp(P_TMP_DEFEND_HOOK, ({ time()+4, this_object(), "Deckung" }));
325 return ERFOLG;
326}
327
328mixed Deckung(int dam, mixed dam_type, mixed spell, object enemy)
329{
330 if (!pointerp(dam_type))
331 dam_type = ({ dam_type });
332 if (sizeof(dam_type & m_indices(PHYSICAL_DAMAGE_TYPES)))
333 {
334 tell_object(previous_object(), "Du weichst gekonnt aus.\n");
335 if (previous_object()->QueryProp(P_TMP_DEFEND_HOOK)[1] == this_object())
336 previous_object()->SetProp(P_TMP_DEFEND_HOOK, 0);
337 return 0;
338 }
339 tell_object(previous_object(), "Dein Ausweichversuch ist vergebens.\n");
340 return ({ dam, dam_type, spell, enemy });
341}
342
343int
344identifiziere(object caster, mapping sinfo) {
345 object ob;
MG Mud User3c1f5a82016-06-25 09:57:34 +0200346 string result, info;
347 int suc;
348 ob=FindVictim(sinfo[SI_SKILLARG], caster,
349 "Was moechtest Du identifizieren?\n");
350 if (!ob)
351 return 0;
352
MG Mud User3c1f5a82016-06-25 09:57:34 +0200353 if ((suc=SpellSuccess(caster,sinfo))<=0)
354 return MISSERFOLG;
355 if (suc < ob->SpellDefend(caster, sinfo))
356 {
357 tell_object(caster, ob->Name() + " wehrt Deinen Spruch ab.\n");
358 return ERFOLG;
359 }
360
361 result="Du identifizierst "+ob->name(WEN,1)+". "
362 +capitalize(ob->QueryPronoun())
363 +" besteh"
364 +(ob->QueryProp(P_PLURAL) ? "en" : "t")
365 +" aus "
366 +(ob->MaterialList(WEM, caster))+". ";
367 if (info=ob->QueryProp(P_INFO))
368 result+="Ausserdem bemerkst Du folgendes:\n"+info;
369 else result+="Du kannst sonst nichts besonderes an "+ob->QueryPronoun(WEM)
370 +" erkennen.";
371 write(break_string(result, 78, 0, 1));
372 return ERFOLG;
373}
374
375int
376licht(object caster, mapping sinfo)
377{
378 object l;
379
380 tell_object(caster, "Du machst eine magische Bewegung.\n");
381 tell_room(environment(caster),
382 sprintf("%s macht eine magische Bewegung.\n",
383 capitalize(caster->name(WER))), ({caster}));
384
385 int suc=SpellSuccess(caster,sinfo);
386 if (suc<=0)
387 return MISSERFOLG;
388
389 l = clone_object(LICHTKUGEL);
390 if (l->move(this_player()) > 0)
391 {
392 int lvl;
393 // fuer Spruchrollen-Support.
394 if (!sinfo[SI_USR] || !(lvl=sinfo[SI_USR][P_LEVEL]) )
395 lvl = caster->QueryProp(P_LEVEL);
396 lvl = min(lvl,42);
397 // wenn der Spell nicht ganz so gut gelingt, ist die Kugel auch etwas
398 // dunkler.
399 if (suc<6000)
400 {
401 l->SetProp(P_LIGHT,1);
402 tell_object(caster,
403 "Wie aus dem Nichts erscheint eine leuchtende Kugel.\n");
404 }
405 else
406 tell_object(caster,
407 "Wie aus dem Nichts erscheint eine hell leuchtende Kugel.\n");
408 l->start_remove(lvl * 20 * min(suc+3333,10000) / 10000);
409 }
410 else
411 {
412 l->remove();
413 tell_object(caster,
414 "Eine Lichtkugel erscheint, zerplatzt aber sofort mit einem sanften 'plopp'.\n");
415 }
416
417 return ERFOLG;
418}
419
420int
421saeurestrahl(object caster, mapping sinfo) {
422 object victim;
MG Mud User3c1f5a82016-06-25 09:57:34 +0200423 string vnw;
424 int suc;
425
426 victim=FindEnemyVictim(sinfo[SI_SKILLARG],caster,
427 "Wen willst Du mit einem Saeurestrahl beschiessen?\n");
428 if (!victim)
429 return 0;
430 if ((suc=SpellSuccess(caster,sinfo))<=0)
431 return MISSERFOLG;
432 if (suc < victim->SpellDefend(caster, sinfo))
433 {
434 tell_object(caster, victim->Name() + " wehrt Deinen Spruch ab.\n");
435 return ERFOLG;
436 }
437
438 vnw = victim->name(WEN, 2);
439 say(break_string(
440 sprintf(
441 "%s fuchtelt seltsam in der Luft herum und schiesst einen Saeurestrahl auf %s.\n",
442 caster->Name(), vnw), 78), victim);
443 printf("Du schiesst einen Saeurestrahl auf %s.\n", vnw);
444 tell_object(victim, sprintf("%s schiesst einen Saeurestrahl auf Dich.\n",
445 caster->Name()));
446
447 TryDefaultAttackSpell(victim,caster,sinfo,
448 ([SP_NAME:"Saeurestrahl", SP_SHOW_DAMAGE:1]));
449
450 return ERFOLG;
451}
452
453int
454feuerball(object caster, mapping sinfo) {
455 object victim;
MG Mud User3c1f5a82016-06-25 09:57:34 +0200456 string vnw;
457 int suc;
458
459 victim=FindEnemyVictim(sinfo[SI_SKILLARG],caster,
460 "Auf wen willst Du einen Feuerball schleudern?\n");
461 if (!victim)
462 return 0;
463 if ((suc=SpellSuccess(caster,sinfo))<=0)
464 return MISSERFOLG;
465 if (suc < victim->SpellDefend(caster, sinfo))
466 {
467 tell_object(caster, victim->Name() + " wehrt Deinen Spruch ab.\n");
468 return ERFOLG;
469 }
470
471 vnw = victim->name(WEM, 2);
472 say(sprintf("%s wirft einen Feuerball nach %s.\n",
473 caster->Name(), vnw), victim);
474 printf("Du wirfst einen Feuerball nach %s.\n", vnw);
475 tell_object(victim, sprintf("%s wirft einen Feuerball nach Dir.\n",
476 caster->Name()));
477
478 TryDefaultAttackSpell(victim,caster,sinfo,
479 ([SP_NAME:"Feuerball", SP_SHOW_DAMAGE:1]));
480
481 return ERFOLG;
482}
483
484int
485pfeil(object caster, mapping sinfo) {
486 object victim;
Bugfixd8a984b2022-10-06 11:08:08 +0200487 string vnw, cn;
MG Mud User3c1f5a82016-06-25 09:57:34 +0200488 int suc;
489
490 victim=FindEnemyVictim(sinfo[SI_SKILLARG],caster,
491 "Nach wem willst Du einen magischen Pfeil werfen?\n");
492 if (!victim)
493 return 0;
494 if ((suc=SpellSuccess(caster,sinfo))<=0)
495 return MISSERFOLG;
496 if (suc < victim->SpellDefend(caster, sinfo))
497 {
498 tell_object(caster, victim->Name() + " wehrt Deinen Spruch ab.\n");
499 return ERFOLG;
500 }
501
502 cn = caster->Name();
503 vnw = victim->name(WEN, 2);
504 say(sprintf("%s feuert einen magischen Pfeil auf %s ab.\n",cn, vnw),
505 victim);
506 printf("Du feuerst einen magischen Pfeil auf %s ab.\n", vnw);
507 tell_object(victim,sprintf("%s feuert einen magischen Pfeil auf Dich ab.\n",
508 cn));
509 TryDefaultAttackSpell(victim,caster,sinfo,
510 ([SP_NAME:"Pfeil", SP_SHOW_DAMAGE:1]));
511 return ERFOLG;
512}
513
514int
515schnell(object caster, mapping sinfo) {
516 int dauer;
517
518 if (SpellSuccess(caster,sinfo)<=0)
519 return MISSERFOLG;
520 write("Du fuehlst Dich ploetzlich deutlich schneller.\n");
521 dauer = 2 * (caster->QueryAttribute(A_DEX) +
522 random(sinfo[SI_SKILLABILITY]/1000));
523 if (dauer>60)
524 dauer = 60;
525 caster->ModifySkillAttribute(SA_SPEED, 100, dauer);
526
Zesstra47b7cdd2018-01-08 22:14:36 +0100527 call_out(function void (object pl)
528 {if (pl) tell_object(pl, "Du wirst wieder langsamer.\n"); },
529 dauer-__HEART_BEAT_INTERVAL__, caster);
530
MG Mud User3c1f5a82016-06-25 09:57:34 +0200531 return ERFOLG;
532}