1#include <base/logger.h>
2#include <base/system.h>
3#include <engine/shared/datafile.h>
4#include <engine/storage.h>
5#include <game/mapitems.h>
6
7struct EnvelopedQuad
8{
9 int m_GroupId;
10 int m_LayerId;
11 int m_TilePosX;
12 int m_TilePosY;
13};
14
15bool OpenMap(const char pMapName[64], CDataFileReader &InputMap)
16{
17 IStorage *pStorage = CreateLocalStorage();
18
19 if(!InputMap.Open(pStorage, pFilename: pMapName, StorageType: IStorage::TYPE_ABSOLUTE))
20 {
21 dbg_msg(sys: "map_find_env", fmt: "ERROR: unable to open map '%s'", pMapName);
22 return false;
23 }
24 return true;
25}
26
27bool GetLayerGroupIds(CDataFileReader &InputMap, const int LayerNumber, int &GroupId, int &LayerRelativeId)
28{
29 int Start, Num;
30 InputMap.GetType(Type: MAPITEMTYPE_GROUP, pStart: &Start, pNum: &Num);
31
32 for(int i = 0; i < Num; i++)
33 {
34 CMapItemGroup *pItem = (CMapItemGroup *)InputMap.GetItem(Index: Start + i);
35 if(LayerNumber >= pItem->m_StartLayer && LayerNumber <= pItem->m_StartLayer + pItem->m_NumLayers)
36 {
37 GroupId = i;
38 LayerRelativeId = LayerNumber - pItem->m_StartLayer - 1;
39 return true;
40 }
41 }
42
43 return false;
44}
45
46int FxToTilePos(const int FxPos)
47{
48 return std::floor(x: fx2f(v: FxPos) / 32);
49}
50
51bool GetEnvelopedQuads(const CQuad *pQuads, const int NumQuads, const int EnvId, const int GroupId, const int LayerId, int &QuadsCounter, EnvelopedQuad pEnvQuads[1024])
52{
53 bool bFound = false;
54 for(int i = 0; i < NumQuads; i++)
55 {
56 if(pQuads[i].m_PosEnv != EnvId && pQuads[i].m_ColorEnv != EnvId)
57 continue;
58
59 pEnvQuads[QuadsCounter].m_GroupId = GroupId;
60 pEnvQuads[QuadsCounter].m_LayerId = LayerId;
61 pEnvQuads[QuadsCounter].m_TilePosX = FxToTilePos(FxPos: pQuads[i].m_aPoints[4].x);
62 pEnvQuads[QuadsCounter].m_TilePosY = FxToTilePos(FxPos: pQuads[i].m_aPoints[4].y);
63
64 QuadsCounter++;
65 bFound = true;
66 }
67
68 return bFound;
69}
70
71void PrintEnvelopedQuads(const EnvelopedQuad pEnvQuads[1024], const int EnvId, const int QuadsCounter)
72{
73 if(!QuadsCounter)
74 {
75 dbg_msg(sys: "map_find_env", fmt: "No quads found with env number #%d", EnvId + 1);
76 return;
77 }
78
79 dbg_msg(sys: "map_find_env", fmt: "Found %d quads with env number #%d:", QuadsCounter, EnvId + 1);
80 for(int i = 0; i < QuadsCounter; i++)
81 dbg_msg(sys: "map_find_env", fmt: "%*d. Group: #%d - Layer: #%d - Pos: %d,%d", (int)(std::log10(x: absolute(a: QuadsCounter))) + 1, i + 1, pEnvQuads[i].m_GroupId, pEnvQuads[i].m_LayerId, pEnvQuads[i].m_TilePosX, pEnvQuads[i].m_TilePosY);
82}
83
84bool FindEnv(const char aFilename[64], const int EnvId)
85{
86 CDataFileReader InputMap;
87 if(!OpenMap(pMapName: aFilename, InputMap))
88 return false;
89
90 int LayersStart, LayersCount, QuadsCounter = 0;
91 InputMap.GetType(Type: MAPITEMTYPE_LAYER, pStart: &LayersStart, pNum: &LayersCount);
92 EnvelopedQuad pEnvQuads[1024];
93
94 for(int i = 0; i < LayersCount; i++)
95 {
96 CMapItemLayer *pItem;
97 pItem = (CMapItemLayer *)InputMap.GetItem(Index: LayersStart + i);
98
99 if(pItem->m_Type != LAYERTYPE_QUADS)
100 continue;
101
102 CMapItemLayerQuads *pQuadLayer = (CMapItemLayerQuads *)pItem;
103 CQuad *pQuads = (CQuad *)InputMap.GetDataSwapped(Index: pQuadLayer->m_Data);
104
105 int GroupId = 0, LayerRelativeId = 0;
106 if(!GetLayerGroupIds(InputMap, LayerNumber: i + 1, GroupId, LayerRelativeId))
107 return false;
108
109 GetEnvelopedQuads(pQuads, NumQuads: pQuadLayer->m_NumQuads, EnvId, GroupId, LayerId: LayerRelativeId, QuadsCounter, pEnvQuads);
110 }
111
112 PrintEnvelopedQuads(pEnvQuads, EnvId, QuadsCounter);
113
114 return true;
115}
116
117int main(int argc, const char **argv)
118{
119 CCmdlineFix CmdlineFix(&argc, &argv);
120 log_set_global_logger_default();
121
122 if(argc < 3)
123 {
124 dbg_msg(sys: "map_find_env", fmt: "Invalid arguments");
125 dbg_msg(sys: "map_find_env", fmt: "Usage: %s <input_map> <env_number>", argv[0]);
126 dbg_msg(sys: "map_find_env", fmt: "Note: returned quads positions are relative to their layers");
127
128 return -1;
129 }
130
131 char aFilename[64];
132 str_copy(dst&: aFilename, src: argv[1]);
133 int EnvId = str_toint(str: argv[2]) - 1;
134 dbg_msg(sys: "map_find_env", fmt: "input_map='%s'; env_number='#%d';", aFilename, EnvId + 1);
135
136 return FindEnv(aFilename, EnvId);
137}
138