The Mugen Fighters Guild
M.U.G.E.N Central => M.U.G.E.N Discussion => Development => Topic started by: 3 on August 03, 2012, 04:31:10 am
So after playing a whole bunch of RTS games, I thought it'd be interesting if fighting games had the same element of progression. I'm a relative novice to MUGEN scripting, and chances are someone has a better idea of how to implement the sort of thing I'm gonna propose, hence this post.
A description of the system:
The character has a "tech" meter, which gradually fills over time. The character can trade power for tech via a charge anim, or can increase the general rate of tech growth by controlling the screen with "nodes"; the more space you control, the faster tech grows, but nodes can be destroyed by being hit. Node influence doesn't overlap with existing influence, as the point is to cover the screen with influence, not spam nodes on top of each other.
When the tech meter is full, you can level up your character; doing this unlocks a previously locked move (which you select right there, although your choice is concealed from the opponent), increases your max power by 1000, and increases your base attack/defence values slightly. There are 5 levels in all, and each one takes more tech to get to.
tl;dr IaMP spellcards meets Zerg creep
Thoughts on how to implement this system:
A node is a helper in an arbitary state (10000 for example purposes). When placed, the node goes into anim 10000 which shows a visual representation of how far the node's influence has spread, has clsn2 at the center, and has clsn1 slightly smaller than the space it controls. The node's contribution to tech is simply AnimElem or floor(AnimElem/10)*10 or whatever works out best (the anim loops at the end obviously).
State 10000 will have a ReversalDef that triggers only on collision with another node; this freezes its animation via putting it into anim 10000+AnimElem, said anims just being static versions of the regular one at different sizes (so anim 10001 = 10000 AnimElem 1, 10002 = 10000 AnimElem 2, etc.). This way I can stop node influence from overlapping. It's not perfect; ideally I'd be able to make them not overlap but still extend in areas they don't overlap... I guess I could do that by placing an utter fuckton of helpers at different intervals and removing the ones that overlap, but that's ridiculous. There has to be a better way.
Also the node states'll have a HitOverride that forces it to kill itself if its clsn2 is hit by anything, so the opponent can get rid of them, and also so they can remove themselves if they're placed within existing influence or obsolete (obviously I want to limit them as much as I can).
Thoughts? Could I do this with explods or something instead? Will it interfere with AI even if the states are idle? Am I missing something critical?
All feasible but only functional for a single run through. You'll lose it once you complete arcade mode basically.
Number of nodes, where they live on screen, what stage they're at can all be completed with bitwise shifting (which i don't really understand still) but you could section off 30 or so variables on the parent to deal with each helpers position and size by using that then you'd be able to respawn them with the same values/settings in the next rounds.
Explods is posisble too, but far far more difficult because they have no awareness of other explods, so you'd need to sort out position+size and do lots of compare shit, it would be more work.
Yeah, I was planning on it being a per-match thing. But I forgot that helpers are cleared between rounds, and I forgot that MUGEN had proper bitwise operations, as well, so that's all helpful. If only it had actual arrays things'd be a lot simpler...
I had a related, although really dumb practically speaking, thought about how one could implement this sort of thing more neatly. Basically it'd involve each node being made up of a bunch of connecting pieces (say center, edges and corners). You'd have a different state and a different anim for each of these, plus a set of "joined" pieces. Initially a node would just be the center, and as it reached different stages in its anim, it'd spawn the other pieces around it.
The crux of the idea is that each individual piece would check on contact with another piece (via the aforementioned ReversalDef) the state of said piece and spawn the appropriate "joined" piece, then both pieces would destroyself (I guess MoveReversed would work for the passive piece). If that sort of thing could work out, it'd be totally possible for there both to be cohesive, non-overlapping graphics, the potential for nodes to spread influence in any and all directions, and a limited number of helpers (since they'd constantly be "merging" into a smaller number of individuals). On the logic side of things, you could have a heirarchy: the smaller pieces are always overridden and absorbed by larger ones, and "equal" pieces just sit next to each other and do nothing.
I don't know if it's the sort of thing I'd be willing to implement as far as my plans go (too much boilerplating) but it might be of use to an unconventional character. Better here than in my head.
On the bitshifting front, I was trying to figure out a way of forcing each node into one var. Mixing positive and negative values in a single var is problematic to say the least, so accounting for negative pos values might be an issue. But if I deliberately give the pos values a larger address space than they need, I can translate. For instance:
12 bits <- 12 bits <- 5 bits <- 1 bit
x pos <- y pos <- node stage <- existential doubt
If the x/y value is negative when recorded, it's flipped to positive and has 2048 added to it. When the system replaces the nodes at the start of a new round and it finds a value >2048, it'll take the 2048 off and flip it to negative. I essentially have four addresses; positive y, negative y, positive x, negative x, even though all the values are actually positive. I think that'll work.
12 bits should be enough for safety's sake, especially if I do something hackish with y values (like destroying any nodes placed above the character's jump height, in case something puts you into a falling state off the top of the screen).
State 10000 will have a ReversalDef that triggers only on collision with another node; Too bad reversaldef is activated when being hit by an attack, and nodes are not attacking. If they were attacking, they would hit the player, and other nodes, and that's no good. Additionally, a reversaldef would reverse attacks coming from any source, including enemy helpers or players, totally breaking them.
I guess I could do that by placing an utter fuckton of helpersNot really, there is a global helper limit of 56, that's 28/player if you ignore simul and don't want to cause the enemy to fail spawning his own helpers.
There has to be a better way.You can have only one helper, make it display explods over the area influenced, and store the data about the areas in the helper's variables. 60 variables*31 bits = up to 1830 possible bits of data to store, for example as a 60 (width)*30 height matrix that covers the stage. With explods of 10*10 pixels, that would be able to cover 600*300, which is about 2x1.5 screen around itself.
As you want to avoid overlapping, you should store data in a format of 1 bit for each possible area (has influence or not, 1/0), instead of storing positions.
Explods cannot be hit, though, so you will need to find a different way of reducing influence.
One more thing : You will not be able to detect enemy influence areas this way, so your influence and enemy influence will overlap. If you want to be able to detect enemy influence, you'll need to store all the data in root variables. Same if you want the data to carry over to the next round.
You'll lose it once you complete arcade mode basically.also when you character select after losing.
I like it. I can work with things resetting round to round, but the players' influence overlapping is more of a problem. I'm guessing it lies in not being able to properly redirect to the equivalent enemy helper?
There could be a couple of other possibilities. One way of getting around the reset might be to purge all root vars and use them as temporary storage for the helper's vars until the start of the next round, preserving the matrix. Obviously that might cause other issues.
The other idea is a combined approach, using multiple helper nodes and explod influence. A controller handles the influence growth; meanwhile, each node checks around itself for enemies in the appropriate anim, and removes them if they're too close. The positions of each node are stored in the root player (and it might as well be the player comparing node positions, not the nodes themselves). This may result in a no-man's-land of sorts between p1's nodes and p2's nodes, but it'd stop them from overlapping, simply because they couldn't actually be placed close enough to overlap. Or is there a functional issue with using helpers at all for this?
I'm guessing it lies in not being able to properly redirect to the equivalent enemy helper?Yes, double redirection (enemy,helper,var(x)) is not supported.
There could be a couple of other possibilities. One way of getting around the reset might be to purge all root vars and use them as temporary storage for the helper's vars until the start of the next round, preserving the matrix. Obviously that might cause other issues.Yes, this is possible but if your character doesn't use too many variables, I'd recommend using root variables in the first place. It'll let you read the influence of the opponent.
Or is there a functional issue with using helpers at all for this? Not really, but you don't need helpers. Well, not more than one, that is. One helper can spawn all the explods to everywhere you have influence and do all the calculations related to spreading out as necessary.
The only reason why you'll need to use a helper is because you will need to create changestate loops to process data (both for spreading and displaying explods), and you can't do that in the minus state of the player.
Any more helpers will make it more complicated for no reason, I think.
Removing influence will be a big pain, though, you'll need to code to detect every possible attack anim in your full game and code the position of clsn1 on the attack into the calculation. Obviously, it won't work on opponents outside of your game because you have no way to detect the area they are hitting.
Even if a single-helper approach is more elegant, surely it'd be easier to just use a hitoverride on the nodes themselves? As I said earlier, the nodes can be destroyed if they're placed in an obsolete location or too close to an existing node, so the chances of them getting out of hand are slim.
My plan as it stands is something like this:
Root: Free vars bitshifted to bools. Bools used to construct array made of cells. Array can be updated in -3.
Node = Helper, is destroyed when hit by non-projectiles (to avoid accidentally blocking projectile helpers) via hitoverride. Can be placed freely. Makes sure it's within the bounds of the array when created, otherwise it's destroyed. Does nothing else.
Controller = Helper. Runs a loop through three states:
1. Get position of any helpers within the array, and check if they're nodes. If they are, destroy them if invalid, then check if they're over x ticks old and spawn influence in the nearest cell if they are.
2. Spawn influence in cells nearby to nodes and existing influence, but not too far, and not overlapping cells influenced by the opponent (if applicable).
3. Update graphics by spawning explods in filled cells and (maybe) explods in cells adjacent to filled cells (edge effect).
This should allow some compatibility with characters not coded to fit the system.
Thanks to the both of you for the help so far; it's made at least the theoretical part of this idea go by a lot faster.
If they are, destroy them if invalidA helper can't destroy another helper, you have to make the nodes self-destruct based on a variable set in the controller instead.