From 735f9cc06b639fdd18dad54f11197fed33b04fa6 Mon Sep 17 00:00:00 2001 From: Nicolas Hake Date: Sat, 2 Apr 2016 17:50:49 +0200 Subject: [PATCH] C4Landscape: Pull everything private out of the header Since LTCG is enabled now, we don't have to define every function inside the headers for ~xXx super speed xXx~, which means we can strip the headers down to their bare minimum and reduce interdependencies and therefore recompilation times by a lot. --- src/control/C4Control.cpp | 8 +- src/control/C4Control.h | 5 +- src/control/C4GameSave.cpp | 8 +- src/editor/C4Console.cpp | 2 +- src/editor/C4ConsoleCocoa.mm | 7 +- src/editor/C4ConsoleGTK.cpp | 49 +- src/editor/C4ConsoleWin32.cpp | 67 +- src/editor/C4EditCursor.cpp | 24 +- src/editor/C4EditorWindowController.mm | 2 +- src/editor/C4ToolsDlg.cpp | 30 +- src/editor/C4ToolsDlg.h | 4 +- src/editor/C4ViewportWindow.cpp | 8 +- src/game/C4Game.cpp | 29 +- src/game/C4GameScript.cpp | 42 +- src/game/C4GraphicsSystem.cpp | 11 +- src/game/C4Physics.h | 2 +- src/game/C4Viewport.cpp | 43 +- src/graphics/C4DrawGLMac.mm | 2 +- src/graphics/CSurface8.cpp | 2 +- src/graphics/CSurface8.h | 2 +- src/gui/C4MouseControl.cpp | 2 +- src/landscape/C4Landscape.cpp | 2555 ++++++++++++--------- src/landscape/C4Landscape.h | 291 +-- src/landscape/C4MassMover.cpp | 2 +- src/landscape/C4Material.cpp | 4 +- src/landscape/C4PXS.cpp | 4 +- src/landscape/C4Particles.cpp | 2 +- src/landscape/C4Sky.cpp | 2 +- src/landscape/C4SolidMask.cpp | 28 +- src/landscape/C4TextureShape.cpp | 10 +- src/landscape/C4TextureShape.h | 2 +- src/landscape/fow/C4FoWAmbient.cpp | 14 +- src/landscape/fow/C4FoWAmbient.h | 5 +- src/landscape/fow/C4FoWLightSection.cpp | 2 +- src/mape/cpp-handles/landscape-handle.cpp | 55 +- src/mape/cpp-handles/stub-handle.cpp | 10 +- src/object/C4Command.cpp | 6 +- src/object/C4Movement.cpp | 14 +- src/object/C4Object.cpp | 4 +- src/object/C4Shape.cpp | 4 +- src/platform/C4WindowController.mm | 8 +- src/player/C4Player.cpp | 20 +- 42 files changed, 1816 insertions(+), 1575 deletions(-) diff --git a/src/control/C4Control.cpp b/src/control/C4Control.cpp index 8adb93d05..a20ee7e60 100644 --- a/src/control/C4Control.cpp +++ b/src/control/C4Control.cpp @@ -1373,7 +1373,7 @@ void C4ControlEMMoveObject::CompileFunc(StdCompiler *pComp) // *** C4ControlEMDrawTool -C4ControlEMDrawTool::C4ControlEMDrawTool(C4ControlEMDrawAction eAction, int32_t iMode, +C4ControlEMDrawTool::C4ControlEMDrawTool(C4ControlEMDrawAction eAction, LandscapeMode iMode, int32_t iX, int32_t iY, int32_t iX2, int32_t iY2, int32_t iGrade, const char *szMaterial, const char *szTexture, const char *szBackMaterial, const char *szBackTexture) : eAction(eAction), iMode(iMode), iX(iX), iY(iY), iX2(iX2), iY2(iY2), iGrade(iGrade), @@ -1392,8 +1392,8 @@ void C4ControlEMDrawTool::Execute() const return; } // check current mode - assert(::Landscape.Mode == iMode); - if (::Landscape.Mode != iMode) return; + assert(::Landscape.GetMode() == iMode); + if (::Landscape.GetMode() != iMode) return; // assert validity of parameters if (!Material.getSize()) return; const char *szMaterial = Material.getData(), @@ -1436,7 +1436,7 @@ void C4ControlEMDrawTool::Execute() const void C4ControlEMDrawTool::CompileFunc(StdCompiler *pComp) { pComp->Value(mkNamingAdapt(mkIntAdaptT(eAction), "Action")); - pComp->Value(mkNamingAdapt(mkIntPackAdapt(iMode), "Mode", 0)); + pComp->Value(mkNamingAdapt(mkIntAdaptT(iMode), "Mode", LandscapeMode::Undefined)); pComp->Value(mkNamingAdapt(iX, "X", 0)); pComp->Value(mkNamingAdapt(iY, "Y", 0)); pComp->Value(mkNamingAdapt(iX2, "X2", 0)); diff --git a/src/control/C4Control.h b/src/control/C4Control.h index 9a358f75d..8cbf95f11 100644 --- a/src/control/C4Control.h +++ b/src/control/C4Control.h @@ -486,17 +486,18 @@ enum C4ControlEMDrawAction EMDT_Rect // drawing tool }; +enum class LandscapeMode; class C4ControlEMDrawTool : public C4ControlPacket // sync { public: C4ControlEMDrawTool() : eAction(EMDT_SetMode), iX(0), iY(0), iX2(0), iY2(0), iGrade(0) { } - C4ControlEMDrawTool(C4ControlEMDrawAction eAction, int32_t iMode, + C4ControlEMDrawTool(C4ControlEMDrawAction eAction, LandscapeMode iMode, int32_t iX=-1, int32_t iY=-1, int32_t iX2=-1, int32_t iY2=-1, int32_t iGrade=-1, const char *szMaterial=NULL, const char *szTexture=NULL, const char *szBackMaterial=NULL, const char *szBackTexture=NULL); protected: C4ControlEMDrawAction eAction; // action to be performed - int32_t iMode; // new mode, or mode action was performed in (action will fail if changed) + LandscapeMode iMode; // new mode, or mode action was performed in (action will fail if changed) int32_t iX,iY,iX2,iY2,iGrade; // drawing parameters StdStrBuf Material; // used material StdStrBuf Texture; // used texture diff --git a/src/control/C4GameSave.cpp b/src/control/C4GameSave.cpp index c6c4f1993..d50f3d0ac 100644 --- a/src/control/C4GameSave.cpp +++ b/src/control/C4GameSave.cpp @@ -139,12 +139,12 @@ bool C4GameSave::SaveScenarioSections() bool C4GameSave::SaveLandscape() { // exact? - if (::Landscape.Mode == C4LSC_Exact || GetForceExactLandscape()) + if (::Landscape.GetMode() == LandscapeMode::Exact || GetForceExactLandscape()) { C4DebugRecOff DBGRECOFF; // Landscape bool fSuccess; - if (::Landscape.Mode == C4LSC_Exact) + if (::Landscape.GetMode() == LandscapeMode::Exact) fSuccess = !!::Landscape.Save(*pSaveGroup); else fSuccess = !!::Landscape.SaveDiff(*pSaveGroup, !IsSynced()); @@ -160,7 +160,7 @@ bool C4GameSave::SaveLandscape() if (!::MaterialMap.SaveEnumeration(*pSaveGroup)) return false; } // static / dynamic - if (::Landscape.Mode == C4LSC_Static) + if (::Landscape.GetMode() == LandscapeMode::Static) { // static map // remove old-style landscape.bmp @@ -174,7 +174,7 @@ bool C4GameSave::SaveLandscape() if (!::Landscape.SaveTextures(*pSaveGroup)) return false; } } - else if (::Landscape.Mode != C4LSC_Exact) + else if (::Landscape.GetMode() != LandscapeMode::Exact) { // dynamic map by landscape.txt or scenario core: nothing to save // in fact, it doesn't even make much sense to save the Objects.txt diff --git a/src/editor/C4Console.cpp b/src/editor/C4Console.cpp index ae4bac94b..9accd1fbd 100644 --- a/src/editor/C4Console.cpp +++ b/src/editor/C4Console.cpp @@ -189,7 +189,7 @@ bool C4Console::SaveScenario(const char * path) SetCursor(C4ConsoleGUI::CURSOR_Wait); bool fOkay=true; - C4GameSave *pGameSave = new C4GameSaveScenario(!Console.Active || ::Landscape.Mode==C4LSC_Exact, false); + C4GameSave *pGameSave = new C4GameSaveScenario(!Console.Active || ::Landscape.GetMode() == LandscapeMode::Exact, false); if (!pGameSave->Save(Game.ScenarioFile, false)) { Out("Game::Save failed"); fOkay=false; } delete pGameSave; diff --git a/src/editor/C4ConsoleCocoa.mm b/src/editor/C4ConsoleCocoa.mm index 97098431d..09911deb7 100644 --- a/src/editor/C4ConsoleCocoa.mm +++ b/src/editor/C4ConsoleCocoa.mm @@ -26,6 +26,7 @@ #include #include #include +#include "landscape/C4Sky.h" #include #include #include @@ -221,7 +222,7 @@ void C4ToolsDlg::UpdateTextures() [texturesPopup removeAllItems]; // bottom-most: any invalid textures bool fAnyEntry = false; int32_t cnt; const char *szTexture; - if (::Landscape.Mode!=C4LSC_Exact) + if (::Landscape.GetMode()!=LandscapeMode::Exact) for (cnt=0; (szTexture=::TextureMap.GetTexture(cnt)); cnt++) { if (!::TextureMap.GetIndex(Material, szTexture, false)) @@ -240,7 +241,7 @@ void C4ToolsDlg::UpdateTextures() for (cnt=0; (szTexture=::TextureMap.GetTexture(cnt)); cnt++) { // Current material-texture valid? Always valid for exact mode - if (::TextureMap.GetIndex(Material,szTexture,false) || ::Landscape.Mode==C4LSC_Exact) + if (::TextureMap.GetIndex(Material,szTexture,false) || ::Landscape.GetMode()==LandscapeMode::Exact) { [texturesPopup insertItemWithTitle:[NSString stringWithUTF8String:szTexture] atIndex:0]; } @@ -295,7 +296,7 @@ CGImageRef C4ToolsDlg::State::CreatePreviewImage() // Sky material: sky as pattern only if (SEqual(GetOwner()->Material,C4TLS_MatSky)) { - Pattern.Set(::Landscape.Sky.Surface, 0); + Pattern.Set(::Landscape.GetSky().Surface, 0); } // Material-Texture else diff --git a/src/editor/C4ConsoleGTK.cpp b/src/editor/C4ConsoleGTK.cpp index ccd802f53..bbc48582a 100644 --- a/src/editor/C4ConsoleGTK.cpp +++ b/src/editor/C4ConsoleGTK.cpp @@ -32,6 +32,7 @@ #include #include #include +#include "landscape/C4Sky.h" #include #include #include @@ -1266,7 +1267,7 @@ void C4ToolsDlg::UpdateTextures() // bottom-most: any invalid textures bool fAnyEntry = false; int32_t cnt; const char *szTexture; - if (::Landscape.Mode!=C4LSC_Exact) + if (::Landscape.GetMode()!=LandscapeMode::Exact) for (cnt=0; (szTexture=::TextureMap.GetTexture(cnt)); cnt++) { if (!::TextureMap.GetIndex(material, szTexture, false)) @@ -1285,7 +1286,7 @@ void C4ToolsDlg::UpdateTextures() for (cnt=0; (szTexture=::TextureMap.GetTexture(cnt)); cnt++) { // Current material-texture valid? Always valid for exact mode - if (::TextureMap.GetIndex(material,szTexture,false) || ::Landscape.Mode==C4LSC_Exact) + if (::TextureMap.GetIndex(material,szTexture,false) || ::Landscape.GetMode()==LandscapeMode::Exact) { gtk_combo_box_text_prepend_text(GTK_COMBO_BOX_TEXT(box), szTexture); } @@ -1324,7 +1325,7 @@ void C4ToolsDlg::State::UpdatePreview() // Sky material: sky as pattern only if (SEqual(dlg->Material,C4TLS_MatSky)) { - Pattern.Set(::Landscape.Sky.Surface, 0); + Pattern.Set(::Landscape.GetSky().Surface, 0); } // Material-Texture else @@ -1373,24 +1374,24 @@ void C4ToolsDlg::UpdateLandscapeModeCtrls() void C4ToolsDlg::State::UpdateLandscapeModeCtrls() { - int32_t iMode = ::Landscape.Mode; + LandscapeMode iMode = ::Landscape.GetMode(); g_signal_handler_block(landscape_dynamic, handlerDynamic); g_signal_handler_block(landscape_static, handlerStatic); g_signal_handler_block(landscape_exact, handlerExact); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(landscape_dynamic), iMode==C4LSC_Dynamic); - gtk_widget_set_sensitive(landscape_dynamic, iMode==C4LSC_Dynamic); + gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(landscape_dynamic), iMode==LandscapeMode::Dynamic); + gtk_widget_set_sensitive(landscape_dynamic, iMode==LandscapeMode::Dynamic); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(landscape_static), iMode==C4LSC_Static); + gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(landscape_static), iMode==LandscapeMode::Static); gtk_widget_set_sensitive(landscape_static, ::Landscape.HasMap()); - gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(landscape_exact), iMode==C4LSC_Exact); + gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(landscape_exact), iMode==LandscapeMode::Exact); g_signal_handler_unblock(landscape_dynamic, handlerDynamic); g_signal_handler_unblock(landscape_static, handlerStatic); g_signal_handler_unblock(landscape_exact, handlerExact); - C4DevmodeDlg::SetTitle(hbox, LoadResStr(iMode==C4LSC_Dynamic ? "IDS_DLG_DYNAMIC" : iMode==C4LSC_Static ? "IDS_DLG_STATIC" : "IDS_DLG_EXACT")); + C4DevmodeDlg::SetTitle(hbox, LoadResStr(iMode==LandscapeMode::Dynamic ? "IDS_DLG_DYNAMIC" : iMode==LandscapeMode::Static ? "IDS_DLG_STATIC" : "IDS_DLG_EXACT")); } void C4ToolsDlg::UpdateIFTControls() @@ -1441,18 +1442,18 @@ void C4ConsoleGUI::SetCaptionToFileName(const char* file_name) void C4ToolsDlg::EnableControls() { - int32_t iLandscapeMode=::Landscape.Mode; - gtk_widget_set_sensitive(state->brush, iLandscapeMode>=C4LSC_Static); - gtk_widget_set_sensitive(state->line, iLandscapeMode>=C4LSC_Static); - gtk_widget_set_sensitive(state->rect, iLandscapeMode>=C4LSC_Static); - gtk_widget_set_sensitive(state->fill, iLandscapeMode>=C4LSC_Exact); - gtk_widget_set_sensitive(state->picker, iLandscapeMode>=C4LSC_Static); - gtk_widget_set_sensitive(state->fg_materials, iLandscapeMode>=C4LSC_Static); - gtk_widget_set_sensitive(state->fg_textures, iLandscapeMode >= C4LSC_Static && !SEqual(Material,C4TLS_MatSky)); - gtk_widget_set_sensitive(state->bg_materials, iLandscapeMode>=C4LSC_Static && !SEqual(Material,C4TLS_MatSky)); - gtk_widget_set_sensitive(state->bg_textures, iLandscapeMode >= C4LSC_Static && !SEqual(Material,C4TLS_MatSky) && !SEqual(BackMaterial, C4TLS_MatSky)); - gtk_widget_set_sensitive(state->scale, iLandscapeMode>=C4LSC_Static); - gtk_widget_set_sensitive(state->preview, iLandscapeMode>=C4LSC_Static); + LandscapeMode iLandscapeMode=::Landscape.GetMode(); + gtk_widget_set_sensitive(state->brush, iLandscapeMode>=LandscapeMode::Static); + gtk_widget_set_sensitive(state->line, iLandscapeMode>=LandscapeMode::Static); + gtk_widget_set_sensitive(state->rect, iLandscapeMode>=LandscapeMode::Static); + gtk_widget_set_sensitive(state->fill, iLandscapeMode>=LandscapeMode::Exact); + gtk_widget_set_sensitive(state->picker, iLandscapeMode>=LandscapeMode::Static); + gtk_widget_set_sensitive(state->fg_materials, iLandscapeMode>=LandscapeMode::Static); + gtk_widget_set_sensitive(state->fg_textures, iLandscapeMode >= LandscapeMode::Static && !SEqual(Material,C4TLS_MatSky)); + gtk_widget_set_sensitive(state->bg_materials, iLandscapeMode>=LandscapeMode::Static && !SEqual(Material,C4TLS_MatSky)); + gtk_widget_set_sensitive(state->bg_textures, iLandscapeMode >= LandscapeMode::Static && !SEqual(Material,C4TLS_MatSky) && !SEqual(BackMaterial, C4TLS_MatSky)); + gtk_widget_set_sensitive(state->scale, iLandscapeMode>=LandscapeMode::Static); + gtk_widget_set_sensitive(state->preview, iLandscapeMode>=LandscapeMode::Static); NeedPreviewUpdate(); } @@ -1588,17 +1589,17 @@ void C4ConsoleGUI::State::OnNetClient(GtkWidget* item, gpointer data) void C4ToolsDlg::State::OnButtonModeDynamic(GtkWidget* widget, gpointer data) { - static_cast(data)->GetOwner()->SetLandscapeMode(C4LSC_Dynamic); + static_cast(data)->GetOwner()->SetLandscapeMode(LandscapeMode::Dynamic); } void C4ToolsDlg::State::OnButtonModeStatic(GtkWidget* widget, gpointer data) { - static_cast(data)->GetOwner()->SetLandscapeMode(C4LSC_Static); + static_cast(data)->GetOwner()->SetLandscapeMode(LandscapeMode::Static); } void C4ToolsDlg::State::OnButtonModeExact(GtkWidget* widget, gpointer data) { - static_cast(data)->GetOwner()->SetLandscapeMode(C4LSC_Exact); + static_cast(data)->GetOwner()->SetLandscapeMode(LandscapeMode::Exact); } void C4ToolsDlg::State::OnButtonBrush(GtkWidget* widget, gpointer data) diff --git a/src/editor/C4ConsoleWin32.cpp b/src/editor/C4ConsoleWin32.cpp index a4bae14c4..6def3e4ba 100644 --- a/src/editor/C4ConsoleWin32.cpp +++ b/src/editor/C4ConsoleWin32.cpp @@ -31,6 +31,7 @@ #include "C4Viewport.h" #include #include "lib/StdColors.h" +#include "landscape/C4Sky.h" #include #include @@ -630,15 +631,15 @@ INT_PTR CALLBACK ToolsDlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam) return true; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - case IDC_BUTTONMODEDYNAMIC: - Console.ToolsDlg.SetLandscapeMode(C4LSC_Dynamic); + Console.ToolsDlg.SetLandscapeMode(LandscapeMode::Dynamic); return true; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - case IDC_BUTTONMODESTATIC: - Console.ToolsDlg.SetLandscapeMode(C4LSC_Static); + Console.ToolsDlg.SetLandscapeMode(LandscapeMode::Static); return true; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - case IDC_BUTTONMODEEXACT: - Console.ToolsDlg.SetLandscapeMode(C4LSC_Exact); + Console.ToolsDlg.SetLandscapeMode(LandscapeMode::Exact); return true; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - case IDC_BUTTONBRUSH: @@ -1251,7 +1252,7 @@ void C4ToolsDlg::UpdateTextures() SendDlgItemMessage(state->hDialog, box, CB_RESETCONTENT, 0, (LPARAM)0); // bottom-most: any invalid textures bool fAnyEntry = false; int32_t cnt; const char *szTexture; - if (::Landscape.Mode != C4LSC_Exact) + if (::Landscape.GetMode() != LandscapeMode::Exact) for (cnt = 0; (szTexture = ::TextureMap.GetTexture(cnt)); cnt++) { if (!::TextureMap.GetIndex(material, szTexture, false)) @@ -1275,7 +1276,7 @@ void C4ToolsDlg::UpdateTextures() for (cnt = 0; (szTexture = ::TextureMap.GetTexture(cnt)); cnt++) { // Current material-texture valid? Always valid for exact mode - if (::TextureMap.GetIndex(material, szTexture, false) || ::Landscape.Mode == C4LSC_Exact) + if (::TextureMap.GetIndex(material, szTexture, false) || ::Landscape.GetMode() == LandscapeMode::Exact) { SendDlgItemMessage(state->hDialog, box, CB_INSERTSTRING, 0, GetWideLPARAM(szTexture)); } @@ -1311,7 +1312,7 @@ void C4ToolsDlg::NeedPreviewUpdate() // Sky material: sky as pattern only if (SEqual(Material,C4TLS_MatSky)) { - Pattern.Set(::Landscape.Sky.Surface, 0); + Pattern.Set(::Landscape.GetSky().Surface, 0); } // Material-Texture else @@ -1375,52 +1376,52 @@ void C4ToolsDlg::UpdateIFTControls() void C4ToolsDlg::UpdateLandscapeModeCtrls() { - int32_t iMode = ::Landscape.Mode; + LandscapeMode iMode = ::Landscape.GetMode(); // Dynamic: enable only if dynamic anyway - SendDlgItemMessage(state->hDialog,IDC_BUTTONMODEDYNAMIC,BM_SETSTATE,(iMode==C4LSC_Dynamic),0); - EnableWindow(GetDlgItem(state->hDialog,IDC_BUTTONMODEDYNAMIC),(iMode==C4LSC_Dynamic)); + SendDlgItemMessage(state->hDialog,IDC_BUTTONMODEDYNAMIC,BM_SETSTATE,(iMode==LandscapeMode::Dynamic),0); + EnableWindow(GetDlgItem(state->hDialog,IDC_BUTTONMODEDYNAMIC),(iMode==LandscapeMode::Dynamic)); UpdateWindow(GetDlgItem(state->hDialog,IDC_BUTTONMODEDYNAMIC)); // Static: enable only if map available - SendDlgItemMessage(state->hDialog,IDC_BUTTONMODESTATIC,BM_SETSTATE,(iMode==C4LSC_Static),0); + SendDlgItemMessage(state->hDialog,IDC_BUTTONMODESTATIC,BM_SETSTATE,(iMode==LandscapeMode::Static),0); EnableWindow(GetDlgItem(state->hDialog,IDC_BUTTONMODESTATIC),(::Landscape.HasMap())); UpdateWindow(GetDlgItem(state->hDialog,IDC_BUTTONMODESTATIC)); // Exact: enable always - SendDlgItemMessage(state->hDialog,IDC_BUTTONMODEEXACT,BM_SETSTATE,(iMode==C4LSC_Exact),0); + SendDlgItemMessage(state->hDialog,IDC_BUTTONMODEEXACT,BM_SETSTATE,(iMode==LandscapeMode::Exact),0); UpdateWindow(GetDlgItem(state->hDialog,IDC_BUTTONMODEEXACT)); // Set dialog caption - SetWindowTextW(state->hDialog,LoadResStrW(iMode==C4LSC_Dynamic ? "IDS_DLG_DYNAMIC" : iMode==C4LSC_Static ? "IDS_DLG_STATIC" : "IDS_DLG_EXACT")); + SetWindowTextW(state->hDialog,LoadResStrW(iMode==LandscapeMode::Dynamic ? "IDS_DLG_DYNAMIC" : iMode==LandscapeMode::Static ? "IDS_DLG_STATIC" : "IDS_DLG_EXACT")); } void C4ToolsDlg::EnableControls() { HWND hDialog = state->hDialog; - int32_t iLandscapeMode=::Landscape.Mode; + LandscapeMode iLandscapeMode = ::Landscape.GetMode(); // Set bitmap buttons - SendDlgItemMessage(hDialog,IDC_BUTTONBRUSH,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)((iLandscapeMode>=C4LSC_Static) ? state->hbmBrush : state->hbmBrush2)); - SendDlgItemMessage(hDialog,IDC_BUTTONLINE,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)((iLandscapeMode>=C4LSC_Static) ? state->hbmLine : state->hbmLine2)); - SendDlgItemMessage(hDialog,IDC_BUTTONRECT,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)((iLandscapeMode>=C4LSC_Static) ? state->hbmRect : state->hbmRect2)); - SendDlgItemMessage(hDialog,IDC_BUTTONFILL,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)((iLandscapeMode>=C4LSC_Exact) ? state->hbmFill : state->hbmFill2)); - SendDlgItemMessage(hDialog,IDC_BUTTONPICKER,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)((iLandscapeMode>=C4LSC_Static) ? state->hbmPicker : state->hbmPicker2)); + SendDlgItemMessage(hDialog,IDC_BUTTONBRUSH,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)((iLandscapeMode>=LandscapeMode::Static) ? state->hbmBrush : state->hbmBrush2)); + SendDlgItemMessage(hDialog,IDC_BUTTONLINE,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)((iLandscapeMode>=LandscapeMode::Static) ? state->hbmLine : state->hbmLine2)); + SendDlgItemMessage(hDialog,IDC_BUTTONRECT,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)((iLandscapeMode>=LandscapeMode::Static) ? state->hbmRect : state->hbmRect2)); + SendDlgItemMessage(hDialog,IDC_BUTTONFILL,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)((iLandscapeMode>=LandscapeMode::Exact) ? state->hbmFill : state->hbmFill2)); + SendDlgItemMessage(hDialog,IDC_BUTTONPICKER,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)((iLandscapeMode>=LandscapeMode::Static) ? state->hbmPicker : state->hbmPicker2)); SendDlgItemMessage(hDialog,IDC_BUTTONMODEDYNAMIC,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)state->hbmDynamic); SendDlgItemMessage(hDialog,IDC_BUTTONMODESTATIC,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)state->hbmStatic); SendDlgItemMessage(hDialog,IDC_BUTTONMODEEXACT,BM_SETIMAGE,IMAGE_BITMAP,(LPARAM)state->hbmExact); // Enable drawing controls - EnableWindow(GetDlgItem(hDialog,IDC_BUTTONBRUSH),(iLandscapeMode>=C4LSC_Static)); - EnableWindow(GetDlgItem(hDialog,IDC_BUTTONLINE),(iLandscapeMode>=C4LSC_Static)); - EnableWindow(GetDlgItem(hDialog,IDC_BUTTONRECT),(iLandscapeMode>=C4LSC_Static)); - EnableWindow(GetDlgItem(hDialog,IDC_BUTTONFILL),(iLandscapeMode>=C4LSC_Exact)); - EnableWindow(GetDlgItem(hDialog,IDC_BUTTONPICKER),(iLandscapeMode>=C4LSC_Static)); - EnableWindow(GetDlgItem(hDialog,IDC_COMBOFGMATERIAL),(iLandscapeMode>=C4LSC_Static)); - EnableWindow(GetDlgItem(hDialog,IDC_COMBOFGTEXTURE),(iLandscapeMode>=C4LSC_Static) && !SEqual(Material,C4TLS_MatSky)); - EnableWindow(GetDlgItem(hDialog,IDC_COMBOBGMATERIAL), (iLandscapeMode >= C4LSC_Static) && !SEqual(Material, C4TLS_MatSky)); - EnableWindow(GetDlgItem(hDialog, IDC_COMBOBGTEXTURE), (iLandscapeMode >= C4LSC_Static) && !SEqual(Material, C4TLS_MatSky) && !SEqual(BackMaterial, C4TLS_MatSky)); - EnableWindow(GetDlgItem(hDialog,IDC_STATICMATERIAL),(iLandscapeMode>=C4LSC_Static)); - EnableWindow(GetDlgItem(hDialog,IDC_STATICTEXTURE),(iLandscapeMode>=C4LSC_Static) && !SEqual(Material,C4TLS_MatSky)); - EnableWindow(GetDlgItem(hDialog,IDC_STATICFOREGROUND), (iLandscapeMode >= C4LSC_Static)); - EnableWindow(GetDlgItem(hDialog,IDC_STATICBACKGROUND), (iLandscapeMode >= C4LSC_Static)); - EnableWindow(GetDlgItem(hDialog,IDC_SLIDERGRADE),(iLandscapeMode>=C4LSC_Static)); - EnableWindow(GetDlgItem(hDialog,IDC_PREVIEW),(iLandscapeMode>=C4LSC_Static)); + EnableWindow(GetDlgItem(hDialog,IDC_BUTTONBRUSH),(iLandscapeMode>=LandscapeMode::Static)); + EnableWindow(GetDlgItem(hDialog,IDC_BUTTONLINE),(iLandscapeMode>=LandscapeMode::Static)); + EnableWindow(GetDlgItem(hDialog,IDC_BUTTONRECT),(iLandscapeMode>=LandscapeMode::Static)); + EnableWindow(GetDlgItem(hDialog,IDC_BUTTONFILL),(iLandscapeMode>=LandscapeMode::Exact)); + EnableWindow(GetDlgItem(hDialog,IDC_BUTTONPICKER),(iLandscapeMode>=LandscapeMode::Static)); + EnableWindow(GetDlgItem(hDialog,IDC_COMBOFGMATERIAL),(iLandscapeMode>=LandscapeMode::Static)); + EnableWindow(GetDlgItem(hDialog,IDC_COMBOFGTEXTURE),(iLandscapeMode>=LandscapeMode::Static) && !SEqual(Material,C4TLS_MatSky)); + EnableWindow(GetDlgItem(hDialog,IDC_COMBOBGMATERIAL), (iLandscapeMode >= LandscapeMode::Static) && !SEqual(Material, C4TLS_MatSky)); + EnableWindow(GetDlgItem(hDialog, IDC_COMBOBGTEXTURE), (iLandscapeMode >= LandscapeMode::Static) && !SEqual(Material, C4TLS_MatSky) && !SEqual(BackMaterial, C4TLS_MatSky)); + EnableWindow(GetDlgItem(hDialog,IDC_STATICMATERIAL),(iLandscapeMode>=LandscapeMode::Static)); + EnableWindow(GetDlgItem(hDialog,IDC_STATICTEXTURE),(iLandscapeMode>=LandscapeMode::Static) && !SEqual(Material,C4TLS_MatSky)); + EnableWindow(GetDlgItem(hDialog,IDC_STATICFOREGROUND), (iLandscapeMode >= LandscapeMode::Static)); + EnableWindow(GetDlgItem(hDialog,IDC_STATICBACKGROUND), (iLandscapeMode >= LandscapeMode::Static)); + EnableWindow(GetDlgItem(hDialog,IDC_SLIDERGRADE),(iLandscapeMode>=LandscapeMode::Static)); + EnableWindow(GetDlgItem(hDialog,IDC_PREVIEW),(iLandscapeMode>=LandscapeMode::Static)); NeedPreviewUpdate(); } diff --git a/src/editor/C4EditCursor.cpp b/src/editor/C4EditCursor.cpp index 70258594e..77dbcd9c9 100644 --- a/src/editor/C4EditCursor.cpp +++ b/src/editor/C4EditCursor.cpp @@ -702,7 +702,7 @@ void C4EditCursor::ApplyToolBrush() if (!EditingOK()) return; C4ToolsDlg *pTools=&Console.ToolsDlg; // execute/send control - EMControl(CID_EMDrawTool, new C4ControlEMDrawTool(EMDT_Brush, ::Landscape.Mode, X,Y,0,0, pTools->Grade, pTools->Material, pTools->Texture, pTools->BackMaterial, pTools->BackTexture)); + EMControl(CID_EMDrawTool, new C4ControlEMDrawTool(EMDT_Brush, ::Landscape.GetMode(), X,Y,0,0, pTools->Grade, pTools->Material, pTools->Texture, pTools->BackMaterial, pTools->BackTexture)); } void C4EditCursor::ApplyToolLine() @@ -710,7 +710,7 @@ void C4EditCursor::ApplyToolLine() if (!EditingOK()) return; C4ToolsDlg *pTools=&Console.ToolsDlg; // execute/send control - EMControl(CID_EMDrawTool, new C4ControlEMDrawTool(EMDT_Line, ::Landscape.Mode, X,Y,X2,Y2, pTools->Grade, pTools->Material,pTools->Texture, pTools->BackMaterial, pTools->BackTexture)); + EMControl(CID_EMDrawTool, new C4ControlEMDrawTool(EMDT_Line, ::Landscape.GetMode(), X,Y,X2,Y2, pTools->Grade, pTools->Material,pTools->Texture, pTools->BackMaterial, pTools->BackTexture)); } void C4EditCursor::ApplyToolRect() @@ -718,7 +718,7 @@ void C4EditCursor::ApplyToolRect() if (!EditingOK()) return; C4ToolsDlg *pTools=&Console.ToolsDlg; // execute/send control - EMControl(CID_EMDrawTool, new C4ControlEMDrawTool(EMDT_Rect, ::Landscape.Mode, X,Y,X2,Y2, pTools->Grade, pTools->Material, pTools->Texture, pTools->BackMaterial, pTools->BackTexture)); + EMControl(CID_EMDrawTool, new C4ControlEMDrawTool(EMDT_Rect, ::Landscape.GetMode(), X,Y,X2,Y2, pTools->Grade, pTools->Material, pTools->Texture, pTools->BackMaterial, pTools->BackTexture)); } void C4EditCursor::ApplyToolFill() @@ -726,7 +726,7 @@ void C4EditCursor::ApplyToolFill() if (!EditingOK()) return; C4ToolsDlg *pTools=&Console.ToolsDlg; // execute/send control - EMControl(CID_EMDrawTool, new C4ControlEMDrawTool(EMDT_Fill, ::Landscape.Mode, X,Y,0,Y2, pTools->Grade, pTools->Material, NULL, NULL, NULL)); + EMControl(CID_EMDrawTool, new C4ControlEMDrawTool(EMDT_Fill, ::Landscape.GetMode(), X,Y,0,Y2, pTools->Grade, pTools->Material, NULL, NULL, NULL)); } void C4EditCursor::AppendMenuItem(int num, const StdStrBuf & label) @@ -756,9 +756,9 @@ bool C4EditCursor::DoContextMenu(DWORD dwKeyState) #ifdef USE_WIN32_WINDOWS POINT point; GetCursorPos(&point); HMENU hContext = GetSubMenu(hMenu,0); - SetMenuItemEnable( hContext, IDM_VIEWPORT_DELETE, fObjectSelected && Console.Editing); - SetMenuItemEnable( hContext, IDM_VIEWPORT_DUPLICATE, fObjectSelected && Console.Editing); - SetMenuItemEnable( hContext, IDM_VIEWPORT_CONTENTS, fObjectSelected && Selection.GetObject()->Contents.ObjectCount() && Console.Editing); + SetMenuItemEnable(hContext, IDM_VIEWPORT_DELETE, fObjectSelected && Console.Editing); + SetMenuItemEnable(hContext, IDM_VIEWPORT_DUPLICATE, fObjectSelected && Console.Editing); + SetMenuItemEnable(hContext, IDM_VIEWPORT_CONTENTS, fObjectSelected && Selection.GetObject()->Contents.ObjectCount() && Console.Editing); SetMenuItemText(hContext,IDM_VIEWPORT_DELETE,LoadResStr("IDS_MNU_DELETE")); SetMenuItemText(hContext,IDM_VIEWPORT_DUPLICATE,LoadResStr("IDS_MNU_DUPLICATE")); SetMenuItemText(hContext,IDM_VIEWPORT_CONTENTS,LoadResStr("IDS_MNU_CONTENTS")); @@ -946,13 +946,13 @@ void C4EditCursor::ApplyToolPicker() { int32_t iMaterial; BYTE byIndex; - switch (::Landscape.Mode) + switch (::Landscape.GetMode()) { - case C4LSC_Static: + case LandscapeMode::Static: { bool material_set = false; - int32_t x = X/::Landscape.MapZoom; - int32_t y = Y/::Landscape.MapZoom; + int32_t x = X/::Landscape.GetMapZoom(); + int32_t y = Y/::Landscape.GetMapZoom(); // Material-texture from map if ((byIndex = ::Landscape.GetMapIndex(x, y))) { @@ -989,7 +989,7 @@ void C4EditCursor::ApplyToolPicker() if (!material_set) Console.ToolsDlg.SelectMaterial(C4TLS_MatSky); break; } - case C4LSC_Exact: + case LandscapeMode::Exact: // Material only from landscape if (MatValid(iMaterial=GBackMat(X,Y))) { diff --git a/src/editor/C4EditorWindowController.mm b/src/editor/C4EditorWindowController.mm index d555265ca..360a6789d 100644 --- a/src/editor/C4EditorWindowController.mm +++ b/src/editor/C4EditorWindowController.mm @@ -160,7 +160,7 @@ int indexFromSender(id sender) - (IBAction) selectLandscapeMode:(id)sender { // add one since 0 is "undefined" - Console.ToolsDlg.SetLandscapeMode([sender selectedSegment]+1, NO); + Console.ToolsDlg.SetLandscapeMode((LandscapeMode)([sender selectedSegment]+1), NO); } - (IBAction) setGrade:(id)sender diff --git a/src/editor/C4ToolsDlg.cpp b/src/editor/C4ToolsDlg.cpp index c2273ef47..abb63d70b 100644 --- a/src/editor/C4ToolsDlg.cpp +++ b/src/editor/C4ToolsDlg.cpp @@ -61,7 +61,7 @@ void C4ToolsDlg::SetMaterial(const char *szMaterial) SCopy(szMaterial,Material,C4M_MaxName); AssertValidTexture(); EnableControls(); - if (::Landscape.Mode==C4LSC_Static) UpdateTextures(); + if (::Landscape.GetMode() == LandscapeMode::Static) UpdateTextures(); NeedPreviewUpdate(); if (ModeBack && SEqual(szMaterial, C4TLS_MatSky)) SelectBackMaterial(C4TLS_MatSky); @@ -109,7 +109,7 @@ void C4ToolsDlg::SetBackMaterial(const char *szMaterial) SCopy(szMaterial,BackMaterial,C4M_MaxName); AssertValidBackTexture(); EnableControls(); - if (::Landscape.Mode==C4LSC_Static) UpdateTextures(); + if (::Landscape.GetMode() == LandscapeMode::Static) UpdateTextures(); } void C4ToolsDlg::SetBackTexture(const char *szTexture) @@ -177,30 +177,30 @@ bool C4ToolsDlg::ChangeGrade(int32_t iChange) return true; } -bool C4ToolsDlg::SetLandscapeMode(int32_t iMode, bool fThroughControl) +bool C4ToolsDlg::SetLandscapeMode(LandscapeMode mode, bool fThroughControl) { - int32_t iLastMode=::Landscape.Mode; + auto last_mode = ::Landscape.GetMode(); // Exact to static: confirm data loss warning - if (iLastMode==C4LSC_Exact) - if (iMode==C4LSC_Static) + if (last_mode == LandscapeMode::Exact) + if (mode == LandscapeMode::Static) if (!fThroughControl) - if (!Console.Message(LoadResStr("IDS_CNS_EXACTTOSTATIC"),true)) + if (!Console.Message(LoadResStr("IDS_CNS_EXACTTOSTATIC"), true)) return false; // send as control if (!fThroughControl) { - ::Control.DoInput(CID_EMDrawTool, new C4ControlEMDrawTool(EMDT_SetMode, iMode), CDT_Decide); + ::Control.DoInput(CID_EMDrawTool, new C4ControlEMDrawTool(EMDT_SetMode, mode), CDT_Decide); return true; } // Set landscape mode - ::Landscape.SetMode(iMode); + ::Landscape.SetMode(mode); // Exact to static: redraw landscape from map - if (iLastMode==C4LSC_Exact) - if (iMode==C4LSC_Static) + if (last_mode == LandscapeMode::Exact) + if (mode == LandscapeMode::Static) ::Landscape.MapToLandscape(); // Assert valid tool - if (iMode!=C4LSC_Exact) - if (SelectedTool==C4TLS_Fill) + if (mode != LandscapeMode::Exact) + if (SelectedTool == C4TLS_Fill) SetTool(C4TLS_Brush, false); // Update controls UpdateLandscapeModeCtrls(); @@ -213,7 +213,7 @@ bool C4ToolsDlg::SetLandscapeMode(int32_t iMode, bool fThroughControl) void C4ToolsDlg::AssertValidTexture() { // Static map mode only - if (::Landscape.Mode!=C4LSC_Static) return; + if (::Landscape.GetMode() != LandscapeMode::Static) return; // Ignore if sky if (SEqual(Material,C4TLS_MatSky)) return; // Current material-texture valid @@ -231,7 +231,7 @@ void C4ToolsDlg::AssertValidTexture() void C4ToolsDlg::AssertValidBackTexture() { // Static map mode only - if (::Landscape.Mode!=C4LSC_Static) return; + if (::Landscape.GetMode() != LandscapeMode::Static) return; // Ignore if not enabled if (!ModeBack) return; // Ignore if sky diff --git a/src/editor/C4ToolsDlg.h b/src/editor/C4ToolsDlg.h index 1c00ce68f..c5da73a2d 100644 --- a/src/editor/C4ToolsDlg.h +++ b/src/editor/C4ToolsDlg.h @@ -25,6 +25,7 @@ #endif #include "C4Constants.h" +#include "landscape/C4Landscape.h" const int32_t C4TLS_Brush = 0, @@ -40,6 +41,7 @@ const int32_t #define C4TLS_MatSky "Sky" +enum class LandscapeMode; class C4ToolsDlg { friend class C4ConsoleGUI; @@ -70,7 +72,7 @@ public: bool SetGrade(int32_t iGrade); bool SetTool(int32_t iTool, bool fTemp); bool ToggleTool() { return !!SetTool((Tool+1)%4, false); } - bool SetLandscapeMode(int32_t iMode, bool fThroughControl=false); + bool SetLandscapeMode(LandscapeMode iMode, bool fThroughControl=false); bool SetIFT(bool fIFT); bool ToggleIFT() { return !!SetIFT(!ModeIFT); } bool SelectTexture(const char *szTexture); diff --git a/src/editor/C4ViewportWindow.cpp b/src/editor/C4ViewportWindow.cpp index 0e8c9f8fc..7c42abb92 100644 --- a/src/editor/C4ViewportWindow.cpp +++ b/src/editor/C4ViewportWindow.cpp @@ -83,14 +83,14 @@ bool C4Viewport::ScrollBarsByViewPosition() // Vertical scroll.fMask=SIF_ALL; scroll.nMin=0; - scroll.nMax = GBackHgt * Zoom; + scroll.nMax = ::Landscape.GetHeight() * Zoom; scroll.nPage=ViewHgt; scroll.nPos=int(GetViewY() * Zoom); SetScrollInfo(pWindow->hWindow,SB_VERT,&scroll,true); // Horizontal scroll.fMask=SIF_ALL; scroll.nMin=0; - scroll.nMax=GBackWdt * Zoom; + scroll.nMax=::Landscape.GetWidth() * Zoom; scroll.nPage=ViewWdt; scroll.nPos = int(GetViewX() * Zoom); SetScrollInfo(pWindow->hWindow,SB_HORZ,&scroll,true); @@ -129,7 +129,7 @@ bool C4Viewport::ScrollBarsByViewPosition() gtk_adjustment_configure(adjustment, GetViewX(), // value 0, // lower - GBackWdt, // upper + ::Landscape.GetWidth(), // upper ViewportScrollSpeed, // step_increment allocation.width / Zoom, // page_increment allocation.width / Zoom // page_size @@ -139,7 +139,7 @@ bool C4Viewport::ScrollBarsByViewPosition() gtk_adjustment_configure(adjustment, GetViewY(), // value 0, // lower - GBackHgt, // upper + ::Landscape.GetHeight(), // upper ViewportScrollSpeed, // step_increment allocation.height / Zoom, // page_increment allocation.height / Zoom // page_size diff --git a/src/game/C4Game.cpp b/src/game/C4Game.cpp index 54874bbd1..d9f5c062e 100644 --- a/src/game/C4Game.cpp +++ b/src/game/C4Game.cpp @@ -65,6 +65,7 @@ #include #include #include +#include "landscape/C4Sky.h" #include #include #include @@ -913,7 +914,7 @@ void C4Game::ClearPointers(C4Object * pObj) TransferZones.ClearPointers(pObj); if (pGlobalEffects) pGlobalEffects->ClearPointers(pObj); - if (::Landscape.pFoW) ::Landscape.pFoW->Remove(pObj); + ::Landscape.ClearPointers(pObj); } bool C4Game::TogglePause() @@ -1680,7 +1681,7 @@ void C4Game::CompileFunc(StdCompiler *pComp, CompileSettings comp, C4ValueNumber { pComp->Value(mkNamingAdapt(Weather, "Weather")); pComp->Value(mkNamingAdapt(Landscape, "Landscape")); - pComp->Value(mkNamingAdapt(Landscape.Sky, "Sky")); + pComp->Value(mkNamingAdapt(Landscape.GetSky(), "Sky")); // save custom GUIs only if a real savegame and not for editor-scenario-saves or section changes if (!comp.fScenarioSection) @@ -2011,7 +2012,7 @@ bool C4Game::QuickSave(const char *strFilename, const char *strTitle, bool fForc bool LandscapeFree(int32_t x, int32_t y) { - if (!Inside(x,0,GBackWdt-1) || !Inside(y,0,GBackHgt-1)) return false; + if (!Inside(x,0,::Landscape.GetWidth()-1) || !Inside(y,0,::Landscape.GetHeight()-1)) return false; return !DensitySolid(GBackDensity(x,y)); } @@ -2243,7 +2244,7 @@ bool C4Game::InitGame(C4Group &hGroup, bool fLoadSection, bool fLoadSky, C4Value if (fLoadSection && fLandscapeLoaded) { PXS.Clear(); MassMover.Clear(); } SetInitProgress(89); // Init main object list - Objects.Init(Landscape.Width, Landscape.Height); + Objects.Init(Landscape.GetWidth(), Landscape.GetHeight()); // Pathfinder if (!fLoadSection) PathFinder.Init( &LandscapeFree, &TransferZones ); @@ -2618,7 +2619,7 @@ bool C4Game::PlaceInEarth(C4ID id) int32_t cnt,tx,ty; for (cnt=0; cnt<35; cnt++) // cheap trys { - tx=Random(GBackWdt); ty=Random(GBackHgt); + tx=Random(::Landscape.GetWidth()); ty=Random(::Landscape.GetHeight()); if (GBackMat(tx,ty)==MEarth) if (CreateObject(id,NULL,NO_OWNER,tx,ty,Random(360))) return true; @@ -2687,7 +2688,7 @@ C4Object* C4Game::PlaceVegetation(C4PropList * PropList, int32_t iX, int32_t iY, // Above tunnel while ((iTy>0) && Landscape.GetBackPix(iTx,iTy) == 0) iTy--; // Above semi solid - if (!AboveSemiSolid(iTx,iTy) || !Inside(iTy,50,GBackHgt-50)) + if (!AboveSemiSolid(iTx,iTy) || !Inside(iTy,50,::Landscape.GetHeight()-50)) continue; // Still inside bounds? if (!PlaceVegetation_IsPosInBounds(iTx, iTy, iX, iY, iWdt, iHgt, shape_proplist)) continue; @@ -2756,7 +2757,7 @@ C4Object* C4Game::PlaceVegetation(C4PropList * PropList, int32_t iX, int32_t iY, // Random hit within target area if (!PlaceVegetation_GetRandomPoint(iX, iY, iWdt, iHgt, shape_proplist, out_pos_proplist, &iTx, &iTy)) break; // Above semi solid - if (!AboveSemiSolid(iTx,iTy) || !Inside(iTy,50,GBackHgt-50)) + if (!AboveSemiSolid(iTx,iTy) || !Inside(iTy,50,::Landscape.GetHeight()-50)) continue; // Free above if (GBackSemiSolid(iTx,iTy-pDef->Shape.Hgt) || GBackSemiSolid(iTx,iTy-pDef->Shape.Hgt/2)) @@ -2793,12 +2794,12 @@ C4Object* C4Game::PlaceAnimal(C4PropList* PropList) { // Running free case C4D_Place_Surface: - iX=Random(GBackWdt); iY=Random(GBackHgt); + iX=Random(::Landscape.GetWidth()); iY=Random(::Landscape.GetHeight()); if (!FindSolidGround(iX,iY,pDef->Shape.Wdt)) return NULL; break; // In liquid case C4D_Place_Liquid: - iX=Random(GBackWdt); iY=Random(GBackHgt); + iX=Random(::Landscape.GetWidth()); iY=Random(::Landscape.GetHeight()); if (!FindSurfaceLiquid(iX,iY,pDef->Shape.Wdt,pDef->Shape.Hgt)) if (!FindLiquid(iX,iY,pDef->Shape.Wdt,pDef->Shape.Hgt)) return NULL; @@ -2806,8 +2807,8 @@ C4Object* C4Game::PlaceAnimal(C4PropList* PropList) break; // Floating in air case C4D_Place_Air: - iX=Random(GBackWdt); - for (iY=0; (iY0) for (cnt=0; cnt #include #include +#include "landscape/C4Landscape.h" +#include "landscape/C4Sky.h" // undocumented! static bool FnIncinerateLandscape(C4PropList * _this, long iX, long iY, long caused_by_plr) @@ -53,12 +55,12 @@ static bool FnIncinerateLandscape(C4PropList * _this, long iX, long iY, long cau static void FnSetGravity(C4PropList * _this, long iGravity) { - ::Landscape.Gravity = C4REAL100(Clamp(iGravity,-1000,1000)); + ::Landscape.SetGravity(C4REAL100(Clamp(iGravity,-1000,1000))); } static long FnGetGravity(C4PropList * _this) { - return fixtoi(::Landscape.Gravity * 100); + return fixtoi(::Landscape.GetGravity() * 100); } static C4String *FnGetPlayerName(C4PropList * _this, long iPlayer) @@ -364,9 +366,9 @@ static long FnGetMaterialCount(C4PropList * _this, long iMaterial, bool fReal) { if (!MatValid(iMaterial)) return -1; if (fReal || !::MaterialMap.Map[iMaterial].MinHeightCount) - return ::Landscape.MatCount[iMaterial]; + return ::Landscape.GetMatCount(iMaterial); else - return ::Landscape.EffectiveMatCount[iMaterial]; + return ::Landscape.GetEffectiveMatCount(iMaterial); } static long FnGetMaterial(C4PropList * _this, long x, long y) @@ -386,7 +388,7 @@ static C4String *FnGetTexture(C4PropList * _this, long x, long y) if (Object(_this)) { x+=Object(_this)->GetX(); y+=Object(_this)->GetY(); } // Get texture - int32_t iTex = PixCol2Tex(GBackPix(x, y)); + int32_t iTex = PixCol2Tex(::Landscape.GetPix(x, y)); if (!iTex) return NULL; // Get material-texture mapping const C4TexMapEntry *pTex = ::TextureMap.GetEntry(iTex); @@ -1211,15 +1213,15 @@ static long FnGetTemperature(C4PropList * _this) static void FnSetAmbientBrightness(C4PropList * _this, long iBrightness) { - if (::Landscape.pFoW) - ::Landscape.pFoW->Ambient.SetBrightness(iBrightness / 100.); + if (::Landscape.HasFoW()) + ::Landscape.GetFoW()->Ambient.SetBrightness(iBrightness / 100.); } static long FnGetAmbientBrightness(C4PropList * _this) { - if (!::Landscape.pFoW) + if (!::Landscape.HasFoW()) return 100; - return static_cast(::Landscape.pFoW->Ambient.GetBrightness() * 100. + 0.5); + return static_cast(::Landscape.GetFoW()->Ambient.GetBrightness() * 100. + 0.5); } static void FnSetSeason(C4PropList * _this, long iSeason) @@ -1244,12 +1246,12 @@ static long FnGetClimate(C4PropList * _this) static long FnLandscapeWidth(C4PropList * _this) { - return GBackWdt; + return ::Landscape.GetWidth(); } static long FnLandscapeHeight(C4PropList * _this) { - return GBackHgt; + return ::Landscape.GetHeight(); } static void FnShakeFree(C4PropList * _this, long x, long y, long rad) @@ -1663,7 +1665,7 @@ static C4String *FnMaterialName(C4PropList * _this, long iMat) static bool FnSetSkyAdjust(C4PropList * _this, long dwAdjust, long dwBackClr) { // set adjust - ::Landscape.Sky.SetModulation(dwAdjust, dwBackClr); + ::Landscape.GetSky().SetModulation(dwAdjust, dwBackClr); // success return true; } @@ -1679,7 +1681,7 @@ static bool FnSetMatAdjust(C4PropList * _this, long dwAdjust) static long FnGetSkyAdjust(C4PropList * _this, bool fBackColor) { // get adjust - return ::Landscape.Sky.GetModulation(!!fBackColor); + return ::Landscape.GetSky().GetModulation(!!fBackColor); } static long FnGetMatAdjust(C4PropList * _this) @@ -1936,13 +1938,13 @@ static bool FnSetSkyParallax(C4PropList * _this, Nillable iMode, Nillable< { // set all parameters that aren't nil if (!iMode.IsNil()) - if (Inside(iMode, 0, 1)) ::Landscape.Sky.ParallaxMode = iMode; - if (!iParX.IsNil() && iParX) ::Landscape.Sky.ParX = iParX; - if (!iParY.IsNil() && iParY) ::Landscape.Sky.ParY = iParY; - if (!iXDir.IsNil()) ::Landscape.Sky.xdir = itofix(iXDir); - if (!iYDir.IsNil()) ::Landscape.Sky.ydir = itofix(iYDir); - if (!iX.IsNil()) ::Landscape.Sky.x = itofix(iX); - if (!iY.IsNil()) ::Landscape.Sky.y = itofix(iY); + if (Inside(iMode, 0, 1)) ::Landscape.GetSky().ParallaxMode = iMode; + if (!iParX.IsNil() && iParX) ::Landscape.GetSky().ParX = iParX; + if (!iParY.IsNil() && iParY) ::Landscape.GetSky().ParY = iParY; + if (!iXDir.IsNil()) ::Landscape.GetSky().xdir = itofix(iXDir); + if (!iYDir.IsNil()) ::Landscape.GetSky().ydir = itofix(iYDir); + if (!iX.IsNil()) ::Landscape.GetSky().x = itofix(iX); + if (!iY.IsNil()) ::Landscape.GetSky().y = itofix(iY); // success return true; } diff --git a/src/game/C4GraphicsSystem.cpp b/src/game/C4GraphicsSystem.cpp index 8b13d6271..4b19ee6ae 100644 --- a/src/game/C4GraphicsSystem.cpp +++ b/src/game/C4GraphicsSystem.cpp @@ -28,6 +28,7 @@ #include #include #include +#include "landscape/C4Sky.h" #include #include #include @@ -229,7 +230,7 @@ bool C4GraphicsSystem::DoSaveScreenshot(bool fSaveAll, const char *szFilename, f C4Viewport *pVP=::Viewports.GetFirstViewport(); if (!pVP) return false; // create image large enough to hold the landscape std::unique_ptr png(new CPNGFile()); - int32_t lWdt = GBackWdt * zoom, lHgt = GBackHgt * zoom; + int32_t lWdt = ::Landscape.GetWidth() * zoom, lHgt = ::Landscape.GetHeight() * zoom; if (!png->Create(lWdt, lHgt, false)) return false; // get backbuffer size int32_t bkWdt=C4GUI::GetScreenWdt(), bkHgt=C4GUI::GetScreenHgt(); @@ -241,8 +242,8 @@ bool C4GraphicsSystem::DoSaveScreenshot(bool fSaveAll, const char *szFilename, f // draw on one big viewport pVP->SetOutputSize(0,0,0,0, bkWdt, bkHgt); // backup and clear sky parallaxity - int32_t iParX=::Landscape.Sky.ParX; ::Landscape.Sky.ParX=10; - int32_t iParY=::Landscape.Sky.ParY; ::Landscape.Sky.ParY=10; + int32_t iParX=::Landscape.GetSky().ParX; ::Landscape.GetSky().ParX=10; + int32_t iParY=::Landscape.GetSky().ParY; ::Landscape.GetSky().ParY=10; // backup and clear viewport borders FLOAT_RECT vp_borders = { pVP->BorderLeft, pVP->BorderRight, pVP->BorderTop, pVP->BorderBottom }; pVP->BorderLeft = pVP->BorderRight = pVP->BorderTop = pVP->BorderBottom = 0.0f; @@ -288,8 +289,8 @@ bool C4GraphicsSystem::DoSaveScreenshot(bool fSaveAll, const char *szFilename, f pVP->BorderRight = vp_borders.right; pVP->BorderBottom = vp_borders.bottom; // restore parallaxity - ::Landscape.Sky.ParX=iParX; - ::Landscape.Sky.ParY=iParY; + ::Landscape.GetSky().ParX=iParX; + ::Landscape.GetSky().ParY=iParY; // restore viewport size ::Viewports.RecalculateViewports(); // save! diff --git a/src/game/C4Physics.h b/src/game/C4Physics.h index eabc48594..b527141da 100644 --- a/src/game/C4Physics.h +++ b/src/game/C4Physics.h @@ -26,7 +26,7 @@ const int StableRange=10; const int AttachRange=5; const int CornerRange=AttachRange+2; -#define GravAccel (::Landscape.Gravity) +#define GravAccel ::Landscape.GetGravity() extern const C4Real HitSpeed1,HitSpeed2,HitSpeed3,HitSpeed4; extern const C4Real FloatFriction; diff --git a/src/game/C4Viewport.cpp b/src/game/C4Viewport.cpp index 2f0458fb1..310e925bf 100644 --- a/src/game/C4Viewport.cpp +++ b/src/game/C4Viewport.cpp @@ -34,6 +34,7 @@ #include #include #include +#include "landscape/C4Sky.h" #include #include #include @@ -260,7 +261,7 @@ void C4Viewport::Draw(C4TargetFacet &cgo0, bool fDrawGame, bool fDrawOverlay) pDraw->SetFoW(pFoW); C4ST_STARTNEW(SkyStat, "C4Viewport::Draw: Sky") - ::Landscape.Sky.Draw(cgo); + ::Landscape.GetSky().Draw(cgo); C4ST_STOP(SkyStat) ::Objects.Draw(cgo, Player, -2147483647 - 1 /* INT32_MIN */, 0); @@ -411,7 +412,7 @@ void C4Viewport::CalculateZoom() if (plr) plr->ZoomLimitsToViewport(this); else - SetZoomLimits(0.8*std::min(float(ViewWdt)/GBackWdt,float(ViewHgt)/GBackHgt), 8); + SetZoomLimits(0.8*std::min(float(ViewWdt)/::Landscape.GetWidth(),float(ViewHgt)/::Landscape.GetHeight()), 8); } @@ -424,7 +425,7 @@ void C4Viewport::InitZoom() } else { - ZoomTarget = std::max(float(ViewWdt)/GBackWdt, 1.0f); + ZoomTarget = std::max(float(ViewWdt)/::Landscape.GetWidth(), 1.0f); Zoom = ZoomTarget; } } @@ -556,13 +557,13 @@ void C4Viewport::AdjustPosition(bool immediate) // if view is close to border, allow scrolling if (targetCenterViewX < ViewportScrollBorder) extraBoundsX = std::min(ViewportScrollBorder - targetCenterViewX, ViewportScrollBorder); - else if (targetCenterViewX >= GBackWdt - ViewportScrollBorder) extraBoundsX = std::min(targetCenterViewX - GBackWdt, 0) + ViewportScrollBorder; + else if (targetCenterViewX >= ::Landscape.GetWidth() - ViewportScrollBorder) extraBoundsX = std::min(targetCenterViewX - ::Landscape.GetWidth(), 0) + ViewportScrollBorder; if (targetCenterViewY < ViewportScrollBorder) extraBoundsY = std::min(ViewportScrollBorder - targetCenterViewY, ViewportScrollBorder); - else if (targetCenterViewY >= GBackHgt - ViewportScrollBorder) extraBoundsY = std::min(targetCenterViewY - GBackHgt, 0) + ViewportScrollBorder; + else if (targetCenterViewY >= ::Landscape.GetHeight() - ViewportScrollBorder) extraBoundsY = std::min(targetCenterViewY - ::Landscape.GetHeight(), 0) + ViewportScrollBorder; } - extraBoundsX = std::max(extraBoundsX, (ViewWdt/Zoom - GBackWdt)/2 + 1); - extraBoundsY = std::max(extraBoundsY, (ViewHgt/Zoom - GBackHgt)/2 + 1); + extraBoundsX = std::max(extraBoundsX, (ViewWdt/Zoom - ::Landscape.GetWidth())/2 + 1); + extraBoundsY = std::max(extraBoundsY, (ViewHgt/Zoom - ::Landscape.GetHeight())/2 + 1); // add mouse auto scroll if (pPlr->MouseControl && ::MouseControl.InitCentered && Config.Controls.MouseAutoScroll) @@ -579,8 +580,8 @@ void C4Viewport::AdjustPosition(bool immediate) targetCenterViewY = Clamp(targetCenterViewY, targetCenterViewY - scrollRange, targetCenterViewY + scrollRange); } // bounds - targetCenterViewX = Clamp(targetCenterViewX, ViewWdt/Zoom/2 - extraBoundsX, GBackWdt - ViewWdt/Zoom/2 + extraBoundsX); - targetCenterViewY = Clamp(targetCenterViewY, ViewHgt/Zoom/2 - extraBoundsY, GBackHgt - ViewHgt/Zoom/2 + extraBoundsY); + targetCenterViewX = Clamp(targetCenterViewX, ViewWdt/Zoom/2 - extraBoundsX, ::Landscape.GetWidth() - ViewWdt/Zoom/2 + extraBoundsX); + targetCenterViewY = Clamp(targetCenterViewY, ViewHgt/Zoom/2 - extraBoundsY, ::Landscape.GetHeight() - ViewHgt/Zoom/2 + extraBoundsY); targetViewX = targetCenterViewX - ViewWdt/Zoom/2 + viewOffsX; targetViewY = targetCenterViewY - ViewHgt/Zoom/2 + viewOffsY; @@ -610,20 +611,20 @@ void C4Viewport::CenterPosition() { // center viewport position on map // set center position - SetViewX(GBackWdt/2 + ViewWdt/Zoom/2); - SetViewY(GBackHgt/2 + ViewHgt/Zoom/2); + SetViewX(::Landscape.GetWidth()/2 + ViewWdt/Zoom/2); + SetViewY(::Landscape.GetHeight()/2 + ViewHgt/Zoom/2); } void C4Viewport::UpdateBordersX() { BorderLeft = std::max(-GetViewX() * Zoom, 0.0f); - BorderRight = std::max(ViewWdt - GBackWdt * Zoom + GetViewX() * Zoom, 0.0f); + BorderRight = std::max(ViewWdt - ::Landscape.GetWidth() * Zoom + GetViewX() * Zoom, 0.0f); } void C4Viewport::UpdateBordersY() { BorderTop = std::max(-GetViewY() * Zoom, 0.0f); - BorderBottom = std::max(ViewHgt - GBackHgt * Zoom + GetViewY() * Zoom, 0.0f); + BorderBottom = std::max(ViewHgt - ::Landscape.GetHeight() * Zoom + GetViewY() * Zoom, 0.0f); } void C4Viewport::DrawPlayerInfo(C4TargetFacet &cgo) @@ -673,9 +674,9 @@ void C4Viewport::DisableFoW() void C4Viewport::EnableFoW() { - if (::Landscape.pFoW && Player != NO_OWNER) + if (::Landscape.HasFoW() && Player != NO_OWNER) { - pFoW.reset(new C4FoWRegion(::Landscape.pFoW, ::Players.Get(Player))); + pFoW.reset(new C4FoWRegion(::Landscape.GetFoW(), ::Players.Get(Player))); } else { @@ -722,13 +723,13 @@ void C4Viewport::SetViewX(float x) if (fIsNoOwnerViewport) { - if(GBackWdt < ViewWdt / Zoom) + if(::Landscape.GetWidth() < ViewWdt / Zoom) { - viewX = GBackWdt/2 - ViewWdt / Zoom / 2; + viewX = ::Landscape.GetWidth()/2 - ViewWdt / Zoom / 2; } else { - viewX = Clamp(x, 0.0f, GBackWdt - ViewWdt / Zoom); + viewX = Clamp(x, 0.0f, ::Landscape.GetWidth() - ViewWdt / Zoom); } } @@ -741,13 +742,13 @@ void C4Viewport::SetViewY(float y) if (fIsNoOwnerViewport) { - if(GBackHgt < ViewHgt / Zoom) + if(::Landscape.GetHeight() < ViewHgt / Zoom) { - viewY = GBackHgt/2 - ViewHgt / Zoom / 2; + viewY = ::Landscape.GetHeight()/2 - ViewHgt / Zoom / 2; } else { - viewY = Clamp(y, 0.0f, GBackHgt - ViewHgt / Zoom); + viewY = Clamp(y, 0.0f, ::Landscape.GetHeight() - ViewHgt / Zoom); } } diff --git a/src/graphics/C4DrawGLMac.mm b/src/graphics/C4DrawGLMac.mm index 0164c123c..edc3ceac8 100644 --- a/src/graphics/C4DrawGLMac.mm +++ b/src/graphics/C4DrawGLMac.mm @@ -397,7 +397,7 @@ int32_t mouseButtonFromEvent(NSEvent* event, DWORD* modifierFlags) if (Application.isEditor && viewport && !viewport->GetPlayerLock()) { NSScrollView* scrollView = self.controller.scrollView; - NSPoint p = NSMakePoint(2*-[event deltaX]/abs(GBackWdt-viewport->ViewWdt), 2*-[event deltaY]/abs(GBackHgt-viewport->ViewHgt)); + NSPoint p = NSMakePoint(2*-[event deltaX]/abs(::Landscape.GetWidth()-viewport->ViewWdt), 2*-[event deltaY]/abs(::Landscape.GetHeight()-viewport->ViewHgt)); [scrollView.horizontalScroller setDoubleValue:scrollView.horizontalScroller.doubleValue+p.x]; [scrollView.verticalScroller setDoubleValue:scrollView.verticalScroller.doubleValue+p.y]; viewport->ViewPositionByScrollBars(); diff --git a/src/graphics/CSurface8.cpp b/src/graphics/CSurface8.cpp index 18cde1e44..98ec9ac22 100644 --- a/src/graphics/CSurface8.cpp +++ b/src/graphics/CSurface8.cpp @@ -192,7 +192,7 @@ void CSurface8::MapBytes(BYTE *bpMap) for (int cnt=0; cntGetFoW() might not be current at this time. - if (/*(pPlayer->fFogOfWar && !pPlayer->FoWIsVisible(int32_t(GameX),int32_t(GameY))) || */GameX<0 || GameY<0 || int32_t(GameX)>=GBackWdt || int32_t(GameY)>=GBackHgt) + if (/*(pPlayer->fFogOfWar && !pPlayer->FoWIsVisible(int32_t(GameX),int32_t(GameY))) || */GameX<0 || GameY<0 || int32_t(GameX)>=::Landscape.GetWidth() || int32_t(GameY)>=::Landscape.GetHeight()) { FogOfWar=true; // allow dragging, scrolling, region selection and manipulations of objects not affected by FoW diff --git a/src/landscape/C4Landscape.cpp b/src/landscape/C4Landscape.cpp index 5998669f7..507f828bd 100644 --- a/src/landscape/C4Landscape.cpp +++ b/src/landscape/C4Landscape.cpp @@ -1,9 +1,9 @@ -/* +/* * OpenClonk, http://www.openclonk.org * * Copyright (c) 1998-2000, Matthes Bender * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/ - * Copyright (c) 2009-2013, The OpenClonk Team and contributors + * Copyright (c) 2009-2016, The OpenClonk Team and contributors * * Distributed under the terms of the ISC license; see accompanying file * "COPYING" for details. @@ -15,44 +15,115 @@ * for the above references. */ -/* Handles landscape and sky */ + /* Handles landscape and sky */ -#include -#include +#include "C4Include.h" +#include "landscape/C4Landscape.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include + +#include "c4group/C4Components.h" +#include "control/C4Record.h" +#include "editor/C4ToolsDlg.h" +#include "game/C4GraphicsSystem.h" +#include "game/C4Physics.h" +#include "graphics/C4GraphicsResource.h" +#include "gui/C4GameMessage.h" +#include "landscape/fow/C4FoW.h" +#include "landscape/C4LandscapeRender.h" +#include "landscape/C4Map.h" +#include "landscape/C4MapCreatorS2.h" +#include "landscape/C4MapScript.h" +#include "landscape/C4MassMover.h" +#include "landscape/C4Material.h" +#include "landscape/C4MaterialList.h" +#include "landscape/C4PXS.h" +#include "landscape/C4Sky.h" +#include "landscape/C4SolidMask.h" +#include "landscape/C4Texture.h" +#include "landscape/C4Weather.h" +#include "lib/C4Random.h" +#include "lib/StdColors.h" +#include "object/C4FindObject.h" +#include "object/C4GameObjects.h" + +struct C4Landscape::P +{ + std::unique_ptr Surface8; + std::unique_ptr Surface8Bkg; // Background material + std::unique_ptr Map; + std::unique_ptr MapBkg; + std::unique_ptr pLandscapeRender; + std::vector TopRowPix, BottomRowPix; // array size of landscape width: Filled with 0s for border pixels that are open and MCVehic for pixels that are closed + int32_t Pix2Mat[C4M_MaxTexIndex], Pix2Dens[C4M_MaxTexIndex], Pix2Place[C4M_MaxTexIndex]; + bool Pix2Light[C4M_MaxTexIndex]; + int32_t PixCntPitch = 0; + std::vector PixCnt; + std::array Relights; + mutable std::array, C4M_MaxTexIndex> BridgeMatConversion; // NoSave // + + LandscapeMode mode = LandscapeMode::Undefined; + int32_t Width = 0, Height = 0; + int32_t MapWidth = 0, MapHeight = 0, MapZoom = 0; + std::array MatCount{}; // NoSave // + std::array EffectiveMatCount{}; // NoSave // + + bool NoScan = false; // ExecuteScan() disabled + int32_t ScanX = 0, ScanSpeed = 2; // SyncClearance-NoSave // + int32_t LeftOpen = 0, RightOpen = 0, TopOpen = 0, BottomOpen = 0; + C4Real Gravity = DefaultGravAccel; + uint32_t Modulation = 0; // landscape blit modulation; 0 means normal + int32_t MapSeed = 0; // random seed for MapToLandscape + C4Sky Sky; + std::unique_ptr pMapCreator; // map creator for script-generated maps + bool fMapChanged = false; + std::unique_ptr pInitial; // Initial landscape after creation - used for diff + std::unique_ptr pInitialBkg; // Initial bkg landscape after creation - used for diff + std::unique_ptr pFoW; + + void ClearMatCount(); + + void ExecuteScan(C4Landscape *); + int32_t DoScan(C4Landscape *, int32_t x, int32_t y, int32_t mat, int32_t dir); + uint32_t ChunkyRandom(uint32_t &iOffset, uint32_t iRange) const; // return static random value, according to offset and MapSeed + void DrawChunk(C4Landscape *, int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, uint8_t mcol, uint8_t mcolBkg, C4MaterialCoreShape Shape, uint32_t cro); + void DrawSmoothOChunk(C4Landscape *, int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, uint8_t mcol, uint8_t mcolBkg, int flip, uint32_t cro); + void ChunkOZoom(C4Landscape *, const CSurface8 &sfcMap, const CSurface8 &sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, uint8_t iTexture, int32_t iOffX = 0, int32_t iOffY = 0); + bool TexOZoom(C4Landscape *, const CSurface8 &sfcMap, const CSurface8 &sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, DWORD *dwpTextureUsage, int32_t iToX = 0, int32_t iToY = 0); + bool MapToSurface(C4Landscape *, const CSurface8 &sfcMap, const CSurface8 &sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, int32_t iToX, int32_t iToY, int32_t iToWdt, int32_t iToHgt, int32_t iOffX, int32_t iOffY); + bool MapToLandscape(C4Landscape *d, const CSurface8 &sfcMap, const CSurface8 &sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, int32_t iOffsX = 0, int32_t iOffsY = 0, bool noClear = false); // zoom map segment to surface (or sector surfaces) + bool InitTopAndBottomRowPix(); // init out-of-landscape pixels for bottom side + bool GetMapColorIndex(const char *szMaterial, const char *szTexture, BYTE &rbyCol) const; + //bool SkyToLandscape(int32_t iToX, int32_t iToY, int32_t iToWdt, int32_t iToHgt, int32_t iOffX, int32_t iOffY); + bool CreateMap(CSurface8*& sfcMap, CSurface8*& sfcMapBkg); // create map by landscape attributes + bool CreateMapS2(C4Group &ScenFile, CSurface8*& sfcMap, CSurface8*& sfcMapBkg); // create map by def file + bool Mat2Pal(); // assign material colors to landscape palette + void UpdatePixCnt(const C4Landscape *, const C4Rect &Rect, bool fCheck = false); + void UpdateMatCnt(const C4Landscape *, C4Rect Rect, bool fPlus); + void PrepareChange(const C4Landscape *d, const C4Rect &BoundingBox); + void FinishChange(C4Landscape *d, C4Rect BoundingBox); + bool DrawLineLandscape(int32_t iX, int32_t iY, int32_t iGrade, uint8_t line_color, uint8_t line_color_bkg); + bool DrawLineMap(int32_t iX, int32_t iY, int32_t iRadius, uint8_t line_color, uint8_t line_color_bkg); + uint8_t *GetBridgeMatConversion(const C4Landscape *d, int32_t for_material_col) const; + bool SaveInternal(const C4Landscape *d, C4Group &hGroup) const; + bool SaveDiffInternal(const C4Landscape *d, C4Group &hGroup, bool fSyncSave) const; + + int32_t ForPolygon(C4Landscape *d, int *vtcs, int length, const std::function &callback, + C4MaterialList *mats_count = NULL, uint8_t col = 0, uint8_t colBkg = 0, uint8_t *conversion_table = NULL); + + std::unique_ptr CreateDefaultBkgSurface(CSurface8& sfcFg, bool msbAsIft) const; + void DigMaterial2Objects(int32_t tx, int32_t ty, C4MaterialList *mat_list, C4Object *pCollect = NULL); + void BlastMaterial2Objects(int32_t tx, int32_t ty, C4MaterialList *mat_list, int32_t caused_by, int32_t str, C4ValueArray *out_objects); + + bool DigFreePix(C4Landscape *d, int32_t tx, int32_t ty); + bool DigFreePixNoInstability(C4Landscape *d, int32_t tx, int32_t ty); + bool BlastFreePix(C4Landscape *d, int32_t tx, int32_t ty); + bool ShakeFreePix(C4Landscape *d, int32_t tx, int32_t ty); + + C4ValueArray *PrepareFreeShape(C4Rect &BoundingBox, C4Object *by_object); + void PostFreeShape(C4ValueArray *dig_objects, C4Object *by_object); + BYTE DefaultBkgMat(BYTE fg) const; +}; namespace { @@ -61,10 +132,10 @@ namespace int32_t *lastx = 0, int32_t *lasty = 0) { int d, dx, dy, aincr, bincr, xincr, yincr, x, y; - if (Abs(x2 - x1)y2) { std::swap(x1, x2); std::swap(y1, y2); } - xincr = (x2>x1) ? 1 : -1; + if (y1 > y2) { std::swap(x1, x2); std::swap(y1, y2); } + xincr = (x2 > x1) ? 1 : -1; dy = y2 - y1; dx = Abs(x2 - x1); d = 2 * dx - dy; aincr = 2 * (dx - dy); bincr = 2 * dx; x = x1; y = y1; if (!fnCallback(x, y)) @@ -85,8 +156,8 @@ namespace } else { - if (x1>x2) { std::swap(x1, x2); std::swap(y1, y2); } - yincr = (y2>y1) ? 1 : -1; + if (x1 > x2) { std::swap(x1, x2); std::swap(y1, y2); } + yincr = (y2 > y1) ? 1 : -1; dx = x2 - x1; dy = Abs(y2 - y1); d = 2 * dy - dx; aincr = 2 * (dy - dx); bincr = 2 * dy; x = x1; y = y1; if (!fnCallback(x, y)) @@ -110,6 +181,7 @@ namespace } C4Landscape::C4Landscape() + : p(new P) { Default(); } @@ -126,10 +198,10 @@ C4Landscape::~C4Landscape() void C4Landscape::Execute() { // Landscape scan - if (!NoScan) - ExecuteScan(); + if (!p->NoScan) + p->ExecuteScan(this); // move sky - Sky.Execute(); + p->Sky.Execute(); // Queued Relights -- note that normally we process them before drawing every frame; // this just makes sure relights don't accumulate over a long period of time if no @@ -139,11 +211,9 @@ void C4Landscape::Execute() } -void C4Landscape::ExecuteScan() +void C4Landscape::P::ExecuteScan(C4Landscape *d) { - - - int32_t cy,mat; + int32_t cy, mat; // Check: Scan needed? const int32_t iTemperature = ::Weather.GetTemperature(); @@ -151,10 +221,10 @@ void C4Landscape::ExecuteScan() if (MatCount[mat]) { if (::MaterialMap.Map[mat].BelowTempConvertTo && - iTemperature < ::MaterialMap.Map[mat].BelowTempConvert) + iTemperature < ::MaterialMap.Map[mat].BelowTempConvert) break; else if (::MaterialMap.Map[mat].AboveTempConvertTo && - iTemperature > ::MaterialMap.Map[mat].AboveTempConvert) + iTemperature > ::MaterialMap.Map[mat].AboveTempConvert) break; } if (mat >= ::MaterialMap.Num) @@ -165,31 +235,31 @@ void C4Landscape::ExecuteScan() AddDbgRec(RCT_MatScan, &ScanX, sizeof(ScanX)); #endif - for (int32_t cnt=0; cnt_GetMat(ScanX, cy); // material change? if (last_mat != mat) { // upwards if (last_mat != -1) - DoScan(ScanX, cy-1, last_mat, 1); + DoScan(d, ScanX, cy - 1, last_mat, 1); // downwards if (mat != -1) - cy += DoScan(ScanX, cy, mat, 0); + cy += DoScan(d, ScanX, cy, mat, 0); } last_mat = mat; } // Scan advance & rewind ScanX++; - if (ScanX>=Width) - ScanX=0; + if (ScanX >= Width) + ScanX = 0; } @@ -197,7 +267,7 @@ void C4Landscape::ExecuteScan() #define PRETTY_TEMP_CONV -int32_t C4Landscape::DoScan(int32_t cx, int32_t cy, int32_t mat, int32_t dir) +int32_t C4Landscape::P::DoScan(C4Landscape *d, int32_t cx, int32_t cy, int32_t mat, int32_t dir) { int32_t conv_to_tex = 0; int32_t iTemperature = ::Weather.GetTemperature(); @@ -205,19 +275,19 @@ int32_t C4Landscape::DoScan(int32_t cx, int32_t cy, int32_t mat, int32_t dir) if (::MaterialMap.Map[mat].BelowTempConvertDir == dir) if (::MaterialMap.Map[mat].BelowTempConvertTo) if (iTemperature< ::MaterialMap.Map[mat].BelowTempConvert) - conv_to_tex=::MaterialMap.Map[mat].BelowTempConvertTo; + conv_to_tex = ::MaterialMap.Map[mat].BelowTempConvertTo; // Check above conv if (::MaterialMap.Map[mat].AboveTempConvertDir == dir) if (::MaterialMap.Map[mat].AboveTempConvertTo) if (iTemperature>::MaterialMap.Map[mat].AboveTempConvert) - conv_to_tex=::MaterialMap.Map[mat].AboveTempConvertTo; + conv_to_tex = ::MaterialMap.Map[mat].AboveTempConvertTo; // nothing to do? if (!conv_to_tex) return 0; // find material int32_t conv_to = ::TextureMap.GetEntry(conv_to_tex)->GetMaterialIndex(); // find mat top int32_t mconv = ::MaterialMap.Map[mat].TempConvStrength, - mconvs = mconv; + mconvs = mconv; #ifdef DEBUGREC_MATSCAN if (Config.General.DebugRec) { @@ -228,7 +298,7 @@ int32_t C4Landscape::DoScan(int32_t cx, int32_t cy, int32_t mat, int32_t dir) int32_t ydir = (dir == 0 ? +1 : -1), cy2; #ifdef PRETTY_TEMP_CONV // get left pixel - int32_t lmat = (cx > 0 ? _GetMat(cx-1, cy) : -1); + int32_t lmat = (cx > 0 ? d->_GetMat(cx - 1, cy) : -1); // left pixel not converted? do nothing if (lmat == mat) return 0; // left pixel converted? suppose it was done by a prior scan and skip check @@ -237,22 +307,22 @@ int32_t C4Landscape::DoScan(int32_t cx, int32_t cy, int32_t mat, int32_t dir) int32_t iSearchRange = std::max(5, mconvs); // search upper/lower bound int32_t cys = cy, cxs = cx; - while (cxs < GBackWdt-1) + while (cxs < ::Landscape.GetWidth() - 1) { // one step right cxs++; - if (_GetMat(cxs, cys) == mat) + if (d->_GetMat(cxs, cys) == mat) { // search surface cys -= ydir; - while (Inside(cys, 0, GBackHgt-1) && _GetMat(cxs, cys) == mat) + while (Inside(cys, 0, ::Landscape.GetHeight() - 1) && d->_GetMat(cxs, cys) == mat) { cys -= ydir; if ((mconvs = std::min(mconv - Abs(cys - cy), mconvs)) < 0) return 0; } // out of bounds? - if (!Inside(cys, 0, GBackHgt-1)) break; + if (!Inside(cys, 0, ::Landscape.GetHeight() - 1)) break; // back one step cys += ydir; } @@ -260,35 +330,35 @@ int32_t C4Landscape::DoScan(int32_t cx, int32_t cy, int32_t mat, int32_t dir) { // search surface cys += ydir; - while (Inside(cys, 0, GBackHgt-1) && _GetMat(cxs, cys) != mat) + while (Inside(cys, 0, ::Landscape.GetHeight() - 1) && d->_GetMat(cxs, cys) != mat) { cys += ydir; if (Abs(cys - cy) > iSearchRange) break; } // out of bounds? - if (!Inside(cys, 0, GBackHgt-1)) break; + if (!Inside(cys, 0, ::Landscape.GetHeight() - 1)) break; if (Abs(cys - cy) > iSearchRange) break; } } } #endif // Conversion - bool conv_to_is_solid = (conv_to>-1) && DensitySolid(::MaterialMap.Map[conv_to].Density); - for (cy2 = cy; mconvs >= 0 && Inside(cy2, 0, GBackHgt-1); cy2 += ydir, mconvs--) + bool conv_to_is_solid = (conv_to > -1) && DensitySolid(::MaterialMap.Map[conv_to].Density); + for (cy2 = cy; mconvs >= 0 && Inside(cy2, 0, ::Landscape.GetHeight() - 1); cy2 += ydir, mconvs--) { // material changed? - int32_t pix = _GetPix(cx, cy2); + int32_t pix = d->_GetPix(cx, cy2); if (PixCol2Mat(pix) != mat) break; #ifdef PRETTY_TEMP_CONV // get left pixel - int32_t lmat = (cx > 0 ? _GetMat(cx-1, cy2) : -1); + int32_t lmat = (cx > 0 ? d->_GetMat(cx - 1, cy2) : -1); // left pixel not converted? break if (lmat == mat) break; #endif // set mat (and keep background material) - SetPix2(cx, cy2, MatTex2PixCol(conv_to_tex), Transparent); - if (!conv_to_is_solid) CheckInstabilityRange(cx,cy2); + d->SetPix2(cx, cy2, MatTex2PixCol(conv_to_tex), Transparent); + if (!conv_to_is_solid) d->CheckInstabilityRange(cx, cy2); } // return pixel converted return Abs(cy2 - cy); @@ -297,51 +367,51 @@ int32_t C4Landscape::DoScan(int32_t cx, int32_t cy, int32_t mat, int32_t dir) void C4Landscape::ScanSideOpen() { int32_t cy; - for (cy=0; (cyHeight) && !GetPix(0, cy); cy++) {} + p->LeftOpen = cy; + for (cy = 0; (cy < p->Height) && !GetPix(p->Width - 1, cy); cy++) {} + p->RightOpen = cy; } void C4Landscape::Draw(C4TargetFacet &cgo, C4FoWRegion *pLight) { - if (Modulation) pDraw->ActivateBlitModulation(Modulation); + if (p->Modulation) pDraw->ActivateBlitModulation(p->Modulation); // blit landscape if (::GraphicsSystem.Show8BitSurface == 1) - pDraw->Blit8Fast(Surface8, cgo.TargetX, cgo.TargetY, cgo.Surface, cgo.X,cgo.Y,cgo.Wdt,cgo.Hgt); + pDraw->Blit8Fast(p->Surface8.get(), cgo.TargetX, cgo.TargetY, cgo.Surface, cgo.X, cgo.Y, cgo.Wdt, cgo.Hgt); else if (::GraphicsSystem.Show8BitSurface == 2) - pDraw->Blit8Fast(Surface8Bkg, cgo.TargetX, cgo.TargetY, cgo.Surface, cgo.X,cgo.Y,cgo.Wdt,cgo.Hgt); - else if(pLandscapeRender) + pDraw->Blit8Fast(p->Surface8Bkg.get(), cgo.TargetX, cgo.TargetY, cgo.Surface, cgo.X, cgo.Y, cgo.Wdt, cgo.Hgt); + else if (p->pLandscapeRender) { DoRelights(); - pLandscapeRender->Draw(cgo, pLight); + p->pLandscapeRender->Draw(cgo, pLight); } - if (Modulation) pDraw->DeactivateBlitModulation(); + if (p->Modulation) pDraw->DeactivateBlitModulation(); } bool C4Landscape::DoRelights() { - if (!pLandscapeRender) return true; + if (!p->pLandscapeRender) return true; for (int32_t i = 0; i < C4LS_MaxRelights; i++) { - if (!Relights[i].Wdt) + if (!p->Relights[i].Wdt) break; // Remove all solid masks in the (twice!) extended region around the change - C4Rect SolidMaskRect = pLandscapeRender->GetAffectedRect(Relights[i]); + C4Rect SolidMaskRect = p->pLandscapeRender->GetAffectedRect(p->Relights[i]); C4SolidMask * pSolid; for (pSolid = C4SolidMask::Last; pSolid; pSolid = pSolid->Prev) pSolid->RemoveTemporary(SolidMaskRect); // Perform the update - pLandscapeRender->Update(Relights[i], this); - if (pFoW) pFoW->Ambient.UpdateFromLandscape(*this, Relights[i]); + p->pLandscapeRender->Update(p->Relights[i], this); + if (p->pFoW) p->pFoW->Ambient.UpdateFromLandscape(*this, p->Relights[i]); // Restore Solidmasks for (pSolid = C4SolidMask::First; pSolid; pSolid = pSolid->Next) pSolid->PutTemporary(SolidMaskRect); C4SolidMask::CheckConsistency(); // Clear slot - Relights[i].Default(); + p->Relights[i].Default(); } return true; } @@ -359,36 +429,36 @@ static std::vector GetRoundPolygon(int32_t x, int32_t y, int32_t size, 0 to 100. 0 gives an exagerated 'explosion' shape while 100 is almost a circle */ - if(smoothness > 100) smoothness = 100; - if(smoothness < 0) smoothness = 0; - if(size <= 0) size = 1; + if (smoothness > 100) smoothness = 100; + if (smoothness < 0) smoothness = 0; + if (size <= 0) size = 1; // vertex count of the polygon - int32_t count = 2*size/3 + 6; + int32_t count = 2 * size / 3 + 6; std::vector vertices; - vertices.reserve(count*2); + vertices.reserve(count * 2); // varying phase of the sin/cos waves - C4Real begin = itofix(360)*Random(100)/100; - C4Real begin2 = itofix(360)*Random(100)/100; + C4Real begin = itofix(360)*Random(100) / 100; + C4Real begin2 = itofix(360)*Random(100) / 100; // parameters: // the bigger the factor, the smaller the divergence from a circle - C4Real anticircle = itofix(3)+smoothness/16*smoothness/16; + C4Real anticircle = itofix(3) + smoothness / 16 * smoothness / 16; // the bigger the factor the more random is the divergence from the circle - int random = 80*(200-smoothness); + int random = 80 * (200 - smoothness); - for(int i=0; i < count; ++i) + for (int i = 0; i < count; ++i) { - C4Real angle = itofix(360)*i/count; + C4Real angle = itofix(360)*i / count; C4Real currsize = itofix(size); - currsize += Sin(angle*3 + begin + itofix(Random(random))/100) * size/anticircle; // +sin - currsize += Cos(angle*5 + begin2 + itofix(Random(random))/100) * size/anticircle/2; // +cos + currsize += Sin(angle * 3 + begin + itofix(Random(random)) / 100) * size / anticircle; // +sin + currsize += Cos(angle * 5 + begin2 + itofix(Random(random)) / 100) * size / anticircle / 2; // +cos - vertices.push_back(x+fixtoi(Sin(angle)*currsize)); - vertices.push_back(y-fixtoi(Cos(angle)*currsize)); + vertices.push_back(x + fixtoi(Sin(angle)*currsize)); + vertices.push_back(y - fixtoi(Cos(angle)*currsize)); } return vertices; @@ -400,9 +470,9 @@ static std::vector GetRectangle(int32_t tx, int32_t ty, int32_t wdt, in vertices.resize(8); vertices[0] = tx; vertices[1] = ty; - vertices[2] = tx; vertices[3] = ty+hgt; - vertices[4] = tx+wdt; vertices[5] = ty+hgt; - vertices[6] = tx+wdt; vertices[7] = ty; + vertices[2] = tx; vertices[3] = ty + hgt; + vertices[4] = tx + wdt; vertices[5] = ty + hgt; + vertices[6] = tx + wdt; vertices[7] = ty; return vertices; } @@ -419,54 +489,54 @@ static C4Rect getBoundingBox(int *vtcs, int length) void C4Landscape::ClearFreeRect(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt) { - std::vector vertices(GetRectangle(tx,ty,wdt,hgt)); + std::vector vertices(GetRectangle(tx, ty, wdt, hgt)); C4Rect r(tx, ty, wdt, hgt); - PrepareChange(r); - ForPolygon(&vertices[0],vertices.size()/2,&C4Landscape::ClearPix); - FinishChange(r); + p->PrepareChange(this, r); + p->ForPolygon(this, &vertices[0], vertices.size() / 2, [this](int32_t x, int32_t y) { return ClearPix(x, y); }); + p->FinishChange(this, r); } int32_t C4Landscape::DigFreeRect(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, C4Object *by_object, bool no_dig2objects, bool no_instability_check) { - std::vector vertices(GetRectangle(tx,ty,wdt,hgt)); - return DigFreeShape(&vertices[0],vertices.size(),by_object, no_dig2objects, no_instability_check); + std::vector vertices(GetRectangle(tx, ty, wdt, hgt)); + return DigFreeShape(&vertices[0], vertices.size(), by_object, no_dig2objects, no_instability_check); } int32_t C4Landscape::DigFree(int32_t tx, int32_t ty, int32_t rad, C4Object *by_object, bool no_dig2objects, bool no_instability_check) { - std::vector vertices(GetRoundPolygon(tx,ty,rad,80)); - return DigFreeShape(&vertices[0],vertices.size(),by_object, no_dig2objects, no_instability_check); + std::vector vertices(GetRoundPolygon(tx, ty, rad, 80)); + return DigFreeShape(&vertices[0], vertices.size(), by_object, no_dig2objects, no_instability_check); } void C4Landscape::BlastFree(int32_t tx, int32_t ty, int32_t rad, int32_t caused_by, C4Object *by_object, int32_t iMaxDensity) { - std::vector vertices(GetRoundPolygon(tx,ty,rad,30)); - BlastFreeShape(&vertices[0],vertices.size(),by_object,caused_by,iMaxDensity); + std::vector vertices(GetRoundPolygon(tx, ty, rad, 30)); + BlastFreeShape(&vertices[0], vertices.size(), by_object, caused_by, iMaxDensity); } void C4Landscape::ShakeFree(int32_t tx, int32_t ty, int32_t rad) { - std::vector vertices(GetRoundPolygon(tx,ty,rad,50)); - ForPolygon(&vertices[0],vertices.size()/2,&C4Landscape::ShakeFreePix); + std::vector vertices(GetRoundPolygon(tx, ty, rad, 50)); + p->ForPolygon(this, &vertices[0], vertices.size() / 2, [this](int32_t x, int32_t y) { return p->ShakeFreePix(this, x, y); }); } -C4ValueArray *C4Landscape::PrepareFreeShape(C4Rect &BoundingBox, C4Object *by_object) +C4ValueArray *C4Landscape::P::PrepareFreeShape(C4Rect &BoundingBox, C4Object *by_object) { // Remember any in-earth objects in area C4FindObjectInRect fo_inrect(BoundingBox); C4FindObjectOCF fo_insolid(OCF_InSolid); C4FindObjectLayer fo_layer(by_object ? by_object->Layer : NULL); - C4FindObject *fo_list[] = {&fo_inrect, &fo_insolid, &fo_layer}; + C4FindObject *fo_list[] = { &fo_inrect, &fo_insolid, &fo_layer }; C4FindObjectAndStatic fo_srch(3, fo_list); return fo_srch.FindMany(::Objects, ::Objects.Sectors); } -void C4Landscape::PostFreeShape(C4ValueArray *dig_objects, C4Object *by_object) +void C4Landscape::P::PostFreeShape(C4ValueArray *dig_objects, C4Object *by_object) { // Do callbacks to digger and dug out objects for objects that are now dug free if (by_object) { - for (int32_t i=0; iGetSize(); ++i) + for (int32_t i = 0; i < dig_objects->GetSize(); ++i) { C4Object *dig_object = dig_objects->GetItem(i).getObj(); if (dig_object && !GBackSolid(dig_object->GetX(), dig_object->GetY())) @@ -487,41 +557,43 @@ void C4Landscape::PostFreeShape(C4ValueArray *dig_objects, C4Object *by_object) int32_t C4Landscape::DigFreeShape(int *vtcs, int length, C4Object *by_object, bool no_dig2objects, bool no_instability_check) { - C4Rect BoundingBox = getBoundingBox(vtcs,length); + using namespace std::placeholders; + + C4Rect BoundingBox = getBoundingBox(vtcs, length); int32_t amount; // Remember any collectible objects in area - std::unique_ptr dig_objects(PrepareFreeShape(BoundingBox, by_object)); + std::unique_ptr dig_objects(p->PrepareFreeShape(BoundingBox, by_object)); - if(by_object) + std::function callback; + if (no_instability_check) + callback = [this](int32_t x, int32_t y) { return p->DigFreePixNoInstability(this, x, y); }; + else + callback = [this](int32_t x, int32_t y) { return p->DigFreePix(this, x, y); }; + + if (by_object) { - if(!by_object->MaterialContents) + if (!by_object->MaterialContents) by_object->MaterialContents = new C4MaterialList; - if (no_instability_check) - amount = ForPolygon(vtcs,length/2,&C4Landscape::DigFreePixNoInstability,by_object->MaterialContents); - else - amount = ForPolygon(vtcs,length/2,&C4Landscape::DigFreePix,by_object->MaterialContents); + amount = p->ForPolygon(this, vtcs, length / 2, callback, by_object->MaterialContents); } else - if (no_instability_check) - amount = ForPolygon(vtcs,length/2,&C4Landscape::DigFreePixNoInstability,NULL); - else - amount = ForPolygon(vtcs,length/2,&C4Landscape::DigFreePix,NULL); + amount = p->ForPolygon(this, vtcs, length / 2, callback, NULL); // create objects from the material - if(!::Game.iTick5) + if (!::Game.iTick5) { - if(!no_dig2objects) - if(by_object) - if(by_object->MaterialContents) + if (!no_dig2objects) + if (by_object) + if (by_object->MaterialContents) { int32_t tx = BoundingBox.GetMiddleX(), ty = BoundingBox.GetBottom(); - DigMaterial2Objects(tx,ty,by_object->MaterialContents, by_object); + p->DigMaterial2Objects(tx, ty, by_object->MaterialContents, by_object); } } // Do callbacks to digger for objects that are now dug free - PostFreeShape(dig_objects.get(), by_object); + p->PostFreeShape(dig_objects.get(), by_object); return amount; } @@ -530,49 +602,49 @@ void C4Landscape::BlastFreeShape(int *vtcs, int length, C4Object *by_object, int { C4MaterialList *MaterialContents = NULL; - C4Rect BoundingBox = getBoundingBox(vtcs,length); + C4Rect BoundingBox = getBoundingBox(vtcs, length); // Remember any collectible objects in area - std::unique_ptr dig_objects(PrepareFreeShape(BoundingBox, by_object)); + std::unique_ptr dig_objects(p->PrepareFreeShape(BoundingBox, by_object)); uint8_t *pblast_tbl = NULL, blast_tbl[C4M_MaxTexIndex]; if (iMaxDensity < C4M_Vehicle) { - for (int32_t i=0; i < C4M_MaxTexIndex; ++i) blast_tbl[i] = (GetPixDensity(i)<=iMaxDensity); + for (int32_t i = 0; i < C4M_MaxTexIndex; ++i) blast_tbl[i] = (GetPixDensity(i) <= iMaxDensity); pblast_tbl = blast_tbl; } - if(by_object) + if (by_object) { - if(!by_object->MaterialContents) + if (!by_object->MaterialContents) by_object->MaterialContents = new C4MaterialList; - ForPolygon(vtcs,length/2,&C4Landscape::BlastFreePix,by_object->MaterialContents, 0, 0, pblast_tbl); + p->ForPolygon(this, vtcs, length / 2, [this](int32_t x, int32_t y) { return p->BlastFreePix(this, x, y); }, by_object->MaterialContents, 0, 0, pblast_tbl); } else { MaterialContents = new C4MaterialList; - ForPolygon(vtcs,length/2,&C4Landscape::BlastFreePix,MaterialContents,iMaxDensity); + p->ForPolygon(this, vtcs, length / 2, [this](int32_t x, int32_t y) { return p->BlastFreePix(this, x, y); }, MaterialContents, iMaxDensity); } // create objects from the material C4MaterialList *mat_list = NULL; - if(by_object) + if (by_object) mat_list = by_object->MaterialContents; else mat_list = MaterialContents; int32_t tx = BoundingBox.GetMiddleX(), ty = BoundingBox.GetMiddleY(); - BlastMaterial2Objects(tx,ty,mat_list,by_player,(BoundingBox.Wdt+BoundingBox.Hgt)/4, dig_objects.get()); + p->BlastMaterial2Objects(tx, ty, mat_list, by_player, (BoundingBox.Wdt + BoundingBox.Hgt) / 4, dig_objects.get()); - if(MaterialContents) delete MaterialContents; + if (MaterialContents) delete MaterialContents; // Do callbacks to digger for objects that are now dug free - PostFreeShape(dig_objects.get(), by_object); + p->PostFreeShape(dig_objects.get(), by_object); } -void C4Landscape::BlastMaterial2Objects(int32_t tx, int32_t ty, C4MaterialList *mat_list, int32_t caused_by, int32_t str, C4ValueArray *out_objects) +void C4Landscape::P::BlastMaterial2Objects(int32_t tx, int32_t ty, C4MaterialList *mat_list, int32_t caused_by, int32_t str, C4ValueArray *out_objects) { - for (int32_t mat=0; mat< ::MaterialMap.Num; mat++) + for (int32_t mat = 0; mat < ::MaterialMap.Num; mat++) { if (mat_list->Amount[mat]) { @@ -581,29 +653,29 @@ void C4Landscape::BlastMaterial2Objects(int32_t tx, int32_t ty, C4MaterialList * if (::MaterialMap.Map[mat].Blast2PXSRatio != 0) { - pxsamount = mat_list->Amount[mat]/::MaterialMap.Map[mat].Blast2PXSRatio; - ::PXS.Cast(mat,pxsamount,tx,ty,cast_strength*2); + pxsamount = mat_list->Amount[mat] / ::MaterialMap.Map[mat].Blast2PXSRatio; + ::PXS.Cast(mat, pxsamount, tx, ty, cast_strength * 2); } if (::MaterialMap.Map[mat].Blast2Object != C4ID::None) { if (::MaterialMap.Map[mat].Blast2ObjectRatio != 0) { - blastamount = mat_list->Amount[mat]/::MaterialMap.Map[mat].Blast2ObjectRatio; + blastamount = mat_list->Amount[mat] / ::MaterialMap.Map[mat].Blast2ObjectRatio; Game.CastObjects(::MaterialMap.Map[mat].Blast2Object, NULL, blastamount, cast_strength, tx, ty, NO_OWNER, caused_by, out_objects); } } mat_list->Amount[mat] -= std::max(blastamount * ::MaterialMap.Map[mat].Blast2ObjectRatio, - pxsamount * ::MaterialMap.Map[mat].Blast2PXSRatio); + pxsamount * ::MaterialMap.Map[mat].Blast2PXSRatio); } } } -void C4Landscape::DigMaterial2Objects(int32_t tx, int32_t ty, C4MaterialList *mat_list, C4Object *pCollect) +void C4Landscape::P::DigMaterial2Objects(int32_t tx, int32_t ty, C4MaterialList *mat_list, C4Object *pCollect) { C4AulParSet pars(pCollect); - for (int32_t mat=0; mat< ::MaterialMap.Num; mat++) + for (int32_t mat = 0; mat < ::MaterialMap.Num; mat++) { if (mat_list->Amount[mat]) { @@ -624,11 +696,11 @@ void C4Landscape::DigMaterial2Objects(int32_t tx, int32_t ty, C4MaterialList *ma pCollect->Call(PSF_DigOutObject, &pars); if (!pObj->Status || !pCollect->Status || pObj->Contained) continue; // Try to collect object - if(::MaterialMap.Map[mat].Dig2ObjectCollect) - if(pCollect && pCollect->Status && pObj && pObj->Status) - if(!pCollect->Collect(pObj)) + if (::MaterialMap.Map[mat].Dig2ObjectCollect) + if (pCollect && pCollect->Status && pObj && pObj->Status) + if (!pCollect->Collect(pObj)) // Collection forced? Don't generate objects - if(::MaterialMap.Map[mat].Dig2ObjectCollect == 2) + if (::MaterialMap.Map[mat].Dig2ObjectCollect == 2) { pObj->AssignRemoval(); // Cap so we never have more than one object worth of material in the store @@ -640,63 +712,63 @@ void C4Landscape::DigMaterial2Objects(int32_t tx, int32_t ty, C4MaterialList *ma } } -bool C4Landscape::DigFreePixNoInstability(int32_t tx, int32_t ty) +bool C4Landscape::P::DigFreePixNoInstability(C4Landscape *d, int32_t tx, int32_t ty) { - int32_t mat = GetMat(tx,ty); + int32_t mat = d->GetMat(tx, ty); if (MatValid(mat)) if (::MaterialMap.Map[mat].DigFree) { - ClearPix(tx,ty); + d->ClearPix(tx, ty); return true; } return false; } -bool C4Landscape::DigFreePix(int32_t tx, int32_t ty) +bool C4Landscape::P::DigFreePix(C4Landscape *d, int32_t tx, int32_t ty) { - int32_t mat = GetMat(tx,ty); + int32_t mat = d->GetMat(tx, ty); if (MatValid(mat)) if (::MaterialMap.Map[mat].DigFree) { - ClearPix(tx,ty); + d->ClearPix(tx, ty); // check for instable materials to start moving by the cleared space - CheckInstabilityRange(tx,ty); + d->CheckInstabilityRange(tx, ty); return true; } return false; } -bool C4Landscape::BlastFreePix(int32_t tx, int32_t ty) +bool C4Landscape::P::BlastFreePix(C4Landscape *d, int32_t tx, int32_t ty) { - int32_t mat = GetMat(tx,ty); + int32_t mat = d->GetMat(tx, ty); if (MatValid(mat)) { // for blast, either shift to different material or blast free if (::MaterialMap.Map[mat].BlastFree) { - ClearPix(tx,ty); + d->ClearPix(tx, ty); // check for instable materials to start moving by the cleared space - CheckInstabilityRange(tx,ty); + d->CheckInstabilityRange(tx, ty); return true; } else if (::MaterialMap.Map[mat].BlastShiftTo) - SetPix2(tx,ty,MatTex2PixCol(::MaterialMap.Map[mat].BlastShiftTo), Transparent); + d->SetPix2(tx, ty, MatTex2PixCol(::MaterialMap.Map[mat].BlastShiftTo), Transparent); } return false; } -bool C4Landscape::ShakeFreePix(int32_t tx, int32_t ty) +bool C4Landscape::P::ShakeFreePix(C4Landscape *d, int32_t tx, int32_t ty) { - int32_t mat=GetMat(tx,ty); + int32_t mat = d->GetMat(tx, ty); if (MatValid(mat)) { if (::MaterialMap.Map[mat].DigFree) { - ClearPix(tx,ty); - ::PXS.Create(mat,itofix(tx),itofix(ty)); + d->ClearPix(tx, ty); + ::PXS.Create(mat, itofix(tx), itofix(ty)); // check for instable materials to start moving by the cleared space - CheckInstabilityRange(tx,ty); + d->CheckInstabilityRange(tx, ty); return true; } } @@ -706,17 +778,22 @@ bool C4Landscape::ShakeFreePix(int32_t tx, int32_t ty) bool C4Landscape::ClearPix(int32_t tx, int32_t ty) { // Replace pixel with background pixel - BYTE bkgPix = Surface8Bkg->GetPix(tx, ty); + BYTE bkgPix = p->Surface8Bkg->GetPix(tx, ty); return SetPix2(tx, ty, bkgPix, bkgPix); } +void C4Landscape::ClearPointers(C4Object * pObj) +{ + if (p->pFoW) p->pFoW->Remove(pObj); +} + bool C4Landscape::SetPix2(int32_t x, int32_t y, BYTE fgPix, BYTE bgPix) { // check bounds - if (x < 0 || y < 0 || x >= Width || y >= Height) + if (x < 0 || y < 0 || x >= GetWidth() || y >= GetHeight()) return false; // no change? - if ((fgPix == Transparent || fgPix == _GetPix(x, y)) && (bgPix == Transparent || bgPix == Surface8Bkg->_GetPix(x, y))) + if ((fgPix == Transparent || fgPix == _GetPix(x, y)) && (bgPix == Transparent || bgPix == p->Surface8Bkg->_GetPix(x, y))) return true; // set pixel return _SetPix2(x, y, fgPix, bgPix); @@ -727,26 +804,30 @@ bool C4Landscape::_SetPix2(int32_t x, int32_t y, BYTE fgPix, BYTE bgPix) if (Config.General.DebugRec) { C4RCSetPix rc; - rc.x=x; rc.y=y; rc.clr=fgPix; rc.bgClr=fgPix; + rc.x = x; rc.y = y; rc.clr = fgPix; rc.bgClr = fgPix; AddDbgRec(RCT_SetPix, &rc, sizeof(rc)); } - assert(x >= 0 && y >= 0 && x < Width && y < Height); + assert(x >= 0 && y >= 0 && x < GetWidth() && y < GetHeight()); // get pixel and resolve transparency to already existing pixel BYTE opix = _GetPix(x, y); if (fgPix == Transparent) fgPix = opix; - if (bgPix == Transparent) bgPix = Surface8Bkg->_GetPix(x, y); + if (bgPix == Transparent) bgPix = p->Surface8Bkg->_GetPix(x, y); // check pixel - if (fgPix == opix && bgPix == Surface8Bkg->_GetPix(x, y)) return true; + if (fgPix == opix && bgPix == p->Surface8Bkg->_GetPix(x, y)) return true; // count pixels - if (Pix2Dens[fgPix]) - { if (!Pix2Dens[opix]) PixCnt[(y / 15) + (x / 17) * PixCntPitch]++; } + if (p->Pix2Dens[fgPix]) + { + if (!p->Pix2Dens[opix]) p->PixCnt[(y / 15) + (x / 17) * p->PixCntPitch]++; + } else - { if (Pix2Dens[opix]) PixCnt[(y / 15) + (x / 17) * PixCntPitch]--; } + { + if (p->Pix2Dens[opix]) p->PixCnt[(y / 15) + (x / 17) * p->PixCntPitch]--; + } // count material - assert(!fgPix || MatValid(Pix2Mat[fgPix])); - int32_t omat = Pix2Mat[opix], nmat = Pix2Mat[fgPix]; - if (opix) MatCount[omat]--; - if (fgPix) MatCount[nmat]++; + assert(!fgPix || MatValid(p->Pix2Mat[fgPix])); + int32_t omat = p->Pix2Mat[opix], nmat = p->Pix2Mat[fgPix]; + if (opix) p->MatCount[omat]--; + if (fgPix) p->MatCount[nmat]++; // count effective material if (omat != nmat) { @@ -754,8 +835,8 @@ bool C4Landscape::_SetPix2(int32_t x, int32_t y, BYTE fgPix, BYTE bgPix) { // Check for material above & below int iMinHeight = ::MaterialMap.Map[nmat].MinHeightCount, - iBelow = GetMatHeight(x, y+1, +1, nmat, iMinHeight), - iAbove = GetMatHeight(x, y-1, -1, nmat, iMinHeight); + iBelow = GetMatHeight(x, y + 1, +1, nmat, iMinHeight), + iAbove = GetMatHeight(x, y - 1, -1, nmat, iMinHeight); // Will be above treshold? if (iBelow + iAbove + 1 >= iMinHeight) { @@ -764,15 +845,15 @@ bool C4Landscape::_SetPix2(int32_t x, int32_t y, BYTE fgPix, BYTE bgPix) if (iBelow < iMinHeight) iChange += iBelow; if (iAbove < iMinHeight) iChange += iAbove; // Change - EffectiveMatCount[nmat] += iChange; + p->EffectiveMatCount[nmat] += iChange; } } if (opix && ::MaterialMap.Map[omat].MinHeightCount) { // Check for material above & below int iMinHeight = ::MaterialMap.Map[omat].MinHeightCount, - iBelow = GetMatHeight(x, y+1, +1, omat, iMinHeight), - iAbove = GetMatHeight(x, y-1, -1, omat, iMinHeight); + iBelow = GetMatHeight(x, y + 1, +1, omat, iMinHeight), + iAbove = GetMatHeight(x, y - 1, -1, omat, iMinHeight); // Not already below threshold? if (iBelow + iAbove + 1 >= iMinHeight) { @@ -781,26 +862,26 @@ bool C4Landscape::_SetPix2(int32_t x, int32_t y, BYTE fgPix, BYTE bgPix) if (iBelow < iMinHeight) iChange += iBelow; if (iAbove < iMinHeight) iChange += iAbove; // Change - EffectiveMatCount[omat] -= iChange; + p->EffectiveMatCount[omat] -= iChange; } } } // set 8bpp-surface only! - Surface8->SetPix(x, y, fgPix); - Surface8Bkg->SetPix(x, y, bgPix); + p->Surface8->SetPix(x, y, fgPix); + p->Surface8Bkg->SetPix(x, y, bgPix); // note for relight - if(pLandscapeRender) + if (p->pLandscapeRender) { - C4Rect CheckRect = pLandscapeRender->GetAffectedRect(C4Rect(x, y, 1, 1)); + C4Rect CheckRect = p->pLandscapeRender->GetAffectedRect(C4Rect(x, y, 1, 1)); for (int32_t i = 0; i < C4LS_MaxRelights; i++) - if (!Relights[i].Wdt || Relights[i].Overlap(CheckRect) || i + 1 >= C4LS_MaxRelights) + if (!p->Relights[i].Wdt || p->Relights[i].Overlap(CheckRect) || i + 1 >= C4LS_MaxRelights) { - Relights[i].Add(CheckRect); + p->Relights[i].Add(CheckRect); break; } // Invalidate FoW - if (pFoW) - pFoW->Invalidate(CheckRect); + if (p->pFoW) + p->pFoW->Invalidate(CheckRect); } // success return true; @@ -809,32 +890,32 @@ bool C4Landscape::_SetPix2(int32_t x, int32_t y, BYTE fgPix, BYTE bgPix) void C4Landscape::_SetPix2Tmp(int32_t x, int32_t y, BYTE fgPix, BYTE bgPix) { // set 8bpp-surface only! - assert(x >= 0 && y >= 0 && x < Width && y < Height); - if (fgPix != Transparent) Surface8->SetPix(x, y, fgPix); - if (bgPix != Transparent) Surface8Bkg->SetPix(x, y, bgPix); + assert(x >= 0 && y >= 0 && x < GetWidth() && y < GetHeight()); + if (fgPix != Transparent) p->Surface8->SetPix(x, y, fgPix); + if (bgPix != Transparent) p->Surface8Bkg->SetPix(x, y, bgPix); } bool C4Landscape::CheckInstability(int32_t tx, int32_t ty, int32_t recursion_count) { - int32_t mat=GetMat(tx,ty); + int32_t mat = GetMat(tx, ty); if (MatValid(mat)) { const C4Material &material = MaterialMap.Map[mat]; if (material.Instable) - return ::MassMover.Create(tx,ty); + return ::MassMover.Create(tx, ty); // Get rid of single pixels - else if (DensitySolid(material.Density) && !material.KeepSinglePixels && recursion_count<10) - if ((!::GBackSolid(tx,ty+1)) + (!::GBackSolid(tx,ty-1)) + (!::GBackSolid(tx+1,ty)) + (!::GBackSolid(tx-1,ty)) >= 3) + else if (DensitySolid(material.Density) && !material.KeepSinglePixels && recursion_count < 10) + if ((!::GBackSolid(tx, ty + 1)) + (!::GBackSolid(tx, ty - 1)) + (!::GBackSolid(tx + 1, ty)) + (!::GBackSolid(tx - 1, ty)) >= 3) { - if (!ClearPix(tx,ty)) return false; + if (!ClearPix(tx, ty)) return false; // Diggable material drops; other material just gets removed - if (material.DigFree) ::PXS.Create(mat,itofix(tx),itofix(ty)); + if (material.DigFree) ::PXS.Create(mat, itofix(tx), itofix(ty)); // check other pixels around this // Note this cannot lead to an endless recursion (unless you do funny stuff like e.g. set DigFree=1 in material Tunnel). // Check recursion anyway, because very large strips of single pixel width might cause sufficient recursion to crash - CheckInstability(tx+1,ty,++recursion_count); - CheckInstability(tx-1,ty,recursion_count); - CheckInstability(tx,ty-1,recursion_count); - CheckInstability(tx,ty+1,recursion_count); + CheckInstability(tx + 1, ty, ++recursion_count); + CheckInstability(tx - 1, ty, recursion_count); + CheckInstability(tx, ty - 1, recursion_count); + CheckInstability(tx, ty + 1, recursion_count); return true; } } @@ -843,47 +924,47 @@ bool C4Landscape::CheckInstability(int32_t tx, int32_t ty, int32_t recursion_cou void C4Landscape::CheckInstabilityRange(int32_t tx, int32_t ty) { - if (!CheckInstability(tx,ty)) + if (!CheckInstability(tx, ty)) { - CheckInstability(tx,ty-1); - CheckInstability(tx,ty-2); - CheckInstability(tx-1,ty); - CheckInstability(tx+1,ty); + CheckInstability(tx, ty - 1); + CheckInstability(tx, ty - 2); + CheckInstability(tx - 1, ty); + CheckInstability(tx + 1, ty); } } void C4Landscape::DrawMaterialRect(int32_t mat, int32_t tx, int32_t ty, int32_t wdt, int32_t hgt) { - int32_t cx,cy; - for (cy=ty; cy=GetDensity(cx,cy))) - SetPix2(cx,cy,Mat2PixColDefault(mat), Surface8Bkg->GetPix(cx, cy)); + int32_t cx, cy; + for (cy = ty; cy < ty + hgt; cy++) + for (cx = tx; cx < tx + wdt; cx++) + if ((MatDensity(mat) >= GetDensity(cx, cy))) + SetPix2(cx, cy, Mat2PixColDefault(mat), p->Surface8Bkg->GetPix(cx, cy)); } void C4Landscape::RaiseTerrain(int32_t tx, int32_t ty, int32_t wdt) { - int32_t cx,cy; + int32_t cx, cy; BYTE cpix; - for (cx=tx; cx=ty) { SetPix2(cx,cy,cpix,GetBackPix(cx,cy+1)); cy--; } - } + for (cy = ty; (cy + 1 < ::Landscape.GetHeight()) && !GBackSolid(cx, cy + 1); cy++) {} + if (cy + 1 < ::Landscape.GetHeight()) if (cy - ty < 20) + { + cpix = GetPix(cx, cy + 1); + if (!MatVehicle(PixCol2Mat(cpix))) + while (cy >= ty) { SetPix2(cx, cy, cpix, GetBackPix(cx, cy + 1)); cy--; } + } } } int32_t C4Landscape::ExtractMaterial(int32_t fx, int32_t fy, bool distant_first) { - int32_t mat=GetMat(fx,fy); - if (mat==MNone) return MNone; - FindMatTop(mat,fx,fy,distant_first); - ClearPix(fx,fy); - CheckInstabilityRange(fx,fy); + int32_t mat = GetMat(fx, fy); + if (mat == MNone) return MNone; + FindMatTop(mat, fx, fy, distant_first); + ClearPix(fx, fy); + CheckInstabilityRange(fx, fy); return mat; } @@ -900,57 +981,59 @@ bool C4Landscape::InsertMaterial(int32_t mat, int32_t *tx, int32_t *ty, int32_t assert(tx); assert(ty); int32_t mdens; if (!MatValid(mat)) return false; - mdens=std::min(MatDensity(mat), C4M_Solid); + mdens = std::min(MatDensity(mat), C4M_Solid); if (!mdens) return true; // Bounds - if (!Inside(*tx, 0, Width - 1) || !Inside(*ty, 0, Height)) return InsertMaterialOutsideLandscape(*tx, *ty, mdens); + if (!Inside(*tx, 0, GetWidth() - 1) || !Inside(*ty, 0, GetHeight())) return InsertMaterialOutsideLandscape(*tx, *ty, mdens); if (Game.C4S.Game.Realism.LandscapePushPull) { // Same or higher density? if (GetDensity(*tx, *ty) >= mdens) // Push - if (!FindMatPathPush(*tx, *ty, mdens, ::MaterialMap.Map[mat].MaxSlide, !! ::MaterialMap.Map[mat].Instable)) + if (!FindMatPathPush(*tx, *ty, mdens, ::MaterialMap.Map[mat].MaxSlide, !!::MaterialMap.Map[mat].Instable)) // Or die return false; } else { // Move up above same density - while (mdens==std::min(GetDensity(*tx,*ty),C4M_Solid)) + while (mdens == std::min(GetDensity(*tx, *ty), C4M_Solid)) { - (*ty)--; if (*ty<0) return false; + (*ty)--; if (*ty < 0) return false; // Primitive slide (1) - if (GetDensity(*tx-1,*ty)mdens) return false; + if (GetDensity(*tx, *ty) > mdens) return false; } // Try slide - while (FindMatSlide(*tx,*ty,+1,mdens,::MaterialMap.Map[mat].MaxSlide)) - if (GetDensity(*tx,*ty+1)(*tx,0,Width-1) || !Inside(*ty,0,Height)) return InsertMaterialOutsideLandscape(*tx, *ty, mdens); - return true; + if (!Inside(*tx, 0, GetWidth() - 1) || !Inside(*ty, 0, GetHeight())) return InsertMaterialOutsideLandscape(*tx, *ty, mdens); + return true; } // Try reaction with material below and at insertion position C4MaterialReaction *pReact; int32_t tmat; int32_t check_dir = 0; - for (int32_t i=0; i<2; ++i) + for (int32_t i = 0; i < 2; ++i) { - if ((pReact = ::MaterialMap.GetReactionUnsafe(mat, tmat=GetMat(*tx,*ty+check_dir)))) + if ((pReact = ::MaterialMap.GetReactionUnsafe(mat, tmat = GetMat(*tx, *ty + check_dir)))) { - C4Real fvx=C4REAL10(vx), fvy=C4REAL10(vy); - if ((*pReact->pFunc)(pReact, *tx,*ty, *tx,*ty+check_dir, fvx,fvy, mat,tmat, meePXSPos,NULL)) + C4Real fvx = C4REAL10(vx), fvy = C4REAL10(vy); + if ((*pReact->pFunc)(pReact, *tx, *ty, *tx, *ty + check_dir, fvx, fvy, mat, tmat, meePXSPos, NULL)) { // the material to be inserted killed itself in some material reaction below return true; @@ -966,7 +1049,7 @@ bool C4Landscape::InsertMaterial(int32_t mat, int32_t *tx, int32_t *ty, int32_t bool C4Landscape::InsertDeadMaterial(int32_t mat, int32_t tx, int32_t ty) { // Check bounds - if (tx < 0 || ty < 0 || tx >= Width || ty >= Height) + if (tx < 0 || ty < 0 || tx >= GetWidth() || ty >= GetHeight()) return InsertMaterialOutsideLandscape(tx, ty, std::min(MatDensity(mat), C4M_Solid)); // Save back original material so we can insert it later @@ -976,24 +1059,24 @@ bool C4Landscape::InsertDeadMaterial(int32_t mat, int32_t tx, int32_t ty) // Check surroundings for inspiration for texture to use int n = 0; int pix = -1; - if(tx > 0 && _GetMat(tx-1, ty) == mat) - if(!Random(++n)) pix = _GetPix(tx-1, ty); - if(ty > 0 && _GetMat(tx, ty-1) == mat) - if(!Random(++n)) pix = _GetPix(tx, ty-1); - if(tx+1 < Width && _GetMat(tx+1, ty) == mat) - if(!Random(++n)) pix = _GetPix(tx+1, ty); - if(ty+1 < Height && _GetMat(tx, ty+1) == mat) - if(!Random(++n)) pix = _GetPix(tx, ty+1); - if(pix < 0) + if (tx > 0 && _GetMat(tx - 1, ty) == mat) + if (!Random(++n)) pix = _GetPix(tx - 1, ty); + if (ty > 0 && _GetMat(tx, ty - 1) == mat) + if (!Random(++n)) pix = _GetPix(tx, ty - 1); + if (tx + 1 < GetWidth() && _GetMat(tx + 1, ty) == mat) + if (!Random(++n)) pix = _GetPix(tx + 1, ty); + if (ty + 1 < GetHeight() && _GetMat(tx, ty + 1) == mat) + if (!Random(++n)) pix = _GetPix(tx, ty + 1); + if (pix < 0) pix = Mat2PixColDefault(mat); // Insert dead material - SetPix2(tx,ty,pix, Transparent); + SetPix2(tx, ty, pix, Transparent); // Search a position for the old material pixel if (Game.C4S.Game.Realism.LandscapeInsertThrust && MatValid(omat)) { - int32_t tyo = ty-1; + int32_t tyo = ty - 1; InsertMaterial(omat, &tx, &tyo); } @@ -1002,7 +1085,7 @@ bool C4Landscape::InsertDeadMaterial(int32_t mat, int32_t tx, int32_t ty) bool C4Landscape::Incinerate(int32_t x, int32_t y, int32_t cause_player) { - int32_t mat=GetMat(x,y); + int32_t mat = GetMat(x, y); if (MatValid(mat)) if (::MaterialMap.Map[mat].Inflammable) { @@ -1012,20 +1095,22 @@ bool C4Landscape::Incinerate(int32_t x, int32_t y, int32_t cause_player) return false; } -BYTE C4Landscape::DefaultBkgMat(BYTE fg) const +BYTE C4Landscape::P::DefaultBkgMat(BYTE fg) const { return ::TextureMap.DefaultBkgMatTex(fg); } -CSurface8* C4Landscape::CreateDefaultBkgSurface(CSurface8& sfcFg, bool msbAsIft) const +std::unique_ptr C4Landscape::P::CreateDefaultBkgSurface(CSurface8& sfcFg, bool msbAsIft) const { - CSurface8* sfcBg = new CSurface8(); + auto sfcBg = std::make_unique(); if (!sfcBg->Create(sfcFg.Wdt, sfcFg.Hgt)) - { delete sfcBg; return NULL; } - - for (int32_t y=0; y_SetPix(x, y, bgPix); @@ -1080,16 +1165,18 @@ struct CPolyEdge // An edge for the polygon drawer static void fill_edge_structure(CPolyEdge *edge, int *i1, int *i2) { if (i2[1] < i1[1]) // Swap - { int *t=i1; i1=i2; i2=t; } + { + int *t = i1; i1 = i2; i2 = t; + } edge->y = i1[1]; edge->bottom = i2[1] - 1; edge->dx = ((i2[0] - i1[0]) << POLYGON_FIX_SHIFT) / (i2[1] - i1[1]); - edge->x = (i1[0] << POLYGON_FIX_SHIFT) + (1<<(POLYGON_FIX_SHIFT-1)) - 1; + edge->x = (i1[0] << POLYGON_FIX_SHIFT) + (1 << (POLYGON_FIX_SHIFT - 1)) - 1; edge->prev = NULL; edge->next = NULL; if (edge->dx < 0) - edge->x += std::min(edge->dx+(1<w = std::max(Abs(edge->dx)-(1<x += std::min(edge->dx + (1 << POLYGON_FIX_SHIFT), 0); + edge->w = std::max(Abs(edge->dx) - (1 << POLYGON_FIX_SHIFT), 0); } static CPolyEdge *add_edge(CPolyEdge *list, CPolyEdge *edge, int sort_by_x) @@ -1098,13 +1185,17 @@ static CPolyEdge *add_edge(CPolyEdge *list, CPolyEdge *edge, int sort_by_x) CPolyEdge *prev = NULL; if (sort_by_x) { - while ((pos) && (pos->x+pos->w/2 < edge->x+edge->w/2)) - { prev = pos; pos = pos->next; } + while ((pos) && (pos->x + pos->w / 2 < edge->x + edge->w / 2)) + { + prev = pos; pos = pos->next; + } } else { while ((pos) && (pos->y < edge->y)) - { prev = pos; pos = pos->next; } + { + prev = pos; pos = pos->next; + } } edge->next = pos; edge->prev = prev; @@ -1124,31 +1215,33 @@ static CPolyEdge *remove_edge(CPolyEdge *list, CPolyEdge *edge) const int QuickPolyBufSize = 20; CPolyEdge QuickPolyBuf[QuickPolyBufSize]; -int32_t C4Landscape::ForPolygon(int *vtcs, int length, bool (C4Landscape::*fnCallback)(int32_t, int32_t), - C4MaterialList *mats_count, uint8_t col, uint8_t colBkg, uint8_t *conversion_table) +int32_t C4Landscape::P::ForPolygon(C4Landscape *d, int *vtcs, int length, const std::function &callback, + C4MaterialList *mats_count, uint8_t col, uint8_t colBkg, uint8_t *conversion_table) { // Variables for polygon drawer - int c,x1,x2,y; + int c, x1, x2, y; int top = INT_MAX; int bottom = INT_MIN; int *i1, *i2; CPolyEdge *edge, *next_edge, *edgebuf; CPolyEdge *active_edges = NULL; CPolyEdge *inactive_edges = NULL; - bool use_qpb=false; + bool use_qpb = false; // Return value int32_t amount = 0; // Poly Buf - if (length<=QuickPolyBufSize) - { edgebuf=QuickPolyBuf; use_qpb=true; } - else if (!(edgebuf = new CPolyEdge [length])) { return 0; } + if (length <= QuickPolyBufSize) + { + edgebuf = QuickPolyBuf; use_qpb = true; + } + else if (!(edgebuf = new CPolyEdge[length])) { return 0; } // Fill the edge table edge = edgebuf; i1 = vtcs; - i2 = vtcs + (length-1) * 2; - for (c=0; cnext)) { - x1=edge->x>>POLYGON_FIX_SHIFT; - x2=(edge->next->x+edge->next->w)>>POLYGON_FIX_SHIFT; - y=c; + x1 = edge->x >> POLYGON_FIX_SHIFT; + x2 = (edge->next->x + edge->next->w) >> POLYGON_FIX_SHIFT; + y = c; // Fix coordinates - if (x1>x2) std::swap(x1,x2); + if (x1 > x2) std::swap(x1, x2); // Set line - if (fnCallback) + if (callback) { - for (int xcnt=x2-x1-1; xcnt>=0; xcnt--) + for (int xcnt = x2 - x1 - 1; xcnt >= 0; xcnt--) { - uint8_t pix = GetPix(x1+xcnt, y); + uint8_t pix = d->GetPix(x1 + xcnt, y); if (!conversion_table || conversion_table[pix]) { - int32_t mat = GetPixMat(pix); - if((this->*fnCallback)(x1+xcnt,y)) - if(mats_count) + int32_t mat = d->GetPixMat(pix); + if (callback(x1 + xcnt, y)) + if (mats_count) { - mats_count->Add(mat,1); + mats_count->Add(mat, 1); amount++; } } } } else if (conversion_table) - for (int xcnt=x2-x1-1; xcnt>=0; xcnt--) + for (int xcnt = x2 - x1 - 1; xcnt >= 0; xcnt--) { - const uint8_t pix = conversion_table[uint8_t(GetPix(x1+xcnt, y))]; - Surface8->SetPix(x1+xcnt, y, pix); - if (colBkg != Transparent) Surface8Bkg->SetPix(x1+xcnt, y, colBkg); + const uint8_t pix = conversion_table[uint8_t(d->GetPix(x1 + xcnt, y))]; + Surface8->SetPix(x1 + xcnt, y, pix); + if (colBkg != Transparent) Surface8Bkg->SetPix(x1 + xcnt, y, colBkg); } else - for (int xcnt=x2-x1-1; xcnt>=0; xcnt--) + for (int xcnt = x2 - x1 - 1; xcnt >= 0; xcnt--) { - if (col != Transparent) Surface8->SetPix(x1+xcnt, y, col); - if (colBkg != Transparent) Surface8Bkg->SetPix(x1+xcnt, y, colBkg); + if (col != Transparent) Surface8->SetPix(x1 + xcnt, y, col); + if (colBkg != Transparent) Surface8Bkg->SetPix(x1 + xcnt, y, colBkg); } edge = edge->next->next; } @@ -1232,7 +1325,7 @@ int32_t C4Landscape::ForPolygon(int *vtcs, int length, bool (C4Landscape::*fnCal else { edge->x += edge->dx; - while ((edge->prev) && (edge->x+edge->w/2 < edge->prev->x+edge->prev->w/2)) + while ((edge->prev) && (edge->x + edge->w / 2 < edge->prev->x + edge->prev->w / 2)) { if (edge->next) edge->next->prev = edge->prev; edge->prev->next = edge->next; @@ -1248,7 +1341,7 @@ int32_t C4Landscape::ForPolygon(int *vtcs, int length, bool (C4Landscape::*fnCal } // Clear scratch memory - if (!use_qpb) delete [] edgebuf; + if (!use_qpb) delete[] edgebuf; return amount; } @@ -1260,96 +1353,95 @@ int32_t C4Landscape::ForPolygon(int *vtcs, int length, bool (C4Landscape::*fnCal void C4Landscape::ScenarioInit() { // Gravity - Gravity = C4REAL100(Game.C4S.Landscape.Gravity.Evaluate()) * DefaultGravAccel; + p->Gravity = C4REAL100(Game.C4S.Landscape.Gravity.Evaluate()) * DefaultGravAccel; // Opens - LeftOpen=Game.C4S.Landscape.LeftOpen; - RightOpen=Game.C4S.Landscape.RightOpen; - TopOpen=Game.C4S.Landscape.TopOpen; - BottomOpen=Game.C4S.Landscape.BottomOpen; + p->LeftOpen = Game.C4S.Landscape.LeftOpen; + p->RightOpen = Game.C4S.Landscape.RightOpen; + p->TopOpen = Game.C4S.Landscape.TopOpen; + p->BottomOpen = Game.C4S.Landscape.BottomOpen; // Side open scan if (Game.C4S.Landscape.AutoScanSideOpen) ScanSideOpen(); } void C4Landscape::Clear(bool fClearMapCreator, bool fClearSky, bool fClearRenderer) { - if (pMapCreator && fClearMapCreator) { delete pMapCreator; pMapCreator=NULL; } + if (fClearMapCreator) { p->pMapCreator.reset(); } // clear sky - if (fClearSky) Sky.Clear(); + if (fClearSky) p->Sky.Clear(); // clear surfaces, if assigned - if (fClearRenderer) { delete pLandscapeRender; pLandscapeRender=NULL; } - delete [] TopRowPix; TopRowPix=NULL; - delete [] BottomRowPix; BottomRowPix=NULL; - delete Surface8; Surface8=NULL; - delete Surface8Bkg; Surface8Bkg=NULL; - delete Map; Map=NULL; - delete MapBkg; MapBkg=NULL; + if (fClearRenderer) { p->pLandscapeRender.reset(); } + p->TopRowPix.clear(); + p->BottomRowPix.clear(); + p->Surface8.reset(); + p->Surface8Bkg.reset(); + p->Map.reset(); + p->MapBkg.reset(); // clear initial landscape - delete [] pInitial; pInitial = NULL; - delete [] pInitialBkg; pInitialBkg = NULL; - delete pFoW; pFoW = NULL; + p->pInitial.reset(); + p->pInitialBkg.reset(); + p->pFoW.reset(); // clear relight array - for (int32_t i = 0; i < C4LS_MaxRelights; ++i) - Relights[i].Default(); + for (auto &relight : p->Relights) + relight.Default(); // clear scan - ScanX=0; - Mode=C4LSC_Undefined; + p->ScanX = 0; + p->mode = LandscapeMode::Undefined; // clear pixel count - delete [] PixCnt; PixCnt = NULL; - PixCntPitch = 0; + p->PixCnt.clear(); + p->PixCntPitch = 0; // clear bridge material conversion temp buffers - for (int32_t i = 0; i < C4M_MaxTexIndex; ++i) - { - delete [] BridgeMatConversion[i]; - BridgeMatConversion[i] = NULL; - } + for (auto &conv : p->BridgeMatConversion) + conv.reset(); } void C4Landscape::CompileFunc(StdCompiler *pComp) { - pComp->Value(mkNamingAdapt(MapSeed, "MapSeed", 0)); - pComp->Value(mkNamingAdapt(LeftOpen, "LeftOpen", 0)); - pComp->Value(mkNamingAdapt(RightOpen, "RightOpen", 0)); - pComp->Value(mkNamingAdapt(TopOpen, "TopOpen", 0)); - pComp->Value(mkNamingAdapt(BottomOpen, "BottomOpen", 0)); - pComp->Value(mkNamingAdapt(mkCastIntAdapt(Gravity), "Gravity", DefaultGravAccel)); - pComp->Value(mkNamingAdapt(Modulation, "MatModulation", 0U)); - pComp->Value(mkNamingAdapt(Mode, "Mode", C4LSC_Undefined)); + pComp->Value(mkNamingAdapt(p->MapSeed, "MapSeed", 0)); + pComp->Value(mkNamingAdapt(p->LeftOpen, "LeftOpen", 0)); + pComp->Value(mkNamingAdapt(p->RightOpen, "RightOpen", 0)); + pComp->Value(mkNamingAdapt(p->TopOpen, "TopOpen", 0)); + pComp->Value(mkNamingAdapt(p->BottomOpen, "BottomOpen", 0)); + pComp->Value(mkNamingAdapt(mkCastIntAdapt(p->Gravity), "Gravity", DefaultGravAccel)); + pComp->Value(mkNamingAdapt(p->Modulation, "MatModulation", 0U)); + pComp->Value(mkNamingAdapt(mkCastIntAdapt(p->mode), "Mode", LandscapeMode::Undefined)); - if(pComp->isCompiler()) + if (pComp->isCompiler()) { int32_t ambient_brightness; - pComp->Value(mkNamingAdapt(ambient_brightness, "AmbientBrightness", 255)); - if(pFoW) pFoW->Ambient.SetBrightness(ambient_brightness / static_cast(255)); + pComp->Value(mkNamingAdapt(ambient_brightness, "AmbientBrightness", 255)); + if (p->pFoW) p->pFoW->Ambient.SetBrightness(ambient_brightness / static_cast(255)); } else { - if(pFoW) + if (p->pFoW) { - int32_t ambient_brightness = static_cast(pFoW->Ambient.GetBrightness() * 255 + 0.5); - pComp->Value(mkNamingAdapt(ambient_brightness, "AmbientBrightness", 255)); + int32_t ambient_brightness = static_cast(p->pFoW->Ambient.GetBrightness() * 255 + 0.5); + pComp->Value(mkNamingAdapt(ambient_brightness, "AmbientBrightness", 255)); } } } -static CSurface8 *GroupReadSurface8(C4Group &hGroup, const char *szWildCard) +static std::unique_ptr GroupReadSurface8(C4Group &hGroup, const char *szWildCard) { if (!hGroup.AccessEntry(szWildCard)) return NULL; // create surface - CSurface8 *pSfc=new CSurface8(); + auto pSfc = std::make_unique(); if (!pSfc->Read(hGroup)) - { delete pSfc; return NULL; } + { + return NULL; + } return pSfc; } bool C4Landscape::Init(C4Group &hGroup, bool fOverloadCurrent, bool fLoadSky, bool &rfLoaded, bool fSavegame) { // set map seed, if not pre-assigned - if (!MapSeed) MapSeed=Random(3133700); + if (!p->MapSeed) p->MapSeed = Random(3133700); // increase max map size, since developers might set a greater one here - Game.C4S.Landscape.MapWdt.Max=10000; - Game.C4S.Landscape.MapHgt.Max=10000; + Game.C4S.Landscape.MapWdt.Max = 10000; + Game.C4S.Landscape.MapHgt.Max = 10000; // map and landscape must be initialized with fixed random, so runtime joining clients may recreate it // with same seed @@ -1362,10 +1454,10 @@ bool C4Landscape::Init(C4Group &hGroup, bool fOverloadCurrent, bool fLoadSky, bo // map is like it's loaded for regular gamestart // but it's changed and would have to be saved if a new section is loaded - fMapChanged = fOverloadCurrent; + p->fMapChanged = fOverloadCurrent; // don't change landscape mode in runtime joins - bool fLandscapeModeSet = (Mode != C4LSC_Undefined); + bool fLandscapeModeSet = (p->mode != LandscapeMode::Undefined); // Make pixel maps // Pixel maps only depend on loaded materials and textures @@ -1376,52 +1468,64 @@ bool C4Landscape::Init(C4Group &hGroup, bool fOverloadCurrent, bool fLoadSky, bo // create map if necessary if (!Game.C4S.Landscape.ExactLandscape) { - CSurface8 * sfcMap=NULL; - CSurface8 * sfcMapBkg=NULL; + std::unique_ptr sfcMap, sfcMapBkg; // Static map from scenario: Old-style Map.bmp with highest bit IFT - if ((sfcMap=GroupReadSurface8(hGroup, C4CFN_Map))) + if ((sfcMap = GroupReadSurface8(hGroup, C4CFN_Map))) { - if (!fLandscapeModeSet) Mode=C4LSC_Static; - sfcMapBkg = CreateDefaultBkgSurface(*sfcMap, true); + if (!fLandscapeModeSet) p->mode = LandscapeMode::Static; + sfcMapBkg = p->CreateDefaultBkgSurface(*sfcMap, true); if (!sfcMapBkg) return false; } - // Static map from scenaruo: New-style MapFg.bmp and MapBg.bmp with + // Static map from scenario: New-style MapFg.bmp and MapBg.bmp with // full 255 mat-tex combinations. Background map is optional, if not // given default will be created with tunnel background for all // semisolid pixels. if (!sfcMap) { - if ((sfcMap=GroupReadSurface8(hGroup, C4CFN_MapFg))) + if ((sfcMap = GroupReadSurface8(hGroup, C4CFN_MapFg))) { - if (!fLandscapeModeSet) Mode=C4LSC_Static; + if (!fLandscapeModeSet) p->mode = LandscapeMode::Static; sfcMapBkg = GroupReadSurface8(hGroup, C4CFN_MapBg); - if (!sfcMapBkg) sfcMapBkg = CreateDefaultBkgSurface(*sfcMap, false); + if (!sfcMapBkg) sfcMapBkg = p->CreateDefaultBkgSurface(*sfcMap, false); if (!sfcMapBkg) return false; } } // dynamic map from Landscape.txt + CSurface8 *rendered_map = nullptr, *rendered_bkg = nullptr; if (!sfcMap) - if (CreateMapS2(hGroup, sfcMap, sfcMapBkg)) - if (!fLandscapeModeSet) Mode=C4LSC_Dynamic; + { + if (p->CreateMapS2(hGroup, rendered_map, rendered_bkg)) + { + sfcMap.reset(rendered_map); + sfcMapBkg.reset(rendered_bkg); + if (!fLandscapeModeSet) p->mode = LandscapeMode::Dynamic; + } + } // script may create or edit map - if (MapScript.InitializeMap(&Game.C4S.Landscape, &::TextureMap, &::MaterialMap, Game.StartupPlayerCount, &sfcMap, &sfcMapBkg)) - if (!fLandscapeModeSet) Mode=C4LSC_Dynamic; + if (MapScript.InitializeMap(&Game.C4S.Landscape, &::TextureMap, &::MaterialMap, Game.StartupPlayerCount, &rendered_map, &rendered_bkg)) + if (!fLandscapeModeSet) p->mode = LandscapeMode::Dynamic; // Dynamic map by scenario if (!sfcMap && !fOverloadCurrent) - if (CreateMap(sfcMap, sfcMapBkg)) - if (!fLandscapeModeSet) Mode=C4LSC_Dynamic; + { + if (p->CreateMap(rendered_map, rendered_bkg)) + { + sfcMap.reset(rendered_map); + sfcMapBkg.reset(rendered_bkg); + if (!fLandscapeModeSet) p->mode = LandscapeMode::Dynamic; + } + } // No map failure if (!sfcMap) { // no problem if only overloading if (!fOverloadCurrent) return false; - if (fLoadSky) if (!Sky.Init(fSavegame)) return false; + if (fLoadSky) if (!p->Sky.Init(fSavegame)) return false; return true; } @@ -1435,32 +1539,31 @@ bool C4Landscape::Init(C4Group &hGroup, bool fOverloadCurrent, bool fLoadSky, bo // Store map size and calculate map zoom int iWdt, iHgt; - sfcMap->GetSurfaceSize(iWdt,iHgt); - MapWidth = iWdt; MapHeight = iHgt; - MapZoom = Game.C4S.Landscape.MapZoom.Evaluate(); + sfcMap->GetSurfaceSize(iWdt, iHgt); + p->MapWidth = iWdt; p->MapHeight = iHgt; + p->MapZoom = Game.C4S.Landscape.MapZoom.Evaluate(); // Calculate landscape size - Width = MapZoom * MapWidth; - Height = MapZoom * MapHeight; - Width = std::max(Width,100); - Height = std::max(Height,100); -// Width = (Width/8)*8; + p->Width = p->MapZoom * p->MapWidth; + p->Height = p->MapZoom * p->MapHeight; + p->Width = std::max(p->Width, 100); + p->Height = std::max(p->Height, 100); // if overloading, clear current landscape (and sections, etc.) // must clear, of course, before new sky is eventually read if (fOverloadCurrent) Clear(!Game.C4S.Landscape.KeepMapCreator, fLoadSky, false); // assign new map - assert(Map == NULL); - assert(MapBkg == NULL); - Map = sfcMap; - MapBkg = sfcMapBkg; + assert(p->Map == NULL); + assert(p->MapBkg == NULL); + p->Map = std::move(sfcMap); + p->MapBkg = std::move(sfcMapBkg); // Sky (might need to know landscape height) if (fLoadSky) { Game.SetInitProgress(70); - if (!Sky.Init(fSavegame)) return false; + if (!p->Sky.Init(fSavegame)) return false; } } @@ -1471,8 +1574,8 @@ bool C4Landscape::Init(C4Group &hGroup, bool fOverloadCurrent, bool fLoadSky, bo // if overloading, clear current if (fOverloadCurrent) Clear(!Game.C4S.Landscape.KeepMapCreator, fLoadSky, false); // load it - if (!fLandscapeModeSet) Mode=C4LSC_Exact; - rfLoaded=true; + if (!fLandscapeModeSet) p->mode = LandscapeMode::Exact; + rfLoaded = true; if (!Load(hGroup, fLoadSky, fSavegame)) return false; } @@ -1480,86 +1583,82 @@ bool C4Landscape::Init(C4Group &hGroup, bool fOverloadCurrent, bool fLoadSky, bo Game.SetInitProgress(75); // copy noscan-var - NoScan=Game.C4S.Landscape.NoScan!=0; + p->NoScan = Game.C4S.Landscape.NoScan != 0; // Scan settings - ScanSpeed=Clamp(Width/500,2,15); + p->ScanSpeed = Clamp(GetWidth() / 500, 2, 15); // Create pixel count array before any SetPix operations may take place // Proper pixel counts will be done later, but needs to have the arrays redy to avoid dead pointer access. // We will use 15x17 blocks so the pixel count can't get over 255. - int32_t PixCntWidth = (Width + 16) / 17; - PixCntPitch = (Height + 14) / 15; - PixCnt = new uint8_t[PixCntWidth * PixCntPitch]; + int32_t PixCntWidth = (GetWidth() + 16) / 17; + p->PixCntPitch = (GetHeight() + 14) / 15; + p->PixCnt.resize(PixCntWidth * p->PixCntPitch); // map to big surface and sectionize it // (not for shaders though - they require continous textures) if (!Game.C4S.Landscape.ExactLandscape) { - assert(Surface8 == NULL); - assert(Surface8Bkg == NULL); + assert(p->Surface8 == NULL); + assert(p->Surface8Bkg == NULL); - // Create landscape surface - Surface8 = new CSurface8(); - if (!Surface8->Create(Width, Height)) + // Create landscape surfaces { - delete Surface8; Surface8 = NULL; - return false; - } - - Surface8Bkg = new CSurface8(); - if (!Surface8Bkg->Create(Width, Height) || !Mat2Pal()) - { - delete Surface8Bkg; Surface8Bkg = NULL; - delete Surface8; Surface8 = NULL; - return false; + auto sf8 = std::make_unique(); + auto sfb8 = std::make_unique(); + if (!sf8->Create(GetWidth(), GetHeight()) || !sfb8->Create(GetWidth(), GetHeight())) + return false; + p->Surface8 = std::move(sf8); + p->Surface8Bkg = std::move(sfb8); + if (!p->Mat2Pal()) + return false; } // Map to landscape // Landscape render disabled during initial landscape zoom (will be updated later) - C4LandscapeRender *lsrender_backup = pLandscapeRender; - pLandscapeRender = NULL; + std::unique_ptr lsrender_backup; + lsrender_backup.swap(p->pLandscapeRender); bool map2landscape_success = MapToLandscape(); - pLandscapeRender = lsrender_backup; + lsrender_backup.swap(p->pLandscapeRender); if (!map2landscape_success) return false; } // Init out-of-landscape pixels for bottom - InitTopAndBottomRowPix(); + p->InitTopAndBottomRowPix(); Game.SetInitProgress(80); if (Config.General.DebugRec) { AddDbgRec(RCT_Block, "|---LANDSCAPE---|", 18); - AddDbgRec(RCT_Map, Surface8->Bits, Surface8->Pitch*Surface8->Hgt); + AddDbgRec(RCT_Map, p->Surface8->Bits, p->Surface8->Pitch * p->Surface8->Hgt); AddDbgRec(RCT_Block, "|---LANDSCAPE BKG---|", 22); - AddDbgRec(RCT_Map, Surface8Bkg->Bits, Surface8Bkg->Pitch*Surface8Bkg->Hgt); + AddDbgRec(RCT_Map, p->Surface8Bkg->Bits, p->Surface8Bkg->Pitch * p->Surface8Bkg->Hgt); } // Create FoW - assert(pFoW == NULL); + assert(p->pFoW == NULL); if (Game.C4S.Game.FoWEnabled) - pFoW = new C4FoW(); + p->pFoW.reset(new C4FoW); // Create renderer #ifndef USE_CONSOLE - if (!pLandscapeRender) - pLandscapeRender = new C4LandscapeRenderGL(); + if (!p->pLandscapeRender) + p->pLandscapeRender.reset(new C4LandscapeRenderGL); #endif - if(pLandscapeRender) + if (p->pLandscapeRender) { // Initialize renderer if (fOverloadCurrent) { - if(!pLandscapeRender->ReInit(Width, Height)) + if (!p->pLandscapeRender->ReInit(GetWidth(), GetHeight())) return false; } else { - if(!pLandscapeRender->Init(Width, Height, &::TextureMap, &::GraphicsResource.Files)) + if (!p->pLandscapeRender->Init(GetWidth(), GetHeight(), &::TextureMap, &::GraphicsResource.Files)) return false; } } @@ -1572,12 +1671,12 @@ bool C4Landscape::Init(C4Group &hGroup, bool fOverloadCurrent, bool fLoadSky, bo ApplyDiff(hGroup); // Pixel count tracking from landscape zoom is incomplete, so recalculate it. - UpdatePixCnt(C4Rect(0, 0, Width, Height)); - ClearMatCount(); - UpdateMatCnt(C4Rect(0, 0, Width, Height), true); + p->UpdatePixCnt(this, C4Rect(0, 0, GetWidth(), GetHeight())); + p->ClearMatCount(); + p->UpdateMatCnt(this, C4Rect(0, 0, GetWidth(), GetHeight()), true); // Create initial landscape render data (after applying diff so landscape is complete) - if (pLandscapeRender) pLandscapeRender->Update(C4Rect(0, 0, Width, Height), this); + if (p->pLandscapeRender) p->pLandscapeRender->Update(C4Rect(0, 0, GetWidth(), GetHeight()), this); Game.SetInitProgress(87); // after map/landscape creation, the seed must be fixed again, so there's no difference between clients creating @@ -1585,33 +1684,38 @@ bool C4Landscape::Init(C4Group &hGroup, bool fOverloadCurrent, bool fLoadSky, bo Game.FixRandom(Game.RandomSeed); // Create ambient light map after landscape creation - if (pFoW) pFoW->Ambient.CreateFromLandscape(*this, 10., 50., 0.25); + if (p->pFoW) p->pFoW->Ambient.CreateFromLandscape(*this, 10., 50., 0.25); Game.SetInitProgress(84); // Success - rfLoaded=true; + rfLoaded = true; return true; } +bool C4Landscape::HasMap() const +{ + return p->Map != NULL && p->MapBkg != NULL; +} + bool C4Landscape::Save(C4Group &hGroup) const { C4SolidMask::RemoveSolidMasks(); - bool r = SaveInternal(hGroup); + bool r = p->SaveInternal(this, hGroup); C4SolidMask::PutSolidMasks(); return r; } -bool C4Landscape::SaveInternal(C4Group &hGroup) const +bool C4Landscape::P::SaveInternal(const C4Landscape *d, C4Group &hGroup) const { // Save landscape surface - char szTempLandscape[_MAX_PATH+1]; + char szTempLandscape[_MAX_PATH + 1]; SCopy(Config.AtTempPath(C4CFN_TempLandscape), szTempLandscape); MakeTempFilename(szTempLandscape); if (!Surface8->Save(szTempLandscape)) return false; // Move temp file to group - if (!hGroup.Move( szTempLandscape, C4CFN_LandscapeFg )) + if (!hGroup.Move(szTempLandscape, C4CFN_LandscapeFg)) return false; // Same for background surface @@ -1624,11 +1728,11 @@ bool C4Landscape::SaveInternal(C4Group &hGroup) const // Save map if (fMapChanged && Map) - if (!SaveMap(hGroup)) + if (!d->SaveMap(hGroup)) return false; // save textures (if changed) - if (!SaveTextures(hGroup)) + if (!d->SaveTextures(hGroup)) return false; return true; @@ -1637,12 +1741,12 @@ bool C4Landscape::SaveInternal(C4Group &hGroup) const bool C4Landscape::SaveDiff(C4Group &hGroup, bool fSyncSave) const { C4SolidMask::RemoveSolidMasks(); - bool r = SaveDiffInternal(hGroup, fSyncSave); + bool r = p->SaveDiffInternal(this, hGroup, fSyncSave); C4SolidMask::PutSolidMasks(); return r; } -bool C4Landscape::SaveDiffInternal(C4Group &hGroup, bool fSyncSave) const +bool C4Landscape::P::SaveDiffInternal(const C4Landscape *d, C4Group &hGroup, bool fSyncSave) const { assert(pInitial && pInitialBkg); if (!pInitial || !pInitialBkg) return false; @@ -1655,12 +1759,12 @@ bool C4Landscape::SaveDiffInternal(C4Group &hGroup, bool fSyncSave) const for (int x = 0; x < Width; x++) { if (pInitial[y * Width + x] == Surface8->_GetPix(x, y)) - Surface8->SetPix(x,y,C4M_MaxTexIndex); + Surface8->SetPix(x, y, C4M_MaxTexIndex); else fChanged = true; if (pInitialBkg[y * Width + x] == Surface8Bkg->_GetPix(x, y)) - Surface8Bkg->SetPix(x,y,C4M_MaxTexIndex); + Surface8Bkg->SetPix(x, y, C4M_MaxTexIndex); else fChangedBkg = true; } @@ -1672,8 +1776,8 @@ bool C4Landscape::SaveDiffInternal(C4Group &hGroup, bool fSyncSave) const return false; // Move temp file to group - if (!hGroup.Move( Config.AtTempPath(C4CFN_TempLandscape), - C4CFN_DiffLandscape )) + if (!hGroup.Move(Config.AtTempPath(C4CFN_TempLandscape), + C4CFN_DiffLandscape)) return false; } @@ -1684,8 +1788,8 @@ bool C4Landscape::SaveDiffInternal(C4Group &hGroup, bool fSyncSave) const return false; // Move temp file to group - if (!hGroup.Move( Config.AtTempPath(C4CFN_TempLandscapeBkg), - C4CFN_DiffLandscapeBkg )) + if (!hGroup.Move(Config.AtTempPath(C4CFN_TempLandscapeBkg), + C4CFN_DiffLandscapeBkg)) return false; } @@ -1695,17 +1799,17 @@ bool C4Landscape::SaveDiffInternal(C4Group &hGroup, bool fSyncSave) const for (int x = 0; x < Width; x++) { if (Surface8->_GetPix(x, y) == C4M_MaxTexIndex) - Surface8->SetPix(x,y,pInitial[y * Width + x]); + Surface8->SetPix(x, y, pInitial[y * Width + x]); if (Surface8Bkg->_GetPix(x, y) == C4M_MaxTexIndex) - Surface8Bkg->SetPix(x,y,pInitialBkg[y * Width + x]); + Surface8Bkg->SetPix(x, y, pInitialBkg[y * Width + x]); } // Save changed map, too if (fMapChanged && Map) - if (!SaveMap(hGroup)) return false; + if (!d->SaveMap(hGroup)) return false; // and textures (if changed) - if (!SaveTextures(hGroup)) return false; + if (!d->SaveTextures(hGroup)) return false; return true; } @@ -1714,37 +1818,38 @@ bool C4Landscape::SaveInitial() { // Create array - delete [] pInitial; - delete [] pInitialBkg; - pInitial = new BYTE [Width * Height]; - pInitialBkg = new BYTE [Width * Height]; + p->pInitial = std::make_unique(GetWidth() * GetHeight()); + p->pInitialBkg = std::make_unique(GetWidth() * GetHeight()); // Save material data - for (int y = 0; y < Height; y++) - for (int x = 0; x < Width; x++) + for (int y = 0; y < GetHeight(); y++) + { + const int pitch = y * GetWidth(); + for (int x = 0; x < GetWidth(); x++) { - pInitial[y * Width + x] = Surface8->_GetPix(x, y); - pInitialBkg[y * Width + x] = Surface8Bkg->_GetPix(x, y); + p->pInitial[pitch + x] = p->Surface8->_GetPix(x, y); + p->pInitialBkg[pitch + x] = p->Surface8Bkg->_GetPix(x, y); } + } return true; } bool C4Landscape::Load(C4Group &hGroup, bool fLoadSky, bool fSavegame) { - assert(!Surface8 && !Surface8Bkg); + assert(!p->Surface8 && !p->Surface8Bkg); // Load exact landscape from group - if (!(Surface8=GroupReadSurface8(hGroup, C4CFN_Landscape))) + if ((p->Surface8 = GroupReadSurface8(hGroup, C4CFN_Landscape)) == nullptr) { - if (!(Surface8=GroupReadSurface8(hGroup, C4CFN_LandscapeFg))) return false; - Surface8Bkg = GroupReadSurface8(hGroup, C4CFN_LandscapeBg); + if ((p->Surface8 = GroupReadSurface8(hGroup, C4CFN_LandscapeFg)) == nullptr) return false; + p->Surface8Bkg = GroupReadSurface8(hGroup, C4CFN_LandscapeBg); - if (Surface8Bkg) + if (p->Surface8Bkg) { - if ( (Surface8->Wdt != Surface8Bkg->Wdt || Surface8->Hgt != Surface8Bkg->Hgt)) + if (p->Surface8->Wdt != p->Surface8Bkg->Wdt || p->Surface8->Hgt != p->Surface8Bkg->Hgt) { - LogFatal(FormatString("Landscape has different dimensions than background landscape (%dx%d vs. %dx%d)", Surface8->Wdt, Surface8->Hgt, Surface8Bkg->Wdt, Surface8Bkg->Hgt).getData()); + LogFatal(FormatString("Landscape has different dimensions than background landscape (%dx%d vs. %dx%d)", p->Surface8->Wdt, p->Surface8->Hgt, p->Surface8Bkg->Wdt, p->Surface8Bkg->Hgt).getData()); return false; } } @@ -1752,41 +1857,41 @@ bool C4Landscape::Load(C4Group &hGroup, bool fLoadSky, bool fSavegame) { // LandscapeFg.bmp loaded: Assume full 8bit mat-tex values // when creating background surface. - Surface8Bkg = CreateDefaultBkgSurface(*Surface8, false); + p->Surface8Bkg = p->CreateDefaultBkgSurface(*p->Surface8, false); } } else { // Landscape.bmp loaded: Assume msb is IFT flag when creating // background surface. - Surface8Bkg = CreateDefaultBkgSurface(*Surface8, true); + p->Surface8Bkg = p->CreateDefaultBkgSurface(*p->Surface8, true); } int iWidth, iHeight; - Surface8->GetSurfaceSize(iWidth,iHeight); - Width = iWidth; Height = iHeight; + p->Surface8->GetSurfaceSize(iWidth, iHeight); + p->Width = iWidth; p->Height = iHeight; // adjust pal - if (!Mat2Pal()) return false; + if (!p->Mat2Pal()) return false; // Landscape should be in correct format: Make sure it is! - for (int32_t y=0; y_GetPix(x, y); + BYTE byPix = p->Surface8->_GetPix(x, y); int32_t iMat = PixCol2Mat(byPix); if (byPix && !MatValid(iMat)) { - LogFatal(FormatString("Landscape loading error at (%d/%d): Pixel value %d not a valid material!", (int) x, (int) y, (int) byPix).getData()); + LogFatal(FormatString("Landscape loading error at (%d/%d): Pixel value %d not a valid material!", (int)x, (int)y, (int)byPix).getData()); return false; } - BYTE byPixBkg = Surface8Bkg->_GetPix(x, y); + BYTE byPixBkg = p->Surface8Bkg->_GetPix(x, y); int32_t iMatBkg = PixCol2Mat(byPixBkg); if (byPixBkg && !MatValid(iMatBkg)) { - LogFatal(FormatString("Background Landscape loading error at (%d/%d): Pixel value %d not a valid material!", (int) x, (int) y, (int) byPixBkg).getData()); + LogFatal(FormatString("Background Landscape loading error at (%d/%d): Pixel value %d not a valid material!", (int)x, (int)y, (int)byPixBkg).getData()); return false; } } @@ -1795,78 +1900,49 @@ bool C4Landscape::Load(C4Group &hGroup, bool fLoadSky, bool fSavegame) if (fLoadSky) { Game.SetInitProgress(70); - if (!Sky.Init(fSavegame)) return false; + if (p->Sky.Init(fSavegame)) return false; } // Success return true; } bool C4Landscape::ApplyDiff(C4Group &hGroup) { - CSurface8 *pDiff; - CSurface8 *pDiffBkg; + std::unique_ptr pDiff, pDiffBkg; // Load diff landscape from group - if (!(pDiff=GroupReadSurface8(hGroup, C4CFN_DiffLandscape))) return false; - if (!(pDiffBkg=GroupReadSurface8(hGroup, C4CFN_DiffLandscapeBkg))) { delete pDiff; return false; } + if ((pDiff = GroupReadSurface8(hGroup, C4CFN_DiffLandscape)) == nullptr) return false; + if ((pDiffBkg = GroupReadSurface8(hGroup, C4CFN_DiffLandscapeBkg)) == nullptr) return false; // convert all pixels: keep if same material; re-set if different material BYTE byPix; - for (int32_t y=0; yGetPix(x, y) != C4M_MaxTexIndex) - if (Surface8->_GetPix(x,y) != (byPix=pDiff->_GetPix(x,y))) + if (p->Surface8->_GetPix(x, y) != (byPix = pDiff->_GetPix(x, y))) // material has changed here: readjust with new texture - Surface8->SetPix(x,y, byPix); + p->Surface8->SetPix(x, y, byPix); if (pDiffBkg->GetPix(x, y) != C4M_MaxTexIndex) - if (Surface8Bkg->_GetPix(x, y) != (byPix=pDiffBkg->_GetPix(x, y))) - Surface8Bkg->_SetPix(x, y, byPix); + if (p->Surface8Bkg->_GetPix(x, y) != (byPix = pDiffBkg->_GetPix(x, y))) + p->Surface8Bkg->_SetPix(x, y, byPix); } - // done; clear diff - delete pDiff; - delete pDiffBkg; + // done return true; } void C4Landscape::Default() { - Mode=C4LSC_Undefined; - Surface8=NULL; - Surface8Bkg=NULL; - pInitial=NULL; - pInitialBkg=NULL; - TopRowPix=NULL; - BottomRowPix=NULL; - pLandscapeRender=NULL; - Map=NULL; - MapBkg=NULL; - Width=Height=0; - MapWidth=MapHeight=MapZoom=0; - ClearMatCount(); - ScanX=0; - ScanSpeed=2; - LeftOpen=RightOpen=TopOpen=BottomOpen=0; - Gravity=DefaultGravAccel; - MapSeed=0; NoScan=false; - pMapCreator=NULL; - Modulation=0; - fMapChanged = false; - for (int32_t i = 0; i < C4M_MaxTexIndex; ++i) - BridgeMatConversion[i] = NULL; - pFoW = NULL; + p = std::make_unique

(); } -void C4Landscape::ClearMatCount() +void C4Landscape::P::ClearMatCount() { - for (int32_t cnt=0; cntScanX = 0; } @@ -1884,31 +1960,31 @@ int32_t PixCol2Mat(BYTE pixc) bool C4Landscape::SaveMap(C4Group &hGroup) const { // No map - if (!Map) return false; - assert(MapBkg != NULL); + if (!p->Map) return false; + assert(p->MapBkg != NULL); // Create map palette CStdPalette Palette; - ::TextureMap.StoreMapPalette(&Palette,::MaterialMap); + ::TextureMap.StoreMapPalette(&Palette, ::MaterialMap); // Save map surface - if (!Map->Save(Config.AtTempPath(C4CFN_TempMapFg), &Palette)) + if (!p->Map->Save(Config.AtTempPath(C4CFN_TempMapFg), &Palette)) return false; // Move temp file to group if (!hGroup.Move(Config.AtTempPath(C4CFN_TempMapFg), - C4CFN_MapFg )) + C4CFN_MapFg)) return false; // Save background map surface - if (!MapBkg->Save(Config.AtTempPath(C4CFN_TempMapBg), &Palette)) + if (!p->MapBkg->Save(Config.AtTempPath(C4CFN_TempMapBg), &Palette)) return false; // Move temp file to group if (!hGroup.Move(Config.AtTempPath(C4CFN_TempMapBg), - C4CFN_MapBg )) + C4CFN_MapBg)) return false; - + // Success return true; } @@ -1919,7 +1995,7 @@ bool C4Landscape::SaveTextures(C4Group &hGroup) const if (::TextureMap.fEntriesAdded) { C4Group *pMatGroup = new C4Group(); - bool fSuccess=false; + bool fSuccess = false; // create local material group if (!hGroup.FindEntry(C4CFN_Material)) { @@ -1933,7 +2009,7 @@ bool C4Landscape::SaveTextures(C4Group &hGroup) const if (pMatGroup->Close()) // add it if (hGroup.Move(Config.AtTempPath(C4CFN_Material), C4CFN_Material)) - fSuccess=true; + fSuccess = true; // temp group must remain for scenario file closure // it will be deleted when the group is closed } @@ -1951,14 +2027,14 @@ bool C4Landscape::SaveTextures(C4Group &hGroup) const return true; } -bool C4Landscape::InitTopAndBottomRowPix() +bool C4Landscape::P::InitTopAndBottomRowPix() { + assert(Width > 0); // Init Top-/BottomRowPix array, which determines if out-of-landscape pixels on top/bottom side of the map are solid or not // In case of Top-/BottomOpen=2, unit by map and not landscape to avoid runtime join sync losses - delete [] TopRowPix; delete [] BottomRowPix; // safety if (!Width) return true; - TopRowPix = new uint8_t[Width]; - BottomRowPix = new uint8_t[Width]; + TopRowPix.clear(); + BottomRowPix.clear(); // must access Game.C4S here because Landscape.TopOpen / Landscape.BottomOpen may not be initialized yet // why is there a local copy of that static variable anyway? int32_t top_open_flag = Game.C4S.Landscape.TopOpen; @@ -1969,35 +2045,37 @@ bool C4Landscape::InitTopAndBottomRowPix() // Init TopRowPix switch (top_open_flag) { - // TopOpen=0: Top is closed - case 0: for (int32_t x=0; xGetPix(x/MapZoom,0); + uint8_t map_pix = MapBkg->GetPix(x / MapZoom, 0); TopRowPix[x] = ((map_pix != 0) ? MCVehic : 0); } break; - // TopOpen=1: Top is open - default: for (int32_t x=0; xGetPix(x/MapZoom,Map->Hgt-1); + uint8_t map_pix = MapBkg->GetPix(x / MapZoom, Map->Hgt - 1); BottomRowPix[x] = ((map_pix != 0) ? MCVehic : 0); } break; - // BottomOpen=1: Bottom is open - default: for (int32_t x=0; xMapToLandscape(this, *p->Map, *p->MapBkg, 0, 0, p->MapWidth, p->MapHeight); } -uint32_t C4Landscape::ChunkyRandom(uint32_t & iOffset, uint32_t iRange) const +uint32_t C4Landscape::P::ChunkyRandom(uint32_t & iOffset, uint32_t iRange) const { if (!iRange) return 0; iOffset = (iOffset * 16807) % 2147483647; return (iOffset ^ MapSeed) % iRange; } -void C4Landscape::DrawChunk(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, uint8_t mcol, uint8_t mcolBkg, C4MaterialCoreShape Shape, uint32_t cro) +void C4Landscape::P::DrawChunk(C4Landscape *d, int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, uint8_t mcol, uint8_t mcolBkg, C4MaterialCoreShape Shape, uint32_t cro) { unsigned int top_rough = 0, side_rough = 0, bottom_rough = 0; // what to do? @@ -2042,19 +2120,19 @@ void C4Landscape::DrawChunk(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, ui int vtcs[16]; unsigned int rx = std::max(wdt / 2, 1); - vtcs[0] = tx - ChunkyRandom(cro, rx * side_rough / 4); vtcs[1] = ty - ChunkyRandom(cro, rx * top_rough / 4); - vtcs[2] = tx - ChunkyRandom(cro, rx * side_rough / 2); vtcs[3] = ty + hgt / 2; - vtcs[4] = tx - ChunkyRandom(cro, rx * side_rough / 4); vtcs[5] = ty + hgt + ChunkyRandom(cro, rx * bottom_rough / 4); - vtcs[6] = tx + wdt / 2; vtcs[7] = ty + hgt + ChunkyRandom(cro, rx * bottom_rough / 2); - vtcs[8] = tx + wdt + ChunkyRandom(cro, rx * side_rough / 4); vtcs[9] = ty + hgt + ChunkyRandom(cro, rx * bottom_rough / 4); + vtcs[0] = tx - ChunkyRandom(cro, rx * side_rough / 4); vtcs[1] = ty - ChunkyRandom(cro, rx * top_rough / 4); + vtcs[2] = tx - ChunkyRandom(cro, rx * side_rough / 2); vtcs[3] = ty + hgt / 2; + vtcs[4] = tx - ChunkyRandom(cro, rx * side_rough / 4); vtcs[5] = ty + hgt + ChunkyRandom(cro, rx * bottom_rough / 4); + vtcs[6] = tx + wdt / 2; vtcs[7] = ty + hgt + ChunkyRandom(cro, rx * bottom_rough / 2); + vtcs[8] = tx + wdt + ChunkyRandom(cro, rx * side_rough / 4); vtcs[9] = ty + hgt + ChunkyRandom(cro, rx * bottom_rough / 4); vtcs[10] = tx + wdt + ChunkyRandom(cro, rx * side_rough / 2); vtcs[11] = ty + hgt / 2; vtcs[12] = tx + wdt + ChunkyRandom(cro, rx * side_rough / 4); vtcs[13] = ty - ChunkyRandom(cro, rx * top_rough / 4); vtcs[14] = tx + wdt / 2; vtcs[15] = ty - ChunkyRandom(cro, rx * top_rough / 2); - ForPolygon(vtcs, 8, NULL, NULL, mcol, mcolBkg); + ForPolygon(d, vtcs, 8, NULL, NULL, mcol, mcolBkg); } -void C4Landscape::DrawSmoothOChunk(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, uint8_t mcol, uint8_t mcolBkg, int flip, uint32_t cro) +void C4Landscape::P::DrawSmoothOChunk(C4Landscape *d, int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, uint8_t mcol, uint8_t mcolBkg, int flip, uint32_t cro) { int vtcs[8]; unsigned int rx = std::max(wdt / 2, 1); @@ -2076,10 +2154,10 @@ void C4Landscape::DrawSmoothOChunk(int32_t tx, int32_t ty, int32_t wdt, int32_t case 7: vtcs[6] = tx + wdt / 2; vtcs[7] += hgt / 2; break; } - ForPolygon(vtcs, 4, NULL, NULL, mcol, mcolBkg); + ForPolygon(d, vtcs, 4, NULL, NULL, mcol, mcolBkg); } -void C4Landscape::ChunkOZoom(CSurface8 * sfcMap, CSurface8 * sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, uint8_t iTexture, int32_t iOffX, int32_t iOffY) +void C4Landscape::P::ChunkOZoom(C4Landscape *d, const CSurface8 &sfcMap, const CSurface8 &sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, uint8_t iTexture, int32_t iOffX, int32_t iOffY) { const C4TexMapEntry *entry = ::TextureMap.GetEntry(iTexture); C4Material *pMaterial = entry->GetMaterial(); @@ -2091,7 +2169,7 @@ void C4Landscape::ChunkOZoom(CSurface8 * sfcMap, CSurface8 * sfcMapBkg, int32_t C4MaterialCoreShape iChunkType = ::Game.C4S.Landscape.FlatChunkShapes ? C4M_Flat : pMaterial->MapChunkType; // Get map & landscape size int iMapWidth, iMapHeight; - sfcMap->GetSurfaceSize(iMapWidth, iMapHeight); + sfcMap.GetSurfaceSize(iMapWidth, iMapHeight); // Clip desired map segment to map size iMapX = Clamp(iMapX, 0, iMapWidth - 1); iMapY = Clamp(iMapY, 0, iMapHeight - 1); @@ -2108,28 +2186,26 @@ void C4Landscape::ChunkOZoom(CSurface8 * sfcMap, CSurface8 * sfcMapBkg, int32_t for (int iX = iMapX; iX < iMapX + iMapWdt; iX++) { // Map scan line start - uint8_t MapPixel=sfcMap->_GetPix(iX, iY); - uint8_t MapPixelBkg=sfcMapBkg->_GetPix(iX, iY); + uint8_t MapPixel = sfcMap._GetPix(iX, iY); + uint8_t MapPixelBkg = sfcMapBkg._GetPix(iX, iY); // Landscape target coordinate horizontal int iToX = iX * iChunkWidth + iOffX; // Here's a chunk of the texture-material to zoom if (MapPixel == iTexture) { // Draw chunk - DrawChunk(iToX, iToY, iChunkWidth, iChunkHeight, MapPixel, MapPixelBkg, iChunkType, (iX<<16)+iY); + DrawChunk(d, iToX, iToY, iChunkWidth, iChunkHeight, MapPixel, MapPixelBkg, iChunkType, (iX << 16) + iY); } // Other chunk, check for slope smoothers else if (iChunkType == C4M_Smooth || iChunkType == C4M_Smoother || iChunkType == C4M_Octagon) { // Map scan line pixel below - uint8_t below = sfcMap->GetPix(iX, iY + 1); - uint8_t above = sfcMap->GetPix(iX, iY - 1); - uint8_t left = sfcMap->GetPix(iX - 1, iY); - uint8_t right = sfcMap->GetPix(iX + 1, iY); - /*uint8_t belowBkg = sfcMapBkg->GetPix(iX, iY + 1); - uint8_t aboveBkg = sfcMapBkg->GetPix(iX, iY - 1);*/ - uint8_t leftBkg = sfcMapBkg->GetPix(iX - 1, iY); - uint8_t rightBkg = sfcMapBkg->GetPix(iX + 1, iY); + uint8_t below = sfcMap.GetPix(iX, iY + 1); + uint8_t above = sfcMap.GetPix(iX, iY - 1); + uint8_t left = sfcMap.GetPix(iX - 1, iY); + uint8_t right = sfcMap.GetPix(iX + 1, iY); + uint8_t leftBkg = sfcMapBkg.GetPix(iX - 1, iY); + uint8_t rightBkg = sfcMapBkg.GetPix(iX + 1, iY); // do not fill a tiny hole if (below == iTexture && above == iTexture && left == iTexture && right == iTexture) continue; @@ -2141,13 +2217,13 @@ void C4Landscape::ChunkOZoom(CSurface8 * sfcMap, CSurface8 * sfcMapBkg, int32_t if (iX > 0 && left == iTexture) { // Draw smoother - DrawSmoothOChunk(iToX, iToY, iChunkWidth, iChunkHeight, left, leftBkg, 3 + flat, (iX<<16) + iY); + DrawSmoothOChunk(d, iToX, iToY, iChunkWidth, iChunkHeight, left, leftBkg, 3 + flat, (iX << 16) + iY); } // Same texture-material on right if (iX < iMapWidth - 1 && right == iTexture) { // Draw smoother - DrawSmoothOChunk(iToX, iToY, iChunkWidth, iChunkHeight, right, rightBkg, 0 + flat, (iX<<16)+iY); + DrawSmoothOChunk(d, iToX, iToY, iChunkWidth, iChunkHeight, right, rightBkg, 0 + flat, (iX << 16) + iY); } } // Smooth chunk & same texture-material above @@ -2157,13 +2233,13 @@ void C4Landscape::ChunkOZoom(CSurface8 * sfcMap, CSurface8 * sfcMapBkg, int32_t if (iX > 0 && left == iTexture) { // Draw smoother - DrawSmoothOChunk(iToX, iToY, iChunkWidth, iChunkHeight, left, leftBkg, 2 + flat, (iX<<16)+iY); + DrawSmoothOChunk(d, iToX, iToY, iChunkWidth, iChunkHeight, left, leftBkg, 2 + flat, (iX << 16) + iY); } // Same texture-material on right if (iX < iMapWidth - 1 && right == iTexture) { // Draw smoother - DrawSmoothOChunk(iToX, iToY, iChunkWidth, iChunkHeight, right, rightBkg, 1 + flat, (iX<<16)+iY); + DrawSmoothOChunk(d, iToX, iToY, iChunkWidth, iChunkHeight, right, rightBkg, 1 + flat, (iX << 16) + iY); } } } @@ -2173,29 +2249,29 @@ void C4Landscape::ChunkOZoom(CSurface8 * sfcMap, CSurface8 * sfcMapBkg, int32_t if (shape && !::Game.C4S.Landscape.FlatChunkShapes) shape->Draw(sfcMap, sfcMapBkg, iMapX, iMapY, iMapWdt, iMapHgt, iTexture, iOffX, iOffY, MapZoom, pMaterial->MinShapeOverlap); } -bool C4Landscape::GetTexUsage(CSurface8 * sfcMap, CSurface8 * sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, DWORD *dwpTextureUsage) const +static bool GetTexUsage(const CSurface8 &sfcMap, const CSurface8 &sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, DWORD *dwpTextureUsage) { - int iX,iY; + int iX, iY; // No good parameters - if (!sfcMap || !sfcMapBkg || !dwpTextureUsage) return false; + if (!dwpTextureUsage) return false; // Clip desired map segment to map size - iMapX=Clamp(iMapX,0,sfcMap->Wdt-1); iMapY=Clamp(iMapY,0,sfcMap->Hgt-1); - iMapWdt=Clamp(iMapWdt,0,sfcMap->Wdt-iMapX); iMapHgt=Clamp(iMapHgt,0,sfcMap->Hgt-iMapY); + iMapX = Clamp(iMapX, 0, sfcMap.Wdt - 1); iMapY = Clamp(iMapY, 0, sfcMap.Hgt - 1); + iMapWdt = Clamp(iMapWdt, 0, sfcMap.Wdt - iMapX); iMapHgt = Clamp(iMapHgt, 0, sfcMap.Hgt - iMapY); // Zero texture usage list - for (int32_t cnt=0; cntGetPix(iX, iY); + const int32_t tex = sfcMap.GetPix(iX, iY); assert(tex < C4M_MaxTexIndex); if (!dwpTextureUsage[tex]++) if (tex) { // Check if texture actually exists if (!::TextureMap.GetEntry(tex)->GetMaterial()) - LogF("Map2Landscape error: Texture index %d at (%d/%d) in map not defined in texture map!", (int) tex, (int) iX, (int) iY); + LogF("Map2Landscape error: Texture index %d at (%d/%d) in map not defined in texture map!", (int)tex, (int)iX, (int)iY); // No error. Landscape is usually fine but might contain some holes where material should be } @@ -2204,7 +2280,7 @@ bool C4Landscape::GetTexUsage(CSurface8 * sfcMap, CSurface8 * sfcMapBkg, int32_t /* // Count texture map index - const int32_t texBkg = sfcMapBkg->GetPix(iX, iY); + const int32_t texBkg = sfcMapBkg.GetPix(iX, iY); if (!dwpTextureUsage[texBkg]++) if (texBkg) { // Check if texture actually exists @@ -2213,24 +2289,21 @@ bool C4Landscape::GetTexUsage(CSurface8 * sfcMap, CSurface8 * sfcMapBkg, int32_t // No error. Landscape is usually fine but might contain some holes where material should be } */ - + } // Done return true; } -bool C4Landscape::TexOZoom(CSurface8 * sfcMap, CSurface8 * sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, DWORD *dwpTextureUsage, int32_t iToX, int32_t iToY) +bool C4Landscape::P::TexOZoom(C4Landscape *d, const CSurface8 &sfcMap, const CSurface8 &sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, DWORD *dwpTextureUsage, int32_t iToX, int32_t iToY) { - int32_t iIndex; - // ChunkOZoom all used textures - for (auto i = ::TextureMap.Order.begin(); i != ::TextureMap.Order.end(); ++i) + for (auto iIndex : ::TextureMap.Order) { - iIndex = *i; if (dwpTextureUsage[iIndex] > 0) { // ChunkOZoom map to landscape - ChunkOZoom(sfcMap, sfcMapBkg, iMapX, iMapY, iMapWdt, iMapHgt, iIndex, iToX, iToY); + ChunkOZoom(d, sfcMap, sfcMapBkg, iMapX, iMapY, iMapWdt, iMapHgt, iIndex, iToX, iToY); } } @@ -2238,25 +2311,25 @@ bool C4Landscape::TexOZoom(CSurface8 * sfcMap, CSurface8 * sfcMapBkg, int32_t iM return true; } -bool C4Landscape::MapToSurface(CSurface8 * sfcMap, CSurface8 * sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, int32_t iToX, int32_t iToY, int32_t iToWdt, int32_t iToHgt, int32_t iOffX, int32_t iOffY) +bool C4Landscape::P::MapToSurface(C4Landscape *d, const CSurface8 &sfcMap, const CSurface8 &sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, int32_t iToX, int32_t iToY, int32_t iToWdt, int32_t iToHgt, int32_t iOffX, int32_t iOffY) { // assign clipper - Surface8->Clip(iToX,iToY,iToX+iToWdt-1,iToY+iToHgt-1); - Surface8Bkg->Clip(iToX,iToY,iToX+iToWdt-1,iToY+iToHgt-1); + Surface8->Clip(iToX, iToY, iToX + iToWdt - 1, iToY + iToHgt - 1); + Surface8Bkg->Clip(iToX, iToY, iToX + iToWdt - 1, iToY + iToHgt - 1); pDraw->NoPrimaryClipper(); // Enlarge map segment for chunky rim - iMapX-=2+MaterialMap.max_shape_width/MapZoom; - iMapY-=2+MaterialMap.max_shape_height/MapZoom; - iMapWdt+=4+MaterialMap.max_shape_width/MapZoom*2; - iMapHgt+=4+MaterialMap.max_shape_height/MapZoom*2; + iMapX -= 2 + MaterialMap.max_shape_width / MapZoom; + iMapY -= 2 + MaterialMap.max_shape_height / MapZoom; + iMapWdt += 4 + MaterialMap.max_shape_width / MapZoom * 2; + iMapHgt += 4 + MaterialMap.max_shape_height / MapZoom * 2; // Determine texture usage in map segment DWORD dwTexUsage[C4M_MaxTexIndex]; - if (!GetTexUsage(sfcMap,sfcMapBkg,iMapX,iMapY,iMapWdt,iMapHgt,dwTexUsage)) return false; + if (!GetTexUsage(sfcMap, sfcMapBkg, iMapX, iMapY, iMapWdt, iMapHgt, dwTexUsage)) return false; // Texture zoom map to landscape - if (!TexOZoom(sfcMap,sfcMapBkg,iMapX,iMapY,iMapWdt,iMapHgt,dwTexUsage,iOffX,iOffY)) return false; + if (!TexOZoom(d, sfcMap, sfcMapBkg, iMapX, iMapY, iMapWdt, iMapHgt, dwTexUsage, iOffX, iOffY)) return false; // remove clipper Surface8->NoClip(); @@ -2266,14 +2339,14 @@ bool C4Landscape::MapToSurface(CSurface8 * sfcMap, CSurface8 * sfcMapBkg, int32_ return true; } -bool C4Landscape::MapToLandscape(CSurface8 * sfcMap, CSurface8 * sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, int32_t iOffsX, int32_t iOffsY, bool noClear) +bool C4Landscape::P::MapToLandscape(C4Landscape *d, const CSurface8 &sfcMap, const CSurface8 &sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, int32_t iOffsX, int32_t iOffsY, bool noClear) { assert(Surface8 && Surface8Bkg); // Clip to map/landscape segment - int iMapWidth,iMapHeight,iLandscapeWidth,iLandscapeHeight; + int iMapWidth, iMapHeight, iLandscapeWidth, iLandscapeHeight; // Get map & landscape size - sfcMap->GetSurfaceSize(iMapWidth,iMapHeight); - Surface8->GetSurfaceSize(iLandscapeWidth,iLandscapeHeight); + sfcMap.GetSurfaceSize(iMapWidth, iMapHeight); + Surface8->GetSurfaceSize(iLandscapeWidth, iLandscapeHeight); // Clip map segment to map size iMapX = Clamp(iMapX, 0, iMapWidth - 1); iMapY = Clamp(iMapY, 0, iMapHeight - 1); iMapWdt = Clamp(iMapWdt, 0, iMapWidth - iMapX); iMapHgt = Clamp(iMapHgt, 0, iMapHeight - iMapY); @@ -2287,53 +2360,56 @@ bool C4Landscape::MapToLandscape(CSurface8 * sfcMap, CSurface8 * sfcMapBkg, int3 To.Wdt = iMapWdt*MapZoom; To.Hgt = iMapHgt*MapZoom; - PrepareChange(To); + PrepareChange(d, To); // clear the old landscape if not supressed - if(!noClear) + if (!noClear) { Surface8->ClearBox8Only(To.x, To.y, To.Wdt, To.Hgt); Surface8Bkg->ClearBox8Only(To.x, To.y, To.Wdt, To.Hgt); } - MapToSurface(sfcMap, sfcMapBkg, iMapX, iMapY, iMapWdt, iMapHgt, To.x, To.y, To.Wdt, To.Hgt, iOffsX, iOffsY); - FinishChange(To); + MapToSurface(d, sfcMap, sfcMapBkg, iMapX, iMapY, iMapWdt, iMapHgt, To.x, To.y, To.Wdt, To.Hgt, iOffsX, iOffsY); + FinishChange(d, To); return true; } -bool C4Landscape::CreateMap(CSurface8*& sfcMap, CSurface8*& sfcMapBkg) +bool C4Landscape::P::CreateMap(CSurface8*& sfcMap, CSurface8*& sfcMapBkg) { - int32_t iWidth=0,iHeight=0; + int32_t iWidth = 0, iHeight = 0; // Create map surface - Game.C4S.Landscape.GetMapSize(iWidth,iHeight,Game.StartupPlayerCount); - if (!(sfcMap=new CSurface8(iWidth,iHeight))) - return false; + Game.C4S.Landscape.GetMapSize(iWidth, iHeight, Game.StartupPlayerCount); + auto fg_map = std::make_unique(iWidth, iHeight); // Fill sfcMap C4MapCreator MapCreator; - MapCreator.Create(sfcMap, - Game.C4S.Landscape, ::TextureMap, - true,Game.StartupPlayerCount); + MapCreator.Create(fg_map.get(), + Game.C4S.Landscape, ::TextureMap, + true, Game.StartupPlayerCount); - sfcMapBkg = CreateDefaultBkgSurface(*sfcMap, false); - if (!sfcMapBkg) { delete sfcMap; sfcMap = NULL; return false; } + auto bg_map = CreateDefaultBkgSurface(*fg_map, false); + if (!bg_map) + return false; + + sfcMap = fg_map.release(); + sfcMapBkg = bg_map.release(); return true; } -bool C4Landscape::CreateMapS2(C4Group &ScenFile, CSurface8*& sfcMap, CSurface8*& sfcMapBkg) +bool C4Landscape::P::CreateMapS2(C4Group &ScenFile, CSurface8*& sfcMap, CSurface8*& sfcMapBkg) { // file present? if (!ScenFile.AccessEntry(C4CFN_DynLandscape)) return false; // create map creator if (!pMapCreator) - pMapCreator = new C4MapCreatorS2(&Game.C4S.Landscape, &::TextureMap, &::MaterialMap, Game.StartupPlayerCount); + pMapCreator = std::make_unique(&Game.C4S.Landscape, &::TextureMap, &::MaterialMap, Game.StartupPlayerCount); // read file pMapCreator->ReadFile(C4CFN_DynLandscape, &ScenFile); // render landscape - if(!pMapCreator->Render(NULL, sfcMap, sfcMapBkg)) + if (!pMapCreator->Render(NULL, sfcMap, sfcMapBkg)) return false; // keep map creator until script callbacks have been done @@ -2343,11 +2419,11 @@ bool C4Landscape::CreateMapS2(C4Group &ScenFile, CSurface8*& sfcMap, CSurface8*& bool C4Landscape::PostInitMap() { // map creator present? - if (!pMapCreator) return true; + if (!p->pMapCreator) return true; // call scripts - pMapCreator->ExecuteCallbacks(MapZoom); + p->pMapCreator->ExecuteCallbacks(p->MapZoom); // destroy map creator, if not needed later - if (!Game.C4S.Landscape.KeepMapCreator) { delete pMapCreator; pMapCreator=NULL; } + if (!Game.C4S.Landscape.KeepMapCreator) { p->pMapCreator.reset(); } // done, success return true; } @@ -2355,39 +2431,11 @@ bool C4Landscape::PostInitMap() /* +++++++++++++++ Searching for features in the landscape +++++++++++++++++ */ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ -bool C4Landscape::_PathFree(int32_t x, int32_t y, int32_t x2, int32_t y2) const -{ - x /= 17; y /= 15; x2 /= 17; y2 /= 15; - while (x != x2 && y != y2) - { - if (PixCnt[x * PixCntPitch + y]) - return false; - if (x > x2) x--; else x++; - if (y > y2) y--; else y++; - } - if (x != x2) - do - { - if (PixCnt[x * PixCntPitch + y]) - return false; - if (x > x2) x--; else x++; - } - while (x != x2); - else - while (y != y2) - { - if (PixCnt[x * PixCntPitch + y]) - return false; - if (y > y2) y--; else y++; - } - return !PixCnt[x * PixCntPitch + y]; -} - int32_t C4Landscape::GetMatHeight(int32_t x, int32_t y, int32_t iYDir, int32_t iMat, int32_t iMax) const { if (iYDir > 0) { - iMax = std::min(iMax, Height - y); + iMax = std::min(iMax, GetHeight() - y); for (int32_t i = 0; i < iMax; i++) if (_GetMat(x, y + i) != iMat) return i; @@ -2404,22 +2452,22 @@ int32_t C4Landscape::GetMatHeight(int32_t x, int32_t y, int32_t iYDir, int32_t i // Nearest free above semi solid bool AboveSemiSolid(int32_t &rx, int32_t &ry) { - int32_t cy1=ry,cy2=ry; - bool UseUpwardsNextFree=false,UseDownwardsNextSolid=false; + int32_t cy1 = ry, cy2 = ry; + bool UseUpwardsNextFree = false, UseDownwardsNextSolid = false; - while ((cy1>=0) || (cy2= 0) || (cy2 < ::Landscape.GetHeight())) { // Check upwards - if (cy1>=0) + if (cy1 >= 0) { - if (GBackSemiSolid(rx,cy1)) UseUpwardsNextFree=true; - else if (UseUpwardsNextFree) { ry=cy1; return true; } + if (GBackSemiSolid(rx, cy1)) UseUpwardsNextFree = true; + else if (UseUpwardsNextFree) { ry = cy1; return true; } } // Check downwards - if (cy2=0) || (cy2= 0) || (cy2 < ::Landscape.GetHeight())) { // Check upwards - if (cy1>=0) - if (!GBackSemiSolid(rx,cy1)) - if (GBackSolid(rx,cy1+1)) - { ry=cy1; return true; } + if (cy1 >= 0) + if (!GBackSemiSolid(rx, cy1)) + if (GBackSolid(rx, cy1 + 1)) + { + ry = cy1; return true; + } // Check downwards - if (cy2+1=0) || (cy2= 0) || (cy2 < ::Landscape.GetHeight())) { // Check upwards - if (cy1>=0) - if (!GBackSolid(rx,cy1)) - if (GBackSolid(rx,cy1+1)) - { ry=cy1; return true; } + if (cy1 >= 0) + if (!GBackSolid(rx, cy1)) + if (GBackSolid(rx, cy1 + 1)) + { + ry = cy1; return true; + } // Check downwards - if (cy2+1=0) || (cy2= 0) || (cy2 < ::Landscape.GetHeight())) { // Check upwards - if (cy1>=0) + if (cy1 >= 0) { - if (GBackLiquid(cx,cy1)) - { rl1++; if (rl1>=hgt) { ry=cy1+hgt/2; return true; } } - else rl1=0; + if (GBackLiquid(cx, cy1)) + { + rl1++; if (rl1 >= hgt) { ry = cy1 + hgt / 2; return true; } + } + else rl1 = 0; } // Check downwards - if (cy2+1=hgt) { ry=cy2-hgt/2; return true; } } - else rl2=0; + if (GBackLiquid(cx, cy2)) + { + rl2++; if (rl2 >= hgt) { ry = cy2 - hgt / 2; return true; } + } + else rl2 = 0; } // Advance cy1--; cy2++; @@ -2505,23 +2565,27 @@ bool FindLiquidHeight(int32_t cx, int32_t &ry, int32_t hgt) bool FindTunnelHeight(int32_t cx, int32_t &ry, int32_t hgt) { - int32_t cy1=ry,cy2=ry,rl1=0,rl2=0; + int32_t cy1 = ry, cy2 = ry, rl1 = 0, rl2 = 0; - while ((cy1>=0) || (cy2= 0) || (cy2 < ::Landscape.GetHeight())) { // Check upwards - if (cy1>=0) + if (cy1 >= 0) { - if (Landscape.GetBackPix(cx, cy1) != 0 && MatDensity(GBackMat(cx,cy1)) < C4M_Liquid) - { rl1++; if (rl1>=hgt) { ry=cy1+hgt/2; return true; } } - else rl1=0; + if (Landscape.GetBackPix(cx, cy1) != 0 && MatDensity(GBackMat(cx, cy1)) < C4M_Liquid) + { + rl1++; if (rl1 >= hgt) { ry = cy1 + hgt / 2; return true; } + } + else rl1 = 0; } // Check downwards - if (cy2+1=hgt) { ry=cy2-hgt/2; return true; } } - else rl2=0; + if (Landscape.GetBackPix(cx, cy2) != 0 && MatDensity(GBackMat(cx, cy2)) < C4M_Liquid) + { + rl2++; if (rl2 >= hgt) { ry = cy2 - hgt / 2; return true; } + } + else rl2 = 0; } // Advance cy1--; cy2++; @@ -2534,95 +2598,95 @@ bool FindTunnelHeight(int32_t cx, int32_t &ry, int32_t hgt) // Returns bottom center of surface space found. bool FindSolidGround(int32_t &rx, int32_t &ry, int32_t width) { - bool fFound=false; + bool fFound = false; - int32_t cx1,cx2,cy1,cy2,rl1=0,rl2=0; + int32_t cx1, cx2, cy1, cy2, rl1 = 0, rl2 = 0; - for (cx1=cx2=rx,cy1=cy2=ry; (cx1>0) || (cx2 0) || (cx2 < ::Landscape.GetWidth()); cx1--, cx2++) { // Left search - if (cx1>=0) // Still going + if (cx1 >= 0) // Still going { - if (AboveSolid(cx1,cy1)) rl1++; // Run okay - else rl1=0; // No run + if (AboveSolid(cx1, cy1)) rl1++; // Run okay + else rl1 = 0; // No run } // Right search - if (cx2=width) { rx=cx1+rl1/2; ry=cy1; fFound=true; break; } - if (rl2>=width) { rx=cx2-rl2/2; ry=cy2; fFound=true; break; } + if (rl1 >= width) { rx = cx1 + rl1 / 2; ry = cy1; fFound = true; break; } + if (rl2 >= width) { rx = cx2 - rl2 / 2; ry = cy2; fFound = true; break; } } - if (fFound) AboveSemiSolid(rx,ry); + if (fFound) AboveSemiSolid(rx, ry); return fFound; } bool FindSurfaceLiquid(int32_t &rx, int32_t &ry, int32_t width, int32_t height) { - bool fFound=false; + bool fFound = false; - int32_t cx1,cx2,cy1,cy2,rl1=0,rl2=0,cnt; + int32_t cx1, cx2, cy1, cy2, rl1 = 0, rl2 = 0, cnt; bool lokay; - for (cx1=cx2=rx,cy1=cy2=ry; (cx1>0) || (cx2 0) || (cx2 < ::Landscape.GetWidth()); cx1--, cx2++) { // Left search - if (cx1>0) // Still going + if (cx1 > 0) // Still going { - if (!AboveSemiSolid(cx1,cy1)) cx1=-1; // Abort left + if (!AboveSemiSolid(cx1, cy1)) cx1 = -1; // Abort left else { - for (lokay=true,cnt=0; cnt=width) { rx=cx1+rl1/2; ry=cy1; fFound=true; break; } - if (rl2>=width) { rx=cx2-rl2/2; ry=cy2; fFound=true; break; } + if (rl1 >= width) { rx = cx1 + rl1 / 2; ry = cy1; fFound = true; break; } + if (rl2 >= width) { rx = cx2 - rl2 / 2; ry = cy2; fFound = true; break; } } - if (fFound) AboveSemiSolid(rx,ry); + if (fFound) AboveSemiSolid(rx, ry); return fFound; } bool FindLiquid(int32_t &rx, int32_t &ry, int32_t width, int32_t height) { - int32_t cx1,cx2,cy1,cy2,rl1=0,rl2=0; + int32_t cx1, cx2, cy1, cy2, rl1 = 0, rl2 = 0; - for (cx1=cx2=rx,cy1=cy2=ry; (cx1>0) || (cx2 0) || (cx2 < ::Landscape.GetWidth()); cx1--, cx2++) { // Left search - if (cx1>0) + if (cx1 > 0) { - if (FindLiquidHeight(cx1,cy1,height)) rl1++; - else rl1=0; + if (FindLiquidHeight(cx1, cy1, height)) rl1++; + else rl1 = 0; } // Right search - if (cx2=width) { rx=cx1+rl1/2; ry=cy1; return true; } - if (rl2>=width) { rx=cx2-rl2/2; ry=cy2; return true; } + if (rl1 >= width) { rx = cx1 + rl1 / 2; ry = cy1; return true; } + if (rl2 >= width) { rx = cx2 - rl2 / 2; ry = cy2; return true; } } return false; @@ -2632,25 +2696,25 @@ bool FindLiquid(int32_t &rx, int32_t &ry, int32_t width, int32_t height) // Tunnel background == no sky && no semi/solid material (density < 25) bool FindTunnel(int32_t &rx, int32_t &ry, int32_t width, int32_t height) { - int32_t cx1,cx2,cy1,cy2,rl1=0,rl2=0; + int32_t cx1, cx2, cy1, cy2, rl1 = 0, rl2 = 0; - for (cx1=cx2=rx,cy1=cy2=ry; (cx1>0) || (cx2 0) || (cx2 < ::Landscape.GetWidth()); cx1--, cx2++) { // Left search - if (cx1>0) + if (cx1 > 0) { - if (FindTunnelHeight(cx1,cy1,height)) rl1++; - else rl1=0; + if (FindTunnelHeight(cx1, cy1, height)) rl1++; + else rl1 = 0; } // Right search - if (cx2=width) { rx=cx1+rl1/2; ry=cy1; return true; } - if (rl2>=width) { rx=cx2-rl2/2; ry=cy2; return true; } + if (rl1 >= width) { rx = cx1 + rl1 / 2; ry = cy1; return true; } + if (rl2 >= width) { rx = cx2 - rl2 / 2; ry = cy2; return true; } } return false; @@ -2660,48 +2724,52 @@ bool FindTunnel(int32_t &rx, int32_t &ry, int32_t width, int32_t height) // may not exceed hrange. Returns bottom center of surface found. bool FindLevelGround(int32_t &rx, int32_t &ry, int32_t width, int32_t hrange) { - bool fFound=false; + bool fFound = false; - int32_t cx1,cx2,cy1,cy2,rh1,rh2,rl1,rl2; + int32_t cx1, cx2, cy1, cy2, rh1, rh2, rl1, rl2; - cx1=cx2=rx; cy1=cy2=ry; - rh1=cy1; rh2=cy2; - rl1=rl2=0; + cx1 = cx2 = rx; cy1 = cy2 = ry; + rh1 = cy1; rh2 = cy2; + rl1 = rl2 = 0; - for (cx1--,cx2++; (cx1>0) || (cx2 0) || (cx2 < ::Landscape.GetWidth()); cx1--, cx2++) { // Left search - if (cx1>0) // Still going + if (cx1 > 0) // Still going { - if (!AboveSemiSolid(cx1,cy1)) cx1=-1; // Abort left + if (!AboveSemiSolid(cx1, cy1)) cx1 = -1; // Abort left else { - if (GBackSolid(cx1,cy1+1) && (Abs(cy1-rh1)=width) { rx=cx1+rl1/2; ry=cy1; fFound=true; break; } - if (rl2>=width) { rx=cx2-rl2/2; ry=cy2; fFound=true; break; } + if (rl1 >= width) { rx = cx1 + rl1 / 2; ry = cy1; fFound = true; break; } + if (rl2 >= width) { rx = cx2 - rl2 / 2; ry = cy2; fFound = true; break; } } - if (fFound) AboveSemiSolid(rx,ry); + if (fFound) AboveSemiSolid(rx, ry); return fFound; } @@ -2710,64 +2778,72 @@ bool FindLevelGround(int32_t &rx, int32_t &ry, int32_t width, int32_t hrange) // structure clearance (category). Returns bottom center of surface found. bool FindConSiteSpot(int32_t &rx, int32_t &ry, int32_t wdt, int32_t hgt, int32_t hrange) { - bool fFound=false; + bool fFound = false; // No hrange limit, use standard smooth surface limit - if (hrange==-1) hrange=std::max(wdt/4,5); + if (hrange == -1) hrange = std::max(wdt / 4, 5); - int32_t cx1,cx2,cy1,cy2,rh1,rh2,rl1,rl2; + int32_t cx1, cx2, cy1, cy2, rh1, rh2, rl1, rl2; // Left offset starting position - cx1=std::min(rx+wdt/2,GBackWdt-1); cy1=ry; + cx1 = std::min(rx + wdt / 2, ::Landscape.GetWidth() - 1); cy1 = ry; // No good: use centered starting position - if (!AboveSemiSolid(cx1,cy1)) { cx1=std::min(rx,GBackWdt-1); cy1=ry; } + if (!AboveSemiSolid(cx1, cy1)) { cx1 = std::min(rx, ::Landscape.GetWidth() - 1); cy1 = ry; } // Right offset starting position - cx2=std::max(rx-wdt/2,0); cy2=ry; + cx2 = std::max(rx - wdt / 2, 0); cy2 = ry; // No good: use centered starting position - if (!AboveSemiSolid(cx2,cy2)) { cx2=std::min(rx,GBackWdt-1); cy2=ry; } + if (!AboveSemiSolid(cx2, cy2)) { cx2 = std::min(rx, ::Landscape.GetWidth() - 1); cy2 = ry; } - rh1=cy1; rh2=cy2; rl1=rl2=0; + rh1 = cy1; rh2 = cy2; rl1 = rl2 = 0; - for (cx1--,cx2++; (cx1>0) || (cx2 0) || (cx2 < ::Landscape.GetWidth()); cx1--, cx2++) { // Left search - if (cx1>0) // Still going + if (cx1 > 0) // Still going { - if (!AboveSemiSolid(cx1,cy1)) - cx1=-1; // Abort left + if (!AboveSemiSolid(cx1, cy1)) + cx1 = -1; // Abort left else { - if (GBackSolid(cx1,cy1+1) && (Abs(cy1-rh1)=wdt) if (cx1>0) - if (!Game.FindConstuctionSiteBlock(cx1,cy1-hgt-10,wdt,hgt+40)) - { rx=cx1+wdt/2; ry=cy1; fFound=true; break; } - if (rl2>=wdt) if (cx2= wdt) if (cx1 > 0) + if (!Game.FindConstuctionSiteBlock(cx1, cy1 - hgt - 10, wdt, hgt + 40)) + { + rx = cx1 + wdt / 2; ry = cy1; fFound = true; break; + } + if (rl2 >= wdt) if (cx2 < ::Landscape.GetWidth()) + if (!Game.FindConstuctionSiteBlock(cx2 - wdt, cy2 - hgt - 10, wdt, hgt + 40)) + { + rx = cx2 - wdt / 2; ry = cy2; fFound = true; break; + } } - if (fFound) AboveSemiSolid(rx,ry); + if (fFound) AboveSemiSolid(rx, ry); return fFound; } @@ -2775,12 +2851,12 @@ bool FindConSiteSpot(int32_t &rx, int32_t &ry, int32_t wdt, int32_t hgt, int32_t // Returns false on any solid pix in path. bool PathFreePix(int32_t x, int32_t y) { - return !GBackSolid(x,y); + return !GBackSolid(x, y); } bool PathFree(int32_t x1, int32_t y1, int32_t x2, int32_t y2) { - return ForLine(x1,y1,x2,y2,&PathFreePix); + return ForLine(x1, y1, x2, y2, &PathFreePix); } bool PathFree(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t *ix, int32_t *iy) @@ -2816,7 +2892,7 @@ bool PathFree(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t *ix, int32 { if (GBackSolid(y, x)) { - if (ix) {*ix = y; *iy = x;} + if (ix) { *ix = y; *iy = x; } return false; } } @@ -2824,7 +2900,7 @@ bool PathFree(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t *ix, int32 { if (GBackSolid(x, y)) { - if (ix) {*ix = x; *iy = y;} + if (ix) { *ix = x; *iy = y; } return false; } } @@ -2852,15 +2928,15 @@ bool PathFree(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t *ix, int32 { if (GBackSolid(y, x)) { - if (ix) {*ix = y; *iy = x;} + if (ix) { *ix = y; *iy = x; } return false; } } else { if (GBackSolid(x, y)) - { - if (ix) {*ix = x; *iy = y;} + { + if (ix) { *ix = x; *iy = y; } return false; } } @@ -2880,57 +2956,58 @@ bool PathFree(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t *ix, int32 bool PathFreeIgnoreVehiclePix(int32_t x, int32_t y) { - BYTE byPix=GBackPix(x,y); + BYTE byPix = ::Landscape.GetPix(x, y); return !byPix || !DensitySolid(::Landscape.GetPixMat(byPix)) || ::Landscape.GetPixMat(byPix) == MVehic; } bool PathFreeIgnoreVehicle(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t *ix, int32_t *iy) { - return ForLine(x1,y1,x2,y2,&PathFreeIgnoreVehiclePix,ix,iy); + return ForLine(x1, y1, x2, y2, &PathFreeIgnoreVehiclePix, ix, iy); } int32_t TrajectoryDistance(int32_t iFx, int32_t iFy, C4Real iXDir, C4Real iYDir, int32_t iTx, int32_t iTy) { - int32_t iClosest = Distance(iFx,iFy,iTx,iTy); + int32_t iClosest = Distance(iFx, iFy, iTx, iTy); // Follow free trajectory, take closest point distance C4Real cx = itofix(iFx), cy = itofix(iFy); int32_t cdis; - while (Inside(fixtoi(cx),0,GBackWdt-1) && Inside(fixtoi(cy),0,GBackHgt-1) && !GBackSolid(fixtoi(cx), fixtoi(cy))) + while (Inside(fixtoi(cx), 0, ::Landscape.GetWidth() - 1) && Inside(fixtoi(cy), 0, ::Landscape.GetHeight() - 1) && !GBackSolid(fixtoi(cx), fixtoi(cy))) { - cdis = Distance(fixtoi(cx),fixtoi(cy),iTx,iTy); - if (cdis0) iDir=-1; + int32_t iDir = +1; if (fXDir > 0) iDir = -1; // Move along surface - for (int32_t cnt=0; Inside(rX,0,GBackWdt-1) && (cnt<=C4LSC_Throwing_MaxHorizontal); rX+=iDir,cnt++) + for (int32_t cnt = 0; Inside(rX, 0, ::Landscape.GetWidth() - 1) && (cnt <= Throwing_MaxHorizontal); rX += iDir, cnt++) { // Adjust to surface - if (!SemiAboveSolid(rX,rY)) return false; + if (!SemiAboveSolid(rX, rY)) return false; // Check trajectory distance - int32_t itjd = TrajectoryDistance(rX,rY-iHeight,fXDir,fYDir,iTx,iTy); + int32_t itjd = TrajectoryDistance(rX, rY - iHeight, fXDir, fYDir, iTx, iTy); // Hitting range: success - if (itjd<=2) return true; + if (itjd <= 2) return true; } // Failure @@ -2938,23 +3015,26 @@ bool FindThrowingPosition(int32_t iTx, int32_t iTy, C4Real fXDir, C4Real fYDir, } -const int32_t C4LSC_Closest_MaxRange = 200, - C4LSC_Closest_Step = 10; +static constexpr int32_t + Closest_MaxRange = 200, + Closest_Step = 10; bool FindClosestFree(int32_t &rX, int32_t &rY, int32_t iAngle1, int32_t iAngle2, - int32_t iExcludeAngle1, int32_t iExcludeAngle2) + int32_t iExcludeAngle1, int32_t iExcludeAngle2) { - int32_t iX,iY; - for (int32_t iR=C4LSC_Closest_Step; iR(iX,0,GBackWdt-1)) - if (Inside(iY,0,GBackHgt-1)) - if (!GBackSemiSolid(iX,iY)) - { rX=iX; rY=iY; return true; } + if (Inside(iX, 0, ::Landscape.GetWidth() - 1)) + if (Inside(iY, 0, ::Landscape.GetHeight() - 1)) + if (!GBackSemiSolid(iX, iY)) + { + rX = iX; rY = iY; return true; + } } return false; } @@ -2963,36 +3043,36 @@ bool ConstructionCheck(C4PropList * PropList, int32_t iX, int32_t iY, C4Object * { C4Def *ndef; // Check def - if (!(ndef=PropList->GetDef())) + if (!(ndef = PropList->GetDef())) { - if (pByObj) GameMsgObjectError(FormatString(LoadResStr("IDS_OBJ_UNDEF"), PropList->GetName()).getData(),pByObj); + if (pByObj) GameMsgObjectError(FormatString(LoadResStr("IDS_OBJ_UNDEF"), PropList->GetName()).getData(), pByObj); return false; } // Constructable? if (!ndef->Constructable) { - if (pByObj) GameMsgObjectError(FormatString(LoadResStr("IDS_OBJ_NOCON"),ndef->GetName()).getData(),pByObj); + if (pByObj) GameMsgObjectError(FormatString(LoadResStr("IDS_OBJ_NOCON"), ndef->GetName()).getData(), pByObj); return false; } // Check area - int32_t rtx,rty,wdt,hgt; - wdt=ndef->Shape.Wdt; hgt=ndef->Shape.Hgt-ndef->ConSizeOff; - rtx=iX-wdt/2; rty=iY-hgt; - if (::Landscape.AreaSolidCount(rtx,rty,wdt,hgt)>(wdt*hgt/20)) + int32_t rtx, rty, wdt, hgt; + wdt = ndef->Shape.Wdt; hgt = ndef->Shape.Hgt - ndef->ConSizeOff; + rtx = iX - wdt / 2; rty = iY - hgt; + if (::Landscape.AreaSolidCount(rtx, rty, wdt, hgt) > (wdt*hgt / 20)) { - if (pByObj) GameMsgObjectError(LoadResStr("IDS_OBJ_NOROOM"),pByObj); + if (pByObj) GameMsgObjectError(LoadResStr("IDS_OBJ_NOROOM"), pByObj); return false; } - if (::Landscape.AreaSolidCount(rtx,rty+hgt,wdt,5)<(wdt*2)) + if (::Landscape.AreaSolidCount(rtx, rty + hgt, wdt, 5) < (wdt * 2)) { - if (pByObj) GameMsgObjectError(LoadResStr("IDS_OBJ_NOLEVEL"),pByObj); + if (pByObj) GameMsgObjectError(LoadResStr("IDS_OBJ_NOLEVEL"), pByObj); return false; } // Check other structures C4Object *other; - if ((other=Game.FindConstuctionSiteBlock(rtx,rty,wdt,hgt))) + if ((other = Game.FindConstuctionSiteBlock(rtx, rty, wdt, hgt))) { - if (pByObj) GameMsgObjectError(FormatString(LoadResStr("IDS_OBJ_NOOTHER"),other->GetName ()).getData(),pByObj); + if (pByObj) GameMsgObjectError(FormatString(LoadResStr("IDS_OBJ_NOOTHER"), other->GetName()).getData(), pByObj); return false; } return true; @@ -3001,32 +3081,36 @@ bool ConstructionCheck(C4PropList * PropList, int32_t iX, int32_t iY, C4Object * // Finds the next pixel position moving to desired slide. bool C4Landscape::FindMatPath(int32_t &fx, int32_t &fy, int32_t ydir, int32_t mdens, int32_t mslide) const { - assert(mdens<=C4M_Solid); // mdens normalized in InsertMaterial + assert(mdens <= C4M_Solid); // mdens normalized in InsertMaterial int32_t cslide; - bool fLeft=true,fRight=true; + bool fLeft = true, fRight = true; // One downwards - if (GetDensity(fx,fy+ydir)=mdens) // Left clogged - fLeft=false; - else if (GetDensity(fx-cslide,fy+ydir)= mdens) // Left clogged + fLeft = false; + else if (GetDensity(fx - cslide, fy + ydir) < mdens) // Left slide okay + { + fx--; return true; + } } // Check right if (fRight) { - if (GetDensity(fx+cslide,fy)>=mdens) // Right clogged - fRight=false; - else if (GetDensity(fx+cslide,fy+ydir)= mdens) // Right clogged + fRight = false; + else if (GetDensity(fx + cslide, fy + ydir) < mdens) // Right slide okay + { + fx++; return true; + } } } @@ -3036,31 +3120,35 @@ bool C4Landscape::FindMatPath(int32_t &fx, int32_t &fy, int32_t ydir, int32_t md // Finds the closest immediate slide position. bool C4Landscape::FindMatSlide(int32_t &fx, int32_t &fy, int32_t ydir, int32_t mdens, int32_t mslide) const { - assert(mdens<=C4M_Solid); // mdens normalized in InsertMaterial and mrfInsertCheck + assert(mdens <= C4M_Solid); // mdens normalized in InsertMaterial and mrfInsertCheck int32_t cslide; - bool fLeft=true,fRight=true; + bool fLeft = true, fRight = true; // One downwards - if (GetDensity(fx,fy+ydir)=mdens && GetDensity(fx-cslide,fy+ydir)>=mdens) // Left clogged - fLeft=false; - else if (GetDensity(fx-cslide,fy+ydir)= mdens && GetDensity(fx - cslide, fy + ydir) >= mdens) // Left clogged + fLeft = false; + else if (GetDensity(fx - cslide, fy + ydir) < mdens) // Left slide okay + { + fx -= cslide; fy += ydir; return true; + } } // Check right if (fRight) { - if (GetDensity(fx+cslide,fy)>=mdens && GetDensity(fx+cslide,fy+ydir)>=mdens) // Right clogged - fRight=false; - else if (GetDensity(fx+cslide,fy+ydir)= mdens && GetDensity(fx + cslide, fy + ydir) >= mdens) // Right clogged + fRight = false; + else if (GetDensity(fx + cslide, fy + ydir) < mdens) // Right slide okay + { + fx += cslide; fy += ydir; return true; + } } } @@ -3073,12 +3161,12 @@ bool C4Landscape::FindMatSlide(int32_t &fx, int32_t &fy, int32_t ydir, int32_t m bool C4Landscape::FindMatPathPush(int32_t &fx, int32_t &fy, int32_t mdens, int32_t mslide, bool liquid) const { // Startpoint must be inside landscape - fx = Clamp(fx, 0, Width - 1); - fy = Clamp(fy, 0, Height - 1); + fx = Clamp(fx, 0, GetWidth() - 1); + fy = Clamp(fy, 0, GetHeight() - 1); // Range to search, calculate bounds const int32_t iPushRange = 500; - int32_t left = std::max(0, fx - iPushRange), right = std::min(Width - 1, fx + iPushRange), - top = std::max(0, fy - iPushRange), bottom = std::min(Height - 1, fy + iPushRange); + int32_t left = std::max(0, fx - iPushRange), right = std::min(GetWidth() - 1, fx + iPushRange), + top = std::max(0, fy - iPushRange), bottom = std::min(GetHeight() - 1, fy + iPushRange); // Direction constants const int8_t R = 0, D = 1, L = 2, U = 3; int8_t dir = 0; @@ -3094,13 +3182,21 @@ bool C4Landscape::FindMatPathPush(int32_t &fx, int32_t &fy, int32_t mdens, int32 // Find start point for border search for (int32_t i = 0; ; i++) if (x - i - 1 < left || GetDensity(x - i - 1, y) != mdens) - { x -= i; dir = L; break; } + { + x -= i; dir = L; break; + } else if (y - i - 1 < top || GetDensity(x, y - i - 1) != mdens) - { y -= i; dir = U; break; } + { + y -= i; dir = U; break; + } else if (x + i + 1 > right || GetDensity(x + i + 1, y) != mdens) - { x += i; dir = R; break; } + { + x += i; dir = R; break; + } else if (y + i + 1 > bottom || GetDensity(x, y + i + 1) != mdens) - { y += i; dir = D; break; } + { + y += i; dir = D; break; + } } // Greater density else @@ -3109,21 +3205,29 @@ bool C4Landscape::FindMatPathPush(int32_t &fx, int32_t &fy, int32_t mdens, int32 int i = 1; for (; i < iPushRange; i++) if (GetDensity(x - i, y) <= mdens) - { x -= i; dir = R; break; } + { + x -= i; dir = R; break; + } else if (GetDensity(x, y - i) <= mdens) - { y -= i; dir = D; break; } + { + y -= i; dir = D; break; + } else if (GetDensity(x + i, y) <= mdens) - { x += i; dir = L; break; } + { + x += i; dir = L; break; + } else if (GetDensity(x, y + i) <= mdens) - { y += i; dir = U; break; } - // Not found? - if (i >= iPushRange) return false; - // Done? - if (GetDensity(x, y) < mdens) - { - fx = x; fy = y; - return true; - } + { + y += i; dir = U; break; + } + // Not found? + if (i >= iPushRange) return false; + // Done? + if (GetDensity(x, y) < mdens) + { + fx = x; fy = y; + return true; + } } // Save startpoint of search int32_t sx = x, sy = y, sdir = dir; @@ -3184,8 +3288,7 @@ bool C4Landscape::FindMatPathPush(int32_t &fx, int32_t &fy, int32_t mdens, int32 ++dir; dir %= 4; } - } - while (x != sx || y != sy || dir != sdir); + } while (x != sx || y != sy || dir != sdir); // Nothing found? if (!fGotBest) return false; // Return it @@ -3195,58 +3298,57 @@ bool C4Landscape::FindMatPathPush(int32_t &fx, int32_t &fy, int32_t mdens, int32 int32_t C4Landscape::AreaSolidCount(int32_t x, int32_t y, int32_t wdt, int32_t hgt) const { - int32_t cx,cy,ascnt=0; - for (cy=y; cy(iMode,C4LSC_Dynamic,C4LSC_Exact)) return false; - // Set mode - Mode=iMode; - // Done - return true; + p->mode = mode; } -bool C4Landscape::GetMapColorIndex(const char *szMaterial, const char *szTexture, BYTE & rbyCol) const +LandscapeMode C4Landscape::GetMode() const +{ + return p->mode; +} + +bool C4Landscape::P::GetMapColorIndex(const char *szMaterial, const char *szTexture, BYTE & rbyCol) const { // Sky - if (SEqual(szMaterial,C4TLS_MatSky)) - rbyCol=0; + if (SEqual(szMaterial, C4TLS_MatSky)) + rbyCol = 0; // Material-Texture else { - if (!(rbyCol=::TextureMap.GetIndex(szMaterial,szTexture))) return false; + rbyCol = ::TextureMap.GetIndex(szMaterial, szTexture); + if (!rbyCol) return false; } // Found return true; @@ -3284,59 +3387,73 @@ bool C4Landscape::DrawBrush(int32_t iX, int32_t iY, int32_t iGrade, const char * { BYTE byCol, byColBkg; // Get map color index by material-texture - if (!GetMapColorIndex(szMaterial,szTexture,byCol)) return false; - if (!GetMapColorIndex(szBackMaterial,szBackTexture,byColBkg)) return false; + if (!p->GetMapColorIndex(szMaterial, szTexture, byCol)) return false; + if (!p->GetMapColorIndex(szBackMaterial, szBackTexture, byColBkg)) return false; // Get material shape size C4Texture *texture = ::TextureMap.GetTexture(szTexture); - int32_t shape_wdt=0, shape_hgt=0; + int32_t shape_wdt = 0, shape_hgt = 0; if (texture && texture->GetMaterialShape()) { - shape_wdt = texture->GetMaterialShape()->GetMaxPolyWidth() / MapZoom; - shape_hgt = texture->GetMaterialShape()->GetMaxPolyHeight() / MapZoom; + shape_wdt = texture->GetMaterialShape()->GetMaxPolyWidth() / p->MapZoom; + shape_hgt = texture->GetMaterialShape()->GetMaxPolyHeight() / p->MapZoom; } // Draw - switch (Mode) + switch (p->mode) { // Dynamic: ignore - case C4LSC_Dynamic: + case LandscapeMode::Dynamic: break; // Static: draw to map by material-texture-index, chunk-o-zoom to landscape - case C4LSC_Static: - // Draw to map - int32_t iRadius; iRadius=std::max(2*iGrade/MapZoom,1); - if (iRadius==1) { Map->SetPix(iX/MapZoom,iY/MapZoom,byCol); MapBkg->SetPix(iX/MapZoom, iY/MapZoom, byColBkg); } - else { Map->Circle(iX/MapZoom,iY/MapZoom,iRadius,byCol); MapBkg->Circle(iX/MapZoom, iY/MapZoom, iRadius, byColBkg); } - // Update landscape - MapToLandscape(Map,MapBkg,iX/MapZoom-iRadius-1-shape_wdt,iY/MapZoom-iRadius-1-shape_hgt,2*iRadius+2+shape_wdt*2,2*iRadius+2+shape_hgt*2); - SetMapChanged(); + case LandscapeMode::Static: + { + // Draw to map + int32_t iRadius = std::max(2 * iGrade / p->MapZoom, 1); + if (iRadius == 1) + { + p->Map->SetPix(iX / p->MapZoom, iY / p->MapZoom, byCol); + p->MapBkg->SetPix(iX / p->MapZoom, iY / p->MapZoom, byColBkg); + } + else + { + p->Map->Circle(iX / p->MapZoom, iY / p->MapZoom, iRadius, byCol); + p->MapBkg->Circle(iX / p->MapZoom, iY / p->MapZoom, iRadius, byColBkg); + } + // Update landscape + p->MapToLandscape(this, *p->Map, *p->MapBkg, iX / p->MapZoom - iRadius - 1 - shape_wdt, iY / p->MapZoom - iRadius - 1 - shape_hgt, 2 * iRadius + 2 + shape_wdt * 2, 2 * iRadius + 2 + shape_hgt * 2); + SetMapChanged(); + } break; // Exact: draw directly to landscape by color & pattern - case C4LSC_Exact: - C4Rect BoundingBox(iX-iGrade-1, iY-iGrade-1, iGrade*2+2, iGrade*2+2); + case LandscapeMode::Exact: + C4Rect BoundingBox(iX - iGrade - 1, iY - iGrade - 1, iGrade * 2 + 2, iGrade * 2 + 2); // Draw to landscape - PrepareChange(BoundingBox); - Surface8->Circle(iX,iY,iGrade, byCol); - Surface8Bkg->Circle(iX,iY,iGrade, byColBkg); - FinishChange(BoundingBox); + p->PrepareChange(this, BoundingBox); + p->Surface8->Circle(iX, iY, iGrade, byCol); + p->Surface8Bkg->Circle(iX, iY, iGrade, byColBkg); + p->FinishChange(this, BoundingBox); break; } return true; } -bool C4Landscape::DrawLineLandscape(int32_t iX, int32_t iY, int32_t iGrade, uint8_t line_color, uint8_t line_color_bkg) +bool C4Landscape::P::DrawLineLandscape(int32_t iX, int32_t iY, int32_t iGrade, uint8_t line_color, uint8_t line_color_bkg) { Surface8->Circle(iX, iY, iGrade, line_color); Surface8Bkg->Circle(iX, iY, iGrade, line_color_bkg); return true; } -bool C4Landscape::DrawLineMap(int32_t iX, int32_t iY, int32_t iRadius, uint8_t line_color, uint8_t line_color_bkg) +bool C4Landscape::P::DrawLineMap(int32_t iX, int32_t iY, int32_t iRadius, uint8_t line_color, uint8_t line_color_bkg) { if (!Map) return false; if (iRadius == 1) - { Map->SetPix(iX, iY, line_color); MapBkg->SetPix(iX, iY, line_color_bkg); } + { + Map->SetPix(iX, iY, line_color); MapBkg->SetPix(iX, iY, line_color_bkg); + } else - { Map->Circle(iX, iY, iRadius, line_color); MapBkg->Circle(iX, iY, iRadius, line_color_bkg); } + { + Map->Circle(iX, iY, iRadius, line_color); MapBkg->Circle(iX, iY, iRadius, line_color_bkg); + } return true; } @@ -3344,44 +3461,47 @@ bool C4Landscape::DrawLine(int32_t iX1, int32_t iY1, int32_t iX2, int32_t iY2, i { // Get map color index by material-texture uint8_t line_color, line_color_bkg; - if (!GetMapColorIndex(szMaterial,szTexture,line_color)) return false; - if (!GetMapColorIndex(szBackMaterial,szBackTexture,line_color_bkg)) return false; + if (!p->GetMapColorIndex(szMaterial, szTexture, line_color)) return false; + if (!p->GetMapColorIndex(szBackMaterial, szBackTexture, line_color_bkg)) return false; // Get material shape size C4Texture *texture = ::TextureMap.GetTexture(szTexture); int32_t shape_wdt = 0, shape_hgt = 0; if (texture && texture->GetMaterialShape()) { - shape_wdt = texture->GetMaterialShape()->GetMaxPolyWidth() / MapZoom; - shape_hgt = texture->GetMaterialShape()->GetMaxPolyHeight() / MapZoom; + shape_wdt = texture->GetMaterialShape()->GetMaxPolyWidth() / p->MapZoom; + shape_hgt = texture->GetMaterialShape()->GetMaxPolyHeight() / p->MapZoom; } // Draw - switch (Mode) + switch (p->mode) { // Dynamic: ignore - case C4LSC_Dynamic: + case LandscapeMode::Dynamic: break; // Static: draw to map by material-texture-index, chunk-o-zoom to landscape - case C4LSC_Static: - // Draw to map - int32_t iRadius; iRadius=std::max(2*iGrade/MapZoom,1); - iX1/=MapZoom; iY1/=MapZoom; iX2/=MapZoom; iY2/=MapZoom; - ForLine(iX1, iY1, iX2, iY2, [this, line_color, line_color_bkg, iRadius](int32_t x, int32_t y) { return DrawLineMap(x, y, iRadius, line_color, line_color_bkg); }); - // Update landscape - int32_t iUpX,iUpY,iUpWdt,iUpHgt; - iUpX=std::min(iX1,iX2)-iRadius-1; iUpY=std::min(iY1,iY2)-iRadius-1; - iUpWdt=Abs(iX2-iX1)+2*iRadius+2; iUpHgt=Abs(iY2-iY1)+2*iRadius+2; - MapToLandscape(Map,MapBkg,iUpX-shape_wdt,iUpY-shape_hgt,iUpWdt+shape_wdt*2,iUpHgt+shape_hgt*2); - SetMapChanged(); + case LandscapeMode::Static: + { + // Draw to map + int32_t iRadius = std::max(2 * iGrade / p->MapZoom, 1); + iX1 /= p->MapZoom; iY1 /= p->MapZoom; iX2 /= p->MapZoom; iY2 /= p->MapZoom; + ForLine(iX1, iY1, iX2, iY2, [this, line_color, line_color_bkg, iRadius](int32_t x, int32_t y) { return p->DrawLineMap(x, y, iRadius, line_color, line_color_bkg); }); + // Update landscape + int iUpX = std::min(iX1, iX2) - iRadius - 1; + int iUpY = std::min(iY1, iY2) - iRadius - 1; + int iUpWdt = Abs(iX2 - iX1) + 2 * iRadius + 2; + int iUpHgt = Abs(iY2 - iY1) + 2 * iRadius + 2; + p->MapToLandscape(this, *p->Map, *p->MapBkg, iUpX - shape_wdt, iUpY - shape_hgt, iUpWdt + shape_wdt * 2, iUpHgt + shape_hgt * 2); + SetMapChanged(); + } break; // Exact: draw directly to landscape by color & pattern - case C4LSC_Exact: + case LandscapeMode::Exact: // Set texture pattern & get material color - C4Rect BoundingBox(iX1 - iGrade, iY1 - iGrade, iGrade*2+1, iGrade*2+1); - BoundingBox.Add(C4Rect(iX2 - iGrade, iY2 - iGrade, iGrade*2+1, iGrade*2+1)); + C4Rect BoundingBox(iX1 - iGrade, iY1 - iGrade, iGrade * 2 + 1, iGrade * 2 + 1); + BoundingBox.Add(C4Rect(iX2 - iGrade, iY2 - iGrade, iGrade * 2 + 1, iGrade * 2 + 1)); // Draw to landscape - PrepareChange(BoundingBox); - ForLine(iX1, iY1, iX2, iY2, [this, line_color, line_color_bkg, iGrade](int32_t x, int32_t y) { return DrawLineLandscape(x, y, iGrade, line_color, line_color_bkg); }); - FinishChange(BoundingBox); + p->PrepareChange(this, BoundingBox); + ForLine(iX1, iY1, iX2, iY2, [this, line_color, line_color_bkg, iGrade](int32_t x, int32_t y) { return p->DrawLineLandscape(x, y, iGrade, line_color, line_color_bkg); }); + p->FinishChange(this, BoundingBox); break; } return true; @@ -3390,44 +3510,44 @@ bool C4Landscape::DrawLine(int32_t iX1, int32_t iY1, int32_t iX2, int32_t iY2, i bool C4Landscape::DrawBox(int32_t iX1, int32_t iY1, int32_t iX2, int32_t iY2, int32_t iGrade, const char *szMaterial, const char *szTexture, const char *szBackMaterial, const char *szBackTexture) { // get upper-left/lower-right - corners - int32_t iX0=std::min(iX1, iX2); int32_t iY0=std::min(iY1, iY2); - iX2=std::max(iX1, iX2); iY2=std::max(iY1, iY2); iX1=iX0; iY1=iY0; + int32_t iX0 = std::min(iX1, iX2); int32_t iY0 = std::min(iY1, iY2); + iX2 = std::max(iX1, iX2); iY2 = std::max(iY1, iY2); iX1 = iX0; iY1 = iY0; BYTE byCol, byColBkg; // Get map color index by material-texture - if (!GetMapColorIndex(szMaterial,szTexture,byCol)) return false; - if (!GetMapColorIndex(szBackMaterial,szBackTexture,byColBkg)) return false; + if (!p->GetMapColorIndex(szMaterial, szTexture, byCol)) return false; + if (!p->GetMapColorIndex(szBackMaterial, szBackTexture, byColBkg)) return false; // Get material shape size C4Texture *texture = ::TextureMap.GetTexture(szTexture); int32_t shape_wdt = 0, shape_hgt = 0; if (texture && texture->GetMaterialShape()) { - shape_wdt = texture->GetMaterialShape()->GetMaxPolyWidth() / MapZoom; - shape_hgt = texture->GetMaterialShape()->GetMaxPolyHeight() / MapZoom; + shape_wdt = texture->GetMaterialShape()->GetMaxPolyWidth() / p->MapZoom; + shape_hgt = texture->GetMaterialShape()->GetMaxPolyHeight() / p->MapZoom; } // Draw - switch (Mode) + switch (p->mode) { // Dynamic: ignore - case C4LSC_Dynamic: + case LandscapeMode::Dynamic: break; // Static: draw to map by material-texture-index, chunk-o-zoom to landscape - case C4LSC_Static: + case LandscapeMode::Static: // Draw to map - iX1/=MapZoom; iY1/=MapZoom; iX2/=MapZoom; iY2/=MapZoom; - Map->Box(iX1,iY1,iX2,iY2,byCol); - MapBkg->Box(iX1, iY1, iX2, iY2, byColBkg); + iX1 /= p->MapZoom; iY1 /= p->MapZoom; iX2 /= p->MapZoom; iY2 /= p->MapZoom; + p->Map->Box(iX1, iY1, iX2, iY2, byCol); + p->MapBkg->Box(iX1, iY1, iX2, iY2, byColBkg); // Update landscape - MapToLandscape(Map,MapBkg,iX1-1-shape_wdt,iY1-1-shape_hgt,iX2-iX1+3+shape_wdt*2,iY2-iY1+3+shape_hgt*2); + p->MapToLandscape(this, *p->Map, *p->MapBkg, iX1 - 1 - shape_wdt, iY1 - 1 - shape_hgt, iX2 - iX1 + 3 + shape_wdt * 2, iY2 - iY1 + 3 + shape_hgt * 2); SetMapChanged(); break; // Exact: draw directly to landscape by color & pattern - case C4LSC_Exact: - C4Rect BoundingBox(iX1, iY1, iX2 - iX1+1, iY2 - iY1+1); + case LandscapeMode::Exact: + C4Rect BoundingBox(iX1, iY1, iX2 - iX1 + 1, iY2 - iY1 + 1); // Draw to landscape - PrepareChange(BoundingBox); - Surface8->Box(iX1,iY1,iX2,iY2,byCol); - Surface8Bkg->Box(iX1,iY1,iX2,iY2,byColBkg); - FinishChange(BoundingBox); + p->PrepareChange(this, BoundingBox); + p->Surface8->Box(iX1, iY1, iX2, iY2, byCol); + p->Surface8Bkg->Box(iX1, iY1, iX2, iY2, byColBkg); + p->FinishChange(this, BoundingBox); break; } return true; @@ -3436,30 +3556,33 @@ bool C4Landscape::DrawBox(int32_t iX1, int32_t iY1, int32_t iX2, int32_t iY2, in bool C4Landscape::DrawChunks(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, int32_t icntx, int32_t icnty, const char *szMaterial, const char *szTexture, bool bIFT) { BYTE byColor; - if (!GetMapColorIndex(szMaterial, szTexture, byColor)) return false; + if (!p->GetMapColorIndex(szMaterial, szTexture, byColor)) return false; + + int32_t iMaterial = ::MaterialMap.Get(szMaterial); + if (!MatValid(iMaterial)) + return false; - int32_t iMaterial = ::MaterialMap.Get(szMaterial); if (!MatValid(iMaterial)) return false; C4MaterialCoreShape shape = ::Game.C4S.Landscape.FlatChunkShapes ? C4M_Flat : ::MaterialMap.Map[iMaterial].MapChunkType; C4Rect BoundingBox(tx - 5, ty - 5, wdt + 10, hgt + 10); - PrepareChange(BoundingBox); + p->PrepareChange(this, BoundingBox); // assign clipper - Surface8->Clip(BoundingBox.x,BoundingBox.y,BoundingBox.x+BoundingBox.Wdt,BoundingBox.y+BoundingBox.Hgt); - Surface8Bkg->Clip(BoundingBox.x,BoundingBox.y,BoundingBox.x+BoundingBox.Wdt,BoundingBox.y+BoundingBox.Hgt); + p->Surface8->Clip(BoundingBox.x, BoundingBox.y, BoundingBox.x + BoundingBox.Wdt, BoundingBox.y + BoundingBox.Hgt); + p->Surface8Bkg->Clip(BoundingBox.x, BoundingBox.y, BoundingBox.x + BoundingBox.Wdt, BoundingBox.y + BoundingBox.Hgt); pDraw->NoPrimaryClipper(); // draw all chunks int32_t x, y; for (x = 0; x < icntx; x++) for (y = 0; y < icnty; y++) - DrawChunk(tx+wdt*x/icntx,ty+hgt*y/icnty,wdt/icntx,hgt/icnty,byColor,bIFT ? DefaultBkgMat(byColor) : 0, shape,Random(1000)); + p->DrawChunk(this, tx + wdt*x / icntx, ty + hgt*y / icnty, wdt / icntx, hgt / icnty, byColor, bIFT ? p->DefaultBkgMat(byColor) : 0, shape, Random(1000)); // remove clipper - Surface8->NoClip(); - Surface8Bkg->NoClip(); + p->Surface8->NoClip(); + p->Surface8Bkg->NoClip(); - FinishChange(BoundingBox); + p->FinishChange(this, BoundingBox); // success return true; @@ -3467,8 +3590,8 @@ bool C4Landscape::DrawChunks(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, i bool C4Landscape::DrawPolygon(int *vtcs, int length, const char *szMaterial, const char* szBackMaterial, bool fDrawBridge) { - if(length < 6) return false; - if(length % 2 == 1) return false; + if (length < 6) return false; + if (length % 2 == 1) return false; // get texture int32_t iMatTex = ::TextureMap.GetIndexMatTex(szMaterial); if (!iMatTex) return false; @@ -3485,31 +3608,237 @@ bool C4Landscape::DrawPolygon(int *vtcs, int length, const char *szMaterial, con uint8_t *conversion_map = NULL; if (fDrawBridge) { - conversion_map = GetBridgeMatConversion(MatTex2PixCol(iMatTex)); + conversion_map = p->GetBridgeMatConversion(this, MatTex2PixCol(iMatTex)); mcolBkg = Transparent; } // prepare pixel count update - C4Rect BoundingBox = getBoundingBox(vtcs,length); + C4Rect BoundingBox = getBoundingBox(vtcs, length); // draw polygon - PrepareChange(BoundingBox); - ForPolygon(vtcs,length/2,NULL,NULL, mcol, mcolBkg, conversion_map); - FinishChange(BoundingBox); + p->PrepareChange(this, BoundingBox); + p->ForPolygon(this, vtcs, length / 2, NULL, NULL, mcol, mcolBkg, conversion_map); + p->FinishChange(this, BoundingBox); return true; } -uint8_t *C4Landscape::GetBridgeMatConversion(int32_t for_material_col) const +CStdPalette * C4Landscape::GetPal() const +{ + return p->Surface8 ? p->Surface8->pPal : NULL; +} + +int32_t C4Landscape::GetWidth() const +{ + return p->Width; +} + +int32_t C4Landscape::GetHeight() const +{ + return p->Height; +} + +int32_t C4Landscape::GetMapZoom() const +{ + return p->MapZoom; +} + +C4Real C4Landscape::GetGravity() const +{ + return p->Gravity; +} + +void C4Landscape::SetGravity(C4Real g) +{ + p->Gravity = g; +} + +BYTE C4Landscape::_GetPix(int32_t x, int32_t y) const +{ +#ifdef _DEBUG + if (x < 0 || y < 0 || x >= Width || y >= Height) { BREAKPOINT_HERE; } +#endif + return p->Surface8->_GetPix(x, y); +} + +BYTE C4Landscape::GetPix(int32_t x, int32_t y) const // get landscape pixel (bounds checked) +{ + extern BYTE MCVehic; + // Border checks + if (x < 0) + { + if (y < p->LeftOpen) return 0; + else return MCVehic; + } + if (static_cast(x) >= static_cast(p->Width)) + { + if (y < p->RightOpen) return 0; + else return MCVehic; + } + if (y < 0) + { + return p->TopRowPix[x]; + } + if (static_cast(y) >= static_cast(p->Height)) + { + return p->BottomRowPix[x]; + } + return p->Surface8->_GetPix(x, y); +} + +int32_t C4Landscape::_GetMat(int32_t x, int32_t y) const +{ + return p->Pix2Mat[_GetPix(x, y)]; +} + +int32_t C4Landscape::_GetDensity(int32_t x, int32_t y) const // get landscape density (bounds not checked) +{ + return p->Pix2Dens[_GetPix(x, y)]; +} + +int32_t C4Landscape::_GetPlacement(int32_t x, int32_t y) const // get landscape material placement (bounds not checked) +{ + return p->Pix2Place[_GetPix(x, y)]; +} + +int32_t C4Landscape::GetMat(int32_t x, int32_t y) const // get landscape material (bounds checked) +{ + return p->Pix2Mat[GetPix(x, y)]; +} + +int32_t C4Landscape::GetDensity(int32_t x, int32_t y) const // get landscape density (bounds checked) +{ + return p->Pix2Dens[GetPix(x, y)]; +} + +int32_t C4Landscape::GetPlacement(int32_t x, int32_t y) const // get landscape material placement (bounds checked) +{ + return p->Pix2Place[GetPix(x, y)]; +} + +BYTE C4Landscape::_GetBackPix(int32_t x, int32_t y) const // get landscape pixel (bounds not checked) +{ +#ifdef _DEBUG + if (x < 0 || y < 0 || x >= Width || y >= Height) { BREAKPOINT_HERE; } +#endif + return p->Surface8Bkg->_GetPix(x, y); +} + +BYTE C4Landscape::GetBackPix(int32_t x, int32_t y) const // get landscape pixel (bounds checked) +{ + // Border checks + if (x < 0) + { + if (y < p->LeftOpen) return 0; + else return Mat2PixColDefault(MTunnel); + } + if (static_cast(x) >= static_cast(GetWidth())) + { + if (y < p->RightOpen) return 0; + else return Mat2PixColDefault(MTunnel); + } + if (y < 0) + { + return p->DefaultBkgMat(p->TopRowPix[x]); + } + if (static_cast(y) >= static_cast(GetHeight())) + { + return p->DefaultBkgMat(p->BottomRowPix[x]); + } + + return p->Surface8Bkg->_GetPix(x, y); +} + +int32_t C4Landscape::_GetBackMat(int32_t x, int32_t y) const // get landscape material (bounds not checked) +{ + return p->Pix2Mat[_GetBackPix(x, y)]; +} + +int32_t C4Landscape::_GetBackDensity(int32_t x, int32_t y) const // get landscape density (bounds not checked) +{ + return p->Pix2Dens[_GetBackPix(x, y)]; +} + +int32_t C4Landscape::_GetBackPlacement(int32_t x, int32_t y) const // get landscape material placement (bounds not checked) +{ + return p->Pix2Place[_GetBackPix(x, y)]; +} + +int32_t C4Landscape::GetBackMat(int32_t x, int32_t y) const // get landscape material (bounds checked) +{ + return p->Pix2Mat[GetBackPix(x, y)]; +} + +int32_t C4Landscape::GetBackDensity(int32_t x, int32_t y) const // get landscape density (bounds checked) +{ + return p->Pix2Dens[GetBackPix(x, y)]; +} + +int32_t C4Landscape::GetBackPlacement(int32_t x, int32_t y) const // get landscape material placement (bounds checked) +{ + return p->Pix2Place[GetBackPix(x, y)]; +} + +bool C4Landscape::GetLight(int32_t x, int32_t y) +{ + return GetBackPix(x, y) == 0 || p->Pix2Light[GetPix(x, y)]; +} + +bool C4Landscape::_GetLight(int32_t x, int32_t y) +{ + return _GetBackPix(x, y) == 0 || p->Pix2Light[_GetPix(x, y)]; +} + +bool C4Landscape::_FastSolidCheck(int32_t x, int32_t y) const // checks whether there *might* be something solid at the point +{ + return p->PixCnt[(x / 17) * p->PixCntPitch + (y / 15)] > 0; +} + +int32_t C4Landscape::FastSolidCheckNextX(int32_t x) +{ + return (x / 17) * 17 + 17; +} + +int32_t C4Landscape::GetPixMat(BYTE byPix) const { return p->Pix2Mat[byPix]; } + +int32_t C4Landscape::GetPixDensity(BYTE byPix) const { return p->Pix2Dens[byPix]; } + +bool C4Landscape::_PathFree(int32_t x, int32_t y, int32_t x2, int32_t y2) const +{ + x /= 17; y /= 15; x2 /= 17; y2 /= 15; + while (x != x2 && y != y2) + { + if (p->PixCnt[x * p->PixCntPitch + y]) + return false; + if (x > x2) x--; else x++; + if (y > y2) y--; else y++; + } + if (x != x2) + do + { + if (p->PixCnt[x * p->PixCntPitch + y]) + return false; + if (x > x2) x--; else x++; + } while (x != x2); + else + while (y != y2) + { + if (p->PixCnt[x * p->PixCntPitch + y]) + return false; + if (y > y2) y--; else y++; + } + return !p->PixCnt[x * p->PixCntPitch + y]; +} + +uint8_t *C4Landscape::P::GetBridgeMatConversion(const C4Landscape *d, int32_t for_material_col) const { // safety - int32_t for_material = GetPixMat(for_material_col); + int32_t for_material = d->GetPixMat(for_material_col); if (for_material < 0 || for_material >= MaterialMap.Num) return NULL; // query map. create if not done yet - uint8_t *conv_map = BridgeMatConversion[for_material_col]; - if (!conv_map) + if (!BridgeMatConversion[for_material_col]) { - conv_map = new uint8_t[C4M_MaxTexIndex]; - for (int32_t i=0; i < C4M_MaxTexIndex; ++i) + auto conv_map = std::make_unique(C4M_MaxTexIndex); + for (int32_t i = 0; i < C4M_MaxTexIndex; ++i) { - if ( (MatDensity(for_material)>=GetPixDensity(i))) + if ((MatDensity(for_material) >= d->GetPixDensity(i))) { // bridge pixel OK here. change pixel. conv_map[i] = for_material_col; @@ -3520,9 +3849,9 @@ uint8_t *C4Landscape::GetBridgeMatConversion(int32_t for_material_col) const conv_map[i] = i; } } - BridgeMatConversion[for_material_col] = conv_map; + BridgeMatConversion[for_material_col] = std::move(conv_map); } - return conv_map; + return BridgeMatConversion[for_material_col].get(); } bool C4Landscape::DrawQuad(int32_t iX1, int32_t iY1, int32_t iX2, int32_t iY2, int32_t iX3, int32_t iY3, int32_t iX4, int32_t iY4, const char *szMaterial, const char *szBackMaterial, bool fDrawBridge) @@ -3538,17 +3867,17 @@ bool C4Landscape::DrawQuad(int32_t iX1, int32_t iY1, int32_t iX2, int32_t iY2, i BYTE C4Landscape::GetMapIndex(int32_t iX, int32_t iY) const { - if (!Map) return 0; - return Map->GetPix(iX,iY); + if (!p->Map) return 0; + return p->Map->GetPix(iX, iY); } BYTE C4Landscape::GetBackMapIndex(int32_t iX, int32_t iY) const { - if (!MapBkg) return 0; - return MapBkg->GetPix(iX,iY); + if (!p->MapBkg) return 0; + return p->MapBkg->GetPix(iX, iY); } -void C4Landscape::PrepareChange(C4Rect BoundingBox) +void C4Landscape::P::PrepareChange(const C4Landscape *d, const C4Rect &BoundingBox) { // move solidmasks out of the way C4Rect SolidMaskRect = BoundingBox; @@ -3558,18 +3887,18 @@ void C4Landscape::PrepareChange(C4Rect BoundingBox) { pSolid->RemoveTemporary(SolidMaskRect); } - UpdateMatCnt(BoundingBox, false); + UpdateMatCnt(d, BoundingBox, false); } -void C4Landscape::FinishChange(C4Rect BoundingBox) +void C4Landscape::P::FinishChange(C4Landscape *d, C4Rect BoundingBox) { // Intersect bounding box with landscape BoundingBox.Intersect(C4Rect(0, 0, Width, Height)); if (!BoundingBox.Wdt || !BoundingBox.Hgt) return; // update render - if(pLandscapeRender) - pLandscapeRender->Update(BoundingBox, this); - UpdateMatCnt(BoundingBox, true); + if (pLandscapeRender) + pLandscapeRender->Update(BoundingBox, d); + UpdateMatCnt(d, BoundingBox, true); // Restore Solidmasks C4Rect SolidMaskRect = BoundingBox; if (pLandscapeRender) @@ -3579,12 +3908,12 @@ void C4Landscape::FinishChange(C4Rect BoundingBox) pSolid->Repair(SolidMaskRect); } C4SolidMask::CheckConsistency(); - UpdatePixCnt(BoundingBox); + UpdatePixCnt(d, BoundingBox); // update FoW if (pFoW) { pFoW->Invalidate(BoundingBox); - pFoW->Ambient.UpdateFromLandscape(*this, BoundingBox); + pFoW->Ambient.UpdateFromLandscape(*d, BoundingBox); } } @@ -3600,9 +3929,9 @@ bool C4Landscape::DrawMap(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, co // clip to landscape size if (!ClipRect(iX, iY, iWdt, iHgt)) return false; // get needed map size - int32_t iMapWdt=(iWdt-1)/MapZoom+1; - int32_t iMapHgt=(iHgt-1)/MapZoom+1; - C4SLandscape FakeLS=Game.C4S.Landscape; + int32_t iMapWdt = (iWdt - 1) / p->MapZoom + 1; + int32_t iMapHgt = (iHgt - 1) / p->MapZoom + 1; + C4SLandscape FakeLS = Game.C4S.Landscape; FakeLS.MapWdt.Set(iMapWdt, 0, iMapWdt, iMapWdt); FakeLS.MapHgt.Set(iMapHgt, 0, iMapHgt, iMapHgt); // create map creator @@ -3615,7 +3944,7 @@ bool C4Landscape::DrawMap(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, co if (!MapCreator.Render(NULL, sfcMap, sfcMapBkg)) return false; // map it to the landscape - bool fSuccess=MapToLandscape(sfcMap, sfcMapBkg, 0, 0, iMapWdt, iMapHgt, iX, iY, ignoreSky); + bool fSuccess = p->MapToLandscape(this, *sfcMap, *sfcMapBkg, 0, 0, iMapWdt, iMapHgt, iX, iY, ignoreSky); // cleanup delete sfcMap; delete sfcMapBkg; @@ -3626,23 +3955,23 @@ bool C4Landscape::DrawMap(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, co bool C4Landscape::DrawDefMap(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, const char *szMapDef, bool ignoreSky) { // safety - if (!szMapDef || !pMapCreator) return false; + if (!szMapDef || !p->pMapCreator) return false; // clip to landscape size if (!ClipRect(iX, iY, iWdt, iHgt)) return false; // get needed map size - int32_t iMapWdt=(iWdt-1)/MapZoom+1; - int32_t iMapHgt=(iHgt-1)/MapZoom+1; - bool fSuccess=false; + int32_t iMapWdt = (iWdt - 1) / p->MapZoom + 1; + int32_t iMapHgt = (iHgt - 1) / p->MapZoom + 1; + bool fSuccess = false; // render map - C4MCMap *pMap=pMapCreator->GetMap(szMapDef); + C4MCMap *pMap = p->pMapCreator->GetMap(szMapDef); if (!pMap) return false; pMap->SetSize(iMapWdt, iMapHgt); CSurface8* sfcMap = NULL; CSurface8* sfcMapBkg = NULL; - if(pMapCreator->Render(szMapDef, sfcMap, sfcMapBkg)) + if (p->pMapCreator->Render(szMapDef, sfcMap, sfcMapBkg)) { // map to landscape - fSuccess = MapToLandscape(sfcMap, sfcMapBkg, 0, 0, iMapWdt, iMapHgt, iX, iY, ignoreSky); + fSuccess = p->MapToLandscape(this, *sfcMap, *sfcMapBkg, 0, 0, iMapWdt, iMapHgt, iX, iY, ignoreSky); // cleanup delete sfcMap; delete sfcMapBkg; @@ -3651,31 +3980,48 @@ bool C4Landscape::DrawDefMap(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, return fSuccess; } +// creates and draws a map section using MapCreatorS2 and a map from the loaded Landscape.txt + +bool C4Landscape::SetModulation(DWORD dwWithClr) // adjust the way the landscape is blitted +{ + p->Modulation = dwWithClr; + return true; +} + +DWORD C4Landscape::GetModulation() const { return p->Modulation; } + bool C4Landscape::ClipRect(int32_t &rX, int32_t &rY, int32_t &rWdt, int32_t &rHgt) const { // clip by bounds - if (rX<0) { rWdt+=rX; rX=0; } - if (rY<0) { rHgt+=rY; rY=0; } + if (rX < 0) { rWdt += rX; rX = 0; } + if (rY < 0) { rHgt += rY; rY = 0; } int32_t iOver; - iOver=rX+rWdt-Width; if (iOver>0) { rWdt-=iOver; } - iOver=rY+rHgt-Height; if (iOver>0) { rHgt-=iOver; } + + iOver = rX + rWdt - GetWidth(); + if (iOver > 0) + rWdt -= iOver; + + iOver = rY + rHgt - GetHeight(); + if (iOver > 0) + rHgt -= iOver; + // anything left inside the bounds? - return rWdt>0 && rHgt>0; + return rWdt > 0 && rHgt > 0; } bool C4Landscape::ReplaceMapColor(BYTE iOldIndex, BYTE iNewIndex) { // find every occurance of iOldIndex in map; replace it by new index - if (!Map) return false; + if (!p->Map) return false; int iPitch, iMapWdt, iMapHgt; - BYTE *pMap = Map->Bits; - iMapWdt = Map->Wdt; - iMapHgt = Map->Hgt; - iPitch = Map->Pitch; + BYTE *pMap = p->Map->Bits; + iMapWdt = p->Map->Wdt; + iMapHgt = p->Map->Hgt; + iPitch = p->Map->Pitch; if (!pMap) return false; - for (int32_t y=0; y(iNewIndex, 1, C4M_MaxTexIndex - 1)) { - DebugLogF("Cannot insert new texture %s to index %d: Invalid parameters.", (const char *) szMatTex, (int) iNewIndex); + DebugLogF("Cannot insert new texture %s to index %d: Invalid parameters.", (const char *)szMatTex, (int)iNewIndex); return false; } // get last mat index - returns zero for not found (valid for insertion mode) @@ -3705,7 +4051,7 @@ bool C4Landscape::SetTextureIndex(const char *szMatTex, BYTE iNewIndex, bool fIn while (::TextureMap.GetEntry(byLastMoveIndex)) if (--byLastMoveIndex == iNewIndex) { - DebugLogF("Cannot insert new texture %s to index %d: No room for insertion.", (const char *) szMatTex, (int) iNewIndex); + DebugLogF("Cannot insert new texture %s to index %d: No room for insertion.", (const char *)szMatTex, (int)iNewIndex); return false; } // then move up all other textures first @@ -3713,8 +4059,8 @@ bool C4Landscape::SetTextureIndex(const char *szMatTex, BYTE iNewIndex, bool fIn while (--byLastMoveIndex >= iNewIndex) if (::TextureMap.GetEntry(byLastMoveIndex)) { - ReplaceMapColor(byLastMoveIndex, byLastMoveIndex+1); - ::TextureMap.MoveIndex(byLastMoveIndex, byLastMoveIndex+1); + ReplaceMapColor(byLastMoveIndex, byLastMoveIndex + 1); + ::TextureMap.MoveIndex(byLastMoveIndex, byLastMoveIndex + 1); } // new insertion desired? if (szMatTex && *szMatTex) @@ -3732,7 +4078,7 @@ bool C4Landscape::SetTextureIndex(const char *szMatTex, BYTE iNewIndex, bool fIn // new insertion if (!::TextureMap.AddEntry(iNewIndex, Material.getData(), Texture.getData())) { - LogF("Cannot insert new texture %s to index %d: Texture map entry error", (const char *) szMatTex, (int) iNewIndex); + LogF("Cannot insert new texture %s to index %d: Texture map entry error", (const char *)szMatTex, (int)iNewIndex); return false; } } @@ -3746,13 +4092,13 @@ bool C4Landscape::SetTextureIndex(const char *szMatTex, BYTE iNewIndex, bool fIn const C4TexMapEntry *pOld; if ((pOld = ::TextureMap.GetEntry(iNewIndex)) && !pOld->isNull()) { - DebugLogF("Cannot move texture %s to index %d: Index occupied by %s-%s.", (const char *) szMatTex, (int) iNewIndex, pOld->GetMaterialName(), pOld->GetTextureName()); + DebugLogF("Cannot move texture %s to index %d: Index occupied by %s-%s.", (const char *)szMatTex, (int)iNewIndex, pOld->GetMaterialName(), pOld->GetTextureName()); return false; } // must only move existing textures if (!iOldIndex) { - DebugLogF("Cannot move texture %s to index %d: Texture not found.", (const char *) szMatTex, (int) iNewIndex); + DebugLogF("Cannot move texture %s to index %d: Texture not found.", (const char *)szMatTex, (int)iNewIndex); return false; } // update map @@ -3764,6 +4110,10 @@ bool C4Landscape::SetTextureIndex(const char *szMatTex, BYTE iNewIndex, bool fIn } } +// change color index of map texture, or insert a new one + +void C4Landscape::SetMapChanged() { p->fMapChanged = true; } + void C4Landscape::RemoveUnusedTexMapEntries() { // check usage in landscape @@ -3771,11 +4121,11 @@ void C4Landscape::RemoveUnusedTexMapEntries() int32_t iMatTex; for (iMatTex = 0; iMatTex < C4M_MaxTexIndex; ++iMatTex) fTexUsage[iMatTex] = false; - for (int32_t y=0; yGetPix(x, y); - const BYTE backPix = Surface8Bkg->GetPix(x, y); + const BYTE pix = p->Surface8->GetPix(x, y); + const BYTE backPix = p->Surface8Bkg->GetPix(x, y); assert(pix < C4M_MaxTexIndex); assert(backPix < C4M_MaxTexIndex); @@ -3800,6 +4150,33 @@ void C4Landscape::RemoveUnusedTexMapEntries() ::TextureMap.fEntriesAdded = true; } +C4Sky & C4Landscape::GetSky() +{ + return p->Sky; +} + +bool C4Landscape::HasFoW() const +{ + return p->pFoW != nullptr; +} + +C4FoW * C4Landscape::GetFoW() +{ + return p->pFoW.get(); +} + +int32_t C4Landscape::GetMatCount(int material) const +{ + assert(material > 0 && material < p->MatCount.size()); + return p->MatCount[material]; +} + +int32_t C4Landscape::GetEffectiveMatCount(int material) const +{ + assert(material > 0 && material < p->EffectiveMatCount.size()); + return p->EffectiveMatCount[material]; +} + /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ /* +++++++++++++++++++++++++++ Update functions ++++++++++++++++++++++++++++ */ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ @@ -3809,31 +4186,27 @@ void C4Landscape::HandleTexMapUpdate() // Pixel maps must be update UpdatePixMaps(); // Update landscape palette - Mat2Pal(); + p->Mat2Pal(); } void C4Landscape::UpdatePixMaps() { int32_t i; - for (i = 0; i < C4M_MaxTexIndex; i++) Pix2Mat[i] = PixCol2Mat(i); - for (i = 0; i < C4M_MaxTexIndex; i++) Pix2Dens[i] = MatDensity(Pix2Mat[i]); - for (i = 0; i < C4M_MaxTexIndex; i++) Pix2Place[i] = MatValid(Pix2Mat[i]) ? ::MaterialMap.Map[Pix2Mat[i]].Placement : 0; - for (i = 0; i < C4M_MaxTexIndex; i++) Pix2Light[i] = MatValid(Pix2Mat[i]) && (::MaterialMap.Map[Pix2Mat[i]].Light>0); - Pix2Place[0] = 0; + for (i = 0; i < C4M_MaxTexIndex; i++) p->Pix2Mat[i] = PixCol2Mat(i); + for (i = 0; i < C4M_MaxTexIndex; i++) p->Pix2Dens[i] = MatDensity(p->Pix2Mat[i]); + for (i = 0; i < C4M_MaxTexIndex; i++) p->Pix2Place[i] = MatValid(p->Pix2Mat[i]) ? ::MaterialMap.Map[p->Pix2Mat[i]].Placement : 0; + for (i = 0; i < C4M_MaxTexIndex; i++) p->Pix2Light[i] = MatValid(p->Pix2Mat[i]) && (::MaterialMap.Map[p->Pix2Mat[i]].Light>0); + p->Pix2Place[0] = 0; // clear bridge mat conversion buffers - for (int32_t i = 0; i < C4M_MaxTexIndex; ++i) - { - delete [] BridgeMatConversion[i]; - BridgeMatConversion[i] = NULL; - } + std::fill(p->BridgeMatConversion.begin(), p->BridgeMatConversion.end(), nullptr); } -bool C4Landscape::Mat2Pal() +bool C4Landscape::P::Mat2Pal() { if (!Surface8 || !Surface8Bkg) return false; // set landscape pal int32_t tex; - for (tex=0; texisNull()) @@ -3848,7 +4221,7 @@ bool C4Landscape::Mat2Pal() } -void C4Landscape::UpdatePixCnt(const C4Rect &Rect, bool fCheck) +void C4Landscape::P::UpdatePixCnt(const C4Landscape *d, const C4Rect &Rect, bool fCheck) { int32_t PixCntWidth = (Width + 16) / 17; for (int32_t y = std::max(0, Rect.y / 15); y < std::min(PixCntPitch, (Rect.y + Rect.Hgt + 14) / 15); y++) @@ -3857,7 +4230,7 @@ void C4Landscape::UpdatePixCnt(const C4Rect &Rect, bool fCheck) int iCnt = 0; for (int32_t x2 = x * 17; x2 < std::min(x * 17 + 17, Width); x2++) for (int32_t y2 = y * 15; y2 < std::min(y * 15 + 15, Height); y2++) - if (_GetDensity(x2, y2)) + if (d->_GetDensity(x2, y2)) iCnt++; if (fCheck) assert(iCnt == PixCnt[x * PixCntPitch + y]); @@ -3865,7 +4238,7 @@ void C4Landscape::UpdatePixCnt(const C4Rect &Rect, bool fCheck) } } -void C4Landscape::UpdateMatCnt(C4Rect Rect, bool fPlus) +void C4Landscape::P::UpdateMatCnt(const C4Landscape *d, C4Rect Rect, bool fPlus) { Rect.Intersect(C4Rect(0, 0, Width, Height)); if (!Rect.Hgt || !Rect.Wdt) return; @@ -3878,9 +4251,9 @@ void C4Landscape::UpdateMatCnt(C4Rect Rect, bool fPlus) int32_t y; for (y = 1; y < Rect.Hgt; y++) { - int32_t iMat = _GetMat(Rect.x+x, Rect.y+y - 1); + int32_t iMat = d->_GetMat(Rect.x + x, Rect.y + y - 1); // Same material? Count it. - if (iMat == _GetMat(Rect.x+x, Rect.y+y)) + if (iMat == d->_GetMat(Rect.x + x, Rect.y + y)) iHgt++; else { @@ -3894,7 +4267,7 @@ void C4Landscape::UpdateMatCnt(C4Rect Rect, bool fPlus) // First chunk? Add any material above when checking chunk height int iAddedHeight = 0; if (Rect.y && iHgt + 1 == y) - iAddedHeight = GetMatHeight(Rect.x+x, Rect.y-1, -1, iMat, iMinHgt); + iAddedHeight = d->GetMatHeight(Rect.x + x, Rect.y - 1, -1, iMat, iMinHgt); // Check the chunk height if (iHgt + 1 + iAddedHeight >= iMinHgt) { @@ -3909,7 +4282,7 @@ void C4Landscape::UpdateMatCnt(C4Rect Rect, bool fPlus) } } // Check last pixel - int32_t iMat = _GetMat(Rect.x+x, Rect.y+Rect.Hgt-1); + int32_t iMat = d->_GetMat(Rect.x + x, Rect.y + Rect.Hgt - 1); if (iMat >= 0) { // Normal material counting @@ -3920,10 +4293,10 @@ void C4Landscape::UpdateMatCnt(C4Rect Rect, bool fPlus) int iAddedHeight1 = 0, iAddedHeight2 = 0; // Add any material above for chunk size check if (Rect.y && iHgt + 1 == Rect.Hgt) - iAddedHeight1 = GetMatHeight(Rect.x+x, Rect.y-1, -1, iMat, iMinHgt); + iAddedHeight1 = d->GetMatHeight(Rect.x + x, Rect.y - 1, -1, iMat, iMinHgt); // Add any material below for chunk size check - if (Rect.y+y < Height) - iAddedHeight2 = GetMatHeight(Rect.x+x, Rect.y+Rect.Hgt, 1, iMat, iMinHgt); + if (Rect.y + y < Height) + iAddedHeight2 = d->GetMatHeight(Rect.x + x, Rect.y + Rect.Hgt, 1, iMat, iMinHgt); // Chunk tall enough? if (iHgt + 1 + iAddedHeight1 + iAddedHeight2 >= ::MaterialMap.Map[iMat].MinHeightCount) { diff --git a/src/landscape/C4Landscape.h b/src/landscape/C4Landscape.h index c78f44b5a..1c6be6a14 100644 --- a/src/landscape/C4Landscape.h +++ b/src/landscape/C4Landscape.h @@ -3,7 +3,7 @@ * * Copyright (c) 1998-2000, Matthes Bender * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/ - * Copyright (c) 2009-2013, The OpenClonk Team and contributors + * Copyright (c) 2009-2016, The OpenClonk Team and contributors * * Distributed under the terms of the ISC license; see accompanying file * "COPYING" for details. @@ -20,61 +20,30 @@ #ifndef INC_C4Landscape #define INC_C4Landscape -#include "C4Sky.h" -#include "C4Shape.h" - -#include -#include +#include "C4Prototypes.h" +#include "C4Constants.h" const int32_t C4MaxMaterial = 125; -const int32_t C4LSC_Undefined = 0, - C4LSC_Dynamic = 1, - C4LSC_Static = 2, - C4LSC_Exact = 3; - const int32_t C4LS_MaxRelights = 50; +enum class LandscapeMode +{ + Undefined = 0, + Dynamic = 1, + Static = 2, + Exact = 3 +}; + class C4Landscape { + struct P; + std::unique_ptr

p; + public: C4Landscape(); ~C4Landscape(); -public: - int32_t Mode; - int32_t Width,Height; - int32_t MapWidth,MapHeight,MapZoom; - DWORD MatCount[C4MaxMaterial]; // NoSave // - DWORD EffectiveMatCount[C4MaxMaterial]; // NoSave // - bool NoScan; // ExecuteScan() disabled - int32_t ScanX,ScanSpeed; // SyncClearance-NoSave // - int32_t LeftOpen,RightOpen,TopOpen,BottomOpen; - C4Real Gravity; - uint32_t Modulation; // landscape blit modulation; 0 means normal - int32_t MapSeed; // random seed for MapToLandscape - C4Sky Sky; - C4MapCreatorS2 *pMapCreator; // map creator for script-generated maps - bool fMapChanged; - BYTE *pInitial; // Initial landscape after creation - used for diff - BYTE *pInitialBkg; // Initial bkg landscape after creation - used for diff - class C4FoW *pFoW; - -private: - CSurface8 * Surface8; - CSurface8 * Surface8Bkg; // Background material - CSurface8 * Map; - CSurface8 * MapBkg; - class C4LandscapeRender *pLandscapeRender; - uint8_t *TopRowPix, *BottomRowPix; // array size of landscape width: Filled with 0s for border pixels that are open and MCVehic for pixels that are closed - int32_t Pix2Mat[C4M_MaxTexIndex], Pix2Dens[C4M_MaxTexIndex], Pix2Place[C4M_MaxTexIndex]; - bool Pix2Light[C4M_MaxTexIndex]; - int32_t PixCntPitch; - uint8_t *PixCnt; - C4Rect Relights[C4LS_MaxRelights]; - mutable uint8_t *BridgeMatConversion[C4M_MaxTexIndex]; // NoSave // - -public: // Use this with the various drawing functions to keep current material for // either foreground or background map. We can use C4M_MaxTexIndex as a value // here because this value is reserved anyway for the differential landscape @@ -85,11 +54,9 @@ public: void Clear(bool fClearMapCreator=true, bool fClearSky=true, bool fClearRenderer=true); void Execute(); void Synchronize(); - void Draw(C4TargetFacet &cgo, class C4FoWRegion *pLight = NULL); + void Draw(C4TargetFacet &cgo, class C4FoWRegion *pLight = nullptr); void ScenarioInit(); - void ClearRectDensity(int32_t iTx, int32_t iTy, int32_t iWdt, int32_t iHgt, int32_t iOfDensity); - void ClearMatCount(); void ScanSideOpen(); void DrawMaterialRect(int32_t mat, int32_t tx, int32_t ty, int32_t wdt, int32_t hgt); @@ -105,10 +72,13 @@ public: bool SaveInitial(); bool SaveTextures(C4Group &hGroup) const; bool Init(C4Group &hGroup, bool fOverloadCurrent, bool fLoadSky, bool &rfLoaded, bool fSavegame); - bool HasMap() const { return Map != NULL && MapBkg != NULL; } + bool HasMap() const; bool MapToLandscape(); bool ApplyDiff(C4Group &hGroup); - bool SetMode(int32_t iMode); + + void SetMode(LandscapeMode iMode); + LandscapeMode GetMode() const; + bool SetPix2(int32_t x, int32_t y, BYTE fgPix, BYTE bgPix); // set landscape pixel (bounds checked) bool _SetPix2(int32_t x, int32_t y, BYTE fgPix, BYTE bgPix); // set landsape pixel (bounds not checked) void _SetPix2Tmp(int32_t x, int32_t y, BYTE fgPix, BYTE bgPix); // set landsape pixel (bounds not checked, no material count updates, no landscape relighting). Material must be reset to original value with this function before modifying landscape in any other way. Only used for temporary pixel changes by SolidMask (C4SolidMask::RemoveTemporary, C4SolidMask::PutTemporary). @@ -125,138 +95,40 @@ public: bool DrawChunks(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, int32_t icntx, int32_t icnty, const char *szMaterial, const char *szTexture, bool bIFT); bool DrawQuad(int32_t iX1, int32_t iY1, int32_t iX2, int32_t iY2, int32_t iX3, int32_t iY3, int32_t iX4, int32_t iY4, const char *szMaterial, const char *szBackMaterial, bool fDrawBridge); bool DrawPolygon(int *vtcs, int length, const char *szMaterial, const char *szBackMaterial, bool fDrawBridge); - CStdPalette *GetPal() const { return Surface8 ? Surface8->pPal : NULL; } - inline BYTE _GetPix(int32_t x, int32_t y) const // get landscape pixel (bounds not checked) - { -#ifdef _DEBUG - if (x<0 || y<0 || x>=Width || y>=Height) { BREAKPOINT_HERE; } -#endif - return Surface8->_GetPix(x,y); - } - inline BYTE GetPix(int32_t x, int32_t y) const // get landscape pixel (bounds checked) - { - extern BYTE MCVehic; - // Border checks - if (x<0) - { - if (y(x) >= static_cast(Width)) - { - if (y(y) >= static_cast(Height)) - { - return BottomRowPix[x]; - } - return Surface8->_GetPix(x,y); - } - inline int32_t _GetMat(int32_t x, int32_t y) const // get landscape material (bounds not checked) - { - return Pix2Mat[_GetPix(x, y)]; - } - inline int32_t _GetDensity(int32_t x, int32_t y) const // get landscape density (bounds not checked) - { - return Pix2Dens[_GetPix(x, y)]; - } - inline int32_t _GetPlacement(int32_t x, int32_t y) const // get landscape material placement (bounds not checked) - { - return Pix2Place[_GetPix(x, y)]; - } - inline int32_t GetMat(int32_t x, int32_t y) const // get landscape material (bounds checked) - { - return Pix2Mat[GetPix(x, y)]; - } - inline int32_t GetDensity(int32_t x, int32_t y) const // get landscape density (bounds checked) - { - return Pix2Dens[GetPix(x, y)]; - } - inline int32_t GetPlacement(int32_t x, int32_t y) const // get landscape material placement (bounds checked) - { - return Pix2Place[GetPix(x, y)]; - } + CStdPalette *GetPal() const; + + int32_t GetWidth() const; + int32_t GetHeight() const; + int32_t GetMapZoom() const; + C4Real GetGravity() const; + void SetGravity(C4Real g); - inline BYTE _GetBackPix(int32_t x, int32_t y) const // get landscape pixel (bounds not checked) - { -#ifdef _DEBUG - if (x<0 || y<0 || x>=Width || y>=Height) { BREAKPOINT_HERE; } -#endif - return Surface8Bkg->_GetPix(x,y); - } - inline BYTE GetBackPix(int32_t x, int32_t y) const // get landscape pixel (bounds checked) - { - // Border checks - if (x<0) - { - if (y(x) >= static_cast(Width)) - { - if (y(y) >= static_cast(Height)) - { - return DefaultBkgMat(BottomRowPix[x]); - } + BYTE _GetPix(int32_t x, int32_t y) const; // get landscape pixel (bounds not checked) + BYTE GetPix(int32_t x, int32_t y) const; + + int32_t _GetMat(int32_t x, int32_t y) const; + int32_t _GetDensity(int32_t x, int32_t y) const; + int32_t _GetPlacement(int32_t x, int32_t y) const; + int32_t GetMat(int32_t x, int32_t y) const; + int32_t GetDensity(int32_t x, int32_t y) const; + int32_t GetPlacement(int32_t x, int32_t y) const; - return Surface8Bkg->_GetPix(x,y); - } - inline int32_t _GetBackMat(int32_t x, int32_t y) const // get landscape material (bounds not checked) - { - return Pix2Mat[_GetBackPix(x, y)]; - } - inline int32_t _GetBackDensity(int32_t x, int32_t y) const // get landscape density (bounds not checked) - { - return Pix2Dens[_GetBackPix(x, y)]; - } - inline int32_t _GetBackPlacement(int32_t x, int32_t y) const // get landscape material placement (bounds not checked) - { - return Pix2Place[_GetBackPix(x, y)]; - } - inline int32_t GetBackMat(int32_t x, int32_t y) const // get landscape material (bounds checked) - { - return Pix2Mat[GetBackPix(x, y)]; - } - inline int32_t GetBackDensity(int32_t x, int32_t y) const // get landscape density (bounds checked) - { - return Pix2Dens[GetBackPix(x, y)]; - } - inline int32_t GetBackPlacement(int32_t x, int32_t y) const // get landscape material placement (bounds checked) - { - return Pix2Place[GetBackPix(x, y)]; - } + BYTE _GetBackPix(int32_t x, int32_t y) const; + BYTE GetBackPix(int32_t x, int32_t y) const; + int32_t _GetBackMat(int32_t x, int32_t y) const; + int32_t _GetBackDensity(int32_t x, int32_t y) const; + int32_t _GetBackPlacement(int32_t x, int32_t y) const; + int32_t GetBackMat(int32_t x, int32_t y) const; + int32_t GetBackDensity(int32_t x, int32_t y) const; + int32_t GetBackPlacement(int32_t x, int32_t y) const; - inline bool GetLight(int32_t x, int32_t y) - { - return GetBackPix(x, y) == 0 || Pix2Light[GetPix(x, y)]; - } - inline bool _GetLight(int32_t x, int32_t y) - { - return _GetBackPix(x, y) == 0 || Pix2Light[_GetPix(x, y)]; - } + bool GetLight(int32_t x, int32_t y); + bool _GetLight(int32_t x, int32_t y); - inline bool _FastSolidCheck(int32_t x, int32_t y) const // checks whether there *might* be something solid at the point - { - return PixCnt[(x / 17) * PixCntPitch + (y / 15)] > 0; - } - static inline int32_t FastSolidCheckNextX(int32_t x) - { - return (x / 17) * 17 + 17; - } - inline int32_t GetPixMat(BYTE byPix) const { return Pix2Mat[byPix]; } - inline int32_t GetPixDensity(BYTE byPix) const { return Pix2Dens[byPix]; } + bool _FastSolidCheck(int32_t x, int32_t y) const; + static int32_t FastSolidCheckNextX(int32_t x); + int32_t GetPixMat(BYTE byPix) const; + int32_t GetPixDensity(BYTE byPix) const; bool _PathFree(int32_t x, int32_t y, int32_t x2, int32_t y2) const; // quickly checks wether there *might* be pixel in the path. int32_t GetMatHeight(int32_t x, int32_t y, int32_t iYDir, int32_t iMat, int32_t iMax) const; @@ -265,49 +137,25 @@ public: bool DrawMap(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, const char *szMapDef, bool ignoreSky = false); // creates and draws a map section using MapCreatorS2 bool ClipRect(int32_t &rX, int32_t &rY, int32_t &rWdt, int32_t &rHgt) const; // clip given rect by landscape size; return whether anything is left unclipped bool DrawDefMap(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, const char *szMapDef, bool ignoreSky = false); // creates and draws a map section using MapCreatorS2 and a map from the loaded Landscape.txt - bool SetModulation(DWORD dwWithClr) // adjust the way the landscape is blitted - { Modulation=dwWithClr; return true; } - DWORD GetModulation() const { return Modulation; } + bool SetModulation(DWORD dwWithClr); + DWORD GetModulation() const; bool PostInitMap(); // do script callbacks of MapCreatorS2 in finished landscape bool ReplaceMapColor(BYTE iOldIndex, BYTE iNewIndex); // find every occurance of iOldIndex in map; replace it by new index bool SetTextureIndex(const char *szMatTex, BYTE iNewIndex, bool fInsert); // change color index of map texture, or insert a new one - void SetMapChanged() { fMapChanged = true; } + void SetMapChanged(); void HandleTexMapUpdate(); void UpdatePixMaps(); bool DoRelights(); void RemoveUnusedTexMapEntries(); -private: - void ExecuteScan(); - int32_t DoScan(int32_t x, int32_t y, int32_t mat, int32_t dir); - uint32_t ChunkyRandom(uint32_t &iOffset, uint32_t iRange) const; // return static random value, according to offset and MapSeed - void DrawChunk(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, uint8_t mcol, uint8_t mcolBkg, C4MaterialCoreShape Shape, uint32_t cro); - void DrawSmoothOChunk(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, uint8_t mcol, uint8_t mcolBkg, int flip, uint32_t cro); - void ChunkOZoom(CSurface8 * sfcMap, CSurface8* sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, uint8_t iTexture, int32_t iOffX=0,int32_t iOffY=0); - bool GetTexUsage(CSurface8 * sfcMap, CSurface8* sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, DWORD *dwpTextureUsage) const; - bool TexOZoom(CSurface8 * sfcMap, CSurface8* sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, DWORD *dwpTextureUsage, int32_t iToX=0,int32_t iToY=0); - bool MapToSurface(CSurface8 * sfcMap, CSurface8* sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, int32_t iToX, int32_t iToY, int32_t iToWdt, int32_t iToHgt, int32_t iOffX, int32_t iOffY); - bool MapToLandscape(CSurface8 * sfcMap, CSurface8* sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, int32_t iOffsX = 0, int32_t iOffsY = 0, bool noClear = false); // zoom map segment to surface (or sector surfaces) - bool InitTopAndBottomRowPix(); // inti out-of-landscape pixels for bottom side - bool GetMapColorIndex(const char *szMaterial, const char *szTexture, BYTE &rbyCol) const; - bool SkyToLandscape(int32_t iToX, int32_t iToY, int32_t iToWdt, int32_t iToHgt, int32_t iOffX, int32_t iOffY); - bool CreateMap(CSurface8*& sfcMap, CSurface8*& sfcMapBkg); // create map by landscape attributes - bool CreateMapS2(C4Group &ScenFile, CSurface8*& sfcMap, CSurface8*& sfcMapBkg); // create map by def file - bool Mat2Pal(); // assign material colors to landscape palette - void UpdatePixCnt(const class C4Rect &Rect, bool fCheck = false); - void UpdateMatCnt(C4Rect Rect, bool fPlus); - void PrepareChange(C4Rect BoundingBox); - void FinishChange(C4Rect BoundingBox); - bool DrawLineLandscape(int32_t iX, int32_t iY, int32_t iGrade, uint8_t line_color, uint8_t line_color_bkg); - bool DrawLineMap(int32_t iX, int32_t iY, int32_t iRadius, uint8_t line_color, uint8_t line_color_bkg); - uint8_t *GetBridgeMatConversion(int32_t for_material_col) const; - bool SaveInternal(C4Group &hGroup) const; - bool SaveDiffInternal(C4Group &hGroup, bool fSyncSave) const; + class C4Sky &GetSky(); - int32_t ForPolygon(int *vtcs, int length, bool (C4Landscape::*fnCallback)(int32_t, int32_t), - C4MaterialList *mats_count = NULL, uint8_t col = 0, uint8_t colBkg = 0, uint8_t *conversion_table = NULL); + bool HasFoW() const; + class C4FoW *GetFoW(); + + int32_t GetMatCount(int material) const; + int32_t GetEffectiveMatCount(int material) const; -public: int32_t DigFreeShape(int *vtcs, int length, C4Object *by_object = NULL, bool no_dig2objects = false, bool no_instability_check = false); void BlastFreeShape(int *vtcs, int length, C4Object *by_object = NULL, int32_t by_player = NO_OWNER, int32_t iMaxDensity = C4M_Vehicle); @@ -322,21 +170,8 @@ public: bool ClearPix(int32_t tx, int32_t ty); // also used by mass mover (corrode) -private: - CSurface8* CreateDefaultBkgSurface(CSurface8& sfcFg, bool msbAsIft) const; - void DigMaterial2Objects(int32_t tx, int32_t ty, C4MaterialList *mat_list, C4Object *pCollect = NULL); - void BlastMaterial2Objects(int32_t tx, int32_t ty, C4MaterialList *mat_list, int32_t caused_by, int32_t str, C4ValueArray *out_objects); + void ClearPointers(C4Object *pObj); - bool DigFreePix(int32_t tx, int32_t ty); - bool DigFreePixNoInstability(int32_t tx, int32_t ty); - bool BlastFreePix(int32_t tx, int32_t ty); - bool ShakeFreePix(int32_t tx, int32_t ty); - - C4ValueArray *PrepareFreeShape(C4Rect &BoundingBox, C4Object *by_object); - void PostFreeShape(C4ValueArray *dig_objects, C4Object *by_object); - BYTE DefaultBkgMat(BYTE fg) const; - -public: void CompileFunc(StdCompiler *pComp); // without landscape bitmaps and sky }; @@ -361,12 +196,6 @@ bool FindClosestFree(int32_t &rX, int32_t &rY, int32_t iAngle1, int32_t iAngle2, bool ConstructionCheck(C4PropList *, int32_t iX, int32_t iY, C4Object *pByObj=NULL); int32_t PixCol2Mat(BYTE pixc); -#define GBackWdt ::Landscape.Width -#define GBackHgt ::Landscape.Height -#define GBackPix ::Landscape.GetPix -#define ClearBackPix ::Landscape.ClearPix -#define _GBackPix ::Landscape._GetPix - inline bool DensitySolid(int32_t dens) { return (dens>=C4M_Solid); diff --git a/src/landscape/C4MassMover.cpp b/src/landscape/C4MassMover.cpp index 30cff7e68..9c0144ce7 100644 --- a/src/landscape/C4MassMover.cpp +++ b/src/landscape/C4MassMover.cpp @@ -100,7 +100,7 @@ void C4MassMoverSet::Draw() bool C4MassMover::Init(int32_t tx, int32_t ty) { // Out of bounds check - if (!Inside(tx,0,GBackWdt-1) || !Inside(ty,0,GBackHgt-1)) + if (!Inside(tx,0,::Landscape.GetWidth()-1) || !Inside(ty,0,::Landscape.GetHeight()-1)) return false; // Check mat Mat=GBackMat(tx,ty); diff --git a/src/landscape/C4Material.cpp b/src/landscape/C4Material.cpp index c9f2c2f14..34ddf75dc 100644 --- a/src/landscape/C4Material.cpp +++ b/src/landscape/C4Material.cpp @@ -816,7 +816,7 @@ bool C4MaterialMap::mrfCorrode(C4MaterialReaction *pReaction, int32_t &iX, int32 fDoCorrode = (d100 < ::MaterialMap.Map[iPxsMat].Corrosive) && (d100 < ::MaterialMap.Map[iLsMat].Corrode); if (fDoCorrode) { - ClearBackPix(iLSPosX,iLSPosY); + ::Landscape.ClearPix(iLSPosX,iLSPosY); //::Landscape.CheckInstabilityRange(iLSPosX,iLSPosY); - more correct, but makes acid too effective as well if (!Random(5)) { @@ -843,7 +843,7 @@ bool C4MaterialMap::mrfCorrode(C4MaterialReaction *pReaction, int32_t &iX, int32 fDoCorrode = (d100 < ::MaterialMap.Map[iPxsMat].Corrosive) && (d100 < ::MaterialMap.Map[iLsMat].Corrode); if (fDoCorrode) { - ClearBackPix(iLSPosX,iLSPosY); + ::Landscape.ClearPix(iLSPosX,iLSPosY); ::Landscape.CheckInstabilityRange(iLSPosX,iLSPosY); if (!Random(5)) { diff --git a/src/landscape/C4PXS.cpp b/src/landscape/C4PXS.cpp index 768d950cc..3d4e83803 100644 --- a/src/landscape/C4PXS.cpp +++ b/src/landscape/C4PXS.cpp @@ -48,7 +48,7 @@ void C4PXS::Execute() { Deactivate(); return; } // Out of bounds - if ((x<0) || (x>=GBackWdt) || (y<-10) || (y>=GBackHgt)) + if ((x<0) || (x>=::Landscape.GetWidth()) || (y<-10) || (y>=::Landscape.GetHeight())) { Deactivate(); return; } // Material conversion @@ -80,7 +80,7 @@ void C4PXS::Execute() int32_t iToX = fixtoi(ctcox), iToY = fixtoi(ctcoy); // In bounds? - if (Inside(iToX, 0, GBackWdt-1) && Inside(iToY, 0, GBackHgt-1)) + if (Inside(iToX, 0, ::Landscape.GetWidth()-1) && Inside(iToY, 0, ::Landscape.GetHeight()-1)) // Check path if (::Landscape._PathFree(iX, iY, iToX, iToY)) { diff --git a/src/landscape/C4Particles.cpp b/src/landscape/C4Particles.cpp index 0ae320824..850f3f743 100644 --- a/src/landscape/C4Particles.cpp +++ b/src/landscape/C4Particles.cpp @@ -534,7 +534,7 @@ float C4ParticleValueProvider::Wind(C4Particle *forParticle) float C4ParticleValueProvider::Gravity(C4Particle *forParticle) { - return startValue + (speedFactor * ::Landscape.Gravity); + return startValue + (speedFactor * ::Landscape.GetGravity()); } void C4ParticleValueProvider::SetType(C4ParticleValueProviderID what) diff --git a/src/landscape/C4Sky.cpp b/src/landscape/C4Sky.cpp index c84fd6f53..2d4e08862 100644 --- a/src/landscape/C4Sky.cpp +++ b/src/landscape/C4Sky.cpp @@ -215,7 +215,7 @@ void C4Sky::Draw(C4TargetFacet &cgo) DWORD C4Sky::GetSkyFadeClr(int32_t iY) { - int32_t iPos2=(iY*256)/GBackHgt; int32_t iPos1=256-iPos2; + int32_t iPos2=(iY*256)/::Landscape.GetHeight(); int32_t iPos1=256-iPos2; return (((((FadeClr1&0xff00ff)*iPos1 + (FadeClr2&0xff00ff)*iPos2) & 0xff00ff00) | (((FadeClr1&0x00ff00)*iPos1 + (FadeClr2&0x00ff00)*iPos2) & 0x00ff0000))>>8) | (FadeClr1 & 0xff000000); diff --git a/src/landscape/C4SolidMask.cpp b/src/landscape/C4SolidMask.cpp index ecc956596..4f5b122b2 100644 --- a/src/landscape/C4SolidMask.cpp +++ b/src/landscape/C4SolidMask.cpp @@ -25,6 +25,8 @@ #include #include #include +#include "graphics/CSurface8.h" +#include "landscape/C4Material.h" void C4SolidMask::Put(bool fCauseInstability, C4TargetRect *pClipRect, bool fRestoreAttachment) @@ -75,8 +77,8 @@ void C4SolidMask::Put(bool fCauseInstability, C4TargetRect *pClipRect, bool fRes MaskPutRect.y = oy; if (MaskPutRect.y < 0) { MaskPutRect.ty = -MaskPutRect.y; MaskPutRect.y = 0; } else MaskPutRect.ty = 0; - MaskPutRect.Wdt = std::min(ox + pForObject->SolidMask.Wdt, GBackWdt) - MaskPutRect.x; - MaskPutRect.Hgt = std::min(oy + pForObject->SolidMask.Hgt, GBackHgt) - MaskPutRect.y; + MaskPutRect.Wdt = std::min(ox + pForObject->SolidMask.Wdt, ::Landscape.GetWidth()) - MaskPutRect.x; + MaskPutRect.Hgt = std::min(oy + pForObject->SolidMask.Hgt, ::Landscape.GetHeight()) - MaskPutRect.y; } // fill rect with mask for (ycnt=0; ycntHgt; ++ycnt) @@ -93,7 +95,7 @@ void C4SolidMask::Put(bool fCauseInstability, C4TargetRect *pClipRect, bool fRes if (!MaskPut) { // get background pixel - byPixel=GBackPix(iTx,iTy); + byPixel=::Landscape.GetPix(iTx,iTy); // store it. If MCVehic, also store in initial put, but won't be used in restore // do not overwrite current value in re-put issued by SolidMask-remover if (!IsSomeVehicle(byPixel) || RegularPut) @@ -128,8 +130,8 @@ void C4SolidMask::Put(bool fCauseInstability, C4TargetRect *pClipRect, bool fRes MaskPutRect.y = ystart; if (MaskPutRect.y < 0) { MaskPutRect.ty = -MaskPutRect.y; MaskPutRect.Hgt = MaskPutRect.y; MaskPutRect.y = 0; } else { MaskPutRect.ty = 0; MaskPutRect.Hgt = 0; } - MaskPutRect.Wdt = std::min(xstart + MatBuffPitch, GBackWdt) - MaskPutRect.x; - MaskPutRect.Hgt = std::min(ystart + MatBuffPitch, GBackHgt) - MaskPutRect.y; + MaskPutRect.Wdt = std::min(xstart + MatBuffPitch, ::Landscape.GetWidth()) - MaskPutRect.x; + MaskPutRect.Hgt = std::min(ystart + MatBuffPitch, ::Landscape.GetHeight()) - MaskPutRect.y; } // go through clipping rect const C4Real y0 = itofix(pClipRect->ty - MatBuffPitch/2); @@ -159,7 +161,7 @@ void C4SolidMask::Put(bool fCauseInstability, C4TargetRect *pClipRect, bool fRes if (!MaskPut) { // get background pixel - byPixel=_GBackPix(iTx,iTy); + byPixel=::Landscape._GetPix(iTx,iTy); // store it. If MCVehic, also store in initial put, but won't be used in restore // do not overwrite current value in re-put issued by SolidMask-remover if (!IsSomeVehicle(byPixel) || RegularPut) @@ -259,7 +261,7 @@ void C4SolidMask::Remove(bool fBackupAttachment) // The pPix-check ensures that only pixels that hads been overwritten by this SolidMask are restored // Non-SolidMask-pixels should not happen here, because all relevant landscape change routines should // temp remove SolidMasks before - assert(IsSomeVehicle(_GBackPix(iTx,iTy))); + assert(IsSomeVehicle(::Landscape._GetPix(iTx,iTy))); if (IsSomeVehicle(::Landscape._GetPix(iTx, iTy))) ::Landscape._SetPix2(iTx, iTy, *pPix, ::Landscape.Transparent); // Instability @@ -353,7 +355,7 @@ void C4SolidMask::RemoveTemporary(C4Rect where) if (*pPix != MCVehic) // { // restore - assert(IsSomeVehicle(GBackPix(x,y))); + assert(IsSomeVehicle(::Landscape.GetPix(x,y))); ::Landscape._SetPix2Tmp(x, y, *pPix, ::Landscape.Transparent); } } @@ -374,7 +376,7 @@ void C4SolidMask::PutTemporary(C4Rect where) if (*pPix != MCVehic) { // put - assert(GBackPix(x,y)==*pPix); + assert(::Landscape.GetPix(x,y)==*pPix); ::Landscape._SetPix2Tmp(x, y, MaskMaterial, ::Landscape.Transparent); } } @@ -395,7 +397,7 @@ void C4SolidMask::Repair(C4Rect where) if (*pPix != MCVehic) { // record changed landscape in MatBuff - *pPix = GBackPix(x,y); + *pPix = ::Landscape.GetPix(x,y); // put ::Landscape.SetPix2(x, y, MaskMaterial, ::Landscape.Transparent); } @@ -439,7 +441,7 @@ C4SolidMask::~C4SolidMask() void C4SolidMask::RemoveSolidMasks() { - C4Rect SolidMaskRect(0,0,GBackWdt,GBackHgt); + C4Rect SolidMaskRect(0,0,::Landscape.GetWidth(),::Landscape.GetHeight()); C4SolidMask *pSolid; for (pSolid = C4SolidMask::Last; pSolid; pSolid = pSolid->Prev) { @@ -449,7 +451,7 @@ void C4SolidMask::RemoveSolidMasks() void C4SolidMask::PutSolidMasks() { - C4Rect SolidMaskRect(0,0,GBackWdt,GBackHgt); + C4Rect SolidMaskRect(0,0,::Landscape.GetWidth(),::Landscape.GetHeight()); C4SolidMask *pSolid; // Restore Solidmasks for (pSolid = C4SolidMask::First; pSolid; pSolid = pSolid->Next) @@ -467,7 +469,7 @@ C4SolidMask * C4SolidMask::Last = 0; bool C4SolidMask::CheckConsistency() { assert(IsSomeVehicle(MaskMaterial)); - C4Rect SolidMaskRect(0,0,GBackWdt,GBackHgt); + C4Rect SolidMaskRect(0,0,::Landscape.GetWidth(),::Landscape.GetHeight()); C4SolidMask *pSolid; for (pSolid = C4SolidMask::Last; pSolid; pSolid = pSolid->Prev) { diff --git a/src/landscape/C4TextureShape.cpp b/src/landscape/C4TextureShape.cpp index 161519c46..7bb960ac0 100644 --- a/src/landscape/C4TextureShape.cpp +++ b/src/landscape/C4TextureShape.cpp @@ -175,7 +175,7 @@ void C4TextureShapeActivationMap::Add(int32_t block_x, int32_t block_y, int32_t } -void C4TextureShape::Draw(CSurface8 * sfcMap, CSurface8* sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, uint8_t iTexture, int32_t iOffX, int32_t iOffY, int32_t MapZoom, int32_t min_overlap_ratio) +void C4TextureShape::Draw(const CSurface8 &sfcMap, const CSurface8 &sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, uint8_t iTexture, int32_t iOffX, int32_t iOffY, int32_t MapZoom, int32_t min_overlap_ratio) { // Safety if (!num_shapes) return; @@ -183,8 +183,8 @@ void C4TextureShape::Draw(CSurface8 * sfcMap, CSurface8* sfcMapBkg, int32_t iMap // Add max polygon size because polygons may extent far onto outside pixels int32_t x0 = std::max(0, iMapX*MapZoom + iOffX - GetMaxPolyWidth()), y0 = std::max(0, iMapY*MapZoom + iOffY - GetMaxPolyHeight()); - int32_t x1 = std::min(::Landscape.Width, x0 + iMapWdt*MapZoom + GetMaxPolyWidth() * 2), - y1 = std::min(::Landscape.Height, y0 + iMapHgt*MapZoom + GetMaxPolyHeight() * 2); + int32_t x1 = std::min(::Landscape.GetWidth(), x0 + iMapWdt*MapZoom + GetMaxPolyWidth() * 2), + y1 = std::min(::Landscape.GetHeight(), y0 + iMapHgt*MapZoom + GetMaxPolyHeight() * 2); // Range in shape blocks. // A shape block is the coverage of the size of one loaded shape data surface int32_t rblock_x0 = x0 / data.Wdt; @@ -202,11 +202,11 @@ void C4TextureShape::Draw(CSurface8 * sfcMap, CSurface8* sfcMapBkg, int32_t iMap { for (int32_t map_x = iMapX; map_x < iMapX + iMapWdt; ++map_x) { - if (sfcMap->GetPix(map_x, map_y) == iTexture) + if (sfcMap.GetPix(map_x, map_y) == iTexture) { // Here we have a pixel of the texture drawn in this shape // Find all shapes covered by this map pixel and remember background pixel for them - const BYTE pixBkg = sfcMapBkg->GetPix(map_x, map_y); + const BYTE pixBkg = sfcMapBkg.GetPix(map_x, map_y); // Find all shape blocks to be checked int32_t px_check_rate = 1; // sample rate to check coverage, in pixels. Could also increase this if it turns out to be a bottleneck for (int32_t pxo_y = 0; pxo_y < MapZoom; pxo_y += px_check_rate) diff --git a/src/landscape/C4TextureShape.h b/src/landscape/C4TextureShape.h index c29a7a322..9e9169b13 100644 --- a/src/landscape/C4TextureShape.h +++ b/src/landscape/C4TextureShape.h @@ -45,7 +45,7 @@ public: int32_t GetMaxPolyWidth() const { return GetWidth() / 4; } int32_t GetMaxPolyHeight() const { return GetHeight() / 4; } - void Draw(CSurface8 * sfcMap, CSurface8* sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, uint8_t iTexture, int32_t iOffX, int32_t iOffY, int32_t MapZoom, int32_t min_overlap_ratio); + void Draw(const CSurface8 &sfcMap, const CSurface8 &sfcMapBkg, int32_t iMapX, int32_t iMapY, int32_t iMapWdt, int32_t iMapHgt, uint8_t iTexture, int32_t iOffX, int32_t iOffY, int32_t MapZoom, int32_t min_overlap_ratio); }; #endif diff --git a/src/landscape/fow/C4FoWAmbient.cpp b/src/landscape/fow/C4FoWAmbient.cpp index 3eeeda654..67fcbc71a 100644 --- a/src/landscape/fow/C4FoWAmbient.cpp +++ b/src/landscape/fow/C4FoWAmbient.cpp @@ -70,8 +70,8 @@ struct LightMapZoom { bool operator()(int x, int y) const { // Landscape coordinates - const int lx = Clamp(static_cast((x + 0.5) * sx), 0, Landscape.Width - 1); - const int ly = Clamp(static_cast((y + 0.5) * sy), 0, Landscape.Height - 1); + const int lx = Clamp(static_cast((x + 0.5) * sx), 0, Landscape.GetWidth() - 1); + const int ly = Clamp(static_cast((y + 0.5) * sy), 0, Landscape.GetHeight() - 1); // LightMap check return ::Landscape._GetLight(lx, ly); } @@ -124,8 +124,8 @@ void C4FoWAmbient::CreateFromLandscape(const C4Landscape& landscape, double reso FullCoverage = full_coverage; // Number of zoomed pixels - LandscapeX = landscape.Width; - LandscapeY = landscape.Height; + LandscapeX = Landscape.GetWidth(); + LandscapeY = Landscape.GetHeight(); SizeX = std::min(static_cast(ceil(LandscapeX / resolution)), pDraw->MaxTexSize); SizeY = std::min(static_cast(ceil(LandscapeY / resolution)), pDraw->MaxTexSize); @@ -139,7 +139,7 @@ void C4FoWAmbient::CreateFromLandscape(const C4Landscape& landscape, double reso glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, SizeX, SizeY, 0, GL_RED, GL_FLOAT, NULL); const C4TimeMilliseconds begin = C4TimeMilliseconds::Now(); - UpdateFromLandscape(landscape, C4Rect(0, 0, landscape.Width, landscape.Height)); + UpdateFromLandscape(landscape, C4Rect(0, 0, Landscape.GetWidth(), Landscape.GetHeight())); uint32_t dt = C4TimeMilliseconds::Now() - begin; LogF("Created %ux%u ambient map in %g secs", SizeX, SizeY, dt / 1000.); #endif @@ -154,8 +154,8 @@ void C4FoWAmbient::UpdateFromLandscape(const C4Landscape& landscape, const C4Rec assert(Tex != 0); // Factor to go from zoomed to landscape coordinates - const double zoom_x = static_cast(landscape.Width) / SizeX; - const double zoom_y = static_cast(landscape.Height) / SizeY; + const double zoom_x = static_cast(Landscape.GetWidth()) / SizeX; + const double zoom_y = static_cast(Landscape.GetHeight()) / SizeY; // Update region in zoomed coordinates const unsigned int left = std::max(static_cast( (update.x - Radius) / zoom_x), 0); const unsigned int right = std::min(static_cast( (update.x + update.Wdt + Radius) / zoom_x), SizeX - 1) + 1; diff --git a/src/landscape/fow/C4FoWAmbient.h b/src/landscape/fow/C4FoWAmbient.h index 7603f69d6..5e80c1962 100644 --- a/src/landscape/fow/C4FoWAmbient.h +++ b/src/landscape/fow/C4FoWAmbient.h @@ -17,6 +17,9 @@ #define C4FOWAMBIENT_H #include +#ifndef USE_CONSOLE +#include +#endif /** This class manages a texture that holds the ambient light intensity @@ -62,7 +65,7 @@ public: void UpdateFromLandscape(const C4Landscape& landscape, const C4Rect& update); // Fills a 2x3 matrix to transform fragment coordinates to ambient map texture coordinates - void GetFragTransform(const FLOAT_RECT& vpRect, const C4Rect& clipRect, const C4Rect& outRect, float ambientTransform[6]) const; + void GetFragTransform(const struct FLOAT_RECT& vpRect, const C4Rect& clipRect, const C4Rect& outRect, float ambientTransform[6]) const; unsigned int GetLandscapeWidth() const { return LandscapeX; } unsigned int GetLandscapeHeight() const { return LandscapeY; } diff --git a/src/landscape/fow/C4FoWLightSection.cpp b/src/landscape/fow/C4FoWLightSection.cpp index 62c0eb64f..8e37c57ed 100644 --- a/src/landscape/fow/C4FoWLightSection.cpp +++ b/src/landscape/fow/C4FoWLightSection.cpp @@ -134,7 +134,7 @@ void C4FoWLightSection::Update(C4Rect RectIn) { // Transform rectangle into our coordinate system C4Rect Rect = rtransRect(RectIn); - C4Rect Bounds = rtransRect(C4Rect(0,0,GBackWdt,GBackHgt)); + C4Rect Bounds = rtransRect(C4Rect(0,0,::Landscape.GetWidth(),::Landscape.GetHeight())); #ifdef LIGHT_DEBUG if (!::Game.iTick255) { diff --git a/src/mape/cpp-handles/landscape-handle.cpp b/src/mape/cpp-handles/landscape-handle.cpp index 99c725526..d79a46d0d 100644 --- a/src/mape/cpp-handles/landscape-handle.cpp +++ b/src/mape/cpp-handles/landscape-handle.cpp @@ -14,13 +14,48 @@ */ #include "C4Include.h" +#include -#include "C4Landscape.h" -#include "C4Texture.h" +#include "graphics/CSurface8.h" +#include "landscape/C4Landscape.h" +#include "landscape/C4Texture.h" /* This is a small part of the implementation of C4Landscape for what is * required by mape. We cannot link the full implementation since it would * introduce a dependency on C4Game, and therefore the rest of the engine. */ + +struct C4Landscape::P +{ + int32_t Pix2Mat[C4M_MaxTexIndex], Pix2Dens[C4M_MaxTexIndex], Pix2Place[C4M_MaxTexIndex]; + bool Pix2Light[C4M_MaxTexIndex]; + mutable std::array, C4M_MaxTexIndex> BridgeMatConversion; + int32_t Width = 0, Height = 0; + std::unique_ptr Surface8; +}; + +C4Landscape::C4Landscape() : p(new P) {} +C4Landscape::~C4Landscape() {} +bool C4Landscape::FindMatSlide(int&, int&, int, int, int) const { return false; } +int32_t C4Landscape::ExtractMaterial(int32_t, int32_t, bool) { return 0; } +bool C4Landscape::InsertMaterial(int32_t, int32_t *, int32_t *, int32_t, int32_t, bool) { return false; } +bool C4Landscape::Incinerate(int32_t, int32_t, int32_t) { return false; } +bool C4Landscape::ClearPix(int32_t, int32_t) { return false; } +void C4Landscape::CheckInstabilityRange(int32_t, int32_t) {} + +int32_t C4Landscape::GetDensity(int32_t x, int32_t y) const { return p->Pix2Dens[GetPix(x, y)]; } +int32_t C4Landscape::GetPixDensity(BYTE byPix) const { return p->Pix2Dens[byPix]; } +C4Real C4Landscape::GetGravity() const { return C4REAL100(20); } +int32_t C4Landscape::GetMat(int32_t x, int32_t y) const { return p->Pix2Mat[GetPix(x, y)]; } + +BYTE C4Landscape::GetPix(int32_t x, int32_t y) const // get landscape pixel (bounds checked) +{ + extern BYTE MCVehic; + // Border checks + if (x < 0 || x >= p->Width) return MCVehic; + if (y < 0 || y >= p->Height) return MCVehic; + return p->Surface8->_GetPix(x, y); +} + int32_t PixCol2Mat(BYTE pixc) { // Get texture @@ -40,15 +75,11 @@ void C4Landscape::HandleTexMapUpdate() void C4Landscape::UpdatePixMaps() // Copied from C4Landscape.cpp { int32_t i; - for (i = 0; i < C4M_MaxTexIndex; i++) Pix2Mat[i] = PixCol2Mat(i); - for (i = 0; i < C4M_MaxTexIndex; i++) Pix2Dens[i] = MatDensity(Pix2Mat[i]); - for (i = 0; i < C4M_MaxTexIndex; i++) Pix2Place[i] = MatValid(Pix2Mat[i]) ? ::MaterialMap.Map[Pix2Mat[i]].Placement : 0; - for (i = 0; i < C4M_MaxTexIndex; i++) Pix2Light[i] = MatValid(Pix2Mat[i]) && (::MaterialMap.Map[Pix2Mat[i]].Light>0); - Pix2Place[0] = 0; + for (i = 0; i < C4M_MaxTexIndex; i++) p->Pix2Mat[i] = PixCol2Mat(i); + for (i = 0; i < C4M_MaxTexIndex; i++) p->Pix2Dens[i] = MatDensity(p->Pix2Mat[i]); + for (i = 0; i < C4M_MaxTexIndex; i++) p->Pix2Place[i] = MatValid(p->Pix2Mat[i]) ? ::MaterialMap.Map[p->Pix2Mat[i]].Placement : 0; + for (i = 0; i < C4M_MaxTexIndex; i++) p->Pix2Light[i] = MatValid(p->Pix2Mat[i]) && (::MaterialMap.Map[p->Pix2Mat[i]].Light>0); + p->Pix2Place[0] = 0; // clear bridge mat conversion buffers - for (int32_t i = 0; i < C4M_MaxTexIndex; ++i) - { - delete [] BridgeMatConversion[i]; - BridgeMatConversion[i] = NULL; - } + std::fill(p->BridgeMatConversion.begin(), p->BridgeMatConversion.end(), nullptr); } diff --git a/src/mape/cpp-handles/stub-handle.cpp b/src/mape/cpp-handles/stub-handle.cpp index f35b92c94..5eadafb44 100644 --- a/src/mape/cpp-handles/stub-handle.cpp +++ b/src/mape/cpp-handles/stub-handle.cpp @@ -29,6 +29,7 @@ #include "C4Record.h" #include "C4RoundResults.h" #include "C4TextureShape.h" +#include "landscape/C4Sky.h" /* This file implements stubs for the parts of the engine that are not used * by mape. */ @@ -76,15 +77,6 @@ void C4DefList::ResetIncludeDependencies() {} bool C4DefList::DrawFontImage(const char* szImageTag, C4Facet& rTarget, C4DrawTransform* pTransform) { return false; } float C4DefList::GetFontImageAspect(const char* szImageTag) { return -1.0f; } -C4Landscape::C4Landscape() {} -C4Landscape::~C4Landscape() {} -bool C4Landscape::FindMatSlide(int&, int&, int, int, int) const { return false; } -int32_t C4Landscape::ExtractMaterial(int32_t, int32_t, bool) { return 0; } -bool C4Landscape::InsertMaterial(int32_t, int32_t *, int32_t *, int32_t, int32_t, bool) { return false; } -bool C4Landscape::Incinerate(int32_t, int32_t, int32_t) { return false; } -bool C4Landscape::ClearPix(int32_t, int32_t) { return false; } -void C4Landscape::CheckInstabilityRange(int32_t, int32_t) {} - void C4Sky::Default() {} C4Sky::~C4Sky() {} diff --git a/src/object/C4Command.cpp b/src/object/C4Command.cpp index 8bb14eb76..9c3ab6c34 100644 --- a/src/object/C4Command.cpp +++ b/src/object/C4Command.cpp @@ -143,7 +143,7 @@ bool FreeMoveTo(C4Object *cObj) void AdjustMoveToTarget(int32_t &rX, int32_t &rY, bool fFreeMove, int32_t iShapeHgt) { // Above solid (always) - int32_t iY=std::min(rY, GBackHgt); + int32_t iY=std::min(rY, ::Landscape.GetHeight()); while ((iY>=0) && GBackSolid(rX,iY)) iY--; if (iY>=0) rY=iY; // No-free-move adjustments (i.e. if walking) @@ -152,8 +152,8 @@ void AdjustMoveToTarget(int32_t &rX, int32_t &rY, bool fFreeMove, int32_t iShape // Drop down to bottom of free space if (!GBackSemiSolid(rX,rY)) { - for (iY=rY; (iY rbound && GetPropertyInt(P_BorderBound) & C4D_Border_Sides) @@ -192,7 +192,7 @@ void C4Object::VerticalBounds(C4Real &ctcoy) } // landscape bounds C4Real tbound = itofix(0 - Shape.GetY()), - bbound = itofix(GBackHgt - (Shape.GetY() + Shape.Hgt)); + bbound = itofix(::Landscape.GetHeight() - (Shape.GetY() + Shape.Hgt)); if (ctcoy < tbound && GetPropertyInt(P_BorderBound) & C4D_Border_Top) StopAndContact(ctcoy, tbound, ydir, CNAT_Top); if (ctcoy > bbound && GetPropertyInt(P_BorderBound) & C4D_Border_Bottom) @@ -578,8 +578,8 @@ bool C4Object::ExecMovement() // Every Tick1 by Execute if (!Def->Rotateable) fix_r=Fix0; // Out of bounds check - if ((!Inside(GetX() + Shape.GetX(), -Shape.Wdt, GBackWdt) && !(GetPropertyInt(P_BorderBound) & C4D_Border_Sides)) - || ((GetY() + Shape.GetY() > GBackHgt) && !(GetPropertyInt(P_BorderBound) & C4D_Border_Bottom))) + if ((!Inside(GetX() + Shape.GetX(), -Shape.Wdt, ::Landscape.GetWidth()) && !(GetPropertyInt(P_BorderBound) & C4D_Border_Sides)) + || ((GetY() + Shape.GetY() > ::Landscape.GetHeight()) && !(GetPropertyInt(P_BorderBound) & C4D_Border_Bottom))) { C4PropList* pActionDef = GetAction(); // Never remove attached objects: If they are truly outside landscape, their target will be removed, @@ -593,9 +593,9 @@ bool C4Object::ExecMovement() // Every Tick1 by Execute int parX, parY; GetParallaxity(&parX, &parY); fRemove = false; - if (GetX()>GBackWdt || GetY()>GBackHgt) fRemove = true; // except if they are really out of the viewport to the right... + if (GetX()>::Landscape.GetWidth() || GetY()>::Landscape.GetHeight()) fRemove = true; // except if they are really out of the viewport to the right... else if (GetX()<0 && !!parX) fRemove = true; // ...or it's not HUD horizontally and it's out to the left - else if (!parX && GetX()<-GBackWdt) fRemove = true; // ...or it's HUD horizontally and it's out to the left + else if (!parX && GetX()<-::Landscape.GetWidth()) fRemove = true; // ...or it's HUD horizontally and it's out to the left } if (fRemove) { @@ -628,7 +628,7 @@ bool SimFlight(C4Real &x, C4Real &y, C4Real &xdir, C4Real &ydir, int32_t iDensit // Movement to target ctcox=fixtoi(x); ctcoy=fixtoi(y); // Bounds - if (!Inside(ctcox,0,GBackWdt) || (ctcoy>=GBackHgt)) + if (!Inside(ctcox,0,::Landscape.GetWidth()) || (ctcoy>=::Landscape.GetHeight())) return false; // Move to target do diff --git a/src/object/C4Object.cpp b/src/object/C4Object.cpp index b00eb75f6..8e65689e8 100644 --- a/src/object/C4Object.cpp +++ b/src/object/C4Object.cpp @@ -4190,7 +4190,7 @@ bool C4Object::SetLightColor(uint32_t iValue) void C4Object::UpdateLight() { - if (Landscape.pFoW) Landscape.pFoW->Add(this); + if (Landscape.HasFoW()) Landscape.GetFoW()->Add(this); } void C4Object::SetAudibilityAt(C4TargetFacet &cgo, int32_t iX, int32_t iY, int32_t player) @@ -4696,7 +4696,7 @@ bool C4Object::StatusDeactivate(bool fClearPointers) // put into inactive list ::Objects.Remove(this); Status = C4OS_INACTIVE; - if (Landscape.pFoW) Landscape.pFoW->Remove(this); + if (Landscape.HasFoW()) Landscape.GetFoW()->Remove(this); ::Objects.InactiveObjects.Add(this, C4ObjectList::stMain); // if desired, clear game pointers if (fClearPointers) diff --git a/src/object/C4Shape.cpp b/src/object/C4Shape.cpp index 5c8d928f9..26f92151e 100644 --- a/src/object/C4Shape.cpp +++ b/src/object/C4Shape.cpp @@ -177,7 +177,7 @@ void C4Shape::GetVertexOutline(C4Rect &rRect) inline bool C4Shape::CheckTouchableMaterial(int32_t x, int32_t y, int32_t vtx_i, int32_t ydir, const C4DensityProvider &rDensityProvider) { return rDensityProvider.GetDensity(x,y) >= ContactDensity && - ((ydir > 0 && !(CNAT_PhaseHalfVehicle & VtxCNAT[vtx_i])) || !IsMCHalfVehicle(GBackPix(x,y))); + ((ydir > 0 && !(CNAT_PhaseHalfVehicle & VtxCNAT[vtx_i])) || !IsMCHalfVehicle(::Landscape.GetPix(x,y))); } // Adjust given position to one pixel before contact @@ -389,7 +389,7 @@ bool C4Shape::ContactCheck(int32_t cx, int32_t cy, uint32_t *border_hack_contact if (border_hack_contacts) { if (x == 0 && CheckTouchableMaterial(x-1, y, cvtx)) *border_hack_contacts |= CNAT_Left; - else if (x == ::Landscape.Width && CheckTouchableMaterial(x+1, y, cvtx)) *border_hack_contacts |= CNAT_Right; + else if (x == ::Landscape.GetWidth() && CheckTouchableMaterial(x+1, y, cvtx)) *border_hack_contacts |= CNAT_Right; } } diff --git a/src/platform/C4WindowController.mm b/src/platform/C4WindowController.mm index 5f7e4f7d3..9716c5bec 100644 --- a/src/platform/C4WindowController.mm +++ b/src/platform/C4WindowController.mm @@ -245,16 +245,16 @@ bool C4Viewport::ScrollBarsByViewPosition() { if (PlayerLock) return false; NSScrollView* scrollView = pWindow->objectiveCObject().scrollView; - [scrollView.horizontalScroller setToLandscapeCoordinate:GetViewX() size:GBackWdt viewportSize:ViewWdt zoom:GetZoom()]; - [scrollView.verticalScroller setToLandscapeCoordinate:GetViewY() size:GBackHgt viewportSize:ViewHgt zoom:GetZoom()]; + [scrollView.horizontalScroller setToLandscapeCoordinate:GetViewX() size:Landscape.GetWidth() viewportSize:ViewWdt zoom:GetZoom()]; + [scrollView.verticalScroller setToLandscapeCoordinate:GetViewY() size:Landscape.GetHeight() viewportSize:ViewHgt zoom:GetZoom()]; return true; } bool C4Viewport::ViewPositionByScrollBars() { NSScrollView* scrollView = pWindow->objectiveCObject().scrollView; - SetViewX([scrollView.horizontalScroller landscapeCoordinateForSize:GBackWdt viewportSize:ViewWdt zoom:GetZoom()]); - SetViewY([scrollView.verticalScroller landscapeCoordinateForSize:GBackHgt viewportSize:ViewHgt zoom:GetZoom()]); + SetViewX([scrollView.horizontalScroller landscapeCoordinateForSize:Landscape.GetWidth() viewportSize:ViewWdt zoom:GetZoom()]); + SetViewY([scrollView.verticalScroller landscapeCoordinateForSize:Landscape.GetHeight() viewportSize:ViewHgt zoom:GetZoom()]); return true; } diff --git a/src/player/C4Player.cpp b/src/player/C4Player.cpp index 61ff7d5c8..9ba631456 100644 --- a/src/player/C4Player.cpp +++ b/src/player/C4Player.cpp @@ -196,8 +196,8 @@ void C4Player::Execute() { // player has selected a team that has a valid start position assigned // set view to this position! - ViewX = Game.C4S.PlrStart[iPlrStartIndex-1].Position[0] * ::Landscape.MapZoom; - ViewY = Game.C4S.PlrStart[iPlrStartIndex-1].Position[1] * ::Landscape.MapZoom; + ViewX = Game.C4S.PlrStart[iPlrStartIndex-1].Position[0] * ::Landscape.GetMapZoom(); + ViewY = Game.C4S.PlrStart[iPlrStartIndex-1].Position[1] * ::Landscape.GetMapZoom(); } } } @@ -289,7 +289,7 @@ bool C4Player::Init(int32_t iNumber, int32_t iAtClient, const char *szAtClientNa Name.Copy(pInfo->GetName()); // view pos init: Start at center pos - ViewX = GBackWdt/2; ViewY = GBackHgt/2; + ViewX = ::Landscape.GetWidth()/2; ViewY = ::Landscape.GetHeight()/2; // Scenario init if (fScenarioInit) @@ -632,8 +632,8 @@ bool C4Player::ScenarioInit() pty = Game.C4S.PlrStart[PlrStartIndex].Position[1]; // Zoomed position - if (ptx>-1) ptx = Clamp( ptx * Game.C4S.Landscape.MapZoom.Evaluate(), 0, GBackWdt-1 ); - if (pty>-1) pty = Clamp( pty * Game.C4S.Landscape.MapZoom.Evaluate(), 0, GBackHgt-1 ); + if (ptx>-1) ptx = Clamp( ptx * Game.C4S.Landscape.MapZoom.Evaluate(), 0, ::Landscape.GetWidth()-1 ); + if (pty>-1) pty = Clamp( pty * Game.C4S.Landscape.MapZoom.Evaluate(), 0, ::Landscape.GetHeight()-1 ); // Standard position (PrefPosition) if (ptx<0) @@ -653,12 +653,12 @@ bool C4Player::ScenarioInit() } Position=iPosition; // Set x position - ptx=Clamp(16+Position*(GBackWdt-32)/(iMaxPos-1),0,GBackWdt-16); + ptx=Clamp(16+Position*(::Landscape.GetWidth()-32)/(iMaxPos-1),0,::Landscape.GetWidth()-16); } // All-random position - if (ptx<0) ptx=16+Random(GBackWdt-32); - if (pty<0) pty=16+Random(GBackHgt-32); + if (ptx<0) ptx=16+Random(::Landscape.GetWidth()-32); + if (pty<0) pty=16+Random(::Landscape.GetHeight()-32); // Place to solid ground if (!Game.C4S.PlrStart[PlrStartIndex].EnforcePosition) @@ -1359,8 +1359,8 @@ void C4Player::ScrollView(float iX, float iY, float ViewWdt, float ViewHgt) if (ViewLock) return; SetViewMode(C4PVM_Scrolling); float ViewportScrollBorder = Application.isEditor ? 0 : C4ViewportScrollBorder; - ViewX = Clamp( ViewX+ftofix(iX), ftofix(ViewWdt/2.0f-ViewportScrollBorder), ftofix(GBackWdt+ViewportScrollBorder-ViewWdt/2.0f) ); - ViewY = Clamp( ViewY+ftofix(iY), ftofix(ViewHgt/2.0f-ViewportScrollBorder), ftofix(GBackHgt+ViewportScrollBorder-ViewHgt/2.0f) ); + ViewX = Clamp( ViewX+ftofix(iX), ftofix(ViewWdt/2.0f-ViewportScrollBorder), ftofix(::Landscape.GetWidth()+ViewportScrollBorder-ViewWdt/2.0f) ); + ViewY = Clamp( ViewY+ftofix(iY), ftofix(ViewHgt/2.0f-ViewportScrollBorder), ftofix(::Landscape.GetHeight()+ViewportScrollBorder-ViewHgt/2.0f) ); } void C4Player::ClearControl()