[[http://www.siedler-games.de|{{:sg-link.jpg|}}]]
====== 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
* [[reference:setentityname|SetEntityName ( _entity, _name )]]
* [[reference:getentityid|GetEntityId ( _name )]]
* [[reference:getentityname|GetEntityName ( _entity )]]
* [[reference:logic:getentitytype|GetEntityType ( _id )]]
* [[reference:logic:getentitytypename|GetEntityTypeName ( _entityType )]]
* [[reference:getposition|GetPosition ( entity )]]
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 [[http://www.siedler-portal.de/vb3/showthread.php?t=4833|Forumsbeitrag im siedler-portal]] posten.