// Copyright (C) 1999-2000 Id Software, Inc. // #include "g_local.h" qboolean G_SpawnString( const char *key, const char *defaultString, char **out ) { int i; if ( !level.spawning ) { *out = (char *)defaultString; // G_Error( "G_SpawnString() called while not spawning" ); } for ( i = 0 ; i < level.numSpawnVars ; i++ ) { if ( !Q_stricmp( key, level.spawnVars[i][0] ) ) { *out = level.spawnVars[i][1]; return qtrue; } } *out = (char *)defaultString; return qfalse; } qboolean G_SpawnFloat( const char *key, const char *defaultString, float *out ) { char *s; qboolean present; present = G_SpawnString( key, defaultString, &s ); *out = atof( s ); return present; } qboolean G_SpawnInt( const char *key, const char *defaultString, int *out ) { char *s; qboolean present; present = G_SpawnString( key, defaultString, &s ); *out = atoi( s ); return present; } qboolean G_SpawnVector( const char *key, const char *defaultString, float *out ) { char *s; qboolean present; present = G_SpawnString( key, defaultString, &s ); sscanf( s, "%f %f %f", &out[0], &out[1], &out[2] ); return present; } BG_field_t fields[] = { {"classname", FOFS(classname), F_LSTRING}, {"teamnodmg", FOFS(teamnodmg), F_INT}, {"teamowner", FOFS(s.teamowner), F_INT}, {"teamuser", FOFS(alliedTeam), F_INT}, {"alliedTeam", FOFS(alliedTeam), F_INT},//for misc_turrets {"roffname", FOFS(roffname), F_LSTRING}, {"rofftarget", FOFS(rofftarget), F_LSTRING}, {"healingclass", FOFS(healingclass), F_LSTRING}, {"healingsound", FOFS(healingsound), F_LSTRING}, {"healingrate", FOFS(healingrate), F_INT}, {"ownername", FOFS(ownername), F_LSTRING}, {"origin", FOFS(s.origin), F_VECTOR}, {"model", FOFS(model), F_LSTRING}, {"model2", FOFS(model2), F_LSTRING}, {"spawnflags", FOFS(spawnflags), F_INT}, {"speed", FOFS(speed), F_FLOAT}, {"target", FOFS(target), F_LSTRING}, {"target2", FOFS(target2), F_LSTRING}, {"target3", FOFS(target3), F_LSTRING}, {"target4", FOFS(target4), F_LSTRING}, {"target5", FOFS(target5), F_LSTRING}, {"target6", FOFS(target6), F_LSTRING}, {"NPC_targetname", FOFS(NPC_targetname), F_LSTRING}, {"NPC_target", FOFS(NPC_target), F_LSTRING}, {"NPC_target2", FOFS(target2), F_LSTRING},//NPC_spawner only {"NPC_target4", FOFS(target4), F_LSTRING},//NPC_spawner only {"NPC_type", FOFS(NPC_type), F_LSTRING}, {"targetname", FOFS(targetname), F_LSTRING}, {"message", FOFS(message), F_LSTRING}, {"team", FOFS(team), F_LSTRING}, {"wait", FOFS(wait), F_FLOAT}, {"delay", FOFS(delay), F_INT}, {"random", FOFS(random), F_FLOAT}, {"count", FOFS(count), F_INT}, {"health", FOFS(health), F_INT}, {"light", 0, F_IGNORE}, {"dmg", FOFS(damage), F_INT}, {"angles", FOFS(s.angles), F_VECTOR}, {"angle", FOFS(s.angles), F_ANGLEHACK}, {"targetShaderName", FOFS(targetShaderName), F_LSTRING}, {"targetShaderNewName", FOFS(targetShaderNewName), F_LSTRING}, {"linear", FOFS(alt_fire), F_INT},//for movers to use linear movement {"closetarget", FOFS(closetarget), F_LSTRING},//for doors {"opentarget", FOFS(opentarget), F_LSTRING},//for doors {"paintarget", FOFS(paintarget), F_LSTRING},//for doors {"goaltarget", FOFS(goaltarget), F_LSTRING},//for siege {"idealclass", FOFS(idealclass), F_LSTRING},//for siege spawnpoints //rww - icarus stuff: {"spawnscript", FOFS(behaviorSet[BSET_SPAWN]), F_LSTRING},//name of script to run {"usescript", FOFS(behaviorSet[BSET_USE]), F_LSTRING},//name of script to run {"awakescript", FOFS(behaviorSet[BSET_AWAKE]), F_LSTRING},//name of script to run {"angerscript", FOFS(behaviorSet[BSET_ANGER]), F_LSTRING},//name of script to run {"attackscript", FOFS(behaviorSet[BSET_ATTACK]), F_LSTRING},//name of script to run {"victoryscript", FOFS(behaviorSet[BSET_VICTORY]), F_LSTRING},//name of script to run {"lostenemyscript", FOFS(behaviorSet[BSET_LOSTENEMY]), F_LSTRING},//name of script to run {"painscript", FOFS(behaviorSet[BSET_PAIN]), F_LSTRING},//name of script to run {"fleescript", FOFS(behaviorSet[BSET_FLEE]), F_LSTRING},//name of script to run {"deathscript", FOFS(behaviorSet[BSET_DEATH]), F_LSTRING},//name of script to run {"delayscript", FOFS(behaviorSet[BSET_DELAYED]), F_LSTRING},//name of script to run {"delayscripttime", FOFS(delayScriptTime), F_INT},//name of script to run {"blockedscript", FOFS(behaviorSet[BSET_BLOCKED]), F_LSTRING},//name of script to run {"ffirescript", FOFS(behaviorSet[BSET_FFIRE]), F_LSTRING},//name of script to run {"ffdeathscript", FOFS(behaviorSet[BSET_FFDEATH]), F_LSTRING},//name of script to run {"mindtrickscript", FOFS(behaviorSet[BSET_MINDTRICK]), F_LSTRING},//name of script to run {"script_targetname", FOFS(script_targetname), F_LSTRING},//scripts look for this when "affecting" {"fullName", FOFS(fullName), F_LSTRING}, {"soundSet", FOFS(soundSet), F_LSTRING}, {"radius", FOFS(radius), F_FLOAT}, {"numchunks", FOFS(radius), F_FLOAT},//for func_breakables {"chunksize", FOFS(mass), F_FLOAT},//for func_breakables //Script parms - will this handle clamping to 16 or whatever length of parm[0] is? {"parm1", 0, F_PARM1}, {"parm2", 0, F_PARM2}, {"parm3", 0, F_PARM3}, {"parm4", 0, F_PARM4}, {"parm5", 0, F_PARM5}, {"parm6", 0, F_PARM6}, {"parm7", 0, F_PARM7}, {"parm8", 0, F_PARM8}, {"parm9", 0, F_PARM9}, {"parm10", 0, F_PARM10}, {"parm11", 0, F_PARM11}, {"parm12", 0, F_PARM12}, {"parm13", 0, F_PARM13}, {"parm14", 0, F_PARM14}, {"parm15", 0, F_PARM15}, {"parm16", 0, F_PARM16}, {NULL} }; typedef struct { char *name; void (*spawn)(gentity_t *ent); } spawn_t; void SP_info_player_start (gentity_t *ent); void SP_info_player_duel( gentity_t *ent ); void SP_info_player_duel1( gentity_t *ent ); void SP_info_player_duel2( gentity_t *ent ); void SP_info_player_deathmatch (gentity_t *ent); void SP_info_player_siegeteam1 (gentity_t *ent); void SP_info_player_siegeteam2 (gentity_t *ent); void SP_info_player_intermission (gentity_t *ent); void SP_info_player_intermission_red (gentity_t *ent); void SP_info_player_intermission_blue (gentity_t *ent); void SP_info_jedimaster_start (gentity_t *ent); void SP_info_player_start_red (gentity_t *ent); void SP_info_player_start_blue (gentity_t *ent); void SP_info_firstplace(gentity_t *ent); void SP_info_secondplace(gentity_t *ent); void SP_info_thirdplace(gentity_t *ent); void SP_info_podium(gentity_t *ent); void SP_info_siege_objective (gentity_t *ent); void SP_info_siege_radaricon (gentity_t *ent); void SP_info_siege_decomplete (gentity_t *ent); void SP_target_siege_end (gentity_t *ent); void SP_misc_siege_item (gentity_t *ent); void SP_func_plat (gentity_t *ent); void SP_func_static (gentity_t *ent); void SP_func_rotating (gentity_t *ent); void SP_func_bobbing (gentity_t *ent); void SP_func_pendulum( gentity_t *ent ); void SP_func_button (gentity_t *ent); void SP_func_door (gentity_t *ent); void SP_func_train (gentity_t *ent); void SP_func_timer (gentity_t *self); void SP_func_breakable (gentity_t *ent); void SP_func_glass (gentity_t *ent); void SP_func_usable( gentity_t *ent); void SP_func_wall( gentity_t *ent ); void SP_trigger_lightningstrike( gentity_t *ent ); void SP_trigger_always (gentity_t *ent); void SP_trigger_multiple (gentity_t *ent); void SP_trigger_once( gentity_t *ent ); void SP_trigger_push (gentity_t *ent); void SP_trigger_teleport (gentity_t *ent); void SP_trigger_hurt (gentity_t *ent); void SP_trigger_space(gentity_t *self); void SP_trigger_shipboundary(gentity_t *self); void SP_trigger_hyperspace(gentity_t *self); void SP_trigger_asteroid_field(gentity_t *self); void SP_target_remove_powerups( gentity_t *ent ); void SP_target_give (gentity_t *ent); void SP_target_delay (gentity_t *ent); void SP_target_speaker (gentity_t *ent); void SP_target_print (gentity_t *ent); void SP_target_laser (gentity_t *self); void SP_target_character (gentity_t *ent); void SP_target_score( gentity_t *ent ); void SP_target_teleporter( gentity_t *ent ); void SP_target_relay (gentity_t *ent); void SP_target_kill (gentity_t *ent); void SP_target_position (gentity_t *ent); void SP_target_location (gentity_t *ent); void SP_target_counter (gentity_t *self); void SP_target_random (gentity_t *self); void SP_target_scriptrunner( gentity_t *self ); void SP_target_interest (gentity_t *self); void SP_target_activate (gentity_t *self); void SP_target_deactivate (gentity_t *self); void SP_target_level_change( gentity_t *self ); void SP_target_play_music( gentity_t *self ); void SP_target_push (gentity_t *ent); void SP_light (gentity_t *self); void SP_info_null (gentity_t *self); void SP_info_notnull (gentity_t *self); void SP_info_camp (gentity_t *self); void SP_path_corner (gentity_t *self); void SP_misc_teleporter_dest (gentity_t *self); void SP_misc_model(gentity_t *ent); void SP_misc_model_static(gentity_t *ent); void SP_misc_G2model(gentity_t *ent); void SP_misc_portal_camera(gentity_t *ent); void SP_misc_portal_surface(gentity_t *ent); void SP_misc_weather_zone( gentity_t *ent ); void SP_misc_bsp (gentity_t *ent); void SP_terrain (gentity_t *ent); void SP_misc_skyportal_orient (gentity_t *ent); void SP_misc_skyportal (gentity_t *ent); void SP_misc_ammo_floor_unit(gentity_t *ent); void SP_misc_shield_floor_unit( gentity_t *ent ); void SP_misc_model_shield_power_converter( gentity_t *ent ); void SP_misc_model_ammo_power_converter( gentity_t *ent ); void SP_misc_model_health_power_converter( gentity_t *ent ); void SP_fx_runner( gentity_t *ent ); void SP_target_screenshake(gentity_t *ent); void SP_target_escapetrig(gentity_t *ent); void SP_misc_maglock ( gentity_t *self ); void SP_misc_faller(gentity_t *ent); void SP_misc_holocron(gentity_t *ent); void SP_reference_tag ( gentity_t *ent ); void SP_misc_weapon_shooter( gentity_t *self ); void SP_NPC_spawner( gentity_t *self ); void SP_NPC_Vehicle( gentity_t *self); void SP_NPC_Kyle( gentity_t *self ); void SP_NPC_Lando( gentity_t *self ); void SP_NPC_Jan( gentity_t *self ); void SP_NPC_Luke( gentity_t *self ); void SP_NPC_MonMothma( gentity_t *self ); void SP_NPC_Tavion( gentity_t *self ); void SP_NPC_Tavion_New( gentity_t *self ); void SP_NPC_Alora( gentity_t *self ); void SP_NPC_Reelo( gentity_t *self ); void SP_NPC_Galak( gentity_t *self ); void SP_NPC_Desann( gentity_t *self ); void SP_NPC_Bartender( gentity_t *self ); void SP_NPC_MorganKatarn( gentity_t *self ); void SP_NPC_Jedi( gentity_t *self ); void SP_NPC_Prisoner( gentity_t *self ); void SP_NPC_Rebel( gentity_t *self ); void SP_NPC_Stormtrooper( gentity_t *self ); void SP_NPC_StormtrooperOfficer( gentity_t *self ); void SP_NPC_Snowtrooper( gentity_t *self); void SP_NPC_Tie_Pilot( gentity_t *self ); void SP_NPC_Ugnaught( gentity_t *self ); void SP_NPC_Jawa( gentity_t *self ); void SP_NPC_Gran( gentity_t *self ); void SP_NPC_Rodian( gentity_t *self ); void SP_NPC_Weequay( gentity_t *self ); void SP_NPC_Trandoshan( gentity_t *self ); void SP_NPC_Tusken( gentity_t *self ); void SP_NPC_Noghri( gentity_t *self ); void SP_NPC_SwampTrooper( gentity_t *self ); void SP_NPC_Imperial( gentity_t *self ); void SP_NPC_ImpWorker( gentity_t *self ); void SP_NPC_BespinCop( gentity_t *self ); void SP_NPC_Reborn( gentity_t *self ); void SP_NPC_ShadowTrooper( gentity_t *self ); void SP_NPC_Monster_Murjj( gentity_t *self ); void SP_NPC_Monster_Swamp( gentity_t *self ); void SP_NPC_Monster_Howler( gentity_t *self ); void SP_NPC_Monster_Claw( gentity_t *self ); void SP_NPC_Monster_Glider( gentity_t *self ); void SP_NPC_Monster_Flier2( gentity_t *self ); void SP_NPC_Monster_Lizard( gentity_t *self ); void SP_NPC_Monster_Fish( gentity_t *self ); void SP_NPC_Monster_Wampa( gentity_t *self ); void SP_NPC_Monster_Rancor( gentity_t *self ); void SP_NPC_MineMonster( gentity_t *self ); void SP_NPC_Droid_Interrogator( gentity_t *self ); void SP_NPC_Droid_Probe( gentity_t *self ); void SP_NPC_Droid_Mark1( gentity_t *self ); void SP_NPC_Droid_Mark2( gentity_t *self ); void SP_NPC_Droid_ATST( gentity_t *self ); void SP_NPC_Droid_Seeker( gentity_t *self ); void SP_NPC_Droid_Remote( gentity_t *self ); void SP_NPC_Droid_Sentry( gentity_t *self ); void SP_NPC_Droid_Gonk( gentity_t *self ); void SP_NPC_Droid_Mouse( gentity_t *self ); void SP_NPC_Droid_R2D2( gentity_t *self ); void SP_NPC_Droid_R5D2( gentity_t *self ); void SP_NPC_Droid_Protocol( gentity_t *self ); void SP_NPC_Reborn_New( gentity_t *self); void SP_NPC_Cultist( gentity_t *self ); void SP_NPC_Cultist_Saber( gentity_t *self ); void SP_NPC_Cultist_Saber_Powers( gentity_t *self ); void SP_NPC_Cultist_Destroyer( gentity_t *self ); void SP_NPC_Cultist_Commando( gentity_t *self ); void SP_waypoint (gentity_t *ent); void SP_waypoint_small (gentity_t *ent); void SP_waypoint_navgoal (gentity_t *ent); void SP_waypoint_navgoal_8 (gentity_t *ent); void SP_waypoint_navgoal_4 (gentity_t *ent); void SP_waypoint_navgoal_2 (gentity_t *ent); void SP_waypoint_navgoal_1 (gentity_t *ent); void SP_CreateSpaceDust( gentity_t *ent ); void SP_CreateSnow( gentity_t *ent ); void SP_CreateRain( gentity_t *ent ); void SP_point_combat( gentity_t *self ); void SP_shooter_blaster( gentity_t *ent ); void SP_team_CTF_redplayer( gentity_t *ent ); void SP_team_CTF_blueplayer( gentity_t *ent ); void SP_team_CTF_redspawn( gentity_t *ent ); void SP_team_CTF_bluespawn( gentity_t *ent ); void SP_misc_turret( gentity_t *ent ); void SP_misc_turretG2( gentity_t *base ); void SP_item_botroam( gentity_t *ent ) { } void SP_gametype_item ( gentity_t* ent ) { gitem_t *item = NULL; char *value; int team = -1; G_SpawnString("teamfilter", "", &value); G_SetOrigin( ent, ent->s.origin ); // If a team filter is set then override any team settings for the spawns if ( level.mTeamFilter[0] ) { if ( Q_stricmp ( level.mTeamFilter, "red") == 0 ) { team = TEAM_RED; } else if ( Q_stricmp ( level.mTeamFilter, "blue") == 0 ) { team = TEAM_BLUE; } } if (ent->targetname && ent->targetname[0]) { if (team != -1) { if (strstr(ent->targetname, "flag")) { if (team == TEAM_RED) { item = BG_FindItem("team_CTF_redflag"); } else { //blue item = BG_FindItem("team_CTF_blueflag"); } } } else if (strstr(ent->targetname, "red_flag")) { item = BG_FindItem("team_CTF_redflag"); } else if (strstr(ent->targetname, "blue_flag")) { item = BG_FindItem("team_CTF_blueflag"); } else { item = NULL; } if (item) { ent->targetname = NULL; ent->classname = item->classname; G_SpawnItem( ent, item ); } } } void SP_emplaced_gun( gentity_t *ent ); spawn_t spawns[] = { // info entities don't do anything at all, but provide positional // information for things controlled by other processes {"info_player_start", SP_info_player_start}, {"info_player_duel", SP_info_player_duel}, {"info_player_duel1", SP_info_player_duel1}, {"info_player_duel2", SP_info_player_duel2}, {"info_player_deathmatch", SP_info_player_deathmatch}, {"info_player_siegeteam1", SP_info_player_siegeteam1}, {"info_player_siegeteam2", SP_info_player_siegeteam2}, {"info_player_intermission", SP_info_player_intermission}, {"info_player_intermission_red", SP_info_player_intermission_red}, {"info_player_intermission_blue", SP_info_player_intermission_blue}, {"info_jedimaster_start", SP_info_jedimaster_start}, {"info_player_start_red", SP_info_player_start_red}, {"info_player_start_blue", SP_info_player_start_blue}, {"info_null", SP_info_null}, {"info_notnull", SP_info_notnull}, // use target_position instead {"info_camp", SP_info_camp}, {"info_siege_objective", SP_info_siege_objective}, {"info_siege_radaricon", SP_info_siege_radaricon}, {"info_siege_decomplete", SP_info_siege_decomplete}, {"target_siege_end", SP_target_siege_end}, {"misc_siege_item", SP_misc_siege_item}, {"func_plat", SP_func_plat}, {"func_button", SP_func_button}, {"func_door", SP_func_door}, {"func_static", SP_func_static}, {"func_rotating", SP_func_rotating}, {"func_bobbing", SP_func_bobbing}, {"func_pendulum", SP_func_pendulum}, {"func_train", SP_func_train}, {"func_group", SP_info_null}, {"func_timer", SP_func_timer}, // rename trigger_timer? {"func_breakable", SP_func_breakable}, {"func_glass", SP_func_glass}, {"func_usable", SP_func_usable}, {"func_wall", SP_func_wall}, // Triggers are brush objects that cause an effect when contacted // by a living player, usually involving firing targets. // While almost everything could be done with // a single trigger class and different targets, triggered effects // could not be client side predicted (push and teleport). {"trigger_lightningstrike", SP_trigger_lightningstrike}, {"trigger_always", SP_trigger_always}, {"trigger_multiple", SP_trigger_multiple}, {"trigger_once", SP_trigger_once}, {"trigger_push", SP_trigger_push}, {"trigger_teleport", SP_trigger_teleport}, {"trigger_hurt", SP_trigger_hurt}, {"trigger_space", SP_trigger_space}, {"trigger_shipboundary", SP_trigger_shipboundary}, {"trigger_hyperspace", SP_trigger_hyperspace}, {"trigger_asteroid_field", SP_trigger_asteroid_field}, // targets perform no action by themselves, but must be triggered // by another entity {"target_give", SP_target_give}, {"target_remove_powerups", SP_target_remove_powerups}, {"target_delay", SP_target_delay}, {"target_speaker", SP_target_speaker}, {"target_print", SP_target_print}, {"target_laser", SP_target_laser}, {"target_score", SP_target_score}, {"target_teleporter", SP_target_teleporter}, {"target_relay", SP_target_relay}, {"target_kill", SP_target_kill}, {"target_position", SP_target_position}, {"target_location", SP_target_location}, {"target_counter", SP_target_counter}, {"target_random", SP_target_random}, {"target_scriptrunner", SP_target_scriptrunner}, {"target_interest", SP_target_interest}, {"target_activate", SP_target_activate}, {"target_deactivate", SP_target_deactivate}, {"target_level_change", SP_target_level_change}, {"target_play_music", SP_target_play_music}, {"target_push", SP_target_push}, {"light", SP_light}, {"path_corner", SP_path_corner}, {"misc_teleporter_dest", SP_misc_teleporter_dest}, {"misc_model", SP_misc_model}, {"misc_model_static", SP_misc_model_static}, {"misc_G2model", SP_misc_G2model}, {"misc_portal_surface", SP_misc_portal_surface}, {"misc_portal_camera", SP_misc_portal_camera}, {"misc_weather_zone", SP_misc_weather_zone}, {"misc_bsp", SP_misc_bsp}, {"terrain", SP_terrain}, {"misc_skyportal_orient", SP_misc_skyportal_orient}, {"misc_skyportal", SP_misc_skyportal}, //rwwFIXMEFIXME: only for testing rmg team stuff {"gametype_item", SP_gametype_item }, {"misc_ammo_floor_unit", SP_misc_ammo_floor_unit}, {"misc_shield_floor_unit", SP_misc_shield_floor_unit}, {"misc_model_shield_power_converter", SP_misc_model_shield_power_converter}, {"misc_model_ammo_power_converter", SP_misc_model_ammo_power_converter}, {"misc_model_health_power_converter", SP_misc_model_health_power_converter}, {"fx_runner", SP_fx_runner}, {"target_screenshake", SP_target_screenshake}, {"target_escapetrig", SP_target_escapetrig}, {"misc_maglock", SP_misc_maglock}, {"misc_faller", SP_misc_faller}, {"ref_tag", SP_reference_tag}, {"ref_tag_huge", SP_reference_tag}, {"misc_weapon_shooter", SP_misc_weapon_shooter}, //new NPC ents {"NPC_spawner", SP_NPC_spawner}, {"NPC_Vehicle", SP_NPC_Vehicle }, {"NPC_Kyle", SP_NPC_Kyle }, {"NPC_Lando", SP_NPC_Lando }, {"NPC_Jan", SP_NPC_Jan }, {"NPC_Luke", SP_NPC_Luke }, {"NPC_MonMothma", SP_NPC_MonMothma }, {"NPC_Tavion", SP_NPC_Tavion }, //new tavion {"NPC_Tavion_New", SP_NPC_Tavion_New }, //new alora {"NPC_Alora", SP_NPC_Alora }, {"NPC_Reelo", SP_NPC_Reelo }, {"NPC_Galak", SP_NPC_Galak }, {"NPC_Desann", SP_NPC_Desann }, {"NPC_Bartender", SP_NPC_Bartender }, {"NPC_MorganKatarn", SP_NPC_MorganKatarn }, {"NPC_Jedi", SP_NPC_Jedi }, {"NPC_Prisoner", SP_NPC_Prisoner }, {"NPC_Rebel", SP_NPC_Rebel }, {"NPC_Stormtrooper", SP_NPC_Stormtrooper }, {"NPC_StormtrooperOfficer", SP_NPC_StormtrooperOfficer }, {"NPC_Snowtrooper", SP_NPC_Snowtrooper }, {"NPC_Tie_Pilot", SP_NPC_Tie_Pilot }, {"NPC_Ugnaught", SP_NPC_Ugnaught }, {"NPC_Jawa", SP_NPC_Jawa }, {"NPC_Gran", SP_NPC_Gran }, {"NPC_Rodian", SP_NPC_Rodian }, {"NPC_Weequay", SP_NPC_Weequay }, {"NPC_Trandoshan", SP_NPC_Trandoshan }, {"NPC_Tusken", SP_NPC_Tusken }, {"NPC_Noghri", SP_NPC_Noghri }, {"NPC_SwampTrooper", SP_NPC_SwampTrooper }, {"NPC_Imperial", SP_NPC_Imperial }, {"NPC_ImpWorker", SP_NPC_ImpWorker }, {"NPC_BespinCop", SP_NPC_BespinCop }, {"NPC_Reborn", SP_NPC_Reborn }, {"NPC_ShadowTrooper", SP_NPC_ShadowTrooper }, {"NPC_Monster_Murjj", SP_NPC_Monster_Murjj }, {"NPC_Monster_Swamp", SP_NPC_Monster_Swamp }, {"NPC_Monster_Howler", SP_NPC_Monster_Howler }, {"NPC_MineMonster", SP_NPC_MineMonster }, {"NPC_Monster_Claw", SP_NPC_Monster_Claw }, {"NPC_Monster_Glider", SP_NPC_Monster_Glider }, {"NPC_Monster_Flier2", SP_NPC_Monster_Flier2 }, {"NPC_Monster_Lizard", SP_NPC_Monster_Lizard }, {"NPC_Monster_Fish", SP_NPC_Monster_Fish }, {"NPC_Monster_Wampa", SP_NPC_Monster_Wampa }, {"NPC_Monster_Rancor", SP_NPC_Monster_Rancor }, {"NPC_Droid_Interrogator", SP_NPC_Droid_Interrogator }, {"NPC_Droid_Probe", SP_NPC_Droid_Probe }, {"NPC_Droid_Mark1", SP_NPC_Droid_Mark1 }, {"NPC_Droid_Mark2", SP_NPC_Droid_Mark2 }, {"NPC_Droid_ATST", SP_NPC_Droid_ATST }, {"NPC_Droid_Seeker", SP_NPC_Droid_Seeker }, {"NPC_Droid_Remote", SP_NPC_Droid_Remote }, {"NPC_Droid_Sentry", SP_NPC_Droid_Sentry }, {"NPC_Droid_Gonk", SP_NPC_Droid_Gonk }, {"NPC_Droid_Mouse", SP_NPC_Droid_Mouse }, {"NPC_Droid_R2D2", SP_NPC_Droid_R2D2 }, {"NPC_Droid_R5D2", SP_NPC_Droid_R5D2 }, {"NPC_Droid_Protocol", SP_NPC_Droid_Protocol }, //maybe put these guys in some day, for now just spawn reborns in their place. {"NPC_Reborn_New", SP_NPC_Reborn_New }, {"NPC_Cultist", SP_NPC_Cultist }, {"NPC_Cultist_Saber", SP_NPC_Cultist_Saber }, {"NPC_Cultist_Saber_Powers", SP_NPC_Cultist_Saber_Powers }, {"NPC_Cultist_Destroyer", SP_NPC_Cultist_Destroyer }, {"NPC_Cultist_Commando", SP_NPC_Cultist_Commando }, //rwwFIXMEFIXME: Faked for testing NPCs (another other things) in RMG with sof2 assets {"NPC_Colombian_Soldier", SP_NPC_Reborn }, {"NPC_Colombian_Rebel", SP_NPC_Reborn }, {"NPC_Colombian_EmplacedGunner", SP_NPC_ShadowTrooper }, {"NPC_Manuel_Vergara_RMG", SP_NPC_Desann }, // {"info_NPCnav", SP_waypoint}, {"waypoint", SP_waypoint}, {"waypoint_small", SP_waypoint_small}, {"waypoint_navgoal", SP_waypoint_navgoal}, {"waypoint_navgoal_8", SP_waypoint_navgoal_8}, {"waypoint_navgoal_4", SP_waypoint_navgoal_4}, {"waypoint_navgoal_2", SP_waypoint_navgoal_2}, {"waypoint_navgoal_1", SP_waypoint_navgoal_1}, {"fx_spacedust", SP_CreateSpaceDust}, {"fx_rain", SP_CreateRain}, {"fx_snow", SP_CreateSnow}, {"point_combat", SP_point_combat}, {"misc_holocron", SP_misc_holocron}, {"shooter_blaster", SP_shooter_blaster}, {"team_CTF_redplayer", SP_team_CTF_redplayer}, {"team_CTF_blueplayer", SP_team_CTF_blueplayer}, {"team_CTF_redspawn", SP_team_CTF_redspawn}, {"team_CTF_bluespawn", SP_team_CTF_bluespawn}, {"item_botroam", SP_item_botroam}, {"emplaced_gun", SP_emplaced_gun}, {"misc_turret", SP_misc_turret}, {"misc_turretG2", SP_misc_turretG2}, {0, 0} }; /* =============== G_CallSpawn Finds the spawn function for the entity and calls it, returning qfalse if not found =============== */ qboolean G_CallSpawn( gentity_t *ent ) { spawn_t *s; gitem_t *item; if ( !ent->classname ) { G_Printf ("G_CallSpawn: NULL classname\n"); return qfalse; } // check item spawn functions for ( item=bg_itemlist+1 ; item->classname ; item++ ) { if ( !strcmp(item->classname, ent->classname) ) { G_SpawnItem( ent, item ); return qtrue; } } // check normal spawn functions for ( s=spawns ; s->name ; s++ ) { if ( !strcmp(s->name, ent->classname) ) { // found it if (ent->healingsound && ent->healingsound[0]) { //yeah...this can be used for anything, so.. precache it if it's there G_SoundIndex(ent->healingsound); } s->spawn(ent); return qtrue; } } G_Printf ("%s doesn't have a spawn function\n", ent->classname); return qfalse; } /* ============= G_NewString Builds a copy of the string, translating \n to real linefeeds so message texts can be multi-line ============= */ char *G_NewString( const char *string ) { char *newb, *new_p; int i,l; l = strlen(string) + 1; newb = (char *) G_Alloc( l ); new_p = newb; // turn \n into a real linefeed for ( i=0 ; i< l ; i++ ) { if (string[i] == '\\' && i < l-1) { i++; if (string[i] == 'n') { *new_p++ = '\n'; } else { *new_p++ = '\\'; } } else { *new_p++ = string[i]; } } return newb; } /* =================== G_SpawnGEntityFromSpawnVars Spawn an entity and fill in all of the level fields from level.spawnVars[], then call the class specfic spawn function =================== */ #include "../namespace_begin.h" void BG_ParseField( BG_field_t *l_fields, const char *key, const char *value, byte *ent ); #include "../namespace_end.h" void G_SpawnGEntityFromSpawnVars( qboolean inSubBSP ) { int i; gentity_t *ent; char *s, *value, *gametypeName; static char *gametypeNames[] = {"ffa", "holocron", "jedimaster", "duel", "powerduel", "single", "team", "siege", "ctf", "cty"}; // get the next free entity ent = G_Spawn(); for ( i = 0 ; i < level.numSpawnVars ; i++ ) { BG_ParseField( fields, level.spawnVars[i][0], level.spawnVars[i][1], (byte *)ent ); } // check for "notsingle" flag if ( g_gametype.integer == GT_SINGLE_PLAYER ) { G_SpawnInt( "notsingle", "0", &i ); if ( i ) { G_FreeEntity( ent ); return; } } // check for "notteam" flag (GT_FFA, GT_DUEL, GT_SINGLE_PLAYER) if ( g_gametype.integer >= GT_TEAM ) { G_SpawnInt( "notteam", "0", &i ); if ( i ) { G_FreeEntity( ent ); return; } } else { G_SpawnInt( "notfree", "0", &i ); if ( i ) { G_FreeEntity( ent ); return; } } G_SpawnInt( "notta", "0", &i ); if ( i ) { G_FreeEntity( ent ); return; } if( G_SpawnString( "gametype", NULL, &value ) ) { if( g_gametype.integer >= GT_FFA && g_gametype.integer < GT_MAX_GAME_TYPE ) { gametypeName = gametypeNames[g_gametype.integer]; s = strstr( value, gametypeName ); if( !s ) { G_FreeEntity( ent ); return; } } } // move editor origin to pos VectorCopy( ent->s.origin, ent->s.pos.trBase ); VectorCopy( ent->s.origin, ent->r.currentOrigin ); // if we didn't get a classname, don't bother spawning anything if ( !G_CallSpawn( ent ) ) { G_FreeEntity( ent ); } //Tag on the ICARUS scripting information only to valid recipients if ( trap_ICARUS_ValidEnt( ent ) ) { trap_ICARUS_InitEnt( ent ); if ( ent->classname && ent->classname[0] ) { if ( Q_strncmp( "NPC_", ent->classname, 4 ) != 0 ) {//Not an NPC_spawner (rww - probably don't even care for MP, but whatever) G_ActivateBehavior( ent, BSET_SPAWN ); } } } } /* ==================== G_AddSpawnVarToken ==================== */ char *G_AddSpawnVarToken( const char *string ) { int l; char *dest; l = strlen( string ); if ( level.numSpawnVarChars + l + 1 > MAX_SPAWN_VARS_CHARS ) { G_Error( "G_AddSpawnVarToken: MAX_SPAWN_CHARS" ); } dest = level.spawnVarChars + level.numSpawnVarChars; memcpy( dest, string, l+1 ); level.numSpawnVarChars += l + 1; return dest; } void AddSpawnField(char *field, char *value) { int i; for(i=0;iinuse && ent->soundSet && ent->soundSet[0]) { if (countedSets >= MAX_AMBIENT_SETS) { Com_Error(ERR_DROP, "MAX_AMBIENT_SETS was exceeded! (too many soundsets)\n"); } ent->s.soundSetIndex = G_SoundSetIndex(ent->soundSet); countedSets++; } } } /* ============== G_SpawnEntitiesFromString Parses textual entity definitions out of an entstring and spawns gentities. ============== */ void G_SpawnEntitiesFromString( qboolean inSubBSP ) { // allow calls to G_Spawn*() level.spawning = qtrue; level.numSpawnVars = 0; // the worldspawn is not an actual entity, but it still // has a "spawn" function to perform any global setup // needed by a level (setting configstrings or cvars, etc) if ( !G_ParseSpawnVars(qfalse) ) { G_Error( "SpawnEntities: no entities" ); } if (!inSubBSP) { SP_worldspawn(); } else { // Skip this guy if its worldspawn fails if ( !SP_bsp_worldspawn() ) { return; } } // parse ents while( G_ParseSpawnVars(inSubBSP) ) { G_SpawnGEntityFromSpawnVars(inSubBSP); } if( g_entities[ENTITYNUM_WORLD].behaviorSet[BSET_SPAWN] && g_entities[ENTITYNUM_WORLD].behaviorSet[BSET_SPAWN][0] ) {//World has a spawn script, but we don't want the world in ICARUS and running scripts, //so make a scriptrunner and start it going. gentity_t *script_runner = G_Spawn(); if ( script_runner ) { script_runner->behaviorSet[BSET_USE] = g_entities[ENTITYNUM_WORLD].behaviorSet[BSET_SPAWN]; script_runner->count = 1; script_runner->think = scriptrunner_run; script_runner->nextthink = level.time + 100; if ( script_runner->inuse ) { trap_ICARUS_InitEnt( script_runner ); } } } if (!inSubBSP) { level.spawning = qfalse; // any future calls to G_Spawn*() will be errors } G_PrecacheSoundsets(); }