This is an example of how to write reusable fight mechanics code using only Ink's Tunnels feature, no Functions. The code is documented with inline comments showing what's happening at each step. There are other code examples of fight scene scripting using Functions, but I wanted to share one that uses Tunnels to illustrate that there are many ways to do the same thing in Ink script. This code is pure Ink script and it's playable if you copy and paste the code below into Inky.
Notes:
Code:
// Initialize the variables.
VAR myHealth = 0
VAR opponentHealth = 0
VAR opponentName = ""
// Set the player's health for the entire game.
~ myHealth = RANDOM(70, 100)
// Start the game by sending the player to the first knot.
-> Main
// The first knot and story introduction.
== Main
I am walking my dog.
You see something approaching.
// If the player chooses "Fight" we use a tunnel to visit the generate opponent knot and then use the same tunnel to visit the reusable fight logic knot.
+ [Fight] -> GenerateOpponnent -> FightLogic
+ [Keep Walking] -> Main
// Reusable knot to generate a random opponent each time a new fight is started.
== GenerateOpponnent
~ opponentHealth = RANDOM(70, 100)
~ temp randomOpponentName = RANDOM(1,4)
{
- randomOpponentName == 1: ~ opponentName = "monster"
- randomOpponentName == 2: ~ opponentName = "cat"
- randomOpponentName == 3: ~ opponentName = "giantess"
- randomOpponentName == 4: ~ opponentName = "werewolf"
}
// End of tunnel statement to send the game flow back to where the tunnel started.
->->
// Reusable fight logic. Punch is the only type of fight choice in this example, but we could add more attack choices and add a defend and run option as well. We could also add logic to show different types of attacks based on what type of weapon the player is holding.
== FightLogic
I have {myHealth} health. My opponent {opponentName} has {opponentHealth}.
+ [Punch]
You decide to throw a punch.
// Random punch damage given.
~ temp punchDamage = RANDOM(5, 15)
// Use a tunnel to visit the calculate damage knot after every attack.
-> CalculateDamage("opponent",punchDamage) ->
You dealt {punchDamage} damage to your opponent.
// Use a tunneel to visit the check health knot after every attack.
-> CheckHealth("opponent") ->
They now have {opponentHealth}.
Your opponent punches you back.
// Random punch damage taken.
~ punchDamage = RANDOM(5, 15)
-> CalculateDamage("me",punchDamage) ->
Your opponent dealt {punchDamage} damage to you.
-> CheckHealth("me") ->
You now have {myHealth}.
-> FightLogic
// We send "who" as a parameter so we can use this knot for calculating damage to both the player and the opponent.
== CalculateDamage(who,Damage)
{who == "opponent":
~ opponentHealth -= Damage
}
{who == "me":
~ myHealth -= Damage
}
// The end of tunnel statement sends the game back to where the tunnel was called after subtracting damage from either the player or opponent.
->->
// We use "who" here as well.
== CheckHealth(who)
{who == "me":
{myHealth <= 0:
// If the player's hit points are zero, the game ends.
Oh no, I'm dead.
-> END
}
}
{who == "opponent":
{opponentHealth <= 0:
// If the opponent is dead, we send the player back to the first knot.
Your opponent is dead.
You go back to your dog.
-> Main
}
}
// The end of tunnel statement sends the game back to where the tunnel was called if everybody is still alive.
->->
Notes:
- The code above uses advanced Ink features including Tunnels, Variables, Temporary Variables, Switch Blocks, Knots With Parameters, and Random(Min,Max).
- The reusable knots GenerateOpponnent, CalculateDamage(who,Damage), and CheckHealth(who) are meant to be called from Tunnel statement so that they can be used anytime they are needed in the game.
- You could probably chain CalculateDamage(who,Damage) -> CheckHealth(who) with some code and text modifications if it better suited your needs.
- There are many possible ways to create game mechanics in Ink. This example is intended to show one way to handle a fight without Functions while mainting reusable code. You should use whatever methods work for your story, and the code that is easiest for you to write and maintain. Reusable code is generally preferable to re-writing the same logic over and over again in your story.
Last edited: