Countdown wird Übersprungen
» Siedler Map Source Forum » Siedler DEdK Script Forum » Countdown wird Übersprungen
Seiten: 1
Narnius
|
#1 12.11.2018 13:00 Beiträge: 34 |
Countdown wird Übersprungen
Bei einer Map die ich gerade erstelle, es soll eine Dreispieler Coop-Map werden, habe ich einen Troop Spawn Generator eingebaut, welcher kontinuierlich Truppen aussenden soll. Mein Endziel damit, ist das dieser Abwechselnd die drei Spieler angreift. Derzeit arbeite ich allerdings noch daran, das das Grundprinzip funktioniert. Es soll ein Trupp spawnen, dann startet ein Countdown. Wenn dieser abgelaufen ist, greift der bestehende Trupp an, und ein neuer spawnt, um das Gebiet zu verteidigen. Ich habe in mein Script eine Countdown-Comfort-Funktion eingebaut und glaube, dass der Fehler bei dieser liegt. Wird Am ende der Funktion ControlArmyOne() wird CreateArmyOne() aufgerufen und dann spawnt auch ein neuer Trupp. Allerdings wird dann der Countdown missachtet, ControlArmyOne() wird sofort wieder aufgerufen und die Truppen schießen wie Pilze aus dem Boden. Hier das Script:
Hinweis: Viele der Kommentierungen stammen nicht von mir, sondern von den Machern der Comfortfunktionen.
-- 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") NewTribute1(); ModelOverwrite(); CreateArmyOne(); MakeInvulnerable(); if XNetwork.Manager_DoesExist() == 0 then for i = 1, 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, 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) StartCountdown(20, ControlArmyOne, true) end function ControlArmyOne() --if not armyOne.created then --armyOne.created = not IsDead(armyOne) --return false --end Redeploy(armyOne, GetPosition("StartPos" ), 5000); Fanfare() end function Fanfare() Sound.PlayGUISound(Sounds.fanfare,95) CreateArmyOne() 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 i=1 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 AddTribute( _tribute ) assert( type( _tribute ) == "table", "Tribut muß ein Table sein" ); assert( type( _tribute.text ) == "string", "Tribut.text muß ein String sein" ); assert( type( _tribute.cost ) == "table", "Tribut.cost muß ein Table sein" ); assert( type( _tribute.playerId ) == "number", "Tribut.playerId muß eine Nummer sein" ); assert( not _tribute.Tribute , "Tribut.Tribute darf nicht vorbelegt sein"); uniqueTributeCounter = uniqueTributeCounter or 1; _tribute.Tribute = uniqueTributeCounter; uniqueTributeCounter = uniqueTributeCounter + 1; local tResCost = {}; for k, v in pairs( _tribute.cost ) do assert( ResourceType[k] ); assert( type( v ) == "number" ); table.insert( tResCost, ResourceType[k] ); table.insert( tResCost, v ); end Logic.AddTribute( _tribute.playerId, _tribute.Tribute, 0, 0, _tribute.text, unpack( tResCost ) ); SetupTributePaid( _tribute ); return _tribute.Tribute; end --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --Hier werden unsere Tribute erstellt --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --Tribut Packen WS0 function NewTribute1() local tribute = {}; tribute.playerId = 3; tribute.text = "Bietet Spieler 1 an, das Tor gegen 200 Gold zu oeffnen"; tribute.cost = { Gold = 0}; tribute.Callback = Tributcallback1; TributId1 = AddTribute( tribute ); end function Tributcallback1() NewTribute2() end function NewTribute2() local tribute = {}; tribute.playerId = 1; tribute.text = "Gebt Spieler 2 200 Gold um das Tor zu oeffnen"; tribute.cost = { Gold = 200}; tribute.Callback = Tributcallback2; TributId1 = AddTribute( tribute ); end function Tributcallback2() AddGold( 1, -200) AddGold( 3, 200) ReplaceEntity ("Tor1", Entities.XD_WallStraightGate ) 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 function GameCallback_FulfillTribute() --Im Multiplayer sind Tribute standardmäßig deaktiviert, daher muss man sie erst wieder aktivieren return 1 end
Weiß jemand, wie man dieses Problem beheben kann?
Wenn ja, freue ich mich sehr über eine schnelle Antwort!
Vielen Dank schon mal im Voraus,
Narnius
Play4FuN
|
#2 13.11.2018 10:24 Beiträge: 704 |
Moin,
ich denke sofern du den Countdown Code richtig kopiert hast, sollte der ordentlich laufen. Ich nutze den so seit Jahren ohne Probleme und bin da sicher nicht der einzige.
Was mir aber beim Überfliegen direkt auffällt: nach 20 Sekunden wird armyOne neu erstellt, das heißt die alte wird überschrieben (die Truppen sind aber ggf noch da...)
Das könnte durchaus zu solch einem Verhalten führen, denke ich.
Daher bevor du die armyOne neu erstellst, erst mal prüfen, ob es die bisherige Army one noch gibt. Alternativ kannst du auch in deinem Countdown Callback anstatt CreateArymOne eine andere Funktion aufrufen, die nur das macht:
local troopDescription = { maxNumberOfSoldiers = 16, minNumberOfSoldiers = 0, experiencePoints = VERYLOW_EXPERIENCE, } troopDescription.leaderType = Entities.CU_Evil_LeaderBearman1 EnlargeArmy(armyOne,troopDescription) EnlargeArmy(armyOne,troopDescription)
... dann sollten nur neue Trupps zur bestehenden Armee hinzugefügt werden. Countdown neu starten nicht vergessen.
Inb4 falls du mal in das Problem rennst: IsDead bei Armeen funzt nicht ordentlich, falls diese noch gar nicht erstellt wurde, siehe dazu: http://www.siedler-games.de/si...id=utilfunctions:isdeadwrapper
____________________
LG Play4FuN
Siedler DEdK Mapping + Scripting Tutorials
Narnius
|
#3 13.11.2018 12:39 Beiträge: 34 |
Zitat von Play4FuN:
Moin,
ich denke sofern du den Countdown Code richtig kopiert hast, sollte der ordentlich laufen. Ich nutze den so seit Jahren ohne Probleme und bin da sicher nicht der einzige.
Was mir aber beim Überfliegen direkt auffällt: nach 20 Sekunden wird armyOne neu erstellt, das heißt die alte wird überschrieben (die Truppen sind aber ggf noch da...)
Das könnte durchaus zu solch einem Verhalten führen, denke ich.
Daher bevor du die armyOne neu erstellst, erst mal prüfen, ob es die bisherige Army one noch gibt. Alternativ kannst du auch in deinem Countdown Callback anstatt CreateArymOne eine andere Funktion aufrufen, die nur das macht:
local troopDescription = { maxNumberOfSoldiers = 16, minNumberOfSoldiers = 0, experiencePoints = VERYLOW_EXPERIENCE, } troopDescription.leaderType = Entities.CU_Evil_LeaderBearman1 EnlargeArmy(armyOne,troopDescription) EnlargeArmy(armyOne,troopDescription)
... dann sollten nur neue Trupps zur bestehenden Armee hinzugefügt werden. Countdown neu starten nicht vergessen.
Inb4 falls du mal in das Problem rennst: IsDead bei Armeen funzt nicht ordentlich, falls diese noch gar nicht erstellt wurde, siehe dazu: http://www.siedler-games.de/si...id=utilfunctions:isdeadwrapper
Danke für die Antwort, den CD hatte ich zu Testzwecken verkürzt, das isDead/notCreated Hilfsskript ist auch schon drin. Mit EnlargeArmyOne hatte ich es auch schon probiert, aber was meinst du mit "Countdown neu starten"?
Mir kam es nämlich so vor, als ob der Countdownwert nicht resetet wird und dadurch beim wiederholten Aufruf direkt zum Callback übergegangen wird.
Play4FuN
|
#4 13.11.2018 17:45 Beiträge: 704 |
Ich meine schlicht den StartCountdown Aufruf.
Kommt denn die Fanfare wie du es erwartest, oder wird die auch gespammt?
____________________
LG Play4FuN
Siedler DEdK Mapping + Scripting Tutorials
Narnius
|
#5 13.11.2018 17:49 Beiträge: 34 |
Doch
Zitat von Play4FuN:
Ich meine schlicht den StartCountdown Aufruf.
Kommt denn die Fanfare wie du es erwartest, oder wird die auch gespammt?
Die wird auch gespammt.
mcb
|
#6 13.11.2018 20:32 Beiträge: 1472 |
Ich glaube ich weiß, was los ist: Wenn der Countdown abgelaufen ist, wird die entsprechende Callback-Funktion aufgerufen, bevor der Countdown entfernt wird. Da du im Callback direkt einen neuen Countdown erstellst und beide sichtbar seien sollen, erzeugt StartCountdown eine Fehlermeldung, da nicht 2 Countdowns gleichzeitig angezeigt werden können.
Du bekommst die Fehlermeldung angezeigt, wenn du das hier machst: http://www.siedler-games.de/si...als:fehlermeldungen_aktivieren
oder den LuaDebugger benutzt.
Als einfachste Lösung würde ich Vorschlagen diese beiden Funktionen so abzuändern:
function ControlArmyOne() Redeploy(armyOne, GetPosition("StartPos" ), 5000); Fanfare() StartCountdown(1, CreateArmyOne, false) end function Fanfare() Sound.PlayGUISound(Sounds.fanfare,95) end
Narnius
|
#7 13.11.2018 21:34 Beiträge: 34 |
Juhu!
Vielen Dank, jetzt geht es, das einzige Problem ist jetzt noch, das die Truppen ihren Angriff abbrechen, wenn neue spawnen. Das lag auch nicht an dem Defend() Befehl, auch ohne war dies noch der Fall. Ich schätze PlayForFuns's Vorschlag könnte da Abhilfe schaffen, nur gibt der Editor mir einen Errsyntax, wenn ich das so reinkopiere (natürlich mit/zwischen Funktionskopf und end).
mcb
|
#8 16.11.2018 16:59 Beiträge: 1472 |
Also das der Mapeditor ErrSyntax sagt muss nix heißen, gerade wenn du TinyScript verwendest funktioniert das nur selten. Aktiviere einfach die Fehlermeldungen und starte die Map, dann weißt du ob du wirklich nen Syntaxfehler hast. (Wenn ja, poste mal den entsprechenden Code und die genaue Fehlermeldung.)
Narnius
|
#9 16.11.2018 18:27 Beiträge: 34 |
ähm
Zitat von mcb:
Also das der Mapeditor ErrSyntax sagt muss nix heißen, gerade wenn du TinyScript verwendest funktioniert das nur selten. Aktiviere einfach die Fehlermeldungen und starte die Map, dann weißt du ob du wirklich nen Syntaxfehler hast. (Wenn ja, poste mal den entsprechenden Code und die genaue Fehlermeldung.)
Ich benutze den LuaDebugger gar nicht, der ging bei mir auch nicht...
mcb
|
#10 16.11.2018 18:56 Beiträge: 1472 |
Ich meinte auch das hier, nicht den Debugger: http://www.siedler-games.de/si...als:fehlermeldungen_aktivieren
Narnius
|
#11 17.11.2018 12:09 Beiträge: 34 |
Hm
Ich glaube, ich habe jetzt den Fehler gefunden und er liegt nicht in meinem Skript. Die Gruppen bzw. Armeen, die ich für den Gegner erstelle, halten einfach immer zusammen. Der letzte Befehl, den ich der einen Armee gebe, wirkt auch auf die andere.
Mir kam nämlich der Geistesblitz, die Truppen in zwei Gruppen aufzuspalten. Ich versprach mir viel davon, da ich die Truppen ja so auch viel einfacher an verschiedene Orte schicken kann. Außerdem ermöglicht mir das, verschiedene Arten von Truppen zu spawnen. armyOne sind Bärenmenschen und armyTwo besteht aus Speerwerfern. Auf meine Schlussfolgerung kam ich, da die Speerwerfer immer mit den Bärenmenschen mitgingen und dann alle Truppen umkehrten, wenn ein neuer gespawnt war. Dieser Fehler blieb dann auch bestehen, als ich die armyTwo in "armeeZweite" umbenannt hatte. Das Endergebnis war dann, dass die Truppen sich langsam in Richtung PlayerHQ vorarbeiteten, und zwischendurch immer wieder umkehrten. Da sie aber nur sieben Sekunden hatten bis zum Angriffsbefehl, und 13, bis zum Spawn neuer Truppen, kamen sie tatsächlich voran. Anbei mein Skript, wisst ihr vielleicht einen Weg das zu umgehen?
-- 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") NewTribute1(); ModelOverwrite(); CreateArmyOne(); MakeInvulnerable(); if XNetwork.Manager_DoesExist() == 0 then for i = 1, 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, 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) troopDescription = { maxNumberOfSoldiers = 16, minNumberOfSoldiers = 0, experiencePoints = VERYLOW_EXPERIENCE, } troopDescription.leaderType = Entities.CU_Evil_LeaderBearman1 EnlargeArmy(armyOne,troopDescription) EnlargeArmy(armyOne,troopDescription) StartCountdown(20, ControlArmyOne, true) end function CreateArmyTwo() armeeZweite = {} armeeZweite.player = 5 armeeZweite.id = 7 armeeZweite.strength = 3 armeeZweite.position = GetPosition("NVolk") armeeZweite.rodeLength = 500 SetupArmy(armeeZweite) troopDescription = { maxNumberOfSoldiers = 16, minNumberOfSoldiers = 0, experiencePoints = VERYLOW_EXPERIENCE, } troopDescription.leaderType = Entities.CU_Evil_LeaderSkirmisher1 EnlargeArmy(armeeZweite,troopDescription) EnlargeArmy(armeeZweite,troopDescription) StartCountdown(20, ControlArmyTwo, true) end function ControlArmyOne() --if not armyOne.created then --armyOne.created = not IsDead(armyOne) --return false --end StartCountdown(1, CreateArmyTwo, false) StartCountdown(7, AngriffEins, false) end function ControlArmyTwo() StartCountdown(1, CreateArmyOne, false) StartCountdown(7, AngriffZwei, false) end function AngriffEins() Redeploy(armyOne, GetPosition("StartPos" ), 5000); --Attack(armyOne,"P3_HQ") Sound.PlayGUISound(Sounds.fanfare,95) end function AngriffZwei() Redeploy(armeeZweite, GetPosition("P3StartPos" ), 5000); --Attack(armeeZweite,"HQ1") Sound.PlayGUISound(Sounds.fanfare,95) 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 i=1 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 AddTribute( _tribute ) assert( type( _tribute ) == "table", "Tribut muß ein Table sein" ); assert( type( _tribute.text ) == "string", "Tribut.text muß ein String sein" ); assert( type( _tribute.cost ) == "table", "Tribut.cost muß ein Table sein" ); assert( type( _tribute.playerId ) == "number", "Tribut.playerId muß eine Nummer sein" ); assert( not _tribute.Tribute , "Tribut.Tribute darf nicht vorbelegt sein"); uniqueTributeCounter = uniqueTributeCounter or 1; _tribute.Tribute = uniqueTributeCounter; uniqueTributeCounter = uniqueTributeCounter + 1; local tResCost = {}; for k, v in pairs( _tribute.cost ) do assert( ResourceType[k] ); assert( type( v ) == "number" ); table.insert( tResCost, ResourceType[k] ); table.insert( tResCost, v ); end Logic.AddTribute( _tribute.playerId, _tribute.Tribute, 0, 0, _tribute.text, unpack( tResCost ) ); SetupTributePaid( _tribute ); return _tribute.Tribute; end --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --Hier werden unsere Tribute erstellt --+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --Tribut Packen WS0 function NewTribute1() local tribute = {}; tribute.playerId = 3; tribute.text = "Bietet Spieler 1 an, das Tor gegen 200 Gold zu oeffnen"; tribute.cost = { Gold = 0}; tribute.Callback = Tributcallback1; TributId1 = AddTribute( tribute ); end function Tributcallback1() NewTribute2() end function NewTribute2() local tribute = {}; tribute.playerId = 1; tribute.text = "Gebt Spieler 2 200 Gold um das Tor zu oeffnen"; tribute.cost = { Gold = 200}; tribute.Callback = Tributcallback2; TributId1 = AddTribute( tribute ); end function Tributcallback2() AddGold( 1, -200) AddGold( 3, 200) ReplaceEntity ("Tor1", Entities.XD_WallStraightGate ) 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 function GameCallback_FulfillTribute() --Im Multiplayer sind Tribute standardmäßig deaktiviert, daher muss man sie erst wieder aktivieren return 1 end
mcb
|
#12 17.11.2018 14:59 Beiträge: 1472 |
Du benutzt für beide Armeen dieselbe id, wenn du die
armeeZweite.id = 7
in
armeeZweite.id = 8
änderst, sollte es besser funktionieren.
Narnius
|
#13 17.11.2018 16:37 Beiträge: 34 |
Oh...
Zitat von mcb:
Du benutzt für beide Armeen dieselbe id, wenn du die
armeeZweite.id = 7
in
armeeZweite.id = 8
änderst, sollte es besser funktionieren.
Ups.
Vielen Dank!
Seiten: 1