How to integrate a "wind up" firerate in a Top Down shooter

Good morning! I appologize in advance if this post sounds confusing or somewhat inept, and I can provide more details on request, but for now I can summarize what I am dealing with right now.

I’ve been developing a top down shooter recently with a plan for multiple classes to choose from with different weaponry.

As a result I’ve been practicing to write my code with things like composition in mind with a goal of modularity among player and enemy entities.

I also had an idea for a planned class to have a firemode for their weapon that “winds up,” increasing firerate over time, and I was wanting to ask about how I could possibly go about integrating that into my current setup for ranged attacks (This logic happens to be in a Marker2D node with a Sprite2D and another Marker2D, denoting the “barrel of the gun,” as childen. The script for this Marker 2D is just programmed right now to instantiate an Area2D based projectile or a raycast depending on a bool toggle, it only has a semi-auto firerate at the moment).

I was not just wondering about how to integrate this on its own, but also set it up so that way I can toggle the “wind up” feature and also just toggle between automatic and semi-auto firemode, all so that way I can keep things customizable (unless I have some wierd view what what can be customizable or modular.)

Any insights or help are very appreciated. :3

Hi,

What I would do is probably have a generic system that has a firerate value and a wind up speed value. For instance, a wind up value of 1 would mean the firerate increases by 1 after every shot. Setting that value to 0 would then result in no wind up at all, which allows you to toggle it on/off (you can also have a boolean use wind up in case that’s more convenient for you).
The only thing to keep in mind is that, since your firerate will change at runtime, you need to keep a track of the default value and update a value that’s dynamic. Pretty easy to do, simply use two variables, one that’s exposed in the inspector and that will not change, and another that will be dynamic and can be reset anytime.


The automatic/semi-automatic modes are a bit more tricky as it needs to be connected to the player inputs somehow. Automatic fire will require a boolean called something like is firing that you toggle on input pressed or release (and obviously when there’s no ammo left, but that’s another topic), and you fire using your firerate while that boolean is true.
Semi-automatic only require one shot on input pressed, which is theorically easier to do as you only have to fire once and then not care about anything else.

You should be able to make a generic system fairly easily for fire mode using an enum or something allowing you to specify for each weapon how it behaves. Then, in your code, adjust the behaviour in the fire starting function depending on the fire mode.

Let me know if that helps, my answer is pretty vague I think but feel free to discuss it a bit more.

1 Like

I’m awfully surprised at the response time for this, and how detailed it is. I think my biggest concerns are how to integrate firemodes into the input handling (as you mentioned) and/or if I should separate the logic for these into different scripts or classes or something. I currently have the input logic in an _input function for the aforementioned semi-auto system, which checks if my fire action is pressed and then does the spawning logic for the bullet/raycast. Other than that I think I can handle the rest for the wind up part, since it is meant to be a simpler system and also doesn’t use some sort of ammo system.

Haha, well I’m working on a game with a generic range weapon system so I’m very interested on that topic :smile:

I don’t think you need a separate class, tbh it feels a bit overkill as your system does not seem that complex (code wise). My current has only one class that handles everything, and I’m using a few booleans like is_firing, is_charging (some of my weapons needs to be charged before firing), etc. I also have a class that represents a weapon but that only stores data so no particular behaviour here.

My suggestion would be: use two functions, one for input pressed and input release (you could also call those “fire start input” and “fire stop input”), call those inside your _input function depending on what input you receive.
In any case, you will probably want to fire a bullet on start input. Then, if the weapon is automatic, you can start a timer of some sort, and fire more bullets inside the _process function (or timer callback, depends on what’s best for you, but you get the idea).
Releasing the input will do nothing for non automatic weapons. For automatic weapons, it will simply stop the timer and no more bullet will be fired.

Not having ammo in your game will indeed make your life easier, but it’s definitely not very hard to implement if you need it someday. Also keep in mind that if you feel like your code becomes a mess as you have too much features in it, you can always refactor your weapon system later on. I tend to think that this kind of system should be kept as simple as possible and become complex only if that’s required, but no need to over complexify the code here imho.

1 Like

I agree with that last part. I’ve been trying to not make things too complex and spaghettified (hence me practicing composition by separating thigns into a lot of nodes) but I definitely have a vision on features. For now I’ll probably want to set up the system to have auto vs semi auto and then expand to my wind up idea. Ill check in on here later if I have further questions because you’ve been very helpful :3

Thank you for your time!

1 Like

You’re welcome. Also feel free to send me a direct message if you find that more convenient to discuss that specific topic.
Writing bad code is a mandatory step to becoming able to write good code, so I’d say that’s a good thing haha

1 Like

Keep weapon logic separated from any visual representation. Have a single configurable class (can even be a resource), you set its parameters and trigger state, and it emits a signal when bullet is supposed to be fired.

Coming back to this a little later, I managed to get the ball rolling on experimenting with some new fire modes.

I mainly added an exported enum with the types I want and can change in editor, and then had logic to check what the enum is set to and execute functions based on that. I also added a timer with a configurable length that connects to a timeout method that had the checking logic I mentioned before and allows for things like refiring a bullet if the fire button is still held, thus adding in full auto. I even managed to add a burst fire mechanic with this system, which is also something I wanted to try adding. I feel like I have the foundations to put in that Wind Up mechanic that this whole post is about.

As for this, I was already planning on a FSM to manage entity states a bit easier. Would be a good ides to decouple the ranged attack logic into a state (for now the states are being made as extensions of Nodes, which is what I see a lot of people do for this in Godot) for the state machine and have the few external references to it be the “hand” node that the code is attached to right now (so that way I can have some sort of point where I can reference rotation and position from when spawning projectiles)?

It doesn’t have to be a state. Just make it a plain generalized object that’s fully independent. Nothing in weapon firing logic requires it to be coupled with anything else. It will also be very easy to unit-test it this way.