YesNoOk
avatar

Fullgame coding guide for undocumented and non-commonly known problems (Read 10152 times)

Started by rednavi, July 19, 2009, 11:01:04 pm
Share this topic:
Fullgame coding guide for undocumented and non-commonly known problems
#1  July 19, 2009, 11:01:04 pm
  • avatar
  • ******
    • USA
 Fullgame coding guide for undocumented, non-commonly known problems and workarounds on MUGEN.
 Author: Rednavi.
 
 NOTE: This guide assumes you know the basics of MUGEN and maybe some advanced coding aswell, after all you're reading this because you want to work on a MUGEN fullgame right? C'mon, 10 years has passed yet we can count good MUGEN fullgames with the fingers of only one hand, get your ass up and get ready for some reading.
 
 Keep in mind that this guide will help you to know why MUGEN does "X" thing sometimes or why you get "X" result even when you coded everything right.
 
 
------------------------------------------------------------------
 SECTION 1: Special states                                       |
------------------------------------------------------------------


 As the mugen document says there are some common states that don't have a clear transition from one state to another, those are considered special states by MUGEN.
 
 The states which have such behaviour are all the states from the common1.cns that lacks of a changestate parameter, most of them are idle states (All the basic states regarding states that act as transitions to other idle states and a few guarding states) and at first you won't notice how each one is connected to the next one while looking at the coding.
 
 For example take a look at statedef 0, the standing state. Do you see a changestate to the crouching state or to a transition to it? No, not even by using a command trigger or something like that. However, you will still change your state if you try to crouch so... why can you change the state even when there's no apparent trigger for a changestate sctrl? Yep, special state.
 
 This will become very important to know later if you try to add a tag team system into your fullgame, you will see it soon. Anyway, the changestates on this kind of idle states will automatically trigger itself only if your character has CTRL = 1 in that moment, otherwise it will remain in the current state.
 
 There are no changestates for the guard start states either, instead MUGEN automatically puts you on that state if the enemy's current hitdef has a guarddist parameter wide enough for you to be able to block the attack (The attack is close to you so you are in a moment you may or not block the attack, if you are far away from that attack then there's no need to block it as it will never make contact with you). This special changestate won't be active either if your character has CTRL = 0 (Remember this, it will be important for a tag team system aswell).
 
 One thing to have in mind is that there are no turning and crouch turning states, those are actually coded in stateno 0 (Standing state) and in stateno 11 (Crouching state), you can see that there are no animchange sctrls for that in this case, another of the special handling MUGEN has with those states. The character will actually turn during the animation even when no turn sctrl is active aswell. And of course, with CTRL = 0, the turning becomes inaccesible.
 
 The lying down state (Stateno 5110) has a special property, you can get up faster by pressing the buttons and the directions while on the ground. To be able to modify that and give your character a fixed get up time you will have to work around that by either giving the character a huge liedown.time in his [data] section and then add a changestate in state 5110 to the state 5120 triggered by a time trigger or just modify your character and put him on a new state on every possible moment he could be on stateno 5110 and work from there to ahead.
 
 With all that said be ready to have some great headaches if you plan to customize your MUGEN fullgame to the maximum, otherwise if you're just making a fullgame that's closer to a character compilation of your own work and don't plan to make any great changes from there to ahead (Like a full tag team system that doesn't need the use of the CTRL+3 and CTRL+4 debug keys) then leave everything as it is and only modify the neccesary things (Lkie changing animations and whatnot).

 
------------------------------------------------------------------
 SECTION 2: Coding fullgame lifebars and other graphics          |
------------------------------------------------------------------


 Oh sir! This section really needs some explination so get ready to read a little bit...
 
 First I'll show you how to code a fully functional (And interactive and flexible if you want too) life gauge. For that we first need to release a helper that will be in charge of the lifebar graphics, just release it as soon as possible, a roundstate < 2 trigger will work on statedef -2, or just put the helper sctrl on the statedef 5900 (Initialize state) and give it a time = 0 trigger or something like that. It is important that the helper doesn't get affected by any superpause or pause for this to work all the time without any glitches.
 
 Inside the helper's state add this:
 
; LIFE READER
[State 9999, VarSet]
type = VarSet
trigger1 = 1
fvar(0) = (100*root,life/root,const(data.life))
persistent = 1
ignorehitpause = 1

 This piece of coding will constantly read the character's life. Now lets add the explod itself:
 
; LIFEBAR GAUGE 1P SIDE
[State 9999]
type = Explod
trigger1 = teamside = 1
anim = Fxxxx
ID = 11
postype = left
pos = xxx,xx
removeongethit = 0
removetime = -1
bindtime = -1
sprpriority = xxxx
ownpal = 1
ontop = 1
supermovetime = 999999999
pausemovetime = 999999999
scale = 0,0
persistent = 0

 This is an example of how the helper releases the lifebar explod for the player 1 side, the scale is set to 0,0 because the explod will be modified later anyway. The priority, position, animation and other triggers are up to your likings. Before moving forward there's something important about the lifebar gauge sprite in the SFF file used for this, the axis must be placed on a certain spot depending of how you wanna make it change it's size (For the standard style, shrink to the right side as you get damaged just put the axis at the rightmost side of the sprite).
 
 Now onto the deal, to make the gauge itself to change it's size depending of your current life you can just add the next modifyexplod sctrl on the helper:

; SIZE CHANGE
[State 9999, change size]
type = ModifyExplod
trigger1 = 1
ID = 11
scale = fvar(0)*0.005,0.5
ignorehitpause = 1
persistent = 1

 This will modify the gauge all the time to match your current life. These are just common examples and aren't advanced at all, in fact you can do lots of stuff later once you learn more coding like change the color of the gauges on certain status or code a red gauge below the normal gauge to read the damage you got aswell like in the default MUGEN lifebars.
 
 Lifebars are composed of more than gauges right? You can code the power bars on a similar fashion aswell and also code the fonts inside the game so you can have more freedom while working on how to add the name of the characters in the lifebars (Or even add transparency effects and change the name of the character in-game if you wish).
 
 However, for your set to fully work and be completelly perfect im must be pixel-perfect in both sides, what does that means? The distance between elements and the edges of the screen must be the same for both teamsides which is impossible in the common lifebars MUGEN support in case you are coding HI-RES lifebars (Atleast on the gauges is completely true). For fortune this has an easy fix if you plan to code them, the best way is to code them as normal (Different facing on the explods depending of the teamside) and then make a duplicate of the gauge animation and add or rest a pixel (This is gauge style dependant, just try) and then use that animation for the second side, you will get a perfect-pixel placement then.
 
 This may give you a complication, the gauge may be above the lifebars BG now, so to fix that just make a duplicate of the BG and make a FG from it using only the pixels you need to cover on the BG and the gauge itself (Means this FG being above both explods) and done! This can't be noted at all if you do it right.
 
 Something to have in mind is that in order to make diagonal shaped lifebars (Or anything except a rectangle) you will have to rely on a totally different process, instead of using the life reader variable to modify the gauge you will use it to actually display or not certain parts of the strange-shaped lifebar.
 
 For example, you want a diagonal gauge which is 10 pixels long from edge to edge in the bottom of it (We are counting the bottom of it, not the whole gauge so don't count the image size itself because the size will count the beginning of the gauge and the end of it which is the top right edge, which has a different placement than the bottom right end of it) so what we are going to do is to divide that image into 10 diagonal parts and code them as explods. This means each part of it corresponds to a 10% of life from your character so each 10% of life you loose means that a part of the gauge must dissapear, and so the modifyexplod with scale = 0,0 gets in action for that particular sprite. The same for the rest.
 
 Yeah, complicated but really the best way to code a diagonal gauge for anything on mugen. Of course bigger gauges require you to do some real math and divide the sprite into several pieces.
 
 There's something to really have in mind in order for all the animations for the gauge to be nsync (Mainly for animated diagonal lifebars), they must come out at the same time so this require some process and memory but it's totally worthly if you pull it right. However, how can we accomplish such thing like triggering all the graphics at the same time without fucking up the layers or releasing them when we don't want to? (Like wanting to them to get visible only after the intro).
 
 Easy, releasing all of the explods with scale = 0,0 as soon as possible and then changing the size of the explod to the desired size once you wanna make everything visible using a modifyexplod sctrl. This means you can't destroy any explod if you want all of them to be nsync (Mainly in the case of the diagonal lifebars) as you may get back your life and it may look glitchy if no explods are available for that to be displayed. This is also useful in case of making gauges that change the colour and have some kind of animations on it (Even transparency effects are enough) as the effect will still have the same tempo after swapping the animation and also because both teamsides must have the gauge on the same animation frame in order to look right.
 
 Now onto the advanced stuff (Yeah, even more advanced). In order for the lifebars to work like they must they have to be ontop of everything other possible explod that may come out during the battle, and so that's why you must add ontop = 1 to every explod, but how can we do that without ruining the setup for the lifebars? How can we display the gauge below the lifebar FG but above the lifebar BG if everything gets released at the same time and everything gets the ontop = 1? EASY!!!
 
 This is the way ontop = 1 really works on the explod sctrl:
 
 Ontop = 1 means the explod gets displayed on top of everything, even if said explod has a negative sprite priority or lower than a previous explod. This explod totally ignores the sprpriority line. However theres a trick to get around that, the explod with ontop = 1 that comes after a previous explod with ontop = 1 actually gets above it anyway so any explod released before will be below and any other after will get above. With this little secret you can now fully set your lifebar set and release the sprites in a certain order so they will have a proper layering yet be on top of everything anyway (So abuse of the time = x triggers for better handling of when to release each explod, explods that should be nsync should get released at the same time or work around with the animations and add a delay on the frames).
 
 MUGEN also reads the coding from top to bottom so this is important in the order of the explods aswell (Cares only with explods that get released at the same time).
 
 The trick with this is that the lifebars (Which has a scale of 0,0 when they first get released) can only have a visible scale modification once all the explods were released in order to make all the parts of it to be displayed at the same time with no glitches. So if the last explod was released at time = 3 then you can make the whole set visible from time = 3 to ahead (I recommend time = 4 to ahead in this case anyway). I personally prefer to release the whole set in roundstate < 2 and then make everything visible on roundstate = 2 (Atleast for the first round, and then make everything visible as soon as possible in succesive rounds).
 
 Wondering about what else can be coded inside the common1.cns? well, anything, you're not limited to common states and interactive lifebars, you can also code the animations for the start and the end of a round so you can say good-bye to the common 1-layer-only animations MUGEN lets you use and say hello to total freedom in explod releasing and modification. The only things you really can't code at all are the teammate portraits on team mode and the win icons/ win counter, even the time can be coded (But will still be there when it shouldn't like in survival).
 
 A last note, if you get some problems handling ontop = 1 then be sure that you aren't over the explod limit MUGEN has (Not the one in the mugen.cfg file, the limit per tick MUGEN actually has), as the engine can release a number of explods near 54 but not much more (Doesn't get over 60 IIRC).
 

------------------------------------------------------------------
 SECTION 3: Tag team implementation                              |
------------------------------------------------------------------


 Ever wanted to get rid of the crappy and buggy as hell simul mode? Yeah I wanted and that's why I created a tag team system functional for any character (It's actually kind of a help file if you think about it), you can search for it, get it and work from there to ahead in case you wanna learn how to code this correctly and have a solid base to start your own version of the tag team system.
 
 Here I will explain what kind of troubles you WILL find if you try to code the tag team system by yourself (Or try to fully edit mine), this is more of a recopilation of the misadventures I had while coding this system a while ago. This assumes you will first code a tag team system that requires the use of debug keys to fully be able to control both characters (CTRL+3 or CTRL+4). I will refer to the character who's inactive or outside of the screen as the "stand by" character.
 
 First thing is the actual intro, the leader of the team (Player 1 or 2) should just do his general intro while the second one may do a teammate intro (Like in KOF IX) or just be off screen since the let's go. At first this sounds easy, "Hey! let's just put the teammate out of the screen on a state with CTRL = 0 and keep him in the stand by state while the leader ends his intro! Piece of cake!", however this can't be done like that at all.
 
 In order to actually start a battle all the characters in the stage MUST HAVE CTRL = 1 on their current state! So how can I make it so I wont be able to move the stand by character outside of the screen while starting the battle? simple, you can just give him CTRL = 1 for a tick and then remove the control. The best way is to read the partner's CTRL and then change your CTRL = 0 to CTRL = 1 when he get's the control back after finishing the intro, and a tick later remove the control again so the stand by character never really get's the control (Heck, you can just remove the control as soon as he gets CTRL = 1, no need to even wait a tick for that).
 
 There's another problem that will bother you even more, all the character must be on STATENO 0 for the battle to start! But again, statedef -2 shall be useful for that to be fixed! add a changestate that reads the previous state (Standby state) and the current one (Stateno 0) and then add a changestate to stateno 0 to be able to start the fight and as soon as you go to stateno 0 you have to use those triggers to go back to the stand by state, that way you will never be able to actually move or see the character in the screen. This is kind of hard and tricky so I suggest you to rely on my tag team system and actually study it to know what else you need to actually have in mind (Like camera movement, visibility, state locking,etc).
 
 Even worse, you have to be on stateno 0 with CTRL = 1 for the round to end aswell (Even when you won't be able to move anyway). Again, the stand by character who's outside of the screen will have to rely on the previously mentioned trick. You know, CTRL = 1, changestate to 0, changestate to stand by state. You can also use roundstate = 4 to take out the control of the character, that works well.
 
 You have to have all kind of events in mind while making the system by yourself, if the active character dies and a certain time passed since he was lying down then the partner should get in. If your active character wins the battle and dies at the same time then tweaking will be necessary for the stand by character to react according and prevent a state locking. Same for a double KO situation, for a time over situation while the leader dies and for a double KO situation where both leader dies and both partners should come in.
 
 All those situations are most than nothing annoying when you are coding the lifebars to react to them (Swapping places when a character is active).
 
 You should also add some camera locking helpers while you try to tag out to make it smoother and use some kind of detection helper for when the first active character dies, it's useful for alot of things.
 
 I forgot to mention that during the intro of a round MUGEN automatically puts you into stateno 0 so work around on that too. You will most than nothing else just have to edit the changeanim according to this behaviour in both the new intro state and the stateno 0 and add some extra changestate triggers to make this work correctly.
 
 All in all there's probably a few points I forgot to talk about, you should just get my tag team system and work fom there to ahead ^^, it will save you some bitching and cursing while trying to code this damn thing...
 
 Now if you are really interested to know how to code the tag team system without having to rely on the debug keys (Useful to prevent cheating on compressed and encripted fullgames) then pay attention to the next section below...
Re: Fullgame coding guide for undocumented and non-commonly known problems
#2  July 19, 2009, 11:01:17 pm
  • avatar
  • ******
    • USA

------------------------------------------------------------------
 SECTION 4: How to handle Ctrl = 0                               |
------------------------------------------------------------------


 In order to enjoy of this dreamed tag team system without the use of debug keys each time you start a match then all you have to do is to add a "partner,command = xxx" trigger on your moves so when you go outside of the stage and your partner gets in you can still control him, however we are way too far to be able to do that yet as we have to make a few stops first...
 
 The first thing to have in mind is the way the A.I. works in MUGEN, the CPU character just press buttons in a random manner and with that executes any changestate he can in that moment, but if you are smart enough you probably already adapted your character to use the Winane's A.I. system so you know that with that system a variable is saved to know if the character is a human or the CPU.
 
 All the changestates affected with a command trigger should be unavailable for the A.I. to use them as they will later have their own changestates you will have to code to give him a proper A.I. in your fullgame later, this does prevents the A.I. to make any attacks and enter into any attack or movement state you coded for your character but as soon as you test him you will notice that the A.I. can still walk, guard, jump, crouch and run (And maybe other states, that depends of your game), this is because the so-called special states discussed on the first section are still "special" hence not having the need of a command trigger yet reacting to the random commands the CPU does.
 
 How can we fix that? simple: EVERY SINGLE STATE IN YOUR CHARACTER MUST HAVE CTRL = 0! This means you will have to rely on changestates for everything in the statedef -1, and yes, this includes the special common states, oh yeah, the pain begins here!
 
 You now have to work your ass up and start adding all the changestates by yourself, this means a changestate to a jump start, to a crouch start, to a standing state, to a guard start state and so on.
 
 Here you will have something new to code btw, a turning state, if you don't code this and just give a general turn sctrl then the character will turn but won't display his turning animation, yeah, go work on a reliable coding for that now.
 
 This also means you have to stop relying on using CTRL = 1 as a trigger for any chain moves, special moves, ect. Instead you will have to use state numbers all the time.
 
 Remember to code the guard start changestate correctly as you won't be able to guard with no proper changestates.
 
 You don't need to changestate your character to the victory or losing poses, just give him CTRL = 1 for a few ticks on roundstate = 3 or 4 (Test this out, highly depends on your game style).
 
 If you did it right with proper changestates and with no bugs then you will still be able to play with your character like before these modifications with no problems and now the A.I. shouldn't be able to changestate anymore, if everything's right he will be in his  standing state forever until you give him a proper A.I. coding.
 
 Yes it's a hard work but making an awesome fullgame requires awesome work, if you pulled this right you got my respect (Unless you are a poor tengu).
 
 Onto the next section, the last parts are just about stuff you may or may not want to include in your game, I highly suggest to use the stuff you will learn in SECTION 5, this will prevent even more glitches in your fullgame and also make it closer to a fullgame, not to mention the flexibility this will give to you once you pull it right.
 
 
------------------------------------------------------------------
 SECTION 5: No roundstate < 2                                    |
------------------------------------------------------------------


 The main concept of this is to not to be able to skip the intros on your character, in fact you can add this nifty feature on your game and then add a way to skip the intros, only this time you will be able to fully edit the transition to the battle with any effect you want.
 
 Real games generaly doesn't let you skip the intros (Games like CVS2 for example) and the ones which lets you doesn't have a fade out crappy screen like the default on in MUGEN (like KOF IX) so I suggest to add this.
 
 First of all the fight.def must be edited, go to [round] and set this:
 
 start.waittime = 1         ;Time to wait before starting intro
 
 A time of 0 may cause bugs so we can only rely on 1 to ahead. Yes, with this the intro can still be skipped (Will cause bugs if you code this in a proper way, sucks) but they can only be skipped for a tick so unless you're button mashing like hell you won't skip it.
 
 ctrl.time = 5              ;Time players get control after "Fight"
 
 Set it like this, after all the intro our character will do will be actually during roundstate = 2, yes! Roundstate = 2! The setup we just did is so you actually never get to really see roundstate = 1 so you will make your intro during the actual fight.
 
 Now onto the real thing. The best way to do this is to changestate your character into stateno 0 from stateno 5900 and then into a new state from stateno 0, this state will be your new intro state. You can actually just use the regular intro state but it's not recommended, and also don't rely on the intro assertspecial, we dont need it at all (In fact, remove that thing from every single state that has it).
 
 Now the best way to setup this is to use an universal variable in your characters inside your fullgame, this is the way I do it in my KOF fullgame:
 
 Var(x) = 0 : Character is not ready to start the battle or is starting his intro animation.
 Var(x) = 1 : Character finished his intro animation and is waiting for the enemy to do the same.
 Var(x) = 2 : All the characters finished their intros and are ready to fight. (Helper for the round start animation get's released).
 Var(x) = 3 : Ready to fight, all the changestates regarding the commands are available now.
 
 With this simple setup You can control with ease when the characters are able to move and whatnot. You can change the parameters or modify the triggers that will lead to different varsets according to your game. In case of var(x) = 2 I release a helper to show the round start animations as if the round just actually started and you just entered into roundstate = 2 when you actually were in that roundstate all the time.
 
 Of course, edit all your command triggered changestates so they get available only when var(x) = 3 so you won't be able to attack during the intros.
 
 You have to be carreful with the time you decide to set for the changestates, remember that even when we are avoiding roundstate < 2 we still pass through roundstate = 1 to roundstate = 2 hence changing to stateno 0 in a certain moment so work around that aswell.
 
 This nifty trick also let's us customize MUGEN even more by adding VS screens with special effects or an intro stage scene (Like in KOF XI).
 
 A last note here: MUGEN has a fixed time for roundstate < 2 so you really can't remove it at all, means you can't start the fight at tick 0. This can be avoided the best if the fight.def file has a start.waittime = 0 but that acts buggy on MUGEN so I suggest to not to do that.
 
 
------------------------------------------------------------------
 SECTION 6: Winpose not being able to be skipped                 |
------------------------------------------------------------------


 This works similar to the previous trick, our goal is to not to be able to skip the winpose or atleast not to be able to skip part of it (Similar to KOF XI where you can skip winposes but you first have to wait for the announcer to say all the stuff first).
 
 The way to setup this correctly is actually half finished already if you decided to adapt your character using the tricks in SECTION 4, otherwise just remove the control on your character by using statedef -2 once roundstate = 3 get's reached.
 
 You must build a system that displays all the stuff the system may need (Like in KOF XI when you see the YOU WIN and PERFECT or YOU LOSE signs) and time everything correctly so you get back the control of the character once all the signs dissapeared or the time you wanted this to last is over.
 
 I suggest using a variable and complex varsets for that as you will need to debug this alot (Well, like anything actually mentioned here). A variable can read when you are ready to start showing the messages for example (Like when you are on stateno 0 and the enemy is lying down and X time has passed for him) and from there to ahead is up to you. You can either change the animation of your character to make a winpose that can't be skipped or just give him CTRL = 1, changestate back to stateno 0 and let MUGEN put you on the common win state (Which can be skipped).
 
 With all this you will not be able to go to the next round until you have CTRL = 1 on your character. Use it for anything you want like special winposes or story mode scenes or next round transitions, anything can be done with this.
 
  Something cool to watch: If you put your character into a win state you created with CTRL = 0 and after a while don't use the roundnotover assertspecial then the round will end, the screen will fade out and you will pass to the next round but the previous round won't be counted at all! This means if someone wins in round 2 and you did all this then you will go to... round 2 and you also MUGEN won't read who won the previous round.
 
 One thing to keep in mind: Don't lock yourself into stateno 0, use another state with the same properties once you won (To not to edit every single possibility just add a changestate on stateno 0 to the new copy state) so MUGEN won't think you got locked on your state. I you keep yourself on stateno 0 with CTRL = 0 for a while MUGEN will push you into the common win state no matter what.
 
 And of course, use the roundnotover assertspecial sctrl to actually prevent the round from ending.
 
 Everything up to now will need further debugging if you plan to keep simul mode (either with or without tag mode) so take your time to think of any kind of possibility where you could get a bug (Iike I showed to you, about the KO situations). Still is totally possible to adapt everything into any mode (I did it in my KOF fullgame).
 
 
------------------------------------------------------------------
 SECTION 7: Last note                                            |
------------------------------------------------------------------

 Well that's all, almost 1 hour and 30 minutes of typing, finished at 5:23 A.M., yeah, I had nothing else to do :P ...
 
 Hope this help you to uncover some of the misteries regarding how MUGEN works, this is here to help you know that sometimes you're doing it right yet MUGEN is the guilty one of the bugs you're getting because of the untold stuff and constant unwritten changestates.
 
 See ya later, signs Rednavi.