[M2:TW] Proseminar Scripting - Lehreinheit III: Counter

Hier wird das modden erlernt

Moderatoren: Modding - Moddingschule, Moderatoren

Benutzeravatar
Amon Amarth 930
Hastatus Prior
Hastatus Prior
Beiträge: 1694
Registriert: 19. November 2010 16:58
Wohnort: Xanten
:
Modder

[M2:TW] Proseminar Scripting - Lehreinheit III: Counter

Beitragvon Amon Amarth 930 » 6. Dezember 2010 22:37

Proseminar Scripting - Lehreinheit III: Counter


Die dritte Lehreinheit wird sich mit einem schwierigem und komplexem Thema beschäftigen, nämlich den Countern im Script. Ich habe die Thematik auf Wunsch etwas vorgezogen, früher oder später wären sie so oder so drangekommen, da sie ein essentielles Bestandteil des Scripts sind und so gut wie unersetzlich. Dieses mal ist allerdings höchste Konzentration gefordert um diesen Aspekt vollständig zu begreifen.
Ein Dank hier an dieser Stelle an gigantus, der mein Wissen gestern nochmal kurz auf Nachfrage aufgefrischt hat, denn ich hatte das Gefühl das mein Wissen ein wenig eingerostet war.

Zahlenbeispiel: 340 Counterbezogene Dinge im Fellowship-Script, 5451 bei dHRR 0.7, 6475 bei DLV und 4751 zur Zeit bei GTW. Im Prinzip sagt das rein gar nichts über die Qualität oder Komplexität einer Mod aus, soll es auch gar nicht. Vielmehr soll die Wichtigkeit von Countern unterstrichen werden, auch wenn viele Counterbezogene Dinge in diesen Scripten sich auf einfache Wiederholungen und ellenlange Scripts wie etwa Feldkosten zurückführen lassen.

Einleitung: Ein Counter erlaubt die Interaktion verschiedener Scripts miteinander, dient innerhalb bestimmter Dateien einer Modifikation als Referenz und man benutzt sie, um mit anderen Dateien wie der EDB, EDCT oder EDA zu arbeiten, erlaubt zeitliche Verzögerungen ohne konkrete Angabe einer Rundenzahl, erlaubt die zufällige Auswahl verschiedener Scripte und ist schlichtweg eines der wichtigsten Mittel wenn es über die einfachsten Scripte hinaus geht.
Man merkt vermutlich schon jetzt, Counter sind verdammt nützlich. Dabei gibt es zwei unterschiedliche Arten von den hauptsächlich verwendeten Countern, große Unterschiede zwischen ihnen gibt es nicht, zumindest nicht in der Verwendung, allerdings ist hier auf die korrekte Verwendung von Conditions und Schreibweisen zu achten. Jeder Counter besitzt einen bestimmten Wert der von 0 bis X geht.
Desweiteren wichtig: Jeder Counter muss (bis auf eine Ausnahme) immer deklariert werden! Für die beiden unterschiedlichen gibt es dabei jeweils einen eigenen Befehl. Darauf gehe ich nun im einzelnen ein.

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------


event counter

Deklaration:

Code: Alles auswählen

add_events
event   counter   ABC
end_add_events


ABC = Countername, beliebig wählbar nach den allgemeinen Regeln. (Keine Umlaute, keine Leerzeichen oder Sonderzeichen)
Der Counter ist standardmäßig nach der Deklaration auf 0.

Veränderung:

Code: Alles auswählen

set_event_counter ABC X


Der Counter ABC wird hier auf einen bestimmten Wert gesetzt.

Code: Alles auswählen

inc_event_counter ABC X


Der Counter ABC wird um einen bestimmten Wert (X) verändert. Dabei sind auch Minus-Werte möglich.

Abprüfung:

Code: Alles auswählen

I_EventCounter ABC = X


Mit dieser Condition wird abgeprüft, ob sich ein bestimmter Counter auf einen bestimmten Wert befindet.
Auch hier kann man wie bei vielen anderen Conditions auch, = (gleich); < (Y ist kleiner als X) und > (Y ist größer als X) verwenden.

Wichtig!:

set_event_counter; I_EventCounter; event counter; inc_event_counter; nur hiermit lässt sich mit diesem Counter-Typ arbeiten.

Spezialfall:

Ein Event-Counter kann auch durch ein historisches Event deklariert werden. Wenn also das Event:
historic_event XYZ
Ausgelöst wurde, hat man automatisch auch einen Event-Counter mit dem Namen XYZ der auf 1 gesetzt wurde mit diesem Event.
Das kann man nutzen oder nicht, man sollte es aber im Hinterkopf behalten, insbesondere wenn man dazu neigt viele Dinge einfach gleich zu benennen bei einem Script-Konstrukt um Übersicht zu wahren, man sollte daher dies vermeiden und Counter und historic_event ggf. unterschiedlich benennen.

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------


declare_counter

Deklaration:

Code: Alles auswählen

declare_counter COB


COB = Countername, beliebig wählbar nach den allgemeinen Regeln. (Keine Umlaute, keine Leerzeichen oder Sonderzeichen)
Der Counter ist standardmäßig nach der Deklaration auf 0.

Veränderung:

Code: Alles auswählen

set_counter COB X


Der Counter COB wird hier auf einen bestimmten Wert gesetzt.

Code: Alles auswählen

inc_counter COB X


Der Counter COB wird um einen bestimmten Wert (X) verändert. Dabei sind auch Minus-Werte möglich.

Abprüfung:

Code: Alles auswählen

I_CompareCounter COB = X


Mit dieser Condition wird abgeprüft, ob sich ein bestimmter Counter auf einen bestimmten Wert befindet.
Auch hier kann man wie bei vielen anderen Conditions auch, = (gleich); < (Y ist kleiner als X) und > (Y ist größer als X) verwenden.

Wichtig!:

Wie beim EventCounter-Typ gilt ebenso hier auch das man auf die korrekte Schreibweise und Verwendung der Conditions und Commands unbedingt achten muss, man darf und kann nicht beide Counter-Typen mischen.

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Beispiele:

Ein Auszug aus der Mission für das Abenteurer-Script (GTW), im Link in meiner Signatur findet ihr die Beschreibung der Mission. Hierhin kopiere ich den ersten Teil ebendieser Mission, da ich bei solchen Scripts sehr, sehr viel mit Countern arbeite ist das geradezu prädestiniert zum Vorführen. Ich verwende hier nur den EventCounter-Typ. (Der andere Counter-Typ funktioniert prinzipiell genau so, nur halt mit den andersnamigen Conditions und Commands) Markiert habe ich alle Counter-Relevanten Dinge, meine Absicht ist, dass die ganze Theorie oben hiermit besser nachzuvollziehen ist und die Zusammenhänge klar werden. (Ein Auswahl bzw. Ja/Nein-Event ist auch vorhanden, dazu später noch mehr).

Spoiler (Öffnen)
monitor_event CharacterTurnStart CharacterIsLocal
and AgentType = merchant
and I_EventCounter angebot_abenteurer = 5
and IsRegionOneOf 37
and I_LocalFaction russia
and TimeInRegion > 4


add_events
event counter gestrandet_abenteurer
date 0
end_add_events

set_event_counter gestrandet_abenteurer 1


console_command give_trait held_soldner gestrandet_prolog
console_command move_character held_soldner 363, 235
snap_strat_camera 363, 235
historic_event gestrandet_prolog event/gestrandet.bik

terminate_monitor
end_monitor

;------------------------------------------- Endeckungsmöglichkeiten

monitor_event TileSeen FactionType russia
and FactionIsLocal
and IsPositionInRect 370 227 1 1
and I_EventCounter gestrandet_abenteurer = 1
historic_event steinkreis_gestrandet
terminate_monitor
end_monitor

monitor_event TileSeen FactionType russia
and FactionIsLocal
and IsPositionInRect 360 232 1 1
and I_EventCounter gestrandet_abenteurer = 1
historic_event schiffswrack_gestrandet
console_command give_ancillary held_soldner gestrandet_rapier
terminate_monitor
end_monitor

monitor_event TileSeen FactionType russia
and FactionIsLocal
and IsPositionInRect 382 227 1 1
and I_EventCounter gestrandet_abenteurer = 1
historic_event huette_gestrandet true
terminate_monitor
end_monitor

monitor_event EventCounter EventCounterType huette_gestrandet_accepted
and I_EventCounter huette_gestrandet_accepted > 0

spawn_army
faction russia
character Henk, general, age 34, x 383, y 227
unit Light Dismounted Soldner exp 0 armour 0 weapon_lvl 0
unit Dismounted Soldner exp 0 armour 0 weapon_lvl 0
end
terminate_monitor
end_monitor
monitor_event TileSeen FactionType russia
and FactionIsLocal
and IsPositionInRect 366 222 1 1
and I_EventCounter gestrandet_abenteurer = 1
historic_event banditenlager_gestrandet
terminate_monitor
end_monitor

;------------------------------------------- Kapitel I

monitor_event TileSeen FactionType russia
and FactionIsLocal
and IsPositionInRect 375 214 1 1
and I_EventCounter gestrandet_abenteurer = 1
historic_event kap_i_gestrandet
set_event_counter gestrandet_abenteurer 2
terminate_monitor
end_monitor

;------------------------------------------- Kapitel II

monitor_event CharacterTurnStart CharacterIsLocal
and AgentType = merchant
and I_EventCounter gestrandet_abenteurer = 2
and IsRegionOneOf 27
and I_LocalFaction russia
and TimeInRegion > 1
snap_strat_camera 369, 211
reveal_tile 369, 211

spawn_army
faction slave
character Sten, named character, age 30, x 369, y 211, direction W
traits Supplies 1 , Turnsaway 3 , krieger 1 , locked 1
unit Banditen Schwertkaempfer exp 2 armour 0 weapon_lvl 0
unit Leichte Banditen exp 0 armour 0 weapon_lvl 0
unit Banditen Speertraeger exp 1 armour 0 weapon_lvl 0
end
terminate_monitor
end_monitor


monitor_event CharacterTurnStart CharacterIsLocal
and AgentType = merchant
and I_EventCounter gestrandet_abenteurer = 2
and IsRegionOneOf 27
and I_LocalFaction russia
and TimeInRegion > 1

historic_event kap_ii_gestrandet
set_event_counter gestrandet_abenteurer 3
destroy_units slave Bauern
console_command capture_settlement Thendal
create_unit Thendal, Bauern, num 4, exp 0, arm 0, wep 0
terminate_monitor
end_monitor

;------------------------------------------- Kapitel III

monitor_event PostBattle FactionType russia
and I_WonBattle russia
and IsRegionOneOf 27
and I_EventCounter gestrandet_abenteurer = 3
historic_event kap_iii_gestrandet
set_event_counter gestrandet_abenteurer 4

spawn_army
faction russia
character Harald, named character, age 43, x 374, y 214, direction S, label gestrandet_general
traits Supplies 1 , Turnsaway 3 , stratege 1 , absolut_loyal_m 1
unit Soldner Bodyguard exp 3 armour 0 weapon_lvl 0
end

spawn_army
faction russia
character Edvin, general, age 45, x 368, y 210
unit Sklave Soldner exp 0 armour 0 weapon_lvl 0
unit Sklave Soldner exp 0 armour 0 weapon_lvl 0
end
terminate_monitor
end_monitor

[...]


-------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Weitere Möglichkeiten:

Auswahlevent:

Ein Auswahlevent gibt dem Spieler eine Entscheidungsmöglichkeit im Spiel, also Akzeptieren oder Ablehnen.
Eingeführt wird dieses Event indem man "true" an einem historic_event dranhängt:
historic_event KLM true

Die Counter die nun bei diesem Auswahlevent Verwendung finden heißen wie das historische Event ("KLM").

Nun will man natürlich auch die Folgen scripten, dazu erschafft man zwei neue Monitore, die Annahme/Ablehnung abprüfen.

monitor_event EventCounter EventCounterType KLM_accepted
and I_EventCounter KLM_accepted > 0

monitor_event EventCounter EventCounterType KLM_declined
and I_EventCounter KLM_declined > 0

Wichtig (!): accepted und declined müssen in jedem Fall immer drangehängt werden an den Counter bzw. historic_event-Namen.

Beispiel:

Spoiler (Öffnen)
monitor_event CharacterTurnEnd CharacterIsLocal
and AgentType = merchant
and not EndedInSettlement
and IsRegionOneOf 62
historic_event geheimer_pass true
end_monitor

;------------------------------------------- Angenommen
monitor_event EventCounter EventCounterType geheimer_pass_accepted
and I_EventCounter geheimer_pass_accepted > 0


console_command move_character held_nordorks 261, 156
console_command move_character held_nordmar 261, 156
console_command move_character held_nomaden 261, 156
console_command move_character held_assassinen 261, 156
console_command move_character held_suedorks 261, 156
console_command move_character held_myrtana 261, 156
console_command move_character held_soldner 261, 156
end_monitor

monitor_event EventCounter EventCounterType geheimer_pass_declined
and I_EventCounter geheimer_pass_declined > 0


console_command move_character held_nordorks 271, 142
console_command move_character held_nordmar 271, 142
console_command move_character held_nomaden 271, 142
console_command move_character held_assassinen 271, 142
console_command move_character held_suedorks 271, 142
console_command move_character held_myrtana 271, 142
console_command move_character held_soldner 271, 142
end_monitor


generate_random_counter:

Eine weitere Möglichkeit, hierbei kann man per Condition einen zufälligen Wert von X bis Y generieren lassen, was zufällige "Entweder - Oder" Ereignisse ermöglicht.
Deklariert wird dabei der Counter automatisch mit der Condition. (Man braucht also nicht etwa declare_counter).
Das Beispiel-Script zeigt auf, wie ich mit generate_random_counter es vom Zufall abhängig mache, welches Ancillarie man in der bestimmten Region finden kann. Das eigentliche Script ist noch etwas aufwendiger und umfassender, hier als Anschauungsmaterial deshalb etwas gekürzt.

Beispiel:

Spoiler (Öffnen)
monitor_event CharacterTurnStart AgentType = merchant
and IsRegionOneOf 76
and TimeInRegion > 2
and Attribute Finance <= 5
generate_random_counter anc_skilla 1 4
console_command add_money, 500
terminate_monitor
end_monitor
;-------------------------------------------
monitor_event CharacterTurnStart I_EventCounter anc_skilla = 1
and AgentType = merchant
and IsRegionOneOf 42 76 65 76
and TimeInRegion > 2
and Attribute Finance <= 5
historic_event waffe_skilla
terminate_monitor
end_monitor

monitor_event CharacterTurnStart I_EventCounter anc_skilla = 2
and AgentType = merchant
and IsRegionOneOf 42 76 65 76
and TimeInRegion > 2
and Attribute Finance <= 5
historic_event waffe_skilla
terminate_monitor
end_monitor

monitor_event CharacterTurnStart I_EventCounter anc_skilla = 3
and AgentType = merchant
and IsRegionOneOf 42 76 65 76
and TimeInRegion > 2
and Attribute Finance <= 5
historic_event waffe_skilla
terminate_monitor
end_monitor

monitor_event CharacterTurnStart I_EventCounter anc_skilla = 4
and AgentType = merchant
and IsRegionOneOf 42 76 65 76
and TimeInRegion > 2
and Attribute Finance <= 5
historic_event waffe_skilla
terminate_monitor
end_monitor


Zeitverzögerung:

Wenn man eine Rundenunabhängige Zeitverzögerung möchte, zB.: Erst 10 Runden nachdem Kairo erobert ist, sollen ägyptische Verstärkungsarmeen kommen.
Hier kann man nicht mit einer bestimmten Rundenzahl arbeiten, da man nicht weiß ob und wann Kairo möglicherweise erobert wird.
Es gibt auch ansonsten keine Conditions die das möglich machen, hier muss man mit Countern arbeiten. (Im Fellowship-Script findet man viele Beispiele, damit haben wir dort recht oft gearbeitet).

Beispiel:

Das Beispiel stammt wiederum aus GTW und dem Gestrandet-Abenteurerscript. Hier soll umgesetzt werden, dass eine Armee erst nach ein paar Runden spawnt. Ich habe dieses mal Anmerkungen geschrieben wo normalerweise in meinem Script die knappen Überschriften stehen, damit es nachvollziehbarer ist.

Spoiler (Öffnen)
;------------------------------------------- Der Time-Counter wird zu Beginn des Spiels einmal deklariert.
monitor_event PreFactionTurnStart I_TurnNumber >= 0
add_events
event counter gestrandet_time_counter
date 0
end_add_events

terminate_monitor
end_monitor
;------------------------------------------- Sobald der Missions-Counter für diese Quest auf 4 steht, startet der Time-Counter. Wichtig hier: Kein terminate_monitor, solange der Missionscounter auf 4 steht wird der Time-Counter jede Runde um 1 Punkt erhöt, bis er...
monitor_event FactionTurnStart FactionType russia
and I_EventCounter gestrandet_abenteurer = 4
inc_event_counter gestrandet_time_counter 1
end_monitor
;-------------------------------------------... auf 3 steht. Dann wird eine Armee gespawnt. Die Zeitverzögerung funktioniert vollkommen Rundenunabhängig und ermöglicht vorher unmögliches, was nun durch Counter möglich wird. (Es wird somit zumVermöglichbaren! Für Insider :D)
monitor_event FactionTurnStart FactionIsLocal
and I_LocalFaction russia
and I_EventCounter gestrandet_time_counter = 3
and I_EventCounter gestrandet_abenteurer = 4
and not I_EventCounter gestrandet_abenteurer = 9
historic_event kap_iv_gestrandet
spawn_army
faction slave
character Ilmar, named character, age 22, x 375, y 217, direction S, label gestrandet_angriff_banditen_a
traits Supplies 1 , Turnsaway 3 , krieger 1
unit Leichte Banditen exp 0 armour 0 weapon_lvl 0
unit Leichte Banditen exp 0 armour 0 weapon_lvl 0
unit Leichte Banditen exp 0 armour 0 weapon_lvl 0
unit Leichte Banditenbogenschuetzen exp 1 armour 0 weapon_lvl 0
end
terminate_monitor
end_monitor


-------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Das wars erstmal. Ich spare mir ne theoretische Aufgabe, da ich denke dass einige noch mit der alten Aufgabe beschäftigt sind und zudem dieser neue Lerninhalt vermutlich ziemlich schwere Kost sein wird.
Also wäre die einzige Aufgabenstellung: Lernen, Lernen, Lernen!
Damit dies als erfüllt gilt muss man sich mindestens einmal in diesem Thread melden.
Dateianhänge
Proseminar Scripting - Lehreinheit III Counter.txt
Alter Thread aus dem TWZ.
(24.41 KiB) 72-mal heruntergeladen

Benutzeravatar
Vlad Tepes
Signifer
Signifer
Beiträge: 469
Registriert: 5. Dezember 2010 22:58
:
AAR-Schreiber Modder

Re: [M2:TW] Proseminar Scripting - Lehreinheit III: Counter

Beitragvon Vlad Tepes » 8. Dezember 2010 19:32

Ganz vergessen mich zu melden, ich habe das Thema mehrmals gelesen und hoffentlich verstanden.
Zeigen wird das wahrscheinlich die nächste Praktische Aufgabe.
Bild

Benutzeravatar
Amon Amarth 930
Hastatus Prior
Hastatus Prior
Beiträge: 1694
Registriert: 19. November 2010 16:58
Wohnort: Xanten
:
Modder

Re: [M2:TW] Proseminar Scripting - Lehreinheit III: Counter

Beitragvon Amon Amarth 930 » 8. Dezember 2010 19:48

Bin aber noch am Rätseln was für eine Aufgabe ich stellen soll um explizit Counter reinzubringen.
(Ohne sowas einfallsloses wie: Verwende Counter! ^^)

Benutzeravatar
Xerxes
Architectus
Architectus
Beiträge: 259
Registriert: 5. Dezember 2010 20:51

Re: [M2:TW] Proseminar Scripting - Lehreinheit III: Counter

Beitragvon Xerxes » 11. Dezember 2010 13:15

Jetzt habe ich es hier mal durchgelesen, MELD.
Werde es mal versuchen zu machen, beliebiges Thema oder?

Edit: KLM, und solche Sachen sind beliebige Dinge die dann in Game irgendetwas sind, also so wie ABC am Anfang??
MfG Xerxes

:strategie_zone_292: :strategie_zone_292: :strategie_zone_292: --> :strategie_zone_87: <--- Ich

Benutzeravatar
Amon Amarth 930
Hastatus Prior
Hastatus Prior
Beiträge: 1694
Registriert: 19. November 2010 16:58
Wohnort: Xanten
:
Modder

Re: [M2:TW] Proseminar Scripting - Lehreinheit III: Counter

Beitragvon Amon Amarth 930 » 11. Dezember 2010 13:19

Das war einfach irgendeine Buchstabenkombo.
Da morgen eine praktische Aufgabe kommt, damit das ganze nicht so langsam einschläft, brauchst du dir heute nicht den Kopf zerbrechen über irgend ein Versuch. ;)