Schaden per Skript

» Siedler Map Source Forum » Siedler DEdK Script Forum » Schaden per Skript

Seiten: 1

Noigi
#1
28.02.2010 19:23
Beiträge: 772

Schaden per Skript

Aloha!

Wer schonmal manuell mit "HurtEntity" oder Ähnlichem ins Kampfgeschehen eingegriffen hat, kennt die Absturzquote. Besonders schlimm ist es, wenn man innerhalb eines LOGIC_EVENT_ENTITY_HURT_ENTITY-Triggers Schaden zufügen will.

Ich habe jetzt eine Komfortfunktion geschrieben, mit der man als Skripter jederzeit Schaden austeilen können soll. Bisher klappt das auch ohne Absturz. Mal sehen wie's bei euch aussieht.

Insbesondere kann die Funktion:
- innerhalb eines LOGIC_EVENT_ENTITY_HURT_ENTITY-Callbacks Schaden verteilen
- bei ganzen Soldatengruppen das oder die richtige(n) Opfer finden und den Schaden korrekt über die Gruppe verteilen - egal ob der Hauptmann oder ein Soldat angegeben wurde

Der Aufruf sieht so aus:

-- Beispiel 1: einer Gruppe Schwertkämpfer mit Hauptmann "schwerti1" sollen 1000 Schaden durch eine Tretmine zugefügt werden.
-- Dabei werden mehrere Soldaten sterben
local entity = "schwerti1";
local schaden = 1000;
HurtEntitySAVE(entity,schaden);

-- Beispiel 2: Schwertis Gruppe wurde mit einem verzauberten Bogen getroffen, der bis zu 500 Schaden machen kann.
-- Hier kann anschaulich nur einer sterben. Man kann zu diesem Zweck das Maximum der verwundeten Ziele mit dem optionalen dritten Parameter begrenzen
local entity = "schwerti1";
local schaden = 500;
local maxZiele = 1;
HurtEntitySAVE(entity,schaden,maxZiele);

-- Der Rückgabewert der Funktion ist ein table mit den IDs aller Entities, die durch den Schaden getötet/zerstört wurden.



Hier der Code. Um die Debug-Infos auszuschalten, einfach den entsprechenden Abschnitt unten auskommentieren.

function ControlHurtSAVE()
	local n = table.getn(gvHurtSAVE);
	if n == 0 then
		return true;
	else
		for i = n,1,-1 do
			for j = 1,table.getn(gvHurtSAVE[i]) do
				local opfer = gvHurtSAVE[i][j];
				if GetHealth(opfer) > 0 then
					SetHealth(opfer,0); -- Ciao Bella! :(
				end
			end
			table.remove(gvHurtSAVE,i);
		end
	end
end

function HurtEntitySAVE(_eID,_dmg,_tarMax)
	_eID = GetEntityId(_eID)
	if (_dmg <= 0) or (GetHealth(_eID) == 0) then
		return {}; -- Trivialfälle
	end
	_tarMax = math.max(1, (_tarMax or 17));
	local aua = _eID;
	local toeten = {};
  -- FALL ABFANGEN: Soldat angegeben; ermittle Hauptmann
	if SoldierTypes[Logic.GetEntityType(aua)] then
		local leader = SoldierGetLeaderEntityID(aua);
		if leader == 0 then
			return {}; -- kein Leader gefunden, Schaden wird nicht zugefügt
		else
			aua = leader; -- Delegiere an den Hauptmann der Gruppe
		end
	end
  -- FALL ABFANGEN: Hauptmann angegeben; ermittle ggf Soldaten, da sie Priorität bei Schadensverteilung haben
	if Logic.IsLeader(aua) == 1 then
		local leader = aua;
		local soldiers = {Logic.GetSoldiersAttachedToLeader(leader)}
		local i = 1;
		while (i <= soldiers[1]) and (_dmg > 0) do
			local opfer = soldiers[i+1];
			i = i+1;
			local overkill = (_dmg - Logic.GetEntityHealth(opfer));
			if overkill >= 0 then
				table.insert(toeten, opfer) -- armes Ding :(
				if table.getn(toeten) >= _tarMax then
					_dmg = 0; -- Maximale Anzahl an Zielen getroffen: kein weiterer Schaden, Euer Ehren!
					break;
				else
					_dmg = overkill; -- Restschaden weiterhin verteilen
				end
			else
				aua = opfer; -- Dieser Soldat wird durch den Schaden nicht getötet: er wird das "Hurt"-Ziel und die Schleife wird abgebrochen. Der "_dmg" stimmt automatisch
				break;
			end
		end
		if leader == aua then -- Jetzt noch prüfen, ob der Hauptmann auch stirbt, oder nur Schaden nimmt. Wenn er nicht mehr "aua" ist, passiert ihm gar nichts
			local overkill = (_dmg - Logic.GetEntityHealth(leader));
			if overkill >= 0 then
				table.insert(toeten, leader) -- Der Hauptmann stirbt auch
				_dmg = 0; -- Restschaden wird jetzt (natürlich) ignoriert!
			end
		end
  -- FALL ABFANGEN: Weder Hauptmann noch Soldat (Leibi, Held, Gebäude o.Ä.)
	else
		local overkill = (_dmg - Logic.GetEntityHealth(aua));
		if overkill >= 0 then
			table.insert(toeten, aua) -- Die Entity stirbt
			_dmg = 0; -- Restschaden wird auch hier (natürlich) nicht verteilt!
		end
	end
  -- FÄLLE GEKLÄRT: Ab jetzt sind alle zu tötenden Entities im table "toeten", und die ggf zu verwundende Entity ist in "aua", der (Rest-)Schaden in "_dmg"

		----------- DEBUG ---------------------------------------
		if _dmg > 0 then
			local pos = GetPosition(aua);
			Logic.CreateEffect( GGL_Effects.FXSalimHeal, pos.X, pos.Y, 0 );
			Message("Getroffen: @color:255,0,0 "..aua.." @color:255,255,255 Schaden: @color:255,0,0 ".._dmg)
		end
		for i = 1,table.getn(toeten) do
			local pos = GetPosition(toeten[i]);
			Logic.CreateEffect( GGL_Effects.FXSalimHeal, pos.X, pos.Y, 0 );
			if i == 1 then
				Message("Es sterben @color:255,0,0 "..table.getn(toeten).." @color:255,255,255 Entitie(s)!")
			end
		end
		----------- DEBUG ---------------------------------------

	gvHurtSAVE = gvHurtSAVE or {};
	table.insert(gvHurtSAVE,toeten); -- Die gesammelten Entities auf die Schlachtbank setzen, ggf Job (neu) starten
	if JobIsRunning(gvHurt_JobIDSAVE) == 0 then
		gvHurt_JobIDSAVE = StartSimpleHiResJob("ControlHurtSAVE");
	end
	if _dmg > 0 then -- Ggf Schaden verteilen
		Logic.HurtEntity(aua,_dmg);
	end
	return toeten; -- Rückgabe der Opfer
end


-- ### COMFORTS ###
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

SoldierTypes = { -- Alle Soldaten-EntityTypes mit zugehörigem Leader-Typ
	[Entities.CU_BanditSoldierBow1] = Entities.CU_BanditLeaderBow1,
	[Entities.CU_BanditSoldierSword1] = Entities.CU_BanditLeaderSword1,
	[Entities.CU_BanditSoldierSword2] = Entities.CU_BanditLeaderSword2,
	[Entities.CU_Barbarian_SoldierClub1] = Entities.CU_Barbarian_LeaderClub1,
	[Entities.CU_Barbarian_SoldierClub2] = Entities.CU_Barbarian_LeaderClub2,
	[Entities.CU_BlackKnight_SoldierMace1] = Entities.CU_BlackKnight_LeaderMace1,
	[Entities.CU_BlackKnight_SoldierMace2] = Entities.CU_BlackKnight_LeaderMace2,
	[Entities.CU_Evil_SoldierBearman1] = Entities.CU_Evil_LeaderBearman1,
	[Entities.CU_Evil_SoldierSkirmisher1] = Entities.CU_Evil_LeaderSkirmisher1,
	[Entities.PU_SoldierBow1] = Entities.PU_LeaderBow1,
	[Entities.PU_SoldierBow2] = Entities.PU_LeaderBow2,
	[Entities.PU_SoldierBow3] = Entities.PU_LeaderBow3,
	[Entities.PU_SoldierBow4] = Entities.PU_LeaderBow4,
	[Entities.PU_SoldierCavalry1] = Entities.PU_LeaderCavalry1,
	[Entities.PU_SoldierCavalry2] = Entities.PU_LeaderCavalry2,
	[Entities.PU_SoldierHeavyCavalry1] = Entities.PU_LeaderHeavyCavalry1,
	[Entities.PU_SoldierHeavyCavalry2] = Entities.PU_LeaderHeavyCavalry2,
	[Entities.PU_SoldierPoleArm1] = Entities.PU_LeaderPoleArm1,
	[Entities.PU_SoldierPoleArm2] = Entities.PU_LeaderPoleArm2,
	[Entities.PU_SoldierPoleArm3] = Entities.PU_LeaderPoleArm3,
	[Entities.PU_SoldierPoleArm4] = Entities.PU_LeaderPoleArm4,
	[Entities.PU_SoldierRifle1] = Entities.PU_LeaderRifle1,
	[Entities.PU_SoldierRifle2] = Entities.PU_LeaderRifle2,
	[Entities.PU_SoldierSword1] = Entities.PU_LeaderSword1,
	[Entities.PU_SoldierSword2] = Entities.PU_LeaderSword2,
	[Entities.PU_SoldierSword3] = Entities.PU_LeaderSword3,
	[Entities.PU_SoldierSword4] = Entities.PU_LeaderSword4,
};

function SoldierGetLeaderEntityID(_solID)
	local leadType = SoldierTypes[Logic.GetEntityType(_solID)]
	if leadType then
		local pID = GetPlayer(_solID)
		local pos = GetPosition(_solID)
		local t = {Logic.GetPlayerEntitiesInArea( pID, leadType, pos.X, pos.Y, 2000, 40 )}
		for i = 1,t[1] do
			local leader = t[i+1];
			local soldiers = {Logic.GetSoldiersAttachedToLeader(leader)}
			if soldiers[1] then
				for j = 1,soldiers[1] do
					if soldiers[j+1] == _solID then
						return leader;
					end
				end
			end
		end
	end
	return 0;
end


Ihr könnt die Funktion frei verwenden. Wer sie ausprobiert, sei angehalten, hier über die Resultate zu berichten.

lg
Noigi

nevermind
Siedler Map Source Admin (Web)
#2
28.02.2010 21:30
Beiträge: 483

Okay, ist lange her aber: Meiner Meinung nach haben Soldaten immer volle Lebenspunkte, auch wenn sie vom Gegner getroffen werden. Wenn man eine Truppe erstellt, manuell die Lebenspunkte jedes Soldaten auf 1 setzt, müsste es trotzdem noch genauso lange dauern bis die Truppe komplett aufgerieben wurde als hätten die Soldaten alle volles Leben.

Es macht meines Erachtens nach deswegen kaum Sinn, einem einzelnen Soldaten Lebenspunkte abzuziehen, weil das Spiel sich für die Gesundheit eines einzelnen Soldaten nicht interessiert.

____________________
LUA_ERRSYNTAX: [string "?"]:1: `=' expected near `<eof>'

Mordred
#3
28.02.2010 21:39
Beiträge: 939

Ich glaub auch, dass die Soldaten nur ein "Anhängsel" des Hauptmannes sind. sie werden ja auch in 8-7-6-5-4-3-2-1 reihenfolge umgebracht, egal was ist.
Aber die Funktion ist klasse, aber geht das auch irgendwie kürzer? Ist ja schon ein starkes Stück
Aber wirklich was dazu sagen kann ich nichts
Kann man "Hurtentity(...)" nicht umbauen mit GetMaxHealth
oder ähnlichem?

Noigi
#4
28.02.2010 21:49
Beiträge: 772

Es ist gut möglich, dass bei den internen "echten" Kämpfen die Soldaten-HP ignoriert wird (wenn man sich die testweise anzeigen lässt ist sie immer auf 150, das meintest du wahrscheinlich).
Innerhalb der Hurt-Mechanik funktioniert die Soldaten-HP aber ganz normal. Ich kann zB einen Trupp Bastardschwerter in 28 50er-Schritten vollständig umlegen.

Wenn man jetzt nur geringen Schaden mit HurtEntitySAVE zufügt kann der tatsächliche Effekt für den "Killspeed" unter dem gewünschten Effekt liegen, sobald der Schaden reicht um Soldaten zu töten gibt es sich aber nicht viel.

Noigi
#5
28.02.2010 21:51
Beiträge: 772

Zitat von Mordred:
Ich glaub auch, dass die Soldaten nur ein "Anhängsel" des Hauptmannes sind. sie werden ja auch in 8-7-6-5-4-3-2-1 reihenfolge umgebracht, egal was ist.
Aber die Funktion ist klasse, aber geht das auch irgendwie kürzer? Ist ja schon ein starkes Stück
Aber wirklich was dazu sagen kann ich nichts
Kann man "Hurtentity(...)" nicht umbauen mit GetMaxHealth
oder ähnlichem?


Jau, Anhängsel sind sie auf jeden Fall! Die Reihenfolge halte ich auch brav ein.

Kürzer geht natürlich immer, wenn man die ganzen Eingabeabfragen weglässt. Das erfordert dann aber mehr Disziplin bei der Bedienung, falscher Input sorgt dann wieder für Abstürze.

nevermind
Siedler Map Source Admin (Web)
#6
28.02.2010 23:18
Beiträge: 483

Zitat von Noigi:
Innerhalb der Hurt-Mechanik funktioniert die Soldaten-HP aber ganz normal.



Ja, aber das bringt dir auch nur was, wenn die Soldaten nicht anderweitig in einem Gefecht verwickelt sind. Und sofern sie das nicht sind, würde ich behaupten, dass man sie auch einzeln mit SetHealth(xxx, 0) ohne den Code und ohne Abstürze "aussortieren" kann.

Warum ich überhaupt was dazu sage: Ich habe selbst mit dem Thema gekämpft und irgendwann resigniert, weil es keine vernünftige Lösung gibt.

____________________
LUA_ERRSYNTAX: [string "?"]:1: `=' expected near `<eof>'

Dieser Beitrag wurde von nevermind am 28.02.2010 um 23:29 editiert.

Mordred
#7
01.03.2010 10:49
Beiträge: 939

Wie kann man eigentlich Entities stärker machen,
nicht nur die GUI verändern?

Noigi
#8
01.03.2010 14:11
Beiträge: 772

Zitat von nevermind:

Zitat von Noigi:
Innerhalb der Hurt-Mechanik funktioniert die Soldaten-HP aber ganz normal.



Ja, aber das bringt dir auch nur was, wenn die Soldaten nicht anderweitig in einem Gefecht verwickelt sind. Und sofern sie das nicht sind, würde ich behaupten, dass man sie auch einzeln mit SetHealth(xxx, 0) ohne den Code und ohne Abstürze "aussortieren" kann.

Warum ich überhaupt was dazu sage: Ich habe selbst mit dem Thema gekämpft und irgendwann resigniert, weil es keine vernünftige Lösung gibt.


Ach ja, ich erinnere mich.
Für eine reine RPG-Map würde mir spontan die Lösung einfallen, die spielinterne Schadensverteilung komplett auszuschalten (Golobal Invulnerability) und alles manuell zu machen. Das könnte natürlich auch wieder Probleme aufwerfen, die ich jetzt noch nicht kenne. Jedenfalls wäre die Schadensverteilung dann wieder konsistent.

Meine Funktion ist jedenfalls eher für Skriptspielereien wie Sprengfallen, Giftgebiete oder extrem starke Einheiten gedacht, bei denen einen dann die Auswahl der richtigen Todesopfer abgenommen wird, und wo 100 Punkte Schaden mehr oder weniger nicht ins Gewicht fallen.


Zitat von Mordred:
Wie kann man eigentlich Entities stärker machen,
nicht nur die GUI verändern?


Kurze Antwort: gar nicht
Lange Antwort: Mit einer Kombination aus GUI-Mod und manuellem "hurten" in einem Trigger-Callback.
Das wird dann bei Soldatengruppen wie angesprochen nicht exakt den gewünschten Effekt haben, bei hohen Schadenszahlen ist der Unterschied aber gering.

DickeWatschnBaby = function()
	local att = Event.GetEntityID1();
	local tar = Event.GetEntityID2();
	if att == GetEntityId("schwarzenegger") then
		local bonusdmg = Logic.GetEntityDamage(att)*10;
		HurtEntitySAVE(tar, bonusdmg);
	end
end
Trigger.RequestTrigger( Events.LOGIC_EVENT_ENTITY_HURT_ENTITY, "", "DickeWatschnBaby", 1);

warrior1024
#9
01.03.2010 15:23
Beiträge: 345

Zitat von Mordred:
Wie kann man eigentlich Entities stärker machen,
nicht nur die GUI verändern?


Die Idee hast du von meinem GUI-Mod, ohne GUI-Funktionen umzuschreiben, richtig?

Zitat von Noigi:

Lange Antwort: Mit einer Kombination aus GUI-Mod und manuellem "hurten" in einem Trigger-Callback.
Das wird dann bei Soldatengruppen wie angesprochen nicht exakt den gewünschten Effekt haben, bei hohen Schadenszahlen ist der Unterschied aber gering.


So veränderst du nur Angriffswert, aber die Lebenspunkte sind das wirklich Schwierige. Die Selektions-Lebenspunkte(die, die bei der Selektion bei ANG und DEFF angezeigt werden) sind einfach zu modden(LOGIC-Funktion umschreiben), aber der LP-Balken, wenn man mit der Maus über die Einheit fährt, ist wirklich schwierig. Das Superfighterskript rückt noch genug Infos zu dem Thema raus.

Wieso ist das Skript so lang? Es müsste doch reichen, wenn man überprüft, ob der angegebene Krieger Leader ist. Wenn ja, dann suche den nächstbesten Soldat des Leaders und schädige den. Oder muss man da noch was beachten?

Warrior1024

____________________
"Banken machen keine Fehlentscheidungen! Haben Euch das Eure Eltern nicht beigebracht?"
- Bankier Samael Silren, Enderal

Mordred
#10
01.03.2010 16:27
Beiträge: 939

@warrior1024

Siedler_Team
#11
02.03.2010 13:04
Beiträge: 847

Kurz mein Senf und meine Gedankengänge dazu.

@Noigi:
Wenn ich Dich richtig verstehe, möchtest Du den Schaden, den eine Entity austeilen kann, verändern?

Wenn ja, soll es sich dabei lediglich um Heros oder auch um Armeen handeln, deren Schadenswerte verändert werden sollen?

Mein Grundgedanke bei meiner Fragestellung ist:

HITPOINTS! und die halt verändern.

...und dafür gibt es schon Muster. Klappt auch und wurde bereits in einer der Team-Karten eingesetzt

____________________
Wer altes Wissen ehrt und neues Wissen erlangt, ist bereit, ein Lehrer zu sein. ( -Konfuzius- )

Noigi
#12
02.03.2010 20:55
Beiträge: 772

Zitat von Siedler_Team:
Wieso ist das Skript so lang? Es müsste doch reichen, wenn man überprüft, ob der angegebene Krieger Leader ist. Wenn ja, dann suche den nächstbesten Soldat des Leaders und schädige den. Oder muss man da noch was beachten?

Warrior1024


Alles nur Comfort!
Ich will halt, dass man nichts bei der Eingabe beachten muss. Man kann sich zB Entities per Area-Check besorgen und denen Schaden zufügen, ohne irgendeine Fallunterscheidung vorher zu machen. Wahrscheinlich ginge auch das kürzer, aber das halte ich nicht für nötig.

Zitat von Siedler_Team:
Kurz mein Senf und meine Gedankengänge dazu.

@Noigi:
Wenn ich Dich richtig verstehe, möchtest Du den Schaden, den eine Entity austeilen kann, verändern?

Wenn ja, soll es sich dabei lediglich um Heros oder auch um Armeen handeln, deren Schadenswerte verändert werden sollen?

Mein Grundgedanke bei meiner Fragestellung ist:

HITPOINTS! und die halt verändern.

...und dafür gibt es schon Muster. Klappt auch und wurde bereits in einer der Team-Karten eingesetzt


Man kann Lebenspunkte verändern?! (also echt, nicht nur die Anzeige?)
Welche Map meinst du?

Siedler_Team
#13
02.03.2010 23:01
Beiträge: 847

Zitat von Noigi:

Zitat von Siedler_Team:
Wieso ist das Skript so lang? Es müsste doch reichen, wenn man überprüft, ob der angegebene Krieger Leader ist. Wenn ja, dann suche den nächstbesten Soldat des Leaders und schädige den. Oder muss man da noch was beachten?

Warrior1024



Nö, nö Noigi, das waren nicht die Worte des Siedler Teams.
Du hast warrior1024 zitiert!

Zitat von Noigi:

Man kann Lebenspunkte verändern?! (also echt, nicht nur die Anzeige?)


Hab ich nicht geschrieben Noigi. Ich habe geschrieben, man kann die HITPOINTS verändern, also den Schaden der pro hit zugefügt wird.

Zitat von Noigi:

Welche Map meinst du?


Die ist zu Zeiten, als es hier mal hoch herging, von mir gelöscht worden. Wird aber aufgearbeitet und kommt dann wieder rauf. Die Map nennt sich "Familienbande"

Im Prinzip war/ist diese Funktion eine "leichte" Abwandlung von Tenjis "Superfighter - Version 2.00"

( ...nachträglich vielen Dank und unsere Hochachtung an Tenji, Chromix, Robert Schmitz und nevermind für diese Wahnsinnsfunktion! )

http://www.siedler-games.de/si...functions:create_superfighters

____________________
Wer altes Wissen ehrt und neues Wissen erlangt, ist bereit, ein Lehrer zu sein. ( -Konfuzius- )

nevermind
Siedler Map Source Admin (Web)
#14
02.03.2010 23:12
Beiträge: 483

Und der neue Superfighter Code scheint so ziemlich auf dem zu basieren, was ich oben verlinkt habe
Und die Lösung ist - zumindest meiner Meinung nach - nicht sehr optimal.

____________________
LUA_ERRSYNTAX: [string "?"]:1: `=' expected near `<eof>'

Noigi
#15
02.03.2010 23:35
Beiträge: 772

Zitat von Siedler_Team:
Nö, nö Noigi, das waren nicht die Worte des Siedler Teams.
Du hast warrior1024 zitiert!


Richtig!
Man sollte bei Copy&Paste das Anpassen nicht vergessen.

Zitat von Siedler_Team:

Zitat von Noigi:

Man kann Lebenspunkte verändern?! (also echt, nicht nur die Anzeige?)


Hab ich nicht geschrieben Noigi. Ich habe geschrieben, man kann die HITPOINTS verändern, also den Schaden der pro hit zugefügt wird.


Ach so - Hitpoints (kurz HP) ist ja auch eine gängige Abkürzung für Lebenspunkte.

Zitat von Siedler_Team:

Zitat von Noigi:

Welche Map meinst du?


Die ist zu Zeiten, als es hier mal hoch herging, von mir gelöscht worden. Wird aber aufgearbeitet und kommt dann wieder rauf. Die Map nennt sich "Familienbande"

Im Prinzip war/ist diese Funktion eine "leichte" Abwandlung von Tenjis "Superfighter - Version 2.00"

( ...nachträglich vielen Dank und unsere Hochachtung an Tenji, Chromix, Robert Schmitz und nevermind für diese Wahnsinnsfunktion! )

http://www.siedler-games.de/si...functions:create_superfighters


Hmm, mal sehen ob ich die Map noch von damals rumliegen habe.
Bei der von dir verlinkten Version wird auf den ersten Blick am "spielinternen" Schaden aber nichts gedreht? Der einzige Extraschaden ist die Bonusattacke über den Entlassen-Button, die im Grunde das gleiche macht wie meine Funktion.

Seiten: 1

SiteEngine v1.5.0 by nevermind, ©2005-2007
Design by SpiderFive (www.siedler-games.de) - English translation by juja

Impressum