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