void drawEffect(const Point& dest, float scaleFactor, bool animate, int offsetX = 0, int offsetY = 0, LightView *lightView = nullptr);
for(const EffectPtr& effect : m_effects)
effect->drawEffect(dest - m_drawElevation*scaleFactor, scaleFactor, animate, m_position.x - g_map.getCentralPosition().x, m_position.y - g_map.getCentralPosition().y, lightView);
hey guys, can you help me to do that?
hello, how to make the animation on player (eg if it has 7 animations) was still on him (player) if player moves?
void Creature::internalDrawOutfit(Point dest, float scaleFactor, bool animateWalk, bool animateIdle, Otc::Direction direction, LightView *lightView)
{
g_painter->setColor(m_outfitColor);
// outfit is a real creature
if(m_outfit.getCategory() == ThingCategoryCreature) {
int animationPhase = animateWalk ? m_walkAnimationPhase : 0;
if(isAnimateAlways() && animateIdle) {
int ticksPerFrame = 1000 / getAnimationPhases();
animationPhase = (g_clock.millis() % (ticksPerFrame * getAnimationPhases())) / ticksPerFrame;
}
// xPattern => creature direction
int xPattern;
if(direction == Otc::NorthEast || direction == Otc::SouthEast)
xPattern = Otc::East;
else if(direction == Otc::NorthWest || direction == Otc::SouthWest)
xPattern = Otc::West;
else
xPattern = direction;
int zPattern = 0;
if(m_outfit.getMount() != 0) {
auto datType = g_things.rawGetThingType(m_outfit.getMount(), ThingCategoryCreature);
dest -= datType->getDisplacement() * scaleFactor;
datType->draw(dest, scaleFactor, 0, xPattern, 0, 0, animationPhase, lightView);
dest += getDisplacement() * scaleFactor;
zPattern = std::min<int>(1, getNumPatternZ() - 1);
}
PointF jumpOffset = m_jumpOffset * scaleFactor;
dest -= Point(stdext::round(jumpOffset.x), stdext::round(jumpOffset.y));
// yPattern => creature addon
for(int yPattern = 0; yPattern < getNumPatternY(); yPattern++) {
// continue if we dont have this addon
if(yPattern > 0 && !(m_outfit.getAddons() & (1 << (yPattern-1))))
continue;
auto datType = rawGetThingType();
datType->draw(dest, scaleFactor, 0, xPattern, yPattern, zPattern, animationPhase, yPattern == 0 ? lightView : nullptr);
if(getLayers() > 1) {
Color oldColor = g_painter->getColor();
Painter::CompositionMode oldComposition = g_painter->getCompositionMode();
g_painter->setCompositionMode(Painter::CompositionMode_Multiply);
g_painter->setColor(m_outfit.getHeadColor());
datType->draw(dest, scaleFactor, SpriteMaskYellow, xPattern, yPattern, zPattern, animationPhase);
g_painter->setColor(m_outfit.getBodyColor());
datType->draw(dest, scaleFactor, SpriteMaskRed, xPattern, yPattern, zPattern, animationPhase);
g_painter->setColor(m_outfit.getLegsColor());
datType->draw(dest, scaleFactor, SpriteMaskGreen, xPattern, yPattern, zPattern, animationPhase);
g_painter->setColor(m_outfit.getFeetColor());
datType->draw(dest, scaleFactor, SpriteMaskBlue, xPattern, yPattern, zPattern, animationPhase);
g_painter->setColor(oldColor);
g_painter->setCompositionMode(oldComposition);
}
}
// outfit is a creature imitating an item or the invisible effect
} else {
ThingType *type = g_things.rawGetThingType(m_outfit.getAuxId(), m_outfit.getCategory());
int animationPhase = 0;
int animationPhases = type->getAnimationPhases();
int animateTicks = Otc::ITEM_TICKS_PER_FRAME;
// when creature is an effect we cant render the first and last animation phase,
// instead we should loop in the phases between
if(m_outfit.getCategory() == ThingCategoryEffect) {
animationPhases = std::max<int>(1, animationPhases-2);
animateTicks = Otc::INVISIBLE_TICKS_PER_FRAME;
}
if(animationPhases > 1) {
if(animateIdle)
animationPhase = (g_clock.millis() % (animateTicks * animationPhases)) / animateTicks;
else
animationPhase = animationPhases-1;
}
if(m_outfit.getCategory() == ThingCategoryEffect)
animationPhase = std::min<int>(animationPhase+1, animationPhases);
type->draw(dest - (getDisplacement() * scaleFactor), scaleFactor, 0, 0, 0, 0, animationPhase, lightView);
}
g_painter->resetColor();
}
void Creature::internalDrawOutfit(Point dest, float scaleFactor, bool animateWalk, bool animateIdle, Otc::Direction direction, LightView *lightView)
{
g_painter->setColor(m_outfitColor);
// outfit is a real creature
if(m_outfit.getCategory() == ThingCategoryCreature) {
int animationPhase = animateWalk ? m_walkAnimationPhase : 0;
if(isAnimateAlways() && animateIdle) {
int ticksPerFrame = 1000 / getAnimationPhases();
animationPhase = (g_clock.millis() % (ticksPerFrame * getAnimationPhases())) / ticksPerFrame;
}
// xPattern => creature direction
int xPattern;
if(direction == Otc::NorthEast || direction == Otc::SouthEast)
xPattern = Otc::East;
else if(direction == Otc::NorthWest || direction == Otc::SouthWest)
xPattern = Otc::West;
else
xPattern = direction;
int zPattern = 0;
if(m_outfit.getMount() != 0) {
auto datType = g_things.rawGetThingType(m_outfit.getMount(), ThingCategoryCreature);
dest -= datType->getDisplacement() * scaleFactor;
datType->draw(dest, scaleFactor, 0, xPattern, 0, 0, animationPhase, lightView);
dest += getDisplacement() * scaleFactor;
zPattern = std::min<int>(1, getNumPatternZ() - 1);
}
PointF jumpOffset = m_jumpOffset * scaleFactor;
dest -= Point(stdext::round(jumpOffset.x), stdext::round(jumpOffset.y));
// yPattern => creature addon
for(int yPattern = 0; yPattern < getNumPatternY(); yPattern++) {
// continue if we dont have this addon
if(yPattern > 0 && !(m_outfit.getAddons() & (1 << (yPattern-1))))
continue;
auto datType = rawGetThingType();
datType->draw(dest, scaleFactor, 0, xPattern, yPattern, zPattern, animationPhase, yPattern == 0 ? lightView : nullptr);
if(getLayers() > 1) {
Color oldColor = g_painter->getColor();
Painter::CompositionMode oldComposition = g_painter->getCompositionMode();
g_painter->setCompositionMode(Painter::CompositionMode_Multiply);
g_painter->setColor(m_outfit.getHeadColor());
datType->draw(dest, scaleFactor, SpriteMaskYellow, xPattern, yPattern, zPattern, animationPhase);
g_painter->setColor(m_outfit.getBodyColor());
datType->draw(dest, scaleFactor, SpriteMaskRed, xPattern, yPattern, zPattern, animationPhase);
g_painter->setColor(m_outfit.getLegsColor());
datType->draw(dest, scaleFactor, SpriteMaskGreen, xPattern, yPattern, zPattern, animationPhase);
g_painter->setColor(m_outfit.getFeetColor());
datType->draw(dest, scaleFactor, SpriteMaskBlue, xPattern, yPattern, zPattern, animationPhase);
g_painter->setColor(oldColor);
g_painter->setCompositionMode(oldComposition);
}
}
// outfit is a creature imitating an item or the invisible effect
} else {
ThingType *type = g_things.rawGetThingType(m_outfit.getAuxId(), m_outfit.getCategory());
int animationPhase = 0;
int animationPhases = type->getAnimationPhases();
int animateTicks = Otc::ITEM_TICKS_PER_FRAME;
// when creature is an effect we cant render the first and last animation phase,
// instead we should loop in the phases between
if(m_outfit.getCategory() == ThingCategoryEffect) {
animationPhases = std::max<int>(1, animationPhases-2);
animateTicks = Otc::INVISIBLE_TICKS_PER_FRAME;
}
if(animationPhases > 1) {
if(animateIdle)
animationPhase = (g_clock.millis() % (animateTicks * animationPhases)) / animateTicks;
else
animationPhase = animationPhases-1;
}
if(m_outfit.getCategory() == ThingCategoryEffect)
animationPhase = std::min<int>(animationPhase+1, animationPhases);
type->draw(dest - (getDisplacement() * scaleFactor), scaleFactor, 0, 0, 0, 0, animationPhase, lightView);
}
//draw effect on creature
ThingType *type = g_things.rawGetThingType(42, ThingCategoryEffect);
int animationPhase = 0;
int animationPhases = type->getAnimationPhases();
int animateTicks = Otc::ITEM_TICKS_PER_FRAME;
animationPhases = std::max<int>(1, animationPhases-2);
animateTicks = 50;
if(animationPhases > 1) {
if(animateIdle)
animationPhase = (g_clock.millis() % (animateTicks * animationPhases)) / animateTicks;
else
animationPhase = animationPhases-1;
}
animationPhase = std::min<int>(animationPhase+1, animationPhases);
type->draw(dest - (getDisplacement() * scaleFactor), scaleFactor, 0, 0, 0, 0, animationPhase, lightView);
//end
g_painter->resetColor();
}
Not this way.
@margoh told you well
Depends how you wanna stick animation to character. cuz just for 'stick animation to creature' you can look at how invisible effect works in OTC and use that to draw your own animation.
First of all you have to decide when you want to draw it, before outfit, after outfit etc. let's say you want to draw your stricked effect at the top.
You can ctrl+c ctrl+v current invisible effect so it will result something like this:
before:
C++:void Creature::internalDrawOutfit(Point dest, float scaleFactor, bool animateWalk, bool animateIdle, Otc::Direction direction, LightView *lightView) { g_painter->setColor(m_outfitColor); // outfit is a real creature if(m_outfit.getCategory() == ThingCategoryCreature) { int animationPhase = animateWalk ? m_walkAnimationPhase : 0; if(isAnimateAlways() && animateIdle) { int ticksPerFrame = 1000 / getAnimationPhases(); animationPhase = (g_clock.millis() % (ticksPerFrame * getAnimationPhases())) / ticksPerFrame; } // xPattern => creature direction int xPattern; if(direction == Otc::NorthEast || direction == Otc::SouthEast) xPattern = Otc::East; else if(direction == Otc::NorthWest || direction == Otc::SouthWest) xPattern = Otc::West; else xPattern = direction; int zPattern = 0; if(m_outfit.getMount() != 0) { auto datType = g_things.rawGetThingType(m_outfit.getMount(), ThingCategoryCreature); dest -= datType->getDisplacement() * scaleFactor; datType->draw(dest, scaleFactor, 0, xPattern, 0, 0, animationPhase, lightView); dest += getDisplacement() * scaleFactor; zPattern = std::min<int>(1, getNumPatternZ() - 1); } PointF jumpOffset = m_jumpOffset * scaleFactor; dest -= Point(stdext::round(jumpOffset.x), stdext::round(jumpOffset.y)); // yPattern => creature addon for(int yPattern = 0; yPattern < getNumPatternY(); yPattern++) { // continue if we dont have this addon if(yPattern > 0 && !(m_outfit.getAddons() & (1 << (yPattern-1)))) continue; auto datType = rawGetThingType(); datType->draw(dest, scaleFactor, 0, xPattern, yPattern, zPattern, animationPhase, yPattern == 0 ? lightView : nullptr); if(getLayers() > 1) { Color oldColor = g_painter->getColor(); Painter::CompositionMode oldComposition = g_painter->getCompositionMode(); g_painter->setCompositionMode(Painter::CompositionMode_Multiply); g_painter->setColor(m_outfit.getHeadColor()); datType->draw(dest, scaleFactor, SpriteMaskYellow, xPattern, yPattern, zPattern, animationPhase); g_painter->setColor(m_outfit.getBodyColor()); datType->draw(dest, scaleFactor, SpriteMaskRed, xPattern, yPattern, zPattern, animationPhase); g_painter->setColor(m_outfit.getLegsColor()); datType->draw(dest, scaleFactor, SpriteMaskGreen, xPattern, yPattern, zPattern, animationPhase); g_painter->setColor(m_outfit.getFeetColor()); datType->draw(dest, scaleFactor, SpriteMaskBlue, xPattern, yPattern, zPattern, animationPhase); g_painter->setColor(oldColor); g_painter->setCompositionMode(oldComposition); } } // outfit is a creature imitating an item or the invisible effect } else { ThingType *type = g_things.rawGetThingType(m_outfit.getAuxId(), m_outfit.getCategory()); int animationPhase = 0; int animationPhases = type->getAnimationPhases(); int animateTicks = Otc::ITEM_TICKS_PER_FRAME; // when creature is an effect we cant render the first and last animation phase, // instead we should loop in the phases between if(m_outfit.getCategory() == ThingCategoryEffect) { animationPhases = std::max<int>(1, animationPhases-2); animateTicks = Otc::INVISIBLE_TICKS_PER_FRAME; } if(animationPhases > 1) { if(animateIdle) animationPhase = (g_clock.millis() % (animateTicks * animationPhases)) / animateTicks; else animationPhase = animationPhases-1; } if(m_outfit.getCategory() == ThingCategoryEffect) animationPhase = std::min<int>(animationPhase+1, animationPhases); type->draw(dest - (getDisplacement() * scaleFactor), scaleFactor, 0, 0, 0, 0, animationPhase, lightView); } g_painter->resetColor(); }
after:
C++:void Creature::internalDrawOutfit(Point dest, float scaleFactor, bool animateWalk, bool animateIdle, Otc::Direction direction, LightView *lightView) { g_painter->setColor(m_outfitColor); // outfit is a real creature if(m_outfit.getCategory() == ThingCategoryCreature) { int animationPhase = animateWalk ? m_walkAnimationPhase : 0; if(isAnimateAlways() && animateIdle) { int ticksPerFrame = 1000 / getAnimationPhases(); animationPhase = (g_clock.millis() % (ticksPerFrame * getAnimationPhases())) / ticksPerFrame; } // xPattern => creature direction int xPattern; if(direction == Otc::NorthEast || direction == Otc::SouthEast) xPattern = Otc::East; else if(direction == Otc::NorthWest || direction == Otc::SouthWest) xPattern = Otc::West; else xPattern = direction; int zPattern = 0; if(m_outfit.getMount() != 0) { auto datType = g_things.rawGetThingType(m_outfit.getMount(), ThingCategoryCreature); dest -= datType->getDisplacement() * scaleFactor; datType->draw(dest, scaleFactor, 0, xPattern, 0, 0, animationPhase, lightView); dest += getDisplacement() * scaleFactor; zPattern = std::min<int>(1, getNumPatternZ() - 1); } PointF jumpOffset = m_jumpOffset * scaleFactor; dest -= Point(stdext::round(jumpOffset.x), stdext::round(jumpOffset.y)); // yPattern => creature addon for(int yPattern = 0; yPattern < getNumPatternY(); yPattern++) { // continue if we dont have this addon if(yPattern > 0 && !(m_outfit.getAddons() & (1 << (yPattern-1)))) continue; auto datType = rawGetThingType(); datType->draw(dest, scaleFactor, 0, xPattern, yPattern, zPattern, animationPhase, yPattern == 0 ? lightView : nullptr); if(getLayers() > 1) { Color oldColor = g_painter->getColor(); Painter::CompositionMode oldComposition = g_painter->getCompositionMode(); g_painter->setCompositionMode(Painter::CompositionMode_Multiply); g_painter->setColor(m_outfit.getHeadColor()); datType->draw(dest, scaleFactor, SpriteMaskYellow, xPattern, yPattern, zPattern, animationPhase); g_painter->setColor(m_outfit.getBodyColor()); datType->draw(dest, scaleFactor, SpriteMaskRed, xPattern, yPattern, zPattern, animationPhase); g_painter->setColor(m_outfit.getLegsColor()); datType->draw(dest, scaleFactor, SpriteMaskGreen, xPattern, yPattern, zPattern, animationPhase); g_painter->setColor(m_outfit.getFeetColor()); datType->draw(dest, scaleFactor, SpriteMaskBlue, xPattern, yPattern, zPattern, animationPhase); g_painter->setColor(oldColor); g_painter->setCompositionMode(oldComposition); } } // outfit is a creature imitating an item or the invisible effect } else { ThingType *type = g_things.rawGetThingType(m_outfit.getAuxId(), m_outfit.getCategory()); int animationPhase = 0; int animationPhases = type->getAnimationPhases(); int animateTicks = Otc::ITEM_TICKS_PER_FRAME; // when creature is an effect we cant render the first and last animation phase, // instead we should loop in the phases between if(m_outfit.getCategory() == ThingCategoryEffect) { animationPhases = std::max<int>(1, animationPhases-2); animateTicks = Otc::INVISIBLE_TICKS_PER_FRAME; } if(animationPhases > 1) { if(animateIdle) animationPhase = (g_clock.millis() % (animateTicks * animationPhases)) / animateTicks; else animationPhase = animationPhases-1; } if(m_outfit.getCategory() == ThingCategoryEffect) animationPhase = std::min<int>(animationPhase+1, animationPhases); type->draw(dest - (getDisplacement() * scaleFactor), scaleFactor, 0, 0, 0, 0, animationPhase, lightView); } //draw effect on creature ThingType *type = g_things.rawGetThingType(42, ThingCategoryEffect); int animationPhase = 0; int animationPhases = type->getAnimationPhases(); int animateTicks = Otc::ITEM_TICKS_PER_FRAME; animationPhases = std::max<int>(1, animationPhases-2); animateTicks = 50; if(animationPhases > 1) { if(animateIdle) animationPhase = (g_clock.millis() % (animateTicks * animationPhases)) / animateTicks; else animationPhase = animationPhases-1; } animationPhase = std::min<int>(animationPhase+1, animationPhases); type->draw(dest - (getDisplacement() * scaleFactor), scaleFactor, 0, 0, 0, 0, animationPhase, lightView); //end g_painter->resetColor(); }
With this code you will see animation with id 42 and phase delay 50 miliseconds will be rendered on your outfit even if you will move your character.
But what now? You need to decide whats next, you can make some cool effect just for your vocation, so every vocation with id = x wil have animation effect with id y, or just show this effect with declared duration just when you will use some function. It's hard to just give easy to use code for this thing, because everything depends where you want to use this. You can pass this effect + duration in addCreature func, and then check in client if creature have some parameter and only then draw this effect, or maybe you want to stick some effect to character when this effect will be rendered on sqms where player currently is, for example:
You have 25 frames effect, and default duration of this effect is 2.5 seconds. You wanna use this effect on some area rune, so when your rune will hit target on area you want to stick this effect to character for that 2.5 seconds.
I send this post cuz stil some users have this problem.
wow what a helpfull reply lol, don't spam if u have nothing usefull to say.