Adding characters is annoying
Extra characters are somewhat a common want for fangames, even if I really haven't seen that many out there with new ones, people might want to add mighty or shadow themselves or something like that to their games. Unfortunately, it takes a while for that to happen, since characters are almost always referenced via hardcoded tables in the locations they're used. This ends up with having to run around the codebase trying to find all the character specific stuff going on almost everywhere to make the game stop crashing. That's... not desirable for an engine designed to be used for fangames (hence the lack of pixel-accurate precision), so ideally this should be cut down somehow, here's the idea:
- Remove Player.gd's character table
- It's redundant, and while it may save your fingers a tiny bit, it only adds another thing to add your character's entry to, and is slightly confusing since it lacks
NONEas an entry and therefore not interchangeable. This change would mean that technicallyNONEcounts as a valid character if you force it via code, but that would be much simpler to grasp in my opinion.
- It's redundant, and while it may save your fingers a tiny bit, it only adds another thing to add your character's entry to, and is slightly confusing since it lacks
- Make a new character node class to contain various properties that scripts can grab from
spriteController- This includes palette textures, name, idle sequence, the works. This is probably the most important thing here since at the moment, if a new character isn't referenced in a certain table, the game crashes, which is kinda dumb.
- Make the stats table independent of character
- Stats right now are annoying for having character specific logic that really only matters for Knuckles and Knuckles only. I can see people wanting to mess with the stats, but since Knuckles is the only character in classic sonic to have character-specific stats, I think it's worth just making it hardcoded or a boolean to use his stats in the
spriteController, as I feel it's safe to assume that most users won't want to mess with them, at least to be consistent with all the other characters.
- Stats right now are annoying for having character specific logic that really only matters for Knuckles and Knuckles only. I can see people wanting to mess with the stats, but since Knuckles is the only character in classic sonic to have character-specific stats, I think it's worth just making it hardcoded or a boolean to use his stats in the
- heavy, HEAVY commenting
- A wiki article on doing so would be best, but unless a team member makes the article after the merge request for this, I assume I'm going to be alone in explaining everything in the code itself. Information on the character system would best be told than just simply observing what is there until it works in some strange way.
At the end of this, Air.gd's abilities, Global.gd's character list, and Player.gd's switching logic should be all the code changes that need to be made for every character added. I'm not entirely sure why I decided to make this given I plan on doing all this stuff right now... but it is what it is.
I've had some pretty similar thoughts about how this yeah. The most obvious to me was just that character-specific code probably shouldn't live inside the more standard state code and instead stuff like air.gd should be able to have a list of callbacks for each state. For instance Sonic would have one for air.gd that handles things like double jump/jump dash and he would have one for ground to handle peelout and another for ground to handle spindash (which most other characters would also share aside from maybe a Sonic Advance 1 style Amy).
And while we are at it we could make characters be able to override states process scripts entirely so that characters like Charmy for instance could just swap out the normal grounded state for one that handles Charmy's unique jump action.
instead stuff like air.gd should be able to have a list of callbacks for each state. For instance Sonic would have one for air.gd that handles things like double jump/jump dash and he would have one for ground to handle peelout and another for ground to handle spindash (which most other characters would also share aside from maybe a Sonic Advance 1 style Amy).
this is mostly vvhat cc does, but the big thing for me is that simply adding the character takes time going through every instance of character specific code, and the more complicated stuff is usually left vvithout comments. I'm fine vvith the user having to go to air.gd to add their ability since that's not complicated and mostly on them to do, but I don't think I like going through and giving them hitbox, super, and more annoyingly their "stats"
the changes planned make most of these things properties in a "Character" node type, I don't plan on adding a script to each spriteController for realsies (though a script is used to make the custom node, but if the user vvishes they can extend it to their ovvn. Maybe it's vvorth more of a discussion on if callbacks like this should exist as the engine as a vvhole seems to disagree vvith this, vvith the only example of it being vvith stuff like action_jump(), and even then it's used more than just once, something that these callbacks definitley vvon't be.
Part 1 and 3 are done. 2 I'm not sure how to implement, so I'll leave this issue open until such a time comes that I or someone else implements a more modular system. 4 is unlikely to ever be done as writing the wiki is a pretty major time commitment.
2 I'm not sure how to implement, so I'll leave this issue open until such a time comes that I or someone else implements a more modular system.
I was working on a system like this for a little bit, but since I'm not working on it anymore and you're absolutely picking up the slack (holy moly) I might as well tell you how I was going to do it.
Air.gd is of course going to be intact, unless we decide we suddenly want CC's callback system, but properties like hitboxes and knuckles' properties would be set as @export variables in a Character node class, replacing spriteController. These properties are then set to their respective player variables---making new ones if they don't---and using it.
I'll post my old class code here since setting up the hitbox group was real annoying and really necessary, but anything that had some form of character check (even if it's just for one character, except maybe tails' tails) be replaced with checking these properties, or some version of them.
also Character.gd is a .txt file because of this stupid thing
sorry about that Character.txt
@NeonSRB2 When you have a chance, look over the Player-Refactor branch to see where we are headed on this effort so far and if it appeals to your sense of how things should be. Still more work to be done there and it's on hold for a couple weeks while I work out personal stuff, but I'd be interested to hear your thoughts.
I do wonder why all the character-specific properties weren't bundled into Resource files to begin with. Seems like the go-to choice for configurability.
Presumably because you want your variables close by while you are still drafting your core engine code. That and Renhoex was learning Godot by making this engine in the first place and didn't know every single feature while working on it. Besides, it doesn't really make that much sense to use resources for everything when you can just use exported variables instead. Yeah, these are hard coded, but what I'm saying is that the right answer isn't always obvious in the moment.