1 /* GemRB - Infinity Engine Emulator
2 * Copyright (C) 2003 The GemRB Project
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "CharAnimations.h"
28 #include "Interface.h"
33 static int AvatarsCount
= 0;
34 static AvatarStruct
*AvatarTable
= NULL
;
35 static const ieByte SixteenToNine
[16]={0,1,2,3,4,5,6,7,8,7,6,5,4,3,2,1};
36 static const ieByte SixteenToFive
[16]={0,0,1,1,2,2,3,3,4,4,3,3,2,2,1,1};
38 static const int zOrder_Mirror16
[16][4] = {
57 static const int zOrder_8
[8][4] = {
68 struct EquipResRefData
{
74 void CharAnimations::ReleaseMemory()
82 int CharAnimations::GetAvatarsCount()
87 AvatarStruct
*CharAnimations::GetAvatarStruct(int RowNum
)
89 return AvatarTable
+RowNum
;
92 unsigned int CharAnimations::GetAnimationID() const
94 if (AvatarsRowNum
==~0u) return 0;
95 return AvatarTable
[AvatarsRowNum
].AnimID
;
98 int CharAnimations::GetCircleSize() const
100 if (AvatarsRowNum
==~0u) return -1;
101 return AvatarTable
[AvatarsRowNum
].CircleSize
;
103 int CharAnimations::NoPalette() const
105 if (AvatarsRowNum
==~0u) return -1;
106 return AvatarTable
[AvatarsRowNum
].PaletteType
;
109 int CharAnimations::GetAnimType() const
111 if (AvatarsRowNum
==~0u) return -1;
112 return AvatarTable
[AvatarsRowNum
].AnimationType
;
115 int CharAnimations::GetSize() const
117 if (AvatarsRowNum
==~0u) return 0;
118 return AvatarTable
[AvatarsRowNum
].Size
;
121 int CharAnimations::GetBloodColor() const
123 if(AvatarsRowNum
==~0u) return 0;
124 return AvatarTable
[AvatarsRowNum
].BloodColor
;
127 static ieResRef EmptySound
={0};
129 const ieResRef
&CharAnimations::GetWalkSound() const
131 if(AvatarsRowNum
==~0u) return EmptySound
;
132 return AvatarTable
[AvatarsRowNum
].WalkSound
;
135 int CharAnimations::GetWalkSoundCount() const
137 if(AvatarsRowNum
==~0u) return 0;
138 return AvatarTable
[AvatarsRowNum
].WalkSoundCount
;
141 int CharAnimations::GetActorPartCount() const
143 if (AvatarsRowNum
==~0u) return -1;
144 switch (AvatarTable
[AvatarsRowNum
].AnimationType
) {
145 case IE_ANI_NINE_FRAMES
: //dragon animations
147 case IE_ANI_FOUR_FRAMES
: //wyvern animations
149 case IE_ANI_PST_GHOST
: //special pst anims
150 if (AvatarTable
[AvatarsRowNum
].Prefixes
[1][0]=='*') {
153 if (AvatarTable
[AvatarsRowNum
].Prefixes
[2][0]=='*') {
156 if (AvatarTable
[AvatarsRowNum
].Prefixes
[3][0]=='*') {
165 int CharAnimations::GetTotalPartCount() const
167 if (AvatarsRowNum
==~0u) return -1;
168 switch (AvatarTable
[AvatarsRowNum
].AnimationType
) {
169 case IE_ANI_FOUR_FILES
:
170 case IE_ANI_FOUR_FILES_2
:
171 return GetActorPartCount() + 1; // only weapon
172 case IE_ANI_CODE_MIRROR
:
173 return GetActorPartCount() + 3; // equipment
174 case IE_ANI_TWENTYTWO
:
175 return GetActorPartCount() + 3; // equipment
177 return GetActorPartCount();
181 void CharAnimations::SetArmourLevel(int ArmourLevel
)
183 if (AvatarsRowNum
==~0u) return;
184 //ignore ArmourLevel for the static pst anims (all sprites are displayed)
185 if (AvatarTable
[AvatarsRowNum
].AnimationType
== IE_ANI_PST_GHOST
) {
188 strncpy( ResRef
, AvatarTable
[AvatarsRowNum
].Prefixes
[ArmourLevel
], 8 );
193 //RangedType could be weird, reducing its value to 0,1,2
194 void CharAnimations::SetRangedType(int rt
)
196 if ((unsigned int) rt
<2) {
197 RangedType
=(ieByte
) rt
;
203 void CharAnimations::SetWeaponType(int wt
)
205 if (wt
!= WeaponType
) {
211 void CharAnimations::SetHelmetRef(const char* ref
)
213 HelmetRef
[0] = ref
[0];
214 HelmetRef
[1] = ref
[1];
216 // TODO: Only drop helmet anims?
217 // Note: this doesn't happen "often", so this isn't a performance
220 gamedata
->FreePalette(palette
[PAL_HELMET
], 0);
221 gamedata
->FreePalette(modifiedPalette
[PAL_HELMET
], 0);
224 void CharAnimations::SetWeaponRef(const char* ref
)
226 WeaponRef
[0] = ref
[0];
227 WeaponRef
[1] = ref
[1];
229 // TODO: Only drop weapon anims?
231 gamedata
->FreePalette(palette
[PAL_WEAPON
], 0);
232 gamedata
->FreePalette(modifiedPalette
[PAL_WEAPON
], 0);
235 void CharAnimations::SetOffhandRef(const char* ref
)
237 OffhandRef
[0] = ref
[0];
238 OffhandRef
[1] = ref
[1];
240 // TODO: Only drop shield/offhand anims?
242 gamedata
->FreePalette(palette
[PAL_OFFHAND
], 0);
243 gamedata
->FreePalette(modifiedPalette
[PAL_OFFHAND
], 0);
246 void CharAnimations::LockPalette(const ieDword
*gradients
)
248 if (lockPalette
) return;
249 //cannot lock colors for PST animations
250 if (GetAnimType() >= IE_ANI_PST_ANIMATION_1
)
254 //force initialisation of animation
255 SetColors( gradients
);
257 if (palette
[PAL_MAIN
]) {
262 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
263 static const char *StancePrefix
[]={"3","2","5","5","4","4","2","2","5","4","1","3","3","3","4","1","4","4","4"};
264 static const char *CyclePrefix
[]= {"0","0","1","1","1","1","0","0","1","1","0","1","1","1","1","1","1","1","1"};
265 static const unsigned int CycleOffset
[] = {0, 0, 0, 0, 0, 9, 0, 0, 0, 18, 0, 0, 9, 18, 0, 0, 0, 0, 0};
267 void CharAnimations::SetColors(const ieDword
*arg
)
270 SetupColors(PAL_MAIN
);
271 SetupColors(PAL_WEAPON
);
272 SetupColors(PAL_OFFHAND
);
273 SetupColors(PAL_HELMET
);
276 void CharAnimations::SetupColors(PaletteType type
)
278 Palette
* pal
= palette
[(int)type
];
288 if (GetAnimType() >= IE_ANI_PST_ANIMATION_1
) {
289 // Only do main palette
290 if (type
!= PAL_MAIN
) {
293 // TODO: handle equipment colour glows
295 // Colors[6] is the COLORCOUNT stat in PST.
296 // It tells how many customisable color slots we have.
297 // The color slots start from the end of the palette and go
298 // backwards. There are 6 available slots with a size of 32 each.
299 // Actually, the slots seem to be written in the cre file
300 // but we ignore them, i'm not sure this is correct
301 int colorcount
= Colors
[6];
303 //the color count shouldn't be more than 6!
304 if (colorcount
>6) colorcount
=6;
305 int dest
= 256-colorcount
*size
;
306 bool needmod
= false;
307 if (GlobalColorMod
.type
!= RGBModifier::NONE
) {
310 if ((colorcount
== 0) && (needmod
==false) ) {
311 gamedata
->FreePalette(palette
[PAL_MAIN
], PaletteResRef
);
315 for (int i
= 0; i
< colorcount
; i
++) {
316 core
->GetPalette( Colors
[i
]&255, size
,
317 &palette
[PAL_MAIN
]->col
[dest
] );
322 if (!modifiedPalette
[PAL_MAIN
])
323 modifiedPalette
[PAL_MAIN
] = new Palette();
324 modifiedPalette
[PAL_MAIN
]->SetupGlobalRGBModification(palette
[PAL_MAIN
], GlobalColorMod
);
326 gamedata
->FreePalette(modifiedPalette
[PAL_MAIN
], 0);
331 int PType
= NoPalette();
332 if ( PType
&& (type
== PAL_MAIN
) ) {
333 bool needmod
= false;
334 if (GlobalColorMod
.type
!= RGBModifier::NONE
) {
337 if (!needmod
&& PaletteResRef
[0]) {
338 gamedata
->FreePalette(palette
[PAL_MAIN
], PaletteResRef
);
341 //handling special palettes like MBER_BL (black bear)
343 if (GetAnimType()==IE_ANI_NINE_FRAMES
) {
344 snprintf(PaletteResRef
,9,"%.4s_%-.2s%s",ResRef
, (char *) &PType
, StancePrefix
[StanceID
]);
346 snprintf(PaletteResRef
,9,"%.4s_%-.2s",ResRef
, (char *) &PType
);
348 strlwr(PaletteResRef
);
349 Palette
*tmppal
= gamedata
->GetPalette(PaletteResRef
);
351 palette
[PAL_MAIN
] = tmppal
;
357 if (!modifiedPalette
[PAL_MAIN
])
358 modifiedPalette
[PAL_MAIN
] = new Palette();
359 modifiedPalette
[PAL_MAIN
]->SetupGlobalRGBModification(palette
[PAL_MAIN
], GlobalColorMod
);
361 gamedata
->FreePalette(modifiedPalette
[PAL_MAIN
], 0);
366 pal
->SetupPaperdollColours(Colors
, (int)type
);
372 bool needmod
= false;
373 if (GlobalColorMod
.type
!= RGBModifier::NONE
) {
376 for (i
= 0; i
< 7; ++i
) {
377 if (ColorMods
[i
+8*((int)type
)].type
!= RGBModifier::NONE
)
384 if (!modifiedPalette
[(int)type
])
385 modifiedPalette
[(int)type
] = new Palette();
387 if (GlobalColorMod
.type
!= RGBModifier::NONE
) {
388 modifiedPalette
[(int)type
]->SetupGlobalRGBModification(palette
[(int)type
], GlobalColorMod
);
390 modifiedPalette
[(int)type
]->SetupRGBModification(palette
[(int)type
],ColorMods
, (int)type
);
393 gamedata
->FreePalette(modifiedPalette
[(int)type
], 0);
398 Palette
* CharAnimations::GetPartPalette(int part
)
400 int actorPartCount
= GetActorPartCount();
401 PaletteType type
= PAL_MAIN
;
403 if (part
== actorPartCount
) type
= PAL_WEAPON
;
404 if (part
== actorPartCount
+1) type
= PAL_OFFHAND
;
405 if (part
== actorPartCount
+2) type
= PAL_HELMET
;
407 if (modifiedPalette
[(int)type
])
408 return modifiedPalette
[(int)type
];
410 return palette
[(int)type
];
413 static int compare_avatars(const void *a
, const void *b
)
415 unsigned int aa
= ((AvatarStruct
*)a
)->AnimID
;
416 unsigned int bb
= ((AvatarStruct
*)b
)->AnimID
;
417 return (int) (aa
-bb
);
420 void CharAnimations::InitAvatarsTable()
422 AutoTable
Avatars("avatars");
424 printMessage("CharAnimations", "A critical animation file is missing!\n", LIGHT_RED
);
427 AvatarTable
= (AvatarStruct
*) calloc ( AvatarsCount
= Avatars
->GetRowCount(), sizeof(AvatarStruct
) );
429 DataFileMgr
*resdata
= core
->GetResDataINI();
431 AvatarTable
[i
].AnimID
=(unsigned int) strtol(Avatars
->GetRowName(i
),NULL
,0 );
432 strnlwrcpy(AvatarTable
[i
].Prefixes
[0],Avatars
->QueryField(i
,AV_PREFIX1
),8);
433 strnlwrcpy(AvatarTable
[i
].Prefixes
[1],Avatars
->QueryField(i
,AV_PREFIX2
),8);
434 strnlwrcpy(AvatarTable
[i
].Prefixes
[2],Avatars
->QueryField(i
,AV_PREFIX3
),8);
435 strnlwrcpy(AvatarTable
[i
].Prefixes
[3],Avatars
->QueryField(i
,AV_PREFIX4
),8);
436 AvatarTable
[i
].AnimationType
=(ieByte
) atoi(Avatars
->QueryField(i
,AV_ANIMTYPE
) );
437 AvatarTable
[i
].CircleSize
=(ieByte
) atoi(Avatars
->QueryField(i
,AV_CIRCLESIZE
) );
438 const char *tmp
= Avatars
->QueryField(i
,AV_USE_PALETTE
);
439 //QueryField will always return a zero terminated string
440 //so tmp[0] must exist
441 if ( isalpha (tmp
[0]) ) {
442 //this is a hack, we store 2 letters on an integer
443 //it was allocated with calloc, so don't bother erasing it
444 strncpy( (char *) &AvatarTable
[i
].PaletteType
, tmp
, 3);
447 AvatarTable
[i
].PaletteType
=atoi(Avatars
->QueryField(i
,AV_USE_PALETTE
) );
449 char size
= Avatars
->QueryField(i
,AV_SIZE
)[0];
453 AvatarTable
[i
].Size
= size
;
455 AvatarTable
[i
].WalkScale
= 0;
456 AvatarTable
[i
].RunScale
= 0;
457 AvatarTable
[i
].Bestiary
= -1;
461 snprintf(section
,10,"%d", i
);
463 if (!resdata
->GetKeysCount(section
)) continue;
465 float walkscale
= resdata
->GetKeyAsFloat(section
, "walkscale", 0.0f
);
466 if (walkscale
!= 0.0f
) AvatarTable
[i
].WalkScale
= (int)(1000.0f
/ walkscale
);
467 float runscale
= resdata
->GetKeyAsFloat(section
, "runscale", 0.0f
);
468 if (runscale
!= 0.0f
) AvatarTable
[i
].RunScale
= (int)(1000.0f
/ runscale
);
469 AvatarTable
[i
].Bestiary
= resdata
->GetKeyAsInt(section
, "bestiary", -1);
472 qsort(AvatarTable
, AvatarsCount
, sizeof(AvatarStruct
), compare_avatars
);
475 AutoTable
blood("bloodclr");
477 int rows
= blood
->GetRowCount();
478 for(int i
=0;i
<rows
;i
++) {
479 unsigned long value
= 0;
480 unsigned long rmin
= 0;
481 unsigned long rmax
= 0xffff;
483 valid_number(blood
->QueryField(i
,0), (long &)value
);
484 valid_number(blood
->QueryField(i
,1), (long &)rmin
);
485 valid_number(blood
->QueryField(i
,2), (long &)rmax
);
486 if (value
>255 || rmin
>0xffff || rmax
>0xffff) {
487 printMessage("CharAnimations", "bloodclr entry:", LIGHT_RED
);
488 printf("%02x %04x-%04x ", (unsigned int) value
, (unsigned int) rmin
, (unsigned int) rmax
);
489 printStatus("Invalid value!", LIGHT_RED
);
492 for(int j
=0;j
<AvatarsCount
;j
++) {
493 if (rmax
<AvatarTable
[j
].AnimID
) break;
494 if (rmin
>AvatarTable
[j
].AnimID
) continue;
495 AvatarTable
[j
].BloodColor
= value
;
500 AutoTable
walk("walksnd");
502 int rows
= walk
->GetRowCount();
503 for(int i
=0;i
<rows
;i
++) {
505 unsigned long rmin
= 0;
506 unsigned long rmax
= 0xffff;
507 unsigned int range
= 0;
509 strnuprcpy(value
, walk
->QueryField(i
,0), 8);
510 valid_number(walk
->QueryField(i
,1), (long &)rmin
);
511 valid_number(walk
->QueryField(i
,2), (long &)rmax
);
512 valid_number(walk
->QueryField(i
,3), (long &)range
);
517 for(int j
=0;j
<AvatarsCount
;j
++) {
518 if (rmax
<AvatarTable
[j
].AnimID
) break;
519 if (rmin
>AvatarTable
[j
].AnimID
) continue;
520 memcpy(AvatarTable
[j
].WalkSound
, value
, sizeof(ieResRef
) );
521 AvatarTable
[j
].WalkSoundCount
= range
;
527 CharAnimations::CharAnimations(unsigned int AnimID
, ieDword ArmourLevel
)
531 for (i
= 0; i
< 4; ++i
) {
532 modifiedPalette
[i
] = NULL
;
537 autoSwitchOnEnd
= false;
543 for (i
= 0; i
< MAX_ANIMS
; i
++) {
544 for (j
= 0; j
< MAX_ORIENT
; j
++) {
551 PaletteResRef
[0] = 0;
555 for (i
= 0; i
< 32; ++i
) {
556 ColorMods
[i
].type
= RGBModifier::NONE
;
557 ColorMods
[i
].speed
= 0;
558 // make initial phase depend on location to make the pulse appear
560 ColorMods
[i
].phase
= 5*i
;
562 GlobalColorMod
.type
= RGBModifier::NONE
;
563 GlobalColorMod
.speed
= 0;
564 GlobalColorMod
.phase
= 0;
567 AvatarsRowNum
=AvatarsCount
;
568 if (core
->HasFeature(GF_ONE_BYTE_ANIMID
) ) {
569 ieDword tmp
= AnimID
&0xf000;
570 if (tmp
==0x6000 || tmp
==0xe000) {
575 while (AvatarsRowNum
--) {
576 if (AvatarTable
[AvatarsRowNum
].AnimID
<=AnimID
) {
577 SetArmourLevel( ArmourLevel
);
582 printMessage("CharAnimations", " ", LIGHT_RED
);
583 printf("Invalid or nonexistent avatar entry:%04X\n", AnimID
);
586 //we have to drop them when armourlevel changes
587 void CharAnimations::DropAnims()
590 int partCount
= GetTotalPartCount();
591 for (int StanceID
= 0; StanceID
< MAX_ANIMS
; StanceID
++) {
592 for (int i
= 0; i
< MAX_ORIENT
; i
++) {
593 if (Anims
[StanceID
][i
]) {
594 tmppoi
= Anims
[StanceID
][i
];
595 for (int j
= 0; j
< partCount
; j
++)
596 delete Anims
[StanceID
][i
][j
];
599 // anims can only be duplicated at the Animation** level
600 for (int IDb
=StanceID
;IDb
< MAX_ANIMS
; IDb
++) {
601 for (int i2
= 0; i2
<MAX_ORIENT
; i2
++) {
602 if (Anims
[IDb
][i2
] == tmppoi
) {
612 CharAnimations::~CharAnimations(void)
615 gamedata
->FreePalette(palette
[PAL_MAIN
], PaletteResRef
);
617 for (i
= 1; i
< 4; ++i
)
618 gamedata
->FreePalette(palette
[i
], 0);
619 for (i
= 0; i
< 4; ++i
)
620 gamedata
->FreePalette(modifiedPalette
[i
], 0);
623 This is a simple Idea of how the animation are coded
625 There are the following animation types:
627 IE_ANI_CODE_MIRROR: The code automatically mirrors the needed frames
628 (as in the example above)
630 These Animations are stores using the following template:
631 [NAME][ARMORTYPE][ACTIONCODE]
633 Each BAM File contains only 9 Orientations, the missing 7 Animations
634 are created by Horizontally Mirroring the 1-7 Orientations.
636 IE_ANI_CODE_MIRROR_2: another mirroring type with more animations
637 [NAME]g[1,11-15,2,21-26]
639 IE_ANI_CODE_MIRROR_3: Almost identical to IE_ANI_CODE_MIRROR_2, but with fewer cycles in g26
641 IE_ANI_ONE_FILE: The whole animation is in one file, no mirroring needed.
642 Each animation group is 16 Cycles.
644 IE_ANI_TWO_FILES: The whole animation is in 2 files. The East and West part are in 2 BAM Files.
649 Each BAM File contains many animation groups, each animation group
650 stores 5 Orientations, the missing 3 are stored in East BAM Files.
653 IE_ANI_FOUR_FILES: The Animation is coded in Four Files. Probably it is an old Two File animation with
654 additional frames added in a second time.
656 IE_ANI_FOUR_FILES_2: Like IE_ANI_FOUR_FILES but with only 16 cycles per frame.
658 IE_ANI_TWENTYTWO: This Animation Type stores the Animation in the following format
659 [NAME][ACTIONCODE][/E]
660 ACTIONCODE=A1-6, CA, SX, SA (sling is A1)
661 The g1 file contains several animation states. See MHR
662 Probably it could use A7-9 files too, bringing the file numbers to 28.
663 This is the original bg1 format.
665 IE_ANI_SIX_FILES: The layout for these files is:
667 Each state contains 16 Orientations, but the last 6 are stored in the East file.
668 g1 contains only the walking animation.
669 G2 contains stand, ready, get hit, die and twitch.
670 g3 contains 3 attacks.
672 IE_ANI_SIX_FILES_2: Similar to SIX_FILES, but the orientation numbers are reduced like in FOUR_FILES. Only one animation uses it: MOGR
674 IE_ANI_TWO_FILES_2: Animations using this type are stored using the following template:
676 Each state contains 8 Orientations, but the second 4 are stored in the East file.
677 From the standard animations, only AHRS and ACOW belong to this type.
679 IE_ANI_TWO_FILES_3: Animations using this type are stored using the following template:
680 [NAME][ACTIONTYPE][/E]
686 Each BAM File contains one animation group, each animation group
687 stores 5 Orientations though the files contain all 8 Cycles, the missing 3 are stored in East BAM Files in Cycle: Stance*8+ (5,6,7).
688 This is the standard IWD animation, but BG2 also has it.
691 IE_ANI_TWO_FILES_3B: Animations using this type are stored using the following template:
692 [NAME][ACTIONTYPE][/E]
698 This is a cut down version of IE_ANI_TWO_FILES_3. A2, CA and SP suffixes are missing.
699 This is the standard IWD animation, but BG2 also has it.
702 IE_ANI_FOUR_FRAMES: These animations are large, four bams make a frame.
705 IE_ANI_NINE_FRAMES: These animations are huge, nine bams make a frame.
708 IE_ANI_FRAGMENT: These animations are used for projectile graphics.
709 A single file contains 5 cycles (code mirror for east animation)
711 IE_ANI_PST_ANIMATION_1:
712 IE_ANI_PST_ANIMATION_2:
713 IE_ANI_PST_ANIMATION_3:
714 Planescape: Torment Animations are stored in a different
715 way than the other games. This format uses the following template:
716 [C/D][ACTIONTYPE][NAME][B]
721 Each Animation stores 5 Orientations, which are automatically mirrored
722 to form an 8 Orientation Animation. PST Animations have a different Palette
723 format. This Animation Type handles the PST Palette format too.
725 NOTE: Walking/Running animations store 9 Orientations.
726 The second variation is missing the resting stance (STD) and the transitions.
727 These creatures are always in combat stance (don't rest).
728 Animation_3 is without STC (combat stance), they are always standing
730 IE_ANI_PST_STAND: This is a modified PST animation, it contains only a
731 Standing image for every orientations, it follows the
732 [C/D]STD[NAME][B] standard.
734 IE_ANI_PST_GHOST: This is a special static animation with no standard
735 All armourlevels are drawn simultaneously. There is no orientation or stance.
738 WEST PART | EAST PART
741 NW 006 007 008 009 010 NE
745 SW 002 001 000 015 014 SE
752 Animation
** CharAnimations::GetAnimation(unsigned char Stance
, unsigned char Orient
)
754 if (StanceID
>=MAX_ANIMS
) {
755 printf("Illegal stance ID\n");
759 //for paletted dragon animations, we need the stance id
760 StanceID
= nextStanceID
= Stance
;
761 int AnimType
= GetAnimType();
763 //alter stance here if it is missing and you know a substitute
764 //probably we should feed this result back to the actor?
766 case -1: //invalid animation
769 case IE_ANI_PST_STAND
:
770 StanceID
=IE_ANI_AWAKE
;
772 case IE_ANI_PST_GHOST
:
773 StanceID
=IE_ANI_AWAKE
;
776 case IE_ANI_PST_ANIMATION_3
: //stc->std
777 if (StanceID
==IE_ANI_READY
) {
778 StanceID
=IE_ANI_AWAKE
;
781 case IE_ANI_PST_ANIMATION_2
: //std->stc
782 if (StanceID
==IE_ANI_AWAKE
) {
783 StanceID
=IE_ANI_READY
;
787 //pst animations don't have separate animation for sleep/die
788 if (AnimType
>= IE_ANI_PST_ANIMATION_1
) {
789 if (StanceID
==IE_ANI_DIE
) {
790 StanceID
=IE_ANI_TWITCH
;
794 //TODO: Implement Auto Resource Loading
795 //setting up the sequencing of animation cycles
796 autoSwitchOnEnd
= false;
799 nextStanceID
= IE_ANI_READY
;
800 autoSwitchOnEnd
= true;
802 case IE_ANI_SLEEP
: //going to sleep
803 nextStanceID
= IE_ANI_TWITCH
;
804 autoSwitchOnEnd
= true;
806 case IE_ANI_TWITCH
: //dead, sleeping
807 autoSwitchOnEnd
= false;
809 case IE_ANI_DIE
: //going to die
810 nextStanceID
= IE_ANI_TWITCH
;
811 autoSwitchOnEnd
= true;
815 case IE_ANI_CAST
: // looping
822 case IE_ANI_HEAD_TURN
:
823 case IE_ANI_PST_START
:
824 nextStanceID
= IE_ANI_AWAKE
;
825 autoSwitchOnEnd
= true;
827 case IE_ANI_CONJURE
: //ending
830 case IE_ANI_ATTACK_JAB
:
831 case IE_ANI_ATTACK_SLASH
:
832 case IE_ANI_ATTACK_BACKSLASH
:
833 nextStanceID
= IE_ANI_READY
;
834 autoSwitchOnEnd
= true;
837 printf ("Invalid Stance: %d\n", StanceID
);
840 Animation
** anims
= Anims
[StanceID
][Orient
];
846 int partCount
= GetTotalPartCount();
847 int actorPartCount
= GetActorPartCount();
848 if (partCount
< 0) return 0;
849 anims
= new Animation
*[partCount
];
851 EquipResRefData
* equipdat
= 0;
852 for (int part
= 0; part
< partCount
; ++part
)
856 //newresref is based on the prefix (ResRef) and various
858 //this is longer than expected so it won't overflow
860 unsigned char Cycle
= 0;
861 if (part
< actorPartCount
) {
862 // Character animation parts
864 if (equipdat
) delete equipdat
;
866 //we need this long for special anims
867 strncpy( NewResRef
, ResRef
, 8 );
868 GetAnimResRef( StanceID
, Orient
, NewResRef
, Cycle
, part
, equipdat
);
870 // Equipment animation parts
873 if (GetSize() == 0) continue;
875 if (part
== actorPartCount
) {
876 if (WeaponRef
[0] == 0) continue;
878 GetEquipmentResRef(WeaponRef
,false,NewResRef
,Cycle
,equipdat
);
879 } else if (part
== actorPartCount
+1) {
880 if (OffhandRef
[0] == 0) continue;
881 if (WeaponType
== IE_ANI_WEAPON_2H
) continue;
883 if (WeaponType
== IE_ANI_WEAPON_1H
) {
884 GetEquipmentResRef(OffhandRef
,false,NewResRef
,Cycle
,
886 } else { // IE_ANI_WEAPON_2W
887 GetEquipmentResRef(OffhandRef
,true,NewResRef
,Cycle
,
890 } else if (part
== actorPartCount
+2) {
891 if (HelmetRef
[0] == 0) continue;
893 GetEquipmentResRef(HelmetRef
,false,NewResRef
,Cycle
,equipdat
);
896 NewResRef
[8]=0; //cutting right to size
898 AnimationFactory
* af
= ( AnimationFactory
* )
899 gamedata
->GetFactoryResource( NewResRef
,
900 IE_BAM_CLASS_ID
, IE_NORMAL
);
903 if (part
< actorPartCount
) {
905 snprintf(warnbuf
, 200,
906 "Couldn't create animationfactory: %s (%04x)\n", NewResRef
, GetAnimationID());
907 printMessage("CharAnimations",warnbuf
,LIGHT_RED
);
908 for (int i
= 0; i
< part
; ++i
)
914 // not fatal if animation for equipment is missing
919 Animation
* a
= af
->GetCycle( Cycle
);
923 if (part
< actorPartCount
) {
925 snprintf(warnbuf
, 200,
926 "Couldn't load animation: %s, cycle %d\n",
928 printMessage("CharAnimations",warnbuf
,LIGHT_RED
);
929 for (int i
= 0; i
< part
; ++i
)
935 // not fatal if animation for equipment is missing
940 if (part
< actorPartCount
) {
941 //if you need to revert this change, consider true paletted
942 //animations which need a GlobalColorMod (mgir for example)
944 //if (!palette[PAL_MAIN] && ((GlobalColorMod.type!=RGBModifier::NONE) || (NoPalette()!=1)) ) {
945 if(!palette
[PAL_MAIN
]) {
946 // This is the first time we're loading an Animation.
947 // We copy the palette of its first frame into our own palette
948 palette
[PAL_MAIN
] = a
->GetFrame(0)->GetPalette()->Copy();
949 // ...and setup the colours properly
950 SetupColors(PAL_MAIN
);
952 } else if (part
== actorPartCount
) {
953 if (!palette
[PAL_WEAPON
]) {
954 palette
[PAL_WEAPON
] = a
->GetFrame(0)->GetPalette()->Copy();
955 SetupColors(PAL_WEAPON
);
957 } else if (part
== actorPartCount
+1) {
958 if (!palette
[PAL_OFFHAND
]) {
959 palette
[PAL_OFFHAND
] = a
->GetFrame(0)->GetPalette()->Copy();
960 SetupColors(PAL_OFFHAND
);
962 } else if (part
== actorPartCount
+2) {
963 if (!palette
[PAL_HELMET
]) {
964 palette
[PAL_HELMET
] = a
->GetFrame(0)->GetPalette()->Copy();
965 SetupColors(PAL_HELMET
);
969 //animation is affected by game flags
970 a
->gameAnimation
= true;
973 //setting up the sequencing of animation cycles
979 case IE_ANI_PST_START
:
980 case IE_ANI_HEAD_TURN
:
984 case IE_ANI_ATTACK_JAB
:
985 case IE_ANI_ATTACK_SLASH
:
986 case IE_ANI_ATTACK_BACKSLASH
:
987 a
->Flags
|= A_ANI_PLAYONCE
;
991 a
->playReversed
= true;
992 a
->Flags
|= A_ANI_PLAYONCE
;
995 switch (GetAnimType()) {
996 case IE_ANI_NINE_FRAMES
: //dragon animations
997 case IE_ANI_FOUR_FRAMES
: //wyvern animations
999 case IE_ANI_CODE_MIRROR
:
1000 case IE_ANI_CODE_MIRROR_2
: //9 orientations
1001 case IE_ANI_CODE_MIRROR_3
:
1002 case IE_ANI_PST_ANIMATION_3
: //no stc just std
1003 case IE_ANI_PST_ANIMATION_2
: //no std just stc
1004 case IE_ANI_PST_ANIMATION_1
:
1005 case IE_ANI_FRAGMENT
:
1007 a
->MirrorAnimation( );
1014 // make animarea of part 0 encompass the animarea of the other parts
1016 anims
[0]->AddAnimArea(a
);
1020 switch (GetAnimType()) {
1021 case IE_ANI_NINE_FRAMES
: //dragon animations
1022 case IE_ANI_FOUR_FRAMES
: //wyvern animations
1024 case IE_ANI_CODE_MIRROR
:
1025 case IE_ANI_SIX_FILES
: //16 anims some are stored elsewhere
1026 case IE_ANI_ONE_FILE
: //16 orientations
1027 case IE_ANI_CODE_MIRROR_2
: //9 orientations
1028 case IE_ANI_CODE_MIRROR_3
:
1029 Anims
[StanceID
][Orient
] = anims
;
1031 case IE_ANI_TWO_FILES
:
1032 case IE_ANI_TWENTYTWO
:
1033 case IE_ANI_TWO_FILES_2
:
1034 case IE_ANI_TWO_FILES_3
:
1035 case IE_ANI_TWO_FILES_3B
:
1036 case IE_ANI_FOUR_FILES
:
1037 case IE_ANI_FOUR_FILES_2
:
1038 case IE_ANI_SIX_FILES_2
:
1039 case IE_ANI_FRAGMENT
:
1041 Anims
[StanceID
][Orient
] = anims
;
1042 Anims
[StanceID
][Orient
+ 1] = anims
;
1045 case IE_ANI_PST_ANIMATION_3
: //no stc just std
1046 case IE_ANI_PST_ANIMATION_2
: //no std just stc
1047 case IE_ANI_PST_ANIMATION_1
:
1051 case IE_ANI_PST_START
:
1052 Anims
[StanceID
][Orient
] = anims
;
1056 Anims
[StanceID
][Orient
] = anims
;
1057 Anims
[StanceID
][Orient
+ 1] = anims
;
1062 case IE_ANI_PST_STAND
:
1064 Anims
[StanceID
][Orient
] = anims
;
1065 Anims
[StanceID
][Orient
+1] = anims
;
1067 case IE_ANI_PST_GHOST
:
1069 StanceID
= IE_ANI_AWAKE
;
1070 Anims
[StanceID
][0] = anims
;
1073 printMessage("CharAnimations","Unknown animation type\n",LIGHT_RED
);
1078 return Anims
[StanceID
][Orient
];
1081 static const int one_file
[19]={2, 1, 0, 0, 2, 3, 0, 1, 0, 4, 1, 0, 0, 0, 3, 1, 4, 4, 4};
1083 void CharAnimations::GetAnimResRef(unsigned char StanceID
,
1084 unsigned char Orient
,
1085 char* NewResRef
, unsigned char& Cycle
,
1086 int Part
, EquipResRefData
*& EquipData
)
1091 switch (GetAnimType()) {
1092 case IE_ANI_FOUR_FRAMES
:
1093 AddFFSuffix( NewResRef
, StanceID
, Cycle
, Orient
, Part
);
1096 case IE_ANI_NINE_FRAMES
:
1097 AddNFSuffix( NewResRef
, StanceID
, Cycle
, Orient
, Part
);
1100 case IE_ANI_CODE_MIRROR
:
1101 AddVHRSuffix( NewResRef
, StanceID
, Cycle
, Orient
, EquipData
);
1105 Cycle
= (ieByte
) ((StanceID
&1) * 9 + SixteenToNine
[Orient
]);
1108 case IE_ANI_FRAGMENT
:
1109 Cycle
= SixteenToFive
[Orient
];
1112 case IE_ANI_ONE_FILE
:
1113 Cycle
= (ieByte
) (one_file
[StanceID
] * 16 + Orient
);
1116 case IE_ANI_SIX_FILES
:
1117 AddSixSuffix( NewResRef
, StanceID
, Cycle
, Orient
);
1120 case IE_ANI_TWENTYTWO
: //5+3 animations
1121 AddMHRSuffix( NewResRef
, StanceID
, Cycle
, Orient
, EquipData
);
1124 case IE_ANI_TWO_FILES_2
: //4+4 animations
1125 AddLR2Suffix( NewResRef
, StanceID
, Cycle
, Orient
);
1128 case IE_ANI_TWO_FILES_3
: //IWD style anims
1129 AddMMRSuffix( NewResRef
, StanceID
, Cycle
, Orient
);
1132 case IE_ANI_TWO_FILES_3B
: //IWD style anims
1133 AddMMR2Suffix( NewResRef
, StanceID
, Cycle
, Orient
);
1136 case IE_ANI_TWO_FILES
:
1137 AddTwoFileSuffix(NewResRef
, StanceID
, Cycle
, Orient
);
1140 case IE_ANI_FOUR_FILES
:
1141 AddLRSuffix( NewResRef
, StanceID
, Cycle
, Orient
, EquipData
);
1144 case IE_ANI_FOUR_FILES_2
:
1145 AddLRSuffix2( NewResRef
, StanceID
, Cycle
, Orient
, EquipData
);
1148 case IE_ANI_SIX_FILES_2
: //MOGR (variant of FOUR_FILES)
1149 AddLR3Suffix( NewResRef
, StanceID
, Cycle
, Orient
);
1152 case IE_ANI_CODE_MIRROR_2
: //9 orientations
1153 AddVHR2Suffix( NewResRef
, StanceID
, Cycle
, Orient
);
1156 case IE_ANI_CODE_MIRROR_3
: // like IE_ANI_CODE_MIRROR_2 but with fewer cycles in g26
1157 AddVHR3Suffix( NewResRef
, StanceID
, Cycle
, Orient
);
1160 case IE_ANI_PST_ANIMATION_1
:
1161 case IE_ANI_PST_ANIMATION_2
:
1162 case IE_ANI_PST_ANIMATION_3
:
1163 AddPSTSuffix( NewResRef
, StanceID
, Cycle
, Orient
);
1166 case IE_ANI_PST_STAND
:
1167 sprintf(NewResRef
,"%cSTD%4s",ResRef
[0], ResRef
+1);
1168 Cycle
= (ieByte
) SixteenToFive
[Orient
];
1170 case IE_ANI_PST_GHOST
: // pst static animations
1171 //still doesn't handle the second cycle of the golem anim
1173 strnlwrcpy(NewResRef
, AvatarTable
[AvatarsRowNum
].Prefixes
[Part
], 8);
1176 sprintf (tmp
,"Unknown animation type in avatars.2da row: %d\n", AvatarsRowNum
);
1177 printMessage ("CharAnimations",tmp
, LIGHT_RED
);
1182 void CharAnimations::GetEquipmentResRef(const char* equipRef
, bool offhand
,
1183 char* ResRef
, unsigned char& Cycle
, EquipResRefData
* equip
)
1185 switch (GetAnimType()) {
1186 case IE_ANI_FOUR_FILES
:
1187 case IE_ANI_FOUR_FILES_2
:
1188 GetLREquipmentRef( ResRef
, Cycle
, equipRef
, offhand
, equip
);
1190 case IE_ANI_CODE_MIRROR
:
1191 GetVHREquipmentRef( ResRef
, Cycle
, equipRef
, offhand
, equip
);
1193 case IE_ANI_TWENTYTWO
:
1194 GetMHREquipmentRef( ResRef
, Cycle
, equipRef
, offhand
, equip
);
1197 printMessage ("CharAnimations", "Unsupported animation type for equipment animation.\n", LIGHT_RED
);
1203 const int* CharAnimations::GetZOrder(unsigned char Orient
)
1205 switch (GetAnimType()) {
1206 case IE_ANI_CODE_MIRROR
:
1207 return zOrder_Mirror16
[Orient
];
1208 case IE_ANI_TWENTYTWO
:
1209 return zOrder_8
[Orient
/2];
1210 case IE_ANI_FOUR_FILES
:
1218 void CharAnimations::AddPSTSuffix(char* ResRef
, unsigned char StanceID
,
1219 unsigned char& Cycle
, unsigned char Orient
)
1225 case IE_ANI_ATTACK_SLASH
:
1226 case IE_ANI_ATTACK_JAB
:
1227 case IE_ANI_ATTACK_BACKSLASH
:
1228 Cycle
=SixteenToFive
[Orient
];
1229 Prefix
="at1"; break;
1231 Cycle
=SixteenToFive
[Orient
];
1232 Prefix
="hit"; break;
1235 Cycle
=SixteenToFive
[Orient
];
1236 Prefix
="gup"; break;
1238 Cycle
=SixteenToFive
[Orient
];
1239 Prefix
="std"; break;
1241 Cycle
=SixteenToFive
[Orient
];
1242 Prefix
="stc"; break;
1246 Cycle
=SixteenToFive
[Orient
];
1247 Prefix
="dfb"; break;
1249 Cycle
=SixteenToNine
[Orient
];
1250 Prefix
="run"; break;
1252 Cycle
=SixteenToNine
[Orient
];
1253 Prefix
="wlk"; break;
1254 case IE_ANI_HEAD_TURN
:
1255 Cycle
=SixteenToFive
[Orient
];
1258 sprintf(ResRef
,"%c%3s%4s",this->ResRef
[0], Prefix
, this->ResRef
+1);
1259 if (gamedata
->Exists(ResRef
, IE_BAM_CLASS_ID
) ) {
1264 sprintf(ResRef
,"%c%3s%4s",this->ResRef
[0], Prefix
, this->ResRef
+1);
1265 if (gamedata
->Exists(ResRef
, IE_BAM_CLASS_ID
) ) {
1270 case IE_ANI_PST_START
:
1272 Prefix
="ms1"; break;
1273 default: //just in case
1274 Cycle
=SixteenToFive
[Orient
];
1275 Prefix
="stc"; break;
1277 sprintf(ResRef
,"%c%3s%4s",this->ResRef
[0], Prefix
, this->ResRef
+1);
1280 void CharAnimations::AddVHR2Suffix(char* ResRef
, unsigned char StanceID
,
1281 unsigned char& Cycle
, unsigned char Orient
)
1283 Cycle
=SixteenToNine
[Orient
];
1286 case IE_ANI_ATTACK
: //temporarily
1287 case IE_ANI_ATTACK_BACKSLASH
:
1288 strcat( ResRef
, "g21" );
1291 case IE_ANI_ATTACK_SLASH
:
1292 strcat( ResRef
, "g2" );
1295 case IE_ANI_ATTACK_JAB
:
1296 strcat( ResRef
, "g26" );
1300 case IE_ANI_CAST
: //looping
1301 strcat( ResRef
, "g25" );
1305 case IE_ANI_CONJURE
://ending
1306 strcat( ResRef
, "g26" );
1311 strcat( ResRef
, "g24" );
1315 case IE_ANI_HEAD_TURN
:
1317 strcat( ResRef
, "g12" );
1322 strcat( ResRef
, "g15" );
1327 strcat( ResRef
, "g14" );
1334 case IE_ANI_PST_START
:
1335 strcat( ResRef
, "g14" );
1340 strcat( ResRef
, "g13" );
1345 strcat( ResRef
, "g1" );
1350 strcat( ResRef
, "g11" );
1353 printf("VHR2 Animation: unhandled stance: %s %d\n", ResRef
, StanceID
);
1359 void CharAnimations::AddVHR3Suffix(char* ResRef
, unsigned char StanceID
,
1360 unsigned char& Cycle
, unsigned char Orient
)
1362 Cycle
=SixteenToNine
[Orient
];
1365 case IE_ANI_ATTACK
: //temporarily
1366 case IE_ANI_ATTACK_BACKSLASH
:
1367 strcat( ResRef
, "g21" );
1370 case IE_ANI_ATTACK_SLASH
:
1371 strcat( ResRef
, "g2" );
1374 case IE_ANI_ATTACK_JAB
:
1375 strcat( ResRef
, "g26" );
1379 case IE_ANI_CAST
: //looping
1380 strcat( ResRef
, "g25" );
1384 case IE_ANI_CONJURE
://ending
1385 strcat( ResRef
, "g26" );
1390 strcat( ResRef
, "g24" );
1394 case IE_ANI_HEAD_TURN
:
1396 strcat( ResRef
, "g12" );
1401 strcat( ResRef
, "g15" );
1406 strcat( ResRef
, "g14" );
1413 case IE_ANI_PST_START
:
1414 strcat( ResRef
, "g14" );
1419 strcat( ResRef
, "g13" );
1424 strcat( ResRef
, "g1" );
1429 strcat( ResRef
, "g11" );
1432 printf("VHR3 Animation: unhandled stance: %s %d\n", ResRef
, StanceID
);
1438 // Note: almost like SixSuffix
1439 void CharAnimations::AddFFSuffix(char* ResRef
, unsigned char StanceID
,
1440 unsigned char& Cycle
, unsigned char Orient
, int Part
)
1442 Cycle
=SixteenToNine
[Orient
];
1445 strcat( ResRef
, "g1" );
1449 case IE_ANI_ATTACK_SLASH
:
1450 strcat( ResRef
, "g3" );
1453 case IE_ANI_ATTACK_BACKSLASH
:
1454 strcat( ResRef
, "g3" );
1458 case IE_ANI_ATTACK_JAB
:
1460 case IE_ANI_CONJURE
:
1461 strcat( ResRef
, "g3" );
1465 case IE_ANI_HEAD_TURN
: //could be wrong
1467 strcat( ResRef
, "g2" );
1471 strcat( ResRef
, "g2" );
1476 strcat( ResRef
, "g2" );
1483 case IE_ANI_PST_START
:
1484 strcat( ResRef
, "g2" );
1489 strcat( ResRef
, "g2" );
1494 printf("Four frames Animation: unhandled stance: %s %d\n", ResRef
, StanceID
);
1499 ResRef
[6]=(char) (Part
+'1');
1503 void CharAnimations::AddNFSuffix(char* ResRef
, unsigned char StanceID
,
1504 unsigned char& Cycle
, unsigned char Orient
, int Part
)
1508 Cycle
= SixteenToNine
[Orient
];
1509 snprintf(prefix
, 9, "%s%s%d%s%d", ResRef
, StancePrefix
[StanceID
], Part
+1,
1510 CyclePrefix
[StanceID
], Cycle
);
1511 strnlwrcpy(ResRef
,prefix
,8);
1512 Cycle
=(ieByte
) (Cycle
+CycleOffset
[StanceID
]);
1517 //static const char *SlashPrefix[]={"a1","a4","a7"};
1518 //static const char *BackPrefix[]={"a2","a5","a8"};
1519 //static const char *JabPrefix[]={"a3","a6","a9"};
1520 static const char *SlashPrefix
[]={"a1","a2","a7"};
1521 static const char *BackPrefix
[]={"a3","a4","a8"};
1522 static const char *JabPrefix
[]={"a5","a6","a9"};
1523 static const char *RangedPrefix
[]={"sa","sx","ss"};
1524 static const char *RangedPrefixOld
[]={"sa","sx","a1"};
1526 void CharAnimations::AddVHRSuffix(char* ResRef
, unsigned char StanceID
,
1527 unsigned char& Cycle
, unsigned char Orient
, EquipResRefData
*& EquipData
)
1529 Cycle
= SixteenToNine
[Orient
];
1530 EquipData
= new EquipResRefData
;
1531 EquipData
->Suffix
[0] = 0;
1534 case IE_ANI_ATTACK_SLASH
:
1535 strcat( ResRef
, SlashPrefix
[WeaponType
] );
1536 strcpy( EquipData
->Suffix
, SlashPrefix
[WeaponType
] );
1539 case IE_ANI_ATTACK_BACKSLASH
:
1540 strcat( ResRef
, BackPrefix
[WeaponType
] );
1541 strcpy( EquipData
->Suffix
, BackPrefix
[WeaponType
] );
1544 case IE_ANI_ATTACK_JAB
:
1545 strcat( ResRef
, JabPrefix
[WeaponType
] );
1546 strcpy( EquipData
->Suffix
, JabPrefix
[WeaponType
] );
1550 strcat( ResRef
, "g17" );
1551 strcpy( EquipData
->Suffix
, "g1" );
1555 case IE_ANI_CAST
: //looping
1556 strcat( ResRef
, "ca" );
1557 strcpy( EquipData
->Suffix
, "ca" );
1560 case IE_ANI_CONJURE
: //ending
1561 strcat( ResRef
, "ca" );
1562 strcpy( EquipData
->Suffix
, "ca" );
1567 strcat( ResRef
, "g14" );
1568 strcpy( EquipData
->Suffix
, "g1" );
1573 strcat( ResRef
, "g15" );
1574 strcpy( EquipData
->Suffix
, "g1" );
1577 //I cannot find an emerge animation...
1578 //Maybe is Die reversed
1581 case IE_ANI_PST_START
:
1582 strcat( ResRef
, "g19" );
1583 strcpy( EquipData
->Suffix
, "g1" );
1587 case IE_ANI_HEAD_TURN
:
1589 strcat( ResRef
, "g12" );
1592 strcat( ResRef
, "g18" );
1595 strcpy( EquipData
->Suffix
, "g1" );
1598 //Unknown... maybe only a transparency effect apply
1603 if ( WeaponType
== IE_ANI_WEAPON_2H
) {
1604 strcat( ResRef
, "g13" );
1607 strcat( ResRef
, "g1" );
1610 strcpy( EquipData
->Suffix
, "g1" );
1612 //This depends on the ranged weapon equipped
1614 strcat( ResRef
, RangedPrefix
[RangedType
] );
1615 strcpy( EquipData
->Suffix
, RangedPrefix
[RangedType
] );
1619 strcat( ResRef
, "g16" );
1620 strcpy( EquipData
->Suffix
, "g1" );
1625 strcat( ResRef
, "g16" );
1626 strcpy( EquipData
->Suffix
, "g1" );
1631 strcat( ResRef
, "g11" );
1632 strcpy( EquipData
->Suffix
, "g1" );
1636 printf("VHR Animation: unhandled stance: %s %d\n", ResRef
, StanceID
);
1640 EquipData
->Cycle
= Cycle
;
1643 void CharAnimations::GetVHREquipmentRef(char* ResRef
, unsigned char& Cycle
,
1644 const char* equipRef
, bool offhand
,
1645 EquipResRefData
* equip
)
1647 Cycle
= equip
->Cycle
;
1649 sprintf( ResRef
, "wq%c%c%co%s", GetSize(), equipRef
[0], equipRef
[1], equip
->Suffix
);
1651 sprintf( ResRef
, "wq%c%c%c%s", GetSize(), equipRef
[0], equipRef
[1], equip
->Suffix
);
1655 void CharAnimations::AddSixSuffix(char* ResRef
, unsigned char StanceID
,
1656 unsigned char& Cycle
, unsigned char Orient
)
1660 strcat( ResRef
, "g1" );
1665 case IE_ANI_ATTACK_SLASH
:
1666 strcat( ResRef
, "g3" );
1670 case IE_ANI_ATTACK_BACKSLASH
:
1671 strcat( ResRef
, "g3" );
1672 Cycle
= 16 + Orient
;
1675 case IE_ANI_ATTACK_JAB
:
1676 strcat( ResRef
, "g3" );
1677 Cycle
= 32 + Orient
;
1680 case IE_ANI_HEAD_TURN
: //could be wrong
1682 strcat( ResRef
, "g2" );
1687 strcat( ResRef
, "g2" );
1688 Cycle
= 16 + Orient
;
1692 strcat( ResRef
, "g2" );
1693 Cycle
= 32 + Orient
;
1699 case IE_ANI_PST_START
:
1700 strcat( ResRef
, "g2" );
1701 Cycle
= 48 + Orient
;
1705 strcat( ResRef
, "g2" );
1706 Cycle
= 64 + Orient
;
1710 printf("Six Animation: unhandled stance: %s %d\n", ResRef
, StanceID
);
1716 strcat( ResRef
, "e" );
1720 void CharAnimations::AddLR2Suffix(char* ResRef
, unsigned char StanceID
,
1721 unsigned char& Cycle
, unsigned char Orient
)
1727 case IE_ANI_CAST
: //looping
1728 case IE_ANI_CONJURE
://ending
1737 case IE_ANI_ATTACK_SLASH
:
1738 case IE_ANI_ATTACK_BACKSLASH
:
1739 case IE_ANI_ATTACK_JAB
:
1740 case IE_ANI_HEAD_TURN
:
1747 case IE_ANI_PST_START
:
1748 Cycle
= 24 + Orient
;
1752 Cycle
= 16 + Orient
;
1757 Cycle
= 32 + Orient
;
1760 printf("LR2 Animation: unhandled stance: %s %d\n", ResRef
, StanceID
);
1765 strcat( ResRef
, "g1e" );
1767 strcat( ResRef
, "g1" );
1771 void CharAnimations::AddMHRSuffix(char* ResRef
, unsigned char StanceID
,
1772 unsigned char& Cycle
, unsigned char Orient
, EquipResRefData
*& EquipData
)
1775 EquipData
= new EquipResRefData
;
1776 EquipData
->Suffix
[0] = 0;
1780 case IE_ANI_ATTACK_SLASH
:
1781 strcat (ResRef
, SlashPrefix
[WeaponType
]);
1782 strcpy( EquipData
->Suffix
, SlashPrefix
[WeaponType
] );
1786 case IE_ANI_ATTACK_BACKSLASH
:
1787 strcat (ResRef
, BackPrefix
[WeaponType
]);
1788 strcpy( EquipData
->Suffix
, BackPrefix
[WeaponType
] );
1792 case IE_ANI_ATTACK_JAB
:
1793 strcat (ResRef
, JabPrefix
[WeaponType
]);
1794 strcpy( EquipData
->Suffix
, JabPrefix
[WeaponType
] );
1799 strcat( ResRef
, "g1" );
1800 strcpy( EquipData
->Suffix
, "g1" );
1801 if ( WeaponType
== IE_ANI_WEAPON_2W
) {
1802 Cycle
= 24 + Orient
;
1808 case IE_ANI_CAST
://looping
1809 strcat( ResRef
, "ca" );
1810 strcpy( EquipData
->Suffix
, "ca" );
1814 case IE_ANI_CONJURE
://ending
1815 strcat( ResRef
, "ca" );
1816 strcpy( EquipData
->Suffix
, "ca" );
1821 strcat( ResRef
, "g1" );
1822 strcpy( EquipData
->Suffix
, "g1" );
1823 Cycle
= 40 + Orient
;
1828 case IE_ANI_PST_START
:
1829 strcat( ResRef
, "g1" );
1830 strcpy( EquipData
->Suffix
, "g1" );
1831 Cycle
= 48 + Orient
;
1834 //I cannot find an emerge animation...
1835 //Maybe is Die reversed
1837 strcat( ResRef
, "g1" );
1838 strcpy( EquipData
->Suffix
, "g1" );
1839 Cycle
= 48 + Orient
;
1842 case IE_ANI_HEAD_TURN
:
1843 strcat( ResRef
, "g1" );
1844 strcpy( EquipData
->Suffix
, "g1" );
1845 Cycle
= 32 + Orient
;
1848 //Unknown... maybe only a transparency effect apply
1853 strcat( ResRef
, "g1" );
1854 strcpy( EquipData
->Suffix
, "g1" );
1855 Cycle
= 16 + Orient
;
1858 //This depends on the ranged weapon equipped
1860 strcat (ResRef
, RangedPrefixOld
[RangedType
]);
1861 strcpy( EquipData
->Suffix
, RangedPrefixOld
[RangedType
] );
1866 strcat( ResRef
, "g1" );
1867 strcpy( EquipData
->Suffix
, "g1" );
1868 Cycle
= 64 + Orient
;
1872 strcat( ResRef
, "g1" );
1873 strcpy( EquipData
->Suffix
, "g1" );
1874 Cycle
= 56 + Orient
;
1878 strcat( ResRef
, "g1" );
1879 strcpy( EquipData
->Suffix
, "g1" );
1883 printf("MHR Animation: unhandled stance: %s %d\n", ResRef
, StanceID
);
1888 strcat( ResRef
, "e" );
1889 strcat( EquipData
->Suffix
, "e" );
1891 EquipData
->Cycle
= Cycle
;
1894 void CharAnimations::GetMHREquipmentRef(char* ResRef
, unsigned char& Cycle
,
1895 const char* equipRef
, bool offhand
,
1896 EquipResRefData
* equip
)
1898 Cycle
= equip
->Cycle
;
1900 //i think there is no offhand stuff for bg1, lets use the bg2 equivalent here?
1901 sprintf( ResRef
, "wq%c%c%co%s", GetSize(), equipRef
[0], equipRef
[1], equip
->Suffix
);
1903 sprintf( ResRef
, "wp%c%c%c%s", GetSize(), equipRef
[0], equipRef
[1], equip
->Suffix
);
1907 void CharAnimations::AddTwoFileSuffix( char* ResRef
, unsigned char StanceID
,
1908 unsigned char& Cycle
, unsigned char Orient
)
1911 case IE_ANI_HEAD_TURN
:
1912 Cycle
= 16 + Orient
/ 2;
1915 Cycle
= 24 + Orient
/ 2;
1919 Cycle
= 40 + Orient
/ 2;
1924 case IE_ANI_PST_START
:
1925 Cycle
= 32 + Orient
/ 2;
1931 Cycle
= 8 + Orient
/ 2;
1934 strcat( ResRef
, "g1" );
1936 strcat( ResRef
, "e" );
1940 void CharAnimations::AddLRSuffix2( char* ResRef
, unsigned char StanceID
,
1941 unsigned char& Cycle
, unsigned char Orient
, EquipResRefData
*&EquipData
)
1943 EquipData
= new EquipResRefData
;
1944 EquipData
->Suffix
[0] = 0;
1947 case IE_ANI_ATTACK_BACKSLASH
:
1948 case IE_ANI_ATTACK_SLASH
:
1949 case IE_ANI_ATTACK_JAB
:
1950 strcat( ResRef
, "g2" );
1951 strcpy( EquipData
->Suffix
, "g2" );
1955 case IE_ANI_CONJURE
:
1957 strcat( ResRef
, "g2" );
1958 strcpy( EquipData
->Suffix
, "g2" );
1959 Cycle
= 8 + Orient
/ 2;
1962 strcat( ResRef
, "g1" );
1963 strcpy( EquipData
->Suffix
, "g1" );
1967 strcat( ResRef
, "g1" );
1968 strcpy( EquipData
->Suffix
, "g1" );
1969 Cycle
= 8 + Orient
/ 2;
1971 case IE_ANI_HEAD_TURN
: //could be wrong
1973 strcat( ResRef
, "g1" );
1974 strcpy( EquipData
->Suffix
, "g1" );
1975 Cycle
= 16 + Orient
/ 2;
1978 strcat( ResRef
, "g1" );
1979 strcpy( EquipData
->Suffix
, "g1" );
1980 Cycle
= 24 + Orient
/ 2;
1984 case IE_ANI_PST_START
:
1986 strcat( ResRef
, "g1" );
1987 strcpy( EquipData
->Suffix
, "g1" );
1988 Cycle
= 32 + Orient
/ 2;
1992 strcat( ResRef
, "g1" );
1993 strcpy( EquipData
->Suffix
, "g1" );
1994 Cycle
= 40 + Orient
/ 2;
1997 printf("LRSuffix2 Animation: unhandled stance: %s %d\n", ResRef
, StanceID
);
2002 strcat( ResRef
, "e" );
2003 strcat( EquipData
->Suffix
, "e");
2005 EquipData
->Cycle
= Cycle
;
2008 void CharAnimations::AddLRSuffix( char* ResRef
, unsigned char StanceID
,
2009 unsigned char& Cycle
, unsigned char Orient
, EquipResRefData
*&EquipData
)
2011 EquipData
= new EquipResRefData
;
2012 EquipData
->Suffix
[0] = 0;
2015 case IE_ANI_ATTACK_BACKSLASH
:
2016 strcat( ResRef
, "g2" );
2017 strcpy( EquipData
->Suffix
, "g2" );
2020 case IE_ANI_ATTACK_SLASH
:
2021 strcat( ResRef
, "g2" );
2022 strcpy( EquipData
->Suffix
, "g2" );
2023 Cycle
= 8 + Orient
/ 2;
2025 case IE_ANI_ATTACK_JAB
:
2026 strcat( ResRef
, "g2" );
2027 strcpy( EquipData
->Suffix
, "g2" );
2028 Cycle
= 16 + Orient
/ 2;
2031 case IE_ANI_CONJURE
:
2033 //these animations are missing
2034 strcat( ResRef
, "g2" );
2035 strcpy( EquipData
->Suffix
, "g2" );
2039 strcat( ResRef
, "g1" );
2040 strcpy( EquipData
->Suffix
, "g1" );
2044 strcat( ResRef
, "g1" );
2045 strcpy( EquipData
->Suffix
, "g1" );
2046 Cycle
= 8 + Orient
/ 2;
2048 case IE_ANI_HEAD_TURN
: //could be wrong
2050 strcat( ResRef
, "g1" );
2051 strcpy( EquipData
->Suffix
, "g1" );
2052 Cycle
= 16 + Orient
/ 2;
2055 strcat( ResRef
, "g1" );
2056 strcpy( EquipData
->Suffix
, "g1" );
2057 Cycle
= 24 + Orient
/ 2;
2061 case IE_ANI_PST_START
:
2063 strcat( ResRef
, "g1" );
2064 strcpy( EquipData
->Suffix
, "g1" );
2065 Cycle
= 32 + Orient
/ 2;
2069 strcat( ResRef
, "g1" );
2070 strcpy( EquipData
->Suffix
, "g1" );
2071 Cycle
= 40 + Orient
/ 2;
2074 printf("LR Animation: unhandled stance: %s %d\n", ResRef
, StanceID
);
2079 strcat( ResRef
, "e" );
2080 strcat( EquipData
->Suffix
, "e");
2082 EquipData
->Cycle
= Cycle
;
2085 void CharAnimations::GetLREquipmentRef(char* ResRef
, unsigned char& Cycle
,
2086 const char* equipRef
, bool /*offhand*/,
2087 EquipResRefData
* equip
)
2089 Cycle
= equip
->Cycle
;
2091 sprintf( ResRef
, "%4s%c%s", this->ResRef
, equipRef
[0], equip
->Suffix
);
2094 //Only for the ogre animation (MOGR)
2095 void CharAnimations::AddLR3Suffix( char* ResRef
, unsigned char StanceID
,
2096 unsigned char& Cycle
, unsigned char Orient
)
2100 case IE_ANI_ATTACK_BACKSLASH
:
2101 strcat( ResRef
, "g2" );
2104 case IE_ANI_ATTACK_SLASH
:
2105 strcat( ResRef
, "g2" );
2106 Cycle
= 8 + Orient
/ 2;
2108 case IE_ANI_ATTACK_JAB
:
2109 strcat( ResRef
, "g2" );
2110 Cycle
= 8 + Orient
/ 2; //there is no third attack animation
2113 case IE_ANI_CONJURE
:
2115 strcat( ResRef
, "g3" );
2119 strcat( ResRef
, "g1" );
2120 Cycle
= 16 + Orient
/ 2;
2123 strcat( ResRef
, "g1" );
2124 Cycle
= 8 + Orient
/ 2;
2126 case IE_ANI_HEAD_TURN
: //could be wrong
2128 strcat( ResRef
, "g1" );
2132 strcat( ResRef
, "g3" );
2133 Cycle
= 8 + Orient
/ 2;
2138 case IE_ANI_PST_START
:
2140 strcat( ResRef
, "g3" );
2141 Cycle
= 16 + Orient
/ 2;
2144 strcat( ResRef
, "g3" );
2145 Cycle
= 24 + Orient
/ 2;
2148 printf("LR3 Animation: unhandled stance: %s %d\n", ResRef
, StanceID
);
2153 strcat( ResRef
, "e" );
2157 void CharAnimations::AddMMR2Suffix(char* ResRef
, unsigned char StanceID
,
2158 unsigned char& Cycle
, unsigned char Orient
)
2162 case IE_ANI_ATTACK_SLASH
:
2163 case IE_ANI_ATTACK_BACKSLASH
:
2164 case IE_ANI_ATTACK_JAB
:
2165 case IE_ANI_CONJURE
:
2167 strcat( ResRef
, "a1" );
2168 Cycle
= ( Orient
/ 2 );
2172 strcat( ResRef
, "a4" );
2173 Cycle
= ( Orient
/ 2 );
2178 strcat( ResRef
, "sd" );
2179 Cycle
= ( Orient
/ 2 );
2182 case IE_ANI_HEAD_TURN
:
2183 strcat( ResRef
, "sc" );
2184 Cycle
= ( Orient
/ 2 );
2188 strcat( ResRef
, "gh" );
2189 Cycle
= ( Orient
/ 2 );
2193 strcat( ResRef
, "de" );
2194 Cycle
= ( Orient
/ 2 );
2199 case IE_ANI_PST_START
:
2200 strcat( ResRef
, "gu" );
2201 Cycle
= ( Orient
/ 2 );
2204 //Unknown... maybe only a transparency effect apply
2209 strcat( ResRef
, "sl" );
2210 Cycle
= ( Orient
/ 2 );
2214 strcat( ResRef
, "tw" );
2215 Cycle
= ( Orient
/ 2 );
2219 strcat( ResRef
, "wk" );
2220 Cycle
= ( Orient
/ 2 );
2223 printf("MMR Animation: unhandled stance: %s %d\n", ResRef
, StanceID
);
2228 strcat( ResRef
, "e" );
2232 void CharAnimations::AddMMRSuffix(char* ResRef
, unsigned char StanceID
,
2233 unsigned char& Cycle
, unsigned char Orient
)
2237 case IE_ANI_ATTACK_SLASH
:
2238 case IE_ANI_ATTACK_BACKSLASH
:
2239 strcat( ResRef
, "a1" );
2240 Cycle
= ( Orient
/ 2 );
2244 strcat( ResRef
, "a4" );
2245 Cycle
= ( Orient
/ 2 );
2248 case IE_ANI_ATTACK_JAB
:
2249 strcat( ResRef
, "a2" );
2250 Cycle
= ( Orient
/ 2 );
2255 strcat( ResRef
, "sd" );
2256 Cycle
= ( Orient
/ 2 );
2259 case IE_ANI_CONJURE
:
2260 strcat( ResRef
, "ca" );
2261 Cycle
= ( Orient
/ 2 );
2265 strcat( ResRef
, "sp" );
2266 Cycle
= ( Orient
/ 2 );
2269 case IE_ANI_HEAD_TURN
:
2270 strcat( ResRef
, "sc" );
2271 Cycle
= ( Orient
/ 2 );
2275 strcat( ResRef
, "gh" );
2276 Cycle
= ( Orient
/ 2 );
2280 strcat( ResRef
, "de" );
2281 Cycle
= ( Orient
/ 2 );
2286 case IE_ANI_PST_START
:
2287 strcat( ResRef
, "gu" );
2288 Cycle
= ( Orient
/ 2 );
2291 //Unknown... maybe only a transparency effect apply
2296 strcat( ResRef
, "sl" );
2297 Cycle
= ( Orient
/ 2 );
2301 strcat( ResRef
, "tw" );
2302 Cycle
= ( Orient
/ 2 );
2306 strcat( ResRef
, "wk" );
2307 Cycle
= ( Orient
/ 2 );
2310 printf("MMR Animation: unhandled stance: %s %d\n", ResRef
, StanceID
);
2315 strcat( ResRef
, "e" );
2319 void CharAnimations::PulseRGBModifiers()
2321 unsigned long time
= core
->GetGame()->Ticks
;
2323 if (time
- lastModUpdate
<= 40)
2326 if (time
- lastModUpdate
> 400) lastModUpdate
= time
- 40;
2328 int inc
= (time
- lastModUpdate
)/40;
2329 bool change
[4] = { false, false, false, false };
2330 if (GlobalColorMod
.type
!= RGBModifier::NONE
&&
2331 GlobalColorMod
.speed
> 0)
2333 GlobalColorMod
.phase
+= inc
;
2334 change
[0] = change
[1] = change
[2] = change
[3] = true;
2337 if (GlobalColorMod
.phase
> 2*GlobalColorMod
.speed
) {
2338 GlobalColorMod
.type
= RGBModifier::NONE
;
2339 GlobalColorMod
.phase
= 0;
2340 GlobalColorMod
.speed
= 0;
2344 for (int i
= 0; i
< 32; ++i
) {
2345 if (ColorMods
[i
].type
!= RGBModifier::NONE
&&
2346 ColorMods
[i
].speed
> 0)
2348 ColorMods
[i
].phase
+= inc
;
2349 change
[i
>>3] = true;
2353 if (change
[0]) SetupColors(PAL_MAIN
);
2354 if (change
[1]) SetupColors(PAL_WEAPON
);
2355 if (change
[2]) SetupColors(PAL_OFFHAND
);
2356 if (change
[3]) SetupColors(PAL_HELMET
);
2358 lastModUpdate
+= inc
*40;