diff --git a/src/otclient/core/creature.cpp b/src/otclient/core/creature.cpp index 95f9abb3..9ac0ef6b 100644 --- a/src/otclient/core/creature.cpp +++ b/src/otclient/core/creature.cpp @@ -27,6 +27,7 @@ #include "tile.h" #include "item.h" #include "game.h" +#include "effect.h" #include #include @@ -84,46 +85,54 @@ void Creature::draw(const Point& p, const Rect&) } // Render creature - for(m_yPattern = 0; m_yPattern < m_type->dimensions[ThingType::PatternY]; m_yPattern++) { - - // continue if we dont have this addon. - if(m_yPattern > 0 && !(m_outfit.getAddons() & (1 << (m_yPattern-1)))) - continue; - - g_painter.setCustomProgram(outfitProgram); - - outfitProgram->bind(); - outfitProgram->setUniformValue(HEAD_COLOR_UNIFORM, m_outfit.getHeadColor()); - outfitProgram->setUniformValue(BODY_COLOR_UNIFORM, m_outfit.getBodyColor()); - outfitProgram->setUniformValue(LEGS_COLOR_UNIFORM, m_outfit.getLegsColor()); - outfitProgram->setUniformValue(FEET_COLOR_UNIFORM, m_outfit.getFeetColor()); - - for(int h = 0; h < m_type->dimensions[ThingType::Height]; h++) { - for(int w = 0; w < m_type->dimensions[ThingType::Width]; w++) { - int spriteId = m_type->getSpriteId(w, h, 0, m_xPattern, m_yPattern, m_zPattern, m_animation); - if(!spriteId) - continue; - TexturePtr spriteTex = g_sprites.getSpriteTexture(spriteId); - if(!spriteTex) - continue; - - if(m_type->dimensions[ThingType::Layers] > 1) { - int maskId = m_type->getSpriteId(w, h, 1, m_xPattern, m_yPattern, m_zPattern, m_animation); - if(!maskId) + if(m_outfit.getCategory() == ThingsType::Creature) { + for(m_yPattern = 0; m_yPattern < m_type->dimensions[ThingType::PatternY]; m_yPattern++) { + + // continue if we dont have this addon. + if(m_yPattern > 0 && !(m_outfit.getAddons() & (1 << (m_yPattern-1)))) + continue; + + g_painter.setCustomProgram(outfitProgram); + + outfitProgram->bind(); + outfitProgram->setUniformValue(HEAD_COLOR_UNIFORM, m_outfit.getHeadColor()); + outfitProgram->setUniformValue(BODY_COLOR_UNIFORM, m_outfit.getBodyColor()); + outfitProgram->setUniformValue(LEGS_COLOR_UNIFORM, m_outfit.getLegsColor()); + outfitProgram->setUniformValue(FEET_COLOR_UNIFORM, m_outfit.getFeetColor()); + + for(int h = 0; h < m_type->dimensions[ThingType::Height]; h++) { + for(int w = 0; w < m_type->dimensions[ThingType::Width]; w++) { + int spriteId = m_type->getSpriteId(w, h, 0, m_xPattern, m_yPattern, m_zPattern, m_animation); + if(!spriteId) + continue; + TexturePtr spriteTex = g_sprites.getSpriteTexture(spriteId); + if(!spriteTex) continue; - TexturePtr maskTex = g_sprites.getSpriteTexture(maskId); - outfitProgram->setUniformTexture(MASK_TEXTURE_UNIFORM, maskTex, 1); - } - Rect drawRect(((p + m_walkOffset).x - w*32) - m_type->parameters[ThingType::DisplacementX], - ((p + m_walkOffset).y - h*32) - m_type->parameters[ThingType::DisplacementY], - 32, 32); - g_painter.drawTexturedRect(drawRect, spriteTex); + if(m_type->dimensions[ThingType::Layers] > 1) { + int maskId = m_type->getSpriteId(w, h, 1, m_xPattern, m_yPattern, m_zPattern, m_animation); + if(!maskId) + continue; + TexturePtr maskTex = g_sprites.getSpriteTexture(maskId); + outfitProgram->setUniformTexture(MASK_TEXTURE_UNIFORM, maskTex, 1); + } + + Rect drawRect(((p + m_walkOffset).x - w*32) - m_type->parameters[ThingType::DisplacementX], + ((p + m_walkOffset).y - h*32) - m_type->parameters[ThingType::DisplacementY], + 32, 32); + g_painter.drawTexturedRect(drawRect, spriteTex); + } } - } - g_painter.releaseCustomProgram(); + g_painter.releaseCustomProgram(); + } + } + else if(m_outfit.getCategory() == ThingsType::Item) { + for(int l = 0; l < m_type->dimensions[ThingType::Layers]; l++) + internalDraw(p + m_walkOffset, l); } + else if(m_outfit.getCategory() == ThingsType::Effect) + internalDraw(p + m_walkOffset, 0); } void Creature::drawInformation(int x, int y, bool useGray, const Rect& visibleRect) @@ -260,10 +269,12 @@ void Creature::updateWalk() m_walkOffset.x = -totalPixelsWalked; } - if(totalPixelsWalked == 32 || m_type->dimensions[ThingType::AnimationPhases] <= 1) - m_animation = 0; - else if(m_type->dimensions[ThingType::AnimationPhases] > 1) - m_animation = 1 + totalPixelsWalked * 4 / Map::NUM_TILE_PIXELS % (m_type->dimensions[ThingType::AnimationPhases] - 1); + if(m_outfit.getCategory() == ThingsType::Creature) { + if(totalPixelsWalked == 32 || m_type->dimensions[ThingType::AnimationPhases] <= 1) + m_animation = 0; + else if(m_type->dimensions[ThingType::AnimationPhases] > 1) + m_animation = 1 + totalPixelsWalked * 4 / Map::NUM_TILE_PIXELS % (m_type->dimensions[ThingType::AnimationPhases] - 1); + } if(g_clock.ticks() > m_walkEnd) cancelWalk(m_turnDirection); @@ -275,7 +286,8 @@ void Creature::cancelWalk(Otc::Direction direction, bool) { m_walking = false; m_walkStart = 0; - m_animation = 0; + if(m_outfit.getCategory() == ThingsType::Creature) + m_animation = 0; m_walkOffset = Point(0, 0); setDirection(direction); } @@ -320,23 +332,44 @@ void Creature::setHealthPercent(uint8 healthPercent) void Creature::setDirection(Otc::Direction direction) { - if(direction == Otc::NorthEast || direction == Otc::SouthEast) - m_xPattern = Otc::East; - else if(direction == Otc::NorthWest || direction == Otc::SouthWest) - m_xPattern = Otc::West; - else - m_xPattern = direction; + if(m_outfit.getCategory() == ThingsType::Creature) { + if(direction == Otc::NorthEast || direction == Otc::SouthEast) + m_xPattern = Otc::East; + else if(direction == Otc::NorthWest || direction == Otc::SouthWest) + m_xPattern = Otc::West; + else + m_xPattern = direction; + } + else { + m_xPattern = 0; + } m_direction = direction; } void Creature::setOutfit(const Outfit& outfit) { + if(m_outfit.getCategory() != ThingsType::Effect && outfit.getCategory() == ThingsType::Effect) { + auto self = asCreature(); + g_dispatcher.scheduleEvent([self]() { + self->updateAnimation(); + }, INVISIBLE_TICKS); + + m_xPattern = 0; + m_yPattern = 0; + } + if(m_outfit.getCategory() == ThingsType::Item) { + m_xPattern = 0; + m_yPattern = 0; + } + m_outfit = outfit; m_type = getType(); - if(m_type->dimensions[ThingType::Layers] == 1) + if(m_outfit.getCategory() == ThingsType::Creature && m_type->dimensions[ThingType::Layers] == 1) { + m_animation = 0; m_outfit.resetClothes(); + } } void Creature::setSkull(uint8 skull) @@ -354,7 +387,6 @@ void Creature::setShield(uint8 shield) void Creature::setEmblem(uint8 emblem) { m_emblem = emblem; - g_lua.callGlobalField("Creature","onEmblemChange", asCreature(), m_emblem); } @@ -385,7 +417,26 @@ void Creature::addVolatileSquare(uint8 color) }, VOLATILE_SQUARE_DURATION); } +void Creature::updateAnimation() +{ + if(m_animation == 1) + m_animation = 2; + else if(m_animation == 2) + m_animation = 3; + else if(m_animation == 3) + m_animation = 1; + else + m_animation = 1; + + if(g_game.isOnline() && m_outfit.getCategory() == ThingsType::Effect) { + auto self = asCreature(); + g_dispatcher.scheduleEvent([self]() { + self->updateAnimation(); + }, INVISIBLE_TICKS); + } +} + ThingType *Creature::getType() { - return g_thingsType.getThingType(m_outfit.getType(), ThingsType::Creature); + return g_thingsType.getThingType(m_outfit.getId(), m_outfit.getCategory()); } diff --git a/src/otclient/core/creature.h b/src/otclient/core/creature.h index ff0ebcfa..a8121e6c 100644 --- a/src/otclient/core/creature.h +++ b/src/otclient/core/creature.h @@ -31,6 +31,7 @@ class Creature : public Thing { public: enum { + INVISIBLE_TICKS = 500, VOLATILE_SQUARE_DURATION = 1000 }; @@ -70,6 +71,9 @@ public: uint8 getShield() { return m_shield; } uint8 getEmblem() { return m_emblem; } bool getPassable() { return m_passable; } + + void updateAnimation(); + ThingType *getType(); //virtual void walk(const Position& oldPos, const Position& newPos, bool inverse = true); diff --git a/src/otclient/core/effect.h b/src/otclient/core/effect.h index 8564c1ba..d305f55d 100644 --- a/src/otclient/core/effect.h +++ b/src/otclient/core/effect.h @@ -28,11 +28,11 @@ class Effect : public Thing { +public: enum { TICKS_PER_FRAME = 75 }; -public: Effect(); void draw(const Point& p, const Rect&); diff --git a/src/otclient/core/item.cpp b/src/otclient/core/item.cpp index 3c929717..c5744f86 100644 --- a/src/otclient/core/item.cpp +++ b/src/otclient/core/item.cpp @@ -44,8 +44,8 @@ void Item::draw(const Point& p, const Rect&) if(m_type->dimensions[ThingType::AnimationPhases] > 1) m_animation = (g_clock.ticks() % (TICKS_PER_FRAME * m_type->dimensions[ThingType::AnimationPhases])) / TICKS_PER_FRAME; - for(int b = 0; b < m_type->dimensions[ThingType::Layers]; b++) - internalDraw(p, b); + for(int l = 0; l < m_type->dimensions[ThingType::Layers]; l++) + internalDraw(p, l); } void Item::setPos(const Position& position) diff --git a/src/otclient/core/outfit.cpp b/src/otclient/core/outfit.cpp index fe4f6978..517ce78d 100644 --- a/src/otclient/core/outfit.cpp +++ b/src/otclient/core/outfit.cpp @@ -24,7 +24,8 @@ Outfit::Outfit() { - m_type = 128; + m_category = ThingsType::Creature; + m_id = 1; resetClothes(); } diff --git a/src/otclient/core/outfit.h b/src/otclient/core/outfit.h index 63edb687..5f425c6b 100644 --- a/src/otclient/core/outfit.h +++ b/src/otclient/core/outfit.h @@ -24,6 +24,7 @@ #define OUTFIT_H #include +#include class Outfit { @@ -37,21 +38,23 @@ public: static Color getColor(int color); - void setType(int type) { m_type = type; } + void setId(int id) { m_id = id; } void setHead(int head) { m_head = head; m_headColor = getColor(head); } void setBody(int body) { m_body = body; m_bodyColor = getColor(body); } void setLegs(int legs) { m_legs = legs; m_legsColor = getColor(legs); } void setFeet(int feet) { m_feet = feet; m_feetColor = getColor(feet); } void setAddons(int addons) { m_addons = addons; } + void setCategory(ThingsType::Categories category) { m_category = category; } void resetClothes(); - int getType() const { return m_type; } + int getId() const { return m_id; } int getHead() const { return m_head; } int getBody() const { return m_body; } int getLegs() const { return m_legs; } int getFeet() const { return m_feet; } int getAddons() const { return m_addons; } + ThingsType::Categories getCategory() const { return m_category; } Color getHeadColor() { return m_headColor; } Color getBodyColor() { return m_bodyColor; } @@ -59,7 +62,8 @@ public: Color getFeetColor() { return m_feetColor; } private: - int m_type, m_head, m_body, m_legs, m_feet, m_addons; + ThingsType::Categories m_category; + int m_id, m_head, m_body, m_legs, m_feet, m_addons; Color m_headColor, m_bodyColor, m_legsColor, m_feetColor; }; diff --git a/src/otclient/luascript/luavaluecasts.cpp b/src/otclient/luascript/luavaluecasts.cpp index 2db519f4..54f99ac0 100644 --- a/src/otclient/luascript/luavaluecasts.cpp +++ b/src/otclient/luascript/luavaluecasts.cpp @@ -26,7 +26,7 @@ void push_luavalue(const Outfit& outfit) { g_lua.newTable(); - g_lua.pushInteger(outfit.getType()); + g_lua.pushInteger(outfit.getId()); g_lua.setField("type"); g_lua.pushInteger(outfit.getAddons()); g_lua.setField("addons"); @@ -44,7 +44,7 @@ bool luavalue_cast(int index, Outfit& outfit) { if(g_lua.isTable(index)) { g_lua.getField("type", index); - outfit.setType(g_lua.popInteger()); + outfit.setId(g_lua.popInteger()); g_lua.getField("addons", index); outfit.setAddons(g_lua.popInteger()); g_lua.getField("head", index); diff --git a/src/otclient/net/protocolgameparse.cpp b/src/otclient/net/protocolgameparse.cpp index 13ebb0d0..e377741a 100644 --- a/src/otclient/net/protocolgameparse.cpp +++ b/src/otclient/net/protocolgameparse.cpp @@ -996,15 +996,16 @@ Outfit ProtocolGame::internalGetOutfit(InputMessage& msg) { Outfit outfit; - uint16 type = msg.getU16(); - if(type != 0) { + uint16 id = msg.getU16(); + if(id != 0) { + outfit.setCategory(ThingsType::Creature); uint8 head = msg.getU8(); uint8 body = msg.getU8(); uint8 legs = msg.getU8(); uint8 feet = msg.getU8(); uint8 addons = msg.getU8(); - outfit.setType(type); + outfit.setId(id); outfit.setHead(head); outfit.setBody(body); outfit.setLegs(legs); @@ -1012,8 +1013,15 @@ Outfit ProtocolGame::internalGetOutfit(InputMessage& msg) outfit.setAddons(addons); } else { - uint16 type = msg.getU16(); - outfit.setType(type); + uint16 id = msg.getU16(); + if(id == 0) { + outfit.setCategory(ThingsType::Effect); + outfit.setId(13); + } + else { + outfit.setCategory(ThingsType::Item); + outfit.setId(id); + } } return outfit; diff --git a/src/otclient/net/protocolgamesend.cpp b/src/otclient/net/protocolgamesend.cpp index e75f5ba1..b5de456e 100644 --- a/src/otclient/net/protocolgamesend.cpp +++ b/src/otclient/net/protocolgamesend.cpp @@ -537,7 +537,7 @@ void ProtocolGame::sendSetOutfit(const Outfit& outfit) OutputMessage oMsg; oMsg.addU8(Proto::ClientSetOutfit); - oMsg.addU16(outfit.getType()); + oMsg.addU16(outfit.getId()); oMsg.addU8(outfit.getHead()); oMsg.addU8(outfit.getBody()); oMsg.addU8(outfit.getLegs());