1 /*
2 ===========================================================================
3 Copyright (C) 1999 - 2005, Id Software, Inc.
4 Copyright (C) 2000 - 2013, Raven Software, Inc.
5 Copyright (C) 2001 - 2013, Activision, Inc.
6 Copyright (C) 2013 - 2015, OpenJK contributors
7 
8 This file is part of the OpenJK source code.
9 
10 OpenJK is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License version 2 as
12 published by the Free Software Foundation.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, see <http://www.gnu.org/licenses/>.
21 ===========================================================================
22 */
23 
24 #include "../cgame/cg_local.h"
25 #include "Q3_Interface.h"
26 #include "g_local.h"
27 #include "g_functions.h"
28 
29 extern cvar_t *g_spskill;
30 extern cvar_t *g_delayedShutdown;
31 
32 // these vars I moved here out of the level_locals_t struct simply because it's pointless to try saving them,
33 //	and the level_locals_t struct is included in the save process... -slc
34 //
35 qboolean	spawning = qfalse;				// the G_Spawn*() functions are valid  (only turned on during one function)
36 int			numSpawnVars;
37 char		*spawnVars[MAX_SPAWN_VARS][2];	// key / value pairs
38 int			numSpawnVarChars;
39 char		spawnVarChars[MAX_SPAWN_VARS_CHARS];
40 
41 int			delayedShutDown = 0;
42 
43 #include "../qcommon/sstring.h"
44 
45 //NOTENOTE: Be sure to change the mirrored code in cgmain.cpp
46 typedef	std::map< sstring_t, unsigned char  >	namePrecache_m;
47 namePrecache_m	*as_preCacheMap = NULL;
48 
49 char *G_AddSpawnVarToken( const char *string );
50 
AddSpawnField(char * field,char * value)51 void AddSpawnField(char *field, char *value)
52 {
53 	int	i;
54 
55 	for(i=0;i<numSpawnVars;i++)
56 	{
57 		if (Q_stricmp(spawnVars[i][0], field) == 0)
58 		{
59 			spawnVars[ i ][1] = G_AddSpawnVarToken( value );
60 			return;
61 		}
62 	}
63 
64 	spawnVars[ numSpawnVars ][0] = G_AddSpawnVarToken( field );
65 	spawnVars[ numSpawnVars ][1] = G_AddSpawnVarToken( value );
66 	numSpawnVars++;
67 }
68 
G_SpawnField(unsigned int uiField,char ** ppKey,char ** ppValue)69 qboolean	G_SpawnField( unsigned int uiField, char **ppKey, char **ppValue )
70 {
71 	if ( (int)uiField >= numSpawnVars )
72 		return qfalse;
73 
74 	(*ppKey) = spawnVars[uiField][0];
75 	*ppValue = spawnVars[uiField][1];
76 
77 	return qtrue;
78 }
79 
G_SpawnString(const char * key,const char * defaultString,char ** out)80 qboolean	G_SpawnString( const char *key, const char *defaultString, char **out ) {
81 	int		i;
82 
83 	if ( !spawning ) {
84 		*out = (char *)defaultString;
85 //		G_Error( "G_SpawnString() called while not spawning" );
86 	}
87 
88 	for ( i = 0 ; i < numSpawnVars ; i++ ) {
89 		if ( !Q_stricmp( key, spawnVars[i][0] ) ) {
90 			*out = spawnVars[i][1];
91 			return qtrue;
92 		}
93 	}
94 
95 	*out = (char *)defaultString;
96 	return qfalse;
97 }
98 
G_SpawnFloat(const char * key,const char * defaultString,float * out)99 qboolean	G_SpawnFloat( const char *key, const char *defaultString, float *out ) {
100 	char		*s;
101 	qboolean	present;
102 
103 	present = G_SpawnString( key, defaultString, &s );
104 	*out = atof( s );
105 	return present;
106 }
107 
G_SpawnInt(const char * key,const char * defaultString,int * out)108 qboolean	G_SpawnInt( const char *key, const char *defaultString, int *out ) {
109 	char		*s;
110 	qboolean	present;
111 
112 	present = G_SpawnString( key, defaultString, &s );
113 	*out = atoi( s );
114 	return present;
115 }
116 
G_SpawnVector(const char * key,const char * defaultString,float * out)117 qboolean	G_SpawnVector( const char *key, const char *defaultString, float *out ) {
118 	char		*s;
119 	qboolean	present;
120 
121 	present = G_SpawnString( key, defaultString, &s );
122 	sscanf( s, "%f %f %f", &out[0], &out[1], &out[2] );
123 	return present;
124 }
125 
G_SpawnVector4(const char * key,const char * defaultString,float * out)126 qboolean	G_SpawnVector4( const char *key, const char *defaultString, float *out ) {
127 	char		*s;
128 	qboolean	present;
129 
130 	present = G_SpawnString( key, defaultString, &s );
131 	sscanf( s, "%f %f %f %f", &out[0], &out[1], &out[2], &out[3] );
132 	return present;
133 }
134 
G_SpawnFlag(const char * key,int flag,int * out)135 qboolean	G_SpawnFlag( const char *key, int flag, int *out )
136 {
137 	//find that key
138 	for ( int i = 0 ; i < numSpawnVars ; i++ )
139 	{
140 		if ( !strcmp( key, spawnVars[i][0] ) )
141 		{
142 			//found the key
143 			if ( atoi( spawnVars[i][1] ) != 0 )
144 			{//if it's non-zero, and in the flag
145 				*out |= flag;
146 			}
147 			else
148 			{//if it's zero, or out the flag
149 				*out &= ~flag;
150 			}
151 			return qtrue;
152 		}
153 	}
154 
155 	return qfalse;
156 }
157 
G_SpawnAngleHack(const char * key,const char * defaultString,float * out)158 qboolean G_SpawnAngleHack( const char *key, const char *defaultString, float *out )
159 {
160 	char		*s;
161 	qboolean	present;
162 	float		temp = 0;
163 
164 	present = G_SpawnString( key, defaultString, &s );
165 	sscanf( s, "%f", &temp );
166 
167 	out[0] = 0;
168 	out[1] = temp;
169 	out[2] = 0;
170 
171 	return present;
172 }
173 
174 stringID_table_t flagTable [] =
175 {
176 	//"noTED", EF_NO_TED,
177 	//stringID_table_t Must end with a null entry
178 	{ "", 0 }
179 };
180 
181 //
182 // fields are needed for spawning from the entity string
183 //
184 typedef enum {
185 	F_INT,
186 	F_FLOAT,
187 	F_LSTRING,			// string on disk, pointer in memory, TAG_LEVEL
188 	F_GSTRING,			// string on disk, pointer in memory, TAG_GAME
189 	F_VECTOR,
190 	F_VECTOR4,
191 	F_ANGLEHACK,
192 	F_ENTITY,			// index on disk, pointer in memory
193 	F_ITEM,				// index on disk, pointer in memory
194 	F_CLIENT,			// index on disk, pointer in memory
195 	F_PARM1,			// Special case for parms
196 	F_PARM2,			// Special case for parms
197 	F_PARM3,			// Special case for parms
198 	F_PARM4,			// Special case for parms
199 	F_PARM5,			// Special case for parms
200 	F_PARM6,			// Special case for parms
201 	F_PARM7,			// Special case for parms
202 	F_PARM8,			// Special case for parms
203 	F_PARM9,			// Special case for parms
204 	F_PARM10,			// Special case for parms
205 	F_PARM11,			// Special case for parms
206 	F_PARM12,			// Special case for parms
207 	F_PARM13,			// Special case for parms
208 	F_PARM14,			// Special case for parms
209 	F_PARM15,			// Special case for parms
210 	F_PARM16,			// Special case for parms
211 	F_FLAG,				// special case for flags
212 	F_IGNORE
213 } fieldtype_t;
214 
215 typedef struct
216 {
217 	const char	*name;
218 	size_t		ofs;
219 	fieldtype_t	type;
220 	int		flags;
221 } field_t;
222 
223 field_t fields[] = {
224 	//Fields for benefit of Radiant only
225 	{"autobound", FOFS(classname), F_IGNORE},
226 	{"groupname", FOFS(classname), F_IGNORE},
227 	{"noBasicSounds", FOFS(classname), F_IGNORE},//will be looked at separately
228 	{"noCombatSounds", FOFS(classname), F_IGNORE},//will be looked at separately
229 	{"noExtraSounds", FOFS(classname), F_IGNORE},//will be looked at separately
230 
231 	{"classname", FOFS(classname), F_LSTRING},
232 	{"origin", FOFS(s.origin), F_VECTOR},
233 	{"mins", FOFS(mins), F_VECTOR},
234 	{"maxs", FOFS(maxs), F_VECTOR},
235 	{"model", FOFS(model), F_LSTRING},
236 	{"model2", FOFS(model2), F_LSTRING},
237 	{"model3", FOFS(target), F_LSTRING},//for misc_replicator_item only!!!
238 	{"model4", FOFS(target2), F_LSTRING},//for misc_replicator_item only!!!
239 	{"model5", FOFS(target3), F_LSTRING},//for misc_replicator_item only!!!
240 	{"model6", FOFS(target4), F_LSTRING},//for misc_replicator_item only!!!
241 	{"spawnflags", FOFS(spawnflags), F_INT},
242 	{"speed", FOFS(speed), F_FLOAT},
243 	{"duration", FOFS(speed), F_FLOAT},//for psycho jism
244 	{"interest", FOFS(health), F_INT},//For target_interest
245 	{"target", FOFS(target), F_LSTRING},
246 	{"target2", FOFS(target2), F_LSTRING},
247 	{"target3", FOFS(target3), F_LSTRING},
248 	{"target4", FOFS(target4), F_LSTRING},
249 	{"targetJump", FOFS(targetJump), F_LSTRING},
250 	{"targetname", FOFS(targetname), F_LSTRING},
251 	{"material", FOFS(material), F_INT},
252 	{"message", FOFS(message), F_LSTRING},
253 	{"team", FOFS(team), F_LSTRING},
254 	{"mapname", FOFS(message), F_LSTRING},
255 	{"wait", FOFS(wait), F_FLOAT},
256 	{"finaltime", FOFS(wait), F_FLOAT},//For dlight
257 	{"random", FOFS(random), F_FLOAT},
258 	{"FOV", FOFS(random), F_FLOAT},//for ref_tags and trigger_visibles
259 	{"count", FOFS(count), F_INT},
260 	{"bounceCount", FOFS(bounceCount), F_INT},
261 	{"health", FOFS(health), F_INT},
262 	{"friction", FOFS(health), F_INT},//For target_friction_change
263 	{"light", 0, F_IGNORE},
264 	{"dmg", FOFS(damage), F_INT},
265 	{"angles", FOFS(s.angles), F_VECTOR},
266 	{"angle", FOFS(s.angles), F_ANGLEHACK},
267 	{"modelAngles", FOFS(modelAngles), F_VECTOR},
268 	{"cameraGroup", FOFS(cameraGroup), F_LSTRING},
269 	{"radius", FOFS(radius), F_FLOAT},
270 	{"hiderange", FOFS(radius), F_FLOAT},//for triggers only
271 	{"starttime", FOFS(radius), F_FLOAT},//for dlight
272 	{"turfrange", FOFS(radius), F_FLOAT},//for sand creatures
273 	{"type", FOFS(count), F_FLOAT},//for fx_crew_beam_in
274 	{"fxfile", FOFS(fxFile), F_LSTRING},
275 	{"fxfile2", FOFS(cameraGroup), F_LSTRING},
276 	{"noVisTime", FOFS(endFrame), F_INT},//for NPC_Vehicle
277 	{"endFrame", FOFS(endFrame), F_INT},//for func_usable shader animation
278 	{"linear", FOFS(alt_fire), F_INT},//for movers to use linear movement
279 	{"weapon",FOFS(paintarget),F_LSTRING},//for misc_weapon_shooter only
280 
281 //Script parms - will this handle clamping to 16 or whatever length of parm[0] is?
282 	{"parm1", 0, F_PARM1},
283 	{"parm2", 0, F_PARM2},
284 	{"parm3", 0, F_PARM3},
285 	{"parm4", 0, F_PARM4},
286 	{"parm5", 0, F_PARM5},
287 	{"parm6", 0, F_PARM6},
288 	{"parm7", 0, F_PARM7},
289 	{"parm8", 0, F_PARM8},
290 	{"parm9", 0, F_PARM9},
291 	{"parm10", 0, F_PARM10},
292 	{"parm11", 0, F_PARM11},
293 	{"parm12", 0, F_PARM12},
294 	{"parm13", 0, F_PARM13},
295 	{"parm14", 0, F_PARM14},
296 	{"parm15", 0, F_PARM15},
297 	{"parm16", 0, F_PARM16},
298 	//{"noTED", FOFS(s.eFlags), F_FLAG},
299 
300 //MCG - Begin
301 	//extra fields for ents
302 	{"delay", FOFS(delay), F_INT},
303 	{"sounds", FOFS(sounds), F_INT},
304 	{"closetarget", FOFS(closetarget), F_LSTRING},//for doors
305 	{"opentarget", FOFS(opentarget), F_LSTRING},//for doors
306 	{"paintarget", FOFS(paintarget), F_LSTRING},//for doors
307 	{"soundGroup", FOFS(paintarget), F_LSTRING},//for target_speakers
308 	{"backwardstarget", FOFS(paintarget), F_LSTRING},//for trigger_bidirectional
309 	{"splashDamage", FOFS(splashDamage), F_INT},
310 	{"splashRadius", FOFS(splashRadius), F_INT},
311 	//Script stuff
312 	{"spawnscript", FOFS(behaviorSet[BSET_SPAWN]), F_LSTRING},//name of script to run
313 	{"usescript", FOFS(behaviorSet[BSET_USE]), F_LSTRING},//name of script to run
314 	{"awakescript", FOFS(behaviorSet[BSET_AWAKE]), F_LSTRING},//name of script to run
315 	{"angerscript", FOFS(behaviorSet[BSET_ANGER]), F_LSTRING},//name of script to run
316 	{"attackscript", FOFS(behaviorSet[BSET_ATTACK]), F_LSTRING},//name of script to run
317 	{"victoryscript", FOFS(behaviorSet[BSET_VICTORY]), F_LSTRING},//name of script to run
318 	{"lostenemyscript", FOFS(behaviorSet[BSET_LOSTENEMY]), F_LSTRING},//name of script to run
319 	{"painscript", FOFS(behaviorSet[BSET_PAIN]), F_LSTRING},//name of script to run
320 	{"fleescript", FOFS(behaviorSet[BSET_FLEE]), F_LSTRING},//name of script to run
321 	{"deathscript", FOFS(behaviorSet[BSET_DEATH]), F_LSTRING},//name of script to run
322 	{"delayscript", FOFS(behaviorSet[BSET_DELAYED]), F_LSTRING},//name of script to run
323 	{"delayscripttime", FOFS(delayScriptTime), F_INT},//name of script to run
324 	{"blockedscript", FOFS(behaviorSet[BSET_BLOCKED]), F_LSTRING},//name of script to run
325 	{"ffirescript", FOFS(behaviorSet[BSET_FFIRE]), F_LSTRING},//name of script to run
326 	{"ffdeathscript", FOFS(behaviorSet[BSET_FFDEATH]), F_LSTRING},//name of script to run
327 	{"mindtrickscript", FOFS(behaviorSet[BSET_MINDTRICK]), F_LSTRING},//name of script to run
328 	{"script_targetname", FOFS(script_targetname), F_LSTRING},//scripts look for this when "affecting"
329 	//For NPCs
330 	//{"playerTeam", FOFS(playerTeam), F_INT},
331 	//{"enemyTeam", FOFS(enemyTeam), F_INT},
332 	{"NPC_targetname", FOFS(NPC_targetname), F_LSTRING},
333 	{"NPC_target", FOFS(NPC_target), F_LSTRING},
334 	{"NPC_target2", FOFS(target2), F_LSTRING},//NPC_spawner only
335 	{"NPC_target4", FOFS(target4), F_LSTRING},//NPC_spawner only
336 	{"NPC_type", FOFS(NPC_type), F_LSTRING},
337 	{"ownername", FOFS(ownername), F_LSTRING},
338 	//for weapon_saber
339 	{"saberType", FOFS(NPC_type), F_LSTRING},
340 	{"saberColor", FOFS(NPC_targetname), F_LSTRING},
341 	{"saberLeftHand", FOFS(alt_fire), F_INT},
342 	{"saberSolo", FOFS(loopAnim), F_INT},
343 	{"saberPitch", FOFS(random), F_FLOAT},
344 	//freaky camera shit
345 	{"startRGBA", FOFS(startRGBA), F_VECTOR4},
346 	{"finalRGBA", FOFS(finalRGBA), F_VECTOR4},
347 //MCG - End
348 
349 	{"soundSet", FOFS(soundSet), F_LSTRING},
350 	{"mass", FOFS(mass), F_FLOAT},		//really only used for pushable misc_model_breakables
351 
352 //q3map stuff
353 	{"scale", 0, F_IGNORE},
354 	{"modelscale", 0, F_IGNORE},
355 	{"modelscale_vec", 0, F_IGNORE},
356 	{"style", 0, F_IGNORE},
357 	{"lip", 0, F_IGNORE},
358 	{"switch_style", 0, F_IGNORE},
359 	{"height", 0, F_IGNORE},
360 	{"noise", 0, F_IGNORE},	//SP_target_speaker
361 	{"gravity", 0, F_IGNORE},	//SP_target_gravity_change
362 
363 	{"storyhead", 0, F_IGNORE},		//SP_target_level_change
364 	{"tier_storyinfo", 0, F_IGNORE},	//SP_target_level_change
365 	{"zoffset", 0, F_IGNORE},		//used by misc_model_static
366 	{"music", 0, F_IGNORE},		//used by target_play_music
367 	{"forcevisible", 0, F_IGNORE},		//for force sight on multiple model entities
368 	{"redcrosshair", 0, F_IGNORE},		//for red crosshairs on breakables
369 	{"nodelay", 0, F_IGNORE},		//for Reborn & Cultist NPCs
370 
371 	{NULL}
372 };
373 
374 
375 typedef struct {
376 	const char	*name;
377 	void	(*spawn)(gentity_t *ent);
378 } spawn_t;
379 
380 void SP_info_player_start (gentity_t *ent);
381 void SP_info_player_deathmatch (gentity_t *ent);
382 void SP_info_player_intermission (gentity_t *ent);
383 void SP_info_firstplace(gentity_t *ent);
384 void SP_info_secondplace(gentity_t *ent);
385 void SP_info_thirdplace(gentity_t *ent);
386 
387 void SP_func_plat (gentity_t *ent);
388 void SP_func_static (gentity_t *ent);
389 void SP_func_rotating (gentity_t *ent);
390 void SP_func_bobbing (gentity_t *ent);
391 void SP_func_breakable (gentity_t *self);
392 void SP_func_glass( gentity_t *self );
393 void SP_func_pendulum( gentity_t *ent );
394 void SP_func_button (gentity_t *ent);
395 void SP_func_door (gentity_t *ent);
396 void SP_func_train (gentity_t *ent);
397 void SP_func_timer (gentity_t *self);
398 void SP_func_wall (gentity_t *ent);
399 void SP_func_usable( gentity_t *self );
400 void SP_rail_mover( gentity_t *self );
401 void SP_rail_track( gentity_t *self );
402 void SP_rail_lane( gentity_t *self );
403 
404 
405 
406 void SP_trigger_always (gentity_t *ent);
407 void SP_trigger_multiple (gentity_t *ent);
408 void SP_trigger_once (gentity_t *ent);
409 void SP_trigger_push (gentity_t *ent);
410 void SP_trigger_teleport (gentity_t *ent);
411 void SP_trigger_hurt (gentity_t *ent);
412 void SP_trigger_bidirectional (gentity_t *ent);
413 void SP_trigger_entdist (gentity_t *self);
414 void SP_trigger_location( gentity_t *ent );
415 void SP_trigger_visible( gentity_t *self );
416 void SP_trigger_space(gentity_t *self);
417 void SP_trigger_shipboundary(gentity_t *self);
418 
419 void SP_target_give (gentity_t *ent);
420 void SP_target_delay (gentity_t *ent);
421 void SP_target_speaker (gentity_t *ent);
422 void SP_target_print (gentity_t *ent);
423 void SP_target_laser (gentity_t *self);
424 void SP_target_character (gentity_t *ent);
425 void SP_target_score( gentity_t *ent );
426 void SP_target_teleporter( gentity_t *ent );
427 void SP_target_relay (gentity_t *ent);
428 void SP_target_kill (gentity_t *ent);
429 void SP_target_position (gentity_t *ent);
430 void SP_target_location (gentity_t *ent);
431 void SP_target_push (gentity_t *ent);
432 void SP_target_random (gentity_t *self);
433 void SP_target_counter (gentity_t *self);
434 void SP_target_scriptrunner (gentity_t *self);
435 void SP_target_interest (gentity_t *self);
436 void SP_target_activate (gentity_t *self);
437 void SP_target_deactivate (gentity_t *self);
438 void SP_target_gravity_change( gentity_t *self );
439 void SP_target_friction_change( gentity_t *self );
440 void SP_target_level_change( gentity_t *self );
441 void SP_target_change_parm( gentity_t *self );
442 void SP_target_play_music( gentity_t *self );
443 void SP_target_autosave( gentity_t *self );
444 void SP_target_secret( gentity_t *self );
445 
446 void SP_light (gentity_t *self);
447 void SP_info_null (gentity_t *self);
448 void SP_info_notnull (gentity_t *self);
449 void SP_path_corner (gentity_t *self);
450 
451 void SP_misc_teleporter (gentity_t *self);
452 void SP_misc_teleporter_dest (gentity_t *self);
453 void SP_misc_model(gentity_t *ent);
454 void SP_misc_model_static(gentity_t *ent);
455 void SP_misc_turret (gentity_t *base);
456 void SP_misc_ns_turret (gentity_t *base);
457 void SP_laser_arm (gentity_t *base);
458 void SP_misc_ion_cannon( gentity_t *ent );
459 void SP_misc_maglock( gentity_t *ent );
460 void SP_misc_panel_turret( gentity_t *ent );
461 void SP_misc_model_welder( gentity_t *ent );
462 void SP_misc_model_jabba_cam( gentity_t *ent );
463 
464 void SP_misc_model_shield_power_converter( gentity_t *ent );
465 void SP_misc_model_ammo_power_converter( gentity_t *ent );
466 void SP_misc_model_bomb_planted( gentity_t *ent );
467 void SP_misc_model_beacon( gentity_t *ent );
468 
469 void SP_misc_shield_floor_unit( gentity_t *ent );
470 void SP_misc_ammo_floor_unit( gentity_t *ent );
471 
472 void SP_misc_model_gun_rack( gentity_t *ent );
473 void SP_misc_model_ammo_rack( gentity_t *ent );
474 void SP_misc_model_cargo_small( gentity_t *ent );
475 
476 void SP_misc_exploding_crate( gentity_t *ent );
477 void SP_misc_gas_tank( gentity_t *ent );
478 void SP_misc_crystal_crate( gentity_t *ent );
479 void SP_misc_atst_drivable( gentity_t *ent );
480 
481 void SP_misc_model_breakable(gentity_t *ent);//stays as an ent
482 void SP_misc_model_ghoul(gentity_t *ent);//stays as an ent
483 void SP_misc_portal_camera(gentity_t *ent);
484 
485 void SP_misc_bsp(gentity_t *ent);
486 void SP_terrain(gentity_t *ent);
487 void SP_misc_skyportal (gentity_t *ent);
488 
489 void SP_misc_portal_surface(gentity_t *ent);
490 void SP_misc_camera_focus (gentity_t *self);
491 void SP_misc_camera_track (gentity_t *self);
492 void SP_misc_dlight (gentity_t *ent);
493 void SP_misc_security_panel (gentity_t *ent);
494 void SP_misc_camera( gentity_t *ent );
495 void SP_misc_spotlight( gentity_t *ent );
496 
497 void SP_shooter_rocket( gentity_t *ent );
498 void SP_shooter_plasma( gentity_t *ent );
499 void SP_shooter_grenade( gentity_t *ent );
500 void SP_misc_replicator_item( gentity_t *ent );
501 void SP_misc_trip_mine( gentity_t *self );
502 void SP_PAS( gentity_t *ent );
503 void SP_misc_weapon_shooter( gentity_t *self );
504 void SP_misc_weather_zone( gentity_t *ent );
505 
506 void SP_misc_cubemap( gentity_t *ent );
507 
508 //New spawn functions
509 void SP_reference_tag ( gentity_t *ent );
510 
511 void SP_NPC_spawner( gentity_t *self );
512 
513 void SP_NPC_Vehicle( gentity_t *self );
514 void SP_NPC_Player( gentity_t *self );
515 void SP_NPC_Kyle( gentity_t *self );
516 void SP_NPC_Lando( gentity_t *self );
517 void SP_NPC_Jan( gentity_t *self );
518 void SP_NPC_Luke( gentity_t *self );
519 void SP_NPC_MonMothma( gentity_t *self );
520 void SP_NPC_Rosh_Penin( gentity_t *self );
521 void SP_NPC_Tavion( gentity_t *self );
522 void SP_NPC_Tavion_New( gentity_t *self );
523 void SP_NPC_Alora( gentity_t *self );
524 void SP_NPC_Reelo( gentity_t *self );
525 void SP_NPC_Galak( gentity_t *self );
526 void SP_NPC_Desann( gentity_t *self );
527 void SP_NPC_Rax( gentity_t *self );
528 void SP_NPC_BobaFett( gentity_t *self );
529 void SP_NPC_Ragnos( gentity_t *self );
530 void SP_NPC_Lannik_Racto( gentity_t *self );
531 void SP_NPC_Kothos( gentity_t *self );
532 void SP_NPC_Chewbacca( gentity_t *self );
533 void SP_NPC_Bartender( gentity_t *self );
534 void SP_NPC_MorganKatarn( gentity_t *self );
535 void SP_NPC_Jedi( gentity_t *self );
536 void SP_NPC_Prisoner( gentity_t *self );
537 void SP_NPC_Merchant( gentity_t *self );
538 void SP_NPC_Rebel( gentity_t *self );
539 void SP_NPC_Human_Merc( gentity_t *self );
540 void SP_NPC_Stormtrooper( gentity_t *self );
541 void SP_NPC_StormtrooperOfficer( gentity_t *self );
542 void SP_NPC_Tie_Pilot( gentity_t *self );
543 void SP_NPC_Snowtrooper( gentity_t *self );
544 void SP_NPC_RocketTrooper( gentity_t *self);
545 void SP_NPC_HazardTrooper( gentity_t *self);
546 void SP_NPC_Ugnaught( gentity_t *self );
547 void SP_NPC_Jawa( gentity_t *self );
548 void SP_NPC_Gran( gentity_t *self );
549 void SP_NPC_Rodian( gentity_t *self );
550 void SP_NPC_Weequay( gentity_t *self );
551 void SP_NPC_Trandoshan( gentity_t *self );
552 void SP_NPC_Tusken( gentity_t *self );
553 void SP_NPC_Noghri( gentity_t *self );
554 void SP_NPC_SwampTrooper( gentity_t *self );
555 void SP_NPC_Imperial( gentity_t *self );
556 void SP_NPC_ImpWorker( gentity_t *self );
557 void SP_NPC_BespinCop( gentity_t *self );
558 void SP_NPC_Reborn( gentity_t *self );
559 void SP_NPC_Reborn_New( gentity_t *self);
560 void SP_NPC_Cultist( gentity_t *self );
561 void SP_NPC_Cultist_Saber( gentity_t *self );
562 void SP_NPC_Cultist_Saber_Powers( gentity_t *self );
563 void SP_NPC_Cultist_Destroyer( gentity_t *self );
564 void SP_NPC_Cultist_Commando( gentity_t *self );
565 void SP_NPC_ShadowTrooper( gentity_t *self );
566 void SP_NPC_Saboteur( gentity_t *self );
567 void SP_NPC_Monster_Murjj( gentity_t *self );
568 void SP_NPC_Monster_Swamp( gentity_t *self );
569 void SP_NPC_Monster_Howler( gentity_t *self );
570 void SP_NPC_Monster_Rancor( gentity_t *self );
571 void SP_NPC_Monster_Mutant_Rancor( gentity_t *self );
572 void SP_NPC_Monster_Wampa( gentity_t *self );
573 void SP_NPC_Monster_Claw( gentity_t *self );
574 void SP_NPC_Monster_Glider( gentity_t *self );
575 void SP_NPC_Monster_Flier2( gentity_t *self );
576 void SP_NPC_Monster_Lizard( gentity_t *self );
577 void SP_NPC_Monster_Fish( gentity_t *self );
578 void SP_NPC_Monster_Sand_Creature( gentity_t *self );
579 void SP_NPC_MineMonster( gentity_t *self );
580 void SP_NPC_Droid_Interrogator( gentity_t *self );
581 void SP_NPC_Droid_Probe( gentity_t *self );
582 void SP_NPC_Droid_Mark1( gentity_t *self );
583 void SP_NPC_Droid_Mark2( gentity_t *self );
584 void SP_NPC_Droid_ATST( gentity_t *self );
585 void SP_NPC_Droid_Seeker( gentity_t *self );
586 void SP_NPC_Droid_Remote( gentity_t *self );
587 void SP_NPC_Droid_Sentry( gentity_t *self );
588 void SP_NPC_Droid_Gonk( gentity_t *self );
589 void SP_NPC_Droid_Mouse( gentity_t *self );
590 void SP_NPC_Droid_R2D2( gentity_t *self );
591 void SP_NPC_Droid_R5D2( gentity_t *self );
592 void SP_NPC_Droid_Protocol( gentity_t *self );
593 void SP_NPC_Droid_Assassin( gentity_t *self);
594 void SP_NPC_Droid_Saber( gentity_t *self);
595 
596 void SP_waypoint (gentity_t *ent);
597 void SP_waypoint_small (gentity_t *ent);
598 void SP_waypoint_navgoal (gentity_t *ent);
599 
600 void SP_fx_runner( gentity_t *ent );
601 void SP_fx_explosion_trail( gentity_t *ent );
602 void SP_fx_target_beam( gentity_t *ent );
603 void SP_fx_cloudlayer( gentity_t *ent );
604 
605 void SP_CreateSnow( gentity_t *ent );
606 void SP_CreateRain( gentity_t *ent );
607 void SP_CreateWind( gentity_t *ent );
608 void SP_CreateWindZone( gentity_t *ent );
609 // Added 10/20/02 by Aurelio Reis
610 void SP_CreatePuffSystem( gentity_t *ent );
611 
612 void SP_object_cargo_barrel1( gentity_t *ent );
613 
614 void SP_point_combat (gentity_t *self);
615 
616 void SP_emplaced_eweb( gentity_t *self );
617 void SP_emplaced_gun( gentity_t *self );
618 
619 void SP_misc_turbobattery( gentity_t *base );
620 
621 
622 spawn_t	spawns[] = {
623 	{"info_player_start", SP_info_player_start},
624 	{"info_player_deathmatch", SP_info_player_deathmatch},
625 
626 	{"func_plat", SP_func_plat},
627 	{"func_button", SP_func_button},
628 	{"func_door", SP_func_door},
629 	{"func_static", SP_func_static},
630 	{"func_rotating", SP_func_rotating},
631 	{"func_bobbing", SP_func_bobbing},
632 	{"func_breakable", SP_func_breakable},
633 	{"func_pendulum", SP_func_pendulum},
634 	{"func_train", SP_func_train},
635 	{"func_timer", SP_func_timer},			// rename trigger_timer?
636 	{"func_wall", SP_func_wall},
637 	{"func_usable", SP_func_usable},
638 	{"func_glass", SP_func_glass},
639 
640 	{"rail_mover", SP_rail_mover},
641 	{"rail_track", SP_rail_track},
642 	{"rail_lane", SP_rail_lane},
643 
644 	{"trigger_always", SP_trigger_always},
645 	{"trigger_multiple", SP_trigger_multiple},
646 	{"trigger_once", SP_trigger_once},
647 	{"trigger_push", SP_trigger_push},
648 	{"trigger_teleport", SP_trigger_teleport},
649 	{"trigger_hurt", SP_trigger_hurt},
650 	{"trigger_bidirectional", SP_trigger_bidirectional},
651 	{"trigger_entdist", SP_trigger_entdist},
652 	{"trigger_location", SP_trigger_location},
653 	{"trigger_visible", SP_trigger_visible},
654 	{"trigger_space", SP_trigger_space},
655 	{"trigger_shipboundary", SP_trigger_shipboundary},
656 
657 	{"target_give", SP_target_give},
658 	{"target_delay", SP_target_delay},
659 	{"target_speaker", SP_target_speaker},
660 	{"target_print", SP_target_print},
661 	{"target_laser", SP_target_laser},
662 	{"target_score", SP_target_score},
663 	{"target_teleporter", SP_target_teleporter},
664 	{"target_relay", SP_target_relay},
665 	{"target_kill", SP_target_kill},
666 	{"target_position", SP_target_position},
667 	{"target_location", SP_target_location},
668 	{"target_push", SP_target_push},
669 	{"target_random", SP_target_random},
670 	{"target_counter", SP_target_counter},
671 	{"target_scriptrunner", SP_target_scriptrunner},
672 	{"target_interest", SP_target_interest},
673 	{"target_activate", SP_target_activate},
674 	{"target_deactivate", SP_target_deactivate},
675 	{"target_gravity_change", SP_target_gravity_change},
676 	{"target_friction_change", SP_target_friction_change},
677 	{"target_level_change", SP_target_level_change},
678 	{"target_change_parm", SP_target_change_parm},
679 	{"target_play_music", SP_target_play_music},
680 	{"target_autosave", SP_target_autosave},
681 	{"target_secret", SP_target_secret},
682 
683 	{"light", SP_light},
684 	{"info_null", SP_info_null},
685 	{"func_group", SP_info_null},
686 	{"info_notnull", SP_info_notnull},		// use target_position instead
687 	{"path_corner", SP_path_corner},
688 
689 	{"misc_teleporter", SP_misc_teleporter},
690 	{"misc_teleporter_dest", SP_misc_teleporter_dest},
691 	{"misc_model", SP_misc_model},
692 	{"misc_model_static", SP_misc_model_static},
693 	{"misc_turret", SP_misc_turret},
694 	{"misc_ns_turret", SP_misc_ns_turret},
695 	{"misc_laser_arm", SP_laser_arm},
696 	{"misc_ion_cannon", SP_misc_ion_cannon},
697 	{"misc_sentry_turret", SP_PAS},
698 	{"misc_maglock", SP_misc_maglock},
699 	{"misc_weapon_shooter", SP_misc_weapon_shooter},
700 	{"misc_weather_zone", SP_misc_weather_zone},
701 
702 	{"misc_model_ghoul", SP_misc_model_ghoul},
703 	{"misc_model_breakable", SP_misc_model_breakable},
704 	{"misc_portal_surface", SP_misc_portal_surface},
705 	{"misc_portal_camera", SP_misc_portal_camera},
706 
707 	{"misc_bsp",					SP_misc_bsp},
708 	{"terrain",						SP_terrain},
709 	{"misc_skyportal",				SP_misc_skyportal},
710 
711 	{"misc_camera_focus", SP_misc_camera_focus},
712 	{"misc_camera_track", SP_misc_camera_track},
713 	{"misc_dlight", SP_misc_dlight},
714 	{"misc_replicator_item", SP_misc_replicator_item},
715 	{"misc_trip_mine", SP_misc_trip_mine},
716 	{"misc_security_panel", SP_misc_security_panel},
717 	{"misc_camera", SP_misc_camera},
718 	{"misc_spotlight", SP_misc_spotlight},
719 	{"misc_panel_turret", SP_misc_panel_turret},
720 	{"misc_model_welder", SP_misc_model_welder},
721 	{"misc_model_jabba_cam", SP_misc_model_jabba_cam},
722 	{"misc_model_shield_power_converter", SP_misc_model_shield_power_converter},
723 	{"misc_model_ammo_power_converter", SP_misc_model_ammo_power_converter},
724 	{"misc_model_bomb_planted", SP_misc_model_bomb_planted},
725 	{"misc_model_beacon", SP_misc_model_beacon},
726 	{"misc_shield_floor_unit", SP_misc_shield_floor_unit},
727 	{"misc_ammo_floor_unit", SP_misc_ammo_floor_unit},
728 
729 	{"misc_model_gun_rack", SP_misc_model_gun_rack},
730 	{"misc_model_ammo_rack", SP_misc_model_ammo_rack},
731 	{"misc_model_cargo_small", SP_misc_model_cargo_small},
732 
733 	{"misc_exploding_crate", SP_misc_exploding_crate},
734 	{"misc_gas_tank", SP_misc_gas_tank},
735 	{"misc_crystal_crate", SP_misc_crystal_crate},
736 	{"misc_atst_drivable", SP_misc_atst_drivable},
737 
738 	{"misc_cubemap", SP_misc_cubemap},
739 
740 	{"shooter_rocket", SP_shooter_rocket},
741 	{"shooter_grenade", SP_shooter_grenade},
742 	{"shooter_plasma", SP_shooter_plasma},
743 
744 	{"ref_tag",	SP_reference_tag},
745 
746 	//new NPC ents
747 	{"NPC_spawner", SP_NPC_spawner},
748 
749 	{"NPC_Vehicle", SP_NPC_Vehicle },
750 	{"NPC_Player", SP_NPC_Player },
751 	{"NPC_Kyle", SP_NPC_Kyle },
752 	{"NPC_Lando", SP_NPC_Lando },
753 	{"NPC_Jan", SP_NPC_Jan },
754 	{"NPC_Luke", SP_NPC_Luke },
755 	{"NPC_MonMothma", SP_NPC_MonMothma },
756 	{"NPC_Rosh_Penin", SP_NPC_Rosh_Penin },
757 	{"NPC_Tavion", SP_NPC_Tavion },
758 	{"NPC_Tavion_New", SP_NPC_Tavion_New },
759 	{"NPC_Alora", SP_NPC_Alora },
760 	{"NPC_Reelo", SP_NPC_Reelo },
761 	{"NPC_Galak", SP_NPC_Galak },
762 	{"NPC_Desann", SP_NPC_Desann },
763 	{"NPC_Rax", SP_NPC_Rax },
764 	{"NPC_BobaFett", SP_NPC_BobaFett },
765 	{"NPC_Ragnos", SP_NPC_Ragnos },
766 	{"NPC_Lannik_Racto", SP_NPC_Lannik_Racto },
767 	{"NPC_Kothos", SP_NPC_Kothos },
768 	{"NPC_Chewbacca", SP_NPC_Chewbacca },
769 	{"NPC_Bartender", SP_NPC_Bartender },
770 	{"NPC_MorganKatarn", SP_NPC_MorganKatarn },
771 	{"NPC_Jedi", SP_NPC_Jedi },
772 	{"NPC_Prisoner", SP_NPC_Prisoner },
773 	{"NPC_Merchant", SP_NPC_Merchant },
774 	{"NPC_Rebel", SP_NPC_Rebel },
775 	{"NPC_Human_Merc", SP_NPC_Human_Merc },
776 	{"NPC_Stormtrooper", SP_NPC_Stormtrooper },
777 	{"NPC_StormtrooperOfficer", SP_NPC_StormtrooperOfficer },
778 	{"NPC_Tie_Pilot", SP_NPC_Tie_Pilot },
779 	{"NPC_Snowtrooper", SP_NPC_Snowtrooper },
780 	{"NPC_RocketTrooper", SP_NPC_RocketTrooper },
781 	{"NPC_HazardTrooper", SP_NPC_HazardTrooper },
782 
783 	{"NPC_Ugnaught", SP_NPC_Ugnaught },
784 	{"NPC_Jawa", SP_NPC_Jawa },
785 	{"NPC_Gran", SP_NPC_Gran },
786 	{"NPC_Rodian", SP_NPC_Rodian },
787 	{"NPC_Weequay", SP_NPC_Weequay },
788 	{"NPC_Trandoshan", SP_NPC_Trandoshan },
789 	{"NPC_Tusken", SP_NPC_Tusken },
790 	{"NPC_Noghri", SP_NPC_Noghri },
791 	{"NPC_SwampTrooper", SP_NPC_SwampTrooper },
792 	{"NPC_Imperial", SP_NPC_Imperial },
793 	{"NPC_ImpWorker", SP_NPC_ImpWorker },
794 	{"NPC_BespinCop", SP_NPC_BespinCop },
795 	{"NPC_Reborn", SP_NPC_Reborn },
796 	{"NPC_Reborn_New", SP_NPC_Reborn_New },
797 	{"NPC_Cultist", SP_NPC_Cultist },
798 	{"NPC_Cultist_Saber", SP_NPC_Cultist_Saber },
799 	{"NPC_Cultist_Saber_Powers", SP_NPC_Cultist_Saber_Powers },
800 	{"NPC_Cultist_Destroyer", SP_NPC_Cultist_Destroyer },
801 	{"NPC_Cultist_Commando", SP_NPC_Cultist_Commando },
802 	{"NPC_ShadowTrooper", SP_NPC_ShadowTrooper },
803 	{"NPC_Saboteur", SP_NPC_Saboteur },
804 	{"NPC_Monster_Murjj", SP_NPC_Monster_Murjj },
805 	{"NPC_Monster_Swamp", SP_NPC_Monster_Swamp },
806 	{"NPC_Monster_Howler", SP_NPC_Monster_Howler },
807 	{"NPC_Monster_Rancor", SP_NPC_Monster_Rancor },
808 	{"NPC_Monster_Mutant_Rancor", SP_NPC_Monster_Mutant_Rancor },
809 	{"NPC_Monster_Wampa", SP_NPC_Monster_Wampa },
810 	{"NPC_MineMonster",	SP_NPC_MineMonster },
811 	{"NPC_Monster_Claw", SP_NPC_Monster_Claw },
812 	{"NPC_Monster_Glider", SP_NPC_Monster_Glider },
813 	{"NPC_Monster_Flier2", SP_NPC_Monster_Flier2 },
814 	{"NPC_Monster_Lizard", SP_NPC_Monster_Lizard },
815 	{"NPC_Monster_Fish", SP_NPC_Monster_Fish },
816 	{"NPC_Monster_Sand_Creature", SP_NPC_Monster_Sand_Creature },
817 	{"NPC_Droid_Interrogator", SP_NPC_Droid_Interrogator },
818 	{"NPC_Droid_Probe", SP_NPC_Droid_Probe },
819 	{"NPC_Droid_Mark1", SP_NPC_Droid_Mark1 },
820 	{"NPC_Droid_Mark2", SP_NPC_Droid_Mark2 },
821 	{"NPC_Droid_ATST", SP_NPC_Droid_ATST },
822 	{"NPC_Droid_Seeker", SP_NPC_Droid_Seeker },
823 	{"NPC_Droid_Remote", SP_NPC_Droid_Remote },
824 	{"NPC_Droid_Sentry", SP_NPC_Droid_Sentry },
825 	{"NPC_Droid_Gonk", SP_NPC_Droid_Gonk },
826 	{"NPC_Droid_Mouse", SP_NPC_Droid_Mouse },
827 	{"NPC_Droid_R2D2", SP_NPC_Droid_R2D2 },
828 	{"NPC_Droid_R5D2", SP_NPC_Droid_R5D2 },
829 	{"NPC_Droid_Protocol", SP_NPC_Droid_Protocol },
830 	{"NPC_Droid_Assassin", SP_NPC_Droid_Assassin },
831 	{"NPC_Droid_Saber", SP_NPC_Droid_Saber },
832 
833 	//rwwFIXMEFIXME: Faked for testing NPCs (another other things) in RMG with sof2 assets
834 	{"NPC_Colombian_Soldier", SP_NPC_Reborn },
835 	{"NPC_Colombian_Rebel", SP_NPC_Reborn },
836 	{"NPC_Colombian_EmplacedGunner", SP_NPC_ShadowTrooper },
837 	{"NPC_Manuel_Vergara_RMG", SP_NPC_Desann },
838 //	{"info_NPCnav", SP_waypoint},
839 
840 	{"waypoint", SP_waypoint},
841 	{"waypoint_small", SP_waypoint_small},
842 	{"waypoint_navgoal", SP_waypoint_navgoal},
843 
844 	{"fx_runner", SP_fx_runner},
845 	{"fx_explosion_trail", SP_fx_explosion_trail},
846 	{"fx_target_beam", SP_fx_target_beam},
847 	{"fx_cloudlayer", SP_fx_cloudlayer},
848 	{"fx_rain", SP_CreateRain},
849 	{"fx_wind", SP_CreateWind},
850 	{"fx_snow", SP_CreateSnow},
851 	{"fx_puff", SP_CreatePuffSystem},
852 	{"fx_wind_zone", SP_CreateWindZone},
853 
854 	{"object_cargo_barrel1", SP_object_cargo_barrel1},
855 	{"point_combat", SP_point_combat},
856 
857 	{"emplaced_gun", SP_emplaced_gun},
858 	{"emplaced_eweb", SP_emplaced_eweb},
859 
860 	{NULL, NULL}
861 };
862 
863 /*
864 ===============
865 G_CallSpawn
866 
867 Finds the spawn function for the entity and calls it,
868 returning qfalse if not found
869 ===============
870 */
G_CallSpawn(gentity_t * ent)871 qboolean G_CallSpawn( gentity_t *ent ) {
872 	spawn_t	*s;
873 	gitem_t	*item;
874 
875 	if ( !ent->classname ) {
876 		gi.Printf (S_COLOR_RED"G_CallSpawn: NULL classname\n");
877 		return qfalse;
878 	}
879 
880 	// check item spawn functions
881 	for ( item=bg_itemlist+1 ; item->classname ; item++ ) {
882 		if ( !strcmp(item->classname, ent->classname) ) {
883 			// found it
884 			G_SpawnItem( ent, item );
885 			return qtrue;
886 		}
887 	}
888 
889 	// check normal spawn functions
890 	for ( s=spawns ; s->name ; s++ ) {
891 		if ( !strcmp(s->name, ent->classname) ) {
892 			// found it
893 			s->spawn(ent);
894 			return qtrue;
895 		}
896 	}
897 	char* str;
898 	G_SpawnString( "origin", "?", &str );
899 	gi.Printf (S_COLOR_RED"ERROR: %s is not a spawn function @(%s)\n", ent->classname, str);
900 	delayedShutDown = level.time + 100;
901 	return qfalse;
902 }
903 
904 /*
905 =============
906 G_NewString
907 
908 Builds a copy of the string, translating \n to real linefeeds
909 so message texts can be multi-line
910 =============
911 */
G_NewString(const char * string)912 char *G_NewString( const char *string ) {
913 	char	*newb, *new_p;
914 	int		i,l;
915 
916 	if(!string || !string[0])
917 	{
918 		//gi.Printf(S_COLOR_RED"Error: G_NewString called with NULL string!\n");
919 		return NULL;
920 	}
921 
922 	l = strlen(string) + 1;
923 
924 	newb = (char *) G_Alloc( l );
925 
926 	new_p = newb;
927 
928 	// turn \n into a real linefeed
929 	for ( i=0 ; i< l ; i++ ) {
930 		if (string[i] == '\\' && i < l-1) {
931 			i++;
932 			if (string[i] == 'n') {
933 				*new_p++ = '\n';
934 			} else {
935 				*new_p++ = '\\';
936 			}
937 		} else {
938 			*new_p++ = string[i];
939 		}
940 	}
941 
942 	return newb;
943 }
944 
945 
946 
947 
948 /*
949 ===============
950 G_ParseField
951 
952 Takes a key/value pair and sets the binary values
953 in a gentity
954 ===============
955 */
956 void Q3_SetParm (int entID, int parmNum, const char *parmValue);
G_ParseField(const char * key,const char * value,gentity_t * ent)957 void G_ParseField( const char *key, const char *value, gentity_t *ent ) {
958 	field_t	*f;
959 	byte	*b;
960 	float	v;
961 	vec3_t	vec;
962 	vec4_t	vec4;
963 
964 	for ( f=fields ; f->name ; f++ ) {
965 		if ( !Q_stricmp(f->name, key) ) {
966 			// found it
967 			b = (byte *)ent;
968 
969 			switch( f->type ) {
970 			case F_LSTRING:
971 				*(char **)(b+f->ofs) = G_NewString (value);
972 				break;
973 			case F_VECTOR:
974 			{
975 				int _iFieldsRead = sscanf (value, "%f %f %f", &vec[0], &vec[1], &vec[2]);
976 				assert(_iFieldsRead==3);
977 				if (_iFieldsRead!=3)
978 				{
979 					gi.Printf (S_COLOR_YELLOW"G_ParseField: VEC3 sscanf() failed to read 3 floats ('angle' key bug?)\n");
980 					delayedShutDown = level.time + 100;
981 				}
982 				((float *)(b+f->ofs))[0] = vec[0];
983 				((float *)(b+f->ofs))[1] = vec[1];
984 				((float *)(b+f->ofs))[2] = vec[2];
985 				break;
986 			}
987 			case F_VECTOR4:
988 			{
989 				int _iFieldsRead =  sscanf (value, "%f %f %f %f", &vec4[0], &vec4[1], &vec4[2], &vec4[3]);
990 				assert(_iFieldsRead==4);
991 				if (_iFieldsRead!=4)
992 				{
993 					gi.Printf (S_COLOR_YELLOW"G_ParseField: VEC4 sscanf() failed to read 4 floats\n");
994 					delayedShutDown = level.time + 100;
995 				}
996 				((float *)(b+f->ofs))[0] = vec4[0];
997 				((float *)(b+f->ofs))[1] = vec4[1];
998 				((float *)(b+f->ofs))[2] = vec4[2];
999 				((float *)(b+f->ofs))[3] = vec4[3];
1000 				break;
1001 			}
1002 			case F_INT:
1003 				*(int *)(b+f->ofs) = atoi(value);
1004 				break;
1005 			case F_FLOAT:
1006 				*(float *)(b+f->ofs) = atof(value);
1007 				break;
1008 			case F_ANGLEHACK:
1009 				v = atof(value);
1010 				((float *)(b+f->ofs))[0] = 0;
1011 				((float *)(b+f->ofs))[1] = v;
1012 				((float *)(b+f->ofs))[2] = 0;
1013 				break;
1014 			case F_PARM1:
1015 			case F_PARM2:
1016 			case F_PARM3:
1017 			case F_PARM4:
1018 			case F_PARM5:
1019 			case F_PARM6:
1020 			case F_PARM7:
1021 			case F_PARM8:
1022 			case F_PARM9:
1023 			case F_PARM10:
1024 			case F_PARM11:
1025 			case F_PARM12:
1026 			case F_PARM13:
1027 			case F_PARM14:
1028 			case F_PARM15:
1029 			case F_PARM16:
1030 				Q3_SetParm( ent->s.number, (f->type - F_PARM1), (char *) value );
1031 				break;
1032 			case F_FLAG:
1033 				{//try to find the proper flag for that key:
1034 					int flag = GetIDForString ( flagTable, key );
1035 
1036 					if ( flag > 0 )
1037 					{
1038 						G_SpawnFlag( key, flag, (int *)(b+f->ofs) );
1039 					}
1040 					else
1041 					{
1042 #ifndef FINAL_BUILD
1043 						gi.Printf (S_COLOR_YELLOW"WARNING: G_ParseField: can't find flag for key %s\n", key);
1044 #endif
1045 					}
1046 				}
1047 				break;
1048 			default:
1049 			case F_IGNORE:
1050 				break;
1051 			}
1052 			return;
1053 		}
1054 	}
1055 #ifndef FINAL_BUILD
1056 	//didn't find it?
1057 	if (key[0]!='_')
1058 	{
1059 		gi.Printf ( S_COLOR_YELLOW"WARNING: G_ParseField: no such field: %s\n", key );
1060 	}
1061 #endif
1062 }
1063 
SpawnForCurrentDifficultySetting(gentity_t * ent)1064 static qboolean SpawnForCurrentDifficultySetting( gentity_t *ent )
1065 {
1066 extern cvar_t	*com_buildScript;
1067 	if (com_buildScript->integer) {	//always spawn when building a pak file
1068 		return qtrue;
1069 	}
1070 	if ( ent->spawnflags & ( 1 << (8 + g_spskill->integer )) )	{// easy -256	medium -512		hard -1024
1071 		return qfalse;
1072 	} else {
1073 		return qtrue;
1074 	}
1075 }
1076 
1077 /*
1078 ===================
1079 G_SpawnGEntityFromSpawnVars
1080 
1081 Spawn an entity and fill in all of the level fields from
1082 level.spawnVars[], then call the class specfic spawn function
1083 ===================
1084 */
1085 
G_SpawnGEntityFromSpawnVars(void)1086 void G_SpawnGEntityFromSpawnVars( void ) {
1087 	int			i;
1088 	gentity_t	*ent;
1089 
1090 	// get the next free entity
1091 	ent = G_Spawn();
1092 
1093 	for ( i = 0 ; i < numSpawnVars ; i++ ) {
1094 		G_ParseField( spawnVars[i][0], spawnVars[i][1], ent );
1095 	}
1096 
1097 	G_SpawnInt( "notsingle", "0", &i );
1098 	if ( i || !SpawnForCurrentDifficultySetting( ent ) ) {
1099 		G_FreeEntity( ent );
1100 		return;
1101 	}
1102 
1103 	// move editor origin to pos
1104 	VectorCopy( ent->s.origin, ent->s.pos.trBase );
1105 	VectorCopy( ent->s.origin, ent->currentOrigin );
1106 
1107 	// if we didn't get a classname, don't bother spawning anything
1108 	if ( !G_CallSpawn( ent ) ) {
1109 		G_FreeEntity( ent );
1110 		return;
1111 	}
1112 
1113 	//Tag on the ICARUS scripting information only to valid recipients
1114 	if ( Quake3Game()->ValidEntity( ent ) )
1115 	{
1116 		Quake3Game()->InitEntity( ent ); //ICARUS_InitEnt( ent );
1117 
1118 		if ( ent->classname && ent->classname[0] )
1119 		{
1120 			if ( Q_strncmp( "NPC_", ent->classname, 4 ) != 0 )
1121 			{//Not an NPC_spawner
1122 				G_ActivateBehavior( ent, BSET_SPAWN );
1123 			}
1124 		}
1125 	}
1126 }
1127 
G_SpawnSubBSPGEntityFromSpawnVars(vec3_t posOffset,vec3_t angOffset)1128 void G_SpawnSubBSPGEntityFromSpawnVars( vec3_t posOffset, vec3_t angOffset ) {
1129 	int			i;
1130 	gentity_t	*ent;
1131 
1132 	// get the next free entity
1133 	ent = G_Spawn();
1134 
1135 	for ( i = 0 ; i < numSpawnVars ; i++ ) {
1136 		G_ParseField( spawnVars[i][0], spawnVars[i][1], ent );
1137 	}
1138 
1139 	G_SpawnInt( "notsingle", "0", &i );
1140 	if ( i || !SpawnForCurrentDifficultySetting( ent ) ) {
1141 		G_FreeEntity( ent );
1142 		return;
1143 	}
1144 
1145 	VectorAdd(ent->s.origin, posOffset, ent->s.origin);
1146 	VectorAdd(ent->s.angles, angOffset, ent->s.angles);
1147 
1148 	VectorCopy(ent->s.angles, ent->s.apos.trBase);
1149 	VectorCopy(ent->s.angles, ent->currentAngles);
1150 
1151 	// move editor origin to pos
1152 	VectorCopy( ent->s.origin, ent->s.pos.trBase );
1153 	VectorCopy( ent->s.origin, ent->currentOrigin );
1154 
1155 	// if we didn't get a classname, don't bother spawning anything
1156 	if ( !G_CallSpawn( ent ) ) {
1157 		G_FreeEntity( ent );
1158 		return;
1159 	}
1160 
1161 	//Tag on the ICARUS scripting information only to valid recipients
1162 	if ( Quake3Game()->ValidEntity( ent ) )
1163 	{
1164 
1165 		Quake3Game()->InitEntity( ent ); // ICARUS_InitEnt( ent );
1166 
1167 		if ( ent->classname && ent->classname[0] )
1168 		{
1169 			if ( Q_strncmp( "NPC_", ent->classname, 4 ) != 0 )
1170 			{//Not an NPC_spawner
1171 				G_ActivateBehavior( ent, BSET_SPAWN );
1172 			}
1173 		}
1174 	}
1175 }
1176 
1177 
1178 /*
1179 ====================
1180 G_AddSpawnVarToken
1181 ====================
1182 */
G_AddSpawnVarToken(const char * string)1183 char *G_AddSpawnVarToken( const char *string ) {
1184 	int		l;
1185 	char	*dest;
1186 
1187 	l = strlen( string );
1188 	if ( numSpawnVarChars + l + 1 > MAX_SPAWN_VARS_CHARS ) {
1189 		G_Error( "G_AddSpawnVarToken: MAX_SPAWN_VARS" );
1190 	}
1191 
1192 	dest = spawnVarChars + numSpawnVarChars;
1193 	memcpy( dest, string, l+1 );
1194 
1195 	numSpawnVarChars += l + 1;
1196 
1197 	return dest;
1198 }
1199 
1200 /*
1201 ====================
1202 G_ParseSpawnVars
1203 
1204 Parses a brace bounded set of key / value pairs out of the
1205 level's entity strings into level.spawnVars[]
1206 
1207 This does not actually spawn an entity.
1208 ====================
1209 */
G_ParseSpawnVars(const char ** data)1210 qboolean G_ParseSpawnVars( const char **data ) {
1211 	char		keyname[MAX_STRING_CHARS];
1212 	const char	*com_token;
1213 
1214 	numSpawnVars = 0;
1215 	numSpawnVarChars = 0;
1216 
1217 	// parse the opening brace
1218 	COM_BeginParseSession();
1219 	com_token = COM_Parse( data );
1220 	if ( !*data ) {
1221 		// end of spawn string
1222 		COM_EndParseSession();
1223 		return qfalse;
1224 	}
1225 	if ( com_token[0] != '{' ) {
1226 		COM_EndParseSession();
1227 		G_Error( "G_ParseSpawnVars: found %s when expecting {",com_token );
1228 	}
1229 
1230 	// go through all the key / value pairs
1231 	while ( 1 ) {
1232 		// parse key
1233 		com_token = COM_Parse( data );
1234 		if ( !*data ) {
1235 			COM_EndParseSession();
1236 			G_Error( "G_ParseSpawnVars: EOF without closing brace" );
1237 		}
1238 
1239 		if ( com_token[0] == '}' ) {
1240 			break;
1241 		}
1242 
1243 		Q_strncpyz( keyname, com_token, sizeof(keyname) );
1244 
1245 		// parse value
1246 		com_token = COM_Parse( data );
1247 		if ( !*data ) {
1248 			COM_EndParseSession();
1249 			G_Error( "G_ParseSpawnVars: EOF without closing brace" );
1250 		}
1251 		if ( com_token[0] == '}' ) {
1252 			COM_EndParseSession();
1253 			G_Error( "G_ParseSpawnVars: closing brace without data" );
1254 		}
1255 		if ( numSpawnVars == MAX_SPAWN_VARS ) {
1256 			COM_EndParseSession();
1257 			G_Error( "G_ParseSpawnVars: MAX_SPAWN_VARS" );
1258 		}
1259 		spawnVars[ numSpawnVars ][0] = G_AddSpawnVarToken( keyname );
1260 		spawnVars[ numSpawnVars ][1] = G_AddSpawnVarToken( com_token );
1261 		numSpawnVars++;
1262 	}
1263 
1264 	COM_EndParseSession();
1265 	return qtrue;
1266 }
1267 
1268 static	const char *defaultStyles[LS_NUM_STYLES][3] =
1269 {
1270 	{	// 0 normal
1271 		"z",
1272 		"z",
1273 		"z"
1274 	},
1275 	{	// 1 FLICKER (first variety)
1276 		"mmnmmommommnonmmonqnmmo",
1277 		"mmnmmommommnonmmonqnmmo",
1278 		"mmnmmommommnonmmonqnmmo"
1279 	},
1280 	{	// 2 SLOW STRONG PULSE
1281 		"abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcb",
1282 		"abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcb",
1283 		"abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcb"
1284 	},
1285 	{	// 3 CANDLE (first variety)
1286 		"mmmmmaaaaammmmmaaaaaabcdefgabcdefg",
1287 		"mmmmmaaaaammmmmaaaaaabcdefgabcdefg",
1288 		"mmmmmaaaaammmmmaaaaaabcdefgabcdefg"
1289 	},
1290 	{	// 4 FAST STROBE
1291 		"mamamamamama",
1292 		"mamamamamama",
1293 		"mamamamamama"
1294 	},
1295 	{	// 5 GENTLE PULSE 1
1296 		"jklmnopqrstuvwxyzyxwvutsrqponmlkj",
1297 		"jklmnopqrstuvwxyzyxwvutsrqponmlkj",
1298 		"jklmnopqrstuvwxyzyxwvutsrqponmlkj"
1299 	},
1300 	{	// 6 FLICKER (second variety)
1301 		"nmonqnmomnmomomno",
1302 		"nmonqnmomnmomomno",
1303 		"nmonqnmomnmomomno"
1304 	},
1305 	{	// 7 CANDLE (second variety)
1306 		"mmmaaaabcdefgmmmmaaaammmaamm",
1307 		"mmmaaaabcdefgmmmmaaaammmaamm",
1308 		"mmmaaaabcdefgmmmmaaaammmaamm"
1309 	},
1310 	{	// 8 CANDLE (third variety)
1311 		"mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa",
1312 		"mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa",
1313 		"mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa"
1314 	},
1315 	{	// 9 SLOW STROBE (fourth variety)
1316 		"aaaaaaaazzzzzzzz",
1317 		"aaaaaaaazzzzzzzz",
1318 		"aaaaaaaazzzzzzzz"
1319 	},
1320 	{	// 10 FLUORESCENT FLICKER
1321 		"mmamammmmammamamaaamammma",
1322 		"mmamammmmammamamaaamammma",
1323 		"mmamammmmammamamaaamammma"
1324 	},
1325 	{	// 11 SLOW PULSE NOT FADE TO BLACK
1326 		"abcdefghijklmnopqrrqponmlkjihgfedcba",
1327 		"abcdefghijklmnopqrrqponmlkjihgfedcba",
1328 		"abcdefghijklmnopqrrqponmlkjihgfedcba"
1329 	},
1330 	{	// 12 FAST PULSE FOR JEREMY
1331 		"mkigegik",
1332 		"mkigegik",
1333 		"mkigegik"
1334 	},
1335 	{	// 13 Test Blending
1336 		"abcdefghijklmqrstuvwxyz",
1337 		"zyxwvutsrqmlkjihgfedcba",
1338 		"aammbbzzccllcckkffyyggp"
1339 	},
1340 	{	// 14
1341 		"",
1342 		"",
1343 		""
1344 	},
1345 	{	// 15
1346 		"",
1347 		"",
1348 		""
1349 	},
1350 	{	// 16
1351 		"",
1352 		"",
1353 		""
1354 	},
1355 	{	// 17
1356 		"",
1357 		"",
1358 		""
1359 	},
1360 	{	// 18
1361 		"",
1362 		"",
1363 		""
1364 	},
1365 	{	// 19
1366 		"",
1367 		"",
1368 		""
1369 	},
1370 	{	// 20
1371 		"",
1372 		"",
1373 		""
1374 	},
1375 	{	// 21
1376 		"",
1377 		"",
1378 		""
1379 	},
1380 	{	// 22
1381 		"",
1382 		"",
1383 		""
1384 	},
1385 	{	// 23
1386 		"",
1387 		"",
1388 		""
1389 	},
1390 	{	// 24
1391 		"",
1392 		"",
1393 		""
1394 	},
1395 	{	// 25
1396 		"",
1397 		"",
1398 		""
1399 	},
1400 	{	// 26
1401 		"",
1402 		"",
1403 		""
1404 	},
1405 	{	// 27
1406 		"",
1407 		"",
1408 		""
1409 	},
1410 	{	// 28
1411 		"",
1412 		"",
1413 		""
1414 	},
1415 	{	// 29
1416 		"",
1417 		"",
1418 		""
1419 	},
1420 	{	// 30
1421 		"",
1422 		"",
1423 		""
1424 	},
1425 	{	// 31
1426 		"",
1427 		"",
1428 		""
1429 	}
1430 };
1431 
1432 
1433 /*QUAKED worldspawn (0 0 0) ?
1434 Every map should have exactly one worldspawn.
1435 "music"     path to WAV or MP3 files (e.g. "music\intro.mp3 music\loopfile.mp3")
1436 "gravity"   800 is default gravity
1437 "message"   Text to print during connection
1438 "soundSet"  Ambient sound set to play
1439 "spawnscript" runs this script
1440 
1441 BSP Options
1442 "gridsize"     size of lighting grid to "X Y Z". default="64 64 128"
1443 "ambient"      amount of global light to add to each surf (uses _color)
1444 "chopsize"     value for bsp on the maximum polygon / portal size
1445 "distancecull" value for vis for the maximum viewing distance
1446 "_minlight"   minimum lighting on a surf.  overrides _mingridlight and _minvertexlight
1447 
1448 Game Options
1449 "fog"          shader name of the global fog texture - must include the full path, such as "textures/rj/fog1"
1450 "ls_Xr"	override lightstyle X with this pattern for Red.
1451 "ls_Xg"	green (valid patterns are "a-z")
1452 "ls_Xb"	blue (a is OFF, z is ON)
1453 "breath"		Whether the entity's have breath puffs or not (0 = No, 1 = All, 2 = Just cold breath, 3 = Just under water bubbles ).
1454 "clearstats" default 1, if 0 loading this map will not clear the stats for player
1455 "tier_storyinfo" sets 'tier_storyinfo' cvar
1456 */
SP_worldspawn(void)1457 void SP_worldspawn( void ) {
1458 	char	*s;
1459 	int		i;
1460 
1461 	g_entities[ENTITYNUM_WORLD].max_health = 0;
1462 
1463 	for ( i = 0 ; i < numSpawnVars ; i++ )
1464 	{
1465 		if ( Q_stricmp( "spawnscript", spawnVars[i][0] ) == 0 )
1466 		{//ONly let them set spawnscript, we don't want them setting an angle or something on the world.
1467 			G_ParseField( spawnVars[i][0], spawnVars[i][1], &g_entities[ENTITYNUM_WORLD] );
1468 		}
1469 		if ( Q_stricmp( "region", spawnVars[i][0] ) == 0 )
1470 		{
1471 			g_entities[ENTITYNUM_WORLD].s.radius = atoi(spawnVars[i][1]);
1472 		}
1473 		if ( Q_stricmp( "distancecull", spawnVars[i][0] ) == 0 )
1474 		{
1475 			g_entities[ENTITYNUM_WORLD].max_health = (int)((float)(atoi(spawnVars[i][1])) * 0.7f);
1476 		}
1477 	}
1478 
1479 	G_SpawnString( "classname", "", &s );
1480 	if ( Q_stricmp( s, "worldspawn" ) ) {
1481 		G_Error( "SP_worldspawn: The first entity isn't 'worldspawn'" );
1482 	}
1483 
1484 	// make some data visible to connecting client
1485 	G_SpawnString( "music", "", &s );
1486 	gi.SetConfigstring( CS_MUSIC, s );
1487 
1488 	G_SpawnString( "message", "", &s );
1489 	gi.SetConfigstring( CS_MESSAGE, s );				// map specific message
1490 
1491 	G_SpawnString( "gravity", "800", &s );
1492 	extern SavedGameJustLoaded_e g_eSavedGameJustLoaded;
1493 	if (g_eSavedGameJustLoaded != eFULL)
1494 	{
1495 		gi.cvar_set( "g_gravity", s );
1496 	}
1497 
1498 	G_SpawnString( "soundSet", "default", &s );
1499 	gi.SetConfigstring( CS_AMBIENT_SET, s );
1500 
1501 	//Lightstyles
1502 	gi.SetConfigstring(CS_LIGHT_STYLES+(LS_STYLES_START*3)+0, defaultStyles[0][0]);
1503 	gi.SetConfigstring(CS_LIGHT_STYLES+(LS_STYLES_START*3)+1, defaultStyles[0][1]);
1504 	gi.SetConfigstring(CS_LIGHT_STYLES+(LS_STYLES_START*3)+2, defaultStyles[0][2]);
1505 
1506 	for(i=1;i<LS_NUM_STYLES;i++)
1507 	{
1508 		char	temp[32];
1509 		int		lengthRed, lengthBlue, lengthGreen;
1510 		Com_sprintf(temp, sizeof(temp), "ls_%dr", i);
1511 		G_SpawnString( temp, defaultStyles[i][0], &s );
1512 		lengthRed = strlen(s);
1513 		gi.SetConfigstring(CS_LIGHT_STYLES+((i+LS_STYLES_START)*3)+0, s);
1514 
1515 		Com_sprintf(temp, sizeof(temp), "ls_%dg", i);
1516 		G_SpawnString(temp, defaultStyles[i][1], &s);
1517 		lengthGreen = strlen(s);
1518 		gi.SetConfigstring(CS_LIGHT_STYLES+((i+LS_STYLES_START)*3)+1, s);
1519 
1520 		Com_sprintf(temp, sizeof(temp), "ls_%db", i);
1521 		G_SpawnString(temp, defaultStyles[i][2], &s);
1522 		lengthBlue = strlen(s);
1523 		gi.SetConfigstring(CS_LIGHT_STYLES+((i+LS_STYLES_START)*3)+2, s);
1524 
1525 		if (lengthRed != lengthGreen || lengthGreen != lengthBlue)
1526 		{
1527 			Com_Error(ERR_DROP, "Style %d has inconsistent lengths: R %d, G %d, B %d",
1528 				i, lengthRed, lengthGreen, lengthBlue);
1529 		}
1530 	}
1531 
1532 	G_SpawnString( "breath", "0", &s );
1533 	gi.cvar_set( "cg_drawBreath", s );
1534 
1535 	G_SpawnString( "clearstats", "1", &s );
1536 	gi.cvar_set( "g_clearstats", s );
1537 
1538 	if (G_SpawnString( "tier_storyinfo", "", &s ))
1539 	{
1540 		gi.cvar_set( "tier_storyinfo", s );
1541 	}
1542 
1543 	g_entities[ENTITYNUM_WORLD].s.number = ENTITYNUM_WORLD;
1544 	g_entities[ENTITYNUM_WORLD].classname = "worldspawn";
1545 }
1546 
1547 /*
1548 -------------------------
1549 G_ParsePrecaches
1550 -------------------------
1551 */
1552 
G_ParsePrecaches(void)1553 void G_ParsePrecaches( void )
1554 {
1555 	gentity_t	*ent = NULL;
1556 
1557 	//Clear any old lists
1558 	if(!as_preCacheMap) {
1559 		as_preCacheMap = new namePrecache_m;
1560 	}
1561 
1562 	as_preCacheMap->clear();
1563 
1564 	for ( int i = 0; i < globals.num_entities; i++ )
1565 	{
1566 		ent = &g_entities[i];
1567 
1568 		if VALIDSTRING( ent->soundSet )
1569 		{
1570 			(*as_preCacheMap)[ (char *) ent->soundSet ] = 1;
1571 		}
1572 	}
1573 }
1574 
1575 
G_ASPreCacheFree(void)1576 void G_ASPreCacheFree(void)
1577 {
1578 	if(as_preCacheMap) {
1579 		delete as_preCacheMap;
1580 		as_preCacheMap = NULL;
1581 	}
1582 }
1583 
1584 /*
1585 ==============
1586 G_SpawnEntitiesFromString
1587 
1588 Parses textual entity definitions out of an entstring and spawns gentities.
1589 ==============
1590 */
1591 extern int num_waypoints;
1592 extern void	RG_RouteGen(void);
1593 extern qboolean NPCsPrecached;
1594 
SP_bsp_worldspawn(void)1595 qboolean SP_bsp_worldspawn ( void )
1596 {
1597 	return qtrue;
1598 }
1599 
G_SubBSPSpawnEntitiesFromString(const char * entityString,vec3_t posOffset,vec3_t angOffset)1600 void G_SubBSPSpawnEntitiesFromString(const char *entityString, vec3_t posOffset, vec3_t angOffset)
1601 {
1602 	const char		*entities;
1603 
1604 	entities = entityString;
1605 
1606 	// allow calls to G_Spawn*()
1607 	spawning = qtrue;
1608 	NPCsPrecached = qfalse;
1609 	numSpawnVars = 0;
1610 
1611 	// the worldspawn is not an actual entity, but it still
1612 	// has a "spawn" function to perform any global setup
1613 	// needed by a level (setting configstrings or cvars, etc)
1614 	if ( !G_ParseSpawnVars( &entities ) ) {
1615 		G_Error( "SpawnEntities: no entities" );
1616 	}
1617 
1618 	// Skip this guy if its worldspawn fails
1619 	if ( !SP_bsp_worldspawn() )
1620 	{
1621 		return;
1622 	}
1623 
1624 	// parse ents
1625 	while( G_ParseSpawnVars(&entities) )
1626 	{
1627 		G_SpawnSubBSPGEntityFromSpawnVars(posOffset, angOffset);
1628 	}
1629 }
1630 
G_SpawnEntitiesFromString(const char * entityString)1631 void G_SpawnEntitiesFromString( const char *entityString ) {
1632 	const char		*entities;
1633 
1634 	entities = entityString;
1635 
1636 	// allow calls to G_Spawn*()
1637 	spawning = qtrue;
1638 	NPCsPrecached = qfalse;
1639 	numSpawnVars = 0;
1640 
1641 	// the worldspawn is not an actual entity, but it still
1642 	// has a "spawn" function to perform any global setup
1643 	// needed by a level (setting configstrings or cvars, etc)
1644 	if ( !G_ParseSpawnVars( &entities ) ) {
1645 		G_Error( "SpawnEntities: no entities" );
1646 	}
1647 
1648 	SP_worldspawn();
1649 
1650 	// parse ents
1651 	while( G_ParseSpawnVars( &entities ) )
1652 	{
1653 		G_SpawnGEntityFromSpawnVars();
1654 	}
1655 
1656 	//Search the entities for precache information
1657 	G_ParsePrecaches();
1658 
1659 
1660 	if( g_entities[ENTITYNUM_WORLD].behaviorSet[BSET_SPAWN] && g_entities[ENTITYNUM_WORLD].behaviorSet[BSET_SPAWN][0] )
1661 	{//World has a spawn script, but we don't want the world in ICARUS and running scripts,
1662 		//so make a scriptrunner and start it going.
1663 		gentity_t *script_runner = G_Spawn();
1664 		if ( script_runner )
1665 		{
1666 			script_runner->behaviorSet[BSET_USE] = g_entities[ENTITYNUM_WORLD].behaviorSet[BSET_SPAWN];
1667 			script_runner->count = 1;
1668 			script_runner->e_ThinkFunc = thinkF_scriptrunner_run;
1669 			script_runner->nextthink = level.time + 100;
1670 
1671 			if ( Quake3Game()->ValidEntity( script_runner ) )
1672 			{
1673 				Quake3Game()->InitEntity( script_runner ); //ICARUS_InitEnt( script_runner );
1674 			}
1675 		}
1676 	}
1677 
1678 	//gi.Printf(S_COLOR_YELLOW"Total waypoints: %d\n", num_waypoints);
1679 	//Automatically run routegen
1680 	//RG_RouteGen();
1681 
1682 	spawning = qfalse;			// any future calls to G_Spawn*() will be errors
1683 
1684 	if ( g_delayedShutdown->integer && delayedShutDown )
1685 	{
1686 		assert(0);
1687 		G_Error( "Errors loading map, check the console for them." );
1688 	}
1689 }
1690 
1691