Currently all the animations WZ uses are hard-wired one way or another. Specifically, they're listed in a file called "anim.cfg" that looks like this (the following was extracted from base.wz, e.g. the campaign):
Code: Select all
anim_module
{
/* anim format: [filename] [id] */
"walkanim.ani" 0
"fireknee.ani" 1
"runanim.ani" 2
"runflame.ani" 3
"flamfall.ani" 4
"blderik.ani" 5
"cybd_run.ani" 6
"cybdpjmp.ani" 7
"cybdplnd.ani" 8
"cybdprun.ani" 9
}
Where are the super cyborgs? They are also stored in the anim.cfg file, but the one in mp.wz, which has this extra line:
Code: Select all
"scbd_run.ani" 10
It doesn't have to be this way; it would be a lot more customizable if we could assign animation files on a per-component, per-event basis. Of course, this requires an overhaul of how WZ handles the animations... the broad details of which, IMHO, could be:
0 - How animations actually work
Each .ani file represents only one animation. There are two methods used: the "frames" method and "transform" method. The frames method is what you see on all scavenger infantry; it's also used to animate the basic cyborg legs. It looks like this:
Code: Select all
ANIM3DFRAMES "cybd_run.pie" 6 7
{
0 0 0 0 0 0 0 1000 1000 1000
1 0 0 0 0 0 0 1000 1000 1000
2 0 0 0 0 0 0 1000 1000 1000
3 0 0 0 0 0 0 1000 1000 1000
4 0 0 0 0 0 0 1000 1000 1000
5 0 0 0 0 0 0 1000 1000 1000
}
Then there's the transform method, which is what animates super-cyborg legs. And the oil derrick:
Code: Select all
ANIM3DTRANS "BLDerik.pie" 25 15 3
{
ANIMOBJECT 0 "DerrickBase"
{
0 0 0 0 0 0 0 1000 1000 1000
1 0 0 0 0 0 0 1000 1000 1000
2 0 0 0 0 0 0 1000 1000 1000
3 0 0 0 0 0 0 1000 1000 1000
4 0 0 0 0 0 0 1000 1000 1000
5 0 0 0 0 0 0 1000 1000 1000
6 0 0 0 0 0 0 1000 1000 1000
7 0 0 0 0 0 0 1000 1000 1000
8 0 0 0 0 0 0 1000 1000 1000
9 0 0 0 0 0 0 1000 1000 1000
10 0 0 0 0 0 0 1000 1000 1000
11 0 0 0 0 0 0 1000 1000 1000
12 0 0 0 0 0 0 1000 1000 1000
13 0 0 0 0 0 0 1000 1000 1000
14 0 0 0 0 0 0 1000 1000 1000
15 0 0 0 0 0 0 1000 1000 1000
16 0 0 0 0 0 0 1000 1000 1000
17 0 0 0 0 0 0 1000 1000 1000
18 0 0 0 0 0 0 1000 1000 1000
19 0 0 0 0 0 0 1000 1000 1000
20 0 0 0 0 0 0 1000 1000 1000
21 0 0 0 0 0 0 1000 1000 1000
22 0 0 0 0 0 0 1000 1000 1000
23 0 0 0 0 0 0 1000 1000 1000
24 0 0 0 0 0 0 1000 1000 1000
}
ANIMOBJECT 1 "Piston"
{
0 0 0 0 0 0 0 999 1000 1000
1 0 0 544 0 0 0 999 1000 1000
2 0 0 2056 0 0 0 999 1000 1000
3 0 0 4349 0 0 0 999 1000 1000
4 0 0 7242 0 0 0 999 1000 1000
5 0 0 10548 0 0 0 999 1000 1000
6 0 0 14085 0 0 0 999 1000 1000
7 0 0 17668 0 0 0 999 1000 1000
8 0 0 21112 0 0 0 999 1000 1000
9 0 0 24235 0 0 0 999 1000 1000
10 0 0 26851 0 0 0 999 1000 1000
11 0 0 28776 0 0 0 999 1000 1000
12 0 0 29827 0 0 0 999 1000 1000
13 0 0 29827 0 0 0 999 1000 1000
14 0 0 28776 0 0 0 999 1000 1000
15 0 0 26851 0 0 0 999 1000 1000
16 0 0 24235 0 0 0 999 1000 1000
17 0 0 21112 0 0 0 999 1000 1000
18 0 0 17668 0 0 0 999 1000 1000
19 0 0 14085 0 0 0 999 1000 1000
20 0 0 10548 0 0 0 999 1000 1000
21 0 0 7242 0 0 0 999 1000 1000
22 0 0 4349 0 0 0 999 1000 1000
23 0 0 2056 0 0 0 999 1000 1000
24 0 0 544 0 0 0 999 1000 1000
}
ANIMOBJECT 2 "Box03"
{
0 0 0 0 0 0 0 1000 1000 1000
1 -671 0 168 0 480 0 999 1000 999
2 -2680 0 707 0 1921 0 999 1000 999
3 -6001 0 1720 0 4328 0 999 1000 999
4 -10581 0 3374 0 7705 0 999 1000 999
5 -16322 0 5895 0 12052 0 999 1000 999
6 -23053 0 9556 0 17365 0 1000 1000 1000
7 -29891 0 14178 0 23089 0 999 1000 999
8 -35243 0 18562 0 27886 0 1000 1000 1000
9 -39228 0 22361 0 31703 0 1000 1000 1000
10 -42031 0 25362 0 34550 0 1000 1000 1000
11 -43808 0 27430 0 36440 0 1000 1000 1000
12 -44668 0 28482 0 37382 0 999 1000 999
13 -44668 0 28482 0 37382 0 999 1000 999
14 -43808 0 27430 0 36440 0 1000 1000 1000
15 -42031 0 25362 0 34550 0 1000 1000 1000
16 -39228 0 22361 0 31703 0 1000 1000 1000
17 -35243 0 18562 0 27886 0 1000 1000 1000
18 -29891 0 14178 0 23089 0 999 1000 999
19 -23053 0 9556 0 17365 0 1000 1000 1000
20 -16322 0 5895 0 12052 0 999 1000 999
21 -10581 0 3374 0 7705 0 999 1000 999
22 -6001 0 1720 0 4328 0 999 1000 999
23 -2680 0 707 0 1921 0 999 1000 999
24 -671 0 168 0 480 0 999 1000 999
}
}
1 - Create a new animation script format
Basically, this would be a replacement for anim.cfg and its purpose is to specify a list of in-game contexts where a given animation should be used. A quick example of cyborg legs might look like this:
Code: Select all
/* format: animation [animation-name] [default-animation] */
animation "cyborg_legs" "cybd_std.pie"
{
/* format: [event-type] [anim-file] [optional-event-parameters] */
onMove "cybd_run.ani" 1
}
For a more complicated example, let's imagine scavenger infantry:
Code: Select all
animation "babaDude" "exbloke.pie"
{
/* running animation */
onMove "runanim.ani" 1
/* Shooting animation */
onShoot "fireknee.ani"
/* Hit by a flame weapon */
onBurn "runflame.ani" 0
/* Killed by flame damage */
onBurnDie "flamfall.ani"
}
Code: Select all
animation "oilDerrick" "blderik.ani"
{
}
Of course, that's only half of the equation. The other half is that once the animation event-scripts are defined and loaded by the game engine, we should be able to reference those animations anywhere a file format would normally refer to a static PIE File. For example, the cyborg legs graphic is actually specified in Body.txt, e.g:
Code: Select all
CybRotMgGrd,Level All,LIGHT,25,100,150,200,cybd_std.pie,100,1,600,12,6,0,0
Code: Select all
CybRotMgGrd,Level All,LIGHT,25,100,150,200,cyborg_legs,100,1,600,12,6,0,0
Code: Select all
cyborg_legs,cyborgLegs.script
babaDude,babaDude.script
Of course, the biggest task is implementing the various events that power the logic of what-animation-gets-rendered-when. Some that I can think of are:
- onMove - animation to play when the unit is moving. Framerate can either be absolute (per second) or relative (per distance moved).
- onShoot - animation to play when an attack round is executed.
- beforeShoot - animation to play before executing an attack round (the actual attack is delayed until this animation completes).
- onHit - when the user is struck by any enemy attack.
- onBurn - when the user is receiving incendiary (burn) damage (mostly scavenger infantry)
- onBurnDie - if the user is killed by incendiary damage (mostly scavenger infantry)
- onJump - when the user takes off into the air (e.g. jump cyborgs)
- onFly - when the user is moving while airborne
- onLand - when the user lands on the ground again
I know this is very rough and mainly conceptual, but what do you think?
For one, I believe Pumpkin clearly intended NEXUS to use flying cyborgs against you in the final campaign level (and wouldn't that be awesome?) - three NEXUS unit templates have "-JUMP" suffixed to their template ids, original warzone.wdg does include jetpack animation files, they just never got it working well enough for the final product so they decided to simply disable it.