DVS_AttractionLimit
» Siedler Map Source Forum » Siedler DEdK Script Forum » DVS_AttractionLimit
Seiten: 1
Zedeg
|
#1 12.12.2014 21:34 Beiträge: 428 |
DVS_AttractionLimit
Nachdem Ludwig die Frage nach einer komfortablen Lösung für das Siedlungslimit-Problem gestellt hat, habe ich im Nachhinein folgendes Skript entworfen. Naja, der Rest steht bereits als Kommentar im Skript. Ausführliches Testen erwünscht.
--[[ DVS_AttractionLimit Version 1.4 Script by Zedeg Mit diesen Komfort-Funktionen ist es möglich, das Siedlungslimit komplett per Skript zu bestimmen. Folgende Funktionen werden benötigt: Funktion : DVS_AttractionLimit_SetUp Beschreibung: Muss vor allem anderen aufgerufen werden; Leitet alles nötige ein. Parameter : Ort, an dem die unsichtbaren Dorfzentren und Soldaten erscheinen(string); Sollte im schwarzen Randbereich liegen. Funktion : GUIUpdate_Population Beschreibung: Wird automatisch aufgerufen; Überprüft die veränderte Einwohneranzeige. Funktion : GameCallback_OnBuildingConstructionComplete Beschreibung: Wird automatisch aufgerufen; Überprüft, ob ein DZ gebaut wurde. Funktion : GameCallback_OnBuildingUpgradeComplete Beschreibung: Wird automatisch aufgerufen; Überprüft, ein DZ ausgebaut wurde. Funktion : DVS_AttractionLimit_Increase Beschreibung: Erhöht die Siedlungsplätze zu den aktuellen. Parameter : Anzahl der hinzugefügten Sidlungsplätze(number). Funktion : DVS_AttractionLimit_Set Beschreibung: Setzt die Höhe des Siedlungslimits. Parameter : Höhe des Siedlungslimits(number). Funktion : DVS_AttractionLimit_CheckTables Beschreibung: Wird automatisch aufgerufen; Überprüft, ob überflüssige Dorfzentren und Soldaten vorhanden sind und zerstört diese dann. Funktion : DVS_AttractionLimit_GetUsage Beschreibung: Gibt die genutzten Sitplätze ohne die unsichtbaren Soldaten zurück. Rückgabe : benutzte Sitzplätze(number) Funktion : DVS_AttractionLimit_GetFreePlaces Beschreibung: Gibt die freien S(number)itzplätze zurück. Rückgabe : freie Sitzplätze Funktion : DVS_AttractionLimit_GetAL Beschreibung: Gibt das Siedlungslimit zurück. Rückgabe : Siedlungslimit(number) Funktion : DVS_AttractionLimit_GameCallback_GUI_SelectionChanged_New Beschreibung: Wird automatisch aufgerufen; Überprüft, ob ein unsichtbares Dorfzentrum per [Strg]+[D] selektiert wurde und deselektiert dann. Funktion : DVS_AttractionLimit_GetVC Beschreibung: Gibt die Anzahl der unsichtbaren Dorfzentren zurück. Rückgabe : unsichtbare Dorfzentren(number) Funktion : DVS_AttractionLimit_GetIV Beschreibung: Gibt die Anzahl der unsichtbaren Soldaten zurück. Rückgabe : unsichtbare Soldaten(number) Funktion : DVS_AttractionLimit_IsVCDestroyed Beschreibung: Wird automatisch aufgerufen; Überprüft, ein DZ abgerissen wurde. --]] function DVS_AttractionLimit_SetUp(_spawnpoint) assert(type(_spawnpoint) == "string", "AttractionLimit_SetUp:ERROR! Spawnpoint must be a string!") DVS_AttractionMemory = { AttractionLimit = -1, Spawnpoint = _spawnpoint, VillageCenters = {}, Invisibles = {}, } local vc1 = Logic.GetNumberOfEntitiesOfTypeOfPlayer(1, Entities.PB_VillageCenter1)*75 local vc2 = Logic.GetNumberOfEntitiesOfTypeOfPlayer(1, Entities.PB_VillageCenter2)*100 local vc3 = Logic.GetNumberOfEntitiesOfTypeOfPlayer(1, Entities.PB_VillageCenter3)*125 local vc = vc1+vc2+vc3 DVS_AttractionLimit_GameCallback_GUI_SelectionChanged_Old = GameCallback_GUI_SelectionChanged GameCallback_GUI_SelectionChanged = DVS_AttractionLimit_GameCallback_GUI_SelectionChanged_New DVS_AttractionLimit_GameCallback_OnBuildingConstructionComplete_Old = GameCallback_OnBuildingConstructionComplete GameCallback_OnBuildingConstructionComplete = DVS_AttractionLimit_GameCallback_OnBuildingConstructionComplete_New DVS_AttractionLimit_GameCallback_OnBuildingUpgradeComplete_Old = GameCallback_OnBuildingUpgradeComplete GameCallback_OnBuildingUpgradeComplete = DVS_AttractionLimit_GameCallback_OnBuildingUpgradeComplete_New Trigger.RequestTrigger(Events.LOGIC_EVENT_ENTITY_DESTROYED, "", "DVS_AttractionLimit_IsVCDestroyed", 1) GUIUpdate_Population = function() local SlotsUsed = DVS_AttractionLimit_GetUsage() local SlotLimit = DVS_AttractionLimit_GetAL() local String if SlotsUsed >= SlotLimit and SlotsUsed ~= 0 then String = "@color:255,120,120,255 " else String = "@color:114,134,124,255 " end String = String .. "@ra " .. SlotsUsed .. "/" .. SlotLimit XGUIEng.SetText("PopulationPlaces", String) end DVS_AttractionMemory.AttractionLimit = vc end function DVS_AttractionLimit_GameCallback_OnBuildingUpgradeComplete_New(_oldId, _newId) DVS_AttractionLimit_GameCallback_OnBuildingUpgradeComplete_Old(_oldId, _newId) local buildingType = Logic.GetEntityTypeName(Logic.GetEntityType(_newId)) if buildingType == "PB_VillageCenter2" and GetPlayer(_newId) == GUI.GetPlayerID() then DVS_AttractionMemory.AttractionLimit = DVS_AttractionMemory.AttractionLimit+100 elseif buildingType == "PB_VillageCenter3" and GetPlayer(_newId) == GUI.GetPlayerID() then DVS_AttractionMemory.AttractionLimit = DVS_AttractionMemory.AttractionLimit+125 end end function DVS_AttractionLimit_GameCallback_OnBuildingConstructionComplete_New(_entity, _player) DVS_AttractionLimit_GameCallback_OnBuildingConstructionComplete_Old(_entity, _player) local buildingType = Logic.GetEntityTypeName(Logic.GetEntityType(_entity)) if buildingType == "PB_VillageCenter1" and _player == GUI.GetPlayerID() then DVS_AttractionMemory.AttractionLimit = DVS_AttractionMemory.AttractionLimit+75 end end function DVS_AttractionLimit_Increase(_value) assert(type(_value) == "number", "AttractionLimit_Increase:ERROR! Value must be a number!") local oldAL = DVS_AttractionLimit_GetAL() local newAL = DVS_AttractionLimit_GetAL()+_value _value = math.floor(_value+0.5) if DVS_AttractionLimit_GetAL() == -1 then oldAL = Logic.GetPlayerAttractionLimit(GUI.GetPlayerID()) newAL = Logic.GetPlayerAttractionLimit(GUI.GetPlayerID())+_value end if _value >= 1 then local requiredVC = math.ceil(_value/75) local requiredIV = requiredVC*75-_value for VC = 1, requiredVC do local position = GetPosition(DVS_AttractionMemory.Spawnpoint) local idVC = Logic.CreateEntity(Entities.PB_VillageCenter1, position.X, position.Y, 0.00, GUI.GetPlayerID()) Logic.SetEntityName(idVC, "VC_ID_"..idVC) Logic.SetEntityScriptingValue(idVC, -30, 257) MakeInvulnerable(idVC) table.insert(DVS_AttractionMemory.VillageCenters, "VC_ID_"..idVC) end for IV = 1, requiredIV do local position = GetPosition(DVS_AttractionMemory.Spawnpoint) local idIV = Logic.CreateEntity(Entities.CU_BlackKnight_SoldierSword3, position.X, position.Y, 0.00, GUI.GetPlayerID()) Logic.SetEntityName(idIV, "IV_ID_"..idIV) Logic.SetEntityScriptingValue(idIV, -30, 257) MakeInvulnerable(idIV) table.insert(DVS_AttractionMemory.Invisibles, "IV_ID_"..idIV) end elseif _value < 0 then for IV = 1, _value*-1 do local position = GetPosition(DVS_AttractionMemory.Spawnpoint) local idIV = Logic.CreateEntity(Entities.CU_BlackKnight_SoldierSword3, position.X, position.Y, 0.00, GUI.GetPlayerID()) Logic.SetEntityName(idIV, "IV_ID_"..idIV) Logic.SetEntityScriptingValue(idIV, -30, 257) MakeInvulnerable(idIV) table.insert(DVS_AttractionMemory.Invisibles, "IV_ID_"..idIV) end end if newAL < 0 then newAL = 0 end DVS_AttractionLimit_CheckTables() DVS_AttractionMemory.AttractionLimit = newAL if DVS_AttractionMemory.AttractionLimit < 0 then DVS_AttractionMemory.AttractionLimit = 0 end end function DVS_AttractionLimit_Set(_value) assert(type(_value) == "number", "AttractionLimit_Set:ERROR! Value must be a number!") local oldAL = DVS_AttractionLimit_GetAL() local newAL = _value local numberOfVC = DVS_AttractionLimit_GetVC() local numberOfIV = DVS_AttractionLimit_GetIV() _value = math.floor(_value+0.5) if DVS_AttractionLimit_GetAL() == -1 then oldAL = Logic.GetPlayerAttractionLimit(GUI.GetPlayerID()) newAL = _value end if newAL > oldAL then local requiredPlaces = newAL-oldAL local requiredVC = math.ceil(requiredPlaces/75) local requiredIV = (requiredVC*75)-requiredPlaces for VC = 1, requiredVC do local position = GetPosition(DVS_AttractionMemory.Spawnpoint) local idVC = Logic.CreateEntity(Entities.PB_VillageCenter1, position.X, position.Y, 0.00, GUI.GetPlayerID()) Logic.SetEntityName(idVC, "VC_ID_"..idVC) Logic.SetEntityScriptingValue(idVC, -30, 257) MakeInvulnerable(idVC) table.insert(DVS_AttractionMemory.VillageCenters, "VC_ID_"..idVC) end for IV = 1, requiredIV do local position = GetPosition(DVS_AttractionMemory.Spawnpoint) local idIV = Logic.CreateEntity(Entities.CU_BlackKnight_SoldierSword3, position.X, position.Y, 0.00, GUI.GetPlayerID()) Logic.SetEntityName(idIV, "IV_ID_"..idIV) Logic.SetEntityScriptingValue(idIV, -30, 257) MakeInvulnerable(idIV) table.insert(DVS_AttractionMemory.Invisibles, "IV_ID_"..idIV) end elseif newAL < oldAL then local requiredIV = oldAL-newAL for IV = 1, requiredIV do local position = GetPosition(DVS_AttractionMemory.Spawnpoint) local idIV = Logic.CreateEntity(Entities.CU_BlackKnight_SoldierSword3, position.X, position.Y, 0.00, GUI.GetPlayerID()) Logic.SetEntityName(idIV, "IV_ID_"..idIV) Logic.SetEntityScriptingValue(idIV, -30, 257) MakeInvulnerable(idIV) table.insert(DVS_AttractionMemory.Invisibles, "IV_ID_"..idIV) end end if newAL < 0 then newAL = 0 end DVS_AttractionLimit_CheckTables() DVS_AttractionMemory.AttractionLimit = newAL if DVS_AttractionMemory.AttractionLimit < 0 then DVS_AttractionMemory.AttractionLimit = 0 end end function DVS_AttractionLimit_CheckTables() local numberOfVC = DVS_AttractionLimit_GetVC() local numberOfIV = DVS_AttractionLimit_GetIV() local uselessVC = math.floor(numberOfIV/75) if uselessVC >= 1 then if uselessVC > numberOfVC then uselessVC = numberOfVC end for uIV = 1, uselessVC*75 do local destroyedIV = table.remove(DVS_AttractionMemory.Invisibles) DestroyEntity(destroyedIV) end for uVC = 1, uselessVC do local destroyedVC = table.remove(DVS_AttractionMemory.VillageCenters) DestroyEntity(destroyedVC) end end end function DVS_AttractionLimit_GetUsage() return Logic.GetPlayerAttractionUsage(GUI.GetPlayerID())-DVS_AttractionLimit_GetIV() end function DVS_AttractionLimit_GetFreePlaces() return DVS_AttractionLimit_GetAL()-DVS_AttractionLimit_GetUsage() end function DVS_AttractionLimit_GetAL() return DVS_AttractionMemory.AttractionLimit end function DVS_AttractionLimit_GameCallback_GUI_SelectionChanged_New() DVS_AttractionLimit_GameCallback_GUI_SelectionChanged_Old() local buildingType = Logic.GetEntityTypeName(Logic.GetEntityType(GUI.GetSelectedEntity())) if buildingType == "PB_VillageCenter1" then for k, v in pairs(DVS_AttractionMemory.VillageCenters) do if GUI.GetSelectedEntity() == GetID(DVS_AttractionMemory.VillageCenters[k]) then GUI.DeselectEntity(GUI.GetSelectedEntity()) end end end end function DVS_AttractionLimit_GetVC() local vc = 0 for v, c in pairs(DVS_AttractionMemory.VillageCenters) do vc = vc + 1 end return vc end function DVS_AttractionLimit_GetIV() local iv = 0 for i, v in pairs(DVS_AttractionMemory.Invisibles) do iv = iv + 1 end return iv end function DVS_AttractionLimit_IsVCDestroyed() local id = Event.GetEntityID() if GetPlayer(id) ~= GUI.GetPlayerID() then return end local buildingType = Logic.GetEntityTypeName(Logic.GetEntityType(id)) if buildingType == "PB_VillageCenter1" then DVS_AttractionMemory.AttractionLimit = DVS_AttractionMemory.AttractionLimit-75 elseif buildingType == "PB_VillageCenter2" then DVS_AttractionMemory.AttractionLimit = DVS_AttractionMemory.AttractionLimit-100 elseif buildingType == "PB_VillageCenter3" then DVS_AttractionMemory.AttractionLimit = DVS_AttractionMemory.AttractionLimit-125 end if DVS_AttractionMemory.AttractionLimit < 0 then DVS_AttractionMemory.AttractionLimit = 0 end end
Edit1: So, jetzt sollte alles richtig kopiert sein.
Edit2: Abfragen für Bau, Upgrade und Abriss hinzugefügt.
Edit3: War ja klar, dass noch was folgt.
Edit4: Zwei neue Abfragen (FreePlaces und Usage) hinzugefügt.
Edit5: Kompatibilität mit anderen GUI-Modifikationen erhöht.
Edit6: Wahnsinn.
____________________
Journalisten erkundigen sich bei Wissenschaftlern meist nicht nach Grundlagen, sondern eher nach Ergebnissen und Folgerungen. Das erklärt womöglich auch, warum sich Forschungsberichte in den Medien so häufig als feststehende Erkenntnisse lesen, nicht aber als Ideen, Entdeckungen oder Indizien, um die es sich genau genommen in den meisten Fällen handelt. -Axel Bojowski
Dieser Beitrag wurde von Zedeg am 24.08.2015 um 00:03 editiert.
Zedeg
|
#3 13.12.2014 17:14 Beiträge: 428 |
Danke, mcb, für den Hinweis!
Ah, dass ein normales DZ zerstört wird, daran habe ich gar nicht gedacht. Wird schnellstmöglichst geändert.
Edit: So, Abfragen für den Bau, für das Upgrade und für den Abriss von DZ wurden eingebaut. Sollte ich noch was vergessen haben, einfach schreiben.
____________________
Journalisten erkundigen sich bei Wissenschaftlern meist nicht nach Grundlagen, sondern eher nach Ergebnissen und Folgerungen. Das erklärt womöglich auch, warum sich Forschungsberichte in den Medien so häufig als feststehende Erkenntnisse lesen, nicht aber als Ideen, Entdeckungen oder Indizien, um die es sich genau genommen in den meisten Fällen handelt. -Axel Bojowski
Dieser Beitrag wurde von Zedeg am 13.12.2014 um 17:46 editiert.
mcb
|
#4 14.12.2014 14:29 Beiträge: 1472 |
Ich hab noch zwei Fehler korrigiert
function DVS_AttractionLimit_IsVCDestroyed() local id = Event.GetEntityID() if GetPlayer(id)~=GUI.GetPlayerID() then -- gegnerisches DZ? return end local buildingType = Logic.GetEntityTypeName(Logic.GetEntityType(id)) if buildingType == "PB_VillageCenter1" then DVS_AttractionMemory.AttractionLimit = DVS_AttractionMemory.AttractionLimit-75 elseif buildingType == "PB_VillageCenter2" then -- VC1? DVS_AttractionMemory.AttractionLimit = DVS_AttractionMemory.AttractionLimit-100 elseif buildingType == "PB_VillageCenter3" then DVS_AttractionMemory.AttractionLimit = DVS_AttractionMemory.AttractionLimit-125 end if DVS_AttractionMemory.AttractionLimit < 0 then DVS_AttractionMemory.AttractionLimit = 0 end end
Zedeg
|
#5 14.12.2014 19:48 Beiträge: 428 |
Ob du's glaubst oder nicht, genau das wollte ich gerade korrigieren. Beim nächsten Mal mach' ich mal besser gleich Langzeitstudien mit Feindkontakt.
Ich test' dann mal weiter. Findet sich bei meiner Betriebsblindheit bestimmt noch was. *gnarf*
____________________
Journalisten erkundigen sich bei Wissenschaftlern meist nicht nach Grundlagen, sondern eher nach Ergebnissen und Folgerungen. Das erklärt womöglich auch, warum sich Forschungsberichte in den Medien so häufig als feststehende Erkenntnisse lesen, nicht aber als Ideen, Entdeckungen oder Indizien, um die es sich genau genommen in den meisten Fällen handelt. -Axel Bojowski
Play4FuN
|
#6 16.08.2017 15:48 Beiträge: 704 |
*Altes Thema hervorkram* ... ähm, übersehe ich etwas Wesentliches, oder ist das ganze auch mit diesen paar Zeilen zu erledigen?
GetPlayerAttractionLimit_Orig = Logic.GetPlayerAttractionLimit Logic.GetPlayerAttractionLimit = function(_player) if (_player == 1) then return 42 end return GetPlayerAttractionLimit_Orig(_player) end
Nur kurz getestet, aber funzt sowohl für Leibis kaufen, als auch für Soldaten aus Kaserne rekrutieren
____________________
LG Play4FuN
Siedler DEdK Mapping + Scripting Tutorials
Ludwig
|
#7 17.08.2017 16:29 Beiträge: 440 |
Nur die halbe Wahrheit
Hallo Play4FuN,
so wie Du das geschrieben hast lässt sich das Limit festsetzen aber versuche dann einmal ein DZ zu bauen oder auszubauen. Das Limit wird sich nicht verändern. Dazu wird also doch etwas mehr benötigt.
Es lässt sich aber etwas daraus machen, das Bevölkerungslimit unabhängig von Ausbaustufe und Anzahl der DZ's machen.
Beispiel:
LimitAendern(50) function LimitAendern(n) v = Logic.GetPlayerAttractionLimit(1) neu = v + n GetPlayerAttractionLimit_Orig = Logic.GetPlayerAttractionLimit Logic.GetPlayerAttractionLimit = function(_player) if (_player == 1) then return neu end return GetPlayerAttractionLimit_Orig(_player) end end
Bei jedem Aufruf der Funktion wird das Limit um 50 heraufgesetzt. Limit könnte also bei einem Hädler gekauft werden. Ist nur so eine Idee.
Ein oder mehrere DZ's werden aber trotzdem benötigt, da sonst keine Settler kommen. Wie weit das also sinnvoll ist ?
Gruß
Ludwig
Dieser Beitrag wurde von Ludwig am 17.08.2017 um 17:21 editiert.
Play4FuN
|
#8 18.08.2017 10:45 Beiträge: 704 |
Hallo Ludwig,
richtig, ein Dorfzentrum benötigt man ohnehin, wenn man Siedler "normal" in seine Siedlung haben will, aber mit der besagten Logic-Funktion, lässt sich das Limit ja beliebig anpassen.
Dabei ist es egal, wann man das Limit verändert, also könnte ein neues DZ z.B. auch 100 neue Plätze bedeuten usw...
Wollte das auch nur noch hinzufügen zu diesem Thread, falls jemand "nur" die kurze Variante benötigt
____________________
LG Play4FuN
Siedler DEdK Mapping + Scripting Tutorials
MadShadow
|
#9 25.08.2017 17:35 Beiträge: 372 |
Du überschreibst lediglich die Funktion die das AttractionLimit zurückgibt, veränderst allerdings nicht das richtige AttractionLimit. Bedeutet alle Funktionen die das AttractionLimit via Logic überprüfen werden getäuscht.
Damit konnte ich zwar mit einem DZ weniger als 75 Plätze erreichen, aber nicht mehr als 75 .. Prinzipiell könnte man jetzt natürlich 20 DZ's am Kartenrand platzieren und dann via Logic das AttractionLimit beliebig regeln.
Wollte obiges jedenfalls nochmal klarstellen, da es noch nicht genannt wurde und vilt. andere Leser verwirren könnte..
Play4FuN
|
#10 27.08.2017 11:27 Beiträge: 704 |
Zitat von MadShadow:
Damit konnte ich zwar mit einem DZ weniger als 75 Plätze erreichen, aber nicht mehr als 75
Ok, das habe ich gar nicht getestet, weil ich dachte, dass diese "Täuschung" genügen sollte - das heißt also, das Spiel prüft zusätzlich zur Information, die es von Logic.GetPlayerAttractionLimit erhält EXTRA noch, wie viele DZ der Spieler hat!? Interessant ...
____________________
LG Play4FuN
Siedler DEdK Mapping + Scripting Tutorials
warrior1024
|
#11 27.08.2017 12:06 Beiträge: 345 |
Zitat von Play4FuN:
Zitat von MadShadow:
Damit konnte ich zwar mit einem DZ weniger als 75 Plätze erreichen, aber nicht mehr als 75
Ok, das habe ich gar nicht getestet, weil ich dachte, dass diese "Täuschung" genügen sollte - das heißt also, das Spiel prüft zusätzlich zur Information, die es von Logic.GetPlayerAttractionLimit erhält EXTRA noch, wie viele DZ der Spieler hat!? Interessant ...
Durch den Hack hast du eher zwei verschiedene Bevölkerungslimits, eines auf Lua-Ebene und eines auf C-Ebene. Wenn für die Erstellung eines neuen Siedlers die Lua-Ebene mitbenutzt wird(Soldat nachkaufen, Leader kaufen, Leibi, Platzanzeige), dann wird min(gehacktes Lua-Limit,C-Limit) verwenden.
Wenn die Lua-Ebene nicht verwendet wird(Automatisch rekrutiertes Gefolge für Hauptmann, Arbeiter aus DZ), dann ist nur das C-Limit relevent, welches aus der Anzahl, DZ-Stufen und Daten in den XMLs berechnet wird.
Somit reicht ein reiner Logic-Hack nicht aus und du musst den Umweg mit den unsichtbaren Soldaten gehen.
Alternativ kannst du mit dem S5Hook(oder den SCV2-Funktionen) auch direkt in der Kopie der XML-Datei im Arbeitsspeicher rumschreiben:
S5Hook.GetRawMem(9002416)[0][16][Entities.PB_VillageCenter3 * 8 + 2][44]:SetInt(1000)
Den ersten Parameter und die ersten 3 Indizes habe ich mir von mcb abgeschaut.
Damit kannst du aber nicht jedem Gebäude(Outpost z.B. funktionieren nicht) DZ-Platz geben und die Änderungen sollten bei Verlassen des Spiels rückgängig gemacht werden. Weiterhin sollte bei jedem Neuladen die Veränderung erneut angewendet werden.
____________________
"Banken machen keine Fehlentscheidungen! Haben Euch das Eure Eltern nicht beigebracht?"
- Bankier Samael Silren, Enderal
Dieser Beitrag wurde von warrior1024 am 27.08.2017 um 12:58 editiert.
Seiten: 1