diff --git a/src/otclient/core/creature.cpp b/src/otclient/core/creature.cpp index 66467e8f..9d7d99c5 100644 --- a/src/otclient/core/creature.cpp +++ b/src/otclient/core/creature.cpp @@ -1,68 +1,171 @@ - #include "creature.h" +#include "creature.h" #include "datmanager.h" +#include "localplayer.h" +#include "map.h" +#include #include -#include -#include "game.h" #include Creature::Creature() : Thing(THING_CREATURE) { m_healthPercent = 0; m_direction = DIRECTION_SOUTH; + m_animation = 0; + + m_walking = false; + m_walkOffsetX = 0; + m_walkOffsetY = 0; + m_lastTicks = g_platform.getTicks(); } void Creature::draw(int x, int y) { - //ThingAttributes *creatureAttributes = getAttributes(); - int anim = 0; + //dump << (int)m_speed; + + // gspeed = 100 + // pspeed = 234 + // (recorded) 400 - 866 = 466 + // (calc by ot eq) 1000 * 100 / 234 = 427 + + // gspeed = 150 + // pspeed = 234 + // (recorded) 934 - 1597 = 663 + // (calc by ot eq) 1000 * 150 / 234 = 641 - // draw outfit - internalDraw(x, y, 0, m_direction, 0, 0, anim); + // gspeed = 100 + // pspeed = 110 + // (recorded) 900 - 1833 = 933 + // (calc by ot eq) 1000 * 100 / 110 = 909 + + // 1000 * groundSpeed / playerSpeed + + // TODO 1: ADD 2 NEW RENDER STEPS, CREATURE AND TOP 3 + // TODO 2: CONSIDER STRETCH FACTOR ON drawInformation + // TODO 3: FIX MAP BUGGY TILES ?? const ThingAttributes& attributes = getAttributes(); - if(attributes.blendframes > 1) { - g_graphics.bindBlendFunc(BLEND_COLORIZING); - - for(int mask = 0; mask < 4; ++mask) { - - int outfitColorId = 0; - if(mask == SpriteMaskYellow) - outfitColorId = m_outfit.head; - else if(mask == SpriteMaskRed) - outfitColorId = m_outfit.body; - else if(mask == SpriteMaskGreen) - outfitColorId = m_outfit.legs; - else if(mask == SpriteMaskBlue) - outfitColorId = m_outfit.feet; - - g_graphics.bindColor(OutfitColors[outfitColorId]); - internalDraw(x, y, 1, m_direction, 0, 0, anim, (SpriteMask)mask); + + // we must walk 32 pixels in m_speed miliseconds + if(m_walking && attributes.animcount > 1) { + + + int groundSpeed = 0; + + ThingPtr ground = g_map.getThing(m_walkingPosition, 0); + if(ground) + groundSpeed = ground->getAttributes().speed; + + float walkTime = 1000.0 * (float)groundSpeed / m_speed; + + //dump << walkTime << (g_platform.getTicks() - m_lastTicks+1); + + if(m_direction == DIRECTION_NORTH) + m_walkOffsetY -= (32.0 / walkTime) * (g_platform.getTicks() - m_lastTicks+1); + else if(m_direction == DIRECTION_EAST) + m_walkOffsetX += (32.0 / walkTime) * (g_platform.getTicks() - m_lastTicks+1); + else if(m_direction == DIRECTION_SOUTH) + m_walkOffsetY += (32.0 / walkTime) * (g_platform.getTicks() - m_lastTicks+1); + else if(m_direction == DIRECTION_WEST) + m_walkOffsetX -= (32.0 / walkTime) * (g_platform.getTicks() - m_lastTicks+1); + + /*if(g_platform.getTicks() - m_lastTicks > m_speed / 4) { + if(m_animation+1 == attributes.animcount) + m_animation = 1; + else + m_animation++; + + m_lastTicks = g_platform.getTicks(); + }*/ + + dump << m_walkOffsetY; + + if(fabs(m_walkOffsetY) >= 32) { + g_map.removeThingByPtr(asThing()); + + // calc newpos + m_position = m_walkingPosition; + + g_map.addThing(asThing()); + m_walking = false; + m_walkOffsetY = 0; } - g_graphics.bindBlendFunc(BLEND_NORMAL); - g_graphics.bindColor(Color::white); + //m_lastTicks = g_platform.getTicks(); + } + + m_lastTicks = g_platform.getTicks(); + + x += m_walkOffsetX; + y += m_walkOffsetY; + + + for(int ydiv = 0; ydiv < attributes.ydiv; ydiv++) { + + // continue if we dont have this addon. + if(ydiv > 0 && !(m_outfit.addons & (1 << (ydiv-1)))) + continue; + + // draw white item + internalDraw(x, y, 0, m_direction, ydiv, 0, m_animation); + + // draw mask if exists + if(attributes.blendframes > 1) { + g_graphics.bindBlendFunc(BLEND_COLORIZING); + + for(int mask = 0; mask < 4; ++mask) { + + int outfitColorId = 0; + if(mask == SpriteMaskYellow) + outfitColorId = m_outfit.head; + else if(mask == SpriteMaskRed) + outfitColorId = m_outfit.body; + else if(mask == SpriteMaskGreen) + outfitColorId = m_outfit.legs; + else if(mask == SpriteMaskBlue) + outfitColorId = m_outfit.feet; + + g_graphics.bindColor(OutfitColors[outfitColorId]); + internalDraw(x, y, 1, m_direction, ydiv, 0, m_animation, (SpriteMask)mask); + } + + g_graphics.bindBlendFunc(BLEND_NORMAL); + g_graphics.bindColor(Color::white); + } } } void Creature::drawInformation(int x, int y, bool useGray) { + x += m_walkOffsetX; + y += m_walkOffsetY; + Color fillColor = Color(96, 96, 96); if(!useGray) { - // health bar + // health bar according to yatc fillColor = Color::black; - if(m_healthPercent > 60 && m_healthPercent <= 100) { - fillColor.setRed(0.0f); - fillColor.setGreen(0.75f); - } else if(m_healthPercent > 30 && m_healthPercent <= 60) { - fillColor.setRed(0.75f); - fillColor.setGreen(0.75f); - } else if(m_healthPercent > 10 && m_healthPercent <= 30) { - fillColor.setRed(0.75f); - fillColor.setGreen(0.00f); - } else if(m_healthPercent > 0 && m_healthPercent <= 10) { - fillColor.setRed(0.25f); - fillColor.setGreen(0.00f); + if(m_healthPercent > 92) { + fillColor.setGreen(188); + } + else if(m_healthPercent > 60) { + fillColor.setRed(80); + fillColor.setGreen(161); + fillColor.setBlue(80); + } + else if(m_healthPercent > 30) { + fillColor.setRed(161); + fillColor.setGreen(161); + } + else if(m_healthPercent > 8) { + fillColor.setRed(160); + fillColor.setGreen(39); + fillColor.setBlue(39); + } + else if(m_healthPercent > 3) { + fillColor.setRed(160); + } + else { + fillColor.setRed(79); } } @@ -84,6 +187,30 @@ void Creature::drawInformation(int x, int y, bool useGray) font->renderText(m_name, Rect(x-100, y-15, 200, 15), AlignTopCenter, fillColor); } +void Creature::walk(const Position& position) +{ + m_walking = true; + m_walkOffsetX = 0; + m_walkOffsetY = 0; + m_walkingPosition = position; + + if(m_position + Position(0, -1, 0) == m_walkingPosition) + m_direction = DIRECTION_NORTH; + else if(m_position + Position(1, 0, 0) == m_walkingPosition) + m_direction = DIRECTION_EAST; + else if(m_position + Position(0, 1, 0) == m_walkingPosition) + m_direction = DIRECTION_SOUTH; + else if(m_position + Position(-1, 0, 0) == m_walkingPosition) + m_direction = DIRECTION_WEST; + else { // Teleport + g_map.removeThingByPtr(asThing()); + m_position = m_walkingPosition; + g_map.addThing(asThing()); + + m_walking = false; + } +} + const ThingAttributes& Creature::getAttributes() { return g_dat.getCreatureAttributes(m_outfit.type); diff --git a/src/otclient/core/creature.h b/src/otclient/core/creature.h index 6872a032..45c8ab35 100644 --- a/src/otclient/core/creature.h +++ b/src/otclient/core/creature.h @@ -43,6 +43,8 @@ public: uint8 getEmblem() { return m_emblem; } bool getImpassable() { return m_impassable; } + void walk(const Position& position); + const ThingAttributes& getAttributes(); CreaturePtr asCreature() { return std::static_pointer_cast(shared_from_this()); } @@ -58,6 +60,12 @@ private: uint8 m_shield; uint8 m_emblem; bool m_impassable; + + int m_lastTicks; + bool m_walking; + Position m_walkingPosition; + float m_walkOffsetX, m_walkOffsetY; + int m_animation; }; #endif diff --git a/src/otclient/core/datmanager.cpp b/src/otclient/core/datmanager.cpp index caac3cd6..3d759aab 100644 --- a/src/otclient/core/datmanager.cpp +++ b/src/otclient/core/datmanager.cpp @@ -17,9 +17,14 @@ bool DatManager::load(const std::string& file) int numShots = fw::getu16(fin); m_itemsAttributes.resize(numItems); - for(int id = 100; id < numItems; ++id) + for(int id = 100; id < numItems; ++id) { parseThingAttributes(fin, m_itemsAttributes[id - 100]); + if(id == 436 || id == 870 || id == 4522) { + dump << id << (int)m_itemsAttributes[id-100].speed; + } + } + m_creaturesAttributes.resize(numItems); for(int id = 0; id < numCreatures; ++id) parseThingAttributes(fin, m_creaturesAttributes[id]); diff --git a/src/otclient/core/item.cpp b/src/otclient/core/item.cpp index 09c651b9..ff170817 100644 --- a/src/otclient/core/item.cpp +++ b/src/otclient/core/item.cpp @@ -1,23 +1,59 @@ #include "item.h" #include "datmanager.h" #include "spritemanager.h" -#include #include "thing.h" +#include Item::Item() : Thing(THING_ITEM) { m_count = 0; + m_lastTicks = g_platform.getTicks(); + m_animation = 0; } void Item::draw(int x, int y) { const ThingAttributes& attributes = g_dat.getItemAttributes(m_id); + int xdiv = 0, ydiv = 0, zdiv = 0; - int xdiv = 0, ydiv = 0, zdiv = 0, anim = 0; - if(attributes.group == THING_GROUP_SPLASH || attributes.group == THING_GROUP_FLUID || attributes.stackable) { - //cDivX = subType % itemAttributes->xdiv; - //cDivY = subType / itemAttributes->xdiv; + if(attributes.animcount > 1) { + if(g_platform.getTicks() - m_lastTicks > 500) { + if(m_animation+1 == attributes.animcount) + m_animation = 0; + else + m_animation++; + + m_lastTicks = g_platform.getTicks(); + } + } + + if(attributes.group == THING_GROUP_SPLASH || attributes.group == THING_GROUP_FLUID) { + //xdiv = m_count % attributes.xdiv; + //ydiv = m_count / attributes.ydiv; + + } + else if(attributes.stackable) { + if(m_count < 5) { + xdiv = m_count-1; + ydiv = 0; + } + else if(m_count < 10) { + xdiv = 0; + ydiv = 1; + } + else if(m_count < 25) { + xdiv = 1; + ydiv = 1; + } + else if(m_count < 50) { + xdiv = 2; + ydiv = 1; + } + else if(m_count <= 100) { + xdiv = 3; + ydiv = 1; + } } else if(!attributes.moveable) { xdiv = m_position.x % attributes.xdiv; @@ -26,7 +62,7 @@ void Item::draw(int x, int y) } for(int b = 0; b < attributes.blendframes; b++) - internalDraw(x, y, b, xdiv, ydiv, zdiv, anim); + internalDraw(x, y, b, xdiv, ydiv, zdiv, m_animation); } const ThingAttributes& Item::getAttributes() diff --git a/src/otclient/core/item.h b/src/otclient/core/item.h index d11ebc68..4541cdea 100644 --- a/src/otclient/core/item.h +++ b/src/otclient/core/item.h @@ -20,6 +20,8 @@ public: private: int m_count; + int m_lastTicks; + int m_animation; }; #endif diff --git a/src/otclient/core/map.cpp b/src/otclient/core/map.cpp index e709e0d4..630c565b 100644 --- a/src/otclient/core/map.cpp +++ b/src/otclient/core/map.cpp @@ -40,7 +40,7 @@ void Map::draw(const Rect& rect) for(int jz = 6; jz >= 0; --jz) { Position coverPos = Position(playerPos.x+(7-jz)-1, playerPos.y+(7-jz)-1, jz); if(const TilePtr& tile = m_tiles[coverPos]) { - if(tile->getStackSize() > 0 && jz < playerPos.z) { + if(tile->getStackSize(3) > 0 && jz < playerPos.z) { drawFloorStop = jz; break; } @@ -99,7 +99,7 @@ void Map::draw(const Rect& rect) } } -void Map::addThing(ThingPtr thing, uint8 stackpos) +void Map::addThing(ThingPtr thing, int stackpos) { if(!thing) return; @@ -115,7 +115,7 @@ void Map::addThing(ThingPtr thing, uint8 stackpos) m_creatures[thing->getId()] = creature; } -ThingPtr Map::getThing(const Position& pos, uint8 stackpos) +ThingPtr Map::getThing(const Position& pos, int stackpos) { if(const TilePtr& tile = m_tiles[pos]) { return tile->getThing(stackpos); @@ -123,7 +123,7 @@ ThingPtr Map::getThing(const Position& pos, uint8 stackpos) return ThingPtr(); } -void Map::removeThing(const Position& pos, uint8 stackpos) +void Map::removeThing(const Position& pos, int stackpos) { if(TilePtr& tile = m_tiles[pos]) { tile->removeThing(stackpos); diff --git a/src/otclient/core/map.h b/src/otclient/core/map.h index 8009618c..0cbeddbb 100644 --- a/src/otclient/core/map.h +++ b/src/otclient/core/map.h @@ -10,9 +10,9 @@ class Map public: void draw(const Rect& rect); - void addThing(ThingPtr thing, uint8 stackpos = 0); - ThingPtr getThing(const Position& pos, uint8 stackpos); - void removeThing(const Position& pos, uint8 stackpos); + void addThing(ThingPtr thing, int stackpos = -1); + ThingPtr getThing(const Position& pos, int stackpos); + void removeThing(const Position& pos, int stackpos); void removeThingByPtr(ThingPtr thing); void clean(); diff --git a/src/otclient/core/tile.cpp b/src/otclient/core/tile.cpp index 843c8dd7..9b843c01 100644 --- a/src/otclient/core/tile.cpp +++ b/src/otclient/core/tile.cpp @@ -72,16 +72,19 @@ void Tile::draw(int x, int y) } } -void Tile::addThing(ThingPtr thing, uint8 stackpos) +void Tile::addThing(ThingPtr thing, int stackpos) { + // TODO: rework this. that -1 sucks if(!thing) return; - if(thing->getPosition() == g_game.getLocalPlayer()->getPosition() + Position(-1, 0, 0) && thing->getAttributes().alwaysOnTop) { + const ThingAttributes& thingAttributes = thing->getAttributes(); + + if(thing->getPosition() == g_game.getLocalPlayer()->getPosition() + Position(-1, 0, 0) && thingAttributes.group == THING_GROUP_GROUND) { logDebug((int)thing->getId()); } - const ThingAttributes& thingAttributes = thing->getAttributes(); + if(thing->asItem()) { if(thingAttributes.group == THING_GROUP_GROUND) @@ -89,8 +92,13 @@ void Tile::addThing(ThingPtr thing, uint8 stackpos) else { if(thingAttributes.alwaysOnTop) m_itemsTop.push_back(thing); - else - m_itemsBottom.push_back(thing); + else { + if(stackpos == -1) + m_itemsBottom.push_back(thing); + else { + m_itemsBottom.insert(m_itemsBottom.begin()+(stackpos-getStackSize(2)), thing); + } + } } } else if(thing->asCreature()) { @@ -101,7 +109,7 @@ void Tile::addThing(ThingPtr thing, uint8 stackpos) } } -ThingPtr Tile::getThing(uint8 stackpos) +ThingPtr Tile::getThing(unsigned int stackpos) { if(stackpos == 0) return m_ground; @@ -121,7 +129,7 @@ ThingPtr Tile::getThing(uint8 stackpos) return ThingPtr(); } -void Tile::removeThing(uint8 stackpos) +void Tile::removeThing(unsigned int stackpos) { if(stackpos == 0) { m_ground.reset(); @@ -205,13 +213,20 @@ void Tile::clean() m_effects.clear(); } -int Tile::getStackSize() +int Tile::getStackSize(int stop) { - int ret = 0; - if(m_ground) - ret++; - ret += m_itemsBottom.size(); - ret += m_creatures.size(); + int ret = m_ground ? 1 : 0; + if(stop == 0) + return ret; + ret += m_itemsTop.size(); + if(stop == 1) + return ret; + + ret += m_creatures.size(); + if(stop == 2) + return ret; + + ret += m_itemsBottom.size(); return ret; } diff --git a/src/otclient/core/tile.h b/src/otclient/core/tile.h index 7c196585..c81cb235 100644 --- a/src/otclient/core/tile.h +++ b/src/otclient/core/tile.h @@ -11,16 +11,16 @@ public: void draw(int x, int y); - void addThing(ThingPtr thing, uint8 stackpos); - ThingPtr getThing(uint8 stackpos); - void removeThing(uint8 stackpos); + void addThing(ThingPtr thing, int stackpos); + ThingPtr getThing(unsigned int stackpos); + void removeThing(unsigned int stackpos); void removeThingByPtr(ThingPtr thing); void clean(); bool hasGround() { return (!!m_ground); } - int getStackSize(); + int getStackSize(int stop); std::deque getCreatures() { return m_creatures; } int getDrawNextOffset() { return m_drawNextOffset; } diff --git a/src/otclient/net/protocolgameparse.cpp b/src/otclient/net/protocolgameparse.cpp index 2695260f..633611d5 100644 --- a/src/otclient/net/protocolgameparse.cpp +++ b/src/otclient/net/protocolgameparse.cpp @@ -382,21 +382,9 @@ void ProtocolGame::parseCreatureMove(InputMessage& msg) ThingPtr thing = g_map.getThing(oldPos, oldStackpos); if(thing) { - g_map.removeThing(oldPos, oldStackpos); - thing->setPosition(newPos); - g_map.addThing(thing); - } - - CreaturePtr creature = thing->asCreature(); - if(creature) { - if(oldPos + Position(0, -1, 0) == newPos) - creature->setDirection(DIRECTION_NORTH); - else if(oldPos + Position(1, 0, 0) == newPos) - creature->setDirection(DIRECTION_EAST); - else if(oldPos + Position(0, 1, 0) == newPos) - creature->setDirection(DIRECTION_SOUTH); - else if(oldPos + Position(-1, 0, 0) == newPos) - creature->setDirection(DIRECTION_WEST); + CreaturePtr creature = thing->asCreature(); + if(creature) + creature->walk(newPos); } } @@ -923,7 +911,7 @@ void ProtocolGame::setTileDescription(InputMessage& msg, Position position) ThingPtr thing = internalGetThing(msg); if(thing) thing->setPosition(position); - g_map.addThing(thing, stackpos); + g_map.addThing(thing); } stackpos++; }