[[http://www.siedler-games.de|{{:sg-link.jpg|}}]]
\\
[[http://www.siedler-portal.de/vb3/member.php?u=2111|Noigi]] \\
\\
====== Einleitung ======
Die atemberaubende Grafik von S5 lässt sich (meiner Meinung nach) mit den gegebenen Kameraeinstellungen nur sehr unzureichend auskosten. Die folgende Funktion ermöglicht es dem Spieler, während des Spieles zwischen der Standardsicht und einer rollenspieltypischen Schulterperspektive zu wechseln. In diesem Modus folgt die Kamera der selektierten Entität, die Sicht ist näher am Boden und Kipp- und Rotationswinkel lassen sich manuell verändern. Es dürften keine Komplikationen mit Briefings oder Cutscenes auftreten.
Im Endeffekt sieht die RPG-Sicht so aus:\\
\\
{{utilfunctions:rpg_demoscreen.jpg}}\\
\\
===== Einbauen =====
Um die RPG-Sicht in seiner Map zu ermöglichen, muss der unten stehende Zusatzcode ins Skript kopiert werden.\\
Der Aufruf erfolgt dann folgendermaßen:\\
EnableRPGView( "NameEinerEntity" )
\\
Dieser Skriptname gibt die Entität an, zur der die Kamera springt, wenn im RPG-Modus die selektierte Einheit stirbt.\\
Es sollte sich dabei also um eine "feste" Entität handeln, beispielsweise das Hauptquartier oder ein Held.\\
Wenn diese Entity im Verlauf des Spieles geändert werden soll, kann man das mit...\\
gvRPG.hero = "NameDerNeuenEntity"
\\
bewerkstelligen.\\
\\
Wenn es in der Map ein PreludeBriefing oder eine einleitende Cutscene gibt, sollte die Initialisierungsfunktion erst **danach**; also am Besten in der Finished-Funktion aufgerufen werden.\\
\\
===== Steuerung =====
Im Spiel kann die RPG-Sicht einfach per [Esc] an- und ausgeschaltet werden. In diesem Modus sind nun einige Funktionen (wie z.B. Speichern und Laden) nicht möglich, da sie zu Problemen führen können. Die neuen Funktionen zur Veränderung der Perspektive sind im Folgenden aufgelistet:\\
* [Einfg] dreht wie gewohnt die Kamera nach links; allerdings schwenkt sie nicht mehr automatisch zurück.\\
* [Entf] macht das gleiche rechtsrum. ;-)\\
* Mit [8] kann man im RPG-Modus nicht mehr die Armee 8 selektieren; hier ist die Taste dafür zuständig, die Kamera nach oben zu kippen. Das geht maximal bis man senkrecht auf den Beobachteten herunterschaut.\\
* [9] kippt entsprechend die Kamera nach unten. Die Untergrenze ist ein Winkel von 5° über dem Boden.\\
In Briefings und Cutscenes kann Escape wie gewohnt verwendet werden.\\
\\
===== Code =====
Mit Kommentaren...\\
function EnableRPGView( _heroName )
-- Die RPG-Sicht darf nicht schon einmal erstellt worden sein...
assert( not gvRPG, "RPGView ERROR: Attempt to setup RPG-View while already existing!" );
-- Der übergebene Name muss ein string sein...
assert( type( _heroName ) == "string", "RPGView ERROR: Hero Name must be a string!" );
-- Setup des golbalen RPG-tables...
gvRPG = {
hero = _heroName,
observedEntity = GetEntityId( _heroName ),
zoomangle = 20,
viewmode = "Normal",
EscapeFunc = function()
if gvRPG.viewmode == "Normal" then
RPGView_SwitchToRPGView();
elseif gvRPG.viewmode == "RPG" then
RPGView_SwitchToNormalView();
end
end
};
-- Speichere Backups der Ingame-Funktionen, die dieses Skript benutzt...
GameCallback_GUI_SelectionChanged_OrigRPGView = GameCallback_GUI_SelectionChanged;
GameCallback_Escape_OrigRPGView = GameCallback_Escape;
QuickSave_OrigRPGView = QuickSave;
QuickLoad_OrigRPGView = QuickLoad;
GUIAction_ChangeBuildingMenu_OrigRPGView = GUIAction_ChangeBuildingMenu;
GUIAction_JumpToBuildingOfWorker_OrigRPGView = GUIAction_JumpToBuildingOfWorker;
GroupSelection_SelectTroops_OrigRPGView = GroupSelection_SelectTroops;
StartBriefing_OrigRPGView = StartBriefing;
EndBriefing_OrigRPGView = EndBriefing;
if StartCutscene then
StartCutscene_OrigRPGView = StartCutscene;
end
if CutsceneDone then
CutsceneDone_OrigRPGView = CutsceneDone;
end
-- Erstelle eine neue Funktion, um die Kamera bei einem Selektionswechsel im RPG-Modus der neuen selektierten Entität folgen zu lassen...
RPGView_ControlCamera = function()
GameCallback_GUI_SelectionChanged_OrigRPGView();
if GUI.GetSelectedEntity() then
gvRPG.observedEntity = GUI.GetSelectedEntity();
Camera.FollowEntity( gvRPG.observedEntity );
elseif IsAlive( gvRPG.observedEntity ) then
local pos = GetPosition( gvRPG.observedEntity );
if ( type( pos ) == "table" ) and ( pos.X > 0 ) and ( pos.Y > 0 ) then
Camera.FollowEntity( gvRPG.observedEntity );
else
gvRPG.observedEntity = GetEntityId( gvRPG.hero );
Camera.FollowEntity( gvRPG.observedEntity );
end
else
gvRPG.observedEntity = GetEntityId( gvRPG.hero );
Camera.FollowEntity( gvRPG.observedEntity );
end
end
-- Überschreibe die Funktion , um per [Esc] zwischen normalem und RPG-Modus wechseln zu können...
GameCallback_Escape = gvRPG.EscapeFunc;
-- Überschreibe die Funktion , um Schnelles Speichern [F6] im RPG-Modus zu deaktivieren, da es zu Problemen führen kann...
QuickSave = function()
if gvRPG.viewmode == "Normal" then
QuickSave_OrigRPGView();
elseif gvRPG.viewmode == "RPG" then
Message("Das Spiel kann nur im normalen Modus gespeichert werden");
end
end
-- Überschreibe die Funktion , um Schnelles Laden [F7] im RPG-Modus zu deaktivieren, da es zu Problemen führen kann...
QuickLoad = function()
if gvRPG.viewmode == "Normal" then
QuickLoad_OrigRPGView();
elseif gvRPG.viewmode == "RPG" then
Message("Spielstände können nur im normalen Modus geladen werden");
end
end
-- Überschreibe die Funktion , um das Wechseln zwischen den Gebäudemenüs im RPG-Modus zu verhindern, da die Kamera der selektierten Entität sonst nicht mehr folgt...
GUIAction_ChangeBuildingMenu = function( _a )
if gvRPG.viewmode == "Normal" then
GUIAction_ChangeBuildingMenu_OrigRPGView( _a );
elseif gvRPG.viewmode == "RPG" then
Message("Diese Option steht nur im normalen Modus zur Verügung");
end
end
-- Überschreibe die Funktion , um das Springen zu den Gebäuden eines Arbeiters im RPG-Modus zu verhindern, da die Kamera der selektierten Entität sonst nicht mehr folgt...
GUIAction_JumpToBuildingOfWorker = function( _a )
if gvRPG.viewmode == "Normal" then
GUIAction_JumpToBuildingOfWorker_OrigRPGView( _a );
elseif gvRPG.viewmode == "RPG" then
Message("Diese Option steht nur im normalen Modus zur Verügung");
end
end
-- Überschreibe die Funktion , um im RPG-Modus das Verändern des Kippwinkels der Kamera durch Drücken von [8] und [9] zu ermöglichen...
GroupSelection_SelectTroops = function( _count )
if gvRPG.viewmode == "RPG" then
if _count == 8 then
if ( gvRPG.zoomangle+1 ) > 90 then
gvRPG.zoomangle = 90;
elseif ( gvRPG.zoomangle+1 ) < 5 then
gvRPG.zoomangle = 5;
else
gvRPG.zoomangle = ( gvRPG.zoomangle+1 );
end
Camera.ZoomSetAngle( gvRPG.zoomangle );
elseif _count == 9 then
if ( gvRPG.zoomangle-1 ) > 90 then
gvRPG.zoomangle = 90;
elseif ( gvRPG.zoomangle-1 ) < 5 then
gvRPG.zoomangle = 5;
else
gvRPG.zoomangle = ( gvRPG.zoomangle-1 );
end
Camera.ZoomSetAngle( gvRPG.zoomangle );
else
GroupSelection_SelectTroops_OrigRPGView( _count );
end
elseif gvRPG.viewmode == "Normal" then
GroupSelection_SelectTroops_OrigRPGView( _count );
else
assert( false, "RPGView ERROR: Invalid Viewmode!" );
end
end
-- Überschreibe die Funktion , um vor einem Briefing den aktuellen Modus auf "Normal" umzustellen und die Standard [Esc]-Funktion zu aktivieren...
StartBriefing = function( _briefing )
if gvRPG.viewmode == "RPG" then
RPGView_SwitchToNormalView();
end
GameCallback_Escape = GameCallback_Escape_OrigRPGView;
StartBriefing_OrigRPGView( _briefing );
Display.SetRenderFogOfWar(0);
end
-- Überschreibe die Funktion , um nach einem Briefing wieder die RPG-spezifische [Esc]-Funktion zu aktivieren...
EndBriefing = function( _briefing )
EndBriefing_OrigRPGView( _briefing );
Display.SetRenderFogOfWar(1);
GameCallback_Escape = gvRPG.EscapeFunc;
end
-- Überschreibe die Funktion , um vor einer Cutscene den aktuellen Modus auf "Normal" umzustellen und die Standard [Esc]-Funktion zu aktivieren...
if StartCutscene then
StartCutscene = function( _Cutscene, _EscapeMode )
if gvRPG.viewmode == "RPG" then
RPGView_SwitchToNormalView();
end
Camera.StopCameraFlight();
GameCallback_Escape = GameCallback_Escape_OrigRPGView;
StartCutscene_OrigRPGView( _Cutscene, _EscapeMode );
end
end
-- Überschreibe die Funktion , um nach einer Cutscene wieder die RPG-spezifische [Esc]-Funktion zu aktivieren...
if CutsceneDone then
CutsceneDone = function()
CutsceneDone_OrigRPGView()
GameCallback_Escape = gvRPG.EscapeFunc;
end
end
-- Vergrößere das Sichtfeld (beeinflusst nur den RPG-Modus), weil es so schöner aussieht... ;)
for i = 1,10 do
Camera_DecreaseFOV();
end
-- ...Ende des Setup.
end
function RPGView_SwitchToNormalView()
-- Dies ist die Funktion, die den Standard-Modus aktiviert.
-- Sie wird aufgerufen wenn [Esc] im RPG-Modus gedrückt wird...
assert( gvRPG.viewmode == "RPG", "RPGView ERROR: Attempt to toggle Normal view failed!" );
-- Aktiviere die Hauptmenü-Buttons zum Speichern und Laden von Spielständen...
XGUIEng.ShowWidget( gvGUI_WidgetID.MainMenuWindow_SaveGame, 1 );
XGUIEng.ShowWidget( gvGUI_WidgetID.MainMenuWindow_LoadGame, 1 );
-- Deaktiviere den Himmel...
Display.SetRenderSky(0);
-- Aktiviere den Nebel des Krieges...
Display.SetRenderFogOfWar(1);
-- Aktiviere den Standard Kamera-Modus...
Camera_ToggleDefault();
GUI.ClearNotes();
-- Benutze wieder die Original -Funktion...
GameCallback_GUI_SelectionChanged = GameCallback_GUI_SelectionChanged_OrigRPGView;
-- ...Und deklariere den aktuellen Modus als "Normal".
gvRPG.viewmode = "Normal";
end
function RPGView_SwitchToRPGView()
-- Dies ist die Funktion, die den RPG-Modus aktiviert.
-- Sie wird aufgerufen wenn [Esc] im normalen Modus gedrückt wird...
assert( gvRPG.viewmode == "Normal", "RPGView ERROR: Attempt to toggle RPG-view failed!" );
-- Deaktiviere die Hauptmenü-Buttons zum Speichern und Laden von Spielständen...
XGUIEng.ShowWidget( gvGUI_WidgetID.MainMenuWindow_SaveGame, 0 );
XGUIEng.ShowWidget( gvGUI_WidgetID.MainMenuWindow_LoadGame, 0 );
-- Aktiviere den Himmel...
Display.SetRenderSky(1);
-- Deaktiviere den Nebel des Krieges...
Display.SetRenderFogOfWar(0);
-- Deaktiviere den Standard Kamera-Modus...
Camera_ToggleDefault();
GUI.ClearNotes();
-- Wenn eine Entität selektiert ist, speichere diese als ...
if GUI.GetSelectedEntity() then
gvRPG.observedEntity = GUI.GetSelectedEntity();
end
-- Lass die Kamera der folgen...
Camera.FollowEntity( gvRPG.observedEntity );
-- Stelle den RPG-Standardzoomabstand ein...
Camera.ZoomSetDistance( 1200 );
-- Aktualisiere den aktuellen Kippwinkel, so dass man
Camera.ZoomSetAngle( gvRPG.zoomangle );
-- Lass die Kamera der "über die Schulter schauen"...
Camera.RotSetAngle( Logic.GetEntityOrientation( gvRPG.observedEntity ) - 90 );
-- Benutze die RPG-spezifische Callback-Funktion anstatt ...
GameCallback_GUI_SelectionChanged = RPGView_ControlCamera;
-- ...Und deklariere den aktuellen Modus als "RPG".
gvRPG.viewmode = "RPG";
end
\\
\\
...und in der platzsparenden Variante:\\
function EnableRPGView(_heroName)
assert(not gvRPG,"RPGView ERROR: Attempt to setup RPG-View while already existing!")
assert(type(_heroName)=="string","RPGView ERROR: Hero Name must be a string!")
gvRPG={
hero=_heroName,
observedEntity=GetEntityId(_heroName),
zoomangle=20,
viewmode="Normal",
EscapeFunc=function()
if gvRPG.viewmode=="Normal" then
RPGView_SwitchToRPGView()
elseif gvRPG.viewmode=="RPG" then
RPGView_SwitchToNormalView()
end
end
}
GameCallback_GUI_SelectionChanged_OrigRPGView=GameCallback_GUI_SelectionChanged
GameCallback_Escape_OrigRPGView=GameCallback_Escape
QuickSave_OrigRPGView=QuickSave
QuickLoad_OrigRPGView=QuickLoad
GUIAction_ChangeBuildingMenu_OrigRPGView=GUIAction_ChangeBuildingMenu
GUIAction_JumpToBuildingOfWorker_OrigRPGView=GUIAction_JumpToBuildingOfWorker
GroupSelection_SelectTroops_OrigRPGView=GroupSelection_SelectTroops
StartBriefing_OrigRPGView=StartBriefing
EndBriefing_OrigRPGView=EndBriefing
if StartCutscene then
StartCutscene_OrigRPGView=StartCutscene
end
if CutsceneDone then
CutsceneDone_OrigRPGView=CutsceneDone
end
RPGView_ControlCamera=function()
GameCallback_GUI_SelectionChanged_OrigRPGView()
if GUI.GetSelectedEntity()then
gvRPG.observedEntity=GUI.GetSelectedEntity()
Camera.FollowEntity(gvRPG.observedEntity)
elseif IsAlive(gvRPG.observedEntity)then
local pos=GetPosition(gvRPG.observedEntity)
if(type(pos)=="table")and(pos.X>0)and(pos.Y>0)then
Camera.FollowEntity(gvRPG.observedEntity)
else
gvRPG.observedEntity=GetEntityId(gvRPG.hero)
Camera.FollowEntity(gvRPG.observedEntity)
end
else
gvRPG.observedEntity=GetEntityId(gvRPG.hero)
Camera.FollowEntity(gvRPG.observedEntity)
end
end
GameCallback_Escape=gvRPG.EscapeFunc
QuickSave=function()
if gvRPG.viewmode=="Normal" then
QuickSave_OrigRPGView()
elseif gvRPG.viewmode=="RPG" then
Message("Das Spiel kann nur im normalen Modus gespeichert werden")
end
end
QuickLoad=function()
if gvRPG.viewmode=="Normal" then
QuickLoad_OrigRPGView()
elseif gvRPG.viewmode=="RPG" then
Message("Spielstände können nur im normalen Modus geladen werden")
end
end
GUIAction_ChangeBuildingMenu=function(_a)
if gvRPG.viewmode=="Normal" then
GUIAction_ChangeBuildingMenu_OrigRPGView(_a)
elseif gvRPG.viewmode=="RPG" then
Message("Diese Option steht nur im normalen Modus zur Verügung")
end
end
GUIAction_JumpToBuildingOfWorker=function(_a)
if gvRPG.viewmode=="Normal" then
GUIAction_JumpToBuildingOfWorker_OrigRPGView(_a)
elseif gvRPG.viewmode=="RPG" then
Message("Diese Option steht nur im normalen Modus zur Verügung")
end
end
GroupSelection_SelectTroops=function(_count)
if gvRPG.viewmode=="RPG" then
if _count==8 then
if(gvRPG.zoomangle+1)>90 then
gvRPG.zoomangle=90
elseif(gvRPG.zoomangle+1)<5 then
gvRPG.zoomangle=5
else
gvRPG.zoomangle=(gvRPG.zoomangle+1)
end
Camera.ZoomSetAngle(gvRPG.zoomangle)
elseif _count==9 then
if(gvRPG.zoomangle-1)>90 then
gvRPG.zoomangle=90
elseif(gvRPG.zoomangle-1)<5 then
gvRPG.zoomangle=5
else
gvRPG.zoomangle=(gvRPG.zoomangle-1)
end
Camera.ZoomSetAngle(gvRPG.zoomangle)
else
GroupSelection_SelectTroops_OrigRPGView(_count)
end
elseif gvRPG.viewmode=="Normal" then
GroupSelection_SelectTroops_OrigRPGView(_count)
else
assert(false,"RPGView ERROR: Invalid Viewmode!")
end
end
StartBriefing=function(_briefing)
if gvRPG.viewmode=="RPG" then
RPGView_SwitchToNormalView()
end
GameCallback_Escape=GameCallback_Escape_OrigRPGView
StartBriefing_OrigRPGView(_briefing)
Display.SetRenderFogOfWar(0)
end
EndBriefing=function(_briefing)
EndBriefing_OrigRPGView(_briefing)
Display.SetRenderFogOfWar(1)
GameCallback_Escape=gvRPG.EscapeFunc
end
if StartCutscene then
StartCutscene=function(_Cutscene,_EscapeMode)
if gvRPG.viewmode=="RPG" then
RPGView_SwitchToNormalView()
end
Camera.StopCameraFlight()
GameCallback_Escape=GameCallback_Escape_OrigRPGView
StartCutscene_OrigRPGView(_Cutscene,_EscapeMode)
end
end
if CutsceneDone then
CutsceneDone=function()
CutsceneDone_OrigRPGView()
GameCallback_Escape=gvRPG.EscapeFunc
end
end
for i=1,10 do
Camera_DecreaseFOV()
end
end
function RPGView_SwitchToNormalView()
assert(gvRPG.viewmode=="RPG","RPGView ERROR: Attempt to toggle Normal view failed!")
XGUIEng.ShowWidget(gvGUI_WidgetID.MainMenuWindow_SaveGame,1)
XGUIEng.ShowWidget(gvGUI_WidgetID.MainMenuWindow_LoadGame,1)
Display.SetRenderSky(0)
Display.SetRenderFogOfWar(1)
Camera_ToggleDefault()
GUI.ClearNotes()
GameCallback_GUI_SelectionChanged=GameCallback_GUI_SelectionChanged_OrigRPGView
gvRPG.viewmode="Normal"
end
function RPGView_SwitchToRPGView()
assert(gvRPG.viewmode=="Normal","RPGView ERROR: Attempt to toggle RPG-view failed!")
XGUIEng.ShowWidget(gvGUI_WidgetID.MainMenuWindow_SaveGame,0)
XGUIEng.ShowWidget(gvGUI_WidgetID.MainMenuWindow_LoadGame,0)
Display.SetRenderSky(1)
Display.SetRenderFogOfWar(0)
Camera_ToggleDefault()
GUI.ClearNotes()
if GUI.GetSelectedEntity()then
gvRPG.observedEntity=GUI.GetSelectedEntity()
end
Camera.FollowEntity(gvRPG.observedEntity)
Camera.ZoomSetDistance(1200)
Camera.ZoomSetAngle(gvRPG.zoomangle)
Camera.RotSetAngle(Logic.GetEntityOrientation(gvRPG.observedEntity)-90)
GameCallback_GUI_SelectionChanged=RPGView_ControlCamera
gvRPG.viewmode="RPG"
end
\\
Es werden keine zusätzlichen Comfort-Funktionen benötigt.\\