Firstly, Bio's logical bodytypes was recently added into the trunk, and the code is functional but its current state is just a proof that it functions and you can draw layered sprites. We're still long ways away from having it being fully realized in the game because we need to remake all the animations for all the bodies. If a logical bodytype is missing an animation, nothing is drawn on the screen so the regular bodytype mercs will be invisible when it's enabled in all animations except for regular male, rifle weapon raised, crouched walking animation. Any rifle type weapon should work, and shotgun type weapons have their own sprite. Steel helmet, TIMS backpack & hat with uiIndex 285 have sprites that will show up if worn in that animation. An example of how this looks can be seen in this video I recorded to show that it functions.
With that out of the way, here's how it works as far as how I've understood it.
There are 5 .xml files in Data-1.13/TableData/LogicalBodyTypes that are used to define a bodytype.
Defines a logical bodytype, what filters is used to select said bodytype and what animationsurfaces are available for its layers and layerprops.
A recommended way to add logical bodytypes is to have the actual data in an external .xml file and add it to the LogicalBodyTypes.xml using an ENTITY. As an example, here's how LogicalBodyTypes is currently
<!DOCTYPE LogicalBodyTypes [
<!ENTITY LobotRGM SYSTEM "LogicalBodyTypes\LBT_RGM\LogicalBodyType_LBT_RGM.xml">
<!-- Bodytypes should be ordered from most specific -> most general -->
<!-- ExcludedObjects filter in the beginning is used to exclude LOBOT system for certain types. In this case filter ExcludedObjects is set up to limit LOBOT only for soldiers with a profile. -->
<LogicalBodyType filter="ExcludedObjects" />
<LogicalBodyType filter="IsRegularMaleAverage" cachesize="2">&LobotRGM;</LogicalBodyType>
'filter' is used to select a specific bodytype if the condition is met. Bodytypes should be ordered from most specific to most general starting from the top.
'cachesize' How big the LRU cache for a bodytype is. Minimum value is 2. It's used to improve performance and cache size should be adjusted depending on the amount of animation states and props a logical bodytype has.
The LogicalBodyType_LBT_RGM.xml contains the relevant data for the defined bodytype. An excerpt for one layer is
'layer name' defines what layer the layerprop surfaces belong to. Name must match with one of the layers defined in Layers.xml
'LayerProp' is a specific prop that is then drawn depending on if the filter used is applicable.
'filter' what condition must be fulfilled for this layerprop to be rendered
'palette' is used if a prop needs a fixed palette or colors that are not available in the default dynamic palette that is used for merc sprites. Name must match with a palette defined in Palettes.xml
'Surface' holds the animation surface that we want to render, and what animation surface does it get used for
'name' defines what logical bodytype animation surface should be used. Name must match with an AnimSurface found in AnimationSurfaces.xml
'animsurface' defines what original animationsurface is the logical one supposed to be used for. In the example, there are two Surfaces under the Layerprop for when the merc is wearing a helmet. The 'name' is the same in this case, because the animation is so similar that the same animation could be used for both. 'animsurface' differs only by one letter, 'R' vs 'P'. These are the animation surfaces that the game uses for regular male crouch walking in a weapon ready stance. One is for rifle weapon and the other for pistol.
Defines the actual animation files to be used for a specific animation for a logical bodytype. A recommended way to add animation surfaces is to have the actual data in an external .xml file and add it to the AnimationSurfaces.xml using an ENTITY. As an example, here's how AnimationSurfaces is currently
'name' is used in LogicalBodyTypes.xml to select a specific animation
'file' points to the file where the animation data is stored. By default, the code looks for these in the 'Data' folder, so the actual path in the example is Data/Anims/LOBOT/RGM/animationfile.sti
'flags' unknown currently, it's used somewhere in the code, but it has not been relevant so far in our quest to get this working in the first place
'structdata' tells what .JSD file to use for the anim, if any. In a merc's case, it's pretty much dependent on what stance is the animation supposed to be for.
'directions' how many directions does the animation have. For merc's it's pretty much always 8
'framesperdir' How many frames per direction is in the animation. New animations *must* have the same amount of frames per direction as the underlying animation. Otherwise bad things happen!
'profile' unknown currently. Same thing as with flags, wasn't relevant to get this working.
Defines fixed palettes that can be used for layerprops in LogicalBodyTypes.xml. Useful for certain props. In bio's example video, the navy dress uniform used a fixed palette, so the uniform is always the same color regardless of a merc's dynamic clothing colors. An entry looks like this:
<Palette name = "hats" filename = "Palettes\Hats.stp" />
'name' identifies it, so it can be used in the other .xmls
'filename' points to the actual palette file, can be either .act or .stp palette file. By default, the code looks for these in the 'Data' folder, so the actual path in the example is Data/Palettes/Hats.stp
Defines layers that can be used to stitch a sprite together during rendering. An entry in Layers looks like
'name' of the specific layer.
'render' tells whether the layer should be rendered or not, with values 1 or 0.
'shadow' determines whether any shadow is rendered for this specific layer, possible values 1 or 0.
number value at the end I'm not completely sure about, could be a unique identifier for the layer? I kept them as a running number and have not played with it so far.
Currently there are 12 layers defined; shadow, legs, body, hands, head, gun, helmet, facegear, vest, backpack, legrig & knees. A base body consists of layers shadow, legs, body, hands & head. Shadow is used for drawing the ground shadow for the base body. Other layers are meant for their respective props. If multiple layers draw shadows in the same spot, the shadow on the ground gets darker with every pass, so that's why only gun and backpack are currently set up to draw shadows on the ground in addition to the basebody. Due to JA's small resolution, it's not noticeable whether a helmet or a vest has ground shadows or not.
I tried to come up with a reasonable number of layers that give us a good starting point to implement props for animations, taking into account the low resolution of JA's graphics. Layers are not hardcoded and can be extended if one wants/needs to.
Filters are used in LogicalBodyTypes.xml to select a specific bodytype and what graphics are drawn in a specific layer for a certain animation surface. You can match conditions against a great number of different things, like physical bodytype, merc's name, sex, skill/experience level, if he has a specific item in a specific slot etc. Operations available for filters are: AND, OR, NOT, EQUAL, GREATER THAN, LESS THAN, BETWEEN & IN
Couple of examples of filters:
<!-- Matches all soldier objects, that are supposed to be rendered as average height regular male -->
IsWearingBackpack for instance, applies only if a regular male bodytype is wearing TIMS backpack. IsShotgun selects for a regular male having a shotgun type weapon in his hands.
Lastly, a big thank you to
bio for making the actual LOBOT implementation
merc05 for figuring out the two missing files' structures and updating the code to work in a newer revision of JA and helping me with getting JA to even launch with LOBOT.
Taro for the render setup for rendering props and helping me by answering all my questions.
Seven for code voodoo help with Imagemagick
CC Attribution credits for 3d models used in rendering props
Hellroon - Travel Backpack
MrIllix - Cowboy Hat
studio lab - American Helmet
TastyTony - Low-Poly Mossberg 500
We are planning on remaking the animations so we'll have actually playable version of this. Help is always welcome, of course!
I updated the sprite rendering framework to work with blender 2.8, but Taro is working on an improved rigging for it so setting up animations is faster than with the current one. I think he also wanted to figure out if Eevee can be used for the rendering engine as it's a lot faster than Cycles. Once that's done, we can start the work on remaking the animations. There's a lot of animations that need to be recreated in blender and I'm not much of an animator, so I'm a little useless there.
Creating new sprites isn't terribly complex, most of the work needed is in making the animations. We have documentation about the older rendering setup, but it needs to be updated once the better setup is done.
Another thing is, the workflow could use automating some more. I made a simple batch script that can create working .sti files out of the frames output from the render setup, but defining the lines in the necessary .xml files was done manually when I was testing stuff and trying to get lobot to work. Bio's repo has some batch scripts to define the .xml data but IIRC they need updating to work with the lobot version we have in the trunk. His scripts are way over my current understanding of batch syntax so I've not been able to figure them out yet, either.
This is a really great feature. Should this feature only work for playable merc's, or would that also be transferable to all npc's like opponents and civilians? With this feature, a much more harmonious atmosphere could be realized in the mods. Red shirts and blue shirts as a mark of who is an enemy or friend is boring in the long run. The possibility of having different headgear (e.g. Japanese cone hat or pashtun pakol) and helmet shapes visually represented by the NPCs would deepen the atmosphere of the game.
It can be used for anything that has animation surfaces, so playable mercs, enemies, civilians, tanks, cars etc. The replacement animation must have the same amount of frames as the underlying animation surface, and you'll have to make and render the animations and create the proper filters to the logic but there's little else in the way of doing whatever one's imagination comes up with.
I've been trying my hand at creating animations recently since we don't have too many animators on board. Here's a little sneak peek of my first attempts. The walking anim is all wonky and needs fixing, but for first attempts, the idle and crouching anims came out surprisingly good.
Just a little update again. The rigging & rendering framework is now redone thanks to taro. Posing is a fair bit easier and the renderer was switched from cycles to eevee which shortened rendering times a lot. It's now also possible to render the basebody and up to 5 props in one go unlike with the old version so no more messing with the holdout and nodegraph muting. I've been working on animations this weekend and here's how it looks ingame at the moment.
The rendering framework is now on github, so if anyone wants to play around with it or work on making animations, feel free to do so. The documentation, and my tutorial is not up to date but it shouldn't be too hard to figure out, and you can always ask for help on the JA discord channel. https://github.com/Asdow/JA2-Character-Animation-Photobooth
Looks better than the previous demo and doesn't have the moments of invisibility between animation changes. Good job. I assume, the invisibility when picking up stuff is because there is no animation for that yet?
Yup, that's exactly it. If there's no animation defined for the lobot bodytype, nothing is drawn on the screen.
None of the animations from the old rig could be carried over so I had to remake the ones seen in the older demo. What you see in the newest video is all the animations I've managed to do so far, and some of them still need tweaking to look more natural. I also had to troubleshoot one of the blitting functions when the mercs are prone which is less than pleasant if you're at all familiar with the rendertiles function JA has.
There are still some kinks needing to be fixed, like missing muzzle flashes when shooting and the body and prop shadows overlaying on top of each other at some parts, which shows up as darker spots in the merc shadow if one looks closely. I'm determined to get this done and into the trunk even if it means I have to do all the animations myself. Hopefully that won't be the case though!
Just a slight update to let you know this is still alive. I had a little setback because bio's intention in the code was to create new filters by combining existing ones in the Filters.xml file but the code does not work correctly. I haven't figured out exactly why it doesn't work, but worked around it for now and managed to do a quick test for dual wielding pistol/machine pistol combo.
Another update on this. The video showcases some of the animations that are done, and they are now in the trunk as of r8943 exe and r2582 gameDir. Not all the animations are done, but there are enough in my opinion, that anyone who wants to playtest LOBOT and find issues can do so.
The video is still processing HD version at the moment, so it might be a bit before it's clear.
These are the planned props so far. Anything with an x beside it is already rigged and renderable in the framework.
--- Assault rifles ---
--- SMG ---
--- Shotgun ---
x Saiga 12k
--- Wooden Stock rifles ---
x Mosin nagant
--- Sniper Rifles ---
x Barrett M82
x Sako TRG-42
x Mossberg Patriot
--- LMG ---
--- Pistol & Machine pistol ---
x HK USP
x HK MP5K
x Desert Eagle
x S&W Model 500
--- Heavy weapons ---
--- Props ---
x Vest (needs proper rigging)
x Booney hat
Merc in water
LAW & mortar anims
karate kick & punch
falling from roof
climbing down from roof
swatting with knife
sidestep with rifle while aiming
rifle hip aim
pistol singlehanded aim & shoot
badass merc anims
kicking the cripple
Death animations lack blood spurts/head explosion
Knife not shown except in stabbing anims
Same thing for crowbar
Shooting low with rifle turns into pistol anims
Sidestep with pistol turns into rifle anims
No breathing animation in the collapsed anims
Some of the animations are quite "janky". I've had to learn as I go so the quality of anims is not the greatest.
Dark pixel artifacts in SCARH sprites in certain camera angles
Palette swap for AK type rifles that have black polymer stocks instead of wooden ones
Same for TRG42 and wooden stock sniper rifles
Could probably do the same for M14 sprites to emulate semiauto rifles with polymer stocks
Great job, I admire it because I know it is a tedious job.
Today playing and testing version 8943, I noticed that the new animations only work for "male-normal" characters.
What about "male-bodybuilding" and "female"? Can I hope you will do them too?
"When you see the truth triumph, ask what powerful lie was fighting for it."
Yeah, they're planned too and the rendering framework has models for them already. I've not done any sprites for them yet, because I wanted to get a full set done first for regular male, since after that it would be pretty much just a case of enabling the correct body, rendering all the animations, creating the sti files with the batch scripts we have and copy the xml definitions and search & replace RGM with BGM or FGM. Btw, the whole rendering and creating animation setup is up on github if you or anyone else wants to take a look at it. The link is in this post http://thepit.ja-galaxy-forum.com/index.php?t=msg&th=24337&goto=360422#msg_360422
[Updated on: Sat, 20 February 2021 04:14] by Moderator
I'm using the version 1.0 codes encoded by utf-8. I'm wondering whether there are any update of the code.By the way, any software can edit the animation? Maybe i can try to take a step on it.
There are no Rilfe_Aim_Sidestep codes and animation in version 1.0.
This is amazing work, thank you so much for giving us your time and effort in making such a great addition! I know that should this get finished it would revitalise the game in ways unimaginable! I think it would revive interest quite a bit. Thanks again for all your hard work