nicht Savesicher
» Siedler Map Source Forum » Siedler DEdK Script Forum » nicht Savesicher
Seiten: 1
Peter-FS
|
#1 14.07.2017 14:40 Beiträge: 1086 |
nicht Savesicher
Hi,
mein Problem ist, dass nach dem Reload die Abfragen, ob ein Gebäude gebaut, bzw. zerstört wurde, nicht mehr ausgeführt wird.
Solange nicht gespeichert und neu geladen wird, funktioniert alles bestens. d.h. vermutlich werden die übergebenen Daten nicht gespeichert?
--Aufruf mit z.B. SetupDestroy_Haus(4, Entities.PB_Farm1, Entities.PU_Farmer) function SetupDestroy_Haus(_nr, _type, _typeReplace, _AreaSize) SetupGebaut(_nr, _type, _typeReplace, _AreaSize) SetupDestroy{ Target = "h".._nr, Callback = function() xWorker[_nr].Aktion = true --beendet den npc local p = GetPosition("haus".._nr) worker[_nr].EffectId = Logic.CreateEffect(GGL_Effects.FXTerrainPointer, p.X, p.Y, 2) --mittelpunkt effekt if _typeReplace ~= nil then --wenn nil, dann wird ein serf erstellt m_TryMoveEntity("worker".._nr, "serf"..GetRandom(1,7).."_pos", 400) end end, } end function SetupGebaut(_nr, _type, _typeReplace, _AreaSize) if _AreaSize == nil then _AreaSize = 800 end _gebaut = _gebaut or 0 bauquest = { EntityTypes = {{_type,1}, }, AreaPos = "haus".._nr, AreaSize = _AreaSize, Any = nil, Callback = function() if gvMission._winterAktiv == true then Logic.DestroyEffect(worker[_nr].EffectId) worker[_nr].EffectId = 100 --damit kein Hinweis mehr erscheint _gebaut = _gebaut +1 --wenn alle gebäude gebaut, dann kann das HQ gebaut werden Bauplan_Update() if _gebaut == 28 then _aufgabenErledigt = true Message("Du hast alle Gebäude der Bevölkerung gebaut. Besuche jetzt den Bürgermeister") elseif _gebaut == 29 then --HQ gebaut DisableQuestInformation() SetupDestroy_SB() --prüfen ob sperre gesprengt _gebaut = 0 StartQuest4_1() end if _typeReplace ~= nil then -- ReplaceEntity("worker".._nr, _typeReplace) aktId = ChangePlayer("worker".._nr,1) Logic.PlayerReAttachAllWorker(1) --fehlende arbeiter im gebäude erstellen und neu zuordnen local BuildingID = Logic.GetSettlersWorkBuilding(aktId) local MaxNumberOfworkers = Logic.GetMaxNumWorkersInBuilding(BuildingID) local CurrentMaxNumbersOfWorkers = Logic.GetBuildingWorkPlaceUsage(BuildingID) --Message("B-Id: "..BuildingID.." / max worker: "..MaxNumberOfworkers.." / Current Workers: "..CurrentMaxNumbersOfWorkers) for ix = 1,MaxNumberOfworkers - CurrentMaxNumbersOfWorkers do CreateEntity(1, _typeReplace, GetPosition( "serf"..ix.."_pos"), nil) Logic.PlayerReAttachAllWorker(1) end end elseif gvMission._sommerAktiv == true then --hier müssen Brunnen gebaut werden, dann werden alle Gebäude in der umgebung dem spieler übergeben worker[_nr].EffectId = 100 --damit kein Hinweis mehr erscheint xWorker[_nr].Aktion = true --beendet den npc _gebaut = _gebaut +1 Bauplan_Update() if _gebaut ==6 then DisableQuestInformation() end if _typeReplace == nil then local _punkt = GetPosition("haus".._nr) local data = {Logic.GetPlayerEntitiesInArea(8,0, _punkt.X, _punkt.Y, _AreaSize, 16)} for ix = 2, data[1]+1 do ChangePlayer(data[ix],1) end Logic.PlayerReAttachAllWorker(1) elseif _typeReplace == "hunter" then DestroyEntity("worker33") local _pos = GetPosition("vorhaus33") Logic.CreateEntity(Entities.PU_Hero10,_pos.X,_pos.Y,0,1) StartPlayer2() --ermöglicht den zugang zum nächsten Gegner elseif _typeReplace == "scout" then DestroyEntity("worker35") local _pos = GetPosition("vorhaus35") Logic.CreateEntity(Entities.PU_Scout,_pos.X,_pos.Y,0,1) elseif _typeReplace == "foerster" then local _pos = GetPosition("vorhaus34") CreateEntity(8,Entities.CU_Hermit,_pos,"waldi") DestroyEntity("worker34") StartCountdown(5,Startgaertner1,false) end end end, }; SetupEstablish( bauquest ) end
____________________
Man muss nicht alles wissen, man muss nur wissen wo es steht!
mcb
|
#2 14.07.2017 18:46 Beiträge: 1472 |
Das Problem sind die upvalues. Kleines Beispiel:
function foo() local upvalue = 5 local function bar() upvalue = upvalue + 10 end end
Die innere Funktion bar hat zugriff auf die lokale variable upvalue der funktion foo. Siedler speichert diese upvalues aber nicht, nach dem laden funktioniert also nichts mehr.
Dasselbe passiert bei deinen Callbacks. Die Lösung ist relativ einfach: Keine upvalues verwenden. Hier kannst du einfach alle benötigten Variablen im table ablegen, dieses table wird dem callback als erster Parameter übergeben.
Peter-FS
|
#3 15.07.2017 00:10 Beiträge: 1086 |
Klappt irgendwie trotzdem nicht.
Ich habe z.B. 28 Häuser h1-h28 und übergebe der Funktion die _nr.
und verschiedene andere Parameter.
Wie meinst du das mit dem table?
So geht es nicht, da wird in allen Funktionen die gleiche Nr verwendet.
function SetupDestroy_Haus(_nr, _type, _typeReplace, _AreaSize) xParameter1={} xParameter1 = {xNr = _nr, xType =_type, xTypeReplace =_typeReplace, xAreaSize=_AreaSize } SetupDestroy{ xParameter1, Target = "h"..xParameter1.xNr, Callback = function() xWorker[xParameter1.xNr].Aktion = true --beendet den npc local p = GetPosition("haus"..xParameter1.xNr) worker[xParameter1.xNr].EffectId = Logic.CreateEffect(GGL_Effects.FXTerrainPointer, p.X, p.Y, 2) --mittelpunkt effekt if xParameter1.xTypeReplace ~= nil then --wenn nil, dann wird ein serf erstellt m_TryMoveEntity("worker"..xParameter1.xNr, "serf"..GetRandom(1,7).."_pos", 400) end end, } end
____________________
Man muss nicht alles wissen, man muss nur wissen wo es steht!
mcb
|
#4 15.07.2017 01:19 Beiträge: 1472 |
Jetzt legst du ein globales table an, das bei jedem Aufruf überschrieben wird.
Ich meinte das so:
function SetupDestroy_Haus(_nr, _type, _typeReplace, _AreaSize) SetupDestroy{ xNr = _nr, xType =_type, xTypeReplace =_typeReplace, xAreaSize=_AreaSize, Target = "h".._nr, Callback = function(xParameter1) xWorker[xParameter1.xNr].Aktion = true --beendet den npc local p = GetPosition("haus"..xParameter1.xNr) worker[xParameter1.xNr].EffectId = Logic.CreateEffect(GGL_Effects.FXTerrainPointer, p.X, p.Y, 2) --mittelpunkt effekt if xParameter1.xTypeReplace ~= nil then --wenn nil, dann wird ein serf erstellt m_TryMoveEntity("worker"..xParameter1.xNr, "serf"..GetRandom(1,7).."_pos", 400) end end, } end
Peter-FS
|
#5 15.07.2017 16:13 Beiträge: 1086 |
Geht noch nicht
Das funktioniert leider so auch noch nicht richtig.
Folgendes Problem:
xNr = _nr, xType =_type, xTypeReplace =_typeReplace, xAreaSize=_AreaSize,
im Debugger ist zu sehen, dass die Werte nicht zugewiesen werden.
xNr ist nil, obwohl _nr einen Wert hat.
Wenn ich im Debugmodus die Funktion (xNr = _nr) markiere, hat xNr anschließend den richtigen Wert.
Zeigt sich auch so beim Spielen der Map!
Was mir jetzt noch dazu einfällt, wäre ein globales Table mit den Werten der 28 Häuser erstellen. Das könnte ich dann für SetupDestroy und SetupEstablish verwenden.
Verstehen kann ich es aber immer noch nicht wirklich, warum das so nicht geht.
Noch jemand Ideen dazu?
____________________
Man muss nicht alles wissen, man muss nur wissen wo es steht!
mcb
|
#6 15.07.2017 16:59 Beiträge: 1472 |
Die Variablen werden auch in einem table gespeichert. Also ist der Wert von _G.xNr nil, weil der nicht benutzt wird. Gespeichert wird dieser Wert in dem table, das du SetupDestroy übergibst (praktisch als zusätzliche Parameter).
Wird dann der Callback aufgerufen, bekommt er dieses table als erstes Argument übergeben und man kommt savegamesicher wieder an die Variablen dran.
(Intern wird das auch nur in einem globalen table gespeichert:
DataTable[_Index].Callback(DataTable[_Index])
)
(Ich weiß schon, warum ich meine Jobs immer selbst schreibe, diese Quest-Funktionen sind ziemlich blöd gemacht )
Peter-FS
|
#7 15.07.2017 18:27 Beiträge: 1086 |
SetupDestroy und SetupEstablish funktionieren eigentlich immer sehr gut.
Ich könnte ja auch 28 eigene Funktionen erstellen, dann würde es auch problemlos funktionieren.
Es geht nur nicht, da ich die Parameter übergebe.
____________________
Man muss nicht alles wissen, man muss nur wissen wo es steht!
Peter-FS
|
#9 15.07.2017 23:26 Beiträge: 1086 |
Das hilft mir und meinem momentanen Problem aber nicht.
Die Parameter, die ich übergebe, ändern sich 28 mal bzw. ist ja eigentlich egal wie oft. Diese Werte brauche ich in der Funktion bzw. im Table Save sicher und nicht, das diese erst im Callback zugewiesen werden! Da wird dann der falsche Wert abgefragt.
____________________
Man muss nicht alles wissen, man muss nur wissen wo es steht!
mcb
|
#10 16.07.2017 00:12 Beiträge: 1472 |
Sie werden eben nicht erst im Callback zugewiesen. Sie werden zugewiesen, wenn du das table erstellst, mit dem du SetupEstablish aufrufst. Da wird dieses table gespeichert und später als Parameter übergeben.
local t = { foo = 1, --hier im table gespeichert, ausgeführt wenn das table erstellt wird Callback = function(t) Message(t.foo) --hier zugriff auf den parameter t, ausgeführt wenn der callback aufgerufen wird end, }
Peter-FS
|
#11 17.07.2017 09:30 Beiträge: 1086 |
Das ist aber nicht ganz das, was ich habe! So mag es ja funktionieren.
Das Problem sind die Parameter, die übergeben werden. Evtl. nicht ByVal sondern ByRef???
Rufe das Ganze z.B. 3x mit verschiedenen Werten auf und du bekommst im Callback 3x den gleichen Wert.
function Irgendwas(_nr) local t = { foo = _nr, --hier im table gespeichert, ausgeführt wenn das table erstellt wird Callback = function(t) Message(t.foo) --hier zugriff auf den parameter t, ausgeführt wenn der callback aufgerufen wird end, end }
____________________
Man muss nicht alles wissen, man muss nur wissen wo es steht!
mcb
|
#12 17.07.2017 12:26 Beiträge: 1472 |
In Lua sind das meiste Referenzen. number und bool sind auf jeden Fall Werte, nil existiert nur ein mal (macht also keinen Unterschied) der Rest sind Referenzen (insbesondere tables, strings und funktionen).
Wichtig ist das aber nur bei tables und funktionen mit upvalues (und userdata/coroutines, die sind aber in Siedler-Lua selten).
totalwarANGEL
|
#13 18.07.2017 18:49 Beiträge: 2123 |
Also, ich kann mir nicht erklären, wieso das nicht funktionieren sollte. Habe das schon 100 Mal so gemacht und so viel Unterschied kann zwischen AeK und DEdK auch nicht sein.
Oder ist es bei mir schon wieder zu lange her?
____________________
Die Welt ist arschlochförmig und wir leben in der Mitte.
Peter-FS
|
#14 19.07.2017 07:14 Beiträge: 1086 |
Also ausser in Lua habe ich mit solchen Funktionen überhaupt keine Probleme. Ok, die werden allerdings auch nicht gespeichert und wieder aufgerufen. Hmmmm????
Na ja, jetzt halt für jeden Aufruf eine eigene Funktion.
Asser es hat noch jemand eine Idee!
____________________
Man muss nicht alles wissen, man muss nur wissen wo es steht!
mcb
|
#15 19.07.2017 12:13 Beiträge: 1472 |
Also eigentlich müsste das funktionieren. Kannst du noch mal das entsprechende Script posten?
Ansonsten würde ich dir Vorschlagen, selber einen Job zu schreiben und dem Parameter zu übergeben (hast du einen Trigger-Fix?) . Falls du wirklich bei den Quest-Funktionen bleiben willst, hab ich auch noch ein Script, das Mithilfe von metatables zusätzliche Parameter beim Aufruf einer Funktion einfügt.
Settlerman
|
#16 04.08.2017 12:50 Beiträge: 238 |
Frage zu den Upvalues:
Wenn ich mir eine Funktion schreibe, der einen Parameter übergebe und innerhalb der Funktion einen Trigger starte welcher den Parameter verwendet und auch überschreibt, wird das dann auch nicht gespeichert?
mcb
|
#17 04.08.2017 13:11 Beiträge: 1472 |
Ja, wird auch nicht gespeichert. parameter sind nichts anderes als lokale Variablen, die beim Funktionsaufruf initialisiert werden.
Wenn du einen Trigger-Fix hast kannst du ein table benutzen, um einen ähnlichen Effekt zu erzielen:
function foo(bar) StartSimpleJob(function(t) Message(t.bar) t.bar = t.bar + 1 end, {bar = bar}) end
Settlerman
|
#18 04.08.2017 13:21 Beiträge: 238 |
Das ganze läuft bei mir momentan so:
function CreateBush(_position) -- erstellt einen Busch an der gegebenen Position local EntityID = Logic.CreateEntity(Entities.XD_Bush1, _position.X, _position.Y); -- Abfrage der Jahreszeiten, Trigger.RequestTrigger( Events.LOGIC_EVENT_EVERY_SECOND, nil, function() if Spring == true then local EntityID = ReplaceEntity(EntityID, Entities.XD_Bush1); else if Summer == true then local EntityID = ReplaceEntity(EntityID,Entities.XD_Bush4); else if Autumn == true then local EntityID = ReplaceEntity(EntityID,Entities.XD_BushMoor2); else if Winter == true then local EntityID = ReplaceEntity(EntityID, Entities.XD_DeadBush1); end end end end end, 1 , nil, nil) end
Also muss ich die einzelnen Positionen und die IDs in einem table speichern um sie nach dem Laden weiter verwenden zu können?
mcb
|
#19 04.08.2017 13:49 Beiträge: 1472 |
Ja. Es gäbe aber für diesen Fall auch noch bessere Möglichkeiten:
1) Aufruf der Funktion nach jedem ändern der Variablen, spart jede menge Rechenzeit (ich würd auch die 4 Variablen durch eine ersetzen).
2) Nur das Model ändern, dann muss kein neues Entity erstellt werden.
Die lassen sich sogar beide kombinieren
Settlerman
|
#20 04.08.2017 14:07 Beiträge: 238 |
Die am Anfang definierte Variable EntityID würde das Speichern und laden aber überleben, wenn sie nicht im Trigger überschrieben wird, oder?
mcb
|
#21 04.08.2017 14:32 Beiträge: 1472 |
Nein, würde sie nicht. Um ein wie auch immer geartetes table wirst du wohl kaum drumherum kommen (Außer du startest für jedes Entity einen Job und übergibst die id als Parameter, die du dann aber nicht ändern kannst).
Seiten: 1