diff --git a/src/animation/animation_wiggle.cpp b/src/animation/animation_wiggle.cpp index 9376539d4..66788ef0d 100644 --- a/src/animation/animation_wiggle.cpp +++ b/src/animation/animation_wiggle.cpp @@ -52,6 +52,55 @@ y *= Heading2Y[unit.Direction / NextDirection]; unit.IX += x; unit.IY += y; + } else if (this->ifNotReached) { + int targetX = x * PixelTileSize.x; + int targetY = y * PixelTileSize.y; + int curX = unit.tilePos.x * PixelTileSize.x + unit.IX; + int curY = unit.tilePos.y * PixelTileSize.y + unit.IY; + int speed = ParseAnimInt(unit, this->speed.c_str()); + + bool reachedX = curX == targetX; + if (reachedX && curY == targetY) { + return; + } + + // watch out for overflow: IX/IY are only signed chars + // we treat the target as reached if we cannot get closer + + signed char newDisplacement; + if (curX > targetX) { + newDisplacement = unit.IX - speed; + if (newDisplacement < unit.IX) { + unit.IX = newDisplacement; + } else { + reachedX = true; + } + } else if (curX < targetX) { + newDisplacement = unit.IX + speed; + if (newDisplacement > unit.IX) { + unit.IX = newDisplacement; + } else { + reachedX = true; + } + } + if (curY > targetY) { + newDisplacement = unit.IY - speed; + if (newDisplacement < unit.IY) { + unit.IY = newDisplacement; + } else if (reachedX) { + return; + } + } else if (curY < targetY) { + newDisplacement = unit.IY + speed; + if (newDisplacement > unit.IY) { + unit.IY = newDisplacement; + } else if (reachedX) { + return; + } + } else if (reachedX) { + return; + } + unit.Anim.Anim = this->ifNotReached; } else { unit.IX += x; unit.IY += y; @@ -73,10 +122,15 @@ begin = std::min(len, str.find_first_not_of(' ', end)); end = std::min(len, str.find(' ', begin)); - std::string mode(str, begin, end - begin); - if (mode == "absolute") { - } else if (mode == "heading") { + this->speed.assign(str, begin, end - begin); + if (this->speed == "absolute") { + } else if (this->speed == "heading") { this->isHeading = true; + } else { + begin = std::min(len, str.find_first_not_of(' ', end)); + end = std::min(len, str.find(' ', begin)); + std::string label(str, begin, end - begin); + FindLabelLater(&this->ifNotReached, label); } } diff --git a/src/include/animation/animation_wiggle.h b/src/include/animation/animation_wiggle.h index 3aa15e129..739ab6dc3 100644 --- a/src/include/animation/animation_wiggle.h +++ b/src/include/animation/animation_wiggle.h @@ -38,7 +38,7 @@ class CAnimation_Wiggle : public CAnimation { public: - CAnimation_Wiggle() : CAnimation(AnimationWiggle), isHeading(false), speed(0), ifNotReached(NULL) {} + CAnimation_Wiggle() : CAnimation(AnimationWiggle), isHeading(false), speed(""), ifNotReached(NULL) {} virtual void Action(CUnit &unit, int &move, int scale) const; virtual void Init(const char *s, lua_State *l);