Benutzer-Werkzeuge

Webseiten-Werkzeuge


tutorials:armeen_erstellen

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

Siehe auch

tutorials/armeen_erstellen.txt · Zuletzt geändert: 2021/09/18 19:16 (Externe Bearbeitung)