This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
| tutorial:intro-to-elden-ring-emevd [2025/02/25 15:20] – created admin | tutorial:intro-to-elden-ring-emevd [2025/02/27 00:33] (current) – [Model names] admin | ||
|---|---|---|---|
| Line 26: | Line 26: | ||
| * Use DSMapStudio ([[https:// | * Use DSMapStudio ([[https:// | ||
| * Use WitchyBND ([[https:// | * Use WitchyBND ([[https:// | ||
| - | * Use various [[er-reference:main | Elden Ring reference pages]], also listed below under "entry points" | + | * Use various [[er-refmat:main| Elden Ring reference pages]], also listed below under "entry points" |
| Of course, also use an event script editor. These are available for Elden Ring: | Of course, also use an event script editor. These are available for Elden Ring: | ||
| Line 65: | Line 65: | ||
| Don't forget! If something isn't happening in the game when you expect it, make sure your changes are even recognized by the game in the first place. This is best accomplished by simple "is it on" checks which do something conspicuous. For instance, in DarkScript3: | Don't forget! If something isn't happening in the game when you expect it, make sure your changes are even recognized by the game in the first place. This is best accomplished by simple "is it on" checks which do something conspicuous. For instance, in DarkScript3: | ||
| - | < | + | < |
| DisplayBanner(TextBannerType.DutyFulfilled); | DisplayBanner(TextBannerType.DutyFulfilled); | ||
| </ | </ | ||
| - | < | + | < |
| AwardItemLot(997200); | AwardItemLot(997200); | ||
| </ | </ | ||
| Line 90: | Line 90: | ||
| Let's start with some shorter events in the game, before getting into longer ones which pull together a ton of game systems. An event script defines many events which run while the script is loaded. You can think of these like functions in a programming language, each identified by a unique number. An event must be initialized to have any effect in the game at all. All events run in parallel, executing one instruction after the next from top to bottom, sometimes skipping optional instructions or stopping altogether until some condition is met. | Let's start with some shorter events in the game, before getting into longer ones which pull together a ton of game systems. An event script defines many events which run while the script is loaded. You can think of these like functions in a programming language, each identified by a unique number. An event must be initialized to have any effect in the game at all. All events run in parallel, executing one instruction after the next from top to bottom, sometimes skipping optional instructions or stopping altogether until some condition is met. | ||
| - | For how loading works, that's a bit complicated. See the [[[er-refmat: | + | For how loading works, that's a bit complicated. See the [[er-refmat: |
| How this works in the event script itself is that there are special events called constructors which get automatically initialized when an event script is loaded. These are events with low ids like 0 and 50. As you can see, these constructor events are responsible for initializing every other event in the file, and a few others too. | How this works in the event script itself is that there are special events called constructors which get automatically initialized when an event script is loaded. These are events with low ids like 0 and 50. As you can see, these constructor events are responsible for initializing every other event in the file, and a few others too. | ||
| Line 96: | Line 96: | ||
| For instance, take a look at m14_00_00_00.emevd.dcx, | For instance, take a look at m14_00_00_00.emevd.dcx, | ||
| - | < | + | < |
| $Event(0, Default, function() { | $Event(0, Default, function() { | ||
| RegisterBonfire(14000002, | RegisterBonfire(14000002, | ||
| Line 113: | Line 113: | ||
| You can Ctrl+Click on 14002080 in the above event (within DarkScript3) to see the event' | You can Ctrl+Click on 14002080 in the above event (within DarkScript3) to see the event' | ||
| - | < | + | < |
| $Event(14002080, | $Event(14002080, | ||
| EndIf(!PlayerIsInOwnWorld()); | EndIf(!PlayerIsInOwnWorld()); | ||
| Line 138: | Line 138: | ||
| Here is another event in Stormveil Castle (m10_00_00_00) which has two waits in it. It includes a RestartEvent, | Here is another event in Stormveil Castle (m10_00_00_00) which has two waits in it. It includes a RestartEvent, | ||
| - | < | + | < |
| $Event(10002460, | $Event(10002460, | ||
| WaitFor(TimeOfDayInRange(19, | WaitFor(TimeOfDayInRange(19, | ||
| Line 158: | Line 158: | ||
| The key thing to note here is '' | The key thing to note here is '' | ||
| - | < | + | < |
| $Event(18002860, | $Event(18002860, | ||
| if (EventFlag(18000850)) { | if (EventFlag(18000850)) { | ||
| Line 197: | Line 197: | ||
| We'll get to the second case when we talk about parameters, but a quick example of the first use case is as follows. This event kills the player if they' | We'll get to the second case when we talk about parameters, but a quick example of the first use case is as follows. This event kills the player if they' | ||
| - | < | + | < |
| $Event(xxxxxxxx, | $Event(xxxxxxxx, | ||
| WaitFor(PlayerHasArmorEquipped(ArmorType.Legs, | WaitFor(PlayerHasArmorEquipped(ArmorType.Legs, | ||
| Line 219: | Line 219: | ||
| Make sure you have DSMapStudio and DarkScript3 open while browsing these scripts. Open the m13_00_00_00 map in DSMapStudio to find entities mentioned below using " | Make sure you have DSMapStudio and DarkScript3 open while browsing these scripts. Open the m13_00_00_00 map in DSMapStudio to find entities mentioned below using " | ||
| - | Because these events are on the longer side, I've added commentary inside of the events themselves, using JavaScript comment lines (with '' | + | Because these events are on the longer side, I've added commentary inside of the events themselves, using JavaScript comment lines (with \/\/). You can check out events without comments first if you want, but **make sure to open up the version with comments** to see a line-by-line explanation. |
| **Event 13002860: Start Godskin Duo** | **Event 13002860: Start Godskin Duo** | ||
| Line 226: | Line 226: | ||
| This fight actually involves three enemies, with these entity ids. Try locating them with DSMapStudio Property Search. | This fight actually involves three enemies, with these entity ids. Try locating them with DSMapStudio Property Search. | ||
| - | * 13000850: The hidden healthbar enemy, lurking beneath the floor. This is technically a Godskin Apostle, but the only thing that matters is that it has a lot of HP. See the Four Kings video! | + | |
| - | * 13000851: The Godskin Apostle you fight | + | * 13000851: The Godskin Apostle you fight |
| - | * 13000852: The Godskin Noble you fight | + | * 13000852: The Godskin Noble you fight |
| After this event finishes, the entire rest of the fight is just fighting the godskins as if they were normal enemies (aside from the regeneration mechanic, which is handled by other events). They choose attacks based on their AI script, which is specified in their NpcThinkParam. | After this event finishes, the entire rest of the fight is just fighting the godskins as if they were normal enemies (aside from the regeneration mechanic, which is handled by other events). They choose attacks based on their AI script, which is specified in their NpcThinkParam. | ||
| - | < | + | < |
| - | < | + | < |
| $Event(13002860, | $Event(13002860, | ||
| if (EventFlag(13000850)) { | if (EventFlag(13000850)) { | ||
| Line 289: | Line 289: | ||
| </ | </ | ||
| - | < | + | < |
| - | < | + | < |
| $Event(13002860, | $Event(13002860, | ||
| // This first block is executed only when the boss defeat flag is set. Otherwise, skip it. | // This first block is executed only when the boss defeat flag is set. Otherwise, skip it. | ||
| Line 426: | Line 426: | ||
| The defeat event also follows a very regular structure for all Elden Ring bosses with fixed boss arenas. The most important thing this event does is turn the boss defeat flag 13000850 on, but it's responsible for many other rewards and effects as well. | The defeat event also follows a very regular structure for all Elden Ring bosses with fixed boss arenas. The most important thing this event does is turn the boss defeat flag 13000850 on, but it's responsible for many other rewards and effects as well. | ||
| - | < | + | < |
| - | < | + | < |
| $Event(13002850, | $Event(13002850, | ||
| EndIf(EventFlag(13000850)); | EndIf(EventFlag(13000850)); | ||
| Line 447: | Line 447: | ||
| </ | </ | ||
| - | < | + | < |
| - | < | + | < |
| $Event(13002850, | $Event(13002850, | ||
| // If they' | // If they' | ||
| Line 500: | Line 500: | ||
| Not every boss has an event like this, but this approach is used in any boss where there is some condition for the soundtrack to "heat up". | Not every boss has an event like this, but this approach is used in any boss where there is some condition for the soundtrack to "heat up". | ||
| - | < | + | <hidden onHidden=" |
| + | < | ||
| $Event(13002861, | $Event(13002861, | ||
| EndIf(EventFlag(13000850)); | EndIf(EventFlag(13000850)); | ||
| Line 507: | Line 508: | ||
| }); | }); | ||
| </ | </ | ||
| + | </ | ||
| - | < | + | <hidden onHidden=" |
| + | < | ||
| $Event(13002861, | $Event(13002861, | ||
| // As usual, ignore the rest if the boss is already defeated. | // As usual, ignore the rest if the boss is already defeated. | ||
| Line 523: | Line 526: | ||
| }); | }); | ||
| </ | </ | ||
| + | </ | ||
| **Event 13002890: Godskin summoning after one dies** | **Event 13002890: Godskin summoning after one dies** | ||
| Line 532: | Line 536: | ||
| The next event starts out like this: | The next event starts out like this: | ||
| - | < | + | < |
| $Event(13002890, | $Event(13002890, | ||
| ... | ... | ||
| Line 540: | Line 544: | ||
| Note the extra X0_4, X4_4, and so on. Remember that all events must be initialized in order to be active. In this case, there is extra data passed in during initialization! If you Ctrl+Click on the event id here, you can hop to the initializations, | Note the extra X0_4, X4_4, and so on. Remember that all events must be initialized in order to be active. In this case, there is extra data passed in during initialization! If you Ctrl+Click on the event id here, you can hop to the initializations, | ||
| - | < | + | < |
| InitializeEvent(0, | InitializeEvent(0, | ||
| InitializeEvent(1, | InitializeEvent(1, | ||
| Line 549: | Line 553: | ||
| In this event, when one of the godskins is dead for 20 seconds, prompt the other one to resurrect them. If it helps, you can think of specific values (like X4_4 being 13000851 and X8_4 being 13000852) as you read through the script. Note that the meaning of X4_4 can change completely from one event to another; the name is only based on the index of the parameter and doesn' | In this event, when one of the godskins is dead for 20 seconds, prompt the other one to resurrect them. If it helps, you can think of specific values (like X4_4 being 13000851 and X8_4 being 13000852) as you read through the script. Note that the meaning of X4_4 can change completely from one event to another; the name is only based on the index of the parameter and doesn' | ||
| - | < | + | < |
| - | < | + | < |
| $Event(13002890, | $Event(13002890, | ||
| EndIf(!PlayerIsInOwnWorld()); | EndIf(!PlayerIsInOwnWorld()); | ||
| Line 568: | Line 572: | ||
| </ | </ | ||
| - | < | + | < |
| - | < | + | < |
| // X0_4: The event flag to set indicating that X4_4 should be respawned | // X0_4: The event flag to set indicating that X4_4 should be respawned | ||
| // X4_4: Entity id of the godskin to respawn | // X4_4: Entity id of the godskin to respawn | ||
| Line 617: | Line 621: | ||
| It respawns a godskin when it has been requested by the other alive godskin. | It respawns a godskin when it has been requested by the other alive godskin. | ||
| - | < | + | < |
| InitializeEvent(0, | InitializeEvent(0, | ||
| InitializeEvent(1, | InitializeEvent(1, | ||
| </ | </ | ||
| - | < | + | < |
| - | < | + | < |
| $Event(13002891, | $Event(13002891, | ||
| EndIf(!PlayerIsInOwnWorld()); | EndIf(!PlayerIsInOwnWorld()); | ||
| Line 641: | Line 644: | ||
| </ | </ | ||
| - | < | + | < |
| - | < | + | < |
| // X0_4: The event flag to check indicating that X4_4 should be respawned | // X0_4: The event flag to check indicating that X4_4 should be respawned | ||
| // X4_4: Generator id (not entity id!) of the godskin to respawn | // X4_4: Generator id (not entity id!) of the godskin to respawn | ||
| Line 698: | Line 701: | ||
| When both godskins are dead, this event randomly picks one of them to respawn without an explicit summon. The randomly respawned godskin will then try to respawn their buddy using the above events. | When both godskins are dead, this event randomly picks one of them to respawn without an explicit summon. The randomly respawned godskin will then try to respawn their buddy using the above events. | ||
| - | < | + | < |
| - | < | + | < |
| $Event(13002892, | $Event(13002892, | ||
| EndIf(!PlayerIsInOwnWorld()); | EndIf(!PlayerIsInOwnWorld()); | ||
| Line 730: | Line 733: | ||
| </ | </ | ||
| - | < | + | < |
| - | < | + | < |
| $Event(13002892, | $Event(13002892, | ||
| // Similar checks for host-only and for avoiding respawn after boss defeat. | // Similar checks for host-only and for avoiding respawn after boss defeat. | ||
| Line 798: | Line 801: | ||
| This event allows a host player to traverse a boss fog gate, and sets a flag once they do. Summoned players use a separate event 9005801 to traverse the fog gate after the host does, meaning when flag X12_4 here is set. They also run this event, but it has no effect for them. | This event allows a host player to traverse a boss fog gate, and sets a flag once they do. Summoned players use a separate event 9005801 to traverse the fog gate after the host does, meaning when flag X12_4 here is set. They also run this event, but it has no effect for them. | ||
| - | < | + | < |
| InitializeCommonEvent(0, | InitializeCommonEvent(0, | ||
| InitializeCommonEvent(0, | InitializeCommonEvent(0, | ||
| Line 804: | Line 807: | ||
| </ | </ | ||
| - | < | + | < |
| - | < | + | < |
| $Event(9005800, | $Event(9005800, | ||
| if (!EventFlag(X0_4)) { | if (!EventFlag(X0_4)) { | ||
| Line 867: | Line 870: | ||
| </ | </ | ||
| - | < | + | < |
| - | < | + | < |
| // X0_4: Boss defeat event flag | // X0_4: Boss defeat event flag | ||
| // X4_4: Entity id for the fog gate asset | // X4_4: Entity id for the fog gate asset | ||
| Line 1019: | Line 1022: | ||
| So the above event allows you pass through a solid wall using RotateCharacter, | So the above event allows you pass through a solid wall using RotateCharacter, | ||
| - | < | + | < |
| InitializeCommonEvent(0, | InitializeCommonEvent(0, | ||
| InitializeCommonEvent(0, | InitializeCommonEvent(0, | ||
| Line 1029: | Line 1032: | ||
| This event controls when the fog gate shows up and disappears using the ChangeAssetEnableState and CreateObjectfollowingSFX commands. I won't explain the details of the event here, as it behaves in a bunch of different complicated ways depending on whether you're a host, a summon, or the invader. Still, the arguments are as follows: | This event controls when the fog gate shows up and disappears using the ChangeAssetEnableState and CreateObjectfollowingSFX commands. I won't explain the details of the event here, as it behaves in a bunch of different complicated ways depending on whether you're a host, a summon, or the invader. Still, the arguments are as follows: | ||
| - | < | + | < |
| // X0_4: The boss defeat flag. When this is on, the fog gate does not show up. | // X0_4: The boss defeat flag. When this is on, the fog gate does not show up. | ||
| // X4_4: Entity id for the fog gate asset | // X4_4: Entity id for the fog gate asset | ||
| Line 1052: | Line 1055: | ||
| Here is an example initialization in m14_00_00_00 (Raya Lucaria), which applies to the scholar in the middle of the Cuckoo Church: | Here is an example initialization in m14_00_00_00 (Raya Lucaria), which applies to the scholar in the middle of the Cuckoo Church: | ||
| - | < | + | < |
| InitializeCommonEvent(0, | InitializeCommonEvent(0, | ||
| </ | </ | ||
| Here is another initialization in m30_04_00_00 (Murkwater Catacombs), which applies to an imp waiting to drop down from the ceiling when you approach: | Here is another initialization in m30_04_00_00 (Murkwater Catacombs), which applies to an imp waiting to drop down from the ceiling when you approach: | ||
| - | < | + | < |
| InitializeCommonEvent(0, | InitializeCommonEvent(0, | ||
| </ | </ | ||
| Line 1063: | Line 1066: | ||
| In total, event 90005200 has nearly 600 total initializations across all maps in the game. It puts an enemy in standby and does a wakeup animation when the player enters a region. You can use ForceAnimationPlayback (or a Cheat Engine table with animation playback) to see these animations in-game. | In total, event 90005200 has nearly 600 total initializations across all maps in the game. It puts an enemy in standby and does a wakeup animation when the player enters a region. You can use ForceAnimationPlayback (or a Cheat Engine table with animation playback) to see these animations in-game. | ||
| - | < | + | < |
| - | < | + | < |
| $Event(90005200, | $Event(90005200, | ||
| EndIf(SpecialStandbyEndedFlag(X0_4)); | EndIf(SpecialStandbyEndedFlag(X0_4)); | ||
| Line 1151: | Line 1154: | ||
| </ | </ | ||
| - | < | + | < |
| - | < | + | < |
| // X0_4: Entity id of the enemy | // X0_4: Entity id of the enemy | ||
| // X4_4: Animation id which loops while it's waiting for the trigger | // X4_4: Animation id which loops while it's waiting for the trigger | ||
| Line 1321: | Line 1324: | ||
| ==== Map ids ==== | ==== Map ids ==== | ||
| * Where it's located: Maps are how most of the game world is split up, so finding a map id is critical to being able to search for something in a particular MSB (in '' | * Where it's located: Maps are how most of the game world is split up, so finding a map id is critical to being able to search for something in a particular MSB (in '' | ||
| - | * How to browse it: Use [[er-refmat: | + | * How to browse it: Use [[er-refmat: |
| * How to use it: Open the files in a map/event editor! | * How to use it: Open the files in a map/event editor! | ||
| * Example: You want to view/edit something in Roundtable Hold. Find that it's m11_10_00_00 in the map list, and open those files in DarkScript3/ | * Example: You want to view/edit something in Roundtable Hold. Find that it's m11_10_00_00 in the map list, and open those files in DarkScript3/ | ||
| Line 1329: | Line 1332: | ||
| * How to browse it: Use [[https:// | * How to browse it: Use [[https:// | ||
| * How to use it: In addition to or instead of the above reference, you can also use the [[https:// | * How to use it: In addition to or instead of the above reference, you can also use the [[https:// | ||
| - | * Example: You want to find Radahn. Use above references to see that he's c4730, and that his full name is m60_52_38_00-c4730_9002, | + | * Example: You want to find Radahn. Use above references to see that he's c4730, and that his full name is m60_52_38_00-c4730_9002, |
| ==== Entity ids ==== | ==== Entity ids ==== | ||