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