Dokumentation zu: abilities.doc(WL)

HR Image


KONZEPT
        Programmierung von Fertigkeiten (Abilities: Skills/Spells)
        von Holger@Wunderland (20.09.1999)

INHALT
	A. EINLEITUNG
	B. UEBERSICHT
	C. ANMELDUNG UND ABMELDUNG
	D. ERLERNEN
	E. SPERREN UND FREIGEBEN
	F. PROGRAMMIERUNG VON SPELLS UND SKILLS
		F.1. SKILLS/SPELLS MIT PRE-DELAY (POLLING)
		F.2. SKILLS/SPELLS OHNE PRE-DELAY
		F.2.1. AUTOMATISCHE EINSCHRAENKUNGEN
		F.2.2. SPELLBOOK-ARBEITSWEISE
		F.2.3. LERNEFFEKT UND AUSFUEHRUNGSDELAY
		F.3. ZUSAMMENFASSUNG
	G. PROGRAMMIERUNG VON COMBAT-SKILLS


A. EINLEITUNG
	Dieser Text beschreibt, wie im Wunderland die Programmierung und
	Ausfuehrung von Fertigkeiten (Skills/Spells/Combatskills) funktio-
	niert. Beispiele fuer Fertigkeiten sind in /spellbooks/beispiel.c
	zu finden. Da im Moment nicht absehbar ist, was mit dem Combatskills
	werden wird, oder ob es sie in Zukunft ueberhaupt in dieser Form
	geben wird, sind die Dokus dazu mit Vorbehalt zu geniessen. *g*


B. UEBERSICHT
	Grundsaetzlich gibt es derzeit 3 verschiedene Typen von Fertigkeiten
	im Wunderland.

	a. Spells - Spells sind magische Zaubersprueche, wie z.B. ein Eis-
		blitz, der mit Hilfe psychisch/magischer Anspannung irgend-
		einen Effekt hervorruft. Spells koennen nicht ausgefuehrt
		werden oder werden mit einer gewissen Wahrscheinlichkeit da
		gehemmt, wo im Raum oder im Opfer P_NOMAGIC gesetzt ist.
		Spells sollten deshalb vorwiegend von Lebewesen verwendet
		werden, die ueber mehr intellektuelle als koerperliche Vor-
		teile haben.

	b. Skills - Skills sind physisch erlernbare Faehigkeiten, wie z.B.
		ein Kampftritt. Der Skill soll grundsaetzlich kaum von der
		Intelligenz des 'Benutzers' abhaengig sein. Er stellt viel-
		mehr eine koerperliche Faehigkeit dar, die durch einen
		Lernprozess abhaengig von Geschicklichkeit, Kraft und Aus-
		dauer einen bestimmten Erfolg bringt.

	c. Combat-Skills - Die Kampf-Faehigkeiten werden automatisch im
		Kampf aufgerufen, wie z.B. 'Schnell'. Die Zukunft der Kampf-
		skills ist im Wunderland noch nicht ganz klar. Man kann sie
		noch einmal unterteilen in Attack-Combat-Skills und Defend-
		Combat-Skills. Die Attack-Skills werden in jeder 'Angriffs-
		runde' des Benutzers aufgerufen und koennen den Angriff mo-
		difizieren. Die Defend-Skills werden in der 'Verteidigungs-
		runde' aufgerufen und koennen den Angriff des Gegners modi-
		fizieren, sprich: abschwaechen.


C. ANMELDUNG UND ABMELDUNG
	Alle echten Fertigkeiten im Wunderland muessen beim Skillmaster
	angemeldet werden, damit Spieler sie ueberhaupt lernen koennen. Dies
	hat zum einen Effizenzgruende, zum anderen soll es dazu beitragen,
	ein wenig die Uebersicht zu behalten, wer wo welche Fertigkeit be-
	nutzen kann. Eine Fertigkeit wird im Skillmaster angemeldet mit
	der Skillmaster-Funktion:

	skillmaster->AddAbility( fertigkeit, ... );

	Die Manpage sollte die einzelnen Argumente ganz gut erklaeren. Der-
	zeit koennen nur Magier ab Regionsmagierstufe eine Fertigkeit an-
	melden. Abmelden kann man eine Fertigkeit mittels:

	skillmaster->RemoveAbility( fertigkeit );

	Es ist darauf zu achten, dass 'abgemeldete' Fertigkeiten noch im
	Spieler aktiv bleiben, bis dieser renewt wird oder Reboot ist. Er
	kann die Fertigkeit dann zwar nicht mehr benutzen, erhaelt jedoch
	eine Meldung. Man sollte dringend darauf achten, dass Spieler die
	eventuell laengere Zeit nicht da waren, nicht ihre Fertigkeiten
	verlieren, weil irgendein Magier diese ab- und unter anderem Namen
	wieder angemeldet hat. Abgemeldete Fertigkeiten verliert der Spieler
	beim Einloggen UNWIEDERBRINGLICH.

	VORM Anmelden (und auch VORM Abmelden) ist unbedingt der Gleichge-
	wichtsmagier oder ein Erzmagier zu informieren. Die Regionsmagier,
	die in der Lage sind, Fertigkeiten anzumelden, tragen dafuer die
	Verantwortung!


D. ERLERNEN
	Nach dem Anmelden kann die Fertigkeit einem Spieler verliehen werden
	(z.B. von einer Gilde oder Spruchrolle) mit der Funktion:

	spieler->GiveAbility( fertigkeit, lernwert );

	Die Manpage erklaert die Argumente. Grundsaetzlich besteht kein
	Unterschied in der Behandlung der Fertigkeiten zwischen NPCs und
	Spielern. Inwieweit eine Fertigkeit aber auch bei einem NPC funk-
	tioniert, haengt von der Fertigkeit selbst und damit von dem Magier
	ab, der die Fertigkeit geschrieben hat. Mit GiveAbility() kann man
	dem Spieler die fertigkeit auch wieder wegnehmen, indem man einen
	Lernwert von -1 angibt. Es ist darauf zu achten, dass das Objekt,
	welches die Fertigkeit vergibt, eine P_SKILLS_ID gesetzt hat, um
	Ueberschneidungen beim Vergabe/Wegnahme zu vermeiden! Die gleiche
	Funktion kann man auch verwenden, um den Lernwert zu erhoehen oder
	zu senken. Dies sollte man aber tunlichst vermeiden, denn das Er-
	lernen/Erhoehen wird automatisch geregelt, wenn der Spieler seine
	Fertigkeit verpatzt.

	Um herauszufinden, wie gut oder schlecht ein Spieler/NPC eine Fer-
	tigkeit beherrscht, kann man folgende Funktion benutzen:

	spieler->GetProbability( fertigkeit );

	Man erhaelt den Lernwert von 'name' in Promille. Wichtig und notwen-
	dig ist diese Funktion vor allem in den sogenannten Spellbooks, um
	die Wahrscheinlichkeit zu berechnen, mit der die Fertigkeit ausge-
	fuehrt wird.

	Um dem Spieler andere alternative Verben zu geben, mit denen er eine
	Fertigkeit ausfuehren kann, kann man die Funktion:

	spieler->SetSkillVerbs( fertigkeit, verben );

	benutzen. Um zu ermitteln, welche Verben der Spieler aktuell fuer
	eine Fertigkeit benutzt, kann man:

	spieler->QuerySkillVerbs( fertigkeit );

	verwenden. Um zu erfahren welche ID das Objekt hat, von dem der
	Spieler/NPC die Fertigkeit erhalten hat, kann man:

	spieler->QuerySkillIDs( fertigkeit );

	verwenden.


E. SPERREN UND FREIGEBEN
	Man kann eine Fertigkeit eines Spielers sperren, indem man die
	Funktion:

	spieler->DisableAbility( fertigkeit );

	verwendet. Der Spieler kann dann diese Fertigkeit solange nicht ver-
	wenden, bis man sie mittels:

	spieler->EnableAbility( fertigkeit );

	wieder freigibt. Es ist darauf zu achten, dass das sperrende Objekt
	wiederum eine eindeutige P_SKILLS_ID gesetzt hat, um Ueberschnei-
	dungen mehrerer Sperrer/Freigeber zu vermeiden! Um zu erfahren, wel-
	che ID die Objekte haben, die eine Fertigkeit momentan sperren, bzw.
	um ueberhaupt zu erfahren, ob eine Fertigkeit gerade gesperrt ist,
	kann man:

	spieler->QueryDisablerIDs( fertigkeit );

	verwenden.


F. PROGRAMMIERUNG VON SPELLS UND SKILLS
	Wenn man sich fuer einen Spell oder Skill entschieden hat, ist die
	Programmierung beider fast identisch. Deshalb wird hier beides ge-
	meinsam beschrieben. Zunaechst sollte man sich noch entscheiden, ob
	man einen Spell/Skill schreibt, der sofort wirkt, oder ob es ein
	Pre-Delay, also eine Vorbereitungsphase geben soll. Bei echten
	Spells, die starke Wirkung haben sollen, ist dies weitaus schoener
	und realistischer, als wenn es sofort ausgefuehrt wird. Wenn es sich
	um einen Skill/Spell mit Pre-Delay handelt, darf sich der Spieler
	waehrend der Ausfuehrung auch nicht bewegen, das heisst, die belieb-
	te Rein-Feuerball-Raus-Taktik wird damit unmoeglich. Es wird zu-
	naechst beschrieben, wie man Skills/Spells mit Pre-Delay schreibt,
	denn ohne Pre-Delay muss man nur einiges weglassen. Dazu mehr in
	Punkt F.2.

	Grundsaetzlich braucht man ein Spellbook. Ein Spellbook ist ein
	praktisch beliebiges Objekt, in dem der Spell/Skill geschrieben ist.
	Spellbooks sollten nach Moeglichkeit in /spellbooks/* liegen. Das
	Spellbook darf natuerlich kein Klon sein, da die Anmeldung ansonsten
	sinnlos wird. Ein Beispiel-Spellbook mit einem Spell und einem Skill
	findet man in /spellbooks/beispiel.c.

F.1. SKILLS/SPELLS MIT PRE-DELAY (POLLING)
	Spells/Skills mit Pre-Delay muessen beim Anmelden im Skillmaster mit
	Flag SM_F_POLL angemeldet werden. Das Spellbook MUSS mindest zwei
	Funktionen enthalten, deren Name fest vorgegeben ist:

	int _poll_XYZ(object player, mixed args, int count)

	int _cast_XYZ(object player, mixed args)

	Wobei XYZ durch den Name der Fertigkeit zu ersetzen ist. Ist der
	Name der Fertigkeit zum Beispiel 'pfeil', so hiessen die beiden
	Funktionen _poll_pfeil() und _cast_pfeil(). Aendert sich der Name
	einer Fertigkeit MUSS man auch die Namen der Funktionen aendern!

	Die Funktion _poll_XYZ() wird waehrend des Pre-Delays solange aufge-
	rufen, wie sie einen Wert ungleich 0 zurueckgibt. Sie wird dann
	in <Returnwert> Sekunden erneut aufgerufen. Gibt also _poll_XYZ()
	als Returnwert 5 zurueck, wird _poll_XYZ() nach 5 Sekunden wieder
	aufgerufen. Damit kann man selbst Textsequenzen und aehnliches rea-
	lisieren. Man bekommt bei jedem Aufruf von _poll_XYZ() den ausfueh-
	renden Spieler als Objektpointer mit, die eingegebenen Argumente als
	Array aus Strings (einzelne Woerter) und als drittes Argument be-
	kommt man einen Zaehler mit, damit man weiss, wie oft _poll_XYZ()
	schon aufgerufen wurde. Beim ersten Aufruf ist der Zaehler 0. Bei
	jedem weiteren Poll wird der Zaehler um 1 erhoeht. Man kann also
	die Vorbereitungs-Sequenz sehr bequem mit switch(count) { ... }
	von 0 beginnend realisieren. Wie lang die Sequenz ist, spielt keine
	Rolle.

	Die Sequenz wird abgebrochen, wenn der Spieler sich in der Vorberei-
	tungsphase BEWEGT. Ausserdem wird sie abgebrochen, wenn der Spieler
	versucht noch eine Fertigkeit innerhalb dieser Phase zu starten.
	Normalerweise darf also nur ein Polling gleichzeitig laufen. Berei-
	tet sich der Spieler gerade auf 'pfeil' vor und versucht waehrend
	dessen noch einen 'feuerball' verhaspelt sich der Spieler. Man kann
	die Anzahl gleichzeitig ausfuehrbarer Polling-Fertigkeiten im Spie-
	ler jedoch auch erhoehen, indem man P_MAX_SKILLS erhoeht.

	Gibt _poll_XYZ() einen Wert kleiner 0 zurueck, wird die weitere Ab-
	arbeitung abgebrochen und die Fertigkeit nicht weiter ausgefuehrt.
	So kann man selbst Abbrueche durchfuehren, wenn zum Beispiel das
	'Opfer' eines Angriffsspruches sich waehrend der Vorbereitungs-
	sequenz entfernt hat, oder andere Bedingungen nicht mehr erfuellt
	sind.

	Gibt _poll_XYZ() einen Wert von 0 zurueck, wird SOFORT (!) die Fun-
	ktion _cast_XYZ() aufgerufen. Die Argumente entsprechen denen von
	_poll_XYZ(), jedoch ohne den Zaehler. Die Cast-Funktion macht jetzt
	die eigentliche Fertigkeit. Da dies mit den Fertigkeiten ohne
	Polling zu 100% uebereinstimmt, wird jetzt der Rest im naechsten
	Punkt gemeinsam beschrieben.

F.2. SKILLS/SPELLS OHNE PRE-DELAY
	Gibt der Spieler ein passendes Verb zu einer Fertigkeit ein, wird
	im Spellbook-Objekt die Funktion:

	int _cast_XYZ(object player, mixed args)

	aufgerufen. Wobei XYZ durch den Name der Fertigkeit zu ersetzen ist.
	Bei Polling-Skills wird die Cast-Funktion erst aufgerufen, wenn die
	Poll-Funktion einen Returnwert von 0 liefert. Argument 'player' ist
	das ausfuehrende Lebewesen, Argument 'args' ist ein Array aus
	Strings, welches die weiteren Argumente als einzelne Woerter ent-
	haelt, die der Spieler beim Aufruf eingegeben hat. (z.B. die ID des
	Opfers oder aehnliches)

F.2.1. AUTOMATISCHE EINSCHRAENKUNGEN
	Der Spieler/NPC kann die Fertigkeit nur ausfuehren, wenn er kein
	Geist ist. Wenn das stoert, muss man die Fertigkeit mit Flag
	SM_F_GHOST anmelden.

	Weiterhin kann der Spieler die Fertigkeit nicht ausfuehren, wenn er
	das notwendige Erhol-Delay (siehe unten) dieser Fertigkeit noch
	nicht gewartet hat.

	Wenn der Spieler gelaehmt ist, oder die Fertigkeit gesperrt ist kann
	er es ebenfalls nicht ausfuehren.

	Und letztlich, wenn der Spieler nicht genuegend Magiepunkte hat, um
	diese Fertigkeit auszufuehren.

	Handelt es sich um einen Spell, kann es sein, dass in dem Raum
	P_NOMAGIC gesetzt wurde und der Spell dann mit einer bestimmten
	Wahrscheinlichkeit fehlschlaegt.

F.2.2. SPELLBOOK-ARBEITSWEISE
	Geht bis hierhin alles gut, bekommt jetzt das Spellbook den oben
	genannten Aufruf von _cast_XYZ(). Das Spellbook kann damit jetzt
	theoretisch verfahren wie es will. Es gibt aber einen gewissen Stil,
	den sollte man einhalten. :-)

	Zunaechst sollte man ueberpruefen, ob die vom Spieler eingegebenen
	Argumente in Ordnung sind. Also das angegebene Opfer sich im Raum
	befindet, eventuell sollte ermittelt werden, ob sich der Spieler im
	Kampf befindet und das 'Opfer' daher automatisch bestimmt werden
	soll, ohne dass es der Spieler angeben muss etc. Stimmen die Argu-
	ment NICHT, dann sollte man jetzt mit return -1; (Define FEHLER in
	sys/living/skills.h) abbrechen. Der Fehler bewirkt, dass die Fertig-
	keit ohne Abzug von Punkten oder aehnliches einfach abgebrochen
	wird.

	Weiterhin sollte man ueberpruefen, ob der Spieler benoetigte Aus-
	ruestungsgegenstaende dabei hat. Ganz wichtig vor allem bei Polling-
	Fertigkeiten mit einer Sequenz, in der man bestimmte Zutaten mischt
	oder aehnliches. Dann empfiehlt es sich jedoch diese Pruefungen
	bereits in der Poll-Funktion (_poll_XYZ()) durchzufuehren. Stimmt
	irgendwas nicht ueberein, dann wiederum -> return FEHLER;

	Sind die Argument ok und der Spieler hat eventuell auch alles dabei,
	muss man errechnen, ob der die Fertigkeit gelingt oder nicht. Dazu
	sollte man sich den aktuellen Lernwert dieser Fertigkeit vom Spieler
	mittels:

	lernwert=spieler->GetProbability( fertigkeit );

	holen. Da der Lernwert in Promille von 0 bis 1000 angegeben ist, und
	Spieler sich immer totaergern, wenn sie nie auf 100% kommen, weil
	Berechung falsch ist, sollte folgendes verwendet werden:

	if(random(1000)<lernwert)
		ERFOLG!
	else
		MISSERFOLG!

	So kann selbst bei einem Lernwert von 999 Promille der Spruch noch
	schief gehen, naemlich wenn der Randomwert auch 999 ist. Natuerlich
	steht es jedem Spellbook-Schreiber frei, die Wahrscheinlichkeit des
	Erfolgs selbst anhand anderer Parameter, wie zum Beispiel des Levels
	oder der Intelligenz usw. zu berechnen. Es ist auch denkbar den Er-
	folg oder Misserfolg abgestufter zu gestalten als dieses Modell, wo
	es nur totalen Erfolg oder totalen Fehlschlag gibt. Das muss jeder
	selbst entscheiden. Wichtig ist im Grunde nur eins, naemlich, dass
	bei erfolgreicher Ausfuehrung ein Returnwert von 1 (Define ERFOLG in
	sys/living/skills.h) zurueckgegeben wird oder bei einem Fehlschlag
	ein Wert von 0 (Define MISSERFOLG in sys/living/skills.h).

	Vorher muss das Spellbook natuerlich noch irgendwas tun. Die Fertig-
	keit eben. Dies kann ein (ggf. magischer) Angriff auf ein Opfer oder
	nur ein netter Gag oder irgendwas anderes sein. Ist es gelungen ->
	return ERFOLG ansonsten return MISSERFOLG.

	Und das wars eigentlich schon. Wichtig bei Spells die einen magi-
	schen Angriff durchfuehren (Aufruf des gegnerischen Defend()) ist,
	dass das Spelllevel mit uebergeben wird und auch der magische Scha-
	denstyp mit gesetzt wird. Mehr muss das Spellbook nicht tun, denn
	alles weitere wird wieder automatisch gemacht.

F.2.3. LERNEFFEKT UND AUSFUEHRUNGSDELAY
	Ist der Zauberspruch geglueckt (ERFOLG), werden jetzt automatisch
	die Kosten abgezogen, die bei der Anmeldung bei Skillmaster angege-
	ben wurden. Weiterhin wird das dort angegebene Delay fuer diese Fer-
	tigkeit gesetzt. Der Spieler kann dann innerhalb eines bestimmten
	Zeitraums diese Fertigkeit nicht mehr anwenden. Existiert im Spell-
	book eine Funktion:

	int get_delay( string fertigkeit, object spieler );

	und diese Funktion liefert daraufhin einen Wert ungleich Null, wird
	dieser Wert als Delay gesetzt. Gibt es sogar eine Funktion:

	string get_delay_msg( string fertigkeit, object spieler );

	dann wird deren Returnwert als Text ausgegeben, wenn der Spieler
	versucht, innerhalb des Delays die Fertigkeit anzuwenden. Damit
	lassen sich originellere Meldungen als die Standard-Message ausge-
	ben.

	War die Ausfuehrung ein Fehlschlag (MISSERFOLG), werden die Kosten
	auch abgezogen und das Delay gesetzt. Zusaetzlich lernt der Spieler
	jedoch aus seinem Fehler. Und zwar um den Wert:

	random( ( ( stat * factor ) / 40 ) + 1 )

	Dabei ist 'stat' der Wert des Attributs welches man beim Anmelden
	der Fertigkeit als Argument 'stat' angegeben hat. Variable 'factor'
	entspricht dem Argument 'factor' beim Anmelden der Fertigkeit beim
	Skillmaster.

	Ein Rechenbeispiel: Wurde die Fertigkeit mit 'stat' A_INT und
	'factor' 15 angemeldet und der aufrufende Spieler hat eine Intelli-
	genz von 12, dann lernt der Spieler beim MISSERFOLG um folgenden
	Wert dazu:

	random( ( ( 12 * 15 ) / 40 ) + 1 ) -> entspricht -> random( 5 );

	Der Spieler lernt die Fertigkeit also um einen Wert zwischen Null
	und 4. Wem das zu wenig ist, der muss den Faktor entsprechend hoeher
	setzen beim Anmelden.

	Es kann bei zu niedrigen Stats passieren, dass ein Spieler den
	Spruch nicht verbessern kann, da ( stat * factor ) / 40 ) immer
	kleiner 1 ist. In diesem Fall erhaelt der Spieler eine entsprechende
	Meldung, dass seine Stats zu klein sind. Will man diese Meldung
	unterdruecken - z.b. weil das Lernen ohnehin 'per hand' vom Spellbook
	gemacht wird, dann kann man den Factor auf 0 setzen. Aber dann wird
	der Spieler den Spruch niemals automatisch verbessern! Dann muss man
	das wirklich ueber das Spellbook oder die Gilde machen lassen.

F.2.4 KOSTEN
        Ist im Spellbook die Funktion get_cost_reduction definiert, so wird
        diese vor dem Abzug der Kosten als

        get_cost_reduction( string fertigkeit, object spieler,
                            int kosten, int resultat );

        aufgerufen. Die zurueckgegebene Zahl wird von den Kosten abgezogen.
        Dabei sind kosten die nicht reduzierten Kosten und resultat entweder
        ERFOLG oder MISSERFOLG.

F.3. ZUSAMMENFASSUNG
	Das alles sieht komplizierter aus, als es ist. Wichtig ist:

	a. Ein Spellbook-Objekt mit mindestens einer Funktion _cast_XYZ()
           Fuer Polling-Fertigkeiten auch noch _poll_XYZ()

	b. In _cast_XYZ() checken, ob die Argumente ok sind.

	c. Wahrscheinlichkeit des Erfolgs berechnen.

	d. Wenn Erfolg -> irgendwas Tolles machen. :-)

	e. Returnwerte richtig zurueckgeben FEHLER, ERFOLG oder MISSERFOLG.

	f. Gnadenlos von /spellbooks/beispiel.c abkupfern. ;-)

	g. Den Gleichgewichtsmagier oder einem Erzmagier abnicken lassen.

	h. Die Fertigkeit richtig anmelden (lassen).
	   Fuer Polling-Fertigkeiten unbedingt mit Flag SM_F_POLL !


G. PROGRAMMIERUNG VON COMBAT-SKILLS
	Fuer Combat-Skills kann _cast_XYZ() den Zusatzschaden zurueckgeben.

	Da die Zukunft dieses Skill-Typs zur zeit etwas unklar ist, gibts
	dazu im Moment keine weitere Doku. Wenn es nicht anders geht, bitte
	Holger fragen...

	Fuer ein Beispiel zu den Combat-Skills ist in /spellbooks/race_skills.c
	der Sprungangriff der Marranen einsehbar.

SIEHE AUCH:
        AddAbility(L), AddSkillAction(L), CountPolls(L), Execute(L),
        FindPoll(L), GetProbability(L), GiveAbility(L), QueryDelay(L),
        QuerySkillVerbs(L), RemoveAbility(L), RemovePolls(L),
        SetActiveSkill(L), SetDelayTime(L), SetSkillVerbs(L), Valid(L),
        _cast_(L), P_ACTIVE_SKILLS, P_LAST_SKILL, P_SKILLS,
        P_COMBAT_SKILLS, P_MAX_SKILLS, P_SM_VERBS, skillmaster(SEC),
        P_SKILLS_ID, QuerySkillIDs(L), DisableAbility(L), EnableAbility(L),
	QueryDisablerIDs(L), get_delay(L), get_delay_msg(L)


Start » Magierhandbuch » Docu » Konzepte » Abilities.doc Letzte Generierung: 25.04.2021, 01:58
Email an: mud@wl.mud.de
Valid HTML 4.01!