Da wir uns ja keine eigenen Helden editieren können, habe ich mir da etwas Abhilfe geschafft!
Diese Version wurde komplett neu geschrieben und ist viel umfangreicher als die erste. Der Code allerdings auch, der bei ca. 86kB liegt. Das komplette Script mit den Zusatzfunktionen und Parameterbeschreibung findet ihr als Lua-Datei hier.
Die Version ist zum Vorgänger „kompatibel“, das heißt ihr könnt einfach den 1.01-Version durch die 2.00 ersetzen. Allerdings müssen sich alle Zusatzfunktionen der neuen Version im Script befinden. Diese stehen am Ende der Lua-Datei, nach dem Kommentar „Ende der Superfighter Funktionen“.
- Zum Aufrufen eines Superfighters genügt wie bisher der folgende Aufruf, solange sich eine Entity (Hauptmann, Kundschafter oder Dieb) mit diesem Namen auf der Karte befindet. \\
CreateSuperfighter(_name)
- Der erweiterte Aufruf um den Typ und Rang des Superfighters zu bestimmen lautet:
CreateSuperfighter(_name, _typ, _experience)
_experience muss zwischen 0 und 3 liegen, was den Variablen (VERYLOW_EXPERIENCE LOW_EXPERIENCE, MEDIUM_EXPERIENCE, HIGH_EXPERIENCE und VERYHIGH_EXPERIENCE entspricht.
- Befindet sich keine Entity auf der Karte, müssen weitere Angaben gemacht werden:
CreateSuperfighter(_name, _type, _experience, _entityType, _position, _player)
Wobei _player optional und standardmaßig 1 ist und _type wenn, durch „“ oder nil eingesetzt, nicht angegeben immer „Warrior“.
Weitere verwendbare Aufrufe sind:
--IsSuperfighter(_entity) -- gibt true und false zurück --IsSuperfighterFeeling(_entity, _feeling) -- gibt true und false zurück --GetNumberOfPlayerSuperfighters(_player) -- gibt die Anzahl an Superfightern zurück, die dem Spieler gehören --GetSuperfighterType(_entity) -- gibt den Superfightertyp als String auf englisch zurück --GetSuperfighterTypeName(_entity) -- gibt den Superfightertyp als String auf deutsch zurück --GetSuperfighterLevel(_entity) -- gibt den Level als Zahl zurück --GetSuperfighterLevelName(_entity) -- gibt den Rang des Superfighters als String zurück --GetSuperfighterDetails(_kind, _entity) -- kann für alle Werte zurückgeben, die für einen Superfighter gespeichert werden --ChangeSuperfighterType(_entity, _type) -- ändert den Superfightertyp --ChangeSuperfighterLevel(_entity, _experience) -- ändert den Level des Superfighters --DestroySuperfighter( _entity, _notEntity) -- löscht oder tötet einen Superfighter -- _entity kann die Id oder der Name der Entity, sowie der Table des Superfighters sein. -- _feeling ist ein String mit bored, sad, happy oder angry, die Gefühlen des Superfighters entsprechen -- wenn _notEntity true ist, wird nur der Superfightertable gelöscht, die normale Entity bleibt bestehen -- _kind steht für den Index des Wertes, den man aus dem Fightertable abfragen möchte
Es sollte zwar nur eine Funktion für meine Bedürfnisse sein, (ich wollte mal einen Reiter als Helden) doch da ich die Funktion jetzt ja schon einmal habe, dachte ich mir ich machs wie Robert mit seinem Bauernhof, und stell das ganze in den Wiki!
Vielleich hat der eine oder andere noch ein paar Tolle einfälle hierzu!
Wenn die Gesundheit des Superfighters unter 15% sinkt, dann heilt er sich komplett auf 100%
( zumindest, wenn die 50 Sekunden seit der letzten Heilung um sind!)
Beim betätigen des „Einheit entlassen“ - Buttons wird eine Spezialattacke aktiviert, die ich bisher Drehschlag nenne:
Alle feindlichen Einheiten im Umkreis von 500 werden um die Hälfte ihrer Gesammtgesundheit geschwächt. Alle Soldaten (in Truppen) im Umkreis von 300 vernichtet! Also so ähnlich wie bei Erec!
(auch gegnerische (jedoch nicht ausführlich getestet))
Einfach da, wo mann den Superfighter erschaffen will diese Zeile einfügen:
CreateSuperfighter("Name") -- "Name" ist der Skriptname eures Superfighters!
Natürlich muss dann auch eine Entity diesen Namen haben!
Ansonsten einfach dashier vor den Aufruf setzen:
CreateEntity(1,Entities.PU_LeaderHeavyCavalry1,GetPosition("Pos1"),"Name") -- natürlich anpassen!
Bitte nur einzelne Hauptmännern, also solche die keine Soldaten bei sich haben, zu Superfightern machen!
Vernichten kann man einen Superfighter dann ganz einfach durch:
DestroySuperfighter("Name")
Natürlich wird dann nur die „Superkraft“ abgeschaltet, die Entity ist noch da!
( Ihr müsst nichts aufrufen, oder verändern [und bitte auch nicht in die „FirstMapAction“ rein! ] )
------------------------------------------------------------------------------------------------------------------------------------------------------------ -- Comfort functions zum Erschaffen eines Superfighters Version 1.01 by Tenji ------------------------------------------------------------------------------------------------------------------------------------------------------------ function CreateSuperfighter( _name) -- Wenn der globale SuperFighters-Table noch nicht erstellt wurde, tue es hier und starte den Control-Job -- und ändere seine Button SuperFighters = SuperFighters or { SuperFighterJobID = StartSimpleJob("ControlSuperfighters"), InitSuperfighterButtons(), } -- merke Daten des aktuellen Superfighter local superfighter = { name = _name, player = GetPlayer( _name), entityType = Logic.GetEntityType(GetEntityId( _name)), npcIsObservedID = GetEntityId( _name), counter = 0, counterCA = 0, callbackDone = true, } -- füge den aufgerufenen Superfighter dem globalen Table hinzu table.insert(SuperFighters,superfighter) end ------------------------------------------------------------------------- -- Lösche diesen Superfighter aus dem globalen Table: function DestroySuperfighter( _name) -- Gehe alle Superfighter durch ... for i = 1,table.getn(SuperFighters) do -- ... und lösche den aus dem globalen Table, der zerstöhrt werden soll if SuperFighters[i].name == _name then table.remove(SuperFighters,i) return true end end end ------------------------------------------------------------------------- -- Der Superfighter-Control-Job: function ControlSuperfighters() -- Kontrolliere alle Superfighter im globalen Table: for i = 1,table.getn(SuperFighters) do -- hohle die notwendigen Daten aus dem jeweiligen Table local fighter = SuperFighters[i] local name = fighter.name local health = GetHealth( name) local deadName = "Dead"..name local pos = GetPosition( name) local deadPos = GetPosition( deadName) -- wenn er nicht tot ist, ... if not IsDead( fighter.name) then -- steure den Health-Effekt je nach Counter-Stand if fighter.counter == 0 then Logic.CreateEffect(GGL_Effects.FXSalimHeal, pos.X, pos.Y, 0) elseif math.mod( fighter.counter, 3 ) == 2 then Logic.CreateEffect(GGL_Effects.FXSalimHeal, pos.X, pos.Y, 0) end -- wenn der counter der CircularAttack über 0 ist, zähle runter if fighter.counterCA > 0 then fighter.counterCA = fighter.counterCA -1 -- bei 1 melde, das du bereit bist if fighter.counterCA == 1 then Logic.CreateEffect(GGL_Effects.FXDarioFear, pos.X, pos.Y, 0) end -- bei 0 aktualisiere den Button, fals nötig elseif fighter.counterCA == 0 and not fighter.callbackDone and GUI.GetSelectedEntity() == GetEntityId( fighter.name) then GameCallback_GUI_SelectionChanged() fighter.callbackDone = true elseif fighter.counterCA == 0 and not fighter.callbackDone then fighter.callbackDone = true end -- wenn der counter über 0 ist, zähle runter if fighter.counter > 0 then fighter.counter = fighter.counter -1 -- bei 1 melde, das du bereit bist if fighter.counter == 1 then Logic.CreateEffect(GGL_Effects.FXDarioFear, pos.X, pos.Y, 0) end end -- verbessere seine Selbstheilung, durch einen konstanten "+5" und einen alle 30 sek. möglichen "=100" Health-Boost if ( health < 100 and health > 15 ) or ( health < 100 and fighter.counter > 0 ) then SetHealth( name, health +5) elseif health < 15 then SetHealth( name, 100) fighter.counter = 50 Sound.PlayGUISound(Sounds.VoicesHero7_HERO7_Madness_rnd_01, 0) Logic.CreateEffect(GGL_Effects.FXDarioFear, pos.X, pos.Y, 0) end end -- wenn er tot ist, ... if IsDead( fighter.name) then -- wenn seine Überreste nicht herum liegen, dann erstelle sie und setze den "rivive"- counter auf 10 if not IsExisting( deadName) then CreateEntity( 1, Entities.XD_BoneHuman1, pos, deadName) CreateEntity( 1, Entities.XD_Sparkles, pos, "Sparkles"..name) Logic.CreateEffect(GGL_Effects.FXDieHero, pos.X, pos.Y, fighter.player) Explore.Show("Explore"..deadName, deadName, 100) Sound.PlayGUISound(Sounds.VoicesHero7_HERO7_NO_rnd_01, 0) Message( name.." ist zusammengebrochen!") fighter.counter = 10 end -- verdeutliche seine Position zu dem "Sparkles" noch durch den "FXSalimHeal" Logic.CreateEffect(GGL_Effects.FXSalimHeal, deadPos.X, deadPos.Y, 1) -- wenn keine Gegner in der Nähe sind, aber eigene oder befreundete Truppen schon, dann ... if ( not AreEnemiesInArea( fighter.player, deadPos, 500) and AreAlliesInArea( fighter.player, deadPos, 500) ) or ( not AreEnemiesInArea( fighter.player, deadPos, 500) and AreEntitiesInArea( 1, 0, deadPos, 500, 1) ) then -- Zähle von 10 runter ... fighter.counter = fighter.counter -1 MapLocal_StartCountDown( fighter.counter) -- und bei 0: Lass ihn wieder auferstehen! if fighter.counter == 0 then fighter.counter = 25 Explore.Hide("Explore"..deadName) local replacedEntity = ReplaceEntity( deadName, fighter.entityType) SetEntityName( replacedEntity, name) SetHealth( name, 50) DestroyEntity("Sparkles"..name) Sound.PlayGUISound(Sounds.VoicesHero7_HERO7_Yes_rnd_01, 0) -- aktualisiere alle npc.ids in den Npc-briefings, die für isObserved fungieren table.foreach(NPC,NpcIsObservedIDUpdate) fighter.npcIsObservedID = GetEntityId( name) end else MapLocal_StopCountDown() end end end end ------------------------------------------------------------------------- -- Ändere die Button des Superfighters! function InitSuperfighterButtons() -- Die Original-Funktionen einem Index zuordnen GameCallback_GUI_SelectionChangedOrig = GameCallback_GUI_SelectionChanged; GUIAction_ExpelSettlerOrig = GUIAction_ExpelSettler; -- Beim Selektieren einer Einheit wird diese Funktion aufgerufen: GameCallback_GUI_SelectionChanged = function() -- alle Superfighter durchgehen ... for i = 1,table.getn(SuperFighters) do -- wenn die selektierte Einheit ein Superfighter ist, dann die Button umstellen! if GUI.GetSelectedEntity() == GetEntityId(SuperFighters[i].name) then local entity = SuperFighters[i].name local ti = i GameCallback_GUI_SelectionChangedOrig() XGUIEng.ShowWidget(gvGUI_WidgetID.BuySoldierArea, 0) if SuperFighters[i].counterCA == 0 then XGUIEng.DisableButton(gvGUI_WidgetID.ExpelSettler, 0) -- Beim Klicken des "Einheiten entlassen"-Buttons ... GUIAction_ExpelSettler = function() if GUI.GetSelectedEntity() == GetEntityId( entity) then -- ... wird meine Funktion aufgerufen! GUIAction_ExpelSettler_Action( entity) XGUIEng.DisableButton(gvGUI_WidgetID.ExpelSettler, 1) -- und den Counter auf 30 setzen SuperFighters[ti].counterCA = 50 SuperFighters[ti].callbackDone = false else GUIAction_ExpelSettlerOrig(); end end else XGUIEng.DisableButton(gvGUI_WidgetID.ExpelSettler, 1); end return true else GameCallback_GUI_SelectionChangedOrig(); end end end end ------------------------------------------------------------------------- -- Statt des Entlassens der Einheit wird das hier gemacht: function GUIAction_ExpelSettler_Action( _entity) -- Alle gegnerischen Einheiten im Umkreis von 500 [s]cm um die Hälfte Schwächen local actionPos = GetPosition( _entity) Logic.CreateEffect(GGL_Effects.FXKerberosFear, actionPos.X, actionPos.Y, 1) Sound.PlayGUISound(Sounds.VoicesHero7_HERO7_InflictFear_rnd_01, 0) for i = 1,8 do if Logic.GetDiplomacyState(GetPlayer( _entity), i) == Diplomacy.Hostile then local data = {Logic.GetPlayerEntitiesInArea( i, 0, actionPos.X, actionPos.Y, 500, 10)} for i = 2, data[1] + 1 do if Logic.IsBuilding(data[i]) == 0 then if Logic.IsLeader(data[i]) == 1 then local data2 = {Logic.GetSoldiersAttachedToLeader( data[i])} for j = 2, data2[1] + 1 do if IsNear( _entity, data2[j], 300) then SetHealth( data2[j], 0) end end if data2[1] == 0 then SetHealth( data[i],GetHealth( data[i]) -50) end else SetHealth( data[i],GetHealth( data[i]) -50) end end end end end end ------------------------------------------------------------------------- -- Hier wird die npc.id in den Npc-briefings aktualisiert function NpcIsObservedIDUpdate( _id) for i = 1,table.getn(SuperFighters) do local fighter = SuperFighters[i] local npc = NPC[_id] if npc.briefing ~= nil then for j = 1, table.getn(npc.briefing) do if npc.briefing[j].npc ~= nil then if npc.briefing[j].npc.id == fighter.npcIsObservedID or npc.briefing[j].npc.id == 0 then npc.briefing[j].npc.id = GetEntityId(fighter.name) end end end end end end
Zusätzlich braucht ihr nur noch drei kleine Funktion: Die GetHealth-Funktion von Chromix und zwei kleinen Funktionen von mir, die ich zwar intern machen hätte können, doch so könnt ihr sie auch für eure Zwecke benützen, ohne sie nochmals einfügen zu müssen!
------------------------------------------------------------------------------------------------------------------------------------------------------------ -- Comfort function zum Abfragen der Health einer Entity by Chromix ------------------------------------------------------------------------------------------------------------------------------------------------------------ function GetHealth( _entity ) local entityID = GetEntityId( _entity ); if not Tools.IsEntityAlive( entityID ) then return 0; end local MaxHealth = Logic.GetEntityMaxHealth( entityID ); local Health = Logic.GetEntityHealth( entityID ); return ( Health / MaxHealth ) * 100 end ------------------------------------------------------------------------------------------------------------------------------------------------------------ -- Comfort functions zur Abfrage, ob Feinde/Verbündete in einem bestimmten Bereich sind by Tenji ------------------------------------------------------------------------------------------------------------------------------------------------------------ function AreEnemiesInArea( _player, _position, _range) return AreEntitiesOfDiplomacyStateInArea( _player, _position, _range, Diplomacy.Hostile ) end function AreAlliesInArea( _player, _position, _range) return AreEntitiesOfDiplomacyStateInArea( _player, _position, _range, Diplomacy.Friendly ) end function AreEntitiesOfDiplomacyStateInArea( _player, _position, _range, _state ) for i = 1,8 do if Logic.GetDiplomacyState( _player, i) == _state then if AreEntitiesInArea( i, 0, _position, _range, 1) then return true end end end return false end
Vielen Dank an Chromix, Robert und nevermind für Hilfe und Tipps!
Das npc.isObserved-Problem ist jetzt behoben! Tenji [2005/11/12 19:22]
Bei Problemen bitte hier im Forum melden!
Zur Tutorial-Übersicht