I assume you're planning to go for Mugen, but just in case you think of starting one with some basics first using OpenBOR. This is something I forgot about how I did with non-scripts as a beginner.
Before you start your new OpenBOR game project for a 1v1 style, pick which module you want to use as a base. I recommend you start with a module that has no (complex) scripts at all. For myself, I picked the original Neo Edit Pack as a base for working on a different system. Any of the OpenBOR templates from
@Bloodbane is also okay (though there are simple scripts). Even though I don't recommend going for complex scripts such as
@bWWd's He-Man,
@O Ilusionista's AUBF,
@Kratus's SORX games, my SF game project (though it's not released hehe),
@White Dragon's TMNT: SS,
@magggas's WHSJ/DDRA, or any module that has very complex scripts to start with as a base to work with/on, Bloodbane's scripts are simplified. But I don't know what your opinion is about his simple scripts.
Change your levels with the same values of both zmin and zmax for it to be straightly linear like platformers. Only if you like to.
Code:
z 200 200
file data/levels/fight000.txt
Create an enemy and make his anim attack as a non-attack animation first before you give him any specific attack so he acts like a dummy.
If you don't want to activate your player to jump with jump button, you don't have to have anim jump, so you can use something like
com j freespecial
in the header for pressing a jump button to do a certain move (instead of jumping).
If you want to allow only 4 buttons to be pressed for your game ala KOF style, you can use menu.txt in the data folder.
Example:
Code:
renamekey moveup Up
renamekey movedown Down
renamekey moveleft Left
renamekey moveright Right
renamekey attack Light_Punch
renamekey attack2 Heavy_Punch
disablekey attack3
disablekey attack4
renamekey jump Light_Kick
renamekey special Heavy_Kick
#fontmonospace 1 1 0 0 0 0 0 0 0 0 0
#fontmonospace {font} {font2} {font3} {font4} {font5} {font6} {font7} {font8}
#fontmbs {font1} {font2} {font3} {font4} {font5} {font6} {font7} {font8}
There are several scripts you need to learn, but I can give you one simple script, which is the jumping script. However, mine is more complex than
@kimono's jumping system for his characters. His Way of the Martial Arts module has the up button active for jumping as a freespecial. It's simpler than what I have. Plus, there is keyint to change animation every time a player jumps forward. Just pay attention to their parameters of their functions (e.g. keyint) like you follow and do leaper, degravity, and some of them you're familiar with. Look at this here.
Code:
com a2 freespecial
com U freespecial6
com a + a2 freespecial9
Code:
anim forwardjump
cancel 0 5 0 a2 freespecial4
delay 12
offset 38 114
bbox.position.x 12
bbox.position.y 14
bbox.size.x 53
bbox.size.y 40
delay 8
frame data/chars/karatedo/jumpf1.gif
frame data/chars/karatedo/jumpf2.gif
frame data/chars/karatedo/jumpf3.gif
frame data/chars/karatedo/jumpf4.gif
frame data/chars/karatedo/jumpf5.gif
anim freespecial6 #Jump
@script
if(frame==1){
void self = getlocalvar("self");
changeentityproperty(self, "aiflag", "jumping", 1);
changeentityproperty(self, "takeaction", "common_jump");
}
@end_script
delay 1
cancel 0 5 0 a2 freespecial3
offset 86 104
bbox.position.x 68
bbox.position.y 0
bbox.size.x 29
bbox.size.y 57
@cmd keyint "ANI_FOLLOW6" 0 "F" 0
jumpframe 0 3 0 0
frame data/chars/karatedo/jump.gif
frame data/chars/karatedo/jump.gif
@cmd keyint "ANI_FOLLOW6" 0 "F" 0
frame data/chars/karatedo/jump.gif
delay 12
frame data/chars/karatedo/jump.gif
delay 8
frame data/chars/karatedo/jump.gif
anim follow6 #Jump Forward
cancel 0 5 0 a2 freespecial4
delay 12
offset 38 114
bbox.position.x 12
bbox.position.y 14
bbox.size.x 53
bbox.size.y 40
delay 12
jumpframe 0 3 1.5 0
frame data/chars/karatedo/jumpf1.gif
frame data/chars/karatedo/jumpf2.gif
frame data/chars/karatedo/jumpf3.gif
frame data/chars/karatedo/jumpf4.gif
frame data/chars/karatedo/jumpf5.gif
anim jumpforward #Front Jump Punch
delay 12
offset 86 104
bbox.position.x 68
bbox.position.y 0
bbox.size.x 29
bbox.size.y 57
sound data/sounds/jumppunch.wav
frame data/chars/karatedo/jump.gif
attack 108 38 46 34 10 1 0 0
frame data/chars/karatedo/jumpfpunch.gif
attack 108 38 46 34 10 1 0 0
frame data/chars/karatedo/jumpfpunch.gif
attack 0 0 0 0 0 0
frame data/chars/karatedo/jump.gif
anim freespecial4 #Jump Front Kick
jumpframe 0 0 2
fastattack 1
jugglecost 5
forcedirection -1
loop 0
delay 8
offset 86 104
bbox.position.x 68
bbox.position.y 0
bbox.size.x 29
bbox.size.y 57
sound data/sounds/jumpkick.wav
frame data/chars/karatedo/Jump.gif
frame data/chars/karatedo/Jump.gif
delay 24
attack 80 42 89 30 10 1 15 1 2
bbox.position.x 72
bbox.position.y 0
bbox.size.x 26
bbox.size.y 48
frame data/chars/karatedo/Jumpfkick.gif
delay 8
attack 80 42 89 30 10 1 15 1 2
bbox.position.x 69
bbox.position.y 0
bbox.size.x 26
bbox.size.y 48
frame data/chars/karatedo/Jumpfkick.gif
attack 0 0 0 0 0 0
bbox.position.x 69
bbox.position.y 0
bbox.size.x 29
bbox.size.y 67
frame data/chars/karatedo/Jump.gif
C:
void keyint(void Ani, int Frame, void Key, int Hflag)
{// Change current animation if proper key is pressed or released
// Animation is changed to attack mode
void self = getlocalvar("self");
int Dir = getentityproperty(self, "direction");
int iPIndex = getentityproperty(self,"playerindex"); //Get player index
void iRKey;
if (Key=="U"){ //Up Required?
iRKey = playerkeys(iPIndex, 0, "moveup"); // "Up"
} else if (Key=="D"){ //Down Required?
iRKey = playerkeys(iPIndex, 0, "movedown"); // "Down"
} else if (Key=="L"){ //Left Required?
iRKey = playerkeys(iPIndex, 0, "moveleft"); // "Left"
} else if (Key=="R"){ //Right Required?
iRKey = playerkeys(iPIndex, 0, "moveright"); // "Right"
} else if (Key=="F"){ //Forward Required?
if (Dir == 0){ // Facing Left?
iRKey = playerkeys(iPIndex, 0, "moveleft"); // "Left"
} else { // Facing Right
iRKey = playerkeys(iPIndex, 0, "moveright"); // "Right"
}
} else if (Key=="B"){ //Backward Required?
if (Dir == 1){ // Facing Right?
iRKey = playerkeys(iPIndex, 0, "moveleft"); // "Left"
} else { // Facing Left
iRKey = playerkeys(iPIndex, 0, "moveright"); // "Right"
}
} else if (Key=="J"){ //Jump Required?
iRKey = playerkeys(iPIndex, 0, "jump"); // "Jump"
} else if (Key=="A"){ //Attack Required?
iRKey = playerkeys(iPIndex, 0, "attack"); // "Attack"
} else if (Key=="S"){ //Special Required?
iRKey = playerkeys(iPIndex, 0, "special"); // "Special"
}
if (Hflag==1){ //Not holding the button case?
iRKey = !iRKey; //Take the opposite condition
}
if (iRKey){
if (Ani=="ANI_IDLE"){ // Going idle?
setidle(self, openborconstant("ANI_IDLE")); //Be idle!
} else {
performattack(self, openborconstant(Ani)); //Change the animation
}
updateframe(self, Frame); //Change frame
}
}
This way, you don't have to do something complex like what I did. But you get some ideas of how they can be done in different modules with scripts (both from simple and complex ones).
Despite the two names being similar,
jumpforward and
forwardjump are different in animations.
anim forwardjump
is an animation which you just hold forward and then jump to perform a forward jump. But
anim jumpforward
is when you jump forward, you perform a jumping attack as a jumping forward attack instead of just jumpattack, leaving jumpattack as a normal straight jump attack. I should've used that method/trick years ago (before WOMA was released) because at that time, I knew a little how to use animation scripts, as well as editing some values.
I already have fighters always facing each other all the time, but that's got to be done in script. However, if you want to know how it's done, I can share it here. Please let me know if you want to see it.
- Falling animation. OpenBOR treats the fall animation as a single thing, which ends in the RISE animation. In Mugen, you have much more control
5030 | Stand/Air Hit back | Looptime around 10-20 |
5035 opt | Stand/Air Hit transition | Looptime around 5-15 (See Note 3) |
5040 | Air Recover | No loop |
5050 | Air Fall | No loop |
5060 opt | Air Fall (coming down) | No loop |
5070 | Tripped | |
5080 | LieDown Hit (stay down) | (See Note 4) |
5090 | LieDown Hit (hit up into air) | |
5100 | Hitting ground from fall | Looptime around 3 |
5160 | Bounce into air | |
5170 | Hit ground from bounce | Looptime around 3 or 4 |
5110 | LieDown | |
5120 | Get up from LieDown | |
5140 opt | LieDead (first rounds) | |
5150 opt | LieDead (final round) | |
5200 | Fall-recovery near ground | |
5210 | Fall-recovery in mid-air | |
There are some parts in the list that I don't know what they mean such as Fall-recover mid-air, FR near ground, Tripped, Air Fall, LieDown Hit (hit up into air). But what I do with those is that I translate them into OpenBOR codes such as anim rise, anim fall, anim fall20 (sweep), etc. I use anim fall20 for the sweep, but I don't use anim rise20 after fall20. Just a normal/default anim rise is enough as a character's get up animation unless you want a different pose of getting up from a given attack.
When it comes to knockdowns, I use different fall animations other than anim fall itself, coming from other special/super moves and some crouch attacks. Since I use the default anim fall as a default air recovery with player's health script active, it simulates the event where a standing fighter hits a jumping fighter. When the jumping fighter gets hit on air before falling to the ground, s/he starts to flip back for recovery to land safely. Dunno if I'm saying it right, but you get what I'm saying about getting knocked down and then land. It's like the old SF2 games and their installments. For instance, Ryu stands on the floor and punches Ken who's on the air, but Ken flips back after getting hit because Ken's health is active. But when a player is knocked down/out with health point 0, that's when s/he plays the default fall animation, skipping the script due to no active health point.
C:
void FallSafe2(void Ani){
//Change animation while being alive but with desired animation change
void self = getlocalvar("self");
int health = getentityproperty(self, "health");
if(health > 0){
changeentityproperty(self, "animation", Ani);
}
}
Example:
C:
anim fall
delay 7
offset 336 292
landframe 3
frame data/chars/ken/cvs2_ken_575.png # 0 3
@cmd FallSafe2 openborconstant("ANI_FOLLOW73")
delay 13
frame data/chars/ken/cvs2_ken_575.png # 1 16
delay 1000
frame data/chars/ken/cvs2_ken_576.png # 2 1016
delay 7
@cmd spawn01 "Dust" 0 0 0
frame data/chars/ken/cvs2_ken_579.png # 3 1023
frame data/chars/ken/cvs2_ken_580.png # 4 1030
frame data/chars/ken/cvs2_ken_583.png # 5 1037
frame data/chars/ken/cvs2_ken_584.png # 6 1042
Code:
anim follow73 #Safe fall
offset 336 292
delay 8
jumpframe 0 1.2 -1.6 0
landframe 7
bbox 314 182 43 105
frame data/chars/ken/cvs2_ken_104.png
bbox 313 194 61 47
frame data/chars/ken/cvs2_ken_103.png
bbox 313 199 48 47
frame data/chars/ken/cvs2_ken_102.png
frame data/chars/ken/cvs2_ken_101.png
bbox 319 199 48 41
frame data/chars/ken/cvs2_ken_100.png
bbox 319 192 45 77
frame data/chars/ken/cvs2_ken_99.png
delay 1000
bbox 318 184 47 108
frame data/chars/ken/cvs2_ken_98.png
@cmd attack0 "ANI_JUMPLAND"
frame data/chars/ken/cvs2_ken_98.png
Thanks to
@Kratus for the multiple landframe script, I was able to make Chun-Li's land to work, but it's close to what I want.
Code:
anim fall
@script
if(frame == 1){
void actress = getlocalvar("self");
int hp = getentityproperty(actress, "health");
if(hp>0){
changeentityproperty(actress, "animation", openborconstant("ANI_FOLLOW73"));
}
}
@end_script
delay 7
offset 336 293
landframe 4
frame data/chars/chun-li/cvs2_chunli_888.png
frame data/chars/chun-li/cvs2_chunli_888.png
frame data/chars/chun-li/cvs2_chunli_889.png
delay 1000
frame data/chars/chun-li/cvs2_chunli_890.png
delay 4
#Straight land for bouncing
frame data/chars/chun-li/cvs2_chunli_892.png
@cmd leaper -1 1.5 0 #Start bouncing
frame data/chars/chun-li/cvs2_chunli_892.png
frame data/chars/chun-li/cvs2_chunli_893.png
@cmd landFrame
@cmd spawn01 "Dust" 0 0 0
frame data/chars/chun-li/cvs2_chunli_894.png
@cmd leaper -1 0.8 0
frame data/chars/chun-li/cvs2_chunli_894.png
frame data/chars/chun-li/cvs2_chunli_895.png
@cmd landFrame
frame data/chars/chun-li/cvs2_chunli_896.png
delay 6
frame data/chars/chun-li/cvs2_chunli_177.png
Thanks to Bloodbane for his scripts for CountMonte's Rise of Warduke and his own VS template demo, it's possible to make an event for the target entity's death anim to trigger the next round or stage.
- Damage animation - Mugen natively has animations for when your character receives damage while crouched, including transition animations between damage and idle, something that does not exist in OpenBOR for example
5000 | Stand/Air Hit high (light) | Looptime around 10-20 |
5001 | Stand/Air Hit high (medium) | " (See Note 2) |
5002 | Stand/Air Hit high (hard) | " |
5005 | Stand Recover high (light) | No loop (See Note 3) |
5006 | Stand Recover high (medium) | " |
5007 | Stand Recover high (hard) | " |
5010 | Stand/Air Hit low (light) | Looptime around 10-20 |
5011 | Stand/Air Hit low (medium) | " |
5012 | Stand/Air Hit low (hard) | " |
5015 | Stand Recover low (light) | No loop |
5016 | Stand Recover low (medium) | " |
5017 | Stand Recover low (hard) | " |
5020 | Crouch Hit (light) | Looptime around 10-20 |
5021 | Crouch Hit (medium) | " |
5022 | Crouch Hit (hard) | " |
5025 | Crouch Recover (light) | No loop |
5026 | Crouch Recover (medium) | " |
5027 | Crouch Recover (hard) | " |
I'm not sure about how crouch/stand recover work and how they play like. But I do know about crouch hit which I made it with doattack and pain scripts (kudos to
@Piccolo for the force pain script).