Hilfe, Stack Overflow!
» Siedler Map Source Forum » Siedler DEdK Script Forum » Hilfe, Stack Overflow!
Seiten: 1
Narnius
|
#1 22.12.2017 15:16 Beiträge: 34 |
Meine Siedler 5 Map
Hallihallo liebe und treue Siedler Community! Ich möchte mich erstmal recht herzlich für die hilfreichen und schnellen Antworten auf meine bisherigen Fragen bedanken. Ich spiele Siedler nur von Zeit zu Zeit, habe aber Gefallen am Map Editor gefunden und versuche eigene Karten zu erstellen. Mit Freunden&Verwandten
Lan-Spiele zu machen ist spaßig, jedoch ist es zu dritt knifflig, erst recht wenn die Spieler unterschiedlich gut sind. Darum habe ich mir schon lange eine Co-op Map gewünscht, bei der alle Spieler im Team gegen die KI spielen. Unter: http://www.siedler-games.de/si...r?s=multiplayer+verb%C3%BCndet wurde ich tatsächlich fündig und fing an eine Dreispieler Co-op Map zu erstellen. Als Vorlage, weil ich möglichst schnell zu skripten anfangen wollte, nahm ich die Schwarzen Berge. Erst lief alles Gut, die Spieler waren verbündet und als ich zum test das gegnerische HQ ins Spielerdorf setzte und es ingame zerstörte war für alle Spieler das Spiel gewonnen. Als ich später dann immer mehr Funktionen implementierte, unter anderem, einen TroopSpawnGenerator(von dem ich keine Ahnung habe),
konnte ich zwar im SP und mit playalone auch im MP als Spieler 1 die Map spielen, aber als ich versucht habe, als die Anderen Spieler zu testen, hing sich das Spiel auf und es erschien die Fehlermeldung: "Stack Overflow". Ich habe mehrere Dinge entfernt und verändert, um das Problem zu lösen, aber nichts hat funktioniert. Anbei füge ich mein Skript ein; sollte das nicht ausreichen, teilt mir das bitte mit!
Vielen Dank schon mal im Voraus,
Narnius
Skript:
-- MapName: Der Fluch der Schwarzen Berge -- MapOriginalAuthor: Christian & Matthias -- Author: Narnius -- Coop Referencescript für zwei Spieler, Diese spielen gegen eine bestimmte Anzahl an KI Spieler -- Man muß im Editor beim Kartenscriptassistenten nur die zwei menschlichen Spieler festlegen, damit auch nur diese zwei Plätze später in der Lobby angezeigt werden. -- Beim Start in der MP Lobby oder im Lan kann man beide Spieler in unterschiedlichen Teams stehen lassen , nach dem Start werden sie im Game verbündet sein . -- Bei dieser Map sind auch die MP Bugtools von chromix eingebaut Enable Alarmlimit und enable overtimelimit -------------------------------------------------------------------------------- -- Hiermit wird die Lobbyfunktion umgangen, so dass die beiden menschlichen Spieler nach dem Start verbündet sind und auch das Gebiet des anderen sehen if XNetwork then XNetwork.GameInformation_GetLogicPlayerTeam = function() return 1; end XNetwork.GameInformation_GetFreeAlliancesFlag = function() return 1; end end function GameCallback_OnGameStart() -- Include global tool script functions Script.Load(Folders.MapTools.."Ai\\Support.lua") Script.Load( Folders.MapTools.."Main.lua" ) -- Unbedingt muß für die Einbindung der Ki hier auch dieses am Anfang geladen werden IncludeGlobals("MapEditorTools") Script.Load( "Data\\Script\\MapTools\\Counter.lua" ) Script.Load( "Data\\Script\\MapTools\\MultiPlayer\\MultiplayerTools.lua" ) Script.Load( "Data\\Script\\MapTools\\Tools.lua" ) Script.Load( "Data\\Script\\MapTools\\WeatherSets.lua" ) IncludeGlobals("Comfort") -- notwendig damit die Siegbedingungen greifen gvMission = {} gvMission.PlayerID = GUI.GetPlayerID() --Init local map stuff Mission_InitWeatherGfxSets() InitWeather() Mission_InitGroups() Mission_InitLocalResources() -- Init global MP stuff --MultiplayerTools.InitResources("normal") MultiplayerTools.InitCameraPositionsForPlayers() MultiplayerTools.SetUpGameLogicOnMPGameConfig() MultiplayerTools.GiveBuyableHerosToHumanPlayer( 1 ) -- 1 Held pro Spieler StartSimpleJob("VictoryJob") ModelOverwrite(); CreateArmyOne(); if XNetwork.Manager_DoesExist() == 0 then for i = 1, 2, 3 do -- Für 3 Spieler eingestellt MultiplayerTools.DeleteFastGameStuff(i) end local PlayerID = GUI.GetPlayerID() Logic.PlayerSetIsHumanFlag( PlayerID, 1 ) Logic.PlayerSetGameStateToPlaying( PlayerID ) end -- Die weiteren menschlichen Spieler müssen auf Feind gestellt werden so dies gewünscht ist zu allen KI's SetHostile( 5, 2 ) SetHostile( 5, 3 ) LocalMusic.UseSet = HIGHLANDMUSIC --Befehlsatz einfach Kommentierung durch entfernen der beiden Bindestriche rausnehmen -- nicht vergessen das jeweils nur ein Set gesetzt sein sollte --LocalMusic.UseSet = EUROPEMUSIC --LocalMusic.UseSet = HIGHLANDMUSIC --LocalMusic.UseSet = MEDITERANEANMUSIC --LocalMusic.UseSet = DARKMOORMUSIC --LocalMusic.UseSet = EVELANCEMUSIC -- Diese Zeilen kommen noch vom Karteneditor und setzen die Standardsiegbedingung vernicht die Player Id MapEditor_SetupDestroyVictoryCondition(5) MapEditor_CreateHQDefeatCondition() -- Hier gehts mit den Parametern für den KI Spieler los. In diesem Fall Spieler 3, denn Spieler 2 ist ja der 2. menschliche Spieler -- Man kann diese Werte natürlich auch direkt in die Funktion eintragen, -- anstatt sie wie hier übersichtlich aufzulisten --Nächste Ki local aiID = 5; local strength = 3; local range = 3000; local techlevel = 3; local position = "P5_AI_HQ"; -- natürlich sollte man P5_AI_HQ als Skriptnamen dem Hauptquartier geben, natürlich bei player 4 P4_AI_HQ etc.. local aggressiveness = 3; local peacetime = 0; MapEditor_SetupAI( aiID, strength, range, techlevel, position, aggressiveness, peacetime ); SetupPlayerAi( aiID, { extracting = 1, repairing = 1 } ); SetPlayerName( aiID, "Nebelvolk" ); --Der Teil hier ist nur wichtig wenn man gezielt die Ressourcen bestimmen möchte die die Ki bekommt. -- Falls man dies nicht möchte, kann dieser Teil weggelassen werden -- Die Parmeter sollten individuelle angpasst werden SetupPlayerAi( 5, { resources = { gold = 10000, clay = 100, iron = 1500, sulfur = 1500, stone = 100, wood = 100, } } ); SetupPlayerAi( 5, { refresh = { gold = 10000, clay = 1000, iron = 1500, sulfur = 1500, stone = 100, wood = 100, updateTime = 1000 } } ); end --++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -- This function is called on game start and after save game is loaded, setup your weather gfx -- sets here function Mission_InitWeatherGfxSets() -- Use gfx sets SetupHighlandWeatherGfxSet() --Befehlsatz einfach Kommentierung durch entfernen der beiden Bindestriche rausnehmen nicht vergessen das man nur ein setzten sollte --SetupNormalWeatherGfxSet() --SetupHighlandWeatherGfxSet() --SetupSteppeWeatherGfxSet() --SetupMoorWeatherGfxSet() --SetupEvelanceWeatherGfxSet() end --++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -- This function is called on game start you should setup your weather periods here function InitWeather() -- Hier wird der Wetterwechsel festgelegtl -- Beispiel 4 Min Sommer, dann 2 Minuten Winter, dann wieder alles von vorne AddPeriodicSummer(240) AddPeriodicWinter(120) --Befehlsatz einfach Kommentierung durch entfernen der beiden Bindestriche rausnehmen --AddPeriodicSummer(600) --AddPeriodicWinter(300) --AddPeriodicRain(120) end --++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -- Build Groups and attach Leaders function Mission_InitGroups() end --++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -- Limit the Technologies here. For example Weathermashine. function Mission_InitTechnologies() --no limitation in this map end --++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -- Set local resources function Mission_InitLocalResources() local HumenPlayer = XNetwork.GameInformation_GetMapMaximumNumberOfHumanPlayer() -- Dies sind die Startresourcen für alle Spieler. Diese sollten angepasst werden local InitGoldRaw = 300 local InitClayRaw = 600 local InitWoodRaw = 400 local InitStoneRaw = 300 local InitIronRaw = 300 local InitSulfurRaw = 250 --Add Players Resources for i = 1, 2, 3 do Tools.GiveResouces(i, InitGoldRaw , InitClayRaw,InitWoodRaw, InitStoneRaw,InitIronRaw,InitSulfurRaw) --Befehlsatz einfach Kommentierung durch entfernen der beiden Bindestriche rausnehmen --Unitechnologien --ResearchTechnology(Technologies.GT_Mercenaries, i) -->Wehrpflicht --ResearchTechnology(Technologies.GT_StandingArmy, i) -- -> stehendes Heer --ResearchTechnology(Technologies.GT_Tactics, i)--> Taktiken --ResearchTechnology(Technologies.GT_Strategies, i) ---> Pferdezucht ResearchTechnology(Technologies.GT_Construction, i) ----> Konstruktion --ResearchTechnology(Technologies.GT_ChainBlock, i) --Flaschenzug --ResearchTechnology(Technologies.GT_GearWheel, i) --Zahnräder --ResearchTechnology(Technologies.GT_Architecture, i) --Architektur ResearchTechnology(Technologies.GT_Alchemy, i) --Alchimie --ResearchTechnology(Technologies.GT_Alloying, i) --Legierungen --ResearchTechnology(Technologies.GT_Metallurgy, i) --Metallurgie --ResearchTechnology(Technologies.GT_Chemistry, i) --Chemie --ResearchTechnology(Technologies.GT_Taxation, i) -- --ResearchTechnology(Technologies.GT_Trading, i) --Handelswesen --ResearchTechnology(Technologies.GT_Banking, i) -- --ResearchTechnology(Technologies.GT_Gilds, i) -- --ResearchTechnology(Technologies.GT_Literacy, i) --Bildung --ResearchTechnology(Technologies.GT_Printing, i) --Buchdruck --ResearchTechnology(Technologies.GT_Laws, i) -- --ResearchTechnology(Technologies.GT_Library, i) --Büchereien ResearchTechnology(Technologies.GT_Mathematics, i) --Mathematik --ResearchTechnology(Technologies.GT_Binocular, i) -- Ferngläser --ResearchTechnology(Technologies.GT_Matchlock, i) --Luntenschloss --ResearchTechnology(Technologies.GT_PulledBarrel, i) --gezogener Lauf --ResearchTechnology(Technologies.T_ChangeWeather, i) --ResearchTechnology(Technologies.T_WeatherForecast,i) --ResearchTechnology(Technologies.T_ThiefSabotage,i) --ResearchTechnology(Technologies., i) --ResearchTechnology(Technologies., i) end end -- victory funktion muß bei coop sein -- Hier wird die Siegbedingung vorgegeben function VictoryJob() if IsDead("P5_AI_HQ") then Victory(); return true; end end function CreateArmyOne() armyOne = {} armyOne.player = 5 armyOne.id = 7 armyOne.strength = 3 armyOne.position = GetPosition("NVolk") armyOne.rodeLength = 500 SetupArmy(armyOne) local troopDescription = { maxNumberOfSoldiers = 16, minNumberOfSoldiers = 0, experiencePoints = VERYLOW_EXPERIENCE, } troopDescription.leaderType = Entities.CU_Evil_LeaderBearman1 EnlargeArmy(armyOne,troopDescription) EnlargeArmy(armyOne,troopDescription) Defend(armyOne) StartSimpleJob("ControlArmyOne") end function ControlArmyOne() if not armyOne.created then armyOne.created = not IsDead(armyOne) return false end if IsDead(armyOne) then -- Angreifende Armee ist tot. Nach 2 Minuten (120 Sekunden) soll die nächste Armee angreifen. Gleichzeitig wird ein Countdown im Spiel angezeigt. StartCountdown(120, CreateArmyOne, true) return true else -- Armee lebt noch. In die feindliche Stadt gehen und da alles niedermetzeln. Redeploy(armyOne, GetPosition("StartPos" ), 5000) end end function StartCountdown(_Limit, _Callback, _Show) assert(type(_Limit) == "number") assert( not _Callback or type(_Callback) == "function" ) Counter.Index = (Counter.Index or 0) + 1 if _Show and CountdownIsVisisble() then assert(false, "StartCountdown: A countdown is already visible") end Counter["counter" .. Counter.Index] = {Limit = _Limit, TickCount = 0, Callback = _Callback, Show = _Show, Finished = false} if _Show then MapLocal_StartCountDown(_Limit) end if Counter.JobId == nil then Counter.JobId = StartSimpleJob("CountdownTick") end return Counter.Index end function StopCountdown(_Id) if Counter.Index == nil then return end if _Id == nil then for i = 1, Counter.Index do if Counter.IsValid("counter" .. i) then if Counter["counter" .. i].Show then MapLocal_StopCountDown() end Counter["counter" .. i] = nil end end else if Counter.IsValid("counter" .. _Id) then if Counter["counter" .. _Id].Show then MapLocal_StopCountDown() end Counter["counter" .. _Id] = nil end end end function CountdownTick() local empty = true for i = 1, Counter.Index do if Counter.IsValid("counter" .. i) then if Counter.Tick("counter" .. i) then Counter["counter" .. i].Finished = true end if Counter["counter" .. i].Finished and not IsBriefingActive() then if Counter["counter" .. i].Show then MapLocal_StopCountDown() end -- callback function if type(Counter["counter" .. i].Callback) == "function" then Counter["counter" .. i].Callback() end Counter["counter" .. i] = nil end empty = false end end if empty then Counter.JobId = nil Counter.Index = nil return true end end function CountdownIsVisisble() for i = 1, Counter.Index do if Counter.IsValid("counter" .. i) and Counter["counter" .. i].Show then return true end end return false end --++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ function ModelOverwrite() Logic.SetModelAndAnimSet(GetEntityId("steinmauer"), Models.XD_RuinWall1) Logic.SetModelAndAnimSet(GetEntityId("wall1"), Models.XD_Palisade1) Logic.SetModelAndAnimSet(GetEntityId("wall2"), Models.XD_Palisade1) Logic.SetModelAndAnimSet(GetEntityId("wall3"), Models.XD_Palisade1) Logic.SetModelAndAnimSet(GetEntityId("wall4"), Models.XD_Palisade1) Logic.SetModelAndAnimSet(GetEntityId("wall5"), Models.XD_Palisade1) -- wall1-wall5 sind sprengbare Steine, die steinmauer ist eigentlich ein abbaubarer Steinhaufen. end
Dieser Beitrag wurde von Narnius am 11.02.2018 um 20:25 editiert.
Kantelo
|
#2 22.12.2017 22:26 Beiträge: 357 |
Hi Narnius,
was definitiv ein Fehler ist ist Zeile 49:
for i = 1, 2, 3 do -- Für 3 Spieler eingestellt
richtig ist
for i = 1, 3 do -- Für 3 Spieler eingestellt
Bei einer for Schleife generell gibt man mit der ersten Zahl (hier 1) den Startwert von i an und mit der zweiten (3) den Endwert.
In der Schleife nimmt dann i einmal den Wert 1 sowie 2 und 3 an
und es werden die drei Befehle ausgeführt
MultiplayerTools.DeleteFastGameStuff(1) MultiplayerTools.DeleteFastGameStuff(2) MultiplayerTools.DeleteFastGameStuff(3)
Ich könnte mir vorstellen, dass das der Fehler ist, habe es aber nicht getestet
LG
Kantelo
Zedeg
|
#3 22.12.2017 23:35 Beiträge: 428 |
Zusatz
Dass
for i = 1, 2, 3 do -- Für 3 Spieler eingestellt
keinen Syntaxfehler liefert, liegt daran, dass du der for-Schleife tatsächlich drei Zahlen geben kannst. Die dritte Zahl gibt nämlich die Größe der Schritte an (die standardmäßig bei 1 liegt, wenn keine dritte Zahl angegeben wird). So kann man bspw. mit -1 eine Rückwärtschleife implementieren.
Was bei dir passiert, ist, dass i zuerst 1 annimmt und der Code für Spieler 1 ausgeführt wird. Dann wird i = 1+3=4 gerechnet. Da aber 4 > 2, hört die Schleife auf, ohne je etwas für Spieler 2, 3 (oder 4) getan zu haben
____________________
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
Narnius
|
#4 24.12.2017 00:04 Beiträge: 34 |
Dankeschön, aber
die Map ist immer noch fehlerhaft. Die Fehlermeldung bleibt bestehen. Hier ist der Map-Download, falls das eventuell Klarheit verschafft. https://www.dropbox.com/s/aq43...r%20Schwarzen%20Berge.s5x?dl=1
mcb
|
#5 24.12.2017 15:32 Beiträge: 1472 |
Was ist denn die genaue Fehlermeldung? (Da ist eine Zeilenangabe mit bei)
Außerdem wirft der Debugger ne Fehlermeldung: In ControlArmyOne verwendest du Redeploy(armyOne, "StartPos", 5000) , es sollte aber Redeploy(armyOne, GetPosition("StartPos" ), 5000) sein.
Narnius
|
#6 24.12.2017 23:32 Beiträge: 34 |
Nun ja...
Zitat von mcb:
Was ist denn die genaue Fehlermeldung? (Da ist eine Zeilenangabe mit bei)
Außerdem wirft der Debugger ne Fehlermeldung: In ControlArmyOne verwendest du Redeploy(armyOne, "StartPos", 5000) , es sollte aber Redeploy(armyOne, GetPosition("StartPos" ), 5000) sein.
Die Fehlermeldung liefert mir nicht der Lua Debugger, sondern Siedler selbst. Das Spiel bleibt ewig beim Ladebildschirm stehen, als das zum ersten Mal vorkam habe ich eine Weile gewartet, dann ALT+TAB und Windows-Taste+D ausprobiert, letztendlich half aber nur STRG+ALT+ENTF und in der Taskleiste entdeckte ich dann ein Unterfenster von Siedler, das war dann die Fehlermeldung. Wenn meine Erklärung unverständlich ist, kannst du dir gerne die Map runterladen und dir ein Bild machen.
EDIT: Vielen Dank trotzdem, der TroopSpawnGenerator funtkioniert jetzt wenigstens (überhaupt)!
EDIT 2: Den Lua Debugger habe ich nicht einmmal benutzen können, da meine Map für Legenden entwickelt ist, ich vom Lua Debugger aus aber nur das "Original Game" starten kann. Den Grund dafür kenne ich nicht.
Dieser Beitrag wurde von Narnius am 26.12.2017 um 11:59 editiert.
Narnius
|
#7 27.12.2017 15:46 Beiträge: 34 |
Das wäre nun aus der Welt.
Ich konnte die Map jetzt endlich mit 2 Spielern testen; es funktioniert einwandfrei! Ein Test mit 3 Spielern steht noch aus, jetzt versuche ich allerdings erst die anderen, restlichen Funktionen einzubauen. Erstens: Einen kostenlosen Tribut für Spieler 3, der wiederum Spieler 1 einen Tribut gibt, mit dem er ein Tor öffnen kann, zweitens: Die Fertigstellung des TroopSpawn Generators der Dämonen, die Erst Truppen spawnen, und nach Ablauf eines Countdowns, wenn diese noch am Leben sind, abwechselnd die Spieler angreifen und das ganze wieder von vorne beginnen lassen sollen. Letztens: Eine Möglichkeit für Spieler 1 finden, die als Palisaden getarnten Steine zu sprengen, ohne Pilgrim rekrutieren zu müssen. Die Passage ist gesperrt, damit Spieler 1 nicht sofort bei Spieler 3 eindringt und dessen Minen besetzt. Es soll allerdings möglich sein diesen Weg im Laufe des spiels frei zu sprengen. Meine erste Idee war, Spieler 1 eine Einheit zu geben, die nach Bezahlung von etwas Schwefel usw. eine Bombe bei sich spawnt und stirbt, eventuell sogar ein Gebäude, in dem man solche Einheiten kaufen kann, und per Knopfdruck alle auslösen kann. Nur wäre das sehr kompliziert für einen Anfänger wie mich und ausserdem ziemlich unnötig. Am Besten wäre also, eine Art Briefing, in dem ein Verrückter Wissenschaftler anbietet, die Steine aus dem Weg zu räumen, also das Übliche. Problem: Briefings funktionieren nicht im Multiplayer. Die Letzte Möglichkeit die mir einfallen würde, bei dessen Umsetztung ich aber hilfe bräuchte ist: Spieler 1 startet sowieso mit einer Alchimistenhütte. Dieser könnte man mit einem GUI-Knopf versehen, der an der genannten Stelle eine Bombe errschafft. Wenn ihr Ideen habt, mit denen man dieses Problem lösen kann, oder generell Skriptvorschläge für die 3 verbleibenden Skriptelemente, schreibt sie bitte als Antwort auf diesen Beitrag,
Gruß Narnius
BrokenSun
|
#8 28.12.2017 11:14 Beiträge: 73 |
Hey Narnius, Briefings funktionieren schon im Multiplayer, jedoch kann da jeder mitlesen...
Wegen der Palisade und dem Wegsprengen, warum nicht nen Countdown setzten? Nach 60 min heißt es dann , message("Mein Herr, ein Erdbeeben erschüttert das Land" und mit CreateEntity() kannst du bomben erschaffen und mit DeleteEntity() kannst du die Palisaden entfernen
Oder du lässt n Dieb n Haus wegsprengen, welches mit if 'isDead then...' mit den Palisaden verbunden ist... Es gibt soviele möglichkeiten
mcb
|
#9 28.12.2017 17:59 Beiträge: 1472 |
Also Tribute funktionieren im MP genauso wie im SP, also einfach in Callback vom ersten den zweiten erstellen.
Zu GUI-Manipulationen im MP: Deutlich komplizierter als im SP, da du auch noch die Synchronisierung übernehmen musst. (Lässt sich mit Tributen erledigen, gibt dann aber keine Parameter für Funktionen und es ist deutlich schwieriger eine Funktion mehrmals aufzurufen. Ich hab allerdings dafür ein paar Comfort-Funktionen geschrieben, die theoretisch beliebige Aufrufe synchronisieren können.)
Bei Briefings solltest du aber darauf Achten, kein MC zu verwenden (das ist im Grunde genommen nur ein normaler nicht synchronisierter Button).
Seiten: 1