Introduction

Welcome to Evanlyn's Emporium of Mapping Mini-Tutorials, or: How To Do Some Really Specific Stuff In Elden Ring.

The following tutorials are meant as a basic guide to creating some basic, reusable features of Elden Ring maps, and is being updated as I learn more. These are by no means exhaustive, and there's no guarantee they're the most efficient or bug-free way of going about things. Use them as a quick reference to gain some basic knowledge, and adjust as needed. Your results may vary.

Special thanks to George/Kingbore and thefifthmatt for significant amounts of help!

Prerequisites:

  • DS Map Studio, and basic usage knowledge
  • DarkScript 3, and basic usage knowledge
  • Yabber (w/ unpacked Elden Ring folder)
  • Patience.

Notes: Be sure to take notes of all the relevant names and IDs as you go. Make lots of backups. Be careful not to use any duplicate flags or Entity IDs; regions with duplicate EntityIDs in particular have a chance to permanently corrupt loaded mapbnds, so exercise caution. Be careful when making Flag IDs; if the fifth digit is 1-9, it will cause the flag to reset on grace/area reload (Eg: XXXX0XXX). Refer to other Entity or Flag IDs to see how FromSoft formatted them; sometimes it might matter, or not. If you're curious about most entities having MapID: -1, UnkE0C: 255, and UnkS0C: -1, don't ask me. I have no idea, but changing it can break things. So just keep them that way.


How To Make Ladders

1. Create a new ladder asset, and give it a unique EntityID.
2. In the map EMEVD file, add a new RegisterLadder event.

$Event(eventID, Default, function() {
    RegisterLadder(disableTopEventFlagId, disableBottomEventFlagId, entityId)
});

FlagIDs should be eight-digit unused values, fifth digit 0

3. Initialize the new event by adding a line to Event(0, at the top of the page.

    InitializeEvent(0, eventID, 0);

4. Done. It's that easy.


How To Make Treasure Chests

1. Create a new treasure chest asset (a common one is AEG099_630). Give it the following values:

  • Name: Unique Name
  • Unk08: 9000
  • EntityID: Unique EntityID

2. Create a new ObjAct. Give it the following values:

  • EventID: Unique, One-To-Three Digit Value
  • EntityID: 0
  • MapID: -1
  • UnkE0C: 255
  • UnkS0C: -1
  • Name: Unique Name
  • ObjActEntityID: 0
  • ObjActPartName: Chest Asset Name
  • StateType: 5
  • EventFlagID: Unique Eight-Digit Value (Fifth digit not 1)

3. Create a new Treasure event. Give it the following values:

  • EventID: Unique, One-To-Three Digit Value
  • EntityID: 0
  • MapID: -1
  • UnkE0C: 255
  • UnkS0C: -1
  • Name: Unique Name
  • TreasurePartName: Chest Asset Name
  • ItemLotID: New ItemLotParam_map entry
  • InChest: 1

4. In a Param Editor, open ItemLotParam_map. Find an entry for the map you're working in, or a similar suitable entry. Duplicate it, and change the value to the same number used in the above ItemLotID.
5. In the new ItemLotParam entry, set lotItemID01 to the item you want in the chest.

  • Note: Check EquipParams for every item's ID

6. Set lotItemCategory01 to match the lotItem (Which EquipParam menu it's from)
7. Set getItemFlagId to a unique value (Fifth digit not 1)
8. Congrats.


How To Make Elevators

Strap in. This one's a doozy.

1. Create one new elevator asset (eg: AEG027_016) and two new lever assets (eg: AEG027_002). Give them each unique EntityIDs.
2. Create two new ObjActs (one ObjAct for each lever), and give them each the following values:

  • ObjActEntityID: Unique EntityID
  • ObjActPartName: Name Of The Related Lever
  • ObjActID: ObjActParam Value (Eg: 227050 for upper lever, 27115 for lower lever)
  • EventFlagID: 0
  • EventID: 0 for upper lever, 2 for lower lever
  • EntityID: 0
  • MapID: -1
  • UnkE0C: 255
  • UnkS0C: -1

3. Create two new Other, Box regions. They'll activate the pressure plates. Place each one where the elevator's pressure plates would be when at the top and bottom. Give them each unique EntityIDs, and the following values:

  • UnkE08: 255
  • MapID: -1
  • UnkS0C: -1

4. Create a new event in the map's EMEVD. This will initialize the main common event (90005500).

$Event(NewEventID1, Default, function() {
    InitializeCommonEvent(0, 90005500, EventFlag1, EventFlag2, Label, ElevatorID, UpperLeverID, ObjActUpperLeverID, LowerLeverID, ObjActLowerLeverID, UpperSwitchRegionID, LowerSwitchRegionID, EventFlag3, EventFlag4, 0);

Notes: NewEventID1 should have 5th digit 2
EventFlag1 should have 5th digit 0
EventFlag2 should have 5th digit 1, and may be the same as the ElevatorID
EventFlag3 should have 5th digit 0
EventFlag4 should have 5th digit 2, and may be the same as LowerSwitchRegionID

Label determines the height of the elevator. 0 is short, 2 is long, etc.

5. Create another new event. This one will run before loading to set up the main event.

$Event(NewEventID2, Default, function() {
    EndIf(ThisEventSlot());
    SetEventFlagID(EventFlag1, ON);
});

Note: NewEventID2 should have 5th digit 0

6. Add two new lines to Event(0

    InitializeCommonEvent(0, 90005501, EventFlag1, EventFlag2, Label, ElevatorID, UpperLeverID, LowerLeverID, EventFlag3);

    InitializeEvent(0, NewEventID1, 0);

7. Add one new line to Event(50

    InitializeEvent(0, NewEventID2, 0);

8. Test it out, adjust as needed. More elevators require repeating all the steps. Different elevator models may require individual adjustment, so reference pre-existing maps and mess around until you've got it working.
9. Congratulations.


How To Make Falling Guillotine Traps

1. Create a new asset using model AEG027_013, and give it a unique EntityID. Place it where you want it to go in the map.
2. Create a new Other, Box region. Make it as large and wide as you want, and place it in the map. It will determine where the player needs to stand to start up the falling blades. Give it a unique EntityID, and the following values:

  • UnkE08: 255
  • MapID: -1
  • UnkS0C: -1

3. Create a new event in the map's EMEVD, to initialize the common event (90005675)

$Event(NewEventID, Default, function() {
    if (EventFlag(57)) {
        InitializeCommonEvent(0, 90005675, targetEventFlagID, eventFlagID, entityID, areaEntityID, 801202070, 1082130432, 0);
    } else if (EventFlag(56)) {
            InitializeCommonEvent(0, 90005675, targetEventFlagID, eventFlagID, entityID, areaEntityID, 801202060, 1082130432, 0);
    } else if (EventFlag(55)) {
        InitializeCommonEvent(0, 90005675, targetEventFlagID, eventFlagID, entityID, areaEntityID, 801202050, 1082130432, 0);
    } else if (EventFlag(54)) {
        InitializeCommonEvent(0, 90005675, targetEventFlagID, eventFlagID, entityID, areaEntityID, 801202040, 1082130432, 0);
    } else if (EventFlag(53)) {
        InitializeCommonEvent(0, 90005675, targetEventFlagID, eventFlagID, entityID, areaEntityID, 801202030, 1082130432, 0);
    } else if (EventFlag(52)) {
        InitializeCommonEvent(0, 90005675, targetEventFlagID, eventFlagID, entityID, areaEntityID, 801202020, 1082130432, 0);
    } else if (EventFlag(51)) {
        InitializeCommonEvent(0, 90005675, targetEventFlagID, eventFlagID, entityID, areaEntityID, 801202010, 1082130432, 0);
    } else (EventFlag(50)) {
        InitializeCommonEvent(0, 90005675, targetEventFlagID, eventFlagID, entityID, areaEntityID, 801202000, 1082130432, 0);
    }
});

Notes: targetEventFlagID and eventFlagID should be unique, eight-digit values. entityID should be the guillotine's EntityID, areaEntityID should be the box region's EntityID.

Notes on EventFlag(5X): For map hazards like these, it's common for there to be eight different BehaviorIDs so that they can scale for NG+0 - NG+7. This means you'll need eight lines, as shown above, matching the eighth digit of the BehaviorID with the second digit of that line's EventFlag. (eg: Flag(56), 801202060; Flag (55), 801202050.)

4. Initialize the event in Event(0, at the top of the script.

    InitializeEvent(0, NewEventID, 0);

5. Repeat for as many guillotines as you want. Multiple blades can reference the same box region, and the event can initialize multiple blades. Just copy the code from step 3, and change values to reference the new blade entity.

6. Congratulations.


How To Make Pressure Plate Arrow Traps

1. Create a new pressure plate asset (eg: AEG027_044). Give it a unique EntityID, and place it where you want it to go.
2. Create a new Enemy entity. Give it a unique EntityID, and the following values:
UnkC4: -1
LightSetID: -1
FogParamID: -1
MapID: -1
Unk0C: -1
Unk14: -1
ThinkParamID: 1
NPCParamID: 10003100
TalkID: 0
PlatoonID: 0
UnkT24: -1
UnkT84: 1.000
ModelName: c1000 (invisible placeholder model)
Unk08: 9004
UnkE0F: 1
IsShadowDest: Yes
EntityGroupIDs: Set all to 0
UnkE3C: -1

3. Create a new Other, Box region. Position it over the pressure plate; you may want to make it slightly bigger to fit the plate. Give it a unique EntityID, and the following values:
Unk2C: Unique one-to-three digit number
UnkE08: 255
MapID: -1
UnkS0C: -1

4. Create three new Other, Sphere regions. Shrink their radius to around 0.050-0.100. Position them where you want the projectiles to spawn from, and aim them in the correct direction. (The blue axis arrow in Map Studio points forward; use it as reference.) Give them each unique EntityIDs, and the following values:
Unk2C: Unique one-to-three digit number
UnkE08: 255
MapID: -1
UnkS0C: -1

5. Add a new Event, which will initialize the necessary common event (90005660).

$Event(NewEventID, Default, function() {
    if (EventFlag(57)) {
        InitializeCommonEvent (0, 90005660, EnemyID, PlateID, BoxRegionID, BehaviorID, HoleRegionID 1, HoleRegionID 2, HoleRegionID 3);
    } else if (EventFlag(56)) {
    [Repeat for EventFlags 56-50]
    }
});

Notes: BehaviorID will pick which BehaviorParam the arrows use. There are eight of each; set the eighth value to match that line's EventFlag, as described in the Guillotine Traps section.

Quick reference:
8010010X0 = Fire Arrows
8010100X0 = Ice Arrows
8010200X0 = Lightning Arrows
8010320X0 = Magic Arrows

5b. For custom projectiles, duplicate and edit one of the above sets of BehaviorParams in Param Editor. Duplicate and edit referenced BulletParams and AtkParam_NPC entries; be careful everything matches.

6. Initialize the event by adding the following line to Event(0, at the top:

InitializeEvent(0, NewEventID, 0);

7. Congrats.


How To Make Lever-Operated Doors

Note: This specifically covers the Catacombs boss doors. The process may or may not differ for other door/lever models.

1. Create a new door asset (Ex: AEG027_041) and a new lever asset (Ex: AEG027_115). Give them each unique EntityIDs.
1b. For this model of lever, you can change the AssetSfxParamRelativeID to add a candlelight effect to the attached statue's lantern.
2. Create a new ObjAct, and set the following values:
ObjActEntityID: Unique Value
ObjActPartName: Name Of Lever Asset
ObjActID: 27115
EventFlagID: 0
EventID: 0
MapID: -1
UnkE0C: 255
UnkS0C: -1

3. Add the following lines to Event(0 to initialize the necessary common events (90005650, 90005651)

    InitializeCommonEvent(0, 90005650, EventFlagID, DoorEntityID, LeverEntityID, ObjActEntityID, ObjActID);
    InitializeCommonEvent(0, 90005651, EventFlagID, DoorEntityID);

Notes: EventFlagID should be a unique value, fifth digit cannot be 1.

4. Well done.


How To Make Hand-Operated Doors

1. Create a new door asset (Ex: AEG027_043), and give it a unique name and EntityID.
2. Create a new ObjAct, and set the following values:

EventID: 11
EntityID: 0
Unk14: 0
MapID: -1
UnkE0C: 255
UnkS0C: -1
Name: Unique Name
ObjActEntityID: Unique Eight-Digit Value
ObjActPartName: Door Name
ObjActID: ObjActParam To Fit Door Model
StateType: 4
EventFlagID: Unique Eight-Digit Value, 8 as Fifth Digit

Note: ObjActID will differ depending on the door (Eg: single or double door, push or pull animation, locked or does-not-open-from-this-side). Look through and cross-reference with other instances of the door model to see what might work for it. One useful ID is ObjActParam 27143 (a simple push-open animation.)

If that's all you need, then you're done! If you need it to open from only one side, then continue onwards.

3. Create two new Other, Box Regions. Make them each suitably large (5x1x2 is common), and position them on either side of the door, clipping a short distance through the ground so that the character's feet will always be inside the region. Give them each a unique EntityID and the following values:

Unk2C for Open Side: 3
Unk2C for Locked Side: 4
UnkE08: 255
MapID: -1
UnkS0C: -1

4. Add the following line to Event(0, to initialize the first common event (90005511):

    InitializeCommonEvent(0, 90005511, EventFlag, DoorEntityID, ObjActEntityID, ObjActID, 0);

Note: EventFlag should be a unique, eight-digit value. Fifth digit should be 8

5. Add the following line to Event(0, to initialize the second common event (90005512):

    InitializeCommonEvent(0, 90005512, EventFlag, OpenRegionID, LockedRegionID);

Note: EventFlag should be the same flag used in the previous line.

6. Congrats.


How To Make Stakes Of Marika

1. Create a new Stake of Marika asset; these are AEG099_500-504, in various states of repair. Give it a new, unused EntityID.

2. Create a new Player part, and place it where you'd like the player to respawn. Give it another new EntityID; this one should be exactly the stake's EntityID, minus 970. (ie: Stake = 30051900, Player Object = 30050930)

3. Create a new Other region, and shape it to fit the area that you'd like the player to be able to respawn from.

4. For the final piece, create a new RetryPoint event. Set RetryPartName to match the stake's name, and set RetryRegionName to match the region's name. Give it the following values:

EventID: 1-to-3 digit number
MapID: -1
UnkS0C: -1
UnkE0C: 255
EventFlagID: 6001
UnkT08: -1

5. That's it. Pretty painless, overall.


How To Make Enemies Fade Out On Death

This one isn't really related to mapping, but it might be useful if you're trying to add or change a few enemy types or minibosses.

Enemy fading animations are often handled by their anibnd (the actual animation files), but sometimes enemies that normally ragdoll on death will fade out. This is caused by a stateInfo setting in a spEffect. For specific reference:

  • stateInfo 453, used by spEffect 4300: A generic fade-out, with white particle effects; used by ghostly enemies
  • stateInfo 454, used by spEffect 4302: A magical fade-out, with blue particle effects
  • stateInfo 455, used by spEffect 4301: A dramatic fade-out, followed by a windy blast; used by miniboss versions of normally-ragdollable enemies

Simply add the desired spEffect to an npcParam— or, add the desired stateInfo to a spEffect being used by the enemy— and it should work without any further legwork.