UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
checkentities.cpp
Go to the documentation of this file.
1 
5 /*
6 All original material Copyright (C) 2002-2020 UFO: Alien Invasion.
7 
8 Copyright (C) 1997-2001 Id Software, Inc.
9 
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
14 
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 
19 See the GNU General Public License for more details.
20 
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 
25 */
26 
27 #include "checkentities.h"
28 #include "../../../shared/mathlib.h"
29 #include "../../../shared/entitiesdef.h"
30 #include "../common/shared.h"
31 #include "../bsp.h"
32 #include "checklib.h"
33 
34 #define MIN_TILE_SIZE 256
36 static int numToMoveToWorldspawn = 0;
37 
38 static void Check_MapSize (vec3_t mapSize);
40 
41 
47 static bool Check_IsInfoStart(const char* classname)
48 {
49  return Q_strstart(classname, "info_") && strstr(classname, "_start");
50 }
51 
58 static 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)
63  Sys_Error("%s", ED_GetLastError());
64 
65  return (((int)e->origin[0] - size[0]) % UNIT_SIZE == 0)
66  && (((int)e->origin[1] - size[1]) % UNIT_SIZE == 0);
67 }
68 
73 static 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 
90 static 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 
112 void 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 */
129  if (Check_IsInfoStart(name) && !Check_InfoStartAligned(ed, e))
130  Check_Printf(VERB_CHECK, false, i, -1, "Misaligned %s\n", name);
131 
132  if (Q_strstart(name, "func_")) /* func_* entities should have brushes */
133  Check_EntityWithBrushes(e, name, i);
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 
181 void 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 
226 static 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 
261  brushesToMove = Mem_AllocTypeN(mapbrush_t* , numToMoveToWorldspawn);
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 ED_CheckKey(const entityKeyDef_t *kd, const char *value)
as ED_Check, but where the entity and key are known, so takes different arguments.
Performs check on a loaded mapfile, and makes changes that can be saved back to the source map...
#define Mem_AllocTypeN(type, n)
Definition: mem.h:38
void setNegativeVolume()
Sets mins and maxs to their starting points before using addPoint.
Definition: aabb.h:98
void Sys_Error(const char *error,...)
Definition: g_main.cpp:421
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
vec3_t origin
Definition: bspfile.h:47
const entityDef_t * ED_GetEntityDef(const char *classname)
searches for the parsed entity def by classname
struct epair_s * next
Definition: bspfile.h:37
bool skip
Definition: bspfile.h:51
char * defaultVal
Definition: entitiesdef.h:66
int firstbrush
Definition: bspfile.h:48
void Check_InitEntityDefs(void)
Definition: checklib.cpp:131
Definition: aabb.h:42
entityDef_t entityDefs[ED_MAX_DEFS+1]
Definition: entitiesdef.cpp:46
#define UNIT_HEIGHT
Definition: defines.h:122
winding_t * winding
Definition: map.h:63
int numsides
Definition: map.h:83
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
const char * value
Definition: bspfile.h:39
int nummapbrushes
Definition: map.cpp:35
#define MIN_TILE_SIZE
entity_t entities[MAX_MAP_ENTITIES]
Definition: bspfile.cpp:395
void getDiagonal(vec3_t diagonal) const
Definition: aabb.h:159
#define Q_strvalid(string)
Definition: shared.h:141
mapbrush_t mapbrushes[MAX_MAP_BRUSHES]
Definition: map.cpp:34
int nummapplanes
Definition: map.cpp:44
void SetKeyValue(entity_t *ent, const char *key, const char *value)
Definition: bspfile.cpp:546
void add(const vec3_t point)
If the point is outside the box, expand the box to accommodate it.
Definition: aabb.cpp:57
GLsizei size
Definition: r_gl.h:152
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 ...
char const * Q_strstart(char const *str, char const *start)
Matches the start of a string.
Definition: shared.cpp:587
struct side_s * original_sides
Definition: map.h:84
struct mapbrush_s * brush
Definition: map.h:72
int numEntityDefs
Definition: entitiesdef.cpp:45
for storing the vertices of the side of a brush or other polygon
Definition: polylib.h:30
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
void Verb_Printf(const verbosityLevel_t importance, const char *format,...) __attribute__((format(__printf__
static bool Check_TargetExists(const epair_t *kvp)
check targets exist (targetname), and check targetnames are targetted (target)
#define UNIT_SIZE
Definition: defines.h:121
char * classname
Definition: entitiesdef.h:74
static void Check_EntityWithBrushes(entity_t *e, const char *classname, int entnum)
int numbrushes
Definition: bspfile.h:49
static int numToMoveToWorldspawn
const char * ED_GetLastError(void)
QGL_EXTERN GLint i
Definition: r_gl.h:113
vec3_t p[4]
Definition: polylib.h:32
const char * key
Definition: bspfile.h:38
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition: r_gl.h:110
Definition: map.h:75
#define Mem_Free(ptr)
Definition: mem.h:35
void Check_Stats(void)
print map stats on -stats
void CheckEntities(void)
Perform an entity check.
int ED_GetIntVector(const entityKeyDef_t *kd, int v[], const int n)
parses a value from the definition
vec_t vec3_t[3]
Definition: ufotypes.h:39
#define Q_streq(a, b)
Definition: shared.h:136
const char * ValueForKey(const entity_t *ent, const char *key)
Definition: bspfile.cpp:558
static bool Check_IsInfoStart(const char *classname)
see if the entity is am actor start point
#define ED_MANDATORY
Definition: entitiesdef.h:36
static bool Check_InfoStartAligned(const entityDef_t *ed, const entity_t *e)
check alignment using abstract size and mandatory origin
#define ED_ERROR
Definition: entitiesdef.h:32
int num_entities
Definition: bspfile.cpp:394
epair_t * epairs
Definition: bspfile.h:50
int nummapbrushsides
Definition: map.cpp:38
entityKeyDef_t * keyDefs
Definition: entitiesdef.h:75
int numpoints
Definition: polylib.h:31