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 char CharAnimations::GetSize() const
117 if (AvatarsRowNum
==~0u) return 0;
118 return AvatarTable
[AvatarsRowNum
].Size
;
121 int CharAnimations::GetActorPartCount() const
123 if (AvatarsRowNum
==~0u) return -1;
124 switch (AvatarTable
[AvatarsRowNum
].AnimationType
) {
125 case IE_ANI_NINE_FRAMES
: //dragon animations
127 case IE_ANI_FOUR_FRAMES
: //wyvern animations
129 case IE_ANI_PST_GHOST
: //special pst anims
130 if (AvatarTable
[AvatarsRowNum
].Prefixes
[1][0]=='*') {
133 if (AvatarTable
[AvatarsRowNum
].Prefixes
[2][0]=='*') {
136 if (AvatarTable
[AvatarsRowNum
].Prefixes
[3][0]=='*') {
145 int CharAnimations::GetTotalPartCount() const
147 if (AvatarsRowNum
==~0u) return -1;
148 switch (AvatarTable
[AvatarsRowNum
].AnimationType
) {
149 case IE_ANI_FOUR_FILES
:
150 case IE_ANI_FOUR_FILES_2
:
151 return GetActorPartCount() + 1; // only weapon
152 case IE_ANI_CODE_MIRROR
:
153 return GetActorPartCount() + 3; // equipment
154 case IE_ANI_TWENTYTWO
:
155 return GetActorPartCount() + 3; // equipment
157 return GetActorPartCount();
161 void CharAnimations::SetArmourLevel(int ArmourLevel
)
163 if (AvatarsRowNum
==~0u) return;
164 //ignore ArmourLevel for the static pst anims (all sprites are displayed)
165 if (AvatarTable
[AvatarsRowNum
].AnimationType
== IE_ANI_PST_GHOST
) {
168 strncpy( ResRef
, AvatarTable
[AvatarsRowNum
].Prefixes
[ArmourLevel
], 8 );
173 //RangedType could be weird, reducing its value to 0,1,2
174 void CharAnimations::SetRangedType(int rt
)
176 if ((unsigned int) rt
<2) {
177 RangedType
=(ieByte
) rt
;
183 void CharAnimations::SetWeaponType(int wt
)
185 if (wt
!= WeaponType
) {
191 void CharAnimations::SetHelmetRef(const char* ref
)
193 HelmetRef
[0] = ref
[0];
194 HelmetRef
[1] = ref
[1];
196 // TODO: Only drop helmet anims?
197 // Note: this doesn't happen "often", so this isn't a performance
200 gamedata
->FreePalette(palette
[PAL_HELMET
], 0);
201 gamedata
->FreePalette(modifiedPalette
[PAL_HELMET
], 0);
204 void CharAnimations::SetWeaponRef(const char* ref
)
206 WeaponRef
[0] = ref
[0];
207 WeaponRef
[1] = ref
[1];
209 // TODO: Only drop weapon anims?
211 gamedata
->FreePalette(palette
[PAL_WEAPON
], 0);
212 gamedata
->FreePalette(modifiedPalette
[PAL_WEAPON
], 0);
215 void CharAnimations::SetOffhandRef(const char* ref
)
217 OffhandRef
[0] = ref
[0];
218 OffhandRef
[1] = ref
[1];
220 // TODO: Only drop shield/offhand anims?
222 gamedata
->FreePalette(palette
[PAL_OFFHAND
], 0);
223 gamedata
->FreePalette(modifiedPalette
[PAL_OFFHAND
], 0);
226 void CharAnimations::LockPalette(const ieDword
*gradients
)
228 if (lockPalette
) return;
229 //cannot lock colors for PST animations
230 if (GetAnimType() >= IE_ANI_PST_ANIMATION_1
)
234 //force initialisation of animation
235 SetColors( gradients
);
237 if (palette
[PAL_MAIN
]) {
242 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
243 static const char *StancePrefix
[]={"3","2","5","5","4","4","2","2","5","4","1","3","3","3","4","1","4","4","4"};
244 static const char *CyclePrefix
[]= {"0","0","1","1","1","1","0","0","1","1","0","1","1","1","1","1","1","1","1"};
245 static const unsigned int CycleOffset
[] = {0, 0, 0, 0, 0, 9, 0, 0, 0, 18, 0, 0, 9, 18, 0, 0, 0, 0, 0};
247 void CharAnimations::SetColors(const ieDword
*arg
)
250 SetupColors(PAL_MAIN
);
251 SetupColors(PAL_WEAPON
);
252 SetupColors(PAL_OFFHAND
);
253 SetupColors(PAL_HELMET
);
256 void CharAnimations::SetupColors(PaletteType type
)
258 Palette
* pal
= palette
[(int)type
];
268 if (GetAnimType() >= IE_ANI_PST_ANIMATION_1
) {
269 // Only do main palette
270 if (type
!= PAL_MAIN
) {
273 // TODO: handle equipment colour glows
275 // Colors[6] is the COLORCOUNT stat in PST.
276 // It tells how many customisable color slots we have.
277 // The color slots start from the end of the palette and go
278 // backwards. There are 6 available slots with a size of 32 each.
279 // Actually, the slots seem to be written in the cre file
280 // but we ignore them, i'm not sure this is correct
281 int colorcount
= Colors
[6];
283 //the color count shouldn't be more than 6!
284 if (colorcount
>6) colorcount
=6;
285 int dest
= 256-colorcount
*size
;
286 bool needmod
= false;
287 if (GlobalColorMod
.type
!= RGBModifier::NONE
) {
290 if ((colorcount
== 0) && (needmod
==false) ) {
291 gamedata
->FreePalette(palette
[PAL_MAIN
], PaletteResRef
);
295 for (int i
= 0; i
< colorcount
; i
++) {
296 core
->GetPalette( Colors
[i
]&255, size
,
297 &palette
[PAL_MAIN
]->col
[dest
] );
302 if (!modifiedPalette
[PAL_MAIN
])
303 modifiedPalette
[PAL_MAIN
] = new Palette();
304 modifiedPalette
[PAL_MAIN
]->SetupGlobalRGBModification(palette
[PAL_MAIN
], GlobalColorMod
);
306 gamedata
->FreePalette(modifiedPalette
[PAL_MAIN
], 0);
311 int PType
= NoPalette();
312 if ( PType
&& (type
== PAL_MAIN
) ) {
313 bool needmod
= false;
314 if (GlobalColorMod
.type
!= RGBModifier::NONE
) {
317 if (!needmod
&& PaletteResRef
[0]) {
318 gamedata
->FreePalette(palette
[PAL_MAIN
], PaletteResRef
);
321 //handling special palettes like MBER_BL (black bear)
323 if (GetAnimType()==IE_ANI_NINE_FRAMES
) {
324 snprintf(PaletteResRef
,9,"%.4s_%-.2s%s",ResRef
, (char *) &PType
, StancePrefix
[StanceID
]);
326 snprintf(PaletteResRef
,9,"%.4s_%-.2s",ResRef
, (char *) &PType
);
328 strlwr(PaletteResRef
);
329 Palette
*tmppal
= gamedata
->GetPalette(PaletteResRef
);
331 palette
[PAL_MAIN
] = tmppal
;
337 if (!modifiedPalette
[PAL_MAIN
])
338 modifiedPalette
[PAL_MAIN
] = new Palette();
339 modifiedPalette
[PAL_MAIN
]->SetupGlobalRGBModification(palette
[PAL_MAIN
], GlobalColorMod
);
341 gamedata
->FreePalette(modifiedPalette
[PAL_MAIN
], 0);
346 pal
->SetupPaperdollColours(Colors
, (int)type
);
352 bool needmod
= false;
353 if (GlobalColorMod
.type
!= RGBModifier::NONE
) {
356 for (i
= 0; i
< 7; ++i
) {
357 if (ColorMods
[i
+8*((int)type
)].type
!= RGBModifier::NONE
)
364 if (!modifiedPalette
[(int)type
])
365 modifiedPalette
[(int)type
] = new Palette();
367 if (GlobalColorMod
.type
!= RGBModifier::NONE
) {
368 modifiedPalette
[(int)type
]->SetupGlobalRGBModification(palette
[(int)type
], GlobalColorMod
);
370 modifiedPalette
[(int)type
]->SetupRGBModification(palette
[(int)type
],ColorMods
, (int)type
);
373 gamedata
->FreePalette(modifiedPalette
[(int)type
], 0);
378 Palette
* CharAnimations::GetPartPalette(int part
)
380 int actorPartCount
= GetActorPartCount();
381 PaletteType type
= PAL_MAIN
;
383 if (part
== actorPartCount
) type
= PAL_WEAPON
;
384 if (part
== actorPartCount
+1) type
= PAL_OFFHAND
;
385 if (part
== actorPartCount
+2) type
= PAL_HELMET
;
387 if (modifiedPalette
[(int)type
])
388 return modifiedPalette
[(int)type
];
390 return palette
[(int)type
];
393 static int compare_avatars(const void *a
, const void *b
)
395 unsigned int aa
= ((AvatarStruct
*)a
)->AnimID
;
396 unsigned int bb
= ((AvatarStruct
*)b
)->AnimID
;
399 if (aa<bb) return -1;
402 return (int) (aa
-bb
);
405 void CharAnimations::InitAvatarsTable()
407 AutoTable
Avatars("avatars");
409 printMessage("CharAnimations", "A critical animation file is missing!\n", LIGHT_RED
);
412 AvatarTable
= (AvatarStruct
*) calloc ( AvatarsCount
= Avatars
->GetRowCount(), sizeof(AvatarStruct
) );
414 DataFileMgr
*resdata
= core
->GetResDataINI();
416 AvatarTable
[i
].AnimID
=(unsigned int) strtol(Avatars
->GetRowName(i
),NULL
,0 );
417 strnlwrcpy(AvatarTable
[i
].Prefixes
[0],Avatars
->QueryField(i
,AV_PREFIX1
),8);
418 strnlwrcpy(AvatarTable
[i
].Prefixes
[1],Avatars
->QueryField(i
,AV_PREFIX2
),8);
419 strnlwrcpy(AvatarTable
[i
].Prefixes
[2],Avatars
->QueryField(i
,AV_PREFIX3
),8);
420 strnlwrcpy(AvatarTable
[i
].Prefixes
[3],Avatars
->QueryField(i
,AV_PREFIX4
),8);
421 AvatarTable
[i
].AnimationType
=(ieByte
) atoi(Avatars
->QueryField(i
,AV_ANIMTYPE
) );
422 AvatarTable
[i
].CircleSize
=(ieByte
) atoi(Avatars
->QueryField(i
,AV_CIRCLESIZE
) );
423 const char *tmp
= Avatars
->QueryField(i
,AV_USE_PALETTE
);
424 //QueryField will always return a zero terminated string
425 //so tmp[0] must exist
426 if ( isalpha (tmp
[0]) ) {
427 //this is a hack, we store 2 letters on an integer
428 //it was allocated with calloc, so don't bother erasing it
429 strncpy( (char *) &AvatarTable
[i
].PaletteType
, tmp
, 3);
432 AvatarTable
[i
].PaletteType
=atoi(Avatars
->QueryField(i
,AV_USE_PALETTE
) );
434 AvatarTable
[i
].Size
=Avatars
->QueryField(i
,AV_SIZE
)[0];
436 AvatarTable
[i
].WalkScale
= 0;
437 AvatarTable
[i
].RunScale
= 0;
438 AvatarTable
[i
].Bestiary
= -1;
442 snprintf(section
,10,"%d", i
);
444 if (!resdata
->GetKeysCount(section
)) continue;
446 float walkscale
= resdata
->GetKeyAsFloat(section
, "walkscale", 0.0f
);
447 if (walkscale
!= 0.0f
) AvatarTable
[i
].WalkScale
= (int)(1000.0f
/ walkscale
);
448 float runscale
= resdata
->GetKeyAsFloat(section
, "runscale", 0.0f
);
449 if (runscale
!= 0.0f
) AvatarTable
[i
].RunScale
= (int)(1000.0f
/ runscale
);
450 AvatarTable
[i
].Bestiary
= resdata
->GetKeyAsInt(section
, "bestiary", -1);
453 qsort(AvatarTable
, AvatarsCount
, sizeof(AvatarStruct
), compare_avatars
);
456 CharAnimations::CharAnimations(unsigned int AnimID
, ieDword ArmourLevel
)
460 for (i
= 0; i
< 4; ++i
) {
461 modifiedPalette
[i
] = NULL
;
466 autoSwitchOnEnd
= false;
472 for (i
= 0; i
< MAX_ANIMS
; i
++) {
473 for (j
= 0; j
< MAX_ORIENT
; j
++) {
480 PaletteResRef
[0] = 0;
484 for (i
= 0; i
< 32; ++i
) {
485 ColorMods
[i
].type
= RGBModifier::NONE
;
486 ColorMods
[i
].speed
= 0;
487 // make initial phase depend on location to make the pulse appear
489 ColorMods
[i
].phase
= 5*i
;
491 GlobalColorMod
.type
= RGBModifier::NONE
;
492 GlobalColorMod
.speed
= 0;
493 GlobalColorMod
.phase
= 0;
497 AvatarsRowNum
=AvatarsCount
;
498 if (core
->HasFeature(GF_ONE_BYTE_ANIMID
) ) {
499 ieDword tmp
= AnimID
&0xf000;
500 if (tmp
==0x6000 || tmp
==0xe000) {
505 while (AvatarsRowNum
--) {
506 if (AvatarTable
[AvatarsRowNum
].AnimID
<=AnimID
) {
507 SetArmourLevel( ArmourLevel
);
512 printMessage("CharAnimations", " ", LIGHT_RED
);
513 printf("Invalid or nonexistent avatar entry:%04X\n", AnimID
);
516 //we have to drop them when armourlevel changes
517 void CharAnimations::DropAnims()
520 int partCount
= GetTotalPartCount();
521 for (int StanceID
= 0; StanceID
< MAX_ANIMS
; StanceID
++) {
522 for (int i
= 0; i
< MAX_ORIENT
; i
++) {
523 if (Anims
[StanceID
][i
]) {
524 tmppoi
= Anims
[StanceID
][i
];
525 for (int j
= 0; j
< partCount
; j
++)
526 delete Anims
[StanceID
][i
][j
];
529 // anims can only be duplicated at the Animation** level
530 for (int IDb
=StanceID
;IDb
< MAX_ANIMS
; IDb
++) {
531 for (int i2
= 0; i2
<MAX_ORIENT
; i2
++) {
532 if (Anims
[IDb
][i2
] == tmppoi
) {
542 CharAnimations::~CharAnimations(void)
545 gamedata
->FreePalette(palette
[PAL_MAIN
], PaletteResRef
);
547 for (i
= 1; i
< 4; ++i
)
548 gamedata
->FreePalette(palette
[i
], 0);
549 for (i
= 0; i
< 4; ++i
)
550 gamedata
->FreePalette(modifiedPalette
[i
], 0);
553 This is a simple Idea of how the animation are coded
555 There are the following animation types:
557 IE_ANI_CODE_MIRROR: The code automatically mirrors the needed frames
558 (as in the example above)
560 These Animations are stores using the following template:
561 [NAME][ARMORTYPE][ACTIONCODE]
563 Each BAM File contains only 9 Orientations, the missing 7 Animations
564 are created by Horizontally Mirroring the 1-7 Orientations.
566 IE_ANI_CODE_MIRROR_2: another mirroring type with more animations
567 [NAME]g[1,11-15,2,21-26]
569 IE_ANI_CODE_MIRROR_3: Almost identical to IE_ANI_CODE_MIRROR_2, but with fewer cycles in g26
571 IE_ANI_ONE_FILE: The whole animation is in one file, no mirroring needed.
572 Each animation group is 16 Cycles.
574 IE_ANI_TWO_FILES: The whole animation is in 2 files. The East and West part are in 2 BAM Files.
579 Each BAM File contains many animation groups, each animation group
580 stores 5 Orientations, the missing 3 are stored in East BAM Files.
583 IE_ANI_FOUR_FILES: The Animation is coded in Four Files. Probably it is an old Two File animation with
584 additional frames added in a second time.
586 IE_ANI_FOUR_FILES_2: Like IE_ANI_FOUR_FILES but with only 16 cycles per frame.
588 IE_ANI_TWENTYTWO: This Animation Type stores the Animation in the following format
589 [NAME][ACTIONCODE][/E]
590 ACTIONCODE=A1-6, CA, SX, SA (sling is A1)
591 The g1 file contains several animation states. See MHR
592 Probably it could use A7-9 files too, bringing the file numbers to 28.
593 This is the original bg1 format.
595 IE_ANI_SIX_FILES: The layout for these files is:
597 Each state contains 16 Orientations, but the last 6 are stored in the East file.
598 g1 contains only the walking animation.
599 G2 contains stand, ready, get hit, die and twitch.
600 g3 contains 3 attacks.
602 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
604 IE_ANI_TWO_FILES_2: Animations using this type are stored using the following template:
606 Each state contains 8 Orientations, but the second 4 are stored in the East file.
607 From the standard animations, only AHRS and ACOW belong to this type.
609 IE_ANI_TWO_FILES_3: Animations using this type are stored using the following template:
610 [NAME][ACTIONTYPE][/E]
616 Each BAM File contains one animation group, each animation group
617 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).
618 This is the standard IWD animation, but BG2 also has it.
621 IE_ANI_TWO_FILES_3B: Animations using this type are stored using the following template:
622 [NAME][ACTIONTYPE][/E]
628 This is a cut down version of IE_ANI_TWO_FILES_3. A2, CA and SP suffixes are missing.
629 This is the standard IWD animation, but BG2 also has it.
632 IE_ANI_FOUR_FRAMES: These animations are large, four bams make a frame.
635 IE_ANI_NINE_FRAMES: These animations are huge, nine bams make a frame.
638 IE_ANI_FRAGMENT: These animations are used for projectile graphics.
639 A single file contains 5 cycles (code mirror for east animation)
641 IE_ANI_PST_ANIMATION_1:
642 IE_ANI_PST_ANIMATION_2:
643 IE_ANI_PST_ANIMATION_3:
644 Planescape: Torment Animations are stored in a different
645 way than the other games. This format uses the following template:
646 [C/D][ACTIONTYPE][NAME][B]
651 Each Animation stores 5 Orientations, which are automatically mirrored
652 to form an 8 Orientation Animation. PST Animations have a different Palette
653 format. This Animation Type handles the PST Palette format too.
655 NOTE: Walking/Running animations store 9 Orientations.
656 The second variation is missing the resting stance (STD) and the transitions.
657 These creatures are always in combat stance (don't rest).
658 Animation_3 is without STC (combat stance), they are always standing
660 IE_ANI_PST_STAND: This is a modified PST animation, it contains only a
661 Standing image for every orientations, it follows the
662 [C/D]STD[NAME][B] standard.
664 IE_ANI_PST_GHOST: This is a special static animation with no standard
665 All armourlevels are drawn simultaneously. There is no orientation or stance.
668 WEST PART | EAST PART
671 NW 006 007 008 009 010 NE
675 SW 002 001 000 015 014 SE
682 Animation
** CharAnimations::GetAnimation(unsigned char Stance
, unsigned char Orient
)
684 if (StanceID
>=MAX_ANIMS
) {
685 printf("Illegal stance ID\n");
689 //for paletted dragon animations, we need the stance id
690 StanceID
= nextStanceID
= Stance
;
691 int AnimType
= GetAnimType();
693 //alter stance here if it is missing and you know a substitute
694 //probably we should feed this result back to the actor?
696 case -1: //invalid animation
699 case IE_ANI_PST_STAND
:
700 StanceID
=IE_ANI_AWAKE
;
702 case IE_ANI_PST_GHOST
:
703 StanceID
=IE_ANI_AWAKE
;
706 case IE_ANI_PST_ANIMATION_3
: //stc->std
707 if (StanceID
==IE_ANI_READY
) {
708 StanceID
=IE_ANI_AWAKE
;
711 case IE_ANI_PST_ANIMATION_2
: //std->stc
712 if (StanceID
==IE_ANI_AWAKE
) {
713 StanceID
=IE_ANI_READY
;
717 //pst animations don't have separate animation for sleep/die
718 if (AnimType
>= IE_ANI_PST_ANIMATION_1
) {
719 if (StanceID
==IE_ANI_DIE
) {
720 StanceID
=IE_ANI_TWITCH
;
724 //TODO: Implement Auto Resource Loading
725 //setting up the sequencing of animation cycles
726 autoSwitchOnEnd
= false;
729 nextStanceID
= IE_ANI_READY
;
730 autoSwitchOnEnd
= true;
732 case IE_ANI_SLEEP
: //going to sleep
733 nextStanceID
= IE_ANI_TWITCH
;
734 autoSwitchOnEnd
= true;
736 case IE_ANI_TWITCH
: //dead, sleeping
737 autoSwitchOnEnd
= false;
739 case IE_ANI_DIE
: //going to die
740 nextStanceID
= IE_ANI_TWITCH
;
741 autoSwitchOnEnd
= true;
745 case IE_ANI_CAST
: // looping
752 case IE_ANI_HEAD_TURN
:
753 case IE_ANI_PST_START
:
754 nextStanceID
= IE_ANI_AWAKE
;
755 autoSwitchOnEnd
= true;
757 case IE_ANI_CONJURE
: //ending
760 case IE_ANI_ATTACK_JAB
:
761 case IE_ANI_ATTACK_SLASH
:
762 case IE_ANI_ATTACK_BACKSLASH
:
763 nextStanceID
= IE_ANI_READY
;
764 autoSwitchOnEnd
= true;
767 printf ("Invalid Stance: %d\n", StanceID
);
770 Animation
** anims
= Anims
[StanceID
][Orient
];
776 int partCount
= GetTotalPartCount();
777 int actorPartCount
= GetActorPartCount();
778 if (partCount
< 0) return 0;
779 anims
= new Animation
*[partCount
];
781 EquipResRefData
* equipdat
= 0;
782 for (int part
= 0; part
< partCount
; ++part
)
786 //newresref is based on the prefix (ResRef) and various
788 //this is longer than expected so it won't overflow
790 unsigned char Cycle
= 0;
791 if (part
< actorPartCount
) {
792 // Character animation parts
794 if (equipdat
) delete equipdat
;
796 //we need this long for special anims
797 strncpy( NewResRef
, ResRef
, 8 );
798 GetAnimResRef( StanceID
, Orient
, NewResRef
, Cycle
, part
, equipdat
);
800 // Equipment animation parts
803 if (GetSize() == '*' || GetSize() == 0) continue;
805 if (part
== actorPartCount
) {
806 if (WeaponRef
[0] == 0) continue;
808 GetEquipmentResRef(WeaponRef
,false,NewResRef
,Cycle
,equipdat
);
809 } else if (part
== actorPartCount
+1) {
810 if (OffhandRef
[0] == 0) continue;
811 if (WeaponType
== IE_ANI_WEAPON_2H
) continue;
813 if (WeaponType
== IE_ANI_WEAPON_1H
) {
814 GetEquipmentResRef(OffhandRef
,false,NewResRef
,Cycle
,
816 } else { // IE_ANI_WEAPON_2W
817 GetEquipmentResRef(OffhandRef
,true,NewResRef
,Cycle
,
820 } else if (part
== actorPartCount
+2) {
821 if (HelmetRef
[0] == 0) continue;
823 GetEquipmentResRef(HelmetRef
,false,NewResRef
,Cycle
,equipdat
);
826 NewResRef
[8]=0; //cutting right to size
828 AnimationFactory
* af
= ( AnimationFactory
* )
829 gamedata
->GetFactoryResource( NewResRef
,
830 IE_BAM_CLASS_ID
, IE_NORMAL
);
833 if (part
< actorPartCount
) {
835 snprintf(warnbuf
, 200,
836 "Couldn't create animationfactory: %s (%04x)\n", NewResRef
, GetAnimationID());
837 printMessage("CharAnimations",warnbuf
,LIGHT_RED
);
838 for (int i
= 0; i
< part
; ++i
)
844 // not fatal if animation for equipment is missing
849 Animation
* a
= af
->GetCycle( Cycle
);
853 if (part
< actorPartCount
) {
855 snprintf(warnbuf
, 200,
856 "Couldn't load animation: %s, cycle %d\n",
858 printMessage("CharAnimations",warnbuf
,LIGHT_RED
);
859 for (int i
= 0; i
< part
; ++i
)
865 // not fatal if animation for equipment is missing
870 if (part
< actorPartCount
) {
871 //if you need to revert this change, consider true paletted
872 //animations which need a GlobalColorMod (mgir for example)
874 //if (!palette[PAL_MAIN] && ((GlobalColorMod.type!=RGBModifier::NONE) || (NoPalette()!=1)) ) {
875 if(!palette
[PAL_MAIN
]) {
876 // This is the first time we're loading an Animation.
877 // We copy the palette of its first frame into our own palette
878 palette
[PAL_MAIN
] = a
->GetFrame(0)->GetPalette()->Copy();
879 // ...and setup the colours properly
880 SetupColors(PAL_MAIN
);
882 } else if (part
== actorPartCount
) {
883 if (!palette
[PAL_WEAPON
]) {
884 palette
[PAL_WEAPON
] = a
->GetFrame(0)->GetPalette()->Copy();
885 SetupColors(PAL_WEAPON
);
887 } else if (part
== actorPartCount
+1) {
888 if (!palette
[PAL_OFFHAND
]) {
889 palette
[PAL_OFFHAND
] = a
->GetFrame(0)->GetPalette()->Copy();
890 SetupColors(PAL_OFFHAND
);
892 } else if (part
== actorPartCount
+2) {
893 if (!palette
[PAL_HELMET
]) {
894 palette
[PAL_HELMET
] = a
->GetFrame(0)->GetPalette()->Copy();
895 SetupColors(PAL_HELMET
);
899 //animation is affected by game flags
900 a
->gameAnimation
= true;
903 //setting up the sequencing of animation cycles
909 case IE_ANI_PST_START
:
910 case IE_ANI_HEAD_TURN
:
914 case IE_ANI_ATTACK_JAB
:
915 case IE_ANI_ATTACK_SLASH
:
916 case IE_ANI_ATTACK_BACKSLASH
:
917 a
->Flags
|= A_ANI_PLAYONCE
;
921 a
->playReversed
= true;
922 a
->Flags
|= A_ANI_PLAYONCE
;
925 switch (GetAnimType()) {
926 case IE_ANI_NINE_FRAMES
: //dragon animations
927 case IE_ANI_FOUR_FRAMES
: //wyvern animations
929 case IE_ANI_CODE_MIRROR
:
930 case IE_ANI_CODE_MIRROR_2
: //9 orientations
931 case IE_ANI_CODE_MIRROR_3
:
932 case IE_ANI_PST_ANIMATION_3
: //no stc just std
933 case IE_ANI_PST_ANIMATION_2
: //no std just stc
934 case IE_ANI_PST_ANIMATION_1
:
935 case IE_ANI_FRAGMENT
:
937 a
->MirrorAnimation( );
944 // make animarea of part 0 encompass the animarea of the other parts
946 anims
[0]->AddAnimArea(a
);
950 switch (GetAnimType()) {
951 case IE_ANI_NINE_FRAMES
: //dragon animations
952 case IE_ANI_FOUR_FRAMES
: //wyvern animations
954 case IE_ANI_CODE_MIRROR
:
955 case IE_ANI_SIX_FILES
: //16 anims some are stored elsewhere
956 case IE_ANI_ONE_FILE
: //16 orientations
957 case IE_ANI_CODE_MIRROR_2
: //9 orientations
958 case IE_ANI_CODE_MIRROR_3
:
959 Anims
[StanceID
][Orient
] = anims
;
961 case IE_ANI_TWO_FILES
:
962 case IE_ANI_TWENTYTWO
:
963 case IE_ANI_TWO_FILES_2
:
964 case IE_ANI_TWO_FILES_3
:
965 case IE_ANI_TWO_FILES_3B
:
966 case IE_ANI_FOUR_FILES
:
967 case IE_ANI_FOUR_FILES_2
:
968 case IE_ANI_SIX_FILES_2
:
969 case IE_ANI_FRAGMENT
:
971 Anims
[StanceID
][Orient
] = anims
;
972 Anims
[StanceID
][Orient
+ 1] = anims
;
975 case IE_ANI_PST_ANIMATION_3
: //no stc just std
976 case IE_ANI_PST_ANIMATION_2
: //no std just stc
977 case IE_ANI_PST_ANIMATION_1
:
981 case IE_ANI_PST_START
:
982 Anims
[StanceID
][Orient
] = anims
;
986 Anims
[StanceID
][Orient
] = anims
;
987 Anims
[StanceID
][Orient
+ 1] = anims
;
992 case IE_ANI_PST_STAND
:
994 Anims
[StanceID
][Orient
] = anims
;
995 Anims
[StanceID
][Orient
+1] = anims
;
997 case IE_ANI_PST_GHOST
:
999 StanceID
= IE_ANI_AWAKE
;
1000 Anims
[StanceID
][0] = anims
;
1003 printMessage("CharAnimations","Unknown animation type\n",LIGHT_RED
);
1008 return Anims
[StanceID
][Orient
];
1011 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};
1013 void CharAnimations::GetAnimResRef(unsigned char StanceID
,
1014 unsigned char Orient
,
1015 char* NewResRef
, unsigned char& Cycle
,
1016 int Part
, EquipResRefData
*& EquipData
)
1021 switch (GetAnimType()) {
1022 case IE_ANI_FOUR_FRAMES
:
1023 AddFFSuffix( NewResRef
, StanceID
, Cycle
, Orient
, Part
);
1026 case IE_ANI_NINE_FRAMES
:
1027 AddNFSuffix( NewResRef
, StanceID
, Cycle
, Orient
, Part
);
1030 case IE_ANI_CODE_MIRROR
:
1031 AddVHRSuffix( NewResRef
, StanceID
, Cycle
, Orient
, EquipData
);
1035 Cycle
= (ieByte
) ((StanceID
&1) * 9 + SixteenToNine
[Orient
]);
1038 case IE_ANI_FRAGMENT
:
1039 Cycle
= SixteenToFive
[Orient
];
1042 case IE_ANI_ONE_FILE
:
1043 Cycle
= (ieByte
) (one_file
[StanceID
] * 16 + Orient
);
1046 case IE_ANI_SIX_FILES
:
1047 AddSixSuffix( NewResRef
, StanceID
, Cycle
, Orient
);
1050 case IE_ANI_TWENTYTWO
: //5+3 animations
1051 AddMHRSuffix( NewResRef
, StanceID
, Cycle
, Orient
, EquipData
);
1054 case IE_ANI_TWO_FILES_2
: //4+4 animations
1055 AddLR2Suffix( NewResRef
, StanceID
, Cycle
, Orient
);
1058 case IE_ANI_TWO_FILES_3
: //IWD style anims
1059 AddMMRSuffix( NewResRef
, StanceID
, Cycle
, Orient
);
1062 case IE_ANI_TWO_FILES_3B
: //IWD style anims
1063 AddMMR2Suffix( NewResRef
, StanceID
, Cycle
, Orient
);
1066 case IE_ANI_TWO_FILES
:
1067 AddTwoFileSuffix(NewResRef
, StanceID
, Cycle
, Orient
);
1070 case IE_ANI_FOUR_FILES
:
1071 AddLRSuffix( NewResRef
, StanceID
, Cycle
, Orient
, EquipData
);
1074 case IE_ANI_FOUR_FILES_2
:
1075 AddLRSuffix2( NewResRef
, StanceID
, Cycle
, Orient
, EquipData
);
1078 case IE_ANI_SIX_FILES_2
: //MOGR (variant of FOUR_FILES)
1079 AddLR3Suffix( NewResRef
, StanceID
, Cycle
, Orient
);
1082 case IE_ANI_CODE_MIRROR_2
: //9 orientations
1083 AddVHR2Suffix( NewResRef
, StanceID
, Cycle
, Orient
);
1086 case IE_ANI_CODE_MIRROR_3
: // like IE_ANI_CODE_MIRROR_2 but with fewer cycles in g26
1087 AddVHR3Suffix( NewResRef
, StanceID
, Cycle
, Orient
);
1090 case IE_ANI_PST_ANIMATION_1
:
1091 case IE_ANI_PST_ANIMATION_2
:
1092 case IE_ANI_PST_ANIMATION_3
:
1093 AddPSTSuffix( NewResRef
, StanceID
, Cycle
, Orient
);
1096 case IE_ANI_PST_STAND
:
1097 sprintf(NewResRef
,"%cSTD%4s",ResRef
[0], ResRef
+1);
1098 Cycle
= (ieByte
) SixteenToFive
[Orient
];
1100 case IE_ANI_PST_GHOST
: // pst static animations
1101 //still doesn't handle the second cycle of the golem anim
1103 strnlwrcpy(NewResRef
, AvatarTable
[AvatarsRowNum
].Prefixes
[Part
], 8);
1106 sprintf (tmp
,"Unknown animation type in avatars.2da row: %d\n", AvatarsRowNum
);
1107 printMessage ("CharAnimations",tmp
, LIGHT_RED
);
1112 void CharAnimations::GetEquipmentResRef(const char* equipRef
, bool offhand
,
1113 char* ResRef
, unsigned char& Cycle
, EquipResRefData
* equip
)
1115 switch (GetAnimType()) {
1116 case IE_ANI_FOUR_FILES
:
1117 case IE_ANI_FOUR_FILES_2
:
1118 GetLREquipmentRef( ResRef
, Cycle
, equipRef
, offhand
, equip
);
1120 case IE_ANI_CODE_MIRROR
:
1121 GetVHREquipmentRef( ResRef
, Cycle
, equipRef
, offhand
, equip
);
1123 case IE_ANI_TWENTYTWO
:
1124 GetMHREquipmentRef( ResRef
, Cycle
, equipRef
, offhand
, equip
);
1127 printMessage ("CharAnimations", "Unsupported animation type for equipment animation.\n", LIGHT_RED
);
1133 const int* CharAnimations::GetZOrder(unsigned char Orient
)
1135 switch (GetAnimType()) {
1136 case IE_ANI_CODE_MIRROR
:
1137 return zOrder_Mirror16
[Orient
];
1138 case IE_ANI_TWENTYTWO
:
1139 return zOrder_8
[Orient
/2];
1140 case IE_ANI_FOUR_FILES
:
1148 void CharAnimations::AddPSTSuffix(char* ResRef
, unsigned char StanceID
,
1149 unsigned char& Cycle
, unsigned char Orient
)
1155 case IE_ANI_ATTACK_SLASH
:
1156 case IE_ANI_ATTACK_JAB
:
1157 case IE_ANI_ATTACK_BACKSLASH
:
1158 Cycle
=SixteenToFive
[Orient
];
1159 Prefix
="at1"; break;
1161 Cycle
=SixteenToFive
[Orient
];
1162 Prefix
="hit"; break;
1165 Cycle
=SixteenToFive
[Orient
];
1166 Prefix
="gup"; break;
1168 Cycle
=SixteenToFive
[Orient
];
1169 Prefix
="std"; break;
1171 Cycle
=SixteenToFive
[Orient
];
1172 Prefix
="stc"; break;
1176 Cycle
=SixteenToFive
[Orient
];
1177 Prefix
="dfb"; break;
1179 Cycle
=SixteenToNine
[Orient
];
1180 Prefix
="run"; break;
1182 Cycle
=SixteenToNine
[Orient
];
1183 Prefix
="wlk"; break;
1184 case IE_ANI_HEAD_TURN
:
1185 Cycle
=SixteenToFive
[Orient
];
1188 sprintf(ResRef
,"%c%3s%4s",this->ResRef
[0], Prefix
, this->ResRef
+1);
1189 if (gamedata
->Exists(ResRef
, IE_BAM_CLASS_ID
) ) {
1194 sprintf(ResRef
,"%c%3s%4s",this->ResRef
[0], Prefix
, this->ResRef
+1);
1195 if (gamedata
->Exists(ResRef
, IE_BAM_CLASS_ID
) ) {
1200 case IE_ANI_PST_START
:
1202 Prefix
="ms1"; break;
1203 default: //just in case
1204 Cycle
=SixteenToFive
[Orient
];
1205 Prefix
="stc"; break;
1207 sprintf(ResRef
,"%c%3s%4s",this->ResRef
[0], Prefix
, this->ResRef
+1);
1210 void CharAnimations::AddVHR2Suffix(char* ResRef
, unsigned char StanceID
,
1211 unsigned char& Cycle
, unsigned char Orient
)
1213 Cycle
=SixteenToNine
[Orient
];
1216 case IE_ANI_ATTACK
: //temporarily
1217 case IE_ANI_ATTACK_BACKSLASH
:
1218 strcat( ResRef
, "g21" );
1221 case IE_ANI_ATTACK_SLASH
:
1222 strcat( ResRef
, "g2" );
1225 case IE_ANI_ATTACK_JAB
:
1226 strcat( ResRef
, "g26" );
1230 case IE_ANI_CAST
: //looping
1231 strcat( ResRef
, "g25" );
1235 case IE_ANI_CONJURE
://ending
1236 strcat( ResRef
, "g26" );
1241 strcat( ResRef
, "g24" );
1245 case IE_ANI_HEAD_TURN
:
1247 strcat( ResRef
, "g12" );
1252 strcat( ResRef
, "g15" );
1257 strcat( ResRef
, "g14" );
1264 case IE_ANI_PST_START
:
1265 strcat( ResRef
, "g14" );
1270 strcat( ResRef
, "g13" );
1275 strcat( ResRef
, "g1" );
1280 strcat( ResRef
, "g11" );
1283 printf("VHR2 Animation: unhandled stance: %s %d\n", ResRef
, StanceID
);
1289 void CharAnimations::AddVHR3Suffix(char* ResRef
, unsigned char StanceID
,
1290 unsigned char& Cycle
, unsigned char Orient
)
1292 Cycle
=SixteenToNine
[Orient
];
1295 case IE_ANI_ATTACK
: //temporarily
1296 case IE_ANI_ATTACK_BACKSLASH
:
1297 strcat( ResRef
, "g21" );
1300 case IE_ANI_ATTACK_SLASH
:
1301 strcat( ResRef
, "g2" );
1304 case IE_ANI_ATTACK_JAB
:
1305 strcat( ResRef
, "g26" );
1309 case IE_ANI_CAST
: //looping
1310 strcat( ResRef
, "g25" );
1314 case IE_ANI_CONJURE
://ending
1315 strcat( ResRef
, "g26" );
1320 strcat( ResRef
, "g24" );
1324 case IE_ANI_HEAD_TURN
:
1326 strcat( ResRef
, "g12" );
1331 strcat( ResRef
, "g15" );
1336 strcat( ResRef
, "g14" );
1343 case IE_ANI_PST_START
:
1344 strcat( ResRef
, "g14" );
1349 strcat( ResRef
, "g13" );
1354 strcat( ResRef
, "g1" );
1359 strcat( ResRef
, "g11" );
1362 printf("VHR3 Animation: unhandled stance: %s %d\n", ResRef
, StanceID
);
1368 // Note: almost like SixSuffix
1369 void CharAnimations::AddFFSuffix(char* ResRef
, unsigned char StanceID
,
1370 unsigned char& Cycle
, unsigned char Orient
, int Part
)
1372 Cycle
=SixteenToNine
[Orient
];
1375 strcat( ResRef
, "g1" );
1379 case IE_ANI_ATTACK_SLASH
:
1380 strcat( ResRef
, "g3" );
1383 case IE_ANI_ATTACK_BACKSLASH
:
1384 strcat( ResRef
, "g3" );
1388 case IE_ANI_ATTACK_JAB
:
1390 case IE_ANI_CONJURE
:
1391 strcat( ResRef
, "g3" );
1395 case IE_ANI_HEAD_TURN
: //could be wrong
1397 strcat( ResRef
, "g2" );
1401 strcat( ResRef
, "g2" );
1406 strcat( ResRef
, "g2" );
1413 case IE_ANI_PST_START
:
1414 strcat( ResRef
, "g2" );
1419 strcat( ResRef
, "g2" );
1424 printf("Four frames Animation: unhandled stance: %s %d\n", ResRef
, StanceID
);
1429 ResRef
[6]=(char) (Part
+'1');
1433 void CharAnimations::AddNFSuffix(char* ResRef
, unsigned char StanceID
,
1434 unsigned char& Cycle
, unsigned char Orient
, int Part
)
1438 Cycle
= SixteenToNine
[Orient
];
1439 snprintf(prefix
, 9, "%s%s%d%s%d", ResRef
, StancePrefix
[StanceID
], Part
+1,
1440 CyclePrefix
[StanceID
], Cycle
);
1441 strnlwrcpy(ResRef
,prefix
,8);
1442 Cycle
=(ieByte
) (Cycle
+CycleOffset
[StanceID
]);
1447 static const char *SlashPrefix
[]={"a1","a4","a7"};
1448 static const char *BackPrefix
[]={"a2","a5","a8"};
1449 static const char *JabPrefix
[]={"a3","a6","a9"};
1450 static const char *RangedPrefix
[]={"sa","sx","ss"};
1451 static const char *RangedPrefixOld
[]={"sa","sx","a1"};
1453 void CharAnimations::AddVHRSuffix(char* ResRef
, unsigned char StanceID
,
1454 unsigned char& Cycle
, unsigned char Orient
, EquipResRefData
*& EquipData
)
1456 Cycle
= SixteenToNine
[Orient
];
1457 EquipData
= new EquipResRefData
;
1458 EquipData
->Suffix
[0] = 0;
1461 case IE_ANI_ATTACK_SLASH
:
1462 strcat( ResRef
, SlashPrefix
[WeaponType
] );
1463 strcpy( EquipData
->Suffix
, SlashPrefix
[WeaponType
] );
1466 case IE_ANI_ATTACK_BACKSLASH
:
1467 strcat( ResRef
, BackPrefix
[WeaponType
] );
1468 strcpy( EquipData
->Suffix
, BackPrefix
[WeaponType
] );
1471 case IE_ANI_ATTACK_JAB
:
1472 strcat( ResRef
, JabPrefix
[WeaponType
] );
1473 strcpy( EquipData
->Suffix
, JabPrefix
[WeaponType
] );
1477 strcat( ResRef
, "g17" );
1478 strcpy( EquipData
->Suffix
, "g1" );
1482 case IE_ANI_CAST
: //looping
1483 strcat( ResRef
, "ca" );
1484 strcpy( EquipData
->Suffix
, "ca" );
1487 case IE_ANI_CONJURE
: //ending
1488 strcat( ResRef
, "ca" );
1489 strcpy( EquipData
->Suffix
, "ca" );
1494 strcat( ResRef
, "g14" );
1495 strcpy( EquipData
->Suffix
, "g1" );
1500 strcat( ResRef
, "g15" );
1501 strcpy( EquipData
->Suffix
, "g1" );
1504 //I cannot find an emerge animation...
1505 //Maybe is Die reversed
1508 case IE_ANI_PST_START
:
1509 strcat( ResRef
, "g19" );
1510 strcpy( EquipData
->Suffix
, "g1" );
1514 case IE_ANI_HEAD_TURN
:
1516 strcat( ResRef
, "g12" );
1519 strcat( ResRef
, "g18" );
1522 strcpy( EquipData
->Suffix
, "g1" );
1525 //Unknown... maybe only a transparency effect apply
1530 if ( WeaponType
== IE_ANI_WEAPON_2H
) {
1531 strcat( ResRef
, "g13" );
1534 strcat( ResRef
, "g1" );
1537 strcpy( EquipData
->Suffix
, "g1" );
1539 //This depends on the ranged weapon equipped
1541 strcat( ResRef
, RangedPrefix
[RangedType
] );
1542 strcpy( EquipData
->Suffix
, RangedPrefix
[RangedType
] );
1546 strcat( ResRef
, "g16" );
1547 strcpy( EquipData
->Suffix
, "g1" );
1552 strcat( ResRef
, "g16" );
1553 strcpy( EquipData
->Suffix
, "g1" );
1558 strcat( ResRef
, "g11" );
1559 strcpy( EquipData
->Suffix
, "g1" );
1563 printf("VHR Animation: unhandled stance: %s %d\n", ResRef
, StanceID
);
1567 EquipData
->Cycle
= Cycle
;
1570 void CharAnimations::GetVHREquipmentRef(char* ResRef
, unsigned char& Cycle
,
1571 const char* equipRef
, bool offhand
,
1572 EquipResRefData
* equip
)
1574 Cycle
= equip
->Cycle
;
1576 sprintf( ResRef
, "wq%c%c%co%s", GetSize(), equipRef
[0], equipRef
[1], equip
->Suffix
);
1578 sprintf( ResRef
, "wq%c%c%c%s", GetSize(), equipRef
[0], equipRef
[1], equip
->Suffix
);
1582 void CharAnimations::AddSixSuffix(char* ResRef
, unsigned char StanceID
,
1583 unsigned char& Cycle
, unsigned char Orient
)
1587 strcat( ResRef
, "g1" );
1592 case IE_ANI_ATTACK_SLASH
:
1593 strcat( ResRef
, "g3" );
1597 case IE_ANI_ATTACK_BACKSLASH
:
1598 strcat( ResRef
, "g3" );
1599 Cycle
= 16 + Orient
;
1602 case IE_ANI_ATTACK_JAB
:
1603 strcat( ResRef
, "g3" );
1604 Cycle
= 32 + Orient
;
1607 case IE_ANI_HEAD_TURN
: //could be wrong
1609 strcat( ResRef
, "g2" );
1614 strcat( ResRef
, "g2" );
1615 Cycle
= 16 + Orient
;
1619 strcat( ResRef
, "g2" );
1620 Cycle
= 32 + Orient
;
1626 case IE_ANI_PST_START
:
1627 strcat( ResRef
, "g2" );
1628 Cycle
= 48 + Orient
;
1632 strcat( ResRef
, "g2" );
1633 Cycle
= 64 + Orient
;
1637 printf("Six Animation: unhandled stance: %s %d\n", ResRef
, StanceID
);
1643 strcat( ResRef
, "e" );
1647 void CharAnimations::AddLR2Suffix(char* ResRef
, unsigned char StanceID
,
1648 unsigned char& Cycle
, unsigned char Orient
)
1654 case IE_ANI_CAST
: //looping
1655 case IE_ANI_CONJURE
://ending
1664 case IE_ANI_ATTACK_SLASH
:
1665 case IE_ANI_ATTACK_BACKSLASH
:
1666 case IE_ANI_ATTACK_JAB
:
1667 case IE_ANI_HEAD_TURN
:
1674 case IE_ANI_PST_START
:
1675 Cycle
= 24 + Orient
;
1679 Cycle
= 16 + Orient
;
1684 Cycle
= 32 + Orient
;
1687 printf("LR2 Animation: unhandled stance: %s %d\n", ResRef
, StanceID
);
1692 strcat( ResRef
, "g1e" );
1694 strcat( ResRef
, "g1" );
1698 void CharAnimations::AddMHRSuffix(char* ResRef
, unsigned char StanceID
,
1699 unsigned char& Cycle
, unsigned char Orient
, EquipResRefData
*& EquipData
)
1702 EquipData
= new EquipResRefData
;
1703 EquipData
->Suffix
[0] = 0;
1707 case IE_ANI_ATTACK_SLASH
:
1708 strcat (ResRef
, SlashPrefix
[WeaponType
]);
1709 strcpy( EquipData
->Suffix
, SlashPrefix
[WeaponType
] );
1713 case IE_ANI_ATTACK_BACKSLASH
:
1714 strcat (ResRef
, BackPrefix
[WeaponType
]);
1715 strcpy( EquipData
->Suffix
, BackPrefix
[WeaponType
] );
1719 case IE_ANI_ATTACK_JAB
:
1720 strcat (ResRef
, JabPrefix
[WeaponType
]);
1721 strcpy( EquipData
->Suffix
, JabPrefix
[WeaponType
] );
1726 strcat( ResRef
, "g1" );
1727 strcpy( EquipData
->Suffix
, "g1" );
1728 if ( WeaponType
== IE_ANI_WEAPON_2W
) {
1729 Cycle
= 24 + Orient
;
1735 case IE_ANI_CAST
://looping
1736 strcat( ResRef
, "ca" );
1737 strcpy( EquipData
->Suffix
, "ca" );
1741 case IE_ANI_CONJURE
://ending
1742 strcat( ResRef
, "ca" );
1743 strcpy( EquipData
->Suffix
, "ca" );
1748 strcat( ResRef
, "g1" );
1749 strcpy( EquipData
->Suffix
, "g1" );
1750 Cycle
= 40 + Orient
;
1755 case IE_ANI_PST_START
:
1756 strcat( ResRef
, "g1" );
1757 strcpy( EquipData
->Suffix
, "g1" );
1758 Cycle
= 48 + Orient
;
1761 //I cannot find an emerge animation...
1762 //Maybe is Die reversed
1764 strcat( ResRef
, "g1" );
1765 strcpy( EquipData
->Suffix
, "g1" );
1766 Cycle
= 48 + Orient
;
1769 case IE_ANI_HEAD_TURN
:
1770 strcat( ResRef
, "g1" );
1771 strcpy( EquipData
->Suffix
, "g1" );
1772 Cycle
= 32 + Orient
;
1775 //Unknown... maybe only a transparency effect apply
1780 strcat( ResRef
, "g1" );
1781 strcpy( EquipData
->Suffix
, "g1" );
1782 Cycle
= 16 + Orient
;
1785 //This depends on the ranged weapon equipped
1787 strcat (ResRef
, RangedPrefixOld
[RangedType
]);
1788 strcpy( EquipData
->Suffix
, RangedPrefixOld
[RangedType
] );
1793 strcat( ResRef
, "g1" );
1794 strcpy( EquipData
->Suffix
, "g1" );
1795 Cycle
= 64 + Orient
;
1799 strcat( ResRef
, "g1" );
1800 strcpy( EquipData
->Suffix
, "g1" );
1801 Cycle
= 56 + Orient
;
1805 strcat( ResRef
, "g1" );
1806 strcpy( EquipData
->Suffix
, "g1" );
1810 printf("MHR Animation: unhandled stance: %s %d\n", ResRef
, StanceID
);
1815 strcat( ResRef
, "e" );
1816 strcat( EquipData
->Suffix
, "e" );
1818 EquipData
->Cycle
= Cycle
;
1821 void CharAnimations::GetMHREquipmentRef(char* ResRef
, unsigned char& Cycle
,
1822 const char* equipRef
, bool offhand
,
1823 EquipResRefData
* equip
)
1825 Cycle
= equip
->Cycle
;
1827 //i think there is no offhand stuff for bg1, lets use the bg2 equivalent here?
1828 sprintf( ResRef
, "wq%c%c%co%s", GetSize(), equipRef
[0], equipRef
[1], equip
->Suffix
);
1830 sprintf( ResRef
, "wp%c%c%c%s", GetSize(), equipRef
[0], equipRef
[1], equip
->Suffix
);
1834 void CharAnimations::AddTwoFileSuffix( char* ResRef
, unsigned char StanceID
,
1835 unsigned char& Cycle
, unsigned char Orient
)
1838 case IE_ANI_HEAD_TURN
:
1839 Cycle
= 16 + Orient
/ 2;
1842 Cycle
= 24 + Orient
/ 2;
1846 Cycle
= 40 + Orient
/ 2;
1851 case IE_ANI_PST_START
:
1852 Cycle
= 32 + Orient
/ 2;
1858 Cycle
= 8 + Orient
/ 2;
1861 strcat( ResRef
, "g1" );
1863 strcat( ResRef
, "e" );
1867 void CharAnimations::AddLRSuffix2( char* ResRef
, unsigned char StanceID
,
1868 unsigned char& Cycle
, unsigned char Orient
, EquipResRefData
*&EquipData
)
1870 EquipData
= new EquipResRefData
;
1871 EquipData
->Suffix
[0] = 0;
1874 case IE_ANI_ATTACK_BACKSLASH
:
1875 case IE_ANI_ATTACK_SLASH
:
1876 case IE_ANI_ATTACK_JAB
:
1877 strcat( ResRef
, "g2" );
1878 strcpy( EquipData
->Suffix
, "g2" );
1882 case IE_ANI_CONJURE
:
1884 strcat( ResRef
, "g2" );
1885 strcpy( EquipData
->Suffix
, "g2" );
1886 Cycle
= 8 + Orient
/ 2;
1889 strcat( ResRef
, "g1" );
1890 strcpy( EquipData
->Suffix
, "g1" );
1894 strcat( ResRef
, "g1" );
1895 strcpy( EquipData
->Suffix
, "g1" );
1896 Cycle
= 8 + Orient
/ 2;
1898 case IE_ANI_HEAD_TURN
: //could be wrong
1900 strcat( ResRef
, "g1" );
1901 strcpy( EquipData
->Suffix
, "g1" );
1902 Cycle
= 16 + Orient
/ 2;
1905 strcat( ResRef
, "g1" );
1906 strcpy( EquipData
->Suffix
, "g1" );
1907 Cycle
= 24 + Orient
/ 2;
1911 case IE_ANI_PST_START
:
1913 strcat( ResRef
, "g1" );
1914 strcpy( EquipData
->Suffix
, "g1" );
1915 Cycle
= 32 + Orient
/ 2;
1918 strcat( ResRef
, "g1" );
1919 strcpy( EquipData
->Suffix
, "g1" );
1920 Cycle
= 40 + Orient
/ 2;
1923 printf("LRSuffix2 Animation: unhandled stance: %s %d\n", ResRef
, StanceID
);
1928 strcat( ResRef
, "e" );
1929 strcat( EquipData
->Suffix
, "e");
1931 EquipData
->Cycle
= Cycle
;
1934 void CharAnimations::AddLRSuffix( char* ResRef
, unsigned char StanceID
,
1935 unsigned char& Cycle
, unsigned char Orient
, EquipResRefData
*&EquipData
)
1937 EquipData
= new EquipResRefData
;
1938 EquipData
->Suffix
[0] = 0;
1941 case IE_ANI_ATTACK_BACKSLASH
:
1942 strcat( ResRef
, "g2" );
1943 strcpy( EquipData
->Suffix
, "g2" );
1946 case IE_ANI_ATTACK_SLASH
:
1947 strcat( ResRef
, "g2" );
1948 strcpy( EquipData
->Suffix
, "g2" );
1949 Cycle
= 8 + Orient
/ 2;
1951 case IE_ANI_ATTACK_JAB
:
1952 strcat( ResRef
, "g2" );
1953 strcpy( EquipData
->Suffix
, "g2" );
1954 Cycle
= 16 + Orient
/ 2;
1957 case IE_ANI_CONJURE
:
1959 //these animations are missing
1960 strcat( ResRef
, "g2" );
1961 strcpy( EquipData
->Suffix
, "g2" );
1965 strcat( ResRef
, "g1" );
1966 strcpy( EquipData
->Suffix
, "g1" );
1970 strcat( ResRef
, "g1" );
1971 strcpy( EquipData
->Suffix
, "g1" );
1972 Cycle
= 8 + Orient
/ 2;
1974 case IE_ANI_HEAD_TURN
: //could be wrong
1976 strcat( ResRef
, "g1" );
1977 strcpy( EquipData
->Suffix
, "g1" );
1978 Cycle
= 16 + Orient
/ 2;
1981 strcat( ResRef
, "g1" );
1982 strcpy( EquipData
->Suffix
, "g1" );
1983 Cycle
= 24 + Orient
/ 2;
1987 case IE_ANI_PST_START
:
1989 strcat( ResRef
, "g1" );
1990 strcpy( EquipData
->Suffix
, "g1" );
1991 Cycle
= 32 + Orient
/ 2;
1995 strcat( ResRef
, "g1" );
1996 strcpy( EquipData
->Suffix
, "g1" );
1997 Cycle
= 40 + Orient
/ 2;
2000 printf("LR Animation: unhandled stance: %s %d\n", ResRef
, StanceID
);
2005 strcat( ResRef
, "e" );
2006 strcat( EquipData
->Suffix
, "e");
2008 EquipData
->Cycle
= Cycle
;
2011 void CharAnimations::GetLREquipmentRef(char* ResRef
, unsigned char& Cycle
,
2012 const char* equipRef
, bool /*offhand*/,
2013 EquipResRefData
* equip
)
2015 Cycle
= equip
->Cycle
;
2017 sprintf( ResRef
, "%4s%c%s", this->ResRef
, equipRef
[0], equip
->Suffix
);
2018 printf("LREquipment resref: %s\n", ResRef
);
2021 //Only for the ogre animation (MOGR)
2022 void CharAnimations::AddLR3Suffix( char* ResRef
, unsigned char StanceID
,
2023 unsigned char& Cycle
, unsigned char Orient
)
2027 case IE_ANI_ATTACK_BACKSLASH
:
2028 strcat( ResRef
, "g2" );
2031 case IE_ANI_ATTACK_SLASH
:
2032 strcat( ResRef
, "g2" );
2033 Cycle
= 8 + Orient
/ 2;
2035 case IE_ANI_ATTACK_JAB
:
2036 strcat( ResRef
, "g2" );
2037 Cycle
= 8 + Orient
/ 2; //there is no third attack animation
2040 case IE_ANI_CONJURE
:
2042 strcat( ResRef
, "g3" );
2046 strcat( ResRef
, "g1" );
2047 Cycle
= 16 + Orient
/ 2;
2050 strcat( ResRef
, "g1" );
2051 Cycle
= 8 + Orient
/ 2;
2053 case IE_ANI_HEAD_TURN
: //could be wrong
2055 strcat( ResRef
, "g1" );
2059 strcat( ResRef
, "g3" );
2060 Cycle
= 8 + Orient
/ 2;
2065 case IE_ANI_PST_START
:
2067 strcat( ResRef
, "g3" );
2068 Cycle
= 16 + Orient
/ 2;
2071 strcat( ResRef
, "g3" );
2072 Cycle
= 24 + Orient
/ 2;
2075 printf("LR3 Animation: unhandled stance: %s %d\n", ResRef
, StanceID
);
2080 strcat( ResRef
, "e" );
2084 void CharAnimations::AddMMR2Suffix(char* ResRef
, unsigned char StanceID
,
2085 unsigned char& Cycle
, unsigned char Orient
)
2089 case IE_ANI_ATTACK_SLASH
:
2090 case IE_ANI_ATTACK_BACKSLASH
:
2091 case IE_ANI_ATTACK_JAB
:
2092 case IE_ANI_CONJURE
:
2094 strcat( ResRef
, "a1" );
2095 Cycle
= ( Orient
/ 2 );
2099 strcat( ResRef
, "a4" );
2100 Cycle
= ( Orient
/ 2 );
2105 strcat( ResRef
, "sd" );
2106 Cycle
= ( Orient
/ 2 );
2109 case IE_ANI_HEAD_TURN
:
2110 strcat( ResRef
, "sc" );
2111 Cycle
= ( Orient
/ 2 );
2115 strcat( ResRef
, "gh" );
2116 Cycle
= ( Orient
/ 2 );
2120 strcat( ResRef
, "de" );
2121 Cycle
= ( Orient
/ 2 );
2126 case IE_ANI_PST_START
:
2127 strcat( ResRef
, "gu" );
2128 Cycle
= ( Orient
/ 2 );
2131 //Unknown... maybe only a transparency effect apply
2136 strcat( ResRef
, "sl" );
2137 Cycle
= ( Orient
/ 2 );
2141 strcat( ResRef
, "tw" );
2142 Cycle
= ( Orient
/ 2 );
2146 strcat( ResRef
, "wk" );
2147 Cycle
= ( Orient
/ 2 );
2150 printf("MMR Animation: unhandled stance: %s %d\n", ResRef
, StanceID
);
2155 strcat( ResRef
, "e" );
2159 void CharAnimations::AddMMRSuffix(char* ResRef
, unsigned char StanceID
,
2160 unsigned char& Cycle
, unsigned char Orient
)
2164 case IE_ANI_ATTACK_SLASH
:
2165 case IE_ANI_ATTACK_BACKSLASH
:
2166 strcat( ResRef
, "a1" );
2167 Cycle
= ( Orient
/ 2 );
2171 strcat( ResRef
, "a4" );
2172 Cycle
= ( Orient
/ 2 );
2175 case IE_ANI_ATTACK_JAB
:
2176 strcat( ResRef
, "a2" );
2177 Cycle
= ( Orient
/ 2 );
2182 strcat( ResRef
, "sd" );
2183 Cycle
= ( Orient
/ 2 );
2186 case IE_ANI_CONJURE
:
2187 strcat( ResRef
, "ca" );
2188 Cycle
= ( Orient
/ 2 );
2192 strcat( ResRef
, "sp" );
2193 Cycle
= ( Orient
/ 2 );
2196 case IE_ANI_HEAD_TURN
:
2197 strcat( ResRef
, "sc" );
2198 Cycle
= ( Orient
/ 2 );
2202 strcat( ResRef
, "gh" );
2203 Cycle
= ( Orient
/ 2 );
2207 strcat( ResRef
, "de" );
2208 Cycle
= ( Orient
/ 2 );
2213 case IE_ANI_PST_START
:
2214 strcat( ResRef
, "gu" );
2215 Cycle
= ( Orient
/ 2 );
2218 //Unknown... maybe only a transparency effect apply
2223 strcat( ResRef
, "sl" );
2224 Cycle
= ( Orient
/ 2 );
2228 strcat( ResRef
, "tw" );
2229 Cycle
= ( Orient
/ 2 );
2233 strcat( ResRef
, "wk" );
2234 Cycle
= ( Orient
/ 2 );
2237 printf("MMR Animation: unhandled stance: %s %d\n", ResRef
, StanceID
);
2242 strcat( ResRef
, "e" );
2246 void CharAnimations::PulseRGBModifiers()
2248 unsigned long time
= core
->GetGame()->Ticks
;
2250 if (time
- lastModUpdate
<= 40)
2253 if (time
- lastModUpdate
> 400) lastModUpdate
= time
- 40;
2255 int inc
= (time
- lastModUpdate
)/40;
2256 bool change
[4] = { false, false, false, false };
2257 if (GlobalColorMod
.type
!= RGBModifier::NONE
&&
2258 GlobalColorMod
.speed
> 0)
2260 GlobalColorMod
.phase
+= inc
;
2261 change
[0] = change
[1] = change
[2] = change
[3] = true;
2264 if (GlobalColorMod
.phase
> 2*GlobalColorMod
.speed
) {
2265 GlobalColorMod
.type
= RGBModifier::NONE
;
2266 GlobalColorMod
.phase
= 0;
2267 GlobalColorMod
.speed
= 0;
2271 for (int i
= 0; i
< 32; ++i
) {
2272 if (ColorMods
[i
].type
!= RGBModifier::NONE
&&
2273 ColorMods
[i
].speed
> 0)
2275 ColorMods
[i
].phase
+= inc
;
2276 change
[i
>>3] = true;
2280 if (change
[0]) SetupColors(PAL_MAIN
);
2281 if (change
[1]) SetupColors(PAL_WEAPON
);
2282 if (change
[2]) SetupColors(PAL_OFFHAND
);
2283 if (change
[3]) SetupColors(PAL_HELMET
);
2285 lastModUpdate
+= inc
*40;