Skip to content

Tutorials · Navigation and AI · Chapter 11

Reinforcements

35 minutes Uses: ScreenNotifier, Spawner, Timer, CharacterBody, NavAgent, AnimatedSprite, StateMachine, Sprite, angle_between, arrived, can_reach, can_see, emit_to, heard, keep_point, kept_point, nearest, node, position, position_of, pulse_turn, quench, random, road_distance, set_flag, set_number, set_param_flag, spawn, sqrt, start_timer, stop_timer, tau, time_left, vec2, walk_to

By the end

  • A Screen Notifier on each round guard: far from the view he sleeps, standing and hearing nothing, and guard.rgs gives up a chase that leaves the view
  • artifacts/reinforcement.artifact: a guard built once, Summoned ticked, whose notifier never puts him to sleep
  • barracks, a shut door with a Spawner and barracks.rgs: each time the bell rings it sends out one more guard, two at most
  • bell_rest, a second Timer with rest.rgs, and bell.rgs: the bell tells the barracks, and rests ten seconds before it can count again
On this page

Guards who sleep off screen

The barracks will send guards out after the thief, and a keep where every guard walks his round all night, wherever she is, is busy for nothing: a guard she cannot see is a guard she cannot meet. A Screen Notifier knows whether the view reaches a rectangle round its node. With its Enabler ticked, the node sleeps while it does not: the guard stands where he is until the view comes near.

  1. Select guard_hall. Click Add component and choose ScreenNotifierComponent.
  2. Set its Size to 160 and 96, clicking each box once, typing and pressing Enter. Tick Enabler. On Screen is greyed.
  3. Select guard_corridor and do the same: Size 160, 96, Enabler ticked.
The whole keep framed with guard_hall selected: a thin grey rectangle ten tiles by six round him in the great hall, and another round guard_corridor in the corridor below; the Inspector, filtered to screennotifier, shows his ScreenNotifierComponent with Size 160.0 and 96.0, Enabler ticked and On Screen unticked
Each Screen Notifier’s rectangle, drawn round its guard whether or not he is selected.
The Screen Notifier’s Size
The rectangle, in world units, centred on the node, that the view has to reach. 160 by 96 is ten tiles by six, half the view each way: he wakes while any of it is in the view, a little before he comes into sight, and sleeps once none of it is. The editor draws it as a thin grey box round the node, in the Gizmos menu’s Framing colour, whether or not the node is selected; it is not drawn in the game. A new Screen Notifier’s is 64 by 64.
The Screen Notifier’s Enabler
Ticked, the node and the nodes under it sleep while the view does not reach the rectangle: his script and his Nav Agent are held, he stands, and nothing he is sent reaches him. Unticked, nothing sleeps: the notifier only tells a script when the rectangle comes into the view and leaves it. A new one’s is unticked.
The Screen Notifier’s On Screen
Greyed: ticked while the view reaches the rectangle, as the step began. You cannot type it; watch it in Play.

His script hears the notifier too. It needs one change for this chapter, a chase that ends when he leaves the view, and one for the next section, a guard the barracks sends.

  1. Click the Code tab, then guard.rgs in its Scripts list. Replace everything in it with the script below, and press Ctrl+S.
  2. Select each guard: his Guard has a new field, Summoned, unticked. Leave it so.
  3. Press Ctrl+S.
rgs guard.rgs
/// A guard's mind. He walks his round, corner to corner. A glimpse of the
/// thief, or a noise near enough by road, makes him suspicious: he creeps to
/// where he glimpsed her or heard it. Seen near enough to be sure, she is
/// chased at a run, and caught she is sent back to where she came in. Lost,
/// she is searched for about where he saw her last until his Timer runs out,
/// and then he goes back to his round. He tells the bell when he starts and
/// stops chasing, and when it rings he comes to search where she was last
/// seen. One the barracks sends comes running to search there as soon as he
/// is out.
enum Mode { Patrol, Suspicious, Chase, Search, Return }

component Guard : Screen {
    /// His round's first corner.
    a: Vec2,
    /// Its second.
    b: Vec2,
    /// Its third; a round of two corners never comes here.
    c: Vec2,
    /// Its fourth.
    d: Vec2,
    /// How many corners his round has: 2 or 4.
    corners: i32 = 4,
    /// How far by road a noise can be and still be heard.
    #[suffix("u")]
    hearing: f32 = 320.0,
    /// How far he sees.
    #[suffix("u")]
    sight: f32 = 112.0,
    /// How far to either side of straight ahead he sees, in radians.
    cone: f32 = 0.6,
    /// The collision layers that hide what is behind them.
    walls: i32 = 1,
    /// How near he must see her to be sure it is her.
    #[suffix("u")]
    sure: f32 = 64.0,
    /// How fast he walks his round.
    walk: f32 = 40.0,
    /// How fast he creeps when suspicious.
    creep: f32 = 24.0,
    /// How fast he runs after her.
    run: f32 = 72.0,
    /// Whether the barracks sent him: he starts by searching where she was
    /// last seen.
    summoned: bool = false,
    /// What is on his mind.
    #[readonly]
    mode: Mode = .Patrol,
    /// Whether the thief is in his cone, as this step began.
    #[readonly]
    sees: bool = false,
    /// Which way he faces: the way he last walked.
    #[hidden]
    facing: Vec2,
    /// Where he stood the step before.
    #[hidden]
    was: Vec2,
    /// Where he saw her last.
    #[hidden]
    last_seen: Vec2,
    /// The corner he is walking to, from 0.
    #[hidden]
    next: i32 = 0,
    /// Whether to set off for that corner this step.
    #[hidden]
    to_round: bool = true,

    fn on_create() {
        was = position();
        facing = vec2(0.0, 1.0);
        if summoned {
            mode = .Search;
            to_round = false;
            last_seen = kept_point("seen", position());
            start_timer();
            set_number("NavAgentComponent", "speed", run);
            walk_to(last_seen);
        }
    }

    fn on_screen_exit() {
        // Going to sleep mid-chase, he loses her: no frozen chase keeps the bell ringing.
        if mode == .Chase {
            mode = .Search;
            start_timer();
            emit_to("bell", "lost");
            walk_to(last_seen);
        }
    }

    fn loop() {
        let moved = position() - was;
        if moved.length() > 0.1 {
            facing = moved;
        }
        was = position();
        let thief = nearest("thief");
        let at = position_of(thief);
        let toward = at - position();
        // Returning, he has given up; he looks again on his round.
        sees = mode != .Return
            && thief != node(0)
            && toward.length() < sight
            && angle_between(facing, toward) < cone
            && can_see(at, walls);
        if sees {
            last_seen = at;
        }

        if mode == .Patrol || mode == .Return {
            if sees {
                mode = .Suspicious;
                set_number("NavAgentComponent", "speed", creep);
                walk_to(at);
            }
        } else if mode == .Suspicious {
            if sees && toward.length() < sure {
                mode = .Chase;
                set_number("NavAgentComponent", "speed", run);
                emit_to("bell", "spotted");
            }
        } else if mode == .Chase {
            if !sees {
                mode = .Search;
                start_timer();
                emit_to("bell", "lost");
                walk_to(last_seen);
            } else if toward.length() < 10.0 {
                emit_to("thief", "caught");
                emit_to("bell", "lost");
                mode = .Return;
                to_round = true;
            } else {
                keep_point("seen", at);
                walk_to(at);
            }
        } else if mode == .Search {
            if sees {
                stop_timer();
                mode = .Chase;
                set_number("NavAgentComponent", "speed", run);
                emit_to("bell", "spotted");
            }
        }

        if to_round {
            to_round = false;
            set_number("NavAgentComponent", "speed", walk);
            if next == 0 {
                walk_to(a);
            } else if next == 1 {
                walk_to(b);
            } else if next == 2 {
                walk_to(c);
            } else {
                walk_to(d);
            }
        }
        set_param_flag("alert", mode == .Chase || mode == .Search);
    }

    fn on_signal() {
        if heard("noise") && (mode == .Patrol || mode == .Return) {
            let noise = kept_point("noise", position());
            let way = road_distance(noise);
            if way >= 0.0 && way < hearing {
                mode = .Suspicious;
                set_number("NavAgentComponent", "speed", creep);
                walk_to(noise);
            }
        }
        if heard("alarm") && (mode == .Patrol || mode == .Return) {
            mode = .Search;
            last_seen = kept_point("seen", position());
            start_timer();
            set_number("NavAgentComponent", "speed", run);
            walk_to(last_seen);
        }
        if heard("nav:ended") {
            if mode == .Patrol || mode == .Return {
                if arrived() {
                    next += 1;
                    if next >= corners {
                        next = 0;
                    }
                }
                mode = .Patrol;
                to_round = true;
            } else if mode == .Suspicious {
                mode = .Return;
                to_round = true;
            } else if mode == .Search {
                let far = 40.0 * sqrt(random(0.0, 1.0));
                let turn = random(0.0, tau());
                let spot = last_seen + vec2(far * turn.cos(), far * turn.sin());
                if can_reach(spot) {
                    walk_to(spot);
                } else {
                    walk_to(last_seen);
                }
            }
        }
        // An arrival on the step the search runs out is the search's, so it is heard first.
        if heard("timer:fired") && mode == .Search {
            mode = .Return;
            to_round = true;
        }
    }
}
component Guard : Screen
A script with a Screen base. It goes on a node that has a Screen Notifier, as pots.rgs, with its Area base, goes on a node with an Area, and it can hear the notifier’s rectangle leave the view. That is why the notifiers went on first.
on_screen_exit
Runs on the step the notifier’s rectangle leaves the view, while he is still awake. A guard chasing her gives the chase up there: he turns to Search, starts his search’s Timer, tells the bell lost, and sends himself to where he saw her last. Then he sleeps where he stands.
Summoned
The Guard’s new field: whether the barracks sent him. Unticked in the two round guards. Ticked, his on_create starts him searching at once, at a run, from the moment he exists: at kept_point("seen", position()), the point a chasing guard keeps under seen on every step of a chase, or his own position if no guard ever has.
  1. Press F5. Select guard_hall, and type screennotifier into the Inspector’s search box and press Enter. The thief is at the courtyard gate, far from him: On Screen is unticked, and he stands where he started.
  2. Walk her into the hall through the kitchen: west along the corridor’s carpet to the opening in its north wall under the kitchen, up through it, and west through the kitchen door. On Screen ticks, and he walks his round. Press F5 again to stop.
Play, looking through the game camera at the corridor’s east end and the courtyard: the thief at the courtyard gate, the mud’s wash, no guard in sight; guard_hall selected in the Hierarchy and the bar under the Viewport saying at 56.0, 72.0; the Inspector narrowed with the search box, screennotifier, to his Screen Notifier: Size 160.0 and 96.0, Enabler ticked, On Screen unticked and greyed
After 300 steps, 5 s, of Play: the view far from the hall guard. On Screen is unticked, and the bar under the Viewport still puts him at 56, 72, the corner he started on.
Play, looking through the game camera at the great hall: the hall guard, selected, near its top left corner, a lime line from him east along the hall’s top to a cross; the thief below and behind him at the hall’s west end, the two tables with their discs, the cat at the top; the Inspector narrowed with the search box, screennotifier, to his Screen Notifier: Size 160.0 and 96.0, Enabler ticked, On Screen ticked
After 60 steps, 1 s, of Play: On Screen ticked, and the hall guard on his way to his round’s second corner. For this picture the thief was placed at the hall’s west end, below and behind him, from the start.

A guard saved for later

The barracks sends copies of one guard. He is saved as an artifact: a file holding a node and the nodes under it, which a Spawner copies into the game while it runs. You build him once in the keep, as the corridor guard is built, save him, and delete him.

  1. Select keep, press + Add node, choose Sprite, and rename it reinforcement. Where he lands does not matter: each copy is put where the barracks says.
  2. In his Sprite, drag art/guard.png from Assets onto Texture. Set Size to 16, 16, Anchor to 0.5, 1, his feet, and Sort Layer to 2.
  3. Under Groups, type guards into Add group and press Enter; then ears, Enter.
  4. Click Add component and choose CharacterBodyComponent. Set its Size to 8, 6, Motion Mode to Floating, Driven By to Script, and Layer to 2 (untick the box labelled 0, tick the one labelled 1).
  5. Click Add component and choose NavAgentComponent. Set Speed to 40, tick Face Walk and untick Use Links.
  6. Click Add component and choose AnimatedSpriteComponent. Drag art/guard.anim onto Animations; Clip stays idle. Tick Frame Size.
  7. Click Add component and choose StateMachineComponent. Drag art/guard.asm onto its Graph.
  8. Click Add component and choose TimerComponent. Set Wait Time to 6, tick One Shot and untick Autostart: his search’s Timer, as the round guards’.
  9. Click Add component and choose ScreenNotifierComponent. Set Size to 160, 96. Leave Enabler unticked.
  10. Click Add component and choose Guard. Set A to 40, 232, B to 600, 232, and Corners to 2: the corridor’s round. Tick Summoned. Every other field stays as the script declares it.
  11. With reinforcement selected, press + Add node, choose Sprite, and rename it reinforcement_cone. Set its Position to 0, -8; drag art/cone.png onto Texture; set Size to 112, 154, Anchor to 0, 0.5 and Sort Layer to 1. Click Add component and choose Cone.
  12. Right-click reinforcement in the Hierarchy and choose Save as artifact…. In the save dialog, make a folder called artifacts, open it, and save the file as reinforcement.artifact.
  13. The editor has put a copy of the artifact in the keep where your node was, under the same name. Delete that reinforcement; his cone goes with him.
  14. Press Ctrl+S.
The Hierarchy with a menu open over it on guard_corridor’s row, which is highlighted: Rename, Duplicate, Copy, Paste as child and Paste as sibling greyed, Group selection, Select children, Groups, Move up, Move down, Add child, Expand all, Collapse all, Save as artifact… with its icon, and Delete
The menu a right-click on a Hierarchy row opens, with Save as artifact… near its foot. For this picture it was opened on guard_corridor, the guard the reinforcement is built like: the finished keep keeps no reinforcement to right-click.

To look at what you saved, double-click reinforcement.artifact in Assets: the editor opens it on its own, him and his cone. Double-click keep.ron in scenes to come back to the keep.

The editor with reinforcement.artifact open, its name in the window’s title: the Hierarchy holds reinforcement, with the chip guards, and reinforcement_cone under him; the Viewport is filled by the guard’s picture, his body’s box drawn over his feet and the edge of his cone beside him; the Inspector narrowed with the search box, guard, to his Guard: A 40.0 and 232.0, B 600.0 and 232.0, C and D 0.0 and 0.0, Corners 2, Hearing 320.00 u, Sight 112.00 u, Cone 0.60, Walls 1, Sure 64.00 u, Walk 40.00, Creep 24.00, Run 72.00, Summoned ticked, Mode Patrol, Sees unticked
The artifact opened in the editor, and his Guard: the corridor’s two corners, Summoned ticked. Frame was pressed on him for this picture, which fills the Viewport with a node 16 units wide.
The Inspector narrowed with the search box, screennotifier, to the reinforcement’s Screen Notifier: Size 160.0 and 96.0, Enabler unticked, On Screen unticked and greyed
The reinforcement’s Screen Notifier, in the same artifact: Enabler unticked.
Save as artifact…
Writes the node and every node under it, with all their components and values, to an .artifact file, and puts a copy of the artifact in the scene in the node’s place: one step, which Undo takes back. A Spawner copies the file, not anything in the scene, so the copy in the keep is not needed.
The reinforcement’s Screen Notifier Size and Enabler
The Screen Notifier’s Size, 160 by 96, the round guards’; its Enabler left unticked, so he never sleeps. The notifier still tells his script when he leaves the view, so a chase he leaves the view on ends, as a round guard’s does.
His Timer’s Wait Time, One Shot and Autostart
The Timer’s Wait Time, 6, One Shot ticked, Autostart unticked: chapter 9’s search, which his script starts as he is made.

The barracks

The barracks is a shut door in the corridor’s north wall, at its west end, above the corridor guard’s post: the door_closed region from chapter 10, on a node of its own. Behind it are two guards. Each time the bell rings it sends one out, while it has one.

  1. Select keep, press + Add node, choose Sprite, and rename it barracks. Set its Position to 40, 216.
  2. In its Sprite, drag art/tilemap_packed.png onto Texture, set Size to 16, 16, type door_closed into Atlas Region, and set Sort Layer to 1.
  3. Under Groups, type barracks into Add group and press Enter.
  4. Click Add component and choose SpawnerComponent. Press + beside Entries, open the new [0] row, type guard as its Name, and drag artifacts/reinforcement.artifact from Assets onto its Artifact.
  5. In Assets, press Create, choose New script, type barracks, and press Enter. In the Code tab, replace everything in barracks.rgs with the script below, and press Ctrl+S.
  6. Select barracks, click Add component and choose Barracks. Left stays 2.
  7. Press Ctrl+S.
rgs barracks.rgs
/// The barracks. Each time the bell rings it sends out one more guard, as
/// long as it has one left.
component Barracks {
    /// How many guards it has left to send.
    left: i32 = 2,

    fn on_signal() {
        if heard("alarm") && left > 0 {
            left -= 1;
            spawn("guard", position() + vec2(0.0, 16.0));
        }
    }
}
Edit mode, looking through the game camera at the corridor’s west end: the barracks, a shut door in the corridor’s north wall, selected, the corridor guard standing below it at his post and the thief on the carpet to the right; the Inspector narrowed with the search box, spawner, to its Spawner: Entries holding one item, [0] unfolded, Name guard, Artifact reinforcement.a…
The barracks’ Spawner, its one entry. For this picture the thief was placed in the corridor, so that looking through the game camera shows the barracks.
The Spawner’s Entries
The names a script on this node can pass to spawn, each with the artifact it copies: here one, guard, copying reinforcement.artifact.
spawn
Makes a copy of the artifact the Spawner names, at a point in the world, at the end of the step. The copy is in the game from the next step, and its on_create runs on the step after that. position() + vec2(0.0, 16.0) is a tile below the barracks: the corridor, at the corridor guard’s post.
Left
The Barracks’ field: how many guards it has still to send, 2. Each alarm it answers takes one; at 0 it answers no more.
heard("alarm")
The barracks hears alarm sent to the group barracks. Nothing sends it yet: the bell’s alarm goes to the group guards. The bell’s script changes in the next section.

A copy is the artifact as you saved it, so each reinforcement is the same guard: Summoned ticked, the corridor’s two corners, awake wherever he is. Made, he searches where she was last seen, at a run; when his search’s six seconds are up he returns to the corridor’s round and walks it, as the corridor guard does.

The bell rests

As it stands, a bell that has rung starts counting again at the next chase, and four more seconds of it would empty the barracks at once. After it rings, the bell now rests ten seconds before it can count again. A node has one Timer, and the bell’s counts the chase, so the rest is a Timer on a node of its own, under the bell.

  1. Select bell, press + Add node, choose Node, and rename it bell_rest. It lands under the bell.
  2. Under Groups, type rest into Add group and press Enter.
  3. Click Add component and choose TimerComponent. Set Wait Time to 10, tick One Shot, and untick Autostart.
  4. In Assets, press Create, choose New script, type rest, and press Enter. In the Code tab, replace everything in rest.rgs with the script below, and press Ctrl+S.
  5. Select bell_rest, click Add component and choose Rest.
  6. Click the Code tab, then bell.rgs in its Scripts list. Replace everything in it with the second script below, and press Ctrl+S. The Bell gains Chased, greyed.
  7. Press Ctrl+S.
rgs rest.rgs
/// The bell's rest: once it has rung it cannot count again until this
/// Timer runs out.
component Rest {
    fn on_signal() {
        if heard("rang") {
            start_timer();
        }
        if heard("timer:fired") {
            emit_to("bell", "rested");
        }
    }
}
rgs bell.rgs
/// The alarm bell. Its Timer starts held, and counts down only while a
/// guard is chasing the thief. When it runs out the bell rings: every guard
/// comes to search where she was last seen, and the barracks sends one
/// more. Then it rests, and is ready to count again when its rest is over.
component Bell {
    /// Seconds left before it rings, as this step began.
    #[readonly]
    left: f32 = 0.0,
    /// Whether a guard is chasing her.
    #[readonly]
    chased: bool = false,

    fn loop() {
        left = time_left();
    }

    fn on_signal() {
        if heard("spotted") {
            chased = true;
            set_flag("TimerComponent", "paused", false);
        }
        if heard("lost") {
            chased = false;
            set_flag("TimerComponent", "paused", true);
        }
        if heard("timer:fired") {
            pulse_turn(0.3, 0.15, .InOutSine);
            emit_to("guards", "alarm");
            emit_to("barracks", "alarm");
            emit_to("rest", "rang");
        }
        if heard("rested") {
            quench();
            start_timer();
            set_flag("TimerComponent", "paused", !chased);
        }
    }
}
The rest’s Wait Time, One Shot and Autostart
The Timer’s Wait Time 10, its One Shot ticked and its Autostart unticked: it counts ten seconds, once, each time its script starts it, and not before.
rang and rested
The bell tells the group rest that it rang; the rest starts its Timer. When that fires, the rest tells the group bell, chapter 9’s, that it has rested. Each is heard on the step after it is sent.
emit_to("barracks", "alarm")
The alarm, sent to the barracks too: it was going to the group guards only.
quench
Stops every anneal and pulse running on this node, wherever each stands: the bell stops swinging as its rest ends.
Chased
The Bell’s new field, greyed: whether a guard is chasing her, as the bell last heard. On rested its Timer starts a fresh four seconds, held by set_flag("TimerComponent", "paused", !chased) unless a chase is on right then.

Read in the order of a chase: spotted ticks Chased and lets the bell’s Timer count. When it fires, the bell swings and tells the guards, the barracks and its rest. The rest counts ten seconds and says rested; the bell stops swinging, starts its four seconds again, and holds them unless the chase is still on. Until then its Timer, which fired once, counts nothing, however long the chase.

  1. Press F5. Walk the thief up into the corridor and west along the carpet as far as the ladder, and wait. The corridor guard wakes at his post at the corridor’s west end, comes into sight, and walks east towards her.
  2. Before he is near, walk her back east to the opening in the corridor’s north wall under the kitchen, and up through it, a tile or two into the kitchen. Wait there while he walks past below her, on his way to the corridor’s east end.
  3. Once he has passed, walk her back down onto the carpet under the opening, and wait there for him on his way back west. He glimpses her and creeps nearer; four tiles from her he is sure of her, and his red mark comes on.
  4. Walk her west along the carpet ahead of him, holding A. Four seconds into the chase the bell rings: a guard comes out of the barracks’ door ahead of her, his red mark on, and runs to where she was last seen.
  5. Select barracks, and type barracks into the Inspector’s search box: Left reads 1. Select bell_rest and type timer into the search box: its Time Left counts down from 10. Press F5 again to stop.
Play, looking through the game camera at the corridor’s west end: a guard with a red mark just out of the barracks’ door, a lime line from him down onto the carpet and east to a cross and ring by the thief; beyond her the corridor guard, marked too; the Inspector narrowed with the search box, barracks, to the Barracks: Left 1
After 255 steps, 4.25 s, of Play: the bell has rung, and a reinforcement out of the barracks has his way to where she was last seen. For this picture the corridor guard was placed at the corridor’s east end, where he sets off west for his post, and the thief on the carpet 50 units west of him from the start, rather than walked there as the steps above walk them; she walked west the whole run, as holding A does.
The same Play later: bell_rest selected under bell in the Hierarchy; on the carpet the reinforcement, marked, to the thief’s left and the corridor guard, marked, to her right, a lime line from each to her; the Inspector narrowed with the search box, timer, to bell_rest’s Timer: Wait Time 10.00 s, One Shot ticked, Autostart and Paused unticked, Time Left 9.10 s
After 300 steps, 5 s, of the same Play: the bell’s rest counting, 9.10 seconds left.

What the chapter set

NodeComponentFieldValue
guard_hallScreen NotifierSize160, 96
Enablerticked
guard_corridorScreen NotifierSize160, 96
Enablerticked
Node, in the artifactComponentFieldValue
reinforcementnodeGroupsguards, ears
SpriteTextureguard.png
Size16, 16
Anchor0.5, 1
Sort Layer2
Character BodySize8, 6
Motion ModeFloating
Driven ByScript
Layer2: the box labelled 1
Nav AgentSpeed40
Face Walkticked
Use Linksunticked
Animated SpriteAnimationsguard.anim
Frame Sizeticked
State MachineGraphguard.asm
TimerWait Time6
One Shotticked
Autostartunticked
Screen NotifierSize160, 96
GuardA40, 232
B600, 232
Corners2
Summonedticked
reinforcement_cone, under reinforcementnodePosition0, -8
SpriteTexturecone.png
Size112, 154
Anchor0, 0.5
Sort Layer1
Coneadded
NodeComponentFieldValue
barracks, under keepnodePosition40, 216
Groupsbarracks
SpriteTexturetilemap_packed.png
Size16, 16
Atlas Regiondoor_closed
Sort Layer1
SpawnerEntries, first rowguard, reinforcement.artifact
Barracksadded
bell_rest, under bellnodeGroupsrest
TimerWait Time10
One Shotticked
Autostartunticked
Restadded

Every other field is as it comes, or as its script declares it: the reinforcement’s Enabler unticked and his Guard’s Hearing, Sight and the rest at the script’s values; the round guards’ Summoned unticked; the barracks’ Left 2.

Check it works