- Learn
- Build a Game
- Pacific Wings
- 9 Kill Chain
9 Kill Chain
Shoot enemies down quickly, one after another, and the points multiply. Each quick shoot-down counts for more than the last, up to four times, and the score shows it in color: cream, then yellow, orange and red. Wait too long, and the chain breaks.
The game as it is at the end of this chapter. Click the game, then press Enter to start.
If your game and this chapter part ways, here is the chapter’s finished project. Open it and compare, or start Chapter 10 from it.
To open it, start Myth Engine, choose File › Open Project... and pick the downloaded file.
9.1 The Idea
Fly into the V of five Enemy Fighters with your guns open. The first one flashes white and breaks up, and SCORE climbs by its points, as it always has.
The second goes before the first one’s explosion has faded. This time the score climbs twice as far, and the word SCORE turns yellow. A third, and it’s orange. A fourth, and the score is red, and every enemy counts four times over. After that, the sky is empty for a moment. The red fades back to cream.
That’s a kill chain: shoot-downs that follow each other quickly. Each one gives the chain a fresh 1.5 seconds. It’s like keeping a balloon up in the air: every tap buys it another moment, and if nobody taps it in time, it drops.
Since Chapter 3, an enemy has been worth the same whenever you shoot it down. Now it matters how fast you are.
The chain’s place lives in one new Global, $chainRow. It points at one row of a small table, the way $weaponLevel did in Chapter 8. Each row holds a multiplier, the number the points are multiplied by, and a color for the score.
9.2 The Plan
Here’s how the pieces work together, one chain to a line.
- An enemy is shot down -> Score adds its points, times the chain’s multiplier, and sends shotDownScored.
- The message shotDownScored arrives -> Kill Chain moves $chainRow down one row, up to the last, and starts its killChain timer over.
- The killChain timer rings, 1.5 seconds after the last shoot-down -> Kill Chain sets the chain back to row 0.
- The chain’s row changes -> Kill Chain Color paints Score Text in that row’s color.
9.3 Set Up
Nothing new comes from the Starter Kit this time, since the chapter is all Logic and one table.
GLOBAL VARIABLES has one new row, $chainRow. It starts at 0, as $weaponLevel does, so make it the same way, from a Globals card, with its own name.
9.4 The Chain
First the table, then the points, then the clock that breaks the chain.
9.4.1 Kill Chain Multipliers
One row of the "Kill Chain Multipliers" Data Table.
1#fff4cf2#ffe0663#ffab404#ff6a3dThis is the chain, written down. Four rows, one for each step. Row 0 is no chain at all, a multiplier of 1, in the cream the score has always been. Each row after it multiplies by one more, and warms the color.
Make it as Weapon Levels was made. The table makes Kill Chain Multipliers Entry, and its two fields are the columns. multiplier is a Number, with a Value of 1. scoreColor is a Color. That’s a new one. Pick Color in its Type list, and give it the card’s #fff4cf, the cream the score has always been.
Add Row four times. Then double-click each row’s name in the Entry column, and type x1, x2, x3 and x4. Those names are for you. The chain finds a row by its number, counting from 0, as Fighter Guns found a weapon level. Last, double-click each row’s two cells and type them from the card. A Color cell shows its code, such as #ffe066, and takes one the same way.
9.4.2 Score
Adds the points of every enemy shot down (times the kill-chain multiplier), and of every pickup collected, to $score.
Any Object- Name
multiplier- Value
1
- Variable
multiplier- Value
data('Kill Chain Multipliers', $chainRow, 'multiplier')
- Variable
$score- Operator
+=- Value
other.enemyStats.points * multiplier- Value
other.enemyStats.points
- Custom Event
shotDownScored
event.current == "mission-failed"- Logic Component
Score- State
Disable
- Variable
$score- Operator
+=- Value
@self.wingCannonsPoints
- Variable
$score- Operator
+=- Value
@self.repairCratePoints
Score learns to multiply. When an enemy is shot down, it first reads the multiplier from the chain’s row. Then it adds the enemy’s points times that multiplier. Last of all, it tells Game Rules that this shoot-down has been counted, with a new message, shotDownScored.
That order matters. The shoot-down is scored first, and only then does the chain move on. So the first enemy of a chain counts once. The second counts twice, because the first one moved the chain. Each shoot-down is paid at the step the ones before it reached.
The multiplier lasts one shoot-down, so it’s a Declare Variable, the first step: a Number named multiplier, with a Value of 1. The next step gives it the chain’s row.
The new steps go in front of the old one, so the old one has to step aside first. On the canvas, find On Enemy Shot Down. Right-click its Change Variable, and choose Disconnect from Flow. That one block slides off, and the line under the Event is empty.
Now add the Declare Variable from the Action List, and join it with Connect to Sequence. It becomes the first step. A Change Variable comes next, joined the same way. Type multiplier into its Variable box, and the card’s data() into its Value. Then right-click the old step, and choose Connect to Sequence. It joins after the new ones. Add * multiplier to the end of its Value.
Last, add Trigger Custom Event on Object from the Action List, and join it. It starts on Self, which is Game Rules here. Type shotDownScored into its Custom Event box.
9.4.3 Kill Chain
Each shoot-down moves $chainRow, the kill chain's row of the Kill Chain Multipliers table, to the next row (up to the last); chainSeconds after the last shoot-down it goes back to the first row.
Any Object$chainRow < (dataCount('Kill Chain Multipliers') - 1)- Variable
$chainRow- Operator
+=- Value
1
- Timer Name
"killChain"- Repeat Every (s)
@self.chainSeconds- Ring Once
Yes
- Variable
$chainRow- Value
0
Kill Chain is the clock, and it does two small things.
When shotDownScored arrives, it moves $chainRow one row down the table, unless it’s already on the last. The If counts the rows with dataCount(), as in Weapon Level, so the last row is one less than the count. Then it starts a timer, killChain, set to ring once, chainSeconds from now. A named timer is always a Recurring Timer, and Ring Once makes it ring a single time.
That timer is the whole trick. Each shoot-down starts it again, and a timer started again starts over. So as long as you keep shooting, it never gets to ring. An enemy breaks up. Half a second goes by, then a whole one. Another breaks up, and the timer’s count starts over from nothing.
Stop shooting, and it rings. 1.5 seconds after the last shoot-down, Kill Chain sets $chainRow back to 0. The chain is broken.
Make it as an Empty Logic Component, with the Shared Variable chainSeconds. shotDownScored is in the Add Event list now, since Score sends it.
Its If’s condition is typed whole, brackets and all, and its one step goes on the True line with Add Inside Then. That Change Variable wants += · Add. Start Recurring Timer comes from the Action List, so Connect to Sequence joins it after the whole If, on the main line. Type "killChain" into Timer Name, with its quote marks, @self.chainSeconds into Repeat Every, and pick Yes for Ring Once.
For the second Event, pick Recurring Timer in Add Event, choose Type a timer name…, and type killChain. Its Change Variable sets $chainRow back to 0.
FighterMilestoneWing CannonsRepair CrateAttach Kill Chain to Game Rules.
Run the game, and fly into the V of five. Hold Space and sweep across them. Watch the score. Each enemy in a quick run adds more than the one before.
9.5 The Color
The chain works now, but only the numbers show it. The score should show it too.
9.5.1 Kill Chain Color
Colors this text by the kill chain: the scoreColor of the chain's row of the Kill Chain Multipliers table.
Any ObjectText / UI- Component Value
self.text.color- Value
data('Kill Chain Multipliers', $chainRow, 'scoreColor')
Kill Chain Color sits on Score Text, and it doesn’t watch the clock or count anything. It waits for one thing: $chainRow to change. When it does, it reads the scoreColor from the chain’s row, and sets the text’s color to it. Nothing else touches the color.
So the chain and the color never talk to each other. They both read the same row.
Make it as an Empty Logic Component. It needs the Text / UI of the Object it’s on, so the Logic can reach the text’s color. Press the + on its Components card, and pick Text / UI under Component types. The row reads self.text.
Add Variable Changed, and pick chainRow in its second window. Its one step is Change Component Value. Type self.text.color into its Component Value box, and pick it in the list that opens. Its Value is the card’s data(), reading scoreColor this time.
Window / UIUIX 32, Y 32SCORE {$score}15Bold#FFF4CFWrap to Width240TextflightmenuChoiceOpen Score Text, and attach Kill Chain Color in Logic. It has nothing to set.
Save, and run the game.
Fly into the V of five and sweep your guns across it. SCORE turns yellow, then orange, then red, as the enemies break up one after another. Let the sky go quiet. A moment later, the score is cream again, as if nothing had happened.
Watch for each of these, one at a time.
- Shoot down one enemy, and wait. The score climbs by its points, as before, and SCORE stays cream.
- Shoot down two quickly. The second adds twice its points, and SCORE turns yellow.
- Keep the chain going. The third turns it orange, and the fourth red.
- After the fourth, the chain stays red. A fifth quick shoot-down still counts four times over, and never more than that.
- Stop shooting. About 1.5 seconds after the last shoot-down, SCORE goes back to cream.
- Catch a pickup mid-chain. It adds its own points, with no multiplier.
An enemy is scored, and the chain moves on a row. A timer starts over. When it finally rings, the chain goes back to the top. And the score’s color follows the row, all by itself.
The idea underneath is one you met in Chapter 8: keep what changes in a table, and point at it. Here three pieces of Logic share one row. Score takes its multiplier, and Kill Chain Color takes its color. Kill Chain only moves the finger.
And the chain counts rows, not multipliers. Give two rows the same multiplier one day, and the chain still climbs through both, and the color still changes.
9.6 If It Didn’t Work
A kill chain is fast, so it can be hard to see what went wrong. Shoot one enemy at a time first, and watch.
Press Play, and a window called Can’t run yet opens? Its message names the piece and what’s wrong with it, so fix that, and press Play again.
The score stops climbing when an enemy breaks up? Look at Score’s first step. Its Value should name the table exactly, Kill Chain Multipliers, in quote marks, and its Variable should be multiplier. Then check that the old step is joined after the new ones, not left loose.
Every enemy counts once, however fast you shoot? Maybe Kill Chain never hears the message. Score’s last step and Kill Chain’s Event must both read shotDownScored, letter for letter. And Kill Chain belongs on Game Rules.
The chain climbs, but never breaks? Look at the two timer names, Start Recurring Timer’s killChain and the Event’s killChain. They must match, and Ring Once should be Yes.
The chain breaks at red, mid-run? Perhaps Start Recurring Timer is inside the If, on its True line. At the top of the chain the If is false, so no shoot-down starts the timer over. It belongs below the whole If, on the main line.
The points multiply, but the color stays cream? Look in Score Text’s Logic for Kill Chain Color, and then at its Event’s block, which should name chainRow.
Each of these is one fix. Make it, run the game again, and you’re back with the chapter. The catch-up download in the Goal is this chapter’s game, finished, if you’d like to compare.
Make the chain your own. Open Game Rules, and under Variables, type 3 into chainSeconds’ Value. How does the chain feel when it’s this forgiving? Or give the table a fifth row, x5, with a multiplier of 5 and a color you choose. Kill Chain reaches it with no change at all. Put things back before Chapter 10.
Still stuck? Search the manual, or ask in the Myth Engine Discord (opens a new tab).
Your score has a temper now: it warms as you get quick, and cools when you wait. In Chapter 10, your Fighter learns to slow down, on purpose.
