forked from github/server
112 lines
4.3 KiB
Plaintext
112 lines
4.3 KiB
Plaintext
|
==-------------------==
|
|||
|
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.
|