2022-06-21 12:35:55 +00:00
|
|
|
#include <base/logger.h>
|
2022-03-16 16:01:23 +00:00
|
|
|
#include <base/system.h>
|
|
|
|
#include <engine/shared/datafile.h>
|
|
|
|
#include <engine/storage.h>
|
|
|
|
#include <game/gamecore.h>
|
|
|
|
#include <game/mapitems.h>
|
|
|
|
|
|
|
|
// global new layers data (set by ReplaceAreaTiles and ReplaceAreaQuads)
|
2022-06-30 22:36:32 +00:00
|
|
|
void *g_apNewData[1024];
|
|
|
|
void *g_apNewItem[1024];
|
|
|
|
int g_aNewDataSize[1024];
|
2022-03-16 16:01:23 +00:00
|
|
|
|
2022-06-20 09:55:55 +00:00
|
|
|
struct MapObject // quad pivot or tile layer
|
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
static constexpr float ms_aStandardScreen[2] = {1430 / 2.f, 1050 / 2.f};
|
2022-06-21 12:47:27 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
float m_aLayerOffset[2];
|
2022-06-21 13:21:33 +00:00
|
|
|
bool m_UseClipping;
|
2022-06-30 22:36:32 +00:00
|
|
|
float m_aaClipArea[2][2];
|
|
|
|
float m_aSpeed[2];
|
|
|
|
float m_aaScreenOffset[2][2];
|
|
|
|
float m_aaBaseArea[2][2]; // adapted to offset
|
|
|
|
float m_aaExtendedArea[2][2]; // extended with parallax
|
2022-06-20 09:55:55 +00:00
|
|
|
};
|
|
|
|
|
2022-09-15 21:19:51 +00:00
|
|
|
bool ReplaceArea(IStorage *, const char[3][64], const float[][2][2]);
|
|
|
|
bool OpenMaps(IStorage *, const char[3][64], CDataFileReader[2], CDataFileWriter &);
|
2022-06-21 13:21:33 +00:00
|
|
|
void SaveOutputMap(CDataFileReader &, CDataFileWriter &);
|
2022-09-15 21:19:51 +00:00
|
|
|
bool CompareLayers(const char[3][64], CDataFileReader[2]);
|
|
|
|
void CompareGroups(const char[3][64], CDataFileReader[2]);
|
2022-06-21 15:13:57 +00:00
|
|
|
const CMapItemGroup *GetLayerGroup(CDataFileReader &, int);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-09-15 21:19:51 +00:00
|
|
|
void ReplaceAreaTiles(CDataFileReader[2], const float[][2][2], const CMapItemGroup *[2], CMapItemLayer *[2]);
|
|
|
|
void RemoveDestinationTiles(CMapItemLayerTilemap *, CTile *, float[2][2]);
|
|
|
|
void ReplaceDestinationTiles(CMapItemLayerTilemap *[2], CTile *[2], float[2][2][2]);
|
|
|
|
bool AdaptVisibleAreas(const float[2][2][2], const MapObject[2], float[2][2][2]);
|
|
|
|
bool AdaptReplaceableAreas(const float[2][2][2], const float[2][2][2], const MapObject[2], float[2][2][2]);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-09-15 21:19:51 +00:00
|
|
|
void ReplaceAreaQuads(CDataFileReader[2], const float[][2][2], const CMapItemGroup *[2], CMapItemLayer *[2], int);
|
|
|
|
bool RemoveDestinationQuads(const float[2][2], const CQuad *, int, const CMapItemGroup *, CQuad *, int &);
|
|
|
|
bool InsertDestinationQuads(const float[2][2][2], const CQuad *, int, const CMapItemGroup *[2], CQuad *, int &);
|
|
|
|
bool AdaptVisiblePoint(const float[2][2][2], const float[2][2], const MapObject[2], float[2]);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 15:13:57 +00:00
|
|
|
MapObject CreateMapObject(const CMapItemGroup *, int, int, int, int);
|
2022-06-21 13:21:33 +00:00
|
|
|
void SetExtendedArea(MapObject &);
|
2022-10-30 12:10:53 +00:00
|
|
|
bool GetVisibleArea(const float[2][2], const MapObject &, float[2][2] = 0x0);
|
|
|
|
bool GetReplaceableArea(const float[2][2], const MapObject &, float[2][2]);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-09-15 21:19:51 +00:00
|
|
|
void GetGameAreaDistance(const float[2][2][2], const MapObject[2], const float[2][2][2], float[2]);
|
|
|
|
void GetGameAreaDistance(const float[2][2][2], const MapObject[2], const float[2][2], float[2]);
|
2022-10-30 12:10:53 +00:00
|
|
|
void GetSignificantScreenPos(const MapObject &, const float[2][2], const float[2][2], float[2]);
|
2022-09-15 21:19:51 +00:00
|
|
|
void ConvertToTiles(const float[2][2], int[2][2]);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-09-15 21:19:51 +00:00
|
|
|
bool GetLineIntersection(const float[2], const float[2], float[2] = 0x0);
|
|
|
|
bool GetLineIntersection(const float[2], float);
|
2022-06-21 15:13:57 +00:00
|
|
|
void SetInexistent(float *, int);
|
|
|
|
bool IsInexistent(const float *, int);
|
|
|
|
bool IsInexistent(float);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-03-16 16:01:23 +00:00
|
|
|
int main(int argc, const char *argv[])
|
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
CCmdlineFix CmdlineFix(&argc, &argv);
|
|
|
|
log_set_global_logger_default();
|
|
|
|
|
|
|
|
if(argc != 10)
|
|
|
|
{
|
|
|
|
dbg_msg("map_replace_area", "Invalid arguments");
|
|
|
|
dbg_msg("map_replace_area", "Usage: %s <from_map> <from_x> <from_y> <to_map> <to_x> <to_y> <width> <height> <output_map>", argv[0]);
|
|
|
|
dbg_msg("map_replace_area", "Note: use game layer tiles as a reference for both coordinates and sizes");
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
char aaMapNames[3][64];
|
2022-10-19 21:31:07 +00:00
|
|
|
str_copy(aaMapNames[0], argv[1]); //from_map
|
|
|
|
str_copy(aaMapNames[1], argv[4]); //to_map
|
|
|
|
str_copy(aaMapNames[2], argv[9]); //output_map
|
2022-06-21 12:47:27 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
float aaaGameAreas[2][2][2];
|
2022-06-21 12:47:27 +00:00
|
|
|
|
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
{
|
2022-10-19 21:18:30 +00:00
|
|
|
aaaGameAreas[i][0][0] = str_tofloat(argv[2 + i * 3]) * 32; //x
|
|
|
|
aaaGameAreas[i][1][0] = str_tofloat(argv[3 + i * 3]) * 32; //y
|
|
|
|
aaaGameAreas[i][0][1] = aaaGameAreas[i][0][0] + str_tofloat(argv[7]) * 32; //x + width
|
|
|
|
aaaGameAreas[i][1][1] = aaaGameAreas[i][1][0] + str_tofloat(argv[8]) * 32; //y + height
|
2022-06-21 12:47:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cmdline_free(argc, argv);
|
|
|
|
|
|
|
|
dbg_msg("map_replace_area", "from_map='%s'; to_map='%s'; from_area='%fx,%fy'; to_area='%fx,%fy'; area_width='%fpx'; area_heigth='%fpx'; output_map='%s'",
|
2022-06-30 22:36:32 +00:00
|
|
|
aaMapNames[0], aaMapNames[1], aaaGameAreas[0][0][0], aaaGameAreas[0][1][0], aaaGameAreas[1][0][0], aaaGameAreas[1][1][0],
|
|
|
|
aaaGameAreas[0][0][1] - aaaGameAreas[0][0][0], aaaGameAreas[0][1][1] - aaaGameAreas[0][1][0], aaMapNames[2]);
|
2022-06-21 12:47:27 +00:00
|
|
|
|
|
|
|
IStorage *pStorage = CreateLocalStorage();
|
|
|
|
for(int i = 0; i < 1024; i++)
|
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
g_apNewData[i] = g_apNewItem[i] = 0;
|
|
|
|
g_aNewDataSize[i] = 0;
|
2022-06-21 12:47:27 +00:00
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
return ReplaceArea(pStorage, aaMapNames, aaaGameAreas) ? 0 : 1;
|
2022-03-16 16:01:23 +00:00
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
bool ReplaceArea(IStorage *pStorage, const char aaMapNames[3][64], const float aaaGameAreas[][2][2])
|
2022-03-16 16:01:23 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
CDataFileReader aInputMaps[2];
|
2022-06-21 12:47:27 +00:00
|
|
|
CDataFileWriter OutputMap;
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if(!OpenMaps(pStorage, aaMapNames, aInputMaps, OutputMap))
|
2022-06-21 12:47:27 +00:00
|
|
|
return false;
|
2022-06-30 22:36:32 +00:00
|
|
|
if(!CompareLayers(aaMapNames, aInputMaps))
|
2022-06-21 12:47:27 +00:00
|
|
|
return false;
|
2022-06-30 22:36:32 +00:00
|
|
|
CompareGroups(aaMapNames, aInputMaps);
|
2022-06-21 12:47:27 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
int aLayersStart[2], LayersCount;
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < 2; i++)
|
2022-06-30 22:36:32 +00:00
|
|
|
aInputMaps[i].GetType(MAPITEMTYPE_LAYER, &aLayersStart[i], &LayersCount);
|
2022-06-21 12:47:27 +00:00
|
|
|
|
|
|
|
for(int i = 0; i < LayersCount; i++)
|
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
const CMapItemGroup *apLayerGroups[2];
|
|
|
|
CMapItemLayer *apItem[2];
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int j = 0; j < 2; j++)
|
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
apLayerGroups[j] = GetLayerGroup(aInputMaps[j], i + 1);
|
2023-02-20 22:38:54 +00:00
|
|
|
apItem[j] = (CMapItemLayer *)aInputMaps[j].GetItem(aLayersStart[j] + i);
|
2022-06-21 12:47:27 +00:00
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if(!apLayerGroups[0] || !apLayerGroups[1])
|
2022-06-21 15:13:57 +00:00
|
|
|
continue;
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if(apItem[0]->m_Type == LAYERTYPE_TILES)
|
|
|
|
ReplaceAreaTiles(aInputMaps, aaaGameAreas, apLayerGroups, apItem);
|
|
|
|
else if(apItem[0]->m_Type == LAYERTYPE_QUADS)
|
|
|
|
ReplaceAreaQuads(aInputMaps, aaaGameAreas, apLayerGroups, apItem, aLayersStart[1] + i);
|
2022-06-21 12:47:27 +00:00
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
SaveOutputMap(aInputMaps[1], OutputMap);
|
2022-06-21 12:47:27 +00:00
|
|
|
|
|
|
|
return true;
|
2022-03-16 16:01:23 +00:00
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
bool OpenMaps(IStorage *pStorage, const char aaMapNames[3][64], CDataFileReader aInputMaps[2], CDataFileWriter &OutputMap)
|
2022-03-16 16:01:23 +00:00
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
if(!aInputMaps[i].Open(pStorage, aaMapNames[i], IStorage::TYPE_ABSOLUTE))
|
2022-06-21 12:47:27 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
dbg_msg("map_replace_area", "ERROR: unable to open map '%s'", aaMapNames[i]);
|
2022-06-21 12:47:27 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if(!OutputMap.Open(pStorage, aaMapNames[2], IStorage::TYPE_ABSOLUTE))
|
2022-06-21 12:47:27 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
dbg_msg("map_replace_area", "ERROR: unable to open map '%s'", aaMapNames[2]);
|
2022-06-21 12:47:27 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2022-03-16 16:01:23 +00:00
|
|
|
}
|
|
|
|
|
2022-06-20 09:55:55 +00:00
|
|
|
void SaveOutputMap(CDataFileReader &InputMap, CDataFileWriter &OutputMap)
|
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < InputMap.NumItems(); i++)
|
|
|
|
{
|
|
|
|
int ID, Type;
|
|
|
|
void *pItem = InputMap.GetItem(i, &Type, &ID);
|
|
|
|
|
2023-12-21 23:10:34 +00:00
|
|
|
// Filter items with unknown type, as we can't write them back.
|
|
|
|
// Filter ITEMTYPE_EX items, they will be automatically added again.
|
|
|
|
if(Type < 0 || Type == ITEMTYPE_EX)
|
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
continue;
|
2023-12-21 23:10:34 +00:00
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if(g_apNewItem[i])
|
|
|
|
pItem = g_apNewItem[i];
|
2022-06-21 12:47:27 +00:00
|
|
|
|
|
|
|
int Size = InputMap.GetItemSize(i);
|
|
|
|
OutputMap.AddItem(Type, ID, Size, pItem);
|
|
|
|
}
|
|
|
|
|
|
|
|
for(int i = 0; i < InputMap.NumData(); i++)
|
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
void *pData = g_apNewData[i] ? g_apNewData[i] : InputMap.GetData(i);
|
|
|
|
int Size = g_aNewDataSize[i] ? g_aNewDataSize[i] : InputMap.GetDataSize(i);
|
2022-06-21 12:47:27 +00:00
|
|
|
OutputMap.AddData(Size, pData);
|
|
|
|
}
|
|
|
|
|
|
|
|
OutputMap.Finish();
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
bool CompareLayers(const char aaMapNames[3][64], CDataFileReader aInputMaps[2])
|
2022-03-16 16:01:23 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
int aStart[2], aNum[2];
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < 2; i++)
|
2022-06-30 22:36:32 +00:00
|
|
|
aInputMaps[i].GetType(MAPITEMTYPE_LAYER, &aStart[i], &aNum[i]);
|
2022-06-21 12:47:27 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if(aNum[0] != aNum[1])
|
2022-06-21 12:47:27 +00:00
|
|
|
{
|
2022-06-21 15:13:57 +00:00
|
|
|
dbg_msg("map_replace_area", "ERROR: different layers quantity");
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < 2; i++)
|
2022-06-30 22:36:32 +00:00
|
|
|
dbg_msg("map_replace_area", " \"%s\": %d layers", aaMapNames[i], aNum[i]);
|
2022-06-21 12:47:27 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
for(int i = 0; i < aNum[0]; i++)
|
2022-06-21 12:47:27 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
CMapItemLayer *apItem[2];
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int j = 0; j < 2; j++)
|
2023-02-20 22:38:54 +00:00
|
|
|
apItem[j] = (CMapItemLayer *)aInputMaps[j].GetItem(aStart[j] + i);
|
2022-06-21 12:47:27 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if(apItem[0]->m_Type != apItem[1]->m_Type)
|
2022-06-21 12:47:27 +00:00
|
|
|
{
|
2022-06-21 15:13:57 +00:00
|
|
|
dbg_msg("map_replace_area", "ERROR: different types on layer #%d", i);
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int j = 0; j < 2; j++)
|
2022-06-30 22:36:32 +00:00
|
|
|
dbg_msg("map_replace_area", " \"%s\": %s", aaMapNames[j], apItem[j]->m_Type == LAYERTYPE_TILES ? "tiles layer" : "quad layer");
|
2022-06-21 12:47:27 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2022-03-16 16:01:23 +00:00
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
void CompareGroups(const char aaMapNames[3][64], CDataFileReader aInputMaps[2])
|
2022-03-16 16:01:23 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
int aStart[2], aNum[2];
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < 2; i++)
|
2022-06-30 22:36:32 +00:00
|
|
|
aInputMaps[i].GetType(MAPITEMTYPE_GROUP, &aStart[i], &aNum[i]);
|
2022-06-21 12:47:27 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
for(int i = 0; i < std::max(aNum[0], aNum[1]); i++)
|
2022-06-21 12:47:27 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
CMapItemGroup *apItem[2];
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int j = 0; j < 2; j++)
|
2023-02-20 22:38:54 +00:00
|
|
|
apItem[j] = (CMapItemGroup *)aInputMaps[j].GetItem(aStart[j] + i);
|
2022-06-21 12:47:27 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
bool bSameConfig = apItem[0]->m_ParallaxX == apItem[1]->m_ParallaxX && apItem[0]->m_ParallaxY == apItem[1]->m_ParallaxY && apItem[0]->m_OffsetX == apItem[1]->m_OffsetX && apItem[0]->m_OffsetY == apItem[1]->m_OffsetY && apItem[0]->m_UseClipping == apItem[1]->m_UseClipping && apItem[0]->m_ClipX == apItem[1]->m_ClipX && apItem[0]->m_ClipY == apItem[1]->m_ClipY && apItem[0]->m_ClipW == apItem[1]->m_ClipW && apItem[0]->m_ClipH == apItem[1]->m_ClipH;
|
2022-06-21 12:47:27 +00:00
|
|
|
|
|
|
|
if(!bSameConfig)
|
2022-06-21 15:13:57 +00:00
|
|
|
dbg_msg("map_replace_area", "WARNING: different configuration on layergroup #%d, this might lead to unexpected results", i);
|
2022-06-21 12:47:27 +00:00
|
|
|
}
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
2022-03-16 16:01:23 +00:00
|
|
|
|
2022-06-21 13:21:33 +00:00
|
|
|
const CMapItemGroup *GetLayerGroup(CDataFileReader &InputMap, const int LayerNumber)
|
2022-06-20 09:55:55 +00:00
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
int Start, Num;
|
|
|
|
InputMap.GetType(MAPITEMTYPE_GROUP, &Start, &Num);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < Num; i++)
|
|
|
|
{
|
2023-02-20 22:38:54 +00:00
|
|
|
CMapItemGroup *pItem = (CMapItemGroup *)InputMap.GetItem(Start + i);
|
2022-06-21 12:47:27 +00:00
|
|
|
if(LayerNumber >= pItem->m_StartLayer && LayerNumber <= pItem->m_StartLayer + pItem->m_NumLayers)
|
|
|
|
return pItem;
|
|
|
|
}
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
return 0x0;
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
void ReplaceAreaTiles(CDataFileReader aInputMaps[2], const float aaaGameAreas[][2][2], const CMapItemGroup *apLayerGroups[2], CMapItemLayer *apItem[2])
|
2022-06-20 09:55:55 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
CMapItemLayerTilemap *apTilemap[2];
|
|
|
|
CTile *apTile[2];
|
|
|
|
float aaaVisibleAreas[2][2][2], aaaReplaceableAreas[2][2][2];
|
|
|
|
MapObject aObs[2];
|
2022-06-21 12:47:27 +00:00
|
|
|
|
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
apTilemap[i] = (CMapItemLayerTilemap *)apItem[i];
|
|
|
|
apTile[i] = (CTile *)aInputMaps[i].GetData(apTilemap[i]->m_Data);
|
|
|
|
aObs[i] = CreateMapObject(apLayerGroups[i], 0, 0, apTilemap[i]->m_Width * 32, apTilemap[i]->m_Height * 32);
|
2022-06-21 12:47:27 +00:00
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if(!GetVisibleArea(aaaGameAreas[1], aObs[1], aaaVisibleAreas[1]))
|
2022-06-21 12:47:27 +00:00
|
|
|
return;
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
GetReplaceableArea(aaaVisibleAreas[1], aObs[1], aaaReplaceableAreas[1]);
|
|
|
|
RemoveDestinationTiles(apTilemap[1], apTile[1], aaaReplaceableAreas[1]);
|
2022-06-21 12:47:27 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if(GetVisibleArea(aaaGameAreas[0], aObs[0], aaaVisibleAreas[0]) && AdaptVisibleAreas(aaaGameAreas, aObs, aaaVisibleAreas))
|
2022-06-21 12:47:27 +00:00
|
|
|
{
|
|
|
|
for(int i = 0; i < 2; i++)
|
2022-06-30 22:36:32 +00:00
|
|
|
GetReplaceableArea(aaaVisibleAreas[i], aObs[i], aaaReplaceableAreas[i]);
|
2022-06-21 12:47:27 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if(AdaptReplaceableAreas(aaaGameAreas, aaaVisibleAreas, aObs, aaaReplaceableAreas))
|
|
|
|
ReplaceDestinationTiles(apTilemap, apTile, aaaReplaceableAreas);
|
2022-06-21 12:47:27 +00:00
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
g_apNewData[apTilemap[1]->m_Data] = apTile[1];
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
void RemoveDestinationTiles(CMapItemLayerTilemap *pTilemap, CTile *pTile, float aaReplaceableArea[2][2])
|
2022-06-20 09:55:55 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
int aaRange[2][2];
|
|
|
|
ConvertToTiles(aaReplaceableArea, aaRange);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
CTile EmptyTile;
|
|
|
|
EmptyTile.m_Index = EmptyTile.m_Flags = EmptyTile.m_Skip = EmptyTile.m_Reserved = 0;
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
for(int y = aaRange[1][0]; y < aaRange[1][1]; y++)
|
|
|
|
for(int x = aaRange[0][0]; x < aaRange[0][1]; x++)
|
2022-06-21 12:47:27 +00:00
|
|
|
pTile[x + (y * pTilemap->m_Width)] = EmptyTile;
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
void ReplaceDestinationTiles(CMapItemLayerTilemap *apTilemap[2], CTile *apTile[2], float aaaReplaceableAreas[2][2][2])
|
2022-06-20 09:55:55 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
int aaaRanges[2][2][2];
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < 2; i++)
|
2022-06-30 22:36:32 +00:00
|
|
|
ConvertToTiles(aaaReplaceableAreas[i], aaaRanges[i]);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
for(int y0 = aaaRanges[0][1][0], y1 = aaaRanges[1][1][0]; y0 < aaaRanges[0][1][1] && y1 < aaaRanges[1][1][1]; y0++, y1++)
|
|
|
|
for(int x0 = aaaRanges[0][0][0], x1 = aaaRanges[1][0][0]; x0 < aaaRanges[0][0][1] && x1 < aaaRanges[1][0][1]; x0++, x1++)
|
|
|
|
apTile[1][x1 + (y1 * apTilemap[1]->m_Width)] = apTile[0][x0 + (y0 * apTilemap[0]->m_Width)];
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
bool AdaptVisibleAreas(const float aaaGameAreas[2][2][2], const MapObject aObs[2], float aaaVisibleAreas[2][2][2])
|
2022-06-20 09:55:55 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
float aDistance[2];
|
|
|
|
GetGameAreaDistance(aaaGameAreas, aObs, aaaVisibleAreas, aDistance);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
if(aObs[0].m_aSpeed[i] == 1 || aObs[1].m_aSpeed[i] == 1)
|
2022-06-21 12:47:27 +00:00
|
|
|
continue;
|
2022-03-16 16:01:23 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int j = 0; j < 2; j++)
|
2022-06-30 22:36:32 +00:00
|
|
|
aaaVisibleAreas[1][i][j] -= aDistance[i];
|
2022-03-16 16:01:23 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if(!GetLineIntersection(aaaVisibleAreas[0][i], aaaVisibleAreas[1][i], aaaVisibleAreas[0][i]))
|
2022-06-21 12:47:27 +00:00
|
|
|
return false;
|
2022-03-16 16:01:23 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int j = 0; j < 2; j++)
|
2022-06-30 22:36:32 +00:00
|
|
|
aaaVisibleAreas[1][i][j] = aaaVisibleAreas[0][i][j] + aDistance[i];
|
2022-06-21 12:47:27 +00:00
|
|
|
}
|
2022-03-16 16:01:23 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
return true;
|
2022-03-16 16:01:23 +00:00
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
bool AdaptReplaceableAreas(const float aaaGameAreas[2][2][2], const float aaaVisibleAreas[2][2][2], const MapObject aObs[2], float aaaReplaceableAreas[2][2][2])
|
2022-03-16 16:01:23 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
float aDistance[2], aScreenPos[2];
|
|
|
|
GetGameAreaDistance(aaaGameAreas, aObs, aaaVisibleAreas, aDistance);
|
|
|
|
GetSignificantScreenPos(aObs[0], aaaVisibleAreas[0], aaaReplaceableAreas[0], aScreenPos);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
float aDestLine[2], aSourceLine[2], aVisibleLine[2];
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
aDestLine[0] = aObs[1].m_aaBaseArea[i][0] + (aScreenPos[i] + aDistance[i]) * aObs[1].m_aSpeed[i];
|
|
|
|
aDestLine[1] = aDestLine[0] + (aObs[1].m_aaBaseArea[i][1] - aObs[1].m_aaBaseArea[i][0]);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if(!GetLineIntersection(aDestLine, aaaVisibleAreas[1][i], aVisibleLine))
|
2022-06-21 12:47:27 +00:00
|
|
|
return false;
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
aSourceLine[0] = aaaVisibleAreas[0][i][0] + aDistance[i] - aaaReplaceableAreas[0][i][0];
|
|
|
|
aSourceLine[1] = aaaVisibleAreas[0][i][1] + aDistance[i] + aaaReplaceableAreas[0][i][1] - aaaReplaceableAreas[0][i][0];
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if(!GetLineIntersection(aSourceLine, aVisibleLine, aVisibleLine))
|
2022-06-21 12:47:27 +00:00
|
|
|
return false;
|
2022-03-16 16:01:23 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
aaaReplaceableAreas[0][i][0] = aVisibleLine[0] - aSourceLine[0];
|
|
|
|
aaaReplaceableAreas[1][i][0] = aVisibleLine[0] - aDestLine[0];
|
2022-06-21 12:47:27 +00:00
|
|
|
}
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
return true;
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
void ReplaceAreaQuads(CDataFileReader aInputMaps[2], const float aaaGameAreas[][2][2], const CMapItemGroup *apLayerGroups[2], CMapItemLayer *apItem[2], const int ItemNumber)
|
2022-06-20 09:55:55 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
CMapItemLayerQuads *apQuadLayer[2];
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < 2; i++)
|
2022-06-30 22:36:32 +00:00
|
|
|
apQuadLayer[i] = (CMapItemLayerQuads *)apItem[i];
|
2022-06-21 12:47:27 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
CQuad *apQuads[3];
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < 2; i++)
|
2022-06-30 22:36:32 +00:00
|
|
|
apQuads[i] = (CQuad *)aInputMaps[i].GetDataSwapped(apQuadLayer[i]->m_Data);
|
2022-06-21 12:47:27 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
apQuads[2] = new CQuad[apQuadLayer[0]->m_NumQuads + apQuadLayer[1]->m_NumQuads];
|
2022-06-21 12:47:27 +00:00
|
|
|
int QuadsCounter = 0;
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
bool bDataChanged = RemoveDestinationQuads(aaaGameAreas[1], apQuads[1], apQuadLayer[1]->m_NumQuads, apLayerGroups[1], apQuads[2], QuadsCounter);
|
|
|
|
bDataChanged |= InsertDestinationQuads(aaaGameAreas, apQuads[0], apQuadLayer[0]->m_NumQuads, apLayerGroups, apQuads[2], QuadsCounter);
|
2022-06-21 12:47:27 +00:00
|
|
|
|
|
|
|
if(bDataChanged)
|
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
g_apNewData[apQuadLayer[1]->m_Data] = apQuads[2];
|
|
|
|
g_aNewDataSize[apQuadLayer[1]->m_Data] = ((int)sizeof(CQuad)) * QuadsCounter;
|
|
|
|
apQuadLayer[1]->m_NumQuads = QuadsCounter;
|
|
|
|
g_apNewItem[ItemNumber] = apItem[1];
|
2022-06-21 12:47:27 +00:00
|
|
|
}
|
|
|
|
else
|
2022-06-30 22:36:32 +00:00
|
|
|
delete[] apQuads[2];
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
bool RemoveDestinationQuads(const float aaGameArea[2][2], const CQuad *pQuads, const int NumQuads, const CMapItemGroup *pLayerGroup, CQuad *pDestQuads, int &QuadsCounter)
|
2022-06-20 09:55:55 +00:00
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
bool bDataChanged = false;
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < NumQuads; i++)
|
|
|
|
{
|
|
|
|
MapObject Ob = CreateMapObject(pLayerGroup, fx2f(pQuads[i].m_aPoints[4].x), fx2f(pQuads[i].m_aPoints[4].y), 0, 0);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if(GetVisibleArea(aaGameArea, Ob))
|
2022-06-21 12:47:27 +00:00
|
|
|
{
|
|
|
|
bDataChanged = true;
|
|
|
|
continue;
|
|
|
|
}
|
2022-03-16 16:01:23 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
pDestQuads[QuadsCounter] = pQuads[i];
|
|
|
|
QuadsCounter++;
|
|
|
|
}
|
2022-03-16 16:01:23 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
return bDataChanged;
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
bool InsertDestinationQuads(const float aaaGameAreas[2][2][2], const CQuad *pQuads, const int NumQuads, const CMapItemGroup *apLayerGroups[2], CQuad *pDestQuads, int &QuadsCounter)
|
2022-06-20 09:55:55 +00:00
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
bool bDataChanged = false;
|
|
|
|
|
|
|
|
for(int i = 0; i < NumQuads; i++)
|
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
MapObject aObs[2];
|
|
|
|
aObs[0] = CreateMapObject(apLayerGroups[0], fx2f(pQuads[i].m_aPoints[4].x), fx2f(pQuads[i].m_aPoints[4].y), 0, 0);
|
|
|
|
float aaVisibleArea[2][2];
|
2022-06-21 12:47:27 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if(GetVisibleArea(aaaGameAreas[0], aObs[0], aaVisibleArea))
|
2022-06-21 12:47:27 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
float aQuadPos[2];
|
|
|
|
aObs[1] = CreateMapObject(apLayerGroups[1], 0, 0, 0, 0);
|
2022-06-21 12:47:27 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if(!AdaptVisiblePoint(aaaGameAreas, aaVisibleArea, aObs, aQuadPos))
|
2022-06-21 12:47:27 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
pDestQuads[QuadsCounter] = pQuads[i];
|
2022-06-21 19:04:54 +00:00
|
|
|
for(auto &Point : pDestQuads[QuadsCounter].m_aPoints)
|
2022-06-21 12:47:27 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
Point.x += f2fx(aQuadPos[0]) - pDestQuads[QuadsCounter].m_aPoints[4].x;
|
|
|
|
Point.y += f2fx(aQuadPos[1]) - pDestQuads[QuadsCounter].m_aPoints[4].y;
|
2022-06-21 12:47:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QuadsCounter++;
|
|
|
|
bDataChanged = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return bDataChanged;
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
bool AdaptVisiblePoint(const float aaaGameAreas[2][2][2], const float aaVisibleArea[2][2], const MapObject aObs[2], float aPos[2])
|
2022-06-20 09:55:55 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
float aDistance[2], aScreenPos[2];
|
|
|
|
GetGameAreaDistance(aaaGameAreas, aObs, aaVisibleArea, aDistance);
|
|
|
|
GetSignificantScreenPos(aObs[0], aaVisibleArea, 0x0, aScreenPos);
|
2022-06-21 12:47:27 +00:00
|
|
|
|
|
|
|
for(int i = 0; i < 2; i++)
|
2022-06-30 22:36:32 +00:00
|
|
|
aPos[i] = aaVisibleArea[i][0] + aDistance[i] + aObs[1].m_aLayerOffset[i] - (aScreenPos[i] + aDistance[i]) * aObs[1].m_aSpeed[i];
|
2022-06-21 13:21:33 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
MapObject FinalOb = aObs[1];
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < 2; i++)
|
2022-06-30 22:36:32 +00:00
|
|
|
FinalOb.m_aaBaseArea[i][0] = FinalOb.m_aaBaseArea[i][1] += aPos[i];
|
2022-06-21 12:47:27 +00:00
|
|
|
SetExtendedArea(FinalOb);
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
return GetVisibleArea(aaaGameAreas[1], FinalOb);
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MapObject CreateMapObject(const CMapItemGroup *pLayerGroup, const int PosX, const int PosY, const int Width, const int Height)
|
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
MapObject Ob;
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
Ob.m_aaBaseArea[0][0] = PosX - pLayerGroup->m_OffsetX;
|
|
|
|
Ob.m_aaBaseArea[1][0] = PosY - pLayerGroup->m_OffsetY;
|
|
|
|
Ob.m_aaBaseArea[0][1] = Ob.m_aaBaseArea[0][0] + Width;
|
|
|
|
Ob.m_aaBaseArea[1][1] = Ob.m_aaBaseArea[1][0] + Height;
|
|
|
|
Ob.m_aLayerOffset[0] = pLayerGroup->m_OffsetX;
|
|
|
|
Ob.m_aLayerOffset[1] = pLayerGroup->m_OffsetY;
|
2022-06-21 13:21:33 +00:00
|
|
|
Ob.m_UseClipping = pLayerGroup->m_UseClipping;
|
2022-06-30 22:36:32 +00:00
|
|
|
Ob.m_aaClipArea[0][0] = pLayerGroup->m_ClipX;
|
|
|
|
Ob.m_aaClipArea[1][0] = pLayerGroup->m_ClipY;
|
|
|
|
Ob.m_aaClipArea[0][1] = pLayerGroup->m_ClipX + pLayerGroup->m_ClipW;
|
|
|
|
Ob.m_aaClipArea[1][1] = pLayerGroup->m_ClipY + pLayerGroup->m_ClipH;
|
|
|
|
Ob.m_aSpeed[0] = 1 - (pLayerGroup->m_ParallaxX / 100.0f);
|
|
|
|
Ob.m_aSpeed[1] = 1 - (pLayerGroup->m_ParallaxY / 100.0f);
|
2022-06-21 12:47:27 +00:00
|
|
|
|
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
{
|
2023-10-06 10:26:33 +00:00
|
|
|
Ob.m_aaScreenOffset[i][0] = -MapObject::ms_aStandardScreen[i];
|
|
|
|
Ob.m_aaScreenOffset[i][1] = MapObject::ms_aStandardScreen[i];
|
2022-06-30 22:36:32 +00:00
|
|
|
if(Ob.m_aSpeed[i] < 0)
|
|
|
|
std::swap(Ob.m_aaScreenOffset[i][0], Ob.m_aaScreenOffset[i][1]);
|
2022-06-21 12:47:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SetExtendedArea(Ob);
|
|
|
|
return Ob;
|
2022-03-16 16:01:23 +00:00
|
|
|
}
|
|
|
|
|
2022-06-20 09:55:55 +00:00
|
|
|
void SetExtendedArea(MapObject &Ob)
|
2022-03-16 16:01:23 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
SetInexistent((float *)Ob.m_aaExtendedArea, 4);
|
2022-06-21 12:47:27 +00:00
|
|
|
|
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
if(Ob.m_aSpeed[i] == 1)
|
2022-06-21 13:21:33 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
float aInspectedArea[2];
|
|
|
|
if(GetLineIntersection(Ob.m_aaBaseArea[i], Ob.m_aaScreenOffset[i], aInspectedArea))
|
2023-03-09 10:49:56 +00:00
|
|
|
mem_copy(Ob.m_aaExtendedArea[i], aInspectedArea, sizeof(float[2]));
|
2022-06-21 12:47:27 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(int j = 0; j < 2; j++)
|
2022-06-30 22:36:32 +00:00
|
|
|
Ob.m_aaExtendedArea[i][j] = (Ob.m_aaBaseArea[i][j] + Ob.m_aaScreenOffset[i][j] * Ob.m_aSpeed[i]) / (1 - Ob.m_aSpeed[i]);
|
2022-06-21 13:21:33 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if(Ob.m_aaExtendedArea[i][0] > Ob.m_aaExtendedArea[i][1])
|
|
|
|
std::swap(Ob.m_aaExtendedArea[i][0], Ob.m_aaExtendedArea[i][1]);
|
2022-06-21 12:47:27 +00:00
|
|
|
}
|
2022-03-16 16:01:23 +00:00
|
|
|
}
|
|
|
|
|
2022-10-30 12:10:53 +00:00
|
|
|
bool GetVisibleArea(const float aaGameArea[2][2], const MapObject &Ob, float aaVisibleArea[2][2])
|
2022-03-16 16:01:23 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
if(IsInexistent((float *)Ob.m_aaExtendedArea, 4))
|
2022-06-21 12:47:27 +00:00
|
|
|
return false;
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if(aaVisibleArea)
|
|
|
|
SetInexistent((float *)aaVisibleArea, 4);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
float aaInspectedArea[2][2];
|
2023-03-09 10:49:56 +00:00
|
|
|
mem_copy(aaInspectedArea, aaGameArea, sizeof(float[2][2]));
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
if(Ob.m_aSpeed[i] == 1)
|
2022-06-21 12:47:27 +00:00
|
|
|
{
|
2023-03-09 10:49:56 +00:00
|
|
|
mem_copy(aaInspectedArea[i], Ob.m_aaExtendedArea[i], sizeof(float[2]));
|
2022-06-21 12:47:27 +00:00
|
|
|
continue;
|
|
|
|
}
|
2022-03-16 16:01:23 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if(Ob.m_UseClipping && !GetLineIntersection(aaInspectedArea[i], Ob.m_aaClipArea[i], aaInspectedArea[i]))
|
2022-06-21 12:47:27 +00:00
|
|
|
return false;
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if(!GetLineIntersection(aaInspectedArea[i], Ob.m_aaExtendedArea[i], aaInspectedArea[i]))
|
2022-06-21 12:47:27 +00:00
|
|
|
return false;
|
|
|
|
}
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if(aaVisibleArea)
|
2023-03-09 10:49:56 +00:00
|
|
|
mem_copy(aaVisibleArea, aaInspectedArea, sizeof(float[2][2]));
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
return true;
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
2022-10-30 12:10:53 +00:00
|
|
|
bool GetReplaceableArea(const float aaVisibleArea[2][2], const MapObject &Ob, float aaReplaceableArea[2][2])
|
2022-06-20 09:55:55 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
SetInexistent((float *)aaReplaceableArea, 4);
|
|
|
|
if(IsInexistent((float *)aaVisibleArea, 4))
|
2022-06-21 12:47:27 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
for(int i = 0; i < 2; i++)
|
2022-06-21 13:21:33 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
if(Ob.m_aSpeed[i] == 1)
|
2022-06-21 12:47:27 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
aaReplaceableArea[i][0] = aaVisibleArea[i][0] - Ob.m_aaBaseArea[i][0];
|
|
|
|
aaReplaceableArea[i][1] = aaVisibleArea[i][1] - Ob.m_aaBaseArea[i][0];
|
2022-06-21 12:47:27 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(int j = 0; j < 2; j++)
|
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
float aVisibleLine[2], aReplaceableLine[2];
|
|
|
|
int k = Ob.m_aSpeed[i] > 1 ? !j : j;
|
2022-06-21 12:47:27 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
aVisibleLine[0] = Ob.m_aaBaseArea[i][0] + (aaVisibleArea[i][j] - Ob.m_aaScreenOffset[i][k]) * Ob.m_aSpeed[i];
|
|
|
|
aVisibleLine[1] = aVisibleLine[0] + Ob.m_aaBaseArea[i][1] - Ob.m_aaBaseArea[i][0];
|
2022-06-21 12:47:27 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if(GetLineIntersection(aaVisibleArea[i], aVisibleLine, aReplaceableLine))
|
|
|
|
aaReplaceableArea[i][k] = aReplaceableLine[j] - aVisibleLine[0];
|
2022-06-21 12:47:27 +00:00
|
|
|
else
|
2022-06-30 22:36:32 +00:00
|
|
|
aaReplaceableArea[i][k] = k * (Ob.m_aaBaseArea[i][1] - Ob.m_aaBaseArea[i][0]);
|
2022-06-21 12:47:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
void GetGameAreaDistance(const float aaaGameAreas[2][2][2], const MapObject aObs[2], const float aaaVisibleAreas[2][2][2], float aDistance[2])
|
2022-06-20 09:55:55 +00:00
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
if(aObs[0].m_aSpeed[i] == 1 && aObs[1].m_aSpeed[i] == 1)
|
|
|
|
aDistance[i] = 0;
|
|
|
|
else if(aObs[0].m_aSpeed[i] == 1 && aObs[1].m_aSpeed[i] != 1)
|
|
|
|
aDistance[i] = aaaGameAreas[1][i][0] - aaaVisibleAreas[0][i][0];
|
|
|
|
else if(aObs[0].m_aSpeed[i] != 1 && aObs[1].m_aSpeed[i] == 1)
|
|
|
|
aDistance[i] = aaaVisibleAreas[1][i][0] - aaaGameAreas[0][i][0];
|
2022-06-21 12:47:27 +00:00
|
|
|
else
|
2022-06-30 22:36:32 +00:00
|
|
|
aDistance[i] = aaaGameAreas[1][i][0] - aaaGameAreas[0][i][0];
|
2022-06-21 12:47:27 +00:00
|
|
|
}
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
2022-03-16 16:01:23 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
void GetGameAreaDistance(const float aaaGameAreas[2][2][2], const MapObject aObs[2], const float aaVisibleArea[2][2], float aDistance[2])
|
2022-06-20 09:55:55 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
float aaaVisibleAreas[2][2][2];
|
2023-03-09 10:49:56 +00:00
|
|
|
mem_copy(aaaVisibleAreas[0], aaVisibleArea[0], sizeof(float[2][2]));
|
|
|
|
mem_copy(aaaVisibleAreas[1], aaVisibleArea[0], sizeof(float[2][2]));
|
2022-06-30 22:36:32 +00:00
|
|
|
GetGameAreaDistance(aaaGameAreas, aObs, aaaVisibleAreas, aDistance);
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
2022-10-30 12:10:53 +00:00
|
|
|
void GetSignificantScreenPos(const MapObject &Ob, const float aaVisibleArea[2][2], const float aaReplaceableArea[2][2], float aScreen[2])
|
2022-06-20 09:55:55 +00:00
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
if(!Ob.m_aSpeed[i])
|
2022-06-21 12:47:27 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
aScreen[i] = aaVisibleArea[i][0] + Ob.m_aaScreenOffset[i][1];
|
2022-06-21 12:47:27 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
float BaseOffset = aaReplaceableArea ? aaReplaceableArea[i][0] : 0;
|
|
|
|
aScreen[i] = (aaVisibleArea[i][0] - Ob.m_aaBaseArea[i][0] - BaseOffset) / Ob.m_aSpeed[i];
|
2022-06-21 12:47:27 +00:00
|
|
|
}
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
void ConvertToTiles(const float aaArea[2][2], int aaTiles[2][2])
|
2022-06-20 09:55:55 +00:00
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < 2; i++)
|
|
|
|
{
|
2023-02-28 20:31:40 +00:00
|
|
|
aaTiles[i][0] = std::floor((std::floor(aaArea[i][0] * 100.0f) / 100.0f) / 32.0f);
|
|
|
|
aaTiles[i][1] = std::ceil((std::floor(aaArea[i][1] * 100.0f) / 100.0f) / 32.0f);
|
2022-06-21 12:47:27 +00:00
|
|
|
}
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
bool GetLineIntersection(const float aLine1[2], const float aLine2[2], float aIntersection[2])
|
2022-06-20 09:55:55 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
float aBorders[2] = {
|
|
|
|
std::max(aLine1[0], aLine2[0]),
|
|
|
|
std::min(aLine1[1], aLine2[1])};
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if(aIntersection)
|
|
|
|
SetInexistent((float *)aIntersection, 2);
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if(aBorders[0] - aBorders[1] > 0.01f)
|
2022-06-21 12:47:27 +00:00
|
|
|
return false;
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
if(aIntersection)
|
2023-03-09 10:49:56 +00:00
|
|
|
mem_copy(aIntersection, aBorders, sizeof(float[2]));
|
2022-06-20 09:55:55 +00:00
|
|
|
|
2022-06-21 12:47:27 +00:00
|
|
|
return true;
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
bool GetLineIntersection(const float aLine[2], const float Point)
|
2022-06-20 09:55:55 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
return aLine[0] - Point <= 0.01f && aLine[1] - Point >= 0.01f;
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SetInexistent(float *pArray, const int Count)
|
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < Count; i++)
|
2022-06-21 19:04:54 +00:00
|
|
|
pArray[i] = std::numeric_limits<float>::max();
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool IsInexistent(const float *pArray, const int Count)
|
|
|
|
{
|
2022-06-21 12:47:27 +00:00
|
|
|
for(int i = 0; i < Count; i++)
|
2022-06-21 19:04:54 +00:00
|
|
|
if(pArray[i] == std::numeric_limits<float>::max())
|
2022-06-21 12:47:27 +00:00
|
|
|
return true;
|
|
|
|
return false;
|
2022-06-20 09:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool IsInexistent(const float Value)
|
|
|
|
{
|
2022-06-21 19:04:54 +00:00
|
|
|
return Value == std::numeric_limits<float>::max();
|
2022-03-16 18:09:29 +00:00
|
|
|
}
|