After all my talk last week about new mechanics I was thinking of implementing, I went off and did something completely different to the mechanics I had listed…
Ever since I started making Ambience, I’ve always wanted to have some sort of ally system where you could traverse the dungeon with a companion, rather than alone. And now, after thinking and programming and debugging for about eight hours straight, I finally did it! The player is no longer alone!
Here’s a short video showcasing the new ally system as it stands at the moment:
Why add allies?
Of course, going through a dungeon alone is much easier programming-wise – but adding in additional characters to help you on the journey has its own benefits.
Firstly, it gives the player a (false) sense of security. Adding ally characters lets me as a programmer ramp up the difficulty more than usual, while the player’s still thinking “hey, this can’t be that bad. I still have my ally here to help me…” In fact, having ally characters to help you out can be a good excuse for making a dungeon much harder without the player realizing it – at least at first. This is especially true late in the story, where you want to throw as many challenges at the player as you possibly can without making the game so ridiculously hard that it becomes almost impossible to progress.
Secondly, it helps with character development. It’s one thing to talk to an NPC a few times over the course of the story, but it’s another thing altogether to have fought by their side throughout the game. Upgrading a character to be a companion with a reasonably helpful and practical role means that the player’s more likely to invest more into that character emotionally. That means that if something were to happen to that character over the course of the story, it would have much greater impact than if you remained reasonably detached from that character all game. (That’s definitely not a spoiler alert, trust me.)
I mentioned earlier it took me eight hours to get this system working, and that’s not an exaggeration. I had to rejig several fundamental aspects of the game’s engine to incorporate allies as well. The especially tricky part about the ally system is the way it specifically disrupted the general turn order, which had to change from “Player – Enemies” to “Player – Allies – Enemies”.
Turns are dealt with in the game using a single, very long script which moves through certain “phases” of each turn until it reaches the end. Phases could include movement, attacking, using items, and so on. Once the player makes a decision, the general way in which a turn proceeds is as follows:
- Allocate attacking and motion “targets” on the movement grid for allies.
- Now do the same for enemies. (This ensures that once the allies have moved, any enemies in the room then attack a newly-adjacent ally.)
- Allies attack, in the pre-allocated direction. (If an enemy is defeated by an ally’s blow here, then dish out experience, reallocate attacking/movement targets, and so on.)
- Allies move. (This means the ally actually performs the pre-allocated movement.)
- Enemies attack. If an ally is defeated here, the defeat is treated much like an enemy, except the ally “flees” to the next floor instead and rejoins the player on the next floor. This was mostly to ease a little of the strain on me programming-wise; to be honest, I’m not sure if I’ll change it – it seems to work okay as it is, although it is a little unconventional.
- Enemies move.
As you can see, there’s a lot to check and a lot to add. Specifically, I had to add steps 1, 3, and 4 in the list above to the turn sequence; I also had to modify the other three steps to take ally motion and so on into account, rather than just the player. (In other words, the enemies should actually be aware of and attack ally characters, rather than ignoring them and only ever attacking the player.) Overall, though, the presence of a plan helped me get through this with relatively few issues.
Then came the surprisingly difficult part… getting the allies to switch places with the player, like so:
Say, for example, you’re walking down a corridor and decide you want to turn around. If the ally character behaves like an ordinary NPC, they’ll just stand there and not move when you try and move towards them. You won’t be able to “push past” them, let alone swap places with them, and you’ll just have to keep moving in the same direction. As annoying as that may be, it also leaves the door open to the player getting trapped in a corridor between two allies who just refuse to budge, so an ally swap system was in order.
Strangely, it took a lot longer than I expected to get this to work. One of the biggest problems I had was with poor ally movement allocation, meaning that allies would often either refuse to move or simply walk on top of each other. Unfortunately, the decidedly feline philosophy of “If it fits, I sits” wasn’t really suitable for this roguelike, so the bug (eventually) got stamped out.
And, finally, I had a working ally system!
I don’t know how much more work I’m going to do on this ally system, if at all. At the moment the allies operate quite independently of the player, healing themselves at the start of each floor (without using up the player’s items at all), and simply running away to the next floor when they get defeated. I don’t know how well received it’s going to be, being such an unconventional way of dealing with allies, but for now it works. And I’m happy about that. 🙂
The Learning Curve
Here’s some thoughts on what I learned from this:
- Don’t skimp out on difficult tasks. I know I’ve said this before, but this is another one of those instances where the fear of failure prevented me from even trying to incorporate allies. Even now it isn’t really a fully integrated system – but it’s still better than nothing, and most importantly it allows me to add yet another layer of depth to the gameplay and storyline. Don’t lose out on those benefits just because you think you can’t do it, especially if you have enough experience to say, well, you probably can…
- Sometimes the easiest-looking parts to incorporate can be the hardest in reality, and vice versa. I definitely found this with the player and ally swapping places, which looked easy but in fact was very tricky to get working perfectly. Likewise, I originally anticipated that the movement and attacking system would be the most difficult and time consuming part, but in reality it was neither. And this was partly because I decided to…
- Always have an action plan. Know how you’re going to implement it before you start coding. Scribble down some pseudo-code, or otherwise a broad plan of how everything’s going to work and interact. I found that having a clear plan for solving a difficult problem saved me a lot of time and trouble in the long run. Conversely, one of the worst things you can do as a programmer is to “go in blind” and simply start programming without any idea of what you’re doing or how you’re going to do it. (Novice programmers, beware! I know I’ve done this before in the past, and it generally never works out well.)
One final note too – I’m always interested in your feedback about the many ideas I like to throw around on these blog posts. So if you have something to say, don’t be shy! Hit me up on Twitter or Reddit, or even just comment your thoughts below. Feedback and interaction are heartily welcomed 🙂