Benutzer-Werkzeuge

Webseiten-Werkzeuge


tutorials:armeen_erstellen2

DELETEME Das ist die alte Armeen Seite. Dient zur Zeit als Backup, wird aber noch zu einem Fortgeschrittenen Tutorial bzgl. Armeen umgestaltet DELETEME

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 auch, genau wie jeder Spieler, 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 10 Armeen haben.

Wenn Ihr also dem menschlichen Spieler eine Armee basteln wollt, müsstet Ihr die playerID 1 vergeben. Aber dazu am Ende noch eine andere Möglichkeit.

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.
    -- Diese wird lokal erzeugt, da sie (zumindest in diesem Beispiel) nicht in anderen Funktionen benötigt wird.
    local armyOne = {
        -- Füllen der Tabelle mit den relevanten Informationen
 
        player      = 2,                        -- ID des Spielers, für den die Armee bestimmt ist
        id          = 1,                        -- Eine zulässige und pro Spieler einmalige(!) ID für die Armee, von 0 bis 9
        strength    = 8,                        -- Anzahl der Hauptmänner, die zur Armee gehören
        position    = GetPosition("armyOne"),   -- Die Position, an der die Armee erzeugt werden soll (eine XD_ScriptEntity, welche in diesem Fall den Namen "armyOne" trägt)
        rodeLength  = 4000                      -- Bestimmt den Aktionsradius, innerhalb dessen die Armee selbständig angreift
        };
 
    -- 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 = {
        maxNumberOfSoldiers = 4,                        -- Anzahl der Soldaten pro Hauptmann
        minNumberOfSoldiers = 0,                        -- Die Anzahl der Soldaten, bei der der Hauptmann zur nächsten Kaserne geht und Soldaten auffüllt
        experiencePoints    = LOW_EXPERIENCE,           -- Der Erfahrungsgrad, den die Armee bei der Erzeugung hat (LOW_EXPERIENCE, MEDIUM_EXPERIENCE, HIGH_EXPERIENCE, VERYHIGH_EXPERIENCE)
        leaderType          = Entities.PU_LeaderSword1  -- Der Truppentyp. Dies sollte möglichst etwas mit "Leader" im Namen sein
        };
 
    -- EnlargeArmy wird 8x aufgerufen, um der Armee 8 dieser Trupps hinzuzufügen. Dadurch hat die Armee, wie oben angegeben, 8 Hauptmänner
    for i = 1, 8 do
        EnlargeArmy(armyOne,troopDescription);
    end
 
    -- Optional kann man einen Job starten, der die Armee nun kontrolliert. Diesem sollte man die Armee als Parameter übergeben
    -- Stattdessen könnte auch einfach Defend(armyOne) (Verteidigung) stehen oder Advance(armyOne) (Angriff)
    --StartSimpleJob("ControlArmyOne")
end

Ohne Erläuterungen

function CreateArmyOne()
    local 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

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. Dann muss aber jede Tabelle einen anderen Namen haben.

function CreateArmyOne()
    local armyOne = {
        player      = 2,
        id          = 1,
        strength    = 18,
        position    = GetPosition("armyOne"),
        rodeLength  = 4000
        };
    SetupArmy(armyOne);
 
    local troopDescription1 = {
        maxNumberOfSoldiers = 4,
        minNumberOfSoldiers = 0,
        experiencePoints    = MEDIUM_EXPERIENCE,
        leaderType          = Entities.PU_LeaderSword1
        };
 
    for i = 1, 8 do
        EnlargeArmy(armyOne,troopDescription1);
    end
 
 
    local troopDescription2 = {
        maxNumberOfSoldiers = 6,
        minNumberOfSoldiers = 0,
        experiencePoints    = LOW_EXPERIENCE,
        leaderType          = Entities.PU_LeaderBow1
        };
 
    for i = 1, 6 do
        EnlargeArmy(armyOne,troopDescription2);
    end
 
 
    local troopDescription3 = {
        maxNumberOfSoldiers = 8,
        minNumberOfSoldiers = 0,
        experiencePoints    = LOW_EXPERIENCE,
        leaderType          = Entities.PU_LeaderPoleArm3
        };
 
    for i = 1, 4 do
        EnlargeArmy(armyOne,troopDescription3);
    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

Da nun 18 Hauptmänner erstellt wurden, muss die Strength der Armee auf 18 gesetzt werden.

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. Wenn man ihm also einfach nur Trupps zuweist, wird dadurch wird keine der ArmeeIDs belegt.

In diesem Beispiel wird ein großer Trupp guter Bogenschützen, sowie drei kleine Trupps mittelmäßiger Schwertkämpfer erstellt.

function CreateSupportTroops()
    local armyOne = { player = 1 };    -- Armee für Spieler 1
 
    local troopDescription1 = {
        maxNumberOfSoldiers = 8,
        minNumberOfSoldiers = 0,
        experiencePoints    = HIGH_EXPERIENCE,
        leaderType          = Entities.PU_LeaderBow3,
        position            = GetPosition( "supporttroops" )
        };
 
    local nBowID = CreateTroop(armyOne,troopDescription1);
 
 
    local troopDescription2 = {
        maxNumberOfSoldiers = 4,
        minNumberOfSoldiers = 0,
        experiencePoints    = LOW_EXPERIENCE,
        leaderType          = Entities.PU_LeaderSword1,
        position            = GetPosition( "supporttroops" )
        };
 
    for i = 1, 3 do
        CreateTroop(armyOne,troopDescription2);
    end
end

Die ID der Bogenschützentruppe wurde in nBowID gespeichert. Dies braucht man nicht zu tun, wenn man dieser Truppe keine anschliessenden Befehle geben will. Mit dieser ID 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( nBowID, "Player_HQ" )

Eine weiter Möglichkeit ist, das man eine Armee in einer Tabelle einließt und sie dann bewegt

function CreateGhostArmy()
      local troopDescription1 = {
      minNumberOfSoldiers = 0,
      maxNumberOfSoldiers = 4,
      experiencePoints = VERYHIGH_EXPERIENCE,
      leaderType = Entities.PU_LeaderHeavyCavalry2,
      position = GetPosition("Barbaren")
      }
 
      army1 = {}
      for i = 1, 10 do
          table.insert (army1, CreateTroop( {player=5}, troopDescription1))
      end
     MoveGhostArmy()
end

In diesem Fall wird eine Armee für den Player 5 verzeugt

Jetzt nur noch den Zielpunkt

function MoveGhostArmy()
   for i = 1, table.getn(army1) do
       Move(army1[i], "BarbarenKill", 300)
   end
end

Spezialfall: Truppen für den Gegner

Hier wird eine Armee mit Parameterübergabe für den Gegner erstellt die sich zu einen Zielpunkt bewegt

CreateTroopsAndMove(_PlayerID, _Position, _LeaderType, _Troops, _Target)
function CreateTroopsAndMove(_PlayerID, _Position, _LeaderType, _Troops, _Target)
    _Position = GetPosition(_Position)
    for i = 1, _Troops do
        Move(GlobalMissionScripting.CreateGroup(_PlayerID, _LeaderType, 8, _Position.X , _Position.Y , 0), _Target)
    end
end

Aufruf der Function

CreateTroopsAndMove(4, "armyOne", GetBow(2), 5, "posArmyOne")

Um einen anderen Armee-Typ auszuwählen, kann man auch
GetPoleArm()
GetSword()
GetBow()
GetHeavyCavalry()
GetLightCavalry()
GetCannon()

angeben. Hier ist die Einstellung von 0-3 Möglich


Eine weiter Möglichkeit Armeen mit Parameterübergabe für den Gegner zu erstellen die sich zu einen Zielpunkt bewegt ist

CreateArmyTroops( _player, _position, _leaderType , _troops, _move)
function CreateArmyTroops( _player, _position, _leaderType , _troops, _move)
    local army = {
        player     = _player,
    }
    local troopDescription	= {
        maxNumberOfSoldiers = 8,
        minNumberOfSoldiers = 0,
        experiencePoints    = HIGH_EXPERIENCE,
        leaderType          = _leaderType,
		position            = _position,
    }
    for i = 1,_troops do
        army[i] = CreateTroop( army , troopDescription )
    end
    for i = 1,_troops do
        Move( army[i], _move)
    end
end

Aufruf der Function

CreateArmyTroops( 4, GetPosition("wacheOne"), Entities.CU_Evil_LeaderBearman1, 2, "posWache")

Der Vorteil ist, das man nicht für jede erstellte Armee den Code neu schreiben muss, und so eine Megne Script-Code spart.
Mit diesem Code kommt man ganz ohne Army ID aus

Man kann diese Functionen auch in einem Counter Aufruf verpacken.
Hier werden all 60 sek. zwei Armeen erstellt, solange der turmTwo noch existiert

Aufruf mit: StartSimpleJob(„ArmyOneTurmTwo“)

function ArmyOneTurmTwo()
      if IsExisting ("turmTwo") and Counter.Tick2( "angriff", 60) then
            Message("Ein Horde Banditen wird euer Dorfzentrum gleich angreifen.")
            CreateArmyTroops( 4, GetPosition("startArmyOne"), Entities.CU_Evil_LeaderBearman1, 2, "Dorfzentrum")
            CreateTroopsAndMove(4, "startArmyOne", GetCannon(2), 3, "Dorfzentrum")
            StartSimpleJob("CheckArmyOneTurmTwo")
	    return true
	 end
end
function CheckArmyOneTurmTwo()
	if not IsDead("turmTwo") then
		StartSimpleJob("ArmyOneTurmTwo")
		return true
	end
end

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.
Hier wird armyOne als Army Table verwendet. Die Message wird nur zu Testzwecken ausgegeben. Sie kann durch die auszuführende Aktion ersetzt werden.

function ControlArmyOne()
	if not armyOne.created then
		armyOne.created = not IsDead(armyOne);
		return false;
	end
 
	if IsDead(armyOne) then
		Message( "armyOne is dead!" );
		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 dem 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 auch mit der Funktion MapEditor_SetupAi() 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_erstellen2.txt · Zuletzt geändert: 2021/09/18 19:16 (Externe Bearbeitung)