server/doc/triggers.txt

112 lines
4.3 KiB
Plaintext
Raw Normal View History

2010-02-20 00:54:42 +01:00
==-------------------==
New Style Eventhandling
==-------------------==
Zweck des ganzen ist es, m<>glichst frei Reaktionen auf Ereignisse zu
implementieren. Dazu mu<6D> nat<61>rlich defineirt sein, was so ein Ereignis
ist. Sowohl die Eriegnisse als auch das, was daraufhin geschieht, mu<6D>
m<>glichst flexibel erweiterbar sein. au<61>erdem sollen solche
Ereigniss-Behandlungen zur Laufzeit defineirt werden k<>nnen. Die m<>glichen
Events kann man nur zur Compilezeit definieren, und auch die Klassen von
Behandlungsroutinen, aber festzulegen wer wann auf was reagiert sollte
durch einen Spruch, das auftauchen eines Drachen, einen Event oder den Tod
einer Einheit ausgel<65>st werden k<>nnen, und beliebiges anderes.
Wie's geht:
Wenn durch den Code ein Event "event" ausgel<65>st wird, dann wird f<>r das
betroffene Objekt X die Funktion handle_event(X->attribs, "event")
aufgerufen. Ja, der Event ist ein String.
handle_event(a, e) sucht in der Liste der attribute nach einem
at_eventhandler Objekt. So ein at_eventhandler verwaltet eine Liste von
Trigger-Objekten trigger_list mit Daten und handle() Funktion, die im Fall
des Events aufgerufen wird. F<>r jeden event-typ (string) gibt es ein
solches at_eventhandler Attribut in der Attributliste, das mehrere
Trigger-Funktionen beinhalten kann. Ich glaube, die hat Ingo in seinem
Ansatz "action" getauft.
Wurde ein Passendes gefunden, dann wird der Reihe nach jeder Trigger
ausgef<65>hrt.
Das ganze wird im Datenfile sogar ziemlich lesbar, wie man hier an diesem
Magier sieht:
eventhandler destroy killunit LeL end
Hier ist ein eventhandler, der im falle eines "destroy" Events auch die
Einheit LeL killt (LeL ist der Vertraute des Magiers).
Neue Trigger-Typen machen:
Neue Trigger zu definieren ist ziemlich leicht, und ich habe schonmal ein
paar flexible vordefiniert. Sie sollten m<>glichst im Verzeichnis triggers/
landen. Dran denken, das jeder in Eressea verwendete trigger-typ mit
tt_register() angemeldet werden mu<6D>. Das passiert in der Datei
eressea/triggers.c
Dabei lohnt es sich, die trigger etwas genereller zu mchen. F<>r viele von
ihnen sollte man resolve.[hc] verstanden haben, da man das zum Speichern
von Referenzen auf Parteien, Einheiten, usw. ben<65>tigt.
Trigger aktivieren:
Der Trigger sollte jeweils in der Attributliste des Objektes landen,
dessen Existnez f<>r die Ausf<73>hrung n<>tig ist. z.B. der Trigger zum T<>ten
des Familiars beim Magier, der zum <20>bergeben eines item an eine person die
ein geb<65>ude betritt, in das Geb<65>ude.
Beispiel: Wenn die verzauberte Burg b zerst<73>rt wird, soll der zaubernde
Magier einen Schock erleiden:
add_trigger(&b->attribs, "destroy", trigger_shock(mage));
Steht die Burg jedoch nach 10 Runden noch an ihrem Fleck, bekommt er einen
Schatz von 100 Silber:
trigger * ttreasure = trigger_giveitem(mage, &i_silver, 100);
trigger * ttimer = trigger_timetrigger(10, ttreasure);
add_trigger(&b-attribs, "timer", ttimer);
Wie man sieht, kann ein trigger einen anderen ausl<73>sen, und mit etwas
Geschick kann man ganze Ketten von Ereignissen hinbekommen, die wieder
neue Trigger setzen, usw.
Bisher definierte Events: (NI=Not Implemented)
{building|faction|unit|ship}:"destroy" - Das Objekt verschwindet.
{building|faction|unit|ship|region}:"timer" - einmal pro Runde in
eressea.c::ageing()
{building}"enter" - Geb<65>ude oder Schiff wird betreten (NI)
Bisher definierte trigger:
- timeout: meta-trigger, aktiviert eine liste von triggern nach einer
zeitspanne.
- changerace: <20>ndert race/irace f<>r eine einheit
- giveitem: gibt items eines typs an eine einheit.
- killunit: t<>tet die angegebene einhiet.
- shock: schockt einen magier.
- changefaction
- removecurse
adaptierte alte trigger:
- famililars:
familiar: on "destroy" shock(mage)
mage: on "destroy" killunit(familiar)
- toad:
mage: on "timer" timeout([changerace(), giveitem(toadslime)])
- summondragon:
region: on "timer" timeout([createunit()])
- magicboost:
mage: on "timer" timeout(createcurse())
- charm:
target: on "timer" changefaction(target)
new faction: on "destroy" destroy(target)
problems to be solved:
- propagation of triggers/attributes in general
- was, wenn ein removecurse(c) ausgefuehrt werden soll, aber der curse
sich propagiert hat? daf<61>r waere wohl ein forwarding-graph ganz geeignet.
(spells:5066, alp)
TODO:
- fprintf/fscanf nochmal checken.