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