Inhaltsverzeichnis
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: