Benutzer-Werkzeuge

Webseiten-Werkzeuge


utilfunctions:changeleader

ChangeLeader

Oftmals möchte man im Spielverlauf Truppen einem anderen Spieler übergeben. Selten sollen aber dabei einfach alle Truppen des Spielers übergeben werden, sondern nur die, die sich in einem bestimmten Gebiet befinden, bzw. nur spezielle Truppenarten. Genau für diesen Verwendungszweck ist die Funktion gedacht.

Wie funktioniert's?

Zunächst einmal müssen wir alle Leader des entsprechenden Spielers, dessen Truppen übergeben werden sollen, ermitteln. Dazu rufen wir eine andere „Hilfsfunktion“ auf, nämlich GetAllLeader. Diese liefert uns 2 Table zurück - eins mit den IDs der Leader und eins mit den IDs der Kanonen des Spielers (sofern welche existieren). Sofern der Spieler auch über Kanonen verfügt, fügen wir deren IDs mit in das Table der Leader-Ids ein.

Nun gehen wir die einzelnen Leader-Ids der Reihe nach durch, und prüfen, wenn nur bestimmte Leader-Typen übergeben werden sollen, ob die jeweilige Einheit einem der angegebenen Typen entspricht, ob sie sich innerhalb des angegebenen Radius befindet und ob die angegebene Anzahl an zu übergebenden Einheiten noch nicht erreicht ist. Fallen alle diese Prüfungen positiv aus, wird die jeweilige Einheit dem anderen Spieler übergeben.

Funktionsaufruf

Die Funktion wird wie folgt aufgerufen:

ChangeLeader(_oldPlayer, _newPlayer, _type, _pos, _range, _amount)

Wobei die Parameter folgendes bedeuten:

  • _oldPlayer = Id des Players, dessen Einheiten übergeben werden sollen.
    (muss immer eine Zahl sein)
  • _newPlayer = Id des Players, dem die Einheiten übergeben werden sollen.
    (muss immer eine Zahl sein)
  • _type = hier kann ein oder mehrere Einheiten-Typen angegeben werden, wenn nur bestimmte Typen übergeben werden sollen, oder „all“ für alle Typen.
    (kann ein String, wie etwa „all“ oder „PU_LeaderSword2“ sein, oder auch ein Table wie etwa {„PV_Cannon1“ , „PV_Cannon2“ , „PV_Cannon3“ , „PV_Cannon4“} )
  • _pos = Positionsangabe um die herum, im Radius (_range), sich die zu übergebenden Einheiten befinden müssen.
    (kann sowohl ein Entity-Name, eine Entity-Id, als auch ein Positions-Table sein)
  • _range = Radius in Siedlerzentimetern in dem, um den Mittelpunkt (_pos) herum, sich die zu übergebenden Einheiten befinden müssen.
    (muss immer eine Zahl sein)
  • _amount = Anzahl der maximal zu übergebenden Einheiten. Kann im Prinzip beliebig groß gewählt werden (z.B. 1000), um sicher zu gehen, dass auch alle Einheiten in dem betreffenden Gebiet übergeben werden.
    (muss immer eine Zahl sein)

Zur Beachtung

Mittels dieser Funktion können beliebige, militärische Einheiten von einem Spieler an einen anderen übergeben werden. Jede militärische Einheit im Spiel hat immer einen sogenannten „Leader“. Jeder Leader kann, je nach Typ, unterschiedlich viele Soldaten (gleichen Typs) „bei sich“ haben. Es genügt aber, den Spieler des Leaders zu wechseln - die zugehörigen Soldaten wechseln automatisch mit. Kanonen haben eine Sonderstellung, werden aber von der Funktion auch erfasst, wobei jede einzelne Kanone als 1 Leader zählt (wichtig für _amount).

Code

An eine beliebige freie Stelle (nicht innerhalb einer anderen Funktion) ins Script packen:

function ChangeLeader(_oldPlayer, _newPlayer, _type, _pos, _range, _amount)
	local _counter = 0
	local _all = 0
	local _leaderIds, _cannonIds = GetAllLeader(_oldPlayer)
	if _cannonIds then
		for i=1,table.getn(_cannonIds) do
			table.insert(_leaderIds, _cannonIds[i])
		end
	end
	local _types = {}
	if type (_type) == "table" then
		for i=1,table.getn(_type) do
			_types[_type[i]] = true
		end
	elseif type (_type) == "string" and _type ~= "all" then
		_types[_type] = true
	elseif type (_type) == "string" and _type == "all" then
		_all = 1
	else Message("Die Angabe der Entities ist fehlerhaft!")
	end
	if type (_pos) == "string" or type (_pos) == "number" then
		_pos = GetPosition(GetEntityId(_pos));
	end
	for i=1,table.getn(_leaderIds) do
		if _all == 0 and not _types[Logic.GetEntityTypeName(Logic.GetEntityType(_leaderIds[i]))] then 
		else 
			if _counter < _amount then
				local _posLeader = GetPosition(_leaderIds[i])
				if (math.sqrt((_pos.X - _posLeader.X)^2 + (_pos.Y - _posLeader.Y)^2) <= _range) then
				  ChangePlayer(_leaderIds[i],_newPlayer)
				  _counter = _counter + 1
				end
			end
		end
	end
end

Wichtig!
Die Funktion GetAllLeader muss sich ebenfalls im Script befinden:

function GetAllLeader(_player)
    local leaderIds = {}
    local cannonIds = {}
    local numberOfLeaders = Logic.GetNumberOfLeader(_player)
    local cannonCount = 0
    local prevLeaderId = 0
    local existing = {}
    for i=1,numberOfLeaders do
        local nextLeaderId = Logic.GetNextLeader( _player, prevLeaderId )
        if existing[nextLeaderId] then
            cannonCount = cannonCount + 1
        else
            existing[nextLeaderId] = true;
            table.insert(leaderIds,nextLeaderId)
        end
        prevLeaderId = nextLeaderId
    end
    if cannonCount > 0 then
        local tempCannonIds = {}
        for i=1,4 do
            local counter = 0
            counter = Logic.GetNumberOfEntitiesOfTypeOfPlayer(_player, Entities["PV_Cannon"..i])
            if counter > 0 then
                tempCannonIds = {Logic.GetPlayerEntities(_player, Entities["PV_Cannon"..i], counter)}
                table.remove(tempCannonIds,1)
                for j=1,table.getn(tempCannonIds) do
                    table.insert(leaderIds,tempCannonIds[j])
                    table.insert(cannonIds,tempCannonIds[j])
                end
            end
        end
    end
    return leaderIds, cannonIds
end

Demo-Map

Hier könnt ihr euch das Ganze mal live in Aktion angucken:

(Legenden) Map: ChangeLeader_Demo

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