UFO: Alien Invasion
Loading...
Searching...
No Matches
checkentities.cpp
Go to the documentation of this file.
1
4
5/*
6All original material Copyright (C) 2002-2025 UFO: Alien Invasion.
7
8Copyright (C) 1997-2001 Id Software, Inc.
9
10This program is free software; you can redistribute it and/or
11modify it under the terms of the GNU General Public License
12as published by the Free Software Foundation; either version 2
13of the License, or (at your option) any later version.
14
15This program is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18
19See the GNU General Public License for more details.
20
21You should have received a copy of the GNU General Public License
22along with this program; if not, write to the Free Software
23Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
25*/
26
27#include "checkentities.h"
30#include "../common/shared.h"
31#include "../bsp.h"
32#include "checklib.h"
33
34#define MIN_TILE_SIZE 256
35
36static int numToMoveToWorldspawn = 0;
37
38static void Check_MapSize (vec3_t mapSize);
40
41
47static bool Check_IsInfoStart(const char* classname)
48{
49 return Q_strstart(classname, "info_") && strstr(classname, "_start");
50}
51
58static bool Check_InfoStartAligned (const entityDef_t* ed, const entity_t* e)
59{
60 static int size[6];
61 const entityKeyDef_t* sizeKd = ED_GetKeyDefEntity(ed, "size", 1); /* 1 means find abstract version of key */
62 if (ED_GetIntVector(sizeKd, size, (int)(sizeof(size) / sizeof(int))) == ED_ERROR)
64
65 return (((int)e->origin[0] - size[0]) % UNIT_SIZE == 0)
66 && (((int)e->origin[1] - size[1]) % UNIT_SIZE == 0);
67}
68
73static bool Check_TargetExists (const epair_t* kvp)
74{
75 const char* thisKey = kvp->key;
76 const char* value = kvp->value;
77 const char* otherKey = Q_streq("target", thisKey) ? "targetname" : "target";
78
79 for (int i = 0; i < num_entities; i++) {
80 const entity_t* e = &entities[i];
81 const char* searchVal = ValueForKey(e, otherKey);
82
83 if (searchVal && Q_streq(searchVal, value))
84 return true;
85 }
86
87 return false;
88}
89
90static void Check_EntityWithBrushes (entity_t* e, const char* classname, int entnum)
91{
92 if (!e->numbrushes) {
93 Check_Printf(VERB_CHECK, true, entnum, -1, "%s with no brushes given - will be deleted\n", classname);
94 e->skip = true;
95 return;
96 }
97
98 if (e->numbrushes > 1 && Q_streq(classname, "func_breakable")) {
99 Check_Printf(VERB_CHECK, false, entnum, -1, "func_breakable with more than one brush given (might break pathfinding)\n");
100 }
101
102 if (e->numbrushes == 1 && Q_streq(classname, "func_group")) {
103 Check_Printf(VERB_CHECK, true, entnum, -1, "%s with one brush only - will be moved to worldspawn\n", classname);
105 e->skip = true;
106 }
107}
108
112void CheckEntities (void)
113{
115
116 for (int i = 0; i < num_entities; i++) {
117 entity_t* e = &entities[i];
118 const char* name = ValueForKey(e, "classname");
119 const entityDef_t* ed = ED_GetEntityDef(name);
120 const epair_t* kvp;
121 const entityKeyDef_t* kd;
122
123 if (!ed) { /* check that a definition exists */
124 Check_Printf(VERB_CHECK, false, i, -1, "Not defined in entities.ufo: %s\n", name);
125 continue;
126 }
127
128 /* check alignment of info_.+_start */
130 Check_Printf(VERB_CHECK, false, i, -1, "Misaligned %s\n", name);
131
132 if (Q_strstart(name, "func_")) /* func_* entities should have brushes */
134
135 /* check all keys in the entity - make sure they are OK */
136 for (kvp = e->epairs; kvp; kvp = kvp->next) {
137 kd = ED_GetKeyDefEntity(ed, kvp->key, 0); /* zero means ignore abstract (radiant only) keys */
138
139 if (!kd) { /* make sure it has a definition */
140 Check_Printf(VERB_CHECK, false, i, -1, "Not defined in entities.ufo: %s in %s\n", kvp->key, name);
141 continue;
142 }
143
144 if (ED_CheckKey(kd, kvp->value) == ED_ERROR) { /* check values against type and range definitions in entities.ufo */
145 Check_Printf(VERB_CHECK, false, i, -1, "%s\n", ED_GetLastError());
146 continue;
147 }
148
149 if (Q_streq("target", kvp->key) || Q_streq("targetname", kvp->key)) {
150 if (!Check_TargetExists(kvp)) {
151 Check_Printf(VERB_CHECK, false, i, -1,
152 "%s with %s of %s: no corresponding entity with %s with matching value\n",
153 ed->classname, kvp->key, kvp->value, Q_streq("target", kvp->key) ? "targetname" : "target");
154 }
155 }
156 }
157
158 /* check keys in the entity definition - make sure mandatory ones are present */
159 for (kd = ed->keyDefs; kd->name; kd++) {
160 if (!(kd->flags & ED_MANDATORY))
161 continue;
162 const char* keyNameInEnt = ValueForKey(e, kd->name);
163 if (Q_strvalid(keyNameInEnt))
164 continue;
165 const char* defaultVal = kd->defaultVal;
166 const bool hasDefault = defaultVal ? true : false;
167 Check_Printf(VERB_CHECK, hasDefault, i, -1, "Mandatory key missing from entity: %s in %s", kd->name, name);
168 if (defaultVal) {
169 Check_Printf(VERB_CHECK, hasDefault, i, -1, ", supplying default: %s", defaultVal);
170 SetKeyValue(e, kd->name, defaultVal);
171 }
172 Check_Printf(VERB_CHECK, hasDefault, i, -1, "\n");
173 }
174 }
175}
176
177
181void Check_Stats(void) {
182 vec3_t worldSize;
183 int j;
184 int* entNums;
185
187
188 entNums = Mem_AllocTypeN(int, numEntityDefs);
189
190 Check_MapSize(worldSize);
191 Verb_Printf(VERB_NORMAL, " Number of brushes: %i\n",nummapbrushes);
192 Verb_Printf(VERB_NORMAL, " Number of planes: %i\n",nummapplanes);
193 Verb_Printf(VERB_NORMAL, " Number of brush sides: %i\n",nummapbrushsides);
194 Verb_Printf(VERB_NORMAL, " Map size (units): %.0f %.0f %.0f\n", worldSize[0], worldSize[1], worldSize[2]);
195 Verb_Printf(VERB_NORMAL, " Map size (fields): %.0f %.0f %.0f\n", worldSize[0] / UNIT_SIZE, worldSize[1] / UNIT_SIZE, worldSize[2] / UNIT_HEIGHT);
196 Verb_Printf(VERB_NORMAL, " Map size (tiles): %.0f %.0f %.0f\n", worldSize[0] / (MIN_TILE_SIZE), worldSize[1] / (MIN_TILE_SIZE), worldSize[2] / UNIT_HEIGHT);
197 Verb_Printf(VERB_NORMAL, " Number of entities: %i\n", num_entities);
198
199 /* count number of each type of entity */
200 for (int i = 0; i < num_entities; i++) {
201 const char* name = ValueForKey(&entities[i], "classname");
202
203 for (j = 0; j < numEntityDefs; j++)
204 if (Q_streq(name, entityDefs[j].classname)) {
205 entNums[j]++;
206 break;
207 }
208 if (j == numEntityDefs) {
209 Com_Printf("Check_Stats: entity '%s' not recognised\n", name);
210 }
211 }
212
213 /* print number of each type of entity */
214 for (j = 0; j < numEntityDefs; j++)
215 if (entNums[j])
216 Com_Printf("%27s: %i\n", entityDefs[j].classname, entNums[j]);
217
218 Mem_Free(entNums);
219}
220
221
226static void Check_MapSize (vec3_t mapSize)
227{
228 AABB mapBox;
229
230 mapBox.setNegativeVolume();
231
232 for (int i = 0; i < nummapbrushes; i++) {
233 const mapbrush_t* brush = &mapbrushes[i];
234
235 for (int bi = 0; bi < brush->numsides; bi++) {
236 const winding_t* winding = brush->original_sides[bi].winding;
237
238 for (int vi = 0; vi < winding->numpoints; vi++)
239 mapBox.add(winding->p[vi]);
240 }
241 }
242 mapBox.getDiagonal(mapSize);
243}
244
252{
253 int i, j;
254 mapbrush_t** brushesToMove;
255
256 *numBrushes = numToMoveToWorldspawn;
257
259 return nullptr;
260
262 if (!brushesToMove)
263 Sys_Error("Check_ExtraBrushesForWorldspawn: out of memory");
264
265 /* 0 is the world - start at 1 */
266 for (i = 1, j = 0; i < num_entities; i++) {
267 const entity_t* e = &entities[i];
268 const char* name = ValueForKey(e, "classname");
269
270 if (e->numbrushes == 1 && Q_streq(name, "func_group")) {
271 assert(j < numToMoveToWorldspawn);
272 brushesToMove[j++] = &mapbrushes[e->firstbrush];
273 }
274 }
275
276 return brushesToMove;
277}
int nummapbrushsides
Definition map.cpp:38
int nummapbrushes
Definition map.cpp:35
int nummapplanes
Definition map.cpp:44
mapbrush_t mapbrushes[MAX_MAP_BRUSHES]
Definition map.cpp:34
void SetKeyValue(entity_t *ent, const char *key, const char *value)
Definition bspfile.cpp:546
int num_entities
Definition bspfile.cpp:394
entity_t entities[MAX_MAP_ENTITIES]
Definition bspfile.cpp:395
const char * ValueForKey(const entity_t *ent, const char *key)
Definition bspfile.cpp:558
static void Check_EntityWithBrushes(entity_t *e, const char *classname, int entnum)
#define MIN_TILE_SIZE
void Check_Stats(void)
print map stats on -stats
static bool Check_IsInfoStart(const char *classname)
see if the entity is am actor start point
static bool Check_TargetExists(const epair_t *kvp)
check targets exist (targetname), and check targetnames are targetted (target)
static void Check_MapSize(vec3_t mapSize)
mapbrush_t ** Check_ExtraBrushesForWorldspawn(int *numBrushes)
single brushes in func_groups are moved to worldspawn. this function allocates space for pointers to ...
void CheckEntities(void)
Perform an entity check.
static int numToMoveToWorldspawn
static bool Check_InfoStartAligned(const entityDef_t *ed, const entity_t *e)
check alignment using abstract size and mandatory origin
void Check_InitEntityDefs(void)
Definition checklib.cpp:131
void Check_Printf(verbosityLevel_t msgVerbLevel, bool change, int entnum, int brushnum, const char *format,...)
decides wether to proceed with output based on verbosity and ufo2map's mode: check/fix/compile
Definition checklib.cpp:49
Performs check on a loaded mapfile, and makes changes that can be saved back to the source map.
Definition aabb.h:42
void setNegativeVolume()
Sets mins and maxs to their starting points before using addPoint.
Definition aabb.h:98
void getDiagonal(vec3_t diagonal) const
Definition aabb.h:159
void add(const vec3_t point)
If the point is outside the box, expand the box to accommodate it.
Definition aabb.cpp:57
void Com_Printf(const char *const fmt,...)
Definition common.cpp:428
#define UNIT_HEIGHT
Definition defines.h:122
#define UNIT_SIZE
Definition defines.h:121
int numEntityDefs
int ED_CheckKey(const entityKeyDef_t *kd, const char *value)
as ED_Check, but where the entity and key are known, so takes different arguments.
const entityKeyDef_t * ED_GetKeyDefEntity(const entityDef_t *ed, const char *keyname, const int abstract)
searches for the parsed key def, when the entity def is known
int ED_GetIntVector(const entityKeyDef_t *kd, int v[], const int n)
parses a value from the definition
const char * ED_GetLastError(void)
entityDef_t entityDefs[ED_MAX_DEFS+1]
const entityDef_t * ED_GetEntityDef(const char *classname)
searches for the parsed entity def by classname
Handles definition of entities, parsing them from entities.ufo.
#define ED_ERROR
Definition entitiesdef.h:32
#define ED_MANDATORY
Definition entitiesdef.h:36
void Sys_Error(const char *error,...)
Definition g_main.cpp:421
voidpf void uLong size
Definition ioapi.h:42
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
#define Mem_Free(ptr)
Definition mem.h:35
#define Mem_AllocTypeN(type, n)
Definition mem.h:38
QGL_EXTERN GLint i
Definition r_gl.h:113
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition r_gl.h:110
#define Q_strvalid(string)
Definition shared.h:141
#define Q_streq(a, b)
Definition shared.h:136
char const * Q_strstart(char const *str, char const *start)
Matches the start of a string.
Definition shared.cpp:587
epair_t * epairs
Definition bspfile.h:50
int numbrushes
Definition bspfile.h:49
int firstbrush
Definition bspfile.h:48
bool skip
Definition bspfile.h:51
vec3_t origin
Definition r_entity.h:101
char * classname
Definition entitiesdef.h:74
entityKeyDef_t * keyDefs
Definition entitiesdef.h:75
char * defaultVal
Definition entitiesdef.h:66
const char * key
Definition bspfile.h:38
struct epair_s * next
Definition bspfile.h:37
const char * value
Definition bspfile.h:39
struct side_s * original_sides
Definition map.h:84
int numsides
Definition map.h:83
for storing the vertices of the side of a brush or other polygon
Definition polylib.h:30
int numpoints
Definition polylib.h:31
vec3_t p[4]
Definition polylib.h:32
void Verb_Printf(const verbosityLevel_t importance, const char *format,...) __attribute__((format(__printf__
@ VERB_NORMAL
Definition shared.h:45
@ VERB_CHECK
Definition shared.h:42
vec_t vec3_t[3]
Definition ufotypes.h:39