Home » MODDING HQ 1.13 » v1.13 Idea Incubation Lab » Logical Bodytypes code added into the trunk (WIP)
Logical Bodytypes code added into the trunk (WIP)[message #359041]
||Sat, 15 February 2020 21:52 |
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
<LayerProp filter="IsWearingHat" palette="hats">
<Surface name="LBT_RGMRIFLE_WALK_CROUCH_HAT" animsurface="RGMCROUCH_R_RDY" />
<Surface name="LBT_RGMRIFLE_WALK_CROUCH_HELMET" animsurface="RGMCROUCH_R_RDY" />
<Surface name="LBT_RGMRIFLE_WALK_CROUCH_HELMET" animsurface="RGMCROUCH_P_RDY" />
'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
<!DOCTYPE AnimSurfaces [
<!ENTITY AnimSurfaces_LobotRGM SYSTEM "LogicalBodyTypes\LBT_RGM\AnimationSurfaces_LBT_RGM.xml">
And the AnimationSurfaces_LBT_RGM.xml has the actual surfaces defined, which look like
<AnimSurface name="LBT_RGMRIFLE_WALK_CROUCH_HEAD" file="Anims\LOBOT\RGM\crouched_walk_rifle_head.STI" flags="0" structdata="ANIMS\STRUCTDATA\M_CROUCH.JSD" directions = "8" framesperdir="24" profile="-1" />
'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
<Layer name="body" render="1" shadow="0">2</Layer>
'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:
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.
<!-- Matches all soldier objects, that are supposed to be rendered as average height regular male -->
List of availabe stats to match against are:
As a reference, here's the link to bio's original thread where he elucidates on the implementation as well.
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
[Updated on: Sat, 15 February 2020 22:02]
Re: Logical Bodytypes code added into the trunk (WIP)[message #359100 is a reply to message #359041]
||Thu, 27 February 2020 18:40 |
||This looks great.
May I ask if you (and the people you mentioned) plan to finish this implementation on your own? Or do you need help?
Maybe you can outline the artistic process so people can easier contribute / mod? You can pm me if you want.
Re: Logical Bodytypes code added into the trunk (WIP)[message #359102 is a reply to message #359100]
||Thu, 27 February 2020 22:16 |
||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.
Re: Logical Bodytypes code added into the trunk (WIP)[message #359298 is a reply to message #359177]
||Sun, 29 March 2020 17:33 |
||Great to see this finally being worked on again! I tried to get into biolecter's code two years ago, but I never quite comprehended it.
So thanks Asdow, for having picked that up!
Re: Logical Bodytypes code added into the trunk (WIP)[message #359979 is a reply to message #359298]
||Sat, 09 May 2020 12:07 |
Location: Hessen Germany
||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.
Thumps up for this freaky job.
[Updated on: Sat, 09 May 2020 12:12]
Current Time: Sun Jul 12 08:27:46 EEST 2020
Total time taken to generate the page: 0.02436 seconds