blob: d706a1f94a8cc11d641dcb4224e477606ab83792 [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;
132 int hands;
133 string vn, vnw, cn;
134 int suc;
135
136 victim=FindEnemyVictim(sinfo[SI_SKILLARG],caster,
137 "Ueber wem willst Du einen Steinschlag niedergehen lassen?\n");
138 if (!victim)
139 return 0;
140 if ((suc=SpellSuccess(caster,sinfo))<=0)
141 return MISSERFOLG;
142 if (suc < victim->SpellDefend(caster, sinfo))
143 {
144 tell_object(caster, victim->Name() + " wehrt Deinen Spruch ab.\n");
145 return ERFOLG;
146 }
147
148 cn = caster->Name();
149 vnw = victim->name(WEN, 2);
150 say(sprintf("%s laesst kleine Kiesel auf %s fallen.\n",cn, vnw),
151 victim);
152 printf("Du konzentrierst Dich darauf, kleine Kiesel auf %s fallen zu lassen.\n", vnw);
153 tell_object(victim,sprintf("%s laesst kleine Kiesel auf Dich fallen.\n",
154 cn));
155 TryDefaultAttackSpell(victim,caster,sinfo,
156 ([SP_NAME:"steinschlag", SP_PHYSICAL_ATTACK:1,SP_SHOW_DAMAGE:1]));
157 return ERFOLG;
158}
159
160int
161schaetz(object caster, mapping sinfo) {
162 object victim;
163 int hpdiff, wcdiff, acdiff;
164 int hp, vhp, wc, vwc, ac, vac;
165 string result;
166 string vname, vnamegen;
167 int suc;
168
169 victim=FindLivingVictim(sinfo[SI_SKILLARG],caster,
170 "Wen moechtest Du einschaetzen?\n");
171 if (!victim)
172 return 0;
173 if ((suc=SpellSuccess(caster,sinfo))<=0)
174 return MISSERFOLG;
175 if (suc < victim->SpellDefend(caster, sinfo))
176 {
177 tell_object(caster, victim->Name() + " wehrt Deinen Spruch ab.\n");
178 return ERFOLG;
179 }
180
181 hp = caster->QueryProp(P_HP); vhp = victim->QueryProp(P_HP);
182 wc = caster->QueryProp(P_TOTAL_WC); vwc = victim->QueryProp(P_TOTAL_WC);
183 ac = caster->QueryProp(P_TOTAL_AC); vac = victim->QueryProp(P_TOTAL_AC);
184 hpdiff = hp - vhp;
185 wcdiff = wc - vwc;
186 acdiff = ac - vac;
187 vname = victim->name(WER, 1);
188 vnamegen = victim->name(WESSEN, 1);
189
190 if (hpdiff > 10*vhp)
191 result = capitalize(victim->name(WER, 1))+" sollte sich besser schon mal einen Sarg besorgen.\n";
192 else if (hpdiff > 7*vhp)
193 result = "Du bist " + victim->name(WEM, 1) + " haushoch ueberlegen.\n";
194 else if (hpdiff > 4*vhp)
195 result = "Du bist sehr viel staerker als " + vname + ".\n";
196 else if (hpdiff > 2*vhp)
197 result = "Du bist viel staerker als " + vname + ".\n";
198 else if (2*hpdiff > 3*vhp)
199 result = "Du bist spuerbar staerker als " + vname + ".\n";
200 else if (hpdiff > vhp)
201 result = "Du bist staerker als " + vname + ".\n";
202 else if (hpdiff > vhp/5)
203 result = "Du bist etwas staerker als " + vname + ".\n";
204 else if (-hpdiff > 10*hp)
205 result = "Besorg Dir besser schon mal einen Sarg.\n";
206 else if (-hpdiff > 7*hp)
207 result = capitalize(vname) + " ist Dir haushoch ueberlegen.\n";
208 else if (-hpdiff > 4*hp)
209 result = capitalize(vname) + " ist sehr viel staerker als Du.\n";
210 else if (-hpdiff > 2*hp)
211 result = capitalize(vname) + " ist viel staerker als Du.\n";
212 else if (-2*hpdiff > 3*hp)
213 result = capitalize(vname) + " ist spuerbar staerker als Du.\n";
214 else if (-hpdiff > hp)
215 result = capitalize(vname) + " ist staerker als Du.\n";
216 else if (-hpdiff > hp/5)
217 result = capitalize(vname) + " ist etwas staerker als Du.\n";
218 else
219 result = capitalize(vname) + " ist etwa gleich stark wie Du.\n";
220 write(result);
221
222 if (acdiff > 2*vac)
223 result = "Deine Ruestung ist unglaublich viel besser als die "
224 + vnamegen + ".\n";
225 else if (acdiff > vac)
226 result = "Deine Ruestung ist viel besser als die " + vnamegen + ".\n";
227 else if (acdiff >vac/5)
228 result = "Deine Ruestung ist besser als die " + vnamegen + ".\n";
229 else if (-acdiff > 2*ac)
230 result = "Die Ruestung " + vnamegen
231 + " ist unglaublich viel besser als Deine.\n";
232 else if (-acdiff > ac)
233 result = "Die Ruestung " + vnamegen + " ist viel besser als Deine.\n";
234 else if (-acdiff > ac/5)
235 result = "Die Ruestung " + vnamegen + " ist besser als Deine.\n";
236 else
237 result = "Eure Ruestungen sind etwa gleich gut.\n";
238 write(result);
239
240 if (wcdiff > 2*vwc)
241 result = "Deine Waffe ist eigentlich zu gut fuer diesen Gegner.\n";
242 else if (wcdiff > vwc)
243 result = "Deine Waffe ist viel besser als die " +vnamegen + ".\n";
244 else if (wcdiff > vwc/5)
245 result = "Deine Waffe ist besser als die " +vnamegen + ".\n";
246 else if (-wcdiff > 2*wc)
247 result = "Die Waffe " + vnamegen
248 + " laesst Deine ganz mickrig aussehen.\n";
249 else if (-wcdiff > wc)
250 result = "Die Waffe " + vnamegen + " ist viel besser als Deine.\n";
251 else if (-wcdiff > wc/5)
252 result = "Die Waffe " + vnamegen + " ist besser als Deine.\n";
253 else
254 result = "Eure Waffen sind etwa gleich gut.\n";
255 write(result);
256 return ERFOLG;
257}
258
259int kampfschrei(object caster, mapping sinfo)
260{
261 object ob;
262 string cmdline, meldung;
263 int suc, dauer;
264
265 cmdline = this_player()->_unparsed_args();
266 if (cmdline)
267 {
268 if (sscanf(cmdline, "meldung %s", meldung))
269 {
270 caster->Set("ab_kampfschrei", SAVE, F_MODE_AS);
271 caster->SetProp("ab_kampfschrei", meldung);
272 printf("Dein Kampfschrei ist jetzt: %s\n", meldung);
273 return 0;
274 }
275 }
276 ob = FindEnemyVictim(sinfo[SI_SKILLARG], caster,
277 "Wem willst Du Deinen Kampfschrei entgegenschleudern?\n");
278
279 if (!ob)
280 return 0;
281
282 if ((suc=SpellSuccess(caster, sinfo)) <= 0)
283 return MISSERFOLG;
284 if (suc < ob->SpellDefend(caster, sinfo))
285 {
286 tell_object(caster, ob->Name() + " wehrt Deinen Spruch ab.\n");
287 return ERFOLG;
288 }
289
290 meldung = caster->QueryProp("ab_kampfschrei");
291 if (!meldung)
292 meldung = "Aaaaaaaiiiiieeeeeeeeeeeeeeeehhhhhhhhhhhhhhh!!!!!!!\n";
293
294 write(break_string(meldung, 78, "Du kreischst: "));
295 tell_room(environment(caster),
296 break_string(meldung, 78, caster->Name()+" kreischt: "),
297 ({caster}));
298 tell_object(ob, "Du fuehlst Dich wie gelaehmt.\n");
299
300 dauer = 1 + (suc/1000 + random(caster->QueryProp(P_LEVEL)/2))/2;
301 if (dauer>25)
302 dauer = 25;
303 ob->ModifySkillAttribute(SA_SPEED, -50, dauer);
304
305 return ERFOLG;
306}
307
308int ausweichen(object caster, mapping sinfo)
309{
310 if (!caster->InFight())
311 {
312 write("Ausweichen ausserhalb eines Kampfes ist ziemlich sinnlos.\n");
313 return 0;
314 }
315
316 if (caster->QueryProp(P_TMP_DEFEND_HOOK))
317 {
318 write("Das geht momentan nicht, Du wunderst Dich wieso!\n");
319 return 0;
320 }
321
322 if (SpellSuccess(caster,sinfo)<=0)
323 return MISSERFOLG;
324
325 caster->SetProp(P_TMP_DEFEND_HOOK, ({ time()+4, this_object(), "Deckung" }));
326 return ERFOLG;
327}
328
329mixed Deckung(int dam, mixed dam_type, mixed spell, object enemy)
330{
331 if (!pointerp(dam_type))
332 dam_type = ({ dam_type });
333 if (sizeof(dam_type & m_indices(PHYSICAL_DAMAGE_TYPES)))
334 {
335 tell_object(previous_object(), "Du weichst gekonnt aus.\n");
336 if (previous_object()->QueryProp(P_TMP_DEFEND_HOOK)[1] == this_object())
337 previous_object()->SetProp(P_TMP_DEFEND_HOOK, 0);
338 return 0;
339 }
340 tell_object(previous_object(), "Dein Ausweichversuch ist vergebens.\n");
341 return ({ dam, dam_type, spell, enemy });
342}
343
344int
345identifiziere(object caster, mapping sinfo) {
346 object ob;
347 string* fi;
348 string cn;
349 string result, info;
350 int suc;
351 ob=FindVictim(sinfo[SI_SKILLARG], caster,
352 "Was moechtest Du identifizieren?\n");
353 if (!ob)
354 return 0;
355
356 cn = caster->name();
357 if ((suc=SpellSuccess(caster,sinfo))<=0)
358 return MISSERFOLG;
359 if (suc < ob->SpellDefend(caster, sinfo))
360 {
361 tell_object(caster, ob->Name() + " wehrt Deinen Spruch ab.\n");
362 return ERFOLG;
363 }
364
365 result="Du identifizierst "+ob->name(WEN,1)+". "
366 +capitalize(ob->QueryPronoun())
367 +" besteh"
368 +(ob->QueryProp(P_PLURAL) ? "en" : "t")
369 +" aus "
370 +(ob->MaterialList(WEM, caster))+". ";
371 if (info=ob->QueryProp(P_INFO))
372 result+="Ausserdem bemerkst Du folgendes:\n"+info;
373 else result+="Du kannst sonst nichts besonderes an "+ob->QueryPronoun(WEM)
374 +" erkennen.";
375 write(break_string(result, 78, 0, 1));
376 return ERFOLG;
377}
378
379int
380licht(object caster, mapping sinfo)
381{
382 object l;
383
384 tell_object(caster, "Du machst eine magische Bewegung.\n");
385 tell_room(environment(caster),
386 sprintf("%s macht eine magische Bewegung.\n",
387 capitalize(caster->name(WER))), ({caster}));
388
389 int suc=SpellSuccess(caster,sinfo);
390 if (suc<=0)
391 return MISSERFOLG;
392
393 l = clone_object(LICHTKUGEL);
394 if (l->move(this_player()) > 0)
395 {
396 int lvl;
397 // fuer Spruchrollen-Support.
398 if (!sinfo[SI_USR] || !(lvl=sinfo[SI_USR][P_LEVEL]) )
399 lvl = caster->QueryProp(P_LEVEL);
400 lvl = min(lvl,42);
401 // wenn der Spell nicht ganz so gut gelingt, ist die Kugel auch etwas
402 // dunkler.
403 if (suc<6000)
404 {
405 l->SetProp(P_LIGHT,1);
406 tell_object(caster,
407 "Wie aus dem Nichts erscheint eine leuchtende Kugel.\n");
408 }
409 else
410 tell_object(caster,
411 "Wie aus dem Nichts erscheint eine hell leuchtende Kugel.\n");
412 l->start_remove(lvl * 20 * min(suc+3333,10000) / 10000);
413 }
414 else
415 {
416 l->remove();
417 tell_object(caster,
418 "Eine Lichtkugel erscheint, zerplatzt aber sofort mit einem sanften 'plopp'.\n");
419 }
420
421 return ERFOLG;
422}
423
424int
425saeurestrahl(object caster, mapping sinfo) {
426 object victim;
427 int hands;
428 string vnw;
429 int suc;
430
431 victim=FindEnemyVictim(sinfo[SI_SKILLARG],caster,
432 "Wen willst Du mit einem Saeurestrahl beschiessen?\n");
433 if (!victim)
434 return 0;
435 if ((suc=SpellSuccess(caster,sinfo))<=0)
436 return MISSERFOLG;
437 if (suc < victim->SpellDefend(caster, sinfo))
438 {
439 tell_object(caster, victim->Name() + " wehrt Deinen Spruch ab.\n");
440 return ERFOLG;
441 }
442
443 vnw = victim->name(WEN, 2);
444 say(break_string(
445 sprintf(
446 "%s fuchtelt seltsam in der Luft herum und schiesst einen Saeurestrahl auf %s.\n",
447 caster->Name(), vnw), 78), victim);
448 printf("Du schiesst einen Saeurestrahl auf %s.\n", vnw);
449 tell_object(victim, sprintf("%s schiesst einen Saeurestrahl auf Dich.\n",
450 caster->Name()));
451
452 TryDefaultAttackSpell(victim,caster,sinfo,
453 ([SP_NAME:"Saeurestrahl", SP_SHOW_DAMAGE:1]));
454
455 return ERFOLG;
456}
457
458int
459feuerball(object caster, mapping sinfo) {
460 object victim;
461 int hands;
462 string vnw;
463 int suc;
464
465 victim=FindEnemyVictim(sinfo[SI_SKILLARG],caster,
466 "Auf wen willst Du einen Feuerball schleudern?\n");
467 if (!victim)
468 return 0;
469 if ((suc=SpellSuccess(caster,sinfo))<=0)
470 return MISSERFOLG;
471 if (suc < victim->SpellDefend(caster, sinfo))
472 {
473 tell_object(caster, victim->Name() + " wehrt Deinen Spruch ab.\n");
474 return ERFOLG;
475 }
476
477 vnw = victim->name(WEM, 2);
478 say(sprintf("%s wirft einen Feuerball nach %s.\n",
479 caster->Name(), vnw), victim);
480 printf("Du wirfst einen Feuerball nach %s.\n", vnw);
481 tell_object(victim, sprintf("%s wirft einen Feuerball nach Dir.\n",
482 caster->Name()));
483
484 TryDefaultAttackSpell(victim,caster,sinfo,
485 ([SP_NAME:"Feuerball", SP_SHOW_DAMAGE:1]));
486
487 return ERFOLG;
488}
489
490int
491pfeil(object caster, mapping sinfo) {
492 object victim;
493 int hands;
494 string vn, vnw, cn;
495 int suc;
496
497 victim=FindEnemyVictim(sinfo[SI_SKILLARG],caster,
498 "Nach wem willst Du einen magischen Pfeil werfen?\n");
499 if (!victim)
500 return 0;
501 if ((suc=SpellSuccess(caster,sinfo))<=0)
502 return MISSERFOLG;
503 if (suc < victim->SpellDefend(caster, sinfo))
504 {
505 tell_object(caster, victim->Name() + " wehrt Deinen Spruch ab.\n");
506 return ERFOLG;
507 }
508
509 cn = caster->Name();
510 vnw = victim->name(WEN, 2);
511 say(sprintf("%s feuert einen magischen Pfeil auf %s ab.\n",cn, vnw),
512 victim);
513 printf("Du feuerst einen magischen Pfeil auf %s ab.\n", vnw);
514 tell_object(victim,sprintf("%s feuert einen magischen Pfeil auf Dich ab.\n",
515 cn));
516 TryDefaultAttackSpell(victim,caster,sinfo,
517 ([SP_NAME:"Pfeil", SP_SHOW_DAMAGE:1]));
518 return ERFOLG;
519}
520
521int
522schnell(object caster, mapping sinfo) {
523 int dauer;
524
525 if (SpellSuccess(caster,sinfo)<=0)
526 return MISSERFOLG;
527 write("Du fuehlst Dich ploetzlich deutlich schneller.\n");
528 dauer = 2 * (caster->QueryAttribute(A_DEX) +
529 random(sinfo[SI_SKILLABILITY]/1000));
530 if (dauer>60)
531 dauer = 60;
532 caster->ModifySkillAttribute(SA_SPEED, 100, dauer);
533
Zesstra47b7cdd2018-01-08 22:14:36 +0100534 call_out(function void (object pl)
535 {if (pl) tell_object(pl, "Du wirst wieder langsamer.\n"); },
536 dauer-__HEART_BEAT_INTERVAL__, caster);
537
MG Mud User3c1f5a82016-06-25 09:57:34 +0200538 return ERFOLG;
539}