Wer kennt nicht die schönen Kameraflüge in den original BB Karten? Hiermit kann man das schon recht gut nachbauen.
Achtung: Dieser Artikel ist nicht mehr „aktuell“. Inzwischen gibt es die Möglichkeit bessere Cutscenes zu erstellen: Cutscenes (Neuer Stil).
Mit dieser Version können Marker, Quests und Pfeile erstellt werden. Diese können mit ResolveCutscene() gelöscht/als beendet gekennzeichnet werden. Alle diese zusätzlichen Elements können sowohl in der StartPosition als auch in den Flügen angegeben werden, wobei, falls nicht irgendwie anders angegeben, normalerweise immer die Zielposition (bei StartPosition natürlich die Start-Position) verwendet wird.
Außerdem wurde es ermöglicht, Cutscenes abzubrechen. Dabei ist zwischen drei Arten des Abbruchs zu unterscheiden:
kein Abbruch
seitenweiser Abbruch
vollständiger Abbruch
Der jeweilige Modus kann durch den zweiten Parameter bestimmt werden. Der Standard ist seitenweiser Abbruch. So können die Modi erzwungen werden:
kein Abbruch: 0 / true
seitenweiser Abbruch: 1 / false / nil (Standard)
vollständiger Abbruch: 2
function StartCutscene(_Cutscene, _EscapeMode) --possible: 0 (true), 1 (false, nil), 2: escape not allowed, allowed, skip all assert(type(_Cutscene) == "table") assert(not cutsceneIsActive and not briefingIsActive); -- Store data gvCutscene = { Page = 1, Flights = assert(type(_Cutscene.Flights) == "table" and _Cutscene.Flights), Callback = _Cutscene.Callback, EscapeOrig = GameCallback_Escape, Effect = Sound.GetVolumeAdjustment(3), Ambient = Sound.GetVolumeAdjustment(5), Music = Music.GetVolumeAdjustment(), Skip = false, SkipAll = _EscapeMode == 2, LastCall = 0, Job = 0, } local startPos = _Cutscene.StartPosition --Prepare Logic.SetGlobalInvulnerability(1) Interface_SetCinematicMode(1) Display.SetFarClipPlaneMinAndMax(0, 14000) XGUIEng.ShowWidget( "Cinematic_Headline", 1 ) --Init Sound Sound.PlayFeedbackSound(0,0) GUI.SetFeedbackSoundOutputState(0) Sound.SetVolumeAdjustment(3, gvCutscene.Effect / 2) Sound.SetVolumeAdjustment(5, gvCutscene.Ambient / 2) Music.SetVolumeAdjustment(gvCutscene.Music / 2) LocalMusic.SongLength = 0 cutsceneIsActive = true -- Init Camera Camera.StopCameraFlight() Camera.ZoomSetDistance(startPos.zoom) Camera.RotSetAngle(startPos.rotation) Camera.ZoomSetAngle(startPos.angle) Camera.ScrollSetLookAt(startPos.position.X,startPos.position.Y) -- Register counter Counter.SetLimit("Cutscene", -1) --Change Escape if not _EscapeMode or _EscapeMode ~= 0 then GameCallback_Escape = function() gvCutscene.EscapeOrig() CutsceneEscape() end end --create markers, pointers and quests CutsceneCreateSpecialEffects(startPos) -- Start! gvCutscene.Job = StartSimpleHiResJob("ControlCutscene") end function ControlCutscene() if gvCutscene.Skip then if gvCutscene.SkipAll then local page = gvCutscene.Flights[table.getn(gvCutscene.Flights)] --go to position --only look at must set (other values will be changed by Interface_SetCinematicMode) Camera.SetLookAt(assert(page.position.X), assert(page.position.Y)) gvCutscene.Page = page + 1 -- synchronize Counter.SetLimit( "Cutscene", 0 ) else --go to next page if CutsceneGoToNextFlight() then CutsceneDone() return true end end gvCutscene.Skip = false end -- page finished??? if Counter.Tick( "Cutscene" ) then --last page??? if CutsceneGoToNextFlight() then --done CutsceneDone() return true end end end function CutsceneDone() Logic.SetGlobalInvulnerability(0) Interface_SetCinematicMode(0) XGUIEng.ShowWidget("Cinematic_Headline", 0) Display.SetFarClipPlaneMinAndMax(0, 0) --Reset Sound Music.SetVolumeAdjustment(gvCutscene.Music) Sound.SetVolumeAdjustment(3, gvCutscene.Effect) Sound.SetVolumeAdjustment(5, gvCutscene.Ambient) GUI.SetFeedbackSoundOutputState(1) --reset music LocalMusic.SongLength = 0 --reset escape GameCallback_Escape = gvCutscene.EscapeOrig --end cutscene job EndJob(gvCutscene.Job) -- destroy cutscene Counter.Cutscene = nil local callback = gvCutscene.Callback gvCutscene = nil cutsceneIsActive = false -- execute callback if callback ~= nil then xpcall( callback, function() end ) end end function CutsceneEscape() gvCutscene.Skip = true --Call ControlCutscene() ControlCutscene() end function ResolveCutscene(_flight) --change quest type if _flight.quest then local quest = _flight.quest Logic.SetQuestType(GUI.GetPlayerID(), quest.id, quest.type + 1, 1) end --destroy marker if _flight.marker then if type(_flight.marker) == "table" then for k, v in pairs(_flight.marker) do local pos = v.position GUI.DestroyMinimapPulse(pos.X, pos.Y) end else GUI.DestroyMinimapPulse(_flight.position.X, _flight.position.Y) end end --destroy pointer if _flight.pointer then Logic.DestroyEffect(_flight.pointer.id) end end function CutsceneGoToNextFlight() local page = gvCutscene.Page; --go if gvCutscene.Flights[page] == nil then return true; end local firstNotShownPage = page while gvCutscene.Flights[page] ~= nil and (gvCutscene.Flights[page].duration or 0) + (gvCutscene.Flights[page].delay or 0) == 0 do page = page + 1 end if firstNotShownPage ~= page then --go to local flight = gvCutscene.Flights[page - 1] Camera.StopCameraFlight(); if flight.zoom then Camera.ZoomSetDistance(flight.zoom) end if flight.angle then Camera.ZoomSetAngle(flight.angle) end if flight.rotation then Camera.RotSetAngle(flight.rotation) end Camera.ScrollSetLookAt(assert(flight.position.X), assert(flight.position.Y)) --create special effects CutsceneCreateSpecialEffects(flight) gvCutscene.Page = page Counter.SetLimit( "Cutscene", 0 ) else local flight = gvCutscene.Flights[page]; Camera.InitCameraFlight() if flight.zoom then Camera.ZoomSetDistanceFlight(flight.zoom) end if flight.angle then Camera.ZoomSetAngleFlight(flight.angle) end if flight.rotation then Camera.RotFlight(flight.rotation) end Camera.FlyToLookAt(assert(flight.position.X), assert(flight.position.Y), flight.duration or 0) CutsceneCreateSpecialEffects(flight) gvCutscene.Page = page + 1 Counter.SetLimit( "Cutscene", ((flight.duration or 0) + (flight.delay or 0)) * 10) end end function CutsceneCreateSpecialEffects(_page) assert(type(_page) == "table") if _page.pointer then _page.pointer.id = Logic.CreateEffect(GGL_Effects.FXTerrainPointer, _page.pointer.X, _page.pointer.Y, GUI.GetPlayerID()) end if _page.quest then Logic.CreateQuestEx(GUI.GetPlayerID(), _page.quest.id, _page.quest.type, _page.quest.title, _page.quest.text, _page.position.X, _page.position.Y, 1) end if _page.marker then if type(_page.marker) == "table" then table.foreach(_page.marker, function(_, __v) ShowBriefingMarker(__v) end) else ShowBriefingMarker(_page) end end if _page.text then PrintBriefingText(_page.text) end if _page.title then PrintBriefingHeadline("@color:255,250,200 " .. _page.title) end end
Normalerweise muss man fast alle Cutscenes-Einstellungen raten, denn es existierte kein Tool, um Cutscenes zu erstellen. Dies ist nun anders. Jetzt kann man Cutscenes direkt in der Map vorbereiten.
Dieses Tool muss in das Map-Script eingefügt werden oder extern geladen werden. Nähere Erläuterungen findet ihr hier.