I didn’t realize how long it had been since the last post. It felt like we hadn’t done too much that was worth sharing. However, after looking back at the commit history, there’s a lot of cool things to talk about. So here we go!
We were planning on adding special weapons to the game, besides the balanced / agile / heavy / rods that we already have. These weapons will be obtainable by progressing through particular dungeons. Without spoiling too much on the “special” mechanics of the bomb, we wanted to at least explain the direction we were thinking of the bomb.
Unlike bombs in Zelda games, bombs in Violet will be on the heavier side. Picking up and throwing bombs will take some time to do. However, if you can land an attack with a bomb, it currently deals 150 damage (7.5 hearts)! That is the equivalent of a S ranked Heavy weapon’s damage output! The blast will disperse those that collide with the bomb at high speeds. The closer you are to the blast zone, the faster you’ll move! The blast of the bomb also stuns, There’s a bit of risk using the bomb, but there’s a good amount of reward, as well as a ton of fun to pull off landing the explosion!
Not to be confused with “good” animations. This simply means we added some animations to things in the game there were originally instantaneous. The aforementioned picking up and throwing now has animation. Objects with little weight will be quick to pickup and throw, while objects with heavier weight will be slower to pickup and throw. We didn’t want to be obnoxious with the speeds, so they’re still pretty generous. It does give a little more risk to picking up and throwing things, however. Once the action has started, it can’t be canceled (unlike other actions in the game).
The other animation we added was removing arrows from enemies. Again, this used to be instantaneous, which made shooting arrows in your enemy, then removing them immediately pretty OP. However, with an animation, there’s a little more risk involved in removing arrows from your enemy. We didn’t want there to be no reward (other than getting your arrow back) — so we improved upon the “stuck arrows” mechanic (special thanks to a friend for these ideas).
Improved Arrow Mechanics
Along with the animation that we implemented, there are three new risk / reward mechanics to “stuck arrows”:
- Originally, each arrow stuck in an enemy would deal 2 damage per second per arrow. There was no cap, which would make fighting Centaurs, for example, really easy to defeat by shooting, say 30 arrows, and then waiting for it to bleed out. Now there’s cap at 5 arrows. The player can still of course “abuse” this mechanic by waiting the enemy out — and that is fine with us! Because…
- Each arrow in an enemy will make them attack faster (capped at 5 as well). Arrows in an enemy will result in them getting more aggressive as they bleed out. Too many arrows in your enemy at once will also make it harder to remove them as well, because you’re enemy will be attacking much faster.
- The reward though for removing an arrow from an enemy is that it will deal 1.5 times the damage coming out than it did going in. So, if you shot the arrow with a bow that deals 30 damage, it will be removed at a damage of 45. Not too shabby!
We also fixed an issue where fire arrows getting unloaded would leave behind the particle of fire. After thinking about it for a while, the easy fix ended up being if an arrow collides with the unloaded zone, instead of unloading the arrow and trying to properly remove the fire particle, the arrow could “break” and we no longer have to keep track of the arrow or the fire, because a breaking arrow destroys itself and properly “puts out” the fire object.
Improved Shield Mechanics
One thing I’ve been struggling with for a while is “what’s the point of leveling up a shield”? Originally, there was no advantage in having weaker types of shields. So, it would be to the player’s benefit to ignore the Wooden Shield, since they are the weakest, and simply go for the more powerful shields. However, we improved on the shield mechanics below:
- If a shield type is overall weaker in power (e.g. Wood Shield), it is also lighter to carry. However, if a shield type is overall more powerful (e.g. White Shield), the slower the player will move as they are holding the shield.
- We were originally mimicking Breath of the Wild‘s “weapon hitting shield mechanic” pretty closely, in that an agile weapon could still hit a shield a few times to eventually knock an opponent down. We ended up redefining this to be:
- If the attack power of a shield is greater than the weapon attacking it, the holder of the weapon attacking will automatically stun.
- Heavy weapons hitting a shield still apply though, where the holder of a shield will be stunned.
- But, if the shield happens to be greater attack power than the heavy weapon’s damage, then both parties will be stunned.
- Parrying or reflecting no longer damages the shield to rank down.
Leveling up your shield is important now, because weaker weapons attacking it will be vulnerable to your strengthen shield. It also makes agile weapons a terrible choice for fighting against enemies with a shield due to its lighter damage output (because of its faster attack repetition).
This part is a little more technical. So if that is not your thing, skip to the next section 😛. Game Maker Studio 2 (GMS2) gives the developer the ability to activate / deactivate objects. Objects that are deactivated are still in memory and can be turned on easily, but will not be processed each frame of the game. This is how we are able to make the open world part work is by only activating objects we need and unloading them when we don’t.
However, GMS2 unfortunately gives us no control over when an object is being activated or being deactivated. This is important because let’s say we have a fire arrow we shot and it’s burning. Normally a fire arrow will burn up in 10 seconds. Let’s say we “unload” the fire arrow by going somewhere and then a minute later we come back to the area where the fire arrow is at. Currently, the fire arrow will still be burning. If GMS2 had an event to say “hey, this fire arrow just came back into play, let’s do something about that”, we could say if the fire arrow has been around for more than 10 seconds, we automatically destroy it after reactivating it, since it would have burnt up by then.
I submitted a feature request to the Game Maker that simply was replied back with “we have plans on adding this, but have no time frame on when that will be complete”. With this reply, we decided to roll out our own event system. It’s pretty simple, really. Basically, we have a wrapper function that before it calls GMS2 activation / deactivation routines, we run our event that should “do something” when an instance activates / deactivates. We’re currently using the
path_ended event, since we aren’t using GMS2 built in path variables, and therefore, it’s a free and open event to use. So, if an object gets activated or deactivated, it will run the event with a string saying what kind of activation it is. We have these constants:
fullyActivated – an instance is fully activated and collisions will work
activated – when an instance is about to be activated.
activatedFromPlacholder – when an instance is about to be activated because we are coming from a dialog state
activatedFromPause – when an instance is about to be activated because we are coming from a pause state
deactivated – when an instance is about to be deactivated
deactivatedFromPlacholder – when an instance is about to be deactivated because we are going to a dialog state
deactivatedFromPause – when an instance is about to be deactivated because we are going to a pause state
Even though this took quite a bit of reworking, it’s now faster than before, as well as giving us more control and flexibility down the road when we add a more robust layering system (think floors in dungeons).
We’ve been needing to add a waterfall for a while now. With the updated zone loading, this had some interesting side effects. The way the game loads in areas is by what we call zones. The game will load the area the player is in, plus a few surrounding zones outside the camera to make things not “pop in”. The original rule was all objects could be no bigger than a zone width and height. This was followed until now, wanting to make a waterfall, since the height of them are larger than one zone height. So, we had to rework how the loader was working to account for larger than zone objects.
The other problem we encountered was an object has two “boxes”: a hitbox and essentially what you see box (the image). For example, the hero has a 32×32 sprite, or rather, the box the image lives in. However, we don’t want collisions to be the entire image which is what the “hitbox” represents. The problem was a function we were using to see what things to “unload” was using hitboxes instead of the actual image. For loading / unloading, we actually want to use the image box, not the collision box. We can see with our debug camera enabled how even though there are four zones loaded, there are a few objects that are on the borders of those zones that are actually loaded as well. That way we don’t get a weird “pop in/out” effect as things get loaded / unloaded.
Other Notable Features and Fixes in the Past Month
- Enemies using weapons will not degrade anymore. Originally it was intentional that enemies weapons degraded. However, with the new merging system, it seemed weird to pickup a dropped weapon of an enemy only for it to degrade after using it few times.
- Lost weapons get picked up by the store. If the player drops a weapon or kills an enemy and doesn’t pick up their weapon, eventually these weapons get “picked up” by the shop keeper. Another reason why it was so important to be able to run our activation events is when these weapons get unloaded, that’s when we decide if it should go back to a shop or not. When returned to the shop, weapons that can be merged will be automatically merged and are able to be bartered. This is an interesting mechanic because weapon merging shops also become bartering shops with potentially better weapons for the player.
- Attacking with Elemental Rods. Fire, Water and Ice Rods originally had no collision on them and the only way to attack with rods was with the projectile they shot. We added collision on these rods. However, elemental rods are not meant to be used as melee weapons. As a consequence, if the player attacks with rod, it will drop in rank immediately.
- Updated enemy chasing logic. Originally as soon as enemy was hit, all enemies nearby would “magically” be triggered to the chasing state as well. Now, enemies will look in the direction of the enemy in danger and determine what to do next. Also, if an enemy is chasing, and another enemy notices their friend chasing, they’ll look in their direction to see if they should chase too.