Skip to main content

Optimizing Multiplayer Mods

See the Following Page Before Proceeding

Criteria

  • Have experience with level modding (modifying entities) & decl modding. If you know about encounter managers, volume triggers, invisible walls, relays, timelines, interactables - then you should be knowledgeable enough.
  • Use Assetsinfo to pull assets from a BATTLEMODE map (both the base folder and _patch1).

Initial Steps

  • Open an entities file.
  • Delete the idGameChallenge_CampaignSinglePlayer and copy+paste an idGameChallenge_PVP from any of the BATTLEMODE entities file. The difficultySettings can be applied here if you want players to change difficulties.
  • Delete ALL idProp2 entities. These are pickups. They are guaranteed crashes for clients. If your level has key cards, you will need to trigger a door opening entities for that colored key around the time you would normally obtain it. The easiest method is to simply activate an idTarget_InteractionAction entity at the end of an encounter with an activateTarget eventCall.

Alternatively, you may set networkReplication to false in the gameresources/generated/decls/entitydef/pickup/default.decl file, but only the host will see the pickups.

  • Delete ALL idPlayerStart entities since they prevent demon players from spawning. You will need to copy the spawn position entities from BATTLEMODE entities. You will need 1 idPlayerStart entity that inherits from player/start and another that inherits online/battle_arena/player_start for the Slayer.
  • Although not required, it is recommended to delete most if not all idInteractable entities. These are usually buttons or switches that the player can activate, but they also include Mod Bots, Rune Stations, & Praetor Suit Sentinel Ghosts. If an interactable opens a door, just add an activateTarget eventCall to activate an¬†idTarget_Timeline at the end of an encounter to open it.
  • Fade teleporters will crash the game for clients. Change all entity instances of:
    class = "idTrigger_Teleporter_Fade";
    to
    class = "idTrigger_Teleporter";

    inherit = "trigger/teleport_fade";
    to
    inherit = "trigger/teleporter";
  • Since checkpoints don't exist, it is recommended to activate portals near the Slayer spawn position when they reach farther into the map. Use a simple activateTarget eventCall to activate an idTarget_Timeline to activate an idTarget_Count relay in an encounter to do so. The relay should contain the idEntityFx, the idTarget_Spawn for the teleporter, then the idTrigger_Teleporter.
  • To broadcast Music to clients, create an idMusicEntity for each ambient, light, heavy music state. Create an idTarget_Count relay that targets the music entity. Create an idTarget_Timeline that activates the relay at least after 500 eventTime. You may need to trigger this twice to work, add at least another 1000 eventTime that targets the same entity. When you want the music to play in an encounter, use an activateTarget eventCall to activate the timeline.
  • To broadcast SFX or VO to clients, create an idSoundEntity for when a sound plays. Use the same method for broadcasting Music in the previous step, but there is no need to add a second event in the timeline. This should be done when a Buff Totem spawns so the SFX notification is heard by clients.
  • Delete the spawnFXEntityDef value for the Pain Elemental idAI2 entity. These will occasionally flicker rapidly for clients.
  • Get another PC/Laptop that can at least run DOOM Eternal, it doesn't have to run well, but it has to run. Buy TAG1 or TAG2 on a separate Steam account. Use this device to verify that changes to the client works as intended. This is not a required step but it will make the process much faster and more importantly, less miserable.

CO-OP

Since vanilla BATTLEMODE supports 3 players, it is recommended to implement spawn positions for 3 different Slayers, even if a 2 player map is preferred.

  • You will need 3 idPlayerStart entities that inherits online/battle_arena/player_start for Slayers.
  • Client Slayers cannot activate¬†idInteractable entities, but they can trigger Gore Nests.
  • idDynamicEntity or idDestructible door entities should either have networkReplication enabled or deleted after they should open. If networkReplication is set to true, they the entity will have a noticeable spawn offset but function as intended. If the offset is too extreme, then disable networkReplication and use an idTarget_Timeline to activate an idTarget_Remove entity to remove the obstruction. In general, removing the door after 3 seconds will be subtle enough to not be noticeable.

BATTLEMODE or INVASION

  • Open a Campaign entities file (preferably from the Base Campaign since they contain leftover Invasion portals).
  • Use proteh's EternalTraversalInfoGenerator for the marauder_wolf so the playable Marauder's Wolf summon has proper traversal navigation for the entire level. Do the same for other AI that Demon players could summon. Do this for other AI that Demon Players may summon.
  • Add 2 spawn positions for Demon Players and additional respawn positions. TEAM_ONE is for the Slayer team, TEAM_TWO is for the demon team. Add respawnOnly = true; to the demon respawn entities. Find the idWorldspawn entity and add the pvpRespawnZ = ...; parameter. Set it to a negative value that is just below the world's geometry. This will allow players to respawn if they fall below a certain vertical distance.
  • DO NOT activate the Invasion layer. This may crash players. Instead, remove the "game/sp/invasion" layer for the demon jump pad and portal entities. Change all instances of:
    game/sp/demon_team
    to
    game/pvp/demon_team

    game/sp/slayer_team
    to
    game/pvp/slayer_team
  • Barricade or add teleporters to dead ends. Energy Barrier entities used in single player work fine. They are idProp_Coop CLIPMODEL_BOX entities that are completely solid so no player can pass through them. Make sure to scale them appropriately. For portals, add the idEntityFx (for both slayer_team & demon_team layers), a idTrigger_Teleporter, and a idInfo_TeleportDestination entity. You can specify if a player (Slayer) or demon player can activate (or both).
  • Applying the demonPlayersPassThrough = false; parameter within the edit field will prevent Demon Players from passing through the entity.
  • Moving invisible wall func_dynamic entities to the slayer_team will help Demon Players navigate to certain locations since they cannot activate triggers as clients.

Dread Knight

By default, the playable Dread Knight character would not load outside of BATTLEMODE maps because its assets only exist in those maps.

  • To get the playable Dread Knight working in single player maps, copy all of its visual components into the highest resource patch for the level that you are modifying. Check resource priority here
  • The following decls must be copied over (they do not need to be added to Assetsinfo). They can be found in an _patch1 resources for BATTLEMODE maps.
aimassist\aimassist\playable_dreadknight.decl
ammo\ammo\demonplayer\pvp\dreadknight\energy_wave.decl
ammo\ammo\demonplayer\pvp\dreadknight\energy_wave_charged.decl
animweb\animweb\characters\monsters\playable\dreadknight.decl
animweb\animweb\characters\monsters\playable\dreadknight_hands.decl
animweb\animweb\characters\monsters\playable\dreadknight_hands_bob_cycle.decl
animweb\animweb\characters\monsters\playable\dreadknight_hands_hit_reactions
animweb\animweb\characters\monsters\playable\dreadknight_tp_body.decl
articulatedfigure\characters\monsters\dreadknight_cstorsorighttoleft.decl
entitydef\fx\pvp\dreadknight_ground_slam_feint_smoke.decl
entitydef\player\playable_dreadknight\dreadknight_ground_slam_feint_smoke_highlight_volume.decl
entitydef\player\playable_dreadknight\energy_wave_launcher.decl
entitydef\player\demonplayer_dreadknight_tp_body.decl
entitydef\projectile_ent\demonplayer\pvp\dreadknight\energy_wave.decl
entitydef\projectile_ent\demonplayer\pvp\dreadknight\energy_wave_charged.decl
entitydef\projectile_ent\demonplayer\pvp\dreadknight\ground_pound_explosion.decl
entitydef\projectile_ent\demonplayer\pvp\dreadknight\quantum_orb.decl
entitydef\projectile_ent\demonplayer\pvp\dreadknight\quantum_tele.decl
fx\demon_player\dreadknight\dreadknight.decl
fx\demon_player\dreadknight\dreadknight_hands.decl
fx\demon_player\dreadknight\ground_slam_explosion.decl
fx\demon_player\dreadknight\quantum_orb.decl
gorecontainer\demonplayer\dreadknight.decl
handsbobcycle\demon\dreadknight.decl
impacteffect\impacteffect\footsteps\playable_dreadknight.decl
impacteffect\impacteffect\footsteps\playable_dreadknight_friendly.decl
impacteffect\impacteffect\footsteps\playable_dreadknight_landing.decl
impacteffect\impacteffect\projectiles\demon_player\dreadknight.decl
material2\models\monsters\dreadknight_1p\dreadknight_arm_1p.decl
material2\models\monsters\dreadknight_1p\dreadknight_arm_1p.decl
material2\models\monsters\dreadknight_1p\dreadknight_blade_1p.decl
material2\models\monsters\dreadknight_1p\dreadknight_hoses_1p.decl
md6def\md6def\player\monsters\dreadknight_1p\base\dreadknight_1p.md6.decl
particle\character_mp\dreadknight\berserk_body.decl
particle\character_mp\dreadknight\berserk_mouth.decl
particle\character_mp\dreadknight\quantum_orb.decl
particle\character_mp\dreadknight\teleport.decl
playerprops\demon\dreadknight.decl
projectile\projectile\demonplayer\pvp\dreadknight\energy_wave.decl
projectile\projectile\demonplayer\pvp\dreadknight\energy_wave_charged.decl
projectile\projectile\demonplayer\pvp\dreadknight\ground_pound_explosion.decl
projectile\projectile\demonplayer\pvp\dreadknight\quantum_orb.decl
projectile\projectile\demonplayer\pvp\dreadknight\quantum_tele.decl
projectile\projectile\demonplayer\pvp\mancubus\dreadknight_enshroud.decl
ribbon2\demon_player\dreadknight_quantum_projectile.decl
statuseffect\statuseffect\pvp\demon_action\dreadknight_berserk_cooldown_info.decl
statuseffect\statuseffect\pvp\toughened_berserk.decl
targeting\player\demon_dreadknight.decl
weapon\weapon\demonplayer\pvp\dreadknight\energy_wave.decl
weapon\weapon\demonplayer\pvp\dreadknight\energy_wave_charged.decl
weaponreticle\weaponreticle\dreadknight.decl
  • The following md6 files must be copied over as well (copy EVERY content in the sub-directories).
md6\characters\monsters\dreadknight_mp\base\motion\combat\...
md6\characters\monsters\dreadknight_mp\base\motion\mechanics\ledgegrab\...
md6\player\monsters\dreadknight_1p\base\assets\mesh\...
md6\player\monsters\dreadknight_1p\base\motion\core\additive\...
md6\player\monsters\dreadknight_1p\base\motion\core\...
md6\player\monsters\dreadknight_1p\base\motion\mechanics\...
md6\player\monsters\dreadknight_1p\base\motion\reactions\hit\base\additive\...

Not all resources may need to be copied. However, a user's machine may not properly load assetsInfo so it is safer to copy everything over.

See Also