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