• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

animateAlways in Outfit - Possibility to ALWAYS begin from first frame, continue to last and then reset timer?

Fresh

Quack!
Joined
Oct 21, 2009
Messages
1,837
Solutions
18
Reaction score
615
Location
Poland
Hello all OTClient users!
I've noticed today an strange thing with animateAlways flag in outfits in OTClient.

I need to make it work like this :
When outfit have animateAlways flag and it's visible (creature/player got that outfit for certain time (in example: 1 second) using for example: doSetCreatureOutfit(player, {lookType = 235}, 1000) ) it should be displayed like this: Got Outfit -> Start from First Frame -> Goes through all (in my case there are 5 frames , duration between each frame is 200ms so 5 * 200 = 1000ms = 1 second) -> Finish "animation" and start from begin if need's.

Disclaimer:
I don't have aSynch/other animation options in my ObjectBuilder, dunno why but I searched entire OtLand and can't get working ObjectBuilder that have animation options / frame durations / groups. All the time I find any builder have only one option not all, so im using that one who have frame durations/groups.

Preview of what I mean:
[1] Video of Problem
[2] Video of What It Should Be

As you can see
[1], the animation is working sometimes (goes good between all frames) or sometimes it stuck/glitch on certain frame or skip or going from reverse (from last to first). On [2] (it's from object builder) that way should be in-game, but I can't handle it to be in-game like this.


Anyone have any clue how to fix that and do it in the way like I said before?
(Receive Outfit -> Start from First Frame -> Goes through all (in my case there are 5 frames , duration between each frame is 200ms so 5 * 200 = 1000ms = 1 second) -> Finish "animation" and start from begin)

Thanks in advance,
Waiting for any good reply with tips,
Fresh.
 
:rolleyes:
Post automatically merged:

Fixed by myself.
Thread can be closed.

Solution:
creature.cpp

C++:
       const auto& type = g_things.rawGetThingType(m_outfit.getId(), ThingCategoryCreature);
        } else if (isAnimateAlways()) {
       // Those under are unused but I added it to calculate REALISTIC time between frames (if you have frame duration (time between frames) in ObjectBuilder, those values under might be helpful for you in something/other ideas)
            int phases = type->getAnimator() ? type->getAnimator()->getAnimationPhases() : type->getAnimationPhases(); // get all frames from objectbuilder
            int totalDuration = type->getAnimator()->getTotalDuration(); // get totalduration (all duration [duration*number of frames]
            int tickPerFrame = totalDuration / phases; // divide totalDuration and number of all frames to get individual duration from objectbuilder

            animationPhase = rawGetThingType()->getAnimator()->getPhaseAt(m_animateAlwaysTimer.ticksElapsed());

        }
and in function void Creature::setOutfit(const Outfit& outfit) in creature.cpp, you need to restart timer (begin from start) so put it somewhere in that function after changing outfit.
C++:
m_animateAlwaysTimer.restart();

creature.h
C++:
Timer m_animateAlwaysTimer;
 
Last edited:
Quick Bug-Fix.
I saw that if you add this code above, all "AnimateAlways" outfits are animated only one time.
To fix that, you have 2 ways making it fixed.
1) You can add restarting timer m_animateAlwaysTimer.restart(); if animation reach last frame, so it will be something like this:
C++:
            if (type->getAnimator()->getPhase() == phases) { // if current Phase (frame) is last (phases = number of total frames, so it will be last frame)
                m_animateAlwaysTimer.restart();
            }
This (1) is not tested by me (im not using it but should work)

2) Add to .OTML in outfit something like:
Code:
creatures:
  235: // ID of outfit
    animate-one-time: true
and add animate-one-time OTML thingtype flag in client sources in thingtype.cpp, after that you can use this:
C++:
            if (type->animateOneTime()) {
                animationPhase = rawGetThingType()->getAnimator()->getPhaseAt(m_animateAlwaysTimer.ticksElapsed());
            } else {
                animationPhase = (g_clock.millis() % (timeBetweenFrames * phases)) / timeBetweenFrames;
            }
And of course in void Creature::setOutfit(const Outfit& outfit) in creature.cpp
C++:
    if (type->animateOneTime()) {
    m_animateAlwaysTimer.restart();
    }
So if you define specific outfit to be animated only one time (like in my case) in .OTML file, only this outfit will be "animated only once", all other outfits with animateAlways flag in ObjectBuilder will be animated infinite (loop all the time).
 
Back
Top