/* FinalSun/FinalAlert 2 Mission Editor Copyright (C) 1999-2024 Electronic Arts, Inc. Authored by Matthias Wagner This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ // CliffModifier.cpp: Implementierung der Klasse CCliffModifier. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "stdafx.h" #include "CliffModifier.h" #include "variables.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[] = __FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Konstruktion/Destruktion ////////////////////////////////////////////////////////////////////// CCliffModifier::CCliffModifier() { } CCliffModifier::~CCliffModifier() { } BOOL CCliffModifier::PlaceCliff(DWORD dwXFrom, DWORD dwYFrom, DWORD dwXDest, DWORD dwYDest, BOOL bAlternative) { m_bAlternative = bAlternative; int x_diff, y_diff; x_diff = dwXDest - dwXFrom; y_diff = dwYDest - dwYFrom; if (x_diff > 0 && y_diff > 0 && ((float)y_diff) / ((float)x_diff) > 1.33f) { x_diff = 0; dwXDest = dwXFrom; } if (x_diff < 0 && y_diff>0 && ((float)y_diff) / (-(float)x_diff) > 1.33f) { x_diff = 0; dwXDest = dwXFrom; } if (x_diff > 0 && y_diff < 0 && ((float)-y_diff) / ((float)x_diff) > 1.33f) { x_diff = 0; dwXDest = dwXFrom; } if (x_diff < 0 && y_diff < 0 && (-(float)y_diff) / (-(float)x_diff) > 1.33f) { x_diff = 0; dwXDest = dwXFrom; } if (y_diff > 0 && x_diff > 0 && ((float)x_diff) / ((float)y_diff) > 2) { y_diff = 0; dwYDest = dwYFrom; } if (y_diff < 0 && x_diff>0 && ((float)x_diff) / (-(float)y_diff) > 2) { y_diff = 0; dwYDest = dwYFrom; } if (y_diff > 0 && x_diff < 0 && ((float)-x_diff) / ((float)y_diff) > 2) { y_diff = 0; dwYDest = dwYFrom; } if (y_diff < 0 && x_diff < 0 && (-(float)x_diff) / (-(float)y_diff) > 2) { y_diff = 0; dwYDest = dwYFrom; } m_dwFrom = dwXFrom + dwYFrom * Map->GetIsoSize(); m_dwTo = dwXDest + dwYDest * Map->GetIsoSize(); if (!x_diff && !y_diff) return FALSE; if (x_diff && y_diff) { if ((x_diff > 0 && y_diff > 0)) { m_direction = cd_verticdiag_bottom; } else if ((x_diff < 0 && y_diff < 0)) { m_direction = cd_verticdiag_top; } else if ((x_diff < 0 && y_diff>0)) { m_direction = cd_horizdiag_right; } else if (x_diff > 0 && y_diff < 0) { m_direction = cd_horizdiag_left; } } else if (y_diff < 0) { m_direction = cd_horiz_left; } else if (y_diff > 0) { m_direction = cd_horiz_right; } else if (x_diff < 0) { m_direction = cd_vertic_top; } else if (x_diff > 0) { m_direction = cd_vertic_bottom; } switch (m_direction) { case cd_horiz_left: m_addx = 0; m_addy = -1; break; case cd_horiz_right: m_addx = 0; m_addy = 1; break; case cd_horizdiag_left: m_addx = 1; m_addy = -1; break; case cd_horizdiag_right: m_addx = -1; m_addy = 1; break; case cd_vertic_top: m_addx = -1; m_addy = 0; break; case cd_vertic_bottom: m_addx = 1; m_addy = 0; break; case cd_verticdiag_top: m_addx = -1; m_addy = -1; break; case cd_verticdiag_bottom: m_addx = 1; m_addy = 1; break; } int i, e; DWORD dwCurPos = m_dwFrom; int startheight = Map->GetHeightAt(dwCurPos); DWORD dwLastTile = -1; FIELDDATA* fd = Map->GetFielddataAt(dwCurPos); int ground = fd->wGround; int subtile = fd->bSubTile; if (ground == 0xFFFF) ground = 0; startheight -= (*tiledata)[ground].tiles[subtile].bZHeight; ModifyStartPos(&dwCurPos, FALSE); BOOL bSmall = FALSE; DWORD dwFirstStartPos = dwCurPos; DWORD dwTile = GetTileToPlace(dwCurPos, &bSmall); BOOL bFirstPos = TRUE; while (dwCurPos != m_dwTo) { ModifyCurrentPos(&dwCurPos, TRUE, bSmall); if (!bFirstPos) { dwTile = GetTileToPlace(dwCurPos, &bSmall); dwLastTile = dwTile; } else bFirstPos = FALSE; if (dwTile == -1) break; TILEDATA* t = &(*tiledata)[dwTile]; if (m_addx < 0) dwCurPos += t->cx * m_addx; if (m_addy < 0) dwCurPos += t->cy * m_addy * Map->GetIsoSize(); int o = 0; DWORD dwTmpTile = dwTile; while (dwFirstStartPos != dwCurPos && dwTile == dwLastTile) { o++; if (o == 10) break; dwTmpTile = GetTileToPlace(dwCurPos, &bSmall); if ((*tiledata)[dwTmpTile].cx == (*tiledata)[dwTile].cx && (*tiledata)[dwTile].cy == (*tiledata)[dwTmpTile].cy) dwTile = dwTmpTile; } t = &(*tiledata)[dwTile]; int p = 0; for (i = 0; i < t->cx; i++) { for (e = 0; e < t->cy; e++) { if (t->tiles[p].pic != NULL) { Map->SetHeightAt(dwCurPos + i + e * Map->GetIsoSize(), startheight + t->tiles[p].bZHeight); Map->SetTileAt(dwCurPos + i + e * Map->GetIsoSize(), dwTile, p); } p++; } } if (m_addx > 0) dwCurPos += t->cx * m_addx; if (m_addy > 0) dwCurPos += t->cy * m_addy * Map->GetIsoSize(); ModifyCurrentPos(&dwCurPos, FALSE, bSmall); dwLastTile = dwTile; } return TRUE; } void CCliffModifier::ModifyStartPos(DWORD* dwStartPos, BOOL bSmall) { } void CCliffModifier::ModifyCurrentPos(DWORD* dwPos, BOOL bBeforePlacing, BOOL bSmall) { } DWORD CCliffModifier::GetTileToPlace(DWORD dwPos, BOOL* bSmall) { vector careables; vector useables; map notusedascliff; CString type; int count = 0; switch (m_direction) { case cd_horiz_left: case cd_horiz_right: type = "horiz_"; break; case cd_horizdiag_left: case cd_horizdiag_right: type = "horiz_diag_"; break; case cd_vertic_top: case cd_vertic_bottom: type = "vertic_"; break; case cd_verticdiag_top: case cd_verticdiag_bottom: type = "vertic_diag_"; break; } CString sec = GetDataSection(); CIniFile& ini = Map->GetIniFile(); auto const& theaterID = g_data.GetString("Map", "Theater"); if (!theaterID.IsEmpty()) { sec += theaterID; } count = g_data.GetInteger(sec, type + "c"); int i; DWORD dwStartSet = 0; /*for(i=0;i<(*tiledata_count);i++) { if( (!m_bAlternative && (*tiledata)[i].wTileSet==cliffset) || (m_bAlternative && (*tiledata)[i].wTileSet==cliff2set)) { dwStartSet=i; break; } }*/ // a bit faster: if (m_bAlternative) dwStartSet = cliff2set_start; else dwStartSet = cliffset_start; for (i = 0; i < count; i++) { char c[50]; itoa(i, c, 10); CString cur = type; cur += c; notusedascliff[dwStartSet + g_data.GetInteger(sec, cur)] = TRUE; } CString corner_searched = ""; DWORD dwCurPos = dwPos; int isosize = Map->GetIsoSize(); ModifyStartPos(&dwCurPos, FALSE); int e; for (i = -1; i < 2; i++) { for (e = -1; e < 2; e++) { FIELDDATA* fd = Map->GetFielddataAt(dwCurPos + i + e * isosize); int ground = fd->wGround; if (ground == 0xFFFF) ground = 0; if ((*tiledata)[ground].wTileSet == cliffset && notusedascliff.find(ground) == notusedascliff.end()) { if (i == 0 && e == -1) { corner_searched = "cornerleft_"; break; } if (i == 0 && e == 1) { corner_searched = "cornerright_"; break; } if (i == -1 && e == 0) { corner_searched = "cornertop_"; break; } if (i == 1 && e == 0) { corner_searched = "cornerbottom_"; break; } /*if(e==-1) {corner_searched="cornerleft_";break;} if(e==1) {corner_searched="cornerright_";break;} if(i==-1) {corner_searched="cornertop_";break;} if(i==1) {corner_searched="cornerbottom_";break;}*/ } } if (corner_searched.GetLength() > 0) break; } BOOL bCornerFound = FALSE;; if (int icount = g_data.GetInteger(sec, type + corner_searched + "c")) { bCornerFound = TRUE; count = icount; } if (!bCornerFound) corner_searched = ""; if (count == 0) return -1; DWORD dwX = dwPos % Map->GetIsoSize(); DWORD dwY = dwPos / Map->GetIsoSize(); DWORD dwDX = m_dwTo % Map->GetIsoSize(); DWORD dwDY = m_dwTo / Map->GetIsoSize(); for (i = 0; i < count; i++) { char c[50]; itoa(i, c, 10); careables.push_back(dwStartSet + g_data.GetInteger(sec, type + corner_searched + c)); } for (i = 0; i < careables.size(); i++) { TILEDATA& t = (*tiledata)[careables[i]]; if (m_addx > 0 && dwX + m_addx * t.cx > dwDX) continue; if (m_addy > 0 && dwY + m_addy * t.cy > dwDY) continue; if (m_addx < 0 && dwX + m_addx * t.cx < dwDX) continue; if (m_addy < 0 && dwY + m_addy * t.cy < dwDY) continue; useables.push_back(careables[i]); } if (useables.size() < 1) return -1; *bSmall = FALSE; int k; k = rand() % (useables.size()); TILEDATA& t1 = (*tiledata)[useables[k]]; for (i = 0; i < careables.size(); i++) { TILEDATA& t = (*tiledata)[careables[i]]; if (t.cx > t1.cx || t.cy > t1.cy) { *bSmall = TRUE; break; } } // check for water BOOL bWater = FALSE; for (i = 0; i < t1.cx; i++) { for (e = 0; e < t1.cy; e++) { FIELDDATA* fd = Map->GetFielddataAt(dwPos + i + e * Map->GetIsoSize()); int ground = fd->wGround; if (ground == 0xFFFF) ground = 0; if ((i == t1.cx - 1 || e == t1.cy - 1) && (*tiledata)[ground].tiles[fd->bSubTile].bHackedTerrainType == TERRAINTYPE_WATER) { bWater = TRUE; break; } } if (bWater) break; } if (bWater && useables[k] - dwStartSet < 22) { CString tset; char c[50]; int watercliffs = tiles->GetInteger("General", "WaterCliffs"); if (m_bAlternative) { watercliffs = cliffwater2set; } itoa(watercliffs, c, 10); int e; for (e = 0; e < 4 - strlen(c); e++) { tset += "0"; } tset += c; CString sec = "TileSet"; sec += tset; auto const pSec = tiles->TryGetSection(sec); if (!pSec) { return useables[k]; } if (pSec->GetInteger("TilesInSet") > useables[k] - dwStartSet) { DWORD dwStartWaterSet = 0; for (i = 0; i < (*tiledata_count); i++) { if ((*tiledata)[i].wTileSet == watercliffs) { dwStartWaterSet = i; return dwStartWaterSet + (useables[k] - dwStartSet); } } } } return useables[k]; }