Inhaltsverzeichnis
Armeen erstellen
Einführung
Um eine Armee zu erstellen, reicht es nicht aus, im Siedler5-Editor einfach die Truppen auf die Karte zu setzen. Man würde die Soldaten zwar im Spiel sehen, aber das wären nur nutzlose Teile, weil man sie weder befehligen noch sonst etwas mit ihnen tun kann.
Eine Armee, egal ob für den menschlichen oder Computerspieler, muss immer im Script erzeugt werden. Da jede Armee, genau wie jeder Spieler auch, eine eindeutige ID haben muss, ist die Anzahl der nutzbaren Armeen (pro Spieler-ID) begrenzt auf 10, da als ID nur die Ziffern von 0 bis 9 zulässig sind. D.h. jeder Spieler kann maximal 10 Armeen haben.
Einfaches Beispiel
Hier wird eine einfache Armee erstellt, welche aus mehreren Trupps des gleichen Soldatentyps besteht.
Mit Erläuterungen
function CreateArmyOne() -- Erzeugt eine so genannte Tabelle, die alle für das Spiel benötigten Daten -- über die Armee aufnimmt. Eine Armee sollte immer in eine globale Variable -- gespeichert werden, um sie später auch noch außerhalb dieser Funktion -- steuern zu können armyOne = { -- ID des Spielers, für den die Armee bestimmt ist player = 2, -- Eine zulässige und pro Armee einmalige(!) ID von 0 bis 9 id = 1, -- strength gibt die durchschnittliche Stärke der Armee an. -- Stärke bedeutet mit anderen Worten die Anzahl der Truppen -- bzw. Hauptmänner -- Der Wert wird u.a. als Richtlinie für die Funktionen IsWeak() und -- IsVeryWeak() genutzt. -- Es können maximal 8 Hauptmänner in einer Armee sein -- Es ist zwar durchaus möglich, hier eine Zahl größer als 8 einzutragen, -- allerdings werden nur maximal 8 Hauptmänner durch die KI kontrolliert. -- Alle anderen stehen nur in der Gegend rum und verteidigen sich nur, -- wenn sie angegriffen werden. strength = 8, -- Die Position, an der die Armee erzeugt werden soll (eine -- XD_ScriptEntity, welche in diesem Fall den Namen "armyOne" trägt) position = GetPosition("armyOne"), -- Bestimmt den Aktionsradius, -- innerhalb dessen die Armee selbständig angreift rodeLength = 4000 } -- ruft die Comfort-Function "SetupArmy" des Spieles auf, -- um die Armee mit den Daten aus der Tabelle zu erzeugen SetupArmy(armyOne) -- Die Armee existiert nun, aber hat noch keine Truppen. -- Also wird eine Tabelle erzeugt, in der festgelegt wird, welche und wie -- viele Trupps zu der Armee gehören -- ein Trupp ist ein Hauptmann und die entsprechende Anzahl Soldaten local troopDescription = { -- Anzahl der Soldaten pro Hauptmann maxNumberOfSoldiers = 4, -- Die Anzahl der Soldaten, bei der der Hauptmann zur nächsten Kaserne -- geht und Soldaten auffüllt minNumberOfSoldiers = 0, -- Der Erfahrungsgrad, den die Armee bei der Erzeugung hat -- LOW_EXPERIENCE, -- MEDIUM_EXPERIENCE, -- HIGH_EXPERIENCE, -- VERYHIGH_EXPERIENCE experiencePoints = LOW_EXPERIENCE, -- Der Truppentyp. -- Dies !!muss!! etwas mit "Leader" im Namen sein, sonst wird das Spiel -- ohne Fehlermeldung abstürzen! leaderType = Entities.PU_LeaderSword1 } -- EnlargeArmy wird 8x aufgerufen, um der Armee 8 dieser Trupps hinzuzu- -- fügen. Dadurch hat die Armee 8 Hauptmänner for i = 1, 8 do EnlargeArmy(armyOne, troopDescription) end -- Einen Job starten, der die Armee nun kontrolliert. -- Das sollte immer gemacht werden, da es sonst vielleicht zu einigen -- merkwürdigen Verhaltensweisen kommt StartSimpleJob("ControlArmyOne") end function ControlArmyOne() -- Armee-Befehle müssen nicht jede Sekunde erteilt werden: -- Im Normalfall reicht es alle 10 Sekunden -- Dafür sorgt diese if-Abfrage if Counter.Tick2("ControlArmyOne", 10) then -- Wenn die Armee besiegt wurde, muss sie auch nicht mehr kontrolliert -- werden. if IsDead(armyOne) then -- Job beenden return true end -- Verhalten der Armee bestimmen -- hier: verteidigen Defend(armyOne) end end
Ohne Erläuterungen
function CreateArmyOne() armyOne = { player = 2, id = 1, strength = 8, position = GetPosition("armyOne"), rodeLength = 4000 } SetupArmy(armyOne) local troopDescription = { maxNumberOfSoldiers = 4, minNumberOfSoldiers = 0, experiencePoints = LOW_EXPERIENCE, leaderType = Entities.PU_LeaderSword1 } for i = 1, 8 do EnlargeArmy(armyOne, troopDescription) end StartSimpleJob("ControlArmyOne") end function ControlArmyOne() if Counter.Tick2("ControlArmyOne", 10) then if IsDead(armyOne) then return true end Defend(armyOne) end end
Wenn Ihr also die Zahl bei maxNumberOfSoldiers auf 8 ändert, werden pro Hauptmann 8 statt 4 Soldaten erzeugt. Die oben stehende Funktion würde also nun 8 Hauptmänner mit je 4 Soldaten vom Typ Schwertkämpfer Stufe 1 mit niedriger Erfahrungsstufe erzeugen.
Erweitertes Beispiel
Wenn jetzt in derselben Armee auch noch Bogenschützen und Lanzenträger vorhanden sein sollen, muss nur der Teil mit der Beschreibungstabelle angepasst werden. Im obigen Fall heißt die Tabelle troopDescription. Nun spricht nichts dagegen, der Armee mehrere Tabellen mit jeweils verschiedenen Truppen zu übergeben.
function CreateArmyOne() armyOne = { player = 2, id = 1, strength = 8, position = GetPosition("armyOne"), rodeLength = 4000 } SetupArmy(armyOne) local troopDescription = { maxNumberOfSoldiers = 4, minNumberOfSoldiers = 0, experiencePoints = MEDIUM_EXPERIENCE, leaderType = Entities.PU_LeaderSword1 } for i = 1, 8 do EnlargeArmy(armyOne, troopDescription) end local troopDescription = { maxNumberOfSoldiers = 6, minNumberOfSoldiers = 0, experiencePoints = LOW_EXPERIENCE, leaderType = Entities.PU_LeaderBow1 } for i = 1, 6 do EnlargeArmy(armyOne, troopDescription) end local troopDescription = { maxNumberOfSoldiers = 8, minNumberOfSoldiers = 0, experiencePoints = LOW_EXPERIENCE, leaderType = Entities.PU_LeaderPoleArm3 } for i = 1, 4 do EnlargeArmy(armyOne, troopDescription) end StartSimpleJob("ControlArmyOne") end
Also haben wir jetzt folgende Tabellen:
- troopDescription1 8 Trupps einfache Schwertkämpfer zu je 4 Soldaten mit mittlerer Erfahrung
- troopDescription2 6 Trupps einfache Bogenschützen zu je 6 Soldaten mit niedriger Erfahrung
- troopDescription3 4 Trupps verbesserte Lanzenträger zu je 8 Soldaten mit niedriger Erfahrung
Spezialfall: Truppen für den Spieler
Wenn dem Spieler Einheiten gegeben werden sollen, braucht man dazu keine Armee erstellen. Der Spieler kann auch mit normalen Truppen umgehen, die keiner Armee gehören.
In diesem Beispiel wird ein großer Trupp guter Bogenschützen, sowie drei kleine Trupps mittelmäßiger Schwertkämpfer erstellt.
function CreateSupportTroops() CreateMilitaryGroup(1, Entities.PU_LeaderBow4, 8, GetPosition("supporttroops"), "bows") for i = 1, 3 do CreateMilitaryGroup(1, Entities.PU_LeaderSword2, 4, GetPosition("supporttroops")) end end
Der Bogenschützentruppe wurde zusätzlich der Name „bows“ gegeben. Dies braucht man nicht zu tun, wenn man dieser Truppe keine anschliessenden Befehle erteilen will. Mit dem Namen könnte man den Trupp beispielsweise vom Spawnpunkt aus zum Hauptquartier des Spielers laufen lassen. Da die Truppen aber schon dem Spieler gehören, kann dieser natürlich jederzeit andere Befehle erteilen.
Move("bows", "Player_HQ")
Potentielle Probleme
Mit der Handhabung von Armeen gibt es leider ein paar Probleme. Diese werden hier aufgelistet.
IsDead direkt nach der Erstellung
Manchmal möchte man wissen, wann eine Armee vernichtet wurde, um daraufhin eine Aktion auszulösen. Dazu wird ein Job gestartet, welcher IsDead( army ) abfragt. Allerdings ist diese Bedingung direkt nach der Erstellung der Armee erfüllt, da von der Erzeugung per Script, bis zum Erscheinen im Spiel, ein wenig Zeit vergeht. Hierzu gibt es einen modifizierten Abfragecode, der das Problem behebt. Damit er korrekt funktioniert, muss er direkt nachdem die Armee erstellt wurde als Job gestartet werden. Achtung: Wenn es nur darum geht, einen Job zu haben, der die Armee kontrolliert, dann ist dieser Code nicht nötig. Durch Counter.Tick2() wird dieses Problem gar nicht erst auftreten, da der erste Befehl erst nach 10 Sekunden erteilt wird und die Armee bis dahin garantiert schon existiert!
function IsDeadArmyOne() if not armyOne.created then armyOne.created = not IsDead(armyOne) return false end if IsDead(armyOne) then Message("armyOne ist besiegt") return true end end
Dieser Code bewirkt, daß armyOne nicht als Dead gilt, solange sie noch nicht erzeugt wurde.
KI benötigt
Armeen funktionieren nicht richtig, wenn kein KI Spieler für die entsprechende SpielerID erstellt wurde. Wenn dieser KI-Spieler aber kein Gebäude besitzt, stürzt das Spiel ab. Dieses Gebäude muss kein Spielergebäude sein, sondern kann auch ein Zelt, ein Turm, ein Leuchtturm usw. sein. „Funktioniert nicht richtig“ bedeutet in diesem Fall, das sämtliche Armeen ohne KI sofort als tot erklärt werden und deshalb jegliche Armee-Kontrolle unmöglich ist. Die Truppen stehen zwar immer noch dort rum, tun aber nichts. In Verbindung mit einem SpawnGenerator entstehen dann unendlich viele Soldaten, wodurch das Spiel früher oder später hängen bleibt oder abstürzt.
Die KI wird übrigens mit der Funktion MapEditor_SetupAi() oder SetupPlayerAi() aktiviert.
Automatische Bewegung durch die KI
Wichtig: Je nach „strength“-Wert, der beim Erstellen eines Computergegners (= KI) angegeben wurde, werden für diese KI unterschiedlich viele Slots für Armeen erstellt. Armeen mit einer der entsprechenden IDs werden von der KI kontrolliert; egal ob sie per Script erstellt wurden oder die KI sie selbst ausgebildet hat.
Zur Vermeidung von Problemen sollten diese IDs für die Erstellung von Armeen per Script nicht verwendet werden.
Stärke | Reservierte IDs |
---|---|
1 | 1 bis 2 |
2 | 1 bis 4 |
3 | 1 bis 6 |
Die KI erteilt Armeen mit einer anderen ID keine Befehle; diese können per Skriptbefehlen kontrolliert werden.
Mehr dazu hier: http://www.siedler-portal.de/vb3/showthread.php?t=3896