rename item count to countOrSubType, rework and improve things animation/drawing

This commit is contained in:
Eduardo Bart 2012-02-02 14:37:52 -02:00
parent edeee80631
commit ef96215421
24 changed files with 315 additions and 337 deletions

View File

@ -30,14 +30,14 @@ function UIItem:onDrop(widget, mousePos)
if not widget or not widget.currentDragThing then return true end if not widget or not widget.currentDragThing then return true end
local pos = self.position local pos = self.position
local data = widget.currentDragThing:getCount() local count = widget.currentDragThing:getCount()
if widget.currentDragThing:isStackable() and data > 1 then if widget.currentDragThing:isStackable() and count > 1 then
widget.parsed = true widget.parsed = true
local moveWindow = displayUI('/game/movewindow.otui') local moveWindow = displayUI('/game/movewindow.otui')
local spinbox = moveWindow:getChildById('spinbox') local spinbox = moveWindow:getChildById('spinbox')
spinbox:setMaximum(data) spinbox:setMaximum(count)
spinbox:setMinimum(1) spinbox:setMinimum(1)
spinbox:setCurrentIndex(data) spinbox:setCurrentIndex(count)
local okButton = moveWindow:getChildById('buttonOk') local okButton = moveWindow:getChildById('buttonOk')
okButton.onClick = function() Game.move(widget.currentDragThing, pos, spinbox:getCurrentIndex()) okButton:getParent():destroy() widget.currentDragThing = nil end okButton.onClick = function() Game.move(widget.currentDragThing, pos, spinbox:getCurrentIndex()) okButton:getParent():destroy() widget.currentDragThing = nil end

View File

@ -26,14 +26,14 @@ function UIMap:onDrop(widget, mousePos)
local tile = self:getTile(mousePos) local tile = self:getTile(mousePos)
if not tile then return false end if not tile then return false end
local data = widget.currentDragThing:getCount() local count = widget.currentDragThing:getCount()
if widget.currentDragThing:isStackable() and data > 1 then if widget.currentDragThing:isStackable() and data > 1 then
widget.parsed = true widget.parsed = true
local moveWindow = displayUI('/game/movewindow.otui') local moveWindow = displayUI('/game/movewindow.otui')
local spinbox = moveWindow:getChildById('spinbox') local spinbox = moveWindow:getChildById('spinbox')
spinbox:setMaximum(data) spinbox:setMaximum(count)
spinbox:setMinimum(1) spinbox:setMinimum(1)
spinbox:setCurrentIndex(data) spinbox:setCurrentIndex(count)
local okButton = moveWindow:getChildById('buttonOk') local okButton = moveWindow:getChildById('buttonOk')
okButton.onClick = function() Game.move(widget.currentDragThing, tile:getPosition(), spinbox:getCurrentIndex()) okButton:getParent():destroy() widget.currentDragThing = nil end okButton.onClick = function() Game.move(widget.currentDragThing, tile:getPosition(), spinbox:getCurrentIndex()) okButton:getParent():destroy() widget.currentDragThing = nil end

View File

@ -6,6 +6,5 @@ varying vec2 textureCoords; // map texture coords
void main() void main()
{ {
vec4 outColor = texture2D(texture, textureCoords) * opacity; gl_FragColor = texture2D(texture, textureCoords) * opacity;
gl_FragColor = outColor;
} }

View File

@ -49,6 +49,7 @@ namespace Otc
AWARE_Y_BOTTOM_TILES = AWARE_Y_TILES/2, AWARE_Y_BOTTOM_TILES = AWARE_Y_TILES/2,
EFFECT_TICKS_PER_FRAME = 75, EFFECT_TICKS_PER_FRAME = 75,
INVISIBLE_TICKS_PER_FRAME = 500,
ITEM_TICKS_PER_FRAME = 500, ITEM_TICKS_PER_FRAME = 500,
ANIMATED_TEXT_DURATION = 1000, ANIMATED_TEXT_DURATION = 1000,
STATIC_DURATION_PER_CHARACTER = 75, STATIC_DURATION_PER_CHARACTER = 75,
@ -66,9 +67,11 @@ namespace Otc
DrawCreaturesInformation = 64, DrawCreaturesInformation = 64,
DrawStaticTexts = 128, DrawStaticTexts = 128,
DrawAnimatedTexts = 256, DrawAnimatedTexts = 256,
DrawEverything = DrawGround | DrawWalls | DrawCommonItems | DrawAnimations = 512,
DrawGroundBorders = 1024,
DrawEverything = DrawGround | DrawGroundBorders | DrawWalls | DrawCommonItems |
DrawCreatures | DrawEffects | DrawMissiles | DrawCreatures | DrawEffects | DrawMissiles |
DrawCreaturesInformation | DrawStaticTexts | DrawAnimatedTexts DrawCreaturesInformation | DrawStaticTexts | DrawAnimatedTexts | DrawAnimations
}; };
enum DatOpts { enum DatOpts {

View File

@ -44,6 +44,7 @@ Creature::Creature() : Thing()
m_showVolatileSquare = false; m_showVolatileSquare = false;
m_showStaticSquare = false; m_showStaticSquare = false;
m_direction = Otc::South; m_direction = Otc::South;
m_walkAnimationPhase = 0;
m_walking = false; m_walking = false;
m_walkInterval = 0; m_walkInterval = 0;
m_walkAnimationInterval = 0; m_walkAnimationInterval = 0;
@ -63,18 +64,20 @@ int LEGS_COLOR_UNIFORM = 12;
int FEET_COLOR_UNIFORM = 13; int FEET_COLOR_UNIFORM = 13;
int MASK_TEXTURE_UNIFORM = 14; int MASK_TEXTURE_UNIFORM = 14;
void Creature::draw(const Point& dest, float scaleFactor) void Creature::draw(const Point& dest, float scaleFactor, bool animate)
{ {
int scaledTileSize = Otc::TILE_PIXELS * scaleFactor; int scaledTileSize = Otc::TILE_PIXELS * scaleFactor;
if(m_showVolatileSquare) { Point animationOffset = animate ? m_walkOffset : Point(0,0);
if(m_showVolatileSquare && animate) {
g_painter.setColor(m_volatileSquareColor); g_painter.setColor(m_volatileSquareColor);
g_painter.drawBoundingRect(Rect(dest + (m_walkOffset - getDisplacement() + 3)*scaleFactor, Size(28*scaleFactor, 28*scaleFactor)), std::max((int)(2*scaleFactor), 1)); g_painter.drawBoundingRect(Rect(dest + (animationOffset - getDisplacement() + 3)*scaleFactor, Size(28*scaleFactor, 28*scaleFactor)), std::max((int)(2*scaleFactor), 1));
} }
if(m_showStaticSquare) { if(m_showStaticSquare && animate) {
g_painter.setColor(m_staticSquareColor); g_painter.setColor(m_staticSquareColor);
g_painter.drawBoundingRect(Rect(dest + (m_walkOffset - getDisplacement() + 1)*scaleFactor, Size(scaledTileSize, scaledTileSize)), std::max((int)(2*scaleFactor), 1)); g_painter.drawBoundingRect(Rect(dest + (animationOffset - getDisplacement() + 1)*scaleFactor, Size(scaledTileSize, scaledTileSize)), std::max((int)(2*scaleFactor), 1));
} }
g_painter.setColor(Fw::white); g_painter.setColor(Fw::white);
@ -90,12 +93,25 @@ void Creature::draw(const Point& dest, float scaleFactor)
outfitProgram->bindUniformLocation(MASK_TEXTURE_UNIFORM, "maskTexture"); outfitProgram->bindUniformLocation(MASK_TEXTURE_UNIFORM, "maskTexture");
} }
// Render creature int xPattern = 0, yPattern = 0, zPattern = 0;
// outfit is a real creature
if(m_outfit.getCategory() == ThingsType::Creature) { if(m_outfit.getCategory() == ThingsType::Creature) {
for(m_yPattern = 0; m_yPattern < getNumPatternsY(); m_yPattern++) { int animationPhase = animate ? m_walkAnimationPhase : 0;
// xPattern => creature direction
if(m_direction == Otc::NorthEast || m_direction == Otc::SouthEast)
xPattern = Otc::East;
else if(m_direction == Otc::NorthWest || m_direction == Otc::SouthWest)
xPattern = Otc::West;
else
xPattern = m_direction;
// yPattern => creature addon
for(yPattern = 0; yPattern < getNumPatternsY(); yPattern++) {
// continue if we dont have this addon. // continue if we dont have this addon.
if(m_yPattern > 0 && !(m_outfit.getAddons() & (1 << (m_yPattern-1)))) if(yPattern > 0 && !(m_outfit.getAddons() & (1 << (yPattern-1))))
continue; continue;
g_painter.setCustomProgram(outfitProgram); g_painter.setCustomProgram(outfitProgram);
@ -108,22 +124,23 @@ void Creature::draw(const Point& dest, float scaleFactor)
for(int h = 0; h < getDimensionHeight(); h++) { for(int h = 0; h < getDimensionHeight(); h++) {
for(int w = 0; w < getDimensionWidth(); w++) { for(int w = 0; w < getDimensionWidth(); w++) {
int spriteId = getSpriteId(w, h, 0, m_xPattern, m_yPattern, m_zPattern, m_animation); int spriteId = getSpriteId(w, h, 0, xPattern, yPattern, zPattern, m_walkAnimationPhase);
if(!spriteId) if(!spriteId)
continue; continue;
TexturePtr spriteTex = g_sprites.getSpriteTexture(spriteId); TexturePtr spriteTex = g_sprites.getSpriteTexture(spriteId);
if(!spriteTex) if(!spriteTex)
continue; continue;
// setup texture outfit mask
TexturePtr maskTex; TexturePtr maskTex;
if(getLayers() > 1) { if(getLayers() > 1) {
int maskId = getSpriteId(w, h, 1, m_xPattern, m_yPattern, m_zPattern, m_animation); int maskId = getSpriteId(w, h, 1, xPattern, yPattern, zPattern, m_walkAnimationPhase);
maskTex = g_sprites.getSpriteTexture(maskId); maskTex = g_sprites.getSpriteTexture(maskId);
} }
outfitProgram->setUniformTexture(MASK_TEXTURE_UNIFORM, maskTex, 1); outfitProgram->setUniformTexture(MASK_TEXTURE_UNIFORM, maskTex, 1);
Rect drawRect(dest.x + (m_walkOffset.x - w*Otc::TILE_PIXELS - getDisplacementX())*scaleFactor, Rect drawRect(dest.x + (animationOffset.x - w*Otc::TILE_PIXELS - getDisplacementX())*scaleFactor,
dest.y + (m_walkOffset.y - h*Otc::TILE_PIXELS - getDisplacementY())*scaleFactor, dest.y + (animationOffset.y - h*Otc::TILE_PIXELS - getDisplacementY())*scaleFactor,
scaledTileSize, scaledTileSize); scaledTileSize, scaledTileSize);
g_painter.drawTexturedRect(drawRect, spriteTex); g_painter.drawTexturedRect(drawRect, spriteTex);
} }
@ -131,13 +148,32 @@ void Creature::draw(const Point& dest, float scaleFactor)
g_painter.releaseCustomProgram(); g_painter.releaseCustomProgram();
} }
// outfit is a creature imitating an item or the invisible effect
} else {
int animationPhase = 0;
int animationPhases = 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() == ThingsType::Effect) {
animationPhases = std::max(1, animationPhases-2);
animateTicks = Otc::INVISIBLE_TICKS_PER_FRAME;
} }
else if(m_outfit.getCategory() == ThingsType::Item) {
for(int l = 0; l < getLayers(); l++) if(animationPhases > 1) {
internalDraw(dest + m_walkOffset, scaleFactor, l); if(animate)
animationPhase = (g_clock.ticks() % (animateTicks * animationPhases)) / animateTicks;
else
animationPhase = animationPhases-1;
}
if(m_outfit.getCategory() == ThingsType::Effect)
animationPhase = std::min(animationPhase+1, getAnimationPhases());
for(int layer = 0; layer < getLayers(); layer++)
internalDraw(dest + animationOffset*scaleFactor, scaleFactor, 0, 0, 0, layer, animationPhase);
} }
else if(m_outfit.getCategory() == ThingsType::Effect)
internalDraw(dest + m_walkOffset, scaleFactor, 0);
} }
void Creature::drawInformation(const Point& point, bool useGray, const Rect& parentRect) void Creature::drawInformation(const Point& point, bool useGray, const Rect& parentRect)
@ -244,7 +280,7 @@ void Creature::stopWalk()
// reset walk animation states // reset walk animation states
m_walkOffset = Point(0,0); m_walkOffset = Point(0,0);
m_animation = 0; m_walkAnimationPhase = 0;
// stops the walk right away // stops the walk right away
terminateWalk(); terminateWalk();
@ -257,9 +293,9 @@ void Creature::updateWalkAnimation(int totalPixelsWalked)
return; return;
if(totalPixelsWalked == 32 || totalPixelsWalked == 0 || getAnimationPhases() <= 1) if(totalPixelsWalked == 32 || totalPixelsWalked == 0 || getAnimationPhases() <= 1)
m_animation = 0; m_walkAnimationPhase = 0;
else if(getAnimationPhases() > 1) else if(getAnimationPhases() > 1)
m_animation = 1 + ((totalPixelsWalked * 4) / Otc::TILE_PIXELS) % (getAnimationPhases() - 1); m_walkAnimationPhase = 1 + ((totalPixelsWalked * 4) / Otc::TILE_PIXELS) % (getAnimationPhases() - 1);
} }
void Creature::updateWalkOffset(int totalPixelsWalked) void Creature::updateWalkOffset(int totalPixelsWalked)
@ -402,40 +438,13 @@ void Creature::setHealthPercent(uint8 healthPercent)
void Creature::setDirection(Otc::Direction direction) void Creature::setDirection(Otc::Direction 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; m_direction = direction;
} }
void Creature::setOutfit(const Outfit& outfit) void Creature::setOutfit(const Outfit& outfit)
{ {
m_outfit = outfit; m_outfit = outfit;
updateType(); m_type = g_thingsType.getThingType(outfit.getId(), outfit.getCategory());
m_animation = 0;
if(m_outfit.getCategory() == ThingsType::Effect) {
updateInvisibleAnimation();
m_xPattern = 0;
m_yPattern = 0;
}
if(m_outfit.getCategory() == ThingsType::Item) {
m_xPattern = 0;
m_yPattern = 0;
}
if(m_outfit.getCategory() == ThingsType::Creature && getLayers() == 1) {
m_outfit.resetClothes();
}
} }
void Creature::setSkull(uint8 skull) void Creature::setSkull(uint8 skull)
@ -493,26 +502,6 @@ void Creature::addVolatileSquare(uint8 color)
}, VOLATILE_SQUARE_DURATION); }, VOLATILE_SQUARE_DURATION);
} }
void Creature::updateInvisibleAnimation()
{
if(!g_game.isOnline() || m_outfit.getCategory() != ThingsType::Effect)
return;
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;
auto self = asCreature();
g_dispatcher.scheduleEvent([self]() {
self->updateInvisibleAnimation();
}, INVISIBLE_TICKS);
}
void Creature::updateShield() void Creature::updateShield()
{ {
m_showShieldTexture = !m_showShieldTexture; m_showShieldTexture = !m_showShieldTexture;

View File

@ -34,16 +34,16 @@ class Creature : public Thing
public: public:
enum { enum {
SHIELD_BLINK_TICKS = 500, SHIELD_BLINK_TICKS = 500,
INVISIBLE_TICKS = 500,
VOLATILE_SQUARE_DURATION = 1000 VOLATILE_SQUARE_DURATION = 1000
}; };
Creature(); Creature();
virtual ~Creature() { } virtual ~Creature() { }
virtual void draw(const Point& dest, float scaleFactor); virtual void draw(const Point& dest, float scaleFactor, bool animate);
void drawInformation(const Point& point, bool useGray, const Rect& parentRect); void drawInformation(const Point& point, bool useGray, const Rect& parentRect);
void setId(uint32 id) { m_id = id; }
void setName(const std::string& name); void setName(const std::string& name);
void setHealthPercent(uint8 healthPercent); void setHealthPercent(uint8 healthPercent);
void setDirection(Otc::Direction direction); void setDirection(Otc::Direction direction);
@ -64,6 +64,7 @@ public:
void showStaticSquare(const Color& color) { m_showStaticSquare = true; m_staticSquareColor = color; } void showStaticSquare(const Color& color) { m_showStaticSquare = true; m_staticSquareColor = color; }
void hideStaticSquare() { m_showStaticSquare = false; } void hideStaticSquare() { m_showStaticSquare = false; }
uint32 getId() { return m_id; }
std::string getName() { return m_name; } std::string getName() { return m_name; }
uint8 getHealthPercent() { return m_healthPercent; } uint8 getHealthPercent() { return m_healthPercent; }
Otc::Direction getDirection() { return m_direction; } Otc::Direction getDirection() { return m_direction; }
@ -96,6 +97,7 @@ protected:
virtual void updateWalk(); virtual void updateWalk();
virtual void terminateWalk(); virtual void terminateWalk();
uint32 m_id;
std::string m_name; std::string m_name;
Size m_nameSize; Size m_nameSize;
uint8 m_healthPercent; uint8 m_healthPercent;
@ -114,6 +116,7 @@ protected:
Color m_informationColor; Color m_informationColor;
// walk related // walk related
int m_walkAnimationPhase;
Timer m_walkTimer; Timer m_walkTimer;
TilePtr m_walkingTile; TilePtr m_walkingTile;
int m_walkInterval; int m_walkInterval;

View File

@ -27,35 +27,27 @@
#include <framework/core/clock.h> #include <framework/core/clock.h>
#include <framework/core/eventdispatcher.h> #include <framework/core/eventdispatcher.h>
void Effect::draw(const Point& dest, float scaleFactor) void Effect::draw(const Point& dest, float scaleFactor, bool animate)
{ {
internalDraw(dest, scaleFactor, 0); if(m_id == 0)
return;
int animationPhase = std::min((int)(m_animationTimer.ticksElapsed() / Otc::EFFECT_TICKS_PER_FRAME), getAnimationPhases() - 1);
for(int layer = 0; layer < getLayers(); layer++)
internalDraw(dest, scaleFactor, 0, 0, 0, layer, animate ? animationPhase : 0);
} }
void Effect::startAnimation() void Effect::startAnimation()
{ {
m_animationTimer.restart(); m_animationTimer.restart();
auto self = asEffect();
// schedule next animation update
if(getAnimationPhases() > 1)
g_dispatcher.scheduleEvent([self]() { self->updateAnimation(); }, Otc::EFFECT_TICKS_PER_FRAME);
// schedule removal // schedule removal
auto self = asEffect();
g_dispatcher.scheduleEvent([self]() { g_map.removeThing(self); }, Otc::EFFECT_TICKS_PER_FRAME * getAnimationPhases()); g_dispatcher.scheduleEvent([self]() { g_map.removeThing(self); }, Otc::EFFECT_TICKS_PER_FRAME * getAnimationPhases());
} }
void Effect::updateAnimation() void Effect::setId(uint32 id)
{ {
int animationPhase = m_animationTimer.ticksElapsed() / Otc::EFFECT_TICKS_PER_FRAME; m_id = id;
m_type = g_thingsType.getThingType(m_id, ThingsType::Effect);
if(animationPhase < getAnimationPhases())
m_animation = animationPhase;
if(animationPhase < getAnimationPhases() - 1) {
//schedule next animation update
auto self = asEffect();
g_dispatcher.scheduleEvent([self]() { self->updateAnimation(); }, Otc::EFFECT_TICKS_PER_FRAME);
}
} }

View File

@ -30,15 +30,17 @@
class Effect : public Thing class Effect : public Thing
{ {
public: public:
void draw(const Point& dest, float scaleFactor); void draw(const Point& dest, float scaleFactor, bool animate);
void setId(uint32 id);
void startAnimation(); void startAnimation();
void updateAnimation();
uint32 getId() { return m_id; }
EffectPtr asEffect() { return std::static_pointer_cast<Effect>(shared_from_this()); } EffectPtr asEffect() { return std::static_pointer_cast<Effect>(shared_from_this()); }
private: private:
Timer m_animationTimer; Timer m_animationTimer;
uint16 m_id;
}; };
#endif #endif

View File

@ -32,7 +32,8 @@
Item::Item() : Thing() Item::Item() : Thing()
{ {
m_count = 1; m_id = 0;
m_countOrSubType = 1;
} }
ItemPtr Item::create(int id) ItemPtr Item::create(int id)
@ -48,72 +49,51 @@ ItemPtr Item::create(int id)
PainterShaderProgramPtr itemProgram; PainterShaderProgramPtr itemProgram;
void Item::draw(const Point& dest, float scaleFactor) void Item::draw(const Point& dest, float scaleFactor, bool animate)
{ {
if(getAnimationPhases() > 1) if(m_id == 0)
m_animation = (g_clock.ticks() % (Otc::ITEM_TICKS_PER_FRAME * getAnimationPhases())) / Otc::ITEM_TICKS_PER_FRAME; return;
if(!itemProgram) { // determine animation phase
itemProgram = PainterShaderProgramPtr(new PainterShaderProgram); int animationPhase = 0;
itemProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); if(getAnimationPhases() > 1) {
itemProgram->addShaderFromSourceFile(Shader::Fragment, "/game_shaders/item.frag"); if(animate)
assert(itemProgram->link()); animationPhase = (g_clock.ticks() % (Otc::ITEM_TICKS_PER_FRAME * getAnimationPhases())) / Otc::ITEM_TICKS_PER_FRAME;
} else
g_painter.setCustomProgram(itemProgram); animationPhase = getAnimationPhases()-1;
for(int layer = 0; layer < getLayers(); layer++)
internalDraw(dest, scaleFactor, layer);
g_painter.releaseCustomProgram();
} }
void Item::setPosition(const Position& position) // determine x,y,z patterns
{ int xPattern = 0, yPattern = 0, zPattern = 0;
if(isGround()) { if(isGround()) {
m_xPattern = position.x % getNumPatternsX(); xPattern = m_position.x % getNumPatternsX();
m_yPattern = position.y % getNumPatternsY(); yPattern = m_position.y % getNumPatternsY();
m_zPattern = position.z % getNumPatternsZ(); zPattern = m_position.z % getNumPatternsZ();
} else if(isStackable() && getNumPatternsX() == 4 && getNumPatternsY() == 2) {
if(m_countOrSubType < 5) {
xPattern = m_countOrSubType-1;
yPattern = 0;
} else if(m_countOrSubType < 10) {
xPattern = 0;
yPattern = 1;
} else if(m_countOrSubType < 25) {
xPattern = 1;
yPattern = 1;
} else if(m_countOrSubType < 50) {
xPattern = 2;
yPattern = 1;
} else if(m_countOrSubType <= 100) {
xPattern = 3;
yPattern = 1;
} }
} else if(isHangable()) {
Thing::setPosition(position); if(isHookSouth())
} xPattern = getNumPatternsX() >= 2 ? 1 : 0;
else if(isHookEast())
void Item::setCount(int count) xPattern = getNumPatternsX() >= 3 ? 2 : 0;
{ } else if(isFluid() || isFluidContainer()) {
count = std::max(std::min(count, 255), 0);
if(isStackable() && getNumPatternsX() == 4 && getNumPatternsY() == 2) {
if(count < 5) {
m_xPattern = count-1;
m_yPattern = 0;
}
else if(count < 10) {
m_xPattern = 0;
m_yPattern = 1;
}
else if(count < 25) {
m_xPattern = 1;
m_yPattern = 1;
}
else if(count < 50) {
m_xPattern = 2;
m_yPattern = 1;
}
else if(count <= 100) {
m_xPattern = 3;
m_yPattern = 1;
}
}
else if(isHangable()) {
if(isHookSouth()) {
m_xPattern = getNumPatternsX() >= 2 ? 1 : 0;
}
else if(isHookEast()) {
m_xPattern = getNumPatternsX() >= 3 ? 2 : 0;
}
}
else if(isFluid() || isFluidContainer()) {
int color = Otc::FluidTransparent; int color = Otc::FluidTransparent;
switch(count) { switch(m_countOrSubType) {
case Otc::FluidNone: case Otc::FluidNone:
color = Otc::FluidTransparent; color = Otc::FluidTransparent;
break; break;
@ -173,9 +153,49 @@ void Item::setCount(int count)
break; break;
} }
m_xPattern = (color % 4) % getNumPatternsX(); xPattern = (color % 4) % getNumPatternsX();
m_yPattern = (color / 4) % getNumPatternsY(); yPattern = (color / 4) % getNumPatternsY();
} }
m_count = count; // setup item drawing shader
if(!itemProgram) {
itemProgram = PainterShaderProgramPtr(new PainterShaderProgram);
itemProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader);
itemProgram->addShaderFromSourceFile(Shader::Fragment, "/game_shaders/item.frag");
assert(itemProgram->link());
}
g_painter.setCustomProgram(itemProgram);
// draw all item layers
for(int layer = 0; layer < getLayers(); layer++)
internalDraw(dest, scaleFactor, xPattern, yPattern, zPattern, layer, animationPhase);
// release draw shader
g_painter.releaseCustomProgram();
}
void Item::setId(uint32 id)
{
if(id < g_thingsType.getFirstItemId() || id > g_thingsType.getMaxItemid()) {
logTraceError("invalid item id ", id);
return;
}
m_id = id;
m_type = g_thingsType.getThingType(m_id, ThingsType::Item);
}
int Item::getCount()
{
if(isStackable())
return m_countOrSubType;
else
return 1;
}
int Item::getSubType()
{
if(isFluid() || isFluidContainer())
return m_countOrSubType;
else
return 0;
} }

View File

@ -33,17 +33,23 @@ public:
static ItemPtr create(int id); static ItemPtr create(int id);
void draw(const Point& dest, float scaleFactor); void draw(const Point& dest, float scaleFactor, bool animate);
void setPosition(const Position &position); void setId(uint32 id);
void setCount(int count); void setCountOrSubType(uint8 value) { m_countOrSubType = value; }
void setCount(int count) { setCountOrSubType(count); }
void setSubType(int subType) { setCountOrSubType(subType); }
int getCount() { return m_count; } uint8 getCountOrSubType() { return m_countOrSubType; }
int getSubType();
int getCount();
uint32 getId() { return m_id; }
ItemPtr asItem() { return std::static_pointer_cast<Item>(shared_from_this()); } ItemPtr asItem() { return std::static_pointer_cast<Item>(shared_from_this()); }
private: private:
uint8 m_count; uint16 m_id;
uint8 m_countOrSubType;
}; };
#endif #endif

View File

@ -69,9 +69,9 @@ void Map::load()
while(id != 0xFFFF) { while(id != 0xFFFF) {
ItemPtr item = Item::create(id); ItemPtr item = Item::create(id);
if(item->isStackable() || item->isFluidContainer() || item->isFluid()) { if(item->isStackable() || item->isFluidContainer() || item->isFluid()) {
uint8 data; uint8 countOrSubType;
in.read((char*)&data, sizeof(data)); in.read((char*)&countOrSubType, sizeof(countOrSubType));
item->setCount(data); item->setCountOrSubType(countOrSubType);
} }
addThing(item, pos, 255); addThing(item, pos, 255);
in.read((char*)&id, sizeof(id)); in.read((char*)&id, sizeof(id));
@ -95,8 +95,8 @@ void Map::save()
id = item->getId(); id = item->getId();
out.write((char*)&id, sizeof(id)); out.write((char*)&id, sizeof(id));
if(item->isStackable() || item->isFluidContainer() || item->isFluid()) { if(item->isStackable() || item->isFluidContainer() || item->isFluid()) {
uint8 data = item->getCount(); uint8 countOrSubType = item->getCountOrSubType();
out.write((char*)&data, sizeof(data)); out.write((char*)&countOrSubType, sizeof(countOrSubType));
} }
} }
} }
@ -264,7 +264,7 @@ void Map::setCentralPosition(const Position& centralPosition)
if(teleported) { if(teleported) {
for(const auto& pair : m_knownCreatures) { for(const auto& pair : m_knownCreatures) {
const CreaturePtr& creature = pair.second; const CreaturePtr& creature = pair.second;
const TilePtr& tile = creature->getCurrentTile(); const TilePtr& tile = creature->getTile();
if(tile) { if(tile) {
tile->removeThing(creature); tile->removeThing(creature);
creature->setPosition(Position()); creature->setPosition(Position());
@ -275,7 +275,7 @@ void Map::setCentralPosition(const Position& centralPosition)
for(const auto& pair : m_knownCreatures) { for(const auto& pair : m_knownCreatures) {
const CreaturePtr& creature = pair.second; const CreaturePtr& creature = pair.second;
if(!isAwareOfPosition(creature->getPosition())) { if(!isAwareOfPosition(creature->getPosition())) {
const TilePtr& tile = creature->getCurrentTile(); const TilePtr& tile = creature->getTile();
if(tile) { if(tile) {
tile->removeThing(creature); tile->removeThing(creature);
creature->setPosition(Position()); creature->setPosition(Position());

View File

@ -60,12 +60,14 @@ void MapView::draw(const Rect& rect)
int tileDrawFlags = 0; int tileDrawFlags = 0;
if(m_viewRange == NEAR_VIEW) if(m_viewRange == NEAR_VIEW)
tileDrawFlags = Otc::DrawGround | Otc::DrawWalls | Otc::DrawCommonItems | Otc::DrawCreatures | Otc::DrawEffects; tileDrawFlags = Otc::DrawGround | Otc::DrawGroundBorders | Otc::DrawWalls | Otc::DrawCommonItems | Otc::DrawCreatures | Otc::DrawEffects | Otc::DrawAnimations;
else if(m_viewRange == MID_VIEW) else if(m_viewRange == MID_VIEW)
tileDrawFlags = Otc::DrawGround | Otc::DrawWalls | Otc::DrawCommonItems; tileDrawFlags = Otc::DrawGround | Otc::DrawGroundBorders | Otc::DrawWalls | Otc::DrawCommonItems;
else if(m_viewRange == FAR_VIEW) else if(m_viewRange == FAR_VIEW)
tileDrawFlags = Otc::DrawGround | Otc::DrawWalls; tileDrawFlags = Otc::DrawGround | Otc::DrawGroundBorders | Otc::DrawWalls;
else // HUGE_VIEW else if(m_tileSize >= 4) // HUGE_VIEW 1
tileDrawFlags = Otc::DrawGround | Otc::DrawGroundBorders;
else // HUGE_VIEW 2
tileDrawFlags = Otc::DrawGround; tileDrawFlags = Otc::DrawGround;
bool animate = m_animated; bool animate = m_animated;
@ -109,11 +111,11 @@ void MapView::draw(const Rect& rect)
// avoid drawing texts on map in far zoom outs // avoid drawing texts on map in far zoom outs
if(m_viewRange == NEAR_VIEW) { if(m_viewRange == NEAR_VIEW) {
for(const CreaturePtr& creature : m_cachedFloorVisibleCreatures) { for(const CreaturePtr& creature : m_cachedFloorVisibleCreatures) {
const TilePtr& tile = creature->getCurrentTile(); const TilePtr& tile = creature->getTile();
Position pos = tile->getPosition(); Position pos = tile->getPosition();
Point p = transformPositionTo2D(pos) - drawOffset; Point p = transformPositionTo2D(pos) - drawOffset;
p += (creature->getWalkOffset()-tile->getDrawElevation() + Point(8, -8)) * scaleFactor; p += (creature->getWalkOffset()-tile->getDrawElevation() + Point(8, -10)) * scaleFactor;
p.x = p.x * horizontalStretchFactor; p.x = p.x * horizontalStretchFactor;
p.y = p.y * verticalStretchFactor; p.y = p.y * verticalStretchFactor;
p += rect.topLeft(); p += rect.topLeft();

View File

@ -27,24 +27,18 @@
#include <framework/core/clock.h> #include <framework/core/clock.h>
#include <framework/core/eventdispatcher.h> #include <framework/core/eventdispatcher.h>
Missile::Missile() : Thing()
{
m_startTicks = 0;
}
void Missile::draw(const Point& p, const Rect&) void Missile::draw(const Point& p, const Rect&)
{ {
if(m_id == 0)
return;
/*
float time = (g_clock.ticks() - m_startTicks) / m_duration; float time = (g_clock.ticks() - m_startTicks) / m_duration;
//internalDraw(p + Point(m_deltax * time, m_deltay * time), 0);
}
void Missile::setPath(const Position& fromPosition, const Position& toPosition)
{
Otc::Direction direction = fromPosition.getDirectionFromPosition(toPosition);
int xPattern = 0, yPattern = 0;
if(direction == Otc::NorthWest) { if(direction == Otc::NorthWest) {
m_xPattern = 0; xPattern = 0;
m_yPattern = 0; yPattern = 0;
} }
else if(direction == Otc::North) { else if(direction == Otc::North) {
m_xPattern = 1; m_xPattern = 1;
@ -79,20 +73,29 @@ void Missile::setPath(const Position& fromPosition, const Position& toPosition)
m_yPattern = 1; m_yPattern = 1;
} }
//internalDraw(p + Point(m_deltax * time, m_deltay * time), 0, 0);
*/
}
void Missile::setPath(const Position& fromPosition, const Position& toPosition)
{
m_direction = fromPosition.getDirectionFromPosition(toPosition);
m_position = fromPosition; m_position = fromPosition;
m_deltax = toPosition.x - fromPosition.x; m_deltax = toPosition.x - fromPosition.x;
m_deltay = toPosition.y - fromPosition.y; m_deltay = toPosition.y - fromPosition.y;
m_startTicks = g_clock.ticks();
m_duration = 150 * std::sqrt(Point(m_deltax, m_deltay).length()); m_duration = 150 * std::sqrt(Point(m_deltax, m_deltay).length());
m_deltax *= Otc::TILE_PIXELS; m_deltax *= Otc::TILE_PIXELS;
m_deltay *= Otc::TILE_PIXELS; m_deltay *= Otc::TILE_PIXELS;
m_animationTimer.restart();
// schedule removal // schedule removal
auto self = asMissile(); auto self = asMissile();
g_dispatcher.scheduleEvent([self]() { g_map.removeThing(self); }, m_duration); g_dispatcher.scheduleEvent([self]() { g_map.removeThing(self); }, m_duration);
} }
ThingType *Missile::getType() void Missile::setId(uint32 id)
{ {
return g_thingsType.getThingType(m_id, ThingsType::Missile); m_id = id;
m_type = g_thingsType.getThingType(m_id, ThingsType::Missile);
} }

View File

@ -24,6 +24,7 @@
#define SHOT_H #define SHOT_H
#include <framework/global.h> #include <framework/global.h>
#include <framework/core/timer.h>
#include "thing.h" #include "thing.h"
class Missile : public Thing class Missile : public Thing
@ -33,23 +34,24 @@ class Missile : public Thing
}; };
public: public:
Missile();
void draw(const Point& p, const Rect&); void draw(const Point& p, const Rect&);
void updateAnimation(); void updateAnimation();
void setId(uint32 id);
void setPath(const Position& fromPosition, const Position& toPosition); void setPath(const Position& fromPosition, const Position& toPosition);
ThingType *getType(); uint32 getId() { return m_id; }
MissilePtr asMissile() { return std::static_pointer_cast<Missile>(shared_from_this()); } MissilePtr asMissile() { return std::static_pointer_cast<Missile>(shared_from_this()); }
private: private:
ticks_t m_startTicks; Timer m_animationTimer;
int m_deltax; int m_deltax;
int m_deltay; int m_deltay;
float m_duration; float m_duration;
uint16 m_id;
Otc::Direction m_direction;
}; };
#endif #endif

View File

@ -28,20 +28,9 @@
Thing::Thing() Thing::Thing()
{ {
m_id = 0;
m_xPattern = 0;
m_yPattern = 0;
m_zPattern = 0;
m_animation = 0;
m_type = g_thingsType.getEmptyThingType(); m_type = g_thingsType.getEmptyThingType();
} }
void Thing::setId(uint32 id)
{
m_id = id;
updateType();
}
int Thing::getStackPriority() int Thing::getStackPriority()
{ {
if(isGround()) if(isGround())
@ -58,42 +47,28 @@ int Thing::getStackPriority()
return 5; return 5;
} }
const TilePtr& Thing::getCurrentTile() const TilePtr& Thing::getTile()
{ {
return g_map.getTile(m_position); return g_map.getTile(m_position);
} }
void Thing::internalDraw(const Point& dest, float scaleFactor, int layer) void Thing::internalDraw(const Point& dest, float scaleFactor, int xPattern, int yPattern, int zPattern, int layer, int animationPhase)
{ {
int scaledSize = Otc::TILE_PIXELS * scaleFactor; int scaledSize = Otc::TILE_PIXELS * scaleFactor;
for(int h = 0; h < getDimensionHeight(); h++) { for(int h = 0; h < getDimensionHeight(); h++) {
for(int w = 0; w < getDimensionWidth(); w++) { for(int w = 0; w < getDimensionWidth(); w++) {
int spriteId = getSpriteId(w, h, layer, m_xPattern, m_yPattern, m_zPattern, m_animation); int spriteId = getSpriteId(w, h, layer, xPattern, yPattern, zPattern, animationPhase);
if(!spriteId) if(!spriteId)
continue; continue;
TexturePtr spriteTex = g_sprites.getSpriteTexture(spriteId); TexturePtr spriteTex = g_sprites.getSpriteTexture(spriteId);
Rect drawRect((dest.x - w*scaledSize) - getDisplacementX()*scaleFactor, Rect drawRect(dest.x - (w*Otc::TILE_PIXELS - getDisplacementX())*scaleFactor,
(dest.y - h*scaledSize) - getDisplacementY()*scaleFactor, dest.y - (h*Otc::TILE_PIXELS - getDisplacementY())*scaleFactor,
scaledSize, scaledSize); scaledSize, scaledSize);
g_painter.setColor(Fw::white);
g_painter.drawTexturedRect(drawRect, spriteTex); g_painter.drawTexturedRect(drawRect, spriteTex);
} }
} }
} }
void Thing::updateType()
{
if(CreaturePtr creature = asCreature())
m_type = g_thingsType.getThingType(creature->getOutfit().getId(), creature->getOutfit().getCategory());
else if(asItem())
m_type = g_thingsType.getThingType(m_id, ThingsType::Item);
else if(asMissile())
m_type = g_thingsType.getThingType(m_id, ThingsType::Missile);
else if(asEffect())
m_type = g_thingsType.getThingType(m_id, ThingsType::Effect);
else
m_type = g_thingsType.getEmptyThingType();
}

View File

@ -40,19 +40,15 @@ public:
virtual ~Thing() { } virtual ~Thing() { }
virtual void startAnimation() { } virtual void startAnimation() { }
virtual void draw(const Point& dest, float scaleFactor) { } virtual void draw(const Point& dest, float scaleFactor, bool animate) { }
virtual void setId(uint32 id); virtual void setId(uint32 id) { }
virtual void setPosition(const Position& position) { m_position = position; } void setPosition(const Position& position) { m_position = position; }
uint32 getId() { return m_id; } virtual uint32 getId() { return 0; }
Position getPosition() { return m_position; } Position getPosition() { return m_position; }
int getStackPriority(); int getStackPriority();
const TilePtr& getCurrentTile(); const TilePtr& getTile();
void setXPattern(int xPattern) { m_xPattern = xPattern; }
void setYPattern(int yPattern) { m_yPattern = yPattern; }
void setZPattern(int zPattern) { m_zPattern = zPattern; }
ThingPtr asThing() { return std::static_pointer_cast<Thing>(shared_from_this()); } ThingPtr asThing() { return std::static_pointer_cast<Thing>(shared_from_this()); }
virtual ItemPtr asItem() { return nullptr; } virtual ItemPtr asItem() { return nullptr; }
@ -105,14 +101,9 @@ public:
int getSpriteId(int w = 0, int h = 0, int layer = 0, int xPattern = 0, int yPattern = 0, int zPattern = 0, int animation = 0) { return m_type->getSpriteId(w, h, layer, xPattern, yPattern, zPattern, animation); } int getSpriteId(int w = 0, int h = 0, int layer = 0, int xPattern = 0, int yPattern = 0, int zPattern = 0, int animation = 0) { return m_type->getSpriteId(w, h, layer, xPattern, yPattern, zPattern, animation); }
protected: protected:
void internalDraw(const Point& dest, float scaleFactor, int layer); void internalDraw(const Point& dest, float scaleFactor, int xPattern, int yPattern, int zPattern, int layer, int animationPhase);
void updateType();
uint32 m_id; //TODO: move to derived class to use less memory
Position m_position; Position m_position;
uint8 m_xPattern, m_yPattern, m_zPattern, m_animation; //TODO: remove this variables to use less memory
private:
ThingType *m_type; ThingType *m_type;
}; };

View File

@ -115,11 +115,12 @@ void ThingsType::parseThingType(std::stringstream& fin, ThingType& thingType)
ThingType *ThingsType::getThingType(uint16 id, Categories category) ThingType *ThingsType::getThingType(uint16 id, Categories category)
{ {
assert(id != 0);
if(category == Item) if(category == Item)
id -= 100; id -= 100;
else if(category == Creature || category == Effect || category == Missile) else if(category == Creature || category == Effect || category == Missile)
id -= 1; id -= 1;
assert(id < m_things[category].size());
if(id == 0 || id >= m_things[category].size())
return &m_emptyThingType;
return &m_things[category][id]; return &m_things[category][id];
} }

View File

@ -49,8 +49,8 @@ public:
uint32 getSignature() { return m_signature; } uint32 getSignature() { return m_signature; }
bool isLoaded() { return m_loaded; } bool isLoaded() { return m_loaded; }
int getFirstItemId() { return 100; } uint16 getFirstItemId() { return 100; }
int getMaxItemid() { return m_things[Item].size() + 100 - 1; } uint16 getMaxItemid() { return m_things[Item].size() + 99; }
private: private:
uint32 m_signature; uint32 m_signature;

View File

@ -39,23 +39,18 @@ Tile::Tile(const Position& position)
void Tile::draw(const Point& dest, float scaleFactor, int drawFlags) void Tile::draw(const Point& dest, float scaleFactor, int drawFlags)
{ {
int drawElevation = 0; int drawElevation = 0;
bool animate = drawFlags & Otc::DrawAnimations;
// optimization far far views
if(drawFlags == Otc::DrawGround) {
const ThingPtr& thing = m_things.front();
if(thing)
thing->draw(dest, scaleFactor);
return;
}
// first bottom items // first bottom items
if(drawFlags & Otc::DrawGround || drawFlags & Otc::DrawWalls) { if(drawFlags & Otc::DrawGround || drawFlags & Otc::DrawWalls || drawFlags & Otc::DrawGroundBorders) {
for(const ThingPtr& thing : m_things) { for(const ThingPtr& thing : m_things) {
if(!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom()) if(!thing->isGround() && !thing->isGroundBorder() && !thing->isOnBottom())
break; break;
if((drawFlags & Otc::DrawGround && thing->isGround()) || (drawFlags & Otc::DrawWalls)) if((thing->isGround() && drawFlags & Otc::DrawGround) ||
thing->draw(dest - drawElevation*scaleFactor, scaleFactor); (thing->isGroundBorder() && drawFlags & Otc::DrawGroundBorders) ||
(thing->isOnBottom() && drawFlags & Otc::DrawWalls))
thing->draw(dest - drawElevation*scaleFactor, scaleFactor, animate);
drawElevation += thing->getElevation(); drawElevation += thing->getElevation();
if(drawElevation > Otc::MAX_ELEVATION) if(drawElevation > Otc::MAX_ELEVATION)
@ -69,7 +64,7 @@ void Tile::draw(const Point& dest, float scaleFactor, int drawFlags)
const ThingPtr& thing = *it; const ThingPtr& thing = *it;
if(thing->isOnTop() || thing->isOnBottom() || thing->isGroundBorder() || thing->isGround() || thing->asCreature()) if(thing->isOnTop() || thing->isOnBottom() || thing->isGroundBorder() || thing->isGround() || thing->asCreature())
break; break;
thing->draw(dest - drawElevation*scaleFactor, scaleFactor); thing->draw(dest - drawElevation*scaleFactor, scaleFactor, animate);
drawElevation += thing->getElevation(); drawElevation += thing->getElevation();
if(drawElevation > Otc::MAX_ELEVATION) if(drawElevation > Otc::MAX_ELEVATION)
@ -79,30 +74,32 @@ void Tile::draw(const Point& dest, float scaleFactor, int drawFlags)
// creatures // creatures
if(drawFlags & Otc::DrawCreatures) { if(drawFlags & Otc::DrawCreatures) {
if(animate) {
for(const CreaturePtr& creature : m_walkingCreatures) { for(const CreaturePtr& creature : m_walkingCreatures) {
creature->draw(Point(dest.x + ((creature->getPosition().x - m_position.x)*Otc::TILE_PIXELS - drawElevation)*scaleFactor, creature->draw(Point(dest.x + ((creature->getPosition().x - m_position.x)*Otc::TILE_PIXELS - drawElevation)*scaleFactor,
dest.y + ((creature->getPosition().y - m_position.y)*Otc::TILE_PIXELS - drawElevation)*scaleFactor), scaleFactor); dest.y + ((creature->getPosition().y - m_position.y)*Otc::TILE_PIXELS - drawElevation)*scaleFactor), scaleFactor, animate);
} }
}
for(auto it = m_things.rbegin(); it != m_things.rend(); ++it) { for(auto it = m_things.rbegin(); it != m_things.rend(); ++it) {
CreaturePtr creature = (*it)->asCreature(); CreaturePtr creature = (*it)->asCreature();
if(creature && !creature->isWalking()) if(creature && (!creature->isWalking() || !animate))
creature->draw(dest - drawElevation, scaleFactor); creature->draw(dest - drawElevation, scaleFactor, animate);
} }
} }
// effects // effects
if(drawFlags & Otc::DrawEffects) { if(drawFlags & Otc::DrawEffects) {
for(const EffectPtr& effect : m_effects) for(const EffectPtr& effect : m_effects)
effect->draw(dest, scaleFactor); effect->draw(dest, scaleFactor, animate);
} }
// top items // top items
if(drawFlags & Otc::DrawWalls) { if(drawFlags & Otc::DrawWalls) {
for(const ThingPtr& thing : m_things) { for(const ThingPtr& thing : m_things) {
if(thing->isOnTop()) if(thing->isOnTop())
thing->draw(dest - drawElevation, scaleFactor); thing->draw(dest - drawElevation, scaleFactor, animate);
} }
} }
} }

View File

@ -92,9 +92,6 @@ void OTClient::registerLuaFunctions()
g_lua.bindClassMemberFunction<Thing>("getPosition", &Thing::getPosition); g_lua.bindClassMemberFunction<Thing>("getPosition", &Thing::getPosition);
g_lua.bindClassMemberFunction<Thing>("getStackPriority", &Thing::getStackPriority); g_lua.bindClassMemberFunction<Thing>("getStackPriority", &Thing::getStackPriority);
g_lua.bindClassMemberFunction<Thing>("getAnimationPhases", &Thing::getAnimationPhases); g_lua.bindClassMemberFunction<Thing>("getAnimationPhases", &Thing::getAnimationPhases);
g_lua.bindClassMemberFunction<Thing>("setXPattern", &Thing::setXPattern);
g_lua.bindClassMemberFunction<Thing>("setYPattern", &Thing::setYPattern);
g_lua.bindClassMemberFunction<Thing>("setZPattern", &Thing::setZPattern);
g_lua.bindClassMemberFunction<Thing>("asThing", &Thing::asThing); g_lua.bindClassMemberFunction<Thing>("asThing", &Thing::asThing);
g_lua.bindClassMemberFunction<Thing>("asItem", &Thing::asItem); g_lua.bindClassMemberFunction<Thing>("asItem", &Thing::asItem);
g_lua.bindClassMemberFunction<Thing>("asCreature", &Thing::asCreature); g_lua.bindClassMemberFunction<Thing>("asCreature", &Thing::asCreature);

View File

@ -1125,7 +1125,7 @@ ItemPtr ProtocolGame::internalGetItem(InputMessage& msg, int id)
ItemPtr item = Item::create(id); ItemPtr item = Item::create(id);
if(item->isStackable() || item->isFluidContainer() || item->isFluid()) if(item->isStackable() || item->isFluidContainer() || item->isFluid())
item->setCount(msg.getU8()); item->setCountOrSubType(msg.getU8());
return item; return item;
} }

View File

@ -30,7 +30,7 @@ void UICreature::draw()
if(m_creature) { if(m_creature) {
g_painter.setColor(Fw::white); g_painter.setColor(Fw::white);
m_creature->draw(m_rect.bottomRight() - Point(32, 32) + Point(m_padding.left, m_padding.top), 1); m_creature->draw(m_rect.bottomRight() - Point(32, 32) + Point(m_padding.left, m_padding.top), 1, false);
} }
drawChildren(); drawChildren();

View File

@ -38,7 +38,7 @@ void UIItem::draw()
Point topLeft = m_rect.bottomRight() - Point(32, 32) + Point(m_padding.left, m_padding.top); Point topLeft = m_rect.bottomRight() - Point(32, 32) + Point(m_padding.left, m_padding.top);
g_painter.setColor(Fw::white); g_painter.setColor(Fw::white);
m_item->draw(topLeft, 1); m_item->draw(topLeft, 1, true);
if(m_font && m_item->isStackable() && m_item->getCount() > 1) { if(m_font && m_item->isStackable() && m_item->getCount() > 1) {
std::string count = Fw::tostring(m_item->getCount()); std::string count = Fw::tostring(m_item->getCount());
@ -65,12 +65,6 @@ void UIItem::setItemId(int id)
} }
} }
void UIItem::setItemCount(int count)
{
if(m_item)
m_item->setCount(count);
}
void UIItem::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode) void UIItem::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode)
{ {
UIWidget::onStyleApply(styleName, styleNode); UIWidget::onStyleApply(styleName, styleNode);

View File

@ -34,13 +34,15 @@ public:
void draw(); void draw();
void setItemId(int id); void setItemId(int id);
void setItemCount(int count); void setItemCount(int count) { if(m_item) m_item->setCount(count); }
void setItemSubType(int subType) { if(m_item) m_item->setSubType(subType); }
void setItem(const ItemPtr& item) { m_item = item; } void setItem(const ItemPtr& item) { m_item = item; }
void setVirtual(bool virt) { m_virtual = virt; } void setVirtual(bool virt) { m_virtual = virt; }
void clearItem() { setItemId(0); } void clearItem() { setItemId(0); }
int getItemId() { return m_item ? m_item->getId() : 0; } int getItemId() { return m_item ? m_item->getId() : 0; }
int getItemCount() { return m_item ? m_item->getCount() : 0; } int getItemCount() { return m_item ? m_item->getCount() : 0; }
int getItemSubType() { return m_item ? m_item->getSubType() : 0; }
ItemPtr getItem() { return m_item; } ItemPtr getItem() { return m_item; }
bool isVirtual() { return m_virtual; } bool isVirtual() { return m_virtual; }