The following features was made by NoOne and it's fully supported by NBlood and Raze source ports. The latest dev builds always available on https://lerppu.net/wannabethesis/nblood/latest/ (for NBlood) or https://devbuilds.drdteam.org/raze (for Raze).
I'm not against to add same features in all other existing ports and maintain it. If authors is interested, they can just mail me to email@example.com or search for me in Discord channel dedicated to Blood so we can discuss it. Coders may also visit modern features on GitHub.
Hope this helps to make maps better than ever and generally turn map editing to the next level. Adding even more new features is planning as well. If you have any questions, problems, bug reports or suggestions, you may use contacts above to talk with me. The same you can do if you want to update, for instance, my "perfect" english in this documentation.
There is two ways to let the port(s) know that you are aiming for modern level design:
If you are using XMAPEDIT, you must open XMAPEDIT.INI, which usually can be found in XMAPEDIT directory, search for [General] section and change "SaveAsModernMap" value to 1. If you stick with PMAPEDIT, you must apply a patch that makes the edtor save the map with version 7.1. Note that using it is not recommended since is not supported anymore.
Every action in the game can be treated as an event. For example when you pressing a switch, enter sector, touching walls or even destroying gib objects, the game produces an event, which may send command on given TX ID. Sometimes we may need to send command on object if it does not have an RX ID assigned or it's ID is unknown. For that a special TX ID 50 is created.
In this example the Damager have TX 50 (event causer channel) which leads to interesting result: it does the damage (sends the command) to any sprite in proximity radius even if the destination sprite RX ID is unknown. This allows to create a complex and very flexible trigger sequences, especially in conjunction with conditional triggers (IF).
There is some limitations, however: objects that using TX 50 must send the command immediately - using waitTime is not safe, because the command may be send to the wrong object.
It's possible to make sprites that were attached to outside walls of movable sector to travel with that sector automatically. This means that there is no need to create a second sector which duplicates properties of the first one anymore.
In this example the sprites placed outside the Z-motion sector, but still close enough to it's walls. Once that sector activates and ceiling moves, the sprites will travel in tact.
For obvious reason this feature intended for all sectors that is supposed to move, but not for marked sector types. For example it works for "Rotate" type, but not for "Rotate Marked", works for "Slide" and "Z-motion", but doesn't for "Slide marked" and "Z-motion SPRITE".
To make this feature work, you need to place sprites close to the walls of sector you want to travel sprites with. Each sector can move up to 256 sprites. The distance between walls and the sprite cannot be longer than 16. Also, to avoid conflicts, sector which contains the sprites cannot be movable and always must be next to the walls of the target sector.
After that you need setup sprites just like you do it for common traveling e.g. blue sprites travels in sector direction and green sprites in opposite. For Z-Motion blue sprites means that it travels with floor and green means that it travels with ceiling.
This command allows to immediately kill all the events in the queue for destination object. For example it can interrupt fuse counter for dropped TNT bundle. Use it only when really sure as it may lead to unexpected results if not enough controlled.
.MAP It's possible to make patrol location by any enemy that can move with using Path Marker (type 15) and dude flags. Basically, this means that AI will follow from one marker to another and go back when is not found. The next marker can be referenced to any of previous markers and can be inserted in underwater sectors, so you can make loops and do many other interesting things which makes your maps more alive.
You must first actually create at least one marker; just put sprite and set type 15. The first marker enemy selects is always the closest marker it can see and it must have no "Locked" or "DudeLockout" flags enabled. There is two ways to make enemy to follow it:
What if you want the enemy to follow another marker after first one is reached? Just create second marker same way you did it for the first, but set data1 (id of the marker) value, then get back to the first marker and set data2 (id of the next marker) according to data1 of the second one. This is very same way you setup path for sectors. If you create two or more markers with same ID, the AI will select next marker randomly, which could make path a bit unpredictable for the player.
Path marker that gets reached (see clipdist) by the enemy will be automatically triggered if have TX ID or Command 15 (Set Dude Flags). If it have no TX ID, but still have "Set Dude Flags" command, all dude flags that marker have will be inherited by the enemy that just reached it. This allows you to change dude flags dynamically, but may also lead to unexpected results such as breaking the patrol when is not supposed to be stopped, so you have to be carefully.
Sometimes it may be useful make enemy to stay for some period of time before it goes to the next marker. There is two ways to make it possible: by enterring fixed value in the waitTime field of the marker after which it starts the move again (similar to path sector) or set same values in both data1 (marker id) and data2 (next marker id) which makes the enemy stay until target is spotted. The second way is very useful to build dynamic path using Data Changer or Inc-Dec since you can change data values.
If you want to break the patrol once marker gets reached, you may set value of the data2 (next marker) to -1 or set it to -2 if you want enemy to go back same path.
Let's back to the dude flags.
The rest of it ((D)eaf, (B)lind, (A)larm, (S)tealth) currently are working only when patrol flag is active and brings additional effects to the enemy:
|Deaf||The enemy is deaf, so the player can be spotted with a sight or touch only.|
|Blind||The enemy is blind, so the player can be spotted with a hear or touch only. This flag also known as dudeGuard in vanilla mapedit.|
|Alarm||The enemy will activate all other enemies in sight radius once player is spotted. If there is other enemies in patrol and have Alarm flag checked, it will activate enemies that they see too. This flag also known as dudeAmbush in vanilla mapedit.|
|Stealth||A special flag that brings some kind of stealth mechanics. This allows the player to sneak around while enemies patrol the location without being spotted immediately. In case if enemy is not Blind nor Deaf, there is spot progress bar will appear on the top of enemy sprite. Player's velocity, race, some sounds, as well as crouching affects spot radius and speed of spot progress.|
See also IF conditions related to dude flags and Stealth region markers that allows to modify spot chance of the enemy.
You can pause or continue motion of any sector by sending command 13 (pause) or 14 (continue) from any source to the destination sector. The sector that in pause, will continue it's movement with exactly same position and velocity that have before it stopped once gets Continue command. If sector have "Interruptable" flag enabled, you may also send commands such as On, Off, Toggle to force it go the opposite way.
Damage Sector will do the damage only when is enabled (State: 1 On). This allows you to control it via TX/RX system and commands.
.MAP Sometimes it may be useful to send command on player's sprite. For instance, you could make Effect Generator to spawn any of effects directly on player's location. This way you could achieve bleeding, if you select "Red blood Trail" effect. For that special Player RX Channels was created.
Player channels supported by all types, include vanilla ones. So, you probably want to experiment with those a lot to get interesting results.
.MAP Teleport target (Type 8) can be triggered via RX ID channel and teleport any TX ID sprite or player from any to it's sprite location! It may be useful to teleport path markers to change path sector's way or player without need to enter the sector. It can also teleport other teleport targets, so it's possible to create complex combinations! There is also few options to control how exactly sprite should be teleported available:
.MAP There is few cool updates for trigger flags available. Previously, "DudeLockout" has no effect when used in conjunction with "Proximity" or "Touch" flags, but now it does. If sprite is not a dude, you can define proximity radius through sprite's clipdist property. Aside from this, "Touch" flag is working for almost every type of sprite and for walls. The name explains itself: sprite or wall with this flag checked triggers something when player or enemy (in case if no DudeLockout checked) touching it.
"Sight" flag was renamed to "Sees Player". Sprite with this flag checked, will be triggered once it can see one of players from it's location.
"Screen" flag means that sprite will trigger when it drawn on the screen of one of players and "Aim" triggers sprite when one of players aims in it.
If sprite have "Impact" flag enabled, this means that it will be triggered once get hit with projectile, affected by explosion or touch another object (like wall, sprite or sector). Note that not all projectiles can make sprite to trigger.
There is 512 of additional sprites with these flags available for you to use. If you want Toggle Switch to send command when player fire a flare in it, or Blood Drip Gen spawn drips only when player can see or at close distance, these flags will help you a lot and save much of time.
If you plan to use any of additional sprites, you probably want to set it properly, because sprites from this arrays triggers a little bit different and more safely than in vanilla.
Make sure the restState is equals to state of the sprite, however in case of thing types (400 - 432), there is required to set restState to On in the level editor. If you want to ignore these rules, just set "Interruptable" trigger flag.
.MAP Grow (Type 129) and Shrink (Type 130) shroom items is working! When player is grown, it receives less damage, jumps higher and become heavier, which means it can easily damage by stomp and push back enemies that have less mass than player. Be carefully when pickup this powerup as you may lose your invisibility or can even die if place is too tight to grow ;)
When player is shrink, the enemies can do same thing to player as it becomes very small and receives way more damage than it usually does. However, player can go to really tight place.
.MAP You can set custom value for the following types of items using it's data1 field:
The value should be greater than 0. If value is greater than max value of the pickup, max value will be used.
.MAP You can specify number of INI message that will be displayed instead of "Picked Up ..." message when item was actually picked up. Just specify it in Lock msg field.