mirror of
https://github.com/electronicarts/CNC_TS_and_RA2_Mission_Editor.git
synced 2025-04-30 09:01:41 -04:00
778 lines
22 KiB
C++
778 lines
22 KiB
C++
/*
|
||
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 <https://www.gnu.org/licenses/>.
|
||
*/
|
||
|
||
// Map->h: Interface for the class CMap.
|
||
//
|
||
// CMap holds all information for the current map
|
||
//
|
||
//////////////////////////////////////////////////////////////////////
|
||
|
||
#if !defined(AFX_MAP_H__9278CAC0_D4E7_11D3_B63B_444553540001__INCLUDED_)
|
||
#define AFX_MAP_H__9278CAC0_D4E7_11D3_B63B_444553540001__INCLUDED_
|
||
|
||
#if _MSC_VER > 1000
|
||
#pragma once
|
||
#endif // _MSC_VER > 1000
|
||
|
||
#include <array>
|
||
#include <vector>
|
||
#include "structs.h"
|
||
#include "variables.h"
|
||
#include "macros.h"
|
||
#include "ovrlinline.h"
|
||
#include "Tube.h"
|
||
#include "IniFile.h" // Hinzugefügt von der Klassenansicht
|
||
|
||
extern TILEDATA** tiledata;
|
||
extern DWORD* tiledata_count;
|
||
extern std::ofstream errstream;
|
||
extern map<int, int> tilesets_start;
|
||
extern CIniFile* tiles;
|
||
extern CFinalSunApp theApp;
|
||
extern int shoreset;
|
||
|
||
extern CIniFile rules;
|
||
|
||
extern TILEDATA* un_tiledata;
|
||
extern CIniFile g_data;
|
||
|
||
extern int ramp2set;
|
||
extern int pave2set;
|
||
extern int ramp2set_start;
|
||
extern int pave2set_start;
|
||
extern int rampset_start;
|
||
extern int rampset;
|
||
|
||
|
||
|
||
#define MAPDATA_UPDATE_FROM_INI 0
|
||
#define MAPDATA_UPDATE_TO_INI 1
|
||
#define MAPDATA_UPDATE_TO_INI_ALL 2
|
||
#define MAPDATA_UPDATE_TO_INI_ALL_PREVIEW 4
|
||
#define MAPDATA_UPDATE_TO_INI_ALL_COMPRESSED 8
|
||
|
||
struct NODEDATA
|
||
{
|
||
NODEDATA();
|
||
int type;
|
||
int index;
|
||
CString house;
|
||
};
|
||
|
||
// mapfielddata is the data of every field in an extracted isomappack!
|
||
struct MAPFIELDDATA
|
||
{
|
||
unsigned short wX;
|
||
unsigned short wY;
|
||
WORD wGround;
|
||
BYTE bData[3];
|
||
BYTE bHeight;
|
||
BYTE bData2[1];
|
||
};
|
||
#define MAPFIELDDATA_SIZE 11
|
||
|
||
/*
|
||
struct TILEDATA{};
|
||
|
||
contains the information needed for one field of the map.
|
||
*/
|
||
struct FIELDDATA
|
||
{
|
||
FIELDDATA();
|
||
short unit; // unit number
|
||
short infantry[SUBPOS_COUNT]; // infantry number
|
||
short aircraft; // aircraft number
|
||
short structure; // structure number
|
||
short structuretype; // structure type id
|
||
short terrain; // terrain number
|
||
int terraintype; // terrain type id
|
||
#ifdef SMUDGE_SUPP
|
||
short smudge;
|
||
int smudgetype;
|
||
#endif
|
||
short waypoint; // waypoint number
|
||
|
||
NODEDATA node; // node info
|
||
BYTE overlay; // overlay number
|
||
BYTE overlaydata; // overlay data info
|
||
WORD wGround; // ground type (tile)
|
||
WORD bMapData; // add. data
|
||
BYTE bSubTile;
|
||
BYTE bHeight; // height of tile
|
||
BYTE bMapData2; // add. data2
|
||
short celltag; // celltag uses
|
||
|
||
//std::uint16_t wTubeId; // tube ID
|
||
//char cTubePart; // 0 is start, 1 is exit, and 2-101 are tube parts
|
||
unsigned bReserved : 1; // for program usage
|
||
unsigned bHide : 1;
|
||
unsigned bRedrawTerrain : 1; // force redraw
|
||
unsigned bCliffHack : 1;
|
||
unsigned bRNDImage : 4; // for using a,b,c of tmp tiles
|
||
bool bShoreProcessed;
|
||
bool bShoreLATNeeded;
|
||
};
|
||
|
||
struct SNAPSHOTDATA
|
||
{
|
||
SNAPSHOTDATA();
|
||
int left;
|
||
int top;
|
||
int bottom;
|
||
int right;
|
||
|
||
BOOL* bRedrawTerrain;
|
||
BYTE* overlay;
|
||
BYTE* overlaydata;
|
||
WORD* wGround;
|
||
WORD* bMapData;
|
||
BYTE* bSubTile;
|
||
BYTE* bHeight;
|
||
BYTE* bMapData2;
|
||
BYTE* bRNDData;
|
||
//CIniFile mapfile;
|
||
};
|
||
|
||
|
||
|
||
class CMapData
|
||
{
|
||
public:
|
||
|
||
BOOL m_noAutoObjectUpdate;
|
||
|
||
void SetFielddataAt(DWORD dwPos, FIELDDATA* lpFd)
|
||
{
|
||
if (dwPos >= fielddata.size()) {
|
||
return;
|
||
}
|
||
|
||
RemoveOvrlMoney(fielddata[dwPos].overlay, fielddata[dwPos].overlaydata);
|
||
fielddata[dwPos] = (*lpFd);
|
||
AddOvrlMoney(fielddata[dwPos].overlay, fielddata[dwPos].overlaydata);
|
||
};
|
||
|
||
DWORD GetMapPos(int mapX, int mapY) const
|
||
{
|
||
return mapX + mapY * m_IsoSize;
|
||
}
|
||
DWORD GetMapPos(const MapCoords& coords) const
|
||
{
|
||
return coords.x + coords.y * m_IsoSize;
|
||
}
|
||
|
||
bool hasLat(WORD wTileSet) const;
|
||
|
||
void HideField(DWORD dwPos, BOOL bHide);
|
||
void SetReserved(DWORD dwPos, BYTE val);
|
||
DWORD GetTileID(DWORD dwTileSet, int iTile);
|
||
int GetNecessarySlope(DWORD dwPos);
|
||
void CreateSlopesAt(DWORD dwPos);
|
||
void CreateMap(DWORD dwWidth, DWORD dwHeight, LPCTSTR lpTerrainType, DWORD dwGroundHeight);
|
||
BOOL SetTileAt(DWORD dwPos, DWORD dwID, DWORD dwTile)
|
||
{
|
||
if (dwPos > fielddata.size()) {
|
||
return FALSE;
|
||
}
|
||
|
||
int replacement = 0; // MW fix: ignore for bridges
|
||
if ((*tiledata)[dwID].bReplacementCount && tiles->GetInteger("General", "BridgeSet") != (*tiledata)[dwID].wTileSet) {
|
||
replacement = rand() * (1 + (*tiledata)[dwID].bReplacementCount) / RAND_MAX;
|
||
}
|
||
|
||
fielddata[dwPos].wGround = dwID;
|
||
fielddata[dwPos].bSubTile = dwTile;
|
||
fielddata[dwPos].bRNDImage = replacement;
|
||
|
||
int e;
|
||
fielddata[dwPos].bRedrawTerrain = FALSE;
|
||
int xx, yy;
|
||
for (xx = -2; xx < 0; xx++) {
|
||
for (yy = -2; yy < 0; yy++) {
|
||
int npos = dwPos + xx + yy * m_IsoSize;
|
||
if (npos > 0 && fielddata[dwPos].bHeight - fielddata[npos].bHeight >= 4) {
|
||
fielddata[dwPos].bRedrawTerrain = TRUE;
|
||
break;
|
||
}
|
||
}
|
||
if (fielddata[dwPos].bRedrawTerrain) {
|
||
break;
|
||
}
|
||
}
|
||
|
||
Mini_UpdatePos(dwPos % m_IsoSize, dwPos / m_IsoSize, IsMultiplayer());
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
void SetHeightAt(DWORD dwPos, BYTE bHeight)
|
||
{
|
||
auto const height = std::max(0, std::min<int>(bHeight, MAXHEIGHT));
|
||
if (dwPos < fielddata.size()) {
|
||
fielddata[dwPos].bHeight = height;
|
||
}
|
||
}
|
||
|
||
|
||
int GetBuildingID(const CString& lpBuildingName);
|
||
void ImportRUL(LPCTSTR lpFilename);
|
||
void ExportRulesChanges(const char* filename);
|
||
void DeleteRulesSections();
|
||
DWORD GetWaypointCount() const;
|
||
DWORD GetCelltagCount() const;
|
||
WCHAR* GetUnitName(LPCTSTR lpID) const;
|
||
const XCString* GetUnitDisplayName(const CString& id) const;
|
||
DWORD GetTerrainCount() const;
|
||
DWORD GetAircraftCount() const;
|
||
DWORD GetStructureCount() const;
|
||
DWORD GetUnitCount() const;
|
||
DWORD GetInfantryCount() const;
|
||
|
||
void GetNthWaypointData(DWORD dwIdx, CString* lpID, DWORD* lpdwPos) const;
|
||
void GetWaypointData(DWORD dwId, CString* lpID, DWORD* lpdwPos) const;
|
||
BOOL IsGroundObjectAt(DWORD dwPos) const;
|
||
BOOL AddTerrain(LPCTSTR lpType, DWORD dwPos, int suggestedIndex = -1);
|
||
void GetTerrainData(DWORD dwIndex, CString* lpType) const;
|
||
void GetTerrainData(DWORD dwIndex, TERRAIN* lpTerrain) const;
|
||
BOOL AddUnit(UNIT* lpUnit, LPCTSTR lpType = NULL, LPCTSTR lpHouse = NULL, DWORD dwPos = 0, CString suggestedID = "");
|
||
BOOL AddAircraft(AIRCRAFT* lpAircraft, LPCTSTR lpType = NULL, LPCTSTR lpHouse = NULL, DWORD dwPos = 0, CString suggestedID = "");
|
||
void GetCelltagData(DWORD dwIndex, CString* lpTag, DWORD* lpdwPos) const;
|
||
BOOL AddCelltag(LPCTSTR lpTag, DWORD dwPos);
|
||
|
||
std::pair<CString, CString> GetNthDataOfTechno(const size_t index, const TechnoType type) const;
|
||
CString GetDataOfTechnoByID(const size_t id, const TechnoType type) const;
|
||
bool ParseBasicTechnoData(const CString& rawText, STDOBJECTDATA& data) const;
|
||
bool ParseTechnoData(const CString& rawText, const TechnoType type, TECHNODATA& data) const;
|
||
CString GetAircraftData(DWORD dwIndex, AIRCRAFT* lpAircraft) const;
|
||
CString GetUnitData(DWORD dwIndex, UNIT* lpUnit) const;
|
||
bool ParseInfantryData(const CString& rawText, INFANTRY& infantry) const;
|
||
bool ParseUnitData(const CString& rawText, UNIT& unit) const;
|
||
bool ParseAircraftData(const CString& rawText, AIRCRAFT& aircraft) const;
|
||
bool ParseStructureData(const CString& rawText, STRUCTURE& structure) const;
|
||
void GetInfantryData(DWORD dwIndex, INFANTRY* lpInfantry) const;
|
||
void GetStdInfantryData(DWORD dwIndex, STDOBJECTDATA* lpStdInfantry) const;
|
||
void GetStdUnitData(DWORD dwIndex, STDOBJECTDATA* lpStdUnit) const;
|
||
void GetStdAircraftData(DWORD dwIndex, STDOBJECTDATA* lpStdAircraft) const;
|
||
void GetStdStructureData(const size_t id, STDOBJECTDATA* lpStdStructure) const;
|
||
void GetNthStdStructureData(DWORD dwIndex, STDOBJECTDATA* lpStdStructure) const;
|
||
|
||
INT GetUnitTypeID(LPCTSTR lpType);
|
||
void InitializeUnitTypes();
|
||
BOOL AddStructure(STRUCTURE* lpStructure, LPCTSTR lpType = NULL, LPCTSTR lpHouse = NULL, DWORD dwPos = 0, CString suggestedID = "");
|
||
BOOL AddInfantry(INFANTRY* lpInfantry, int suggestedIndex = -1, LPCTSTR lpType = NULL, LPCTSTR lpHouse = NULL, DWORD dwPos = 0);
|
||
BOOL AddNode(NODE* lpNode, WORD dwPos);
|
||
CString GetNthStructureData(DWORD dwIndex, STRUCTURE* lpStructure) const;
|
||
void GetStructureData(size_t id, STRUCTURE* lpStructure) const;
|
||
BOOL AddWaypoint(CString lpID, DWORD dwPos);
|
||
|
||
void DeleteNode(const CString& house, const int index);
|
||
void DeleteTerrain(DWORD dwIndex);
|
||
void DeleteAircraft(DWORD dwIndex);
|
||
void DeleteNthStructure(const size_t dwIndex);
|
||
bool DeleteStructure(const size_t id);
|
||
void DeleteUnit(DWORD dwIndex);
|
||
void DeleteCelltag(DWORD dwIndex);
|
||
void DeleteWaypoint(DWORD id);
|
||
void DeleteInfantry(DWORD dwIndex);
|
||
|
||
bool IsTileIntact(int x, int y, int startX = -1, int startY = -1, int right = -1, int bottom = -1);
|
||
std::vector<MapCoords> GetIntactTileCoords(int x, int y, bool oriIntact);
|
||
char GetHackedTerrainType(int tileIndex, int TileSubIndex);
|
||
|
||
INT GetCelltagAt(DWORD dwPos) const
|
||
{
|
||
return fielddata[dwPos].celltag;
|
||
}
|
||
INT GetCelltagAt(MapCoords pos) const
|
||
{
|
||
return GetCelltagAt(GetMapPos(pos));
|
||
}
|
||
INT GetWaypointAt(DWORD dwPos) const
|
||
{
|
||
return fielddata[dwPos].waypoint;
|
||
}
|
||
INT GetWaypointAt(MapCoords pos) const
|
||
{
|
||
return GetWaypointAt(GetMapPos(pos));
|
||
}
|
||
INT GetTerrainAt(DWORD dwPos) const
|
||
{
|
||
return fielddata[dwPos].terrain;
|
||
}
|
||
INT GetTerrainAt(MapCoords pos) const
|
||
{
|
||
return GetTerrainAt(GetMapPos(pos));
|
||
}
|
||
INT GetAirAt(DWORD dwPos) const
|
||
{
|
||
return fielddata[dwPos].aircraft;
|
||
}
|
||
INT GetAirAt(MapCoords pos) const
|
||
{
|
||
return GetAirAt(GetMapPos(pos));
|
||
}
|
||
INT GetStructureAt(DWORD dwPos) const
|
||
{
|
||
if (fielddata[dwPos].structure >= 0) {
|
||
return fielddata[dwPos].structure;
|
||
}
|
||
return -1;
|
||
}
|
||
INT GetStructureAt(MapCoords pos) const
|
||
{
|
||
return GetStructureAt(GetMapPos(pos));
|
||
}
|
||
INT GetUnitAt(DWORD dwPos) const
|
||
{
|
||
return fielddata[dwPos].unit;
|
||
}
|
||
INT GetUnitAt(MapCoords pos) const
|
||
{
|
||
return GetUnitAt(GetMapPos(pos));
|
||
}
|
||
INT GetInfantryAt(DWORD dwPos, DWORD dwSubPos = 0xFFFFFFFF) const
|
||
{
|
||
if (dwSubPos == 0xFFFFFFFF) {
|
||
int i;
|
||
for (i = 0; i < SUBPOS_COUNT; i++)
|
||
if (fielddata[dwPos].infantry[i] != -1)
|
||
return fielddata[dwPos].infantry[i];
|
||
return -1;
|
||
}
|
||
return fielddata[dwPos].infantry[dwSubPos];
|
||
}
|
||
INT GetInfantryAt(MapCoords pos, DWORD dwSubPos = 0xFFFFFFFF)
|
||
{
|
||
return GetInfantryAt(GetMapPos(pos), dwSubPos);
|
||
}
|
||
INT GetNodeAt(DWORD dwPos, CString& lpHouse) const;
|
||
INT GetNodeAt(MapCoords pos, CString& lpHouse) const
|
||
{
|
||
return GetNodeAt(GetMapPos(pos), lpHouse);
|
||
}
|
||
INT GetHeightAt(DWORD dwPos) const
|
||
{
|
||
if (dwPos < fielddata.size()) {
|
||
return fielddata[dwPos].bHeight;
|
||
}
|
||
return 0;
|
||
}
|
||
INT GetHeightAt(const MapCoords& coords) const
|
||
{
|
||
return GetHeightAt(GetMapPos(coords));
|
||
}
|
||
|
||
const FIELDDATA* GetFielddataAt(DWORD dwPos) const
|
||
{
|
||
if (dwPos >= fielddata.size()) {
|
||
outside_f.bReserved = 1;
|
||
return &outside_f;
|
||
}
|
||
|
||
return &fielddata[dwPos];
|
||
};
|
||
|
||
FIELDDATA* GetFielddataAt(DWORD dwPos)
|
||
{
|
||
if (dwPos >= fielddata.size()) {
|
||
outside_f.bReserved = 1;
|
||
return &outside_f;
|
||
}
|
||
|
||
return &fielddata[dwPos];
|
||
};
|
||
|
||
FIELDDATA* GetFielddataAt(int X, int Y)
|
||
{
|
||
return GetFielddataAt(GetCoordIndex(X, Y));
|
||
};
|
||
|
||
const FIELDDATA* GetFielddataAt(const MapCoords& pos) const
|
||
{
|
||
auto dwPos = GetMapPos(pos);
|
||
if (dwPos >= fielddata.size()) {
|
||
outside_f.bReserved = 1;
|
||
return &outside_f;
|
||
}
|
||
|
||
return &fielddata[dwPos];
|
||
};
|
||
|
||
FIELDDATA* GetFielddataAt(const MapCoords& pos)
|
||
{
|
||
auto dwPos = GetMapPos(pos);
|
||
if (dwPos >= fielddata.size()) {
|
||
outside_f.bReserved = 1;
|
||
return &outside_f;
|
||
}
|
||
|
||
return &fielddata[dwPos];
|
||
};
|
||
|
||
BYTE GetOverlayDataAt(DWORD dwPos);
|
||
void SetOverlayDataAt(DWORD dwPos, BYTE bValue);
|
||
BYTE GetOverlayAt(DWORD dwPos);
|
||
void SetOverlayAt(DWORD dwPos, BYTE bValue);
|
||
void ClearOverlay();
|
||
void ClearOverlayData();
|
||
|
||
const std::vector<std::unique_ptr<CTube>>& GetTubes() const
|
||
{
|
||
return m_tubes;
|
||
}
|
||
|
||
DWORD GetIsoSize() const
|
||
{
|
||
return m_IsoSize;
|
||
}
|
||
void LoadMap(const std::string& file);
|
||
void UpdateIniFile(DWORD dwFlags = MAPDATA_UPDATE_TO_INI);
|
||
CIniFile& GetIniFile();
|
||
CString GetAITriggerTypeID(DWORD dwAITriggerType);
|
||
DWORD GetAITriggerTypeIndex(LPCTSTR lpID);
|
||
WORD GetHouseIndex(LPCTSTR lpHouse);
|
||
void GetAITriggerType(DWORD dwAITriggerType, AITRIGGERTYPE* pAITrg);
|
||
DWORD GetAITriggerTypeCount();
|
||
CString GetHouseID(WORD wHouse, BOOL bCountry = FALSE);
|
||
WORD GetHousesCount(BOOL bCountries = FALSE);
|
||
WORD GetHeight() const
|
||
{
|
||
return m_maprect.bottom;
|
||
};
|
||
WORD GetWidth() const
|
||
{
|
||
return m_maprect.right;
|
||
};
|
||
BOOL IsRulesSection(LPCTSTR lpSection);
|
||
|
||
CMapData();
|
||
virtual ~CMapData();
|
||
void Pack(BOOL bCreatePreview = FALSE, BOOL bCompression = FALSE);
|
||
void Unpack();
|
||
void UpdateTreeInfo(const CString* lpTreeType = NULL);
|
||
void UpdateBuildingInfo(const CString* lpUnitType = NULL);
|
||
void CalcMapRect();
|
||
|
||
// MW change: UpdateStructures() public, so that houses dialog can access it
|
||
void UpdateStructures(BOOL bSave = FALSE);
|
||
|
||
MapCoords ToMapCoords(ProjectedCoords xy) const;
|
||
MapCoords ToMapCoords3d(ProjectedCoords xy, int mapZ) const;
|
||
MapCoords ToMapCoords3d(ProjectedCoords xy, bool bAllowAccessBehindCliffs = false, bool ignoreHideFlagsAndOutside = false) const;
|
||
ProjectedCoords ProjectCoords(MapCoords xy) const;
|
||
ProjectedCoords ProjectCoords3d(MapCoords xy) const;
|
||
ProjectedCoords ProjectCoords3d(MapCoords xy, int z) const;
|
||
bool IsCoordInMap(int X, int Y) const;
|
||
inline int GetCoordIndex(int X, int Y) const { return X + Y * GetIsoSize(); }
|
||
bool isInside(MapCoords xy) const;
|
||
bool isInside(int x, int y) const;
|
||
|
||
__forceinline CPoint GetMiniMapPos(MapCoords mapCoords)
|
||
{
|
||
int x, y;
|
||
GetMiniMapPos(mapCoords.x, mapCoords.y, x, y);
|
||
return CPoint(static_cast<LONG>(x), static_cast<LONG>(y));
|
||
}
|
||
|
||
static CString GetBuildingIDBy(size_t offset);
|
||
|
||
private:
|
||
void UpdateTubes(BOOL bSave);
|
||
MAPFIELDDATA* GetMappackPointer(DWORD dwPos);
|
||
|
||
void UpdateMapFieldData(BOOL bSave = FALSE);
|
||
|
||
DWORD m_IsoSize;
|
||
mutable FIELDDATA outside_f;
|
||
BOOL isInitialized;
|
||
void UpdateCelltags(BOOL bSave = FALSE);
|
||
void UpdateOverlay(BOOL bSave = FALSE);
|
||
void UpdateNodes(BOOL bSave = FALSE);
|
||
void UpdateWaypoints(BOOL bSave = FALSE);
|
||
void UpdateUnits(BOOL bSave = FALSE);
|
||
void UpdateTerrain(BOOL bSave = FALSE, int num = -1);
|
||
void UpdateInfantry(BOOL bSave = FALSE);
|
||
void UpdateAircraft(BOOL bSave = FALSE);
|
||
|
||
map<CString, int> buildingid;
|
||
map<CString, int> terrainid;
|
||
#ifdef SMUDGE_SUPP
|
||
map<CString, int> smudgeid;
|
||
#endif
|
||
|
||
static constexpr size_t overlayDataCapacity = 262144;
|
||
|
||
BYTE m_Overlay[overlayDataCapacity]; // overlay byte values (extracted)
|
||
BYTE m_OverlayData[overlayDataCapacity]; // overlay data byte values (extracted)
|
||
BYTE* m_mfd; // map field data buffer
|
||
DWORD dwIsoMapSize;
|
||
CIniFile m_mapfile;
|
||
RECT m_maprect;
|
||
RECT m_vismaprect;
|
||
std::vector<FIELDDATA> fielddata;
|
||
SNAPSHOTDATA* m_snapshots;
|
||
DWORD dwSnapShotCount;
|
||
int m_cursnapshot;
|
||
int m_money;
|
||
|
||
std::unordered_map<size_t, STRUCTUREPAINT> m_structurepaint;
|
||
|
||
|
||
protected:
|
||
|
||
void InitMinimap();
|
||
vector<std::unique_ptr<CTube>> m_tubes;
|
||
|
||
// vectors for terrain, infantry, structures and units, as those need to be displayed very fast.
|
||
// we don´t need them for aircraft right now, as there won´t be many aircrafts on the map anyway.
|
||
#ifdef SMUDGE_SUPP
|
||
vector<SMUDGE> m_smudges;
|
||
#endif
|
||
vector<TERRAIN> m_terrain;
|
||
vector<INFANTRY> m_infantry;
|
||
vector<UNIT> m_units;
|
||
vector<STRUCTURE> m_structures;
|
||
|
||
// we use a dib to draw the minimap
|
||
std::vector<BYTE> m_mini_colors;
|
||
BITMAPINFO m_mini_biinfo;
|
||
int m_mini_pitch;
|
||
|
||
enum OverlayCreditsType
|
||
{
|
||
OverlayCredits_Riparius = 0,
|
||
OverlayCredits_Cruentus = 1,
|
||
OverlayCredits_Vinifera = 2,
|
||
OverlayCredits_Aboreus = 3,
|
||
OverlayCredits_NumOf
|
||
};
|
||
|
||
std::array<int, OverlayCredits_NumOf> m_overlayCredits;
|
||
|
||
|
||
__forceinline void RemoveOvrlMoney(unsigned char ovrl, unsigned char ovrld)
|
||
{
|
||
if (ovrl >= RIPARIUS_BEGIN && ovrl <= RIPARIUS_END) {
|
||
m_money -= (ovrld + 1) * m_overlayCredits[OverlayCredits_Riparius];
|
||
}
|
||
|
||
if (ovrl >= CRUENTUS_BEGIN && ovrl <= CRUENTUS_END) {
|
||
m_money -= (ovrld + 1) * m_overlayCredits[OverlayCredits_Cruentus];
|
||
}
|
||
|
||
if (ovrl >= VINIFERA_BEGIN && ovrl <= VINIFERA_END) {
|
||
m_money -= (ovrld + 1) * m_overlayCredits[OverlayCredits_Vinifera];
|
||
}
|
||
|
||
if (ovrl >= ABOREUS_BEGIN && ovrl <= ABOREUS_END) {
|
||
m_money -= (ovrld + 1) * m_overlayCredits[OverlayCredits_Aboreus];
|
||
}
|
||
}
|
||
|
||
__forceinline void AddOvrlMoney(unsigned char ovrl, unsigned char ovrld)
|
||
{
|
||
if (ovrl >= RIPARIUS_BEGIN && ovrl <= RIPARIUS_END) {
|
||
m_money += (ovrld + 1) * m_overlayCredits[OverlayCredits_Riparius];
|
||
}
|
||
|
||
if (ovrl >= CRUENTUS_BEGIN && ovrl <= CRUENTUS_END) {
|
||
m_money += (ovrld + 1) * m_overlayCredits[OverlayCredits_Cruentus];
|
||
}
|
||
|
||
if (ovrl >= VINIFERA_BEGIN && ovrl <= VINIFERA_END) {
|
||
m_money += (ovrld + 1) * m_overlayCredits[OverlayCredits_Vinifera];
|
||
}
|
||
|
||
if (ovrl >= ABOREUS_BEGIN && ovrl <= ABOREUS_END) {
|
||
m_money += (ovrld + 1) * m_overlayCredits[OverlayCredits_Aboreus];
|
||
}
|
||
}
|
||
|
||
__forceinline void GetMiniMapPos(int i, int e, int& x, int& y)
|
||
{
|
||
const int pheight = m_mini_biinfo.bmiHeader.biHeight;
|
||
|
||
const DWORD dwIsoSize = m_IsoSize;
|
||
y = e / 2 + i / 2;
|
||
x = dwIsoSize - i + e;
|
||
|
||
int tx, ty;
|
||
tx = GetWidth();
|
||
ty = GetHeight();
|
||
|
||
ty = ty / 2 + tx / 2;
|
||
tx = dwIsoSize - GetWidth() + GetHeight();
|
||
|
||
x -= tx;
|
||
y -= ty;
|
||
|
||
x += pheight;
|
||
y += pheight / 2;
|
||
}
|
||
|
||
|
||
void Mini_UpdatePos(const int i, const int e, bool isMultiplayer);
|
||
|
||
// helper function. Is val==iSet1 or val=iSet2?
|
||
__forceinline BOOL st(int val, int iSet)
|
||
{
|
||
|
||
if (val == iSet) return TRUE;
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
public:
|
||
void RedrawMinimap();
|
||
BOOL GetInfantryINIData(int index, CString* lpINI);
|
||
|
||
|
||
#ifdef SMUDGE_SUPP
|
||
void UpdateSmudges(BOOL bSave = FALSE, int num = -1);
|
||
void DeleteSmudge(DWORD dwIndex);
|
||
BOOL AddSmudge(SMUDGE* lpSmudge);
|
||
void GetSmudgeData(DWORD dwIndex, SMUDGE* lpData) const;
|
||
void UpdateSmudgeInfo(LPCSTR lpSmudgeType = NULL);
|
||
#endif
|
||
|
||
BOOL IsYRMap();
|
||
bool IsMapSection(const CString& sectionName);
|
||
void ResizeMap(int iLeft, int iTop, DWORD dwNewWidth, DWORD dwNewHeight);
|
||
void SmoothTiberium(DWORD dwPos);
|
||
int GetPowerOfHouse(LPCTSTR lpHouse);
|
||
int GetMoneyOnMap() const;
|
||
int CalcMoneyOnMap();
|
||
void GetMinimap(BYTE** lpData, BITMAPINFO* lpBI, int* pitch);
|
||
void GetStructurePaint(int index, STRUCTUREPAINT& structurePaint) const;
|
||
void Paste(int x, int y, int z_mod);
|
||
void Copy(int left = 0, int top = 0, int right = 0, int bottom = 0);
|
||
CString GetTheater();
|
||
BOOL IsMultiplayer();
|
||
void CreateShore(int left, int top, int right, int bottom, BOOL bRemoveUseless = TRUE);
|
||
void Redo();
|
||
void SmoothAllAt(DWORD dwPos);
|
||
|
||
void SmoothAt(DWORD dwPos, int iSmoothSet, int iLatSet, int iTargetSet, BOOL bIgnoreShore = TRUE);
|
||
|
||
BOOL GetLocalSize(RECT* rect) const;
|
||
void Undo();
|
||
void TakeSnapshot(BOOL bEraseFollowing = TRUE, int left = 0, int top = 0, int right = 0, int bottom = 0);
|
||
BOOL CheckMapPackData();
|
||
int GetInfantryCountAt(DWORD dwPos);
|
||
void DeleteTube(std::uint16_t wID);
|
||
// void SetTube(WORD wID, CTube *lpTI);
|
||
void SetTube(CTube* lpTI);
|
||
CTube* GetTube(std::uint16_t wID);
|
||
};
|
||
|
||
inline bool CMapData::IsCoordInMap(int X, int Y) const
|
||
{
|
||
return
|
||
X > 0 && Y > 0 &&
|
||
X + Y > GetWidth() &&
|
||
X + Y <= GetWidth() + 2 * GetHeight() &&
|
||
(Y < GetWidth() || X > Y - GetWidth()) &&
|
||
(X < GetWidth() || X < Y + GetWidth());
|
||
}
|
||
|
||
inline bool CMapData::isInside(MapCoords xy) const
|
||
{
|
||
return xy.x >= 0 && xy.y >= 0 && xy.x < m_IsoSize&& xy.y < m_IsoSize;
|
||
}
|
||
inline bool CMapData::isInside(int x, int y) const
|
||
{
|
||
return x >= 0 && y >= 0 && x < m_IsoSize&& y < m_IsoSize;
|
||
}
|
||
|
||
inline MapCoords CMapData::ToMapCoords(ProjectedCoords xy) const
|
||
{
|
||
return ToMapCoords3d(xy, 0);
|
||
}
|
||
|
||
inline MapCoords CMapData::ToMapCoords3d(ProjectedCoords xy, int mapZ) const
|
||
{
|
||
auto const cx = static_cast<float>(xy.x);
|
||
auto const cy = static_cast<float>(xy.y + mapZ * f_y / 2);
|
||
return MapCoords(
|
||
cy / (float)f_y - cx / (float)f_x + (float)(m_IsoSize - 2) / 2 + (float)0.5,
|
||
cy / (float)f_y + cx / (float)f_x - (float)(m_IsoSize - 2) / 2.0f - (float)0.5
|
||
);
|
||
}
|
||
|
||
inline MapCoords CMapData::ToMapCoords3d(const ProjectedCoords xy, bool bAllowAccessBehindCliffs, bool ignoreHideFlagsAndOutside) const
|
||
{
|
||
auto xy2d = ToMapCoords(xy);
|
||
static const auto fxy = ProjectedVec(f_x, f_y).convertT<float>();
|
||
auto ret = ignoreHideFlagsAndOutside ? xy2d : MapCoords(-1, -1);
|
||
|
||
for (int i = 15; i >= 0; i--) {
|
||
for (int e = 0; e < 3; e++) {
|
||
const MapVec off(i, i); // this is a vertical line starting from the bottom
|
||
const MapVec off2(e == 1 ? -1 : 0, e == 2 ? -1 : 0); // increase x or y or neither in map coordinates by one so that we have a broader area to check
|
||
const MapCoords cur = xy2d + off + off2;
|
||
|
||
if (isInside(cur)) {
|
||
const auto& mfd = *GetFielddataAt(GetMapPos(cur));
|
||
const int ground = mfd.wGround == 0xFFFF ? 0 : mfd.wGround;
|
||
if (ignoreHideFlagsAndOutside || (!mfd.bHide && !(tiledata && (*tiledata)[ground].bHide))) {
|
||
const auto curProj = ProjectCoords3d(cur);
|
||
|
||
// now projCoords hold the logical pixel coordinates for the current field...
|
||
// we now need to check if cx and cy are in this field
|
||
//if(*x >= m && *x<= m+f_x && *y>=n && *y<=n+f_y)
|
||
{
|
||
auto df1 = (xy - curProj).convertT<float>();
|
||
auto dfScaled = df1 / fxy;
|
||
auto d = Vec2<CSProjected, float>(dfScaled.y - dfScaled.x + 0.5f, dfScaled.y + dfScaled.x - 0.5f);
|
||
if (d.x >= 0.0f && d.y >= 0.0f && d.x <= 1.0f && d.y <= 1.0f)// || (!bAllowAccessBehindCliffs && xy.y >= curProj.y)))
|
||
//if (d == MapCoords(0, 0))
|
||
{
|
||
if (bAllowAccessBehindCliffs)
|
||
ret = cur;
|
||
else
|
||
return cur;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
inline ProjectedCoords CMapData::ProjectCoords(MapCoords xy) const
|
||
{
|
||
return ProjectCoords3d(xy, 0);
|
||
}
|
||
|
||
inline ProjectedCoords CMapData::ProjectCoords3d(MapCoords xy, int z) const
|
||
{
|
||
return ProjectedCoords(
|
||
(m_IsoSize - 2 - xy.x + xy.y) * f_x / 2,
|
||
(xy.y + xy.x - z) * f_y / 2
|
||
);
|
||
}
|
||
|
||
inline ProjectedCoords CMapData::ProjectCoords3d(MapCoords xy) const
|
||
{
|
||
return ProjectCoords3d(xy, isInside(xy) ? GetHeightAt(xy) : 0);
|
||
}
|
||
|
||
#endif // !defined(AFX_MAP_H__9278CAC0_D4E7_11D3_B63B_444553540001__INCLUDED_)
|