Inhaltsverzeichnis


Tenji

Da wir uns ja keine eigenen Helden editieren können, habe ich mir da etwas Abhilfe geschafft!


Create Superfighter - Version 2.00

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“.

Features:




- 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

Create Superfighter - Version 1.01


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!


Die Fähigkeiten eines Superfighters sind:


Die Spezialfähigkeiten kann er alle 50 Sekunden:

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!


Mit diesem Code ...

kann man sich beliebig viele Superfigter erschaffen!

(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!


Damit das ganze funktioniert ...

muss das hier einfach in euer Skript eingefügt werden:

( 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 benötigte Code:

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!

Auch das hier muss einmal in eurem Skript vorhanden sein:
------------------------------------------------------------------------------------------------------------------------------------------------------------ 
-- 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 


Schlusswort

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