Сохраняемые объекты s_PreserveEnts (белый список)

From Valve Developer Community
< Ru
Jump to navigation Jump to search
English (en)Русский (ru)中文 (zh)Translate (Translate)

В многопользовательских играх Source Source все объекты(en) возвращаются к исходному состоянию во время сброса раунда путём их удаления и немедленного повторного создания, если их текущее имя класса(en) не указано в белом списке s_PreserveEnts. Объекты из белого списка либо имеют специальный код для обработки процесса сброса, либо его нет вовсе, и поэтому такой объект считается неудаляемым.

Некоторые перечисленные в белом списке объекты могут неправильно учитывать сброс раунда и, вероятно, сохранят свои предыдущие свойства в следующем раунде, например, своё положение(en).

Note.pngПримечание:
  • Some games might not have any way to reset the round (even through mp_forcewin or mp_restartgame commands).
  • Contexts aren't preserved between round restart even for preserved entities  (подтверждено в: Left 4 Dead 2)
  • Entities with the entity flag EFL_KILLME are preserved, even if they aren't in the s_PreserveEnts array. This can be set via Vscript in supported games, to preserve entities that aren't normally preserved.
Игра Есть
белый список
Есть
система раундов
Примечания
Counter-Strike: Source Counter-Strike: Source Да Да
Half-Life: Source Half-Life: Source Нет -
Half-Life Deathmatch: Source Half-Life Deathmatch: Source Нет -
Half-Life 2 Half-Life 2 Нет -
Half-Life 2: Deathmatch Half-Life 2: Deathmatch Да Нет Раунд можно сбросить с помощью команды mp_restartgame
Day of Defeat: Source Day of Defeat: Source Да Да
Half-Life 2: Episode One Half-Life 2: Episode One Нет -
Half-Life 2: Episode Two Half-Life 2: Episode Two Нет -
Portal Portal Нет - Белый список существует, но не добавлен в скомпилированные DLL.
Team Fortress 2 Team Fortress 2 Да Да
Left 4 Dead Left 4 Dead Да Да
Left 4 Dead 2 Left 4 Dead 2 Да Да
Alien Swarm Alien SwarmAlien Swarm: Reactive Drop Alien Swarm: Reactive Drop Да Нет Параметр asw_instant_restart 1 должен позволять сбросить раунд без полной перезагрузки карты, но, похоже, вместо этого в Alien Swarm всегда приводит к сбою игры. Это поведение по умолчанию в Alien Swarm: Reactive Drop и работает правильно.
Использует функцию m_MapResetFilter.AddKeepEntity() вместо массива s_PreserveEnts[].
Portal 2 Portal 2 Да Нет Можно ли перезапустить раунд в кооперативном режиме?[подтвердить]
Counter-Strike: Global Offensive Counter-Strike: Global Offensive Да Да

Поведение

Если в игре есть система перезапуска раундов, сохраняемый объект может вести себя не так, как ожидается:

  • В новом раунде объекты с таким именем класса преднамеренно не будут сбрасываться. Вы можете использовать logic_auto для имитации сброса.
  • При уничтожении(en) такого объекта он удаляется навсегда (до перезапуска игрового процесса), так как он не создаётся вновь в новом раунде.
  • Его нельзя создать с помощью point_template.
  • Привязка этого объекта к несохраняемым объектам может привести к нежелательным последствиям.

Списки

Note.pngПримечание:Some entities don't exist in the given games despite being in s_preservedEnts list. (for example info_node* entities in Серия игр Left 4 DeadСерия игр Left 4 Dead)

Source Code

Alien Swarm Alien Swarm

swarm/asw_gamerules.cpp
CAlienSwarm::CAlienSwarm()
{
	// set which entities should stay around when we restart the mission
	m_MapResetFilter.AddKeepEntity("worldspawn");
	m_MapResetFilter.AddKeepEntity("soundent");
	m_MapResetFilter.AddKeepEntity("asw_gamerules");
	m_MapResetFilter.AddKeepEntity("player");
	m_MapResetFilter.AddKeepEntity("asw_player");
	m_MapResetFilter.AddKeepEntity("player_manager");	
	m_MapResetFilter.AddKeepEntity("predicted_viewmodel");
	m_MapResetFilter.AddKeepEntity("sdk_team_manager");
	m_MapResetFilter.AddKeepEntity("scene_manager");
	m_MapResetFilter.AddKeepEntity("event_queue_saveload_proxy");
	m_MapResetFilter.AddKeepEntity("ai_network");
}

Alien Swarm: Reactive Drop Alien Swarm: Reactive Drop

swarm/asw_gamerules.cpp
	// set which entities should stay around when we restart the mission
	m_MapResetFilter.AddKeepEntity( "worldspawn" );
	m_MapResetFilter.AddKeepEntity( "soundent" );
	m_MapResetFilter.AddKeepEntity( "asw_gamerules" );
	m_MapResetFilter.AddKeepEntity( "player" );
	m_MapResetFilter.AddKeepEntity( "asw_player" );
	m_MapResetFilter.AddKeepEntity( "player_manager" );
	m_MapResetFilter.AddKeepEntity( "predicted_viewmodel" );
	m_MapResetFilter.AddKeepEntity( "sdk_team_manager" );
	m_MapResetFilter.AddKeepEntity( "scene_manager" );
	m_MapResetFilter.AddKeepEntity( "event_queue_saveload_proxy" );
	m_MapResetFilter.AddKeepEntity( "ai_network" );
	m_MapResetFilter.AddKeepEntity( "ai_hint" );
	m_MapResetFilter.AddKeepEntity( "info_node" );
	m_MapResetFilter.AddKeepEntity( "info_hint" );
	m_MapResetFilter.AddKeepEntity( "info_node_hint" );
	m_MapResetFilter.AddKeepEntity( "info_node_air" );
	m_MapResetFilter.AddKeepEntity( "info_node_air_hint" );
	m_MapResetFilter.AddKeepEntity( "info_node_climb" );
	m_MapResetFilter.AddKeepEntity( "info_marine_hint" );
	m_MapResetFilter.AddKeepEntity( "info_node_marine_hint" );
	m_MapResetFilter.AddKeepEntity( "infodecal" );

	// riflemod: keep health regen entity all the time
	m_MapResetFilter.AddKeepEntity( "asw_health_regen" );

Counter-Strike: Global Offensive Counter-Strike: Global Offensive

cstrike15/cs_gamerules.cpp
static const char *s_PreserveEnts[] =
{
	"ai_network",
	"ai_hint",
	"cs_gamerules",
	"cs_team_manager",
	"cs_player_manager",
	"env_soundscape",
	"env_soundscape_proxy",
	"env_soundscape_triggerable",
	"env_sun",
	"env_wind",
	"env_fog_controller",
	"env_tonemap_controller",
	"env_cascade_light",
	"func_brush",
	"func_wall",
	"func_buyzone",
	"func_illusionary",
	"func_hostage_rescue",
	"func_bomb_target",
	"infodecal",
	"info_projecteddecal",
	"info_node",
	"info_target",
	"info_node_hint",
	"info_player_counterterrorist",
	"info_player_terrorist",
	"info_enemy_terrorist_spawn",
	"info_deathmatch_spawn",
	"info_armsrace_counterterrorist",
	"info_armsrace_terrorist",
	"info_map_parameters",
	"keyframe_rope",
	"move_rope",
	"info_ladder",
	"player",
	"point_viewcontrol",
	"point_viewcontrol_multiplayer",
	"scene_manager",
	"shadow_control",
	"sky_camera",
	"soundent",
	"trigger_soundscape",
	"viewmodel",
	"predicted_viewmodel",
	"worldspawn",
	"point_devshot_camera",
	"logic_choreographed_scene",
	"cfe_player_decal",
	"info_bomb_target_hint_A",
	"info_bomb_target_hint_B",
	"info_hostage_rescue_zone_hint",
	"generic_actor",
	"vote_controller",
	"wearable_item",
	"point_hiding_spot",
	"game_coopmission_manager",
	"chicken",
	"", // END Marker
};

Counter-Strike: Source Counter-Strike: Source

cstrike/cs_gamerules.cpp
static const char *s_PreserveEnts[] =
{
	"ai_network",
	"ai_hint",
	"cs_gamerules",
	"cs_team_manager",
	"cs_player_manager",
	"env_soundscape",
	"env_soundscape_proxy",
	"env_soundscape_triggerable",
	"env_sun",
	"env_wind",
	"env_fog_controller",
	"func_brush",
	"func_wall",
	"func_buyzone",
	"func_illusionary",
	"func_hostage_rescue",
	"func_bomb_target",
	"infodecal",
	"info_projecteddecal",
	"info_node",
	"info_target",
	"info_node_hint",
	"info_player_counterterrorist",
	"info_player_terrorist",
	"info_map_parameters",
	"keyframe_rope",
	"move_rope",
	"info_ladder",
	"player",
	"point_viewcontrol",
	"scene_manager",
	"shadow_control",
	"sky_camera",
	"soundent",
	"trigger_soundscape",
	"viewmodel",
	"predicted_viewmodel",
	"worldspawn",
	"point_devshot_camera",
	"", // END Marker
};

Day of Defeat: Source Day of Defeat: Source

dod/dod_gamerules.cpp
static const char *s_PreserveEnts[] =
{
	"player",
	"viewmodel",
	"worldspawn",
	"soundent",
	"ai_network",
	"ai_hint",
	"dod_gamerules",
	"dod_team_manager",
	"dod_player_manager",
	"dod_objective_resource",
	"env_soundscape",
	"env_soundscape_proxy",
	"env_soundscape_triggerable",
	"env_sprite",
	"env_sun",
	"env_wind",
	"env_fog_controller",
	"func_brush",
	"func_wall",
	"func_illusionary",
	"info_node",
	"info_target",
	"info_node_hint",
	"info_player_allies",
	"info_player_axis",
	"point_viewcontrol",
	"shadow_control",
	"sky_camera",
	"scene_manager",
	"trigger_soundscape",
	"info_dod_detect",
	"dod_team_allies",
	"dod_team_axis",
	"point_commentary_node",
	"dod_round_timer",
	"func_precipitation",
	"func_team_wall",
	"", // END Marker
};

Half-Life 2: Deathmatch Half-Life 2: Deathmatch

hl2mp/hl2mp_gamerules.cpp
static const char *s_PreserveEnts[] =
{
	"ai_network",
	"ai_hint",
	"hl2mp_gamerules",
	"team_manager",
	"player_manager",
	"env_soundscape",
	"env_soundscape_proxy",
	"env_soundscape_triggerable",
	"env_sun",
	"env_wind",
	"env_fog_controller",
	"func_brush",
	"func_wall",
	"func_buyzone",
	"func_illusionary",
	"infodecal",
	"info_projecteddecal",
	"info_node",
	"info_target",
	"info_node_hint",
	"info_player_deathmatch",
	"info_player_combine",
	"info_player_rebel",
	"info_map_parameters",
	"keyframe_rope",
	"move_rope",
	"info_ladder",
	"player",
	"point_viewcontrol",
	"scene_manager",
	"shadow_control",
	"sky_camera",
	"soundent",
	"trigger_soundscape",
	"viewmodel",
	"predicted_viewmodel",
	"worldspawn",
	"point_devshot_camera",
	"", // END Marker
};

Portal 2 Portal 2

portal/portal_mp_gamerules.cpp
static const char *s_PreserveEnts[] =
{
	"ai_network",
		"ai_hint",
		"hl2mp_gamerules",
		"team_manager",
		"player_manager",
		"env_soundscape",
		"env_soundscape_proxy",
		"env_soundscape_triggerable",
		"env_sun",
		"env_wind",
		"env_fog_controller",
		"func_brush",
		"func_wall",
		"func_buyzone",
		"func_illusionary",
		"infodecal",
		"info_projecteddecal",
		"info_node",
		"info_target",
		"info_node_hint",
		"info_player_deathmatch",
		"info_player_combine",
		"info_player_rebel",
		"info_map_parameters",
		"keyframe_rope",
		"move_rope",
		"info_ladder",
		"player",
		"point_viewcontrol",
		"scene_manager",
		"shadow_control",
		"sky_camera",
		"soundent",
		"trigger_soundscape",
		"viewmodel",
		"predicted_viewmodel",
		"worldspawn",
		"point_devshot_camera",
		"", // END Marker
};

Team Fortress 2 Team Fortress 2

teamplayroundbased_gamerules.cpp
// Classnames of entities that are preserved across round restarts
static const char *s_PreserveEnts[] =
{
	"player",
	"viewmodel",
	"worldspawn",
	"soundent",
	"ai_network",
	"ai_hint",
	"env_soundscape",
	"env_soundscape_proxy",
	"env_soundscape_triggerable",
	"env_sprite",
	"env_sun",
	"env_wind",
	"env_fog_controller",
	"func_wall",
	"func_illusionary",
	"info_node",
	"info_target",
	"info_node_hint",
	"point_commentary_node",
	"point_viewcontrol",
	"func_precipitation",
	"func_team_wall",
	"shadow_control",
	"sky_camera",
	"scene_manager",
	"trigger_soundscape",
	"commentary_auto",
	"point_commentary_node",
	"point_commentary_viewpoint",
	"bot_roster",
	"info_populator",
	"", // END Marker
};
tf/tf_gamerules.cpp
// Classnames of entities that are preserved across round restarts
static const char *s_PreserveEnts[] =
{
	"tf_gamerules",
	"tf_team_manager",
	"tf_player_manager",
	"tf_team",
	"tf_objective_resource",
	"keyframe_rope",
	"move_rope",
	"tf_viewmodel",
	"tf_logic_training",
	"tf_logic_training_mode",
	"tf_powerup_bottle",
	"tf_mann_vs_machine_stats",
	"tf_wearable",
	"tf_wearable_demoshield",
	"tf_wearable_robot_arm",
	"tf_wearable_vm",
	"tf_logic_bonusround",
	"vote_controller",
	"monster_resource",
	"tf_logic_medieval",
	"tf_logic_cp_timer",
	"tf_logic_tower_defense",	// legacy
	"tf_logic_mann_vs_machine",
	"func_upgradestation",
	"entity_rocket",
	"entity_carrier",
	"entity_sign",
	"entity_saucer",
	"tf_halloween_gift_pickup",
	"tf_logic_competitive",
	"tf_wearable_razorback",
	"entity_soldier_statue",
	"", // END Marker
};

Code Dumps

To find the S_PreserveEnts whitelist in the Left 4 Dead games in IDA:

  1. Search for the ai_network string reference.
  2. Bring up all applicable XREFs.
  3. Search for the list that includes survivor_bot and logic_versus_random.

Left 4 Dead Left 4 Dead

; "ai_network",
; "ai_hint",
; "cs_team_manager",
; "terror_gamerules",
; "terror_player_manager",
; "survivor_bot",
; "env_tonemap_controller",
; "env_tonemap_controller_infected",
; "env_tonemap_controller_ghost",
; "vote_controller",
; "env_soundscape",
; "env_soundscape_proxy",
; "env_soundscape_triggerable",
; "env_sun",
; "env_wind",
; "env_fog_controller",
; "func_wall",
; "func_buyzone",
; "func_illusionary",
; "func_hostage_rescue",
; "func_bomb_target",
; "infodecal",
; "info_projecteddecal",
; "info_node",
; "info_target",
; "info_node_hint",
; "info_player_counterterrorist",
; "info_player_terrorist",
; "info_map_parameters",
; "info_map_parameters_versus",
; "info_ladder",
; "func_simpleladder",
; "player",
; "point_viewcontrol",
; "scene_manager",
; "shadow_control",
; "sky_camera",
; "soundent",
; "trigger_soundscape",
; "viewmodel",
; "predicted_viewmodel",
; "worldspawn",
; "point_devshot_camera",
; "info_survivor_position",
; "logic_versus_random",

Left 4 Dead 2 Left 4 Dead 2

; "ai_network",
; "ai_hint",
; "cs_team_manager",
; "terror_gamerules",
; "terror_player_manager",
; "survivor_bot",
; "env_tonemap_controller",
; "env_tonemap_controller_infected",
; "env_tonemap_controller_ghost",
; "vote_controller",
; "env_soundscape",
; "env_soundscape_proxy",
; "env_soundscape_triggerable",
; "env_sun",
; "env_wind",
; "env_fog_controller",
; "func_wall",
; "infodecal",
; "info_projecteddecal",
; "info_node",
; "info_node_hint",
; "info_map_parameters",
; "info_map_parameters_versus",
; "info_ladder",
; "func_simpleladder",
; "player",
; "point_viewcontrol",
; "scene_manager",
; "shadow_control",
; "sky_camera",
; "soundent",
; "trigger_soundscape",
; "viewmodel",
; "predicted_viewmodel",
; "worldspawn",
; "point_devshot_camera",
; "weapon_scavenge_item_spawn",
; "logic_versus_random",