Inhaltsverzeichnis
GetAllHeroes
Diese Funktion benennt automatisch alle (zum Zeitpunkt des Aufrufs) auf der (Singleplayer) Map vorhandenen Helden von Player 1, und erzeugt zu jedem Helden eine globale Tabelle (Table), die jeweils folgende Werte beinhaltet:
- EntityId
- EntityTyp Id
- Entity Typename
- Entity X-Pos
- Entity Y-Pos
Verwendung
Damit von beginn an alle Helden benannt werden und die anderen Informationen zur Verfügung stehen, sollte der Funktionsaufruf
GetAllHeroes()
unbedingt in der FMA (FirstMapAction) erfolgen!
Ein erneuter Aufruf der Funktion ist immer dann, und nur dann erforderlich, wenn per
CreateEntity (_playerId,_entity,_position,_name)
ein neuer Held/ eine neue Heldin „erschaffen“ wurde, bzw. wenn ein Held/ eine Heldin per
DestroyEntity (_entity)
aus dem Spiel „entfernt“ wurde.
Beispiele
- Entity Scriptname ⇒ _name
Jeder vorhandene Held/ jede vorhandene Heldin wird gemäß den in der 'herotable' angegebenen Namen benannt und man kann somit fortan per Scriptname auf sie zugreifen:
if IsNear ("Dario", "Pilgrim", 300) then ... end
- Entity Id ⇒ _name.id
Die jeweilige Id eines Helden/ einer Heldin wird im zugehörigen Table gespeichert und man kann wiefolgt darauf zugreifen:
MakeInvulnerable (Dario.id)
- Entity Typ-Id ⇒ _name.typeId
Die jeweilige Typ-Id eines Helden/ einer Heldin wird im zugehörigen Table gespeichert und man kann wiefolgt darauf zugreifen:
AreEntitiesInArea (1, Ari.typeId, _position, _range, 1)
- Entity Typename ⇒ _name.typeName
Der jeweilige Entity Typename eines Helden/ einer Heldin wird im zugehörigen Table gespeichert und man kann wiefolgt darauf zugreifen:
Message (Erec.typeName)
- Entity X-Pos, Y-Pos ⇒ _name.pos.X, _name.pos.Y
Die jeweilige (aktuelle) X- & Y-Koordinate eines Helden/ einer Heldin wird im zugehörigen Table gespeichert und man kann wiefolgt darauf zugreifen:
Move ("Varg", {X = Helias.pos.X, Y = Helias.pos.Y})
Hierbei handelt es sich natürlich um willkürlich gewählte Beispiele, die lediglich den Zugriff auf die entsprechenden Daten veranschaulichen sollen und nicht unbedingt eine sinnvolle Art der Anwendung darstellen.
Einschränkungen/ Fehlerüberprüfung
Da es von der Spiellogik her nicht vorgesehen (obwohl möglich) ist, dass mehrere Helden desselben Typs zur gleichen Zeit (für Player 1) existieren, wird dies in der Funktion geprüft und sie nur dann ausgeführt, wenn kein Held mehrfach vorkommt.
Wer eine Map hat, wo dies (absichtlich) dennoch der Fall ist, der kann die Funktion nicht verwenden!
Sinn & Zweck
Funktionen sind ja predistiniert dafür, um uns immer wiederkehrende Aufgaben abzunehmen/ zu erleichtern. Und da eigentlich jede Map mind. einen Helden beinhaltet …!
Die Funktion dient rein der Bequemlichkeit und verhindert das versehentliche mehrfache Setzen/ Erstellen von Helden - sonst nichts!
Natürlich lassen sich alle Aufgaben auch mit Hilfe der entsprechenden Comfort- & Logic-Funktionen
umsetzen.
Code
Hier nun der benötigte Scriptcode:
function GetAllHeroes() local heroIds={} --# Table mit den Entitytypnamen und den zu verwendenden Scriptnamen local herotable = { {"PU_Hero1", "Dario"}, {"PU_Hero1a", "Dario"}, {"PU_Hero1b", "Dario"}, {"PU_Hero1c", "Dario"}, {"PU_Hero2", "Pilgrim"}, {"PU_Hero3", "Salim"}, {"PU_Hero4", "Erec"}, {"PU_Hero5", "Ari"}, {"PU_Hero6", "Helias"}, {"CU_BlackKnight", "Kerberos"}, {"CU_Mary_de_Mortfichet", "MarydeMortfichet"}, {"CU_Barbarian_Hero", "Varg"}, {"CU_Evil_Queen", "Kala"}, {"PU_Hero10", "Drake"}, {"PU_Hero11", "Yuki"} } --# Metatable local metaPosHeroes = { __index = function(_table, key) if key=="pos" then return GetPosition(_table.id) end end } --# eigentliche Funktion zum Erstellen der globalen Indizes für jeden Hero local SetupHeroTable = function(_id,_name) Logic.SetEntityName(_id,_name) _G[_name] = { id = _id, typeId = Logic.GetEntityType(_id), typeName = Logic.GetEntityTypeName(Logic.GetEntityType(_id)), _metatable = true, } setmetatable(_G[_name], metaPosHeroes) end Logic.GetHeroes(1,heroIds) --# Abschnitt zur Fehlerprüfung: Heroes mehrfach vorhanden? local tmp_EntityTypeIds={} for k,v in pairs(heroIds) do table.insert(tmp_EntityTypeIds,Logic.GetEntityType(v)) end table.sort(tmp_EntityTypeIds) local error_count=0 local dario_count=0 for k,v in pairs(tmp_EntityTypeIds) do local a,b=next(tmp_EntityTypeIds,k) if v==b then Message("Error: Held vom Typ "..Logic.GetEntityTypeName(v).." ist mehrfach vorhanden!") error_count=error_count+1 end for i=1,4 do if v==Entities[herotable[i][1]] then dario_count=dario_count+1 end end end if dario_count>1 then Message("Error: Held Dario ist "..dario_count.." mal vorhanden!") error_count=error_count+1 end --# wenn keine Fehler aufgetreten sind, dann Indexe anlegen if error_count==0 then for i=1,table.getn(heroIds) do local typ=Logic.GetEntityType(heroIds[i]) local hFound = false; for j=1,table.getn(herotable) do if typ==Entities[herotable[j][1]] then hFound=true; SetupHeroTable(heroIds[i],herotable[j][2]) end end if not hFound then local tmp_name=Logic.GetEntityTypeName(typ) Message("Error: Es existiert ein unbekannter Held vom Entity-Typ: "..tmp_name) end end --# früher vorhandene und nicht mehr existierende Indexe löschen for i=1,table.getn(herotable) do if (not IsExisting(herotable[i][2])) then _G[herotable[i][2]]=nil end end end end --# Funktionen zum wiederherstellen der Metatables/-verknüpfungen nach dem Laden eines Savegames Mission_OnSaveGameLoadedOrig = Mission_OnSaveGameLoaded; function Mission_OnSaveGameLoaded() Mission_OnSaveGameLoadedOrig(); ResetMetatables(_G, {}); end function ResetMetatables(_table, _visited) if not _visited[_table] then _visited[_table] = true; for k, v in pairs(_table) do if type(v) == "table" then ResetMetatables(v, _visited); if v._metatable == true then setmetatable( v, { __index = function(_table, _key) if _key == "pos" then return GetPosition(_table.id); end end } ); end end end end end
Anmerkung: Die zu vergebenden Scriptnamen im 'herotable' können natürlich nach eigenem Wunsch angepasst werden.
Forumsbeitrag
Wer Fragen, Anregungen und/ oder Probleme zu/ mit der Funktion hat, der kann diese auch gerne im entsprechenden Forumsbeitrag im siedler-portal posten.