Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/client/luafunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,6 @@ void Client::registerLuaFunctions()

g_lua.registerSingletonClass("g_map");
g_lua.bindSingletonFunction("g_map", "isLookPossible", &Map::isLookPossible, &g_map);
g_lua.bindSingletonFunction("g_map", "isCovered", &Map::isCovered, &g_map);
g_lua.bindSingletonFunction("g_map", "isCompletelyCovered", &Map::isCompletelyCovered, &g_map);
g_lua.bindSingletonFunction("g_map", "addThing", &Map::addThing, &g_map);
g_lua.bindSingletonFunction("g_map", "addStaticText", &Map::addStaticText, &g_map);
g_lua.bindSingletonFunction("g_map", "addAnimatedText", &Map::addAnimatedText, &g_map);
Expand Down Expand Up @@ -904,14 +902,17 @@ void Client::registerLuaFunctions()
g_lua.bindClassMemberFunction<Tile>("isWalkable", &Tile::isWalkable);
g_lua.bindClassMemberFunction<Tile>("hasElevation", &Tile::hasElevation);

g_lua.bindClassMemberFunction<Tile>("isCovered", &Tile::isCovered);
g_lua.bindClassMemberFunction<Tile>("isCompletelyCovered", &Tile::isCompletelyCovered);
g_lua.bindClassMemberFunction<Tile>("isFullGround", &Tile::isFullGround);
g_lua.bindClassMemberFunction<Tile>("isFullyOpaque", &Tile::isFullyOpaque);
g_lua.bindClassMemberFunction<Tile>("isLookPossible", &Tile::isLookPossible);
g_lua.bindClassMemberFunction<Tile>("hasCreatures", &Tile::hasCreatures);
g_lua.bindClassMemberFunction<Tile>("isEmpty", &Tile::isEmpty);
g_lua.bindClassMemberFunction<Tile>("isClickable", &Tile::isClickable);
g_lua.bindClassMemberFunction<Tile>("isPathable", &Tile::isPathable);

g_lua.bindClassMemberFunction<Tile>("hasCreatures", &Tile::hasCreatures);

g_lua.bindClassMemberFunction<Tile>("select", &Tile::select);
g_lua.bindClassMemberFunction<Tile>("unselect", &Tile::unselect);
g_lua.bindClassMemberFunction<Tile>("isSelected", &Tile::isSelected);
Expand Down
14 changes: 12 additions & 2 deletions src/client/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -660,13 +660,18 @@ bool Map::isLookPossible(const Position& pos)
return tile && tile->isLookPossible();
}

bool Map::isCovered(const Position& pos, const uint8_t firstFloor)
bool Map::isCovered(const Position& pos, bool& isLoading, const uint8_t firstFloor)
{
// check for tiles on top of the postion
Position tilePos = pos;
while (tilePos.coveredUp() && tilePos.z >= firstFloor) {
// the below tile is covered when the above tile has a full opaque
if (const auto& tile = getTile(tilePos)) {
if (tile->isLoading()) {
isLoading = true;
return false;
}

if (tile->isFullyOpaque())
return true;
}
Expand All @@ -680,7 +685,7 @@ bool Map::isCovered(const Position& pos, const uint8_t firstFloor)
return false;
}

bool Map::isCompletelyCovered(const Position& pos, const uint8_t firstFloor)
bool Map::isCompletelyCovered(const Position& pos, bool& isLoading, const uint8_t firstFloor)
{
const auto& checkTile = getTile(pos);
Position tilePos = pos;
Expand Down Expand Up @@ -711,6 +716,11 @@ bool Map::isCompletelyCovered(const Position& pos, const uint8_t firstFloor)
for (auto x = -1; ++x < 2 && !done;) {
for (auto y = -1; ++y < 2 && !done;) {
const auto& tile = getTile(tilePos.translated(-x, -y));
if (tile && tile->isLoading()) {
isLoading = true;
return false;
}

if (!tile || !tile->isFullyOpaque()) {
covered = false;
done = true;
Expand Down
14 changes: 12 additions & 2 deletions src/client/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,18 @@ class Map
void setCentralPosition(const Position& centralPosition);

bool isLookPossible(const Position& pos);
bool isCovered(const Position& pos, uint8_t firstFloor = 0);
bool isCompletelyCovered(const Position& pos, uint8_t firstFloor = 0);
bool isCovered(const Position& pos, uint8_t firstFloor = 0) {
bool isLoading = false;
return isCovered(pos, isLoading, firstFloor);
}

bool isCompletelyCovered(const Position& pos, uint8_t firstFloor = 0) {
bool isLoading = false;
return isCompletelyCovered(pos, isLoading, firstFloor);
}

bool isCovered(const Position& pos, bool& isLoading, uint8_t firstFloor = 0);
bool isCompletelyCovered(const Position& pos, bool& isLoading, uint8_t firstFloor = 0);
bool isAwareOfPosition(const Position& pos) const { return isAwareOfPosition(pos, m_awareRange); }
bool isAwareOfPosition(const Position& pos, const AwareRange& awareRange) const;

Expand Down
5 changes: 3 additions & 2 deletions src/client/spriteappearances.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,8 +233,9 @@ ImagePtr SpriteAppearances::getSpriteImage(const int id, bool& isLoading)
if (!image->hasTransparentPixel()) {
// The image must be more than 4 pixels transparent to be considered transparent.
uint8_t cntTrans = 0;
for (const uint8_t pixel : image->getPixels()) {
if (pixel == 0x00 && ++cntTrans > 4) {
const auto& buf = image->getPixels();
for (size_t i = 3, n = buf.size(); i < n; i += 4) {
if (buf[i] == 0x00 && ++cntTrans > 4) {
image->setTransparentPixel(true);
break;
}
Expand Down
6 changes: 5 additions & 1 deletion src/client/spritemanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,8 @@ ImagePtr SpriteManager::getSpriteImage(const int id, const FileStreamPtr& file)
const uint16_t transparentPixels = readU16FromBuffer(spriteBuffer.data(), offset);
const uint16_t coloredPixels = readU16FromBuffer(spriteBuffer.data(), offset);

transparentCount += transparentPixels;

const int transparentBytes = transparentPixels * 4;
if (writePos + transparentBytes > maxWriteSize)
break;
Expand Down Expand Up @@ -330,8 +332,10 @@ ImagePtr SpriteManager::getSpriteImage(const int id, const FileStreamPtr& file)
}
}

if (writePos < maxWriteSize)
if (writePos < maxWriteSize) {
std::memset(pixels + writePos, 0, maxWriteSize - writePos);
transparentCount += maxWriteSize - writePos;
}

if (hasAlpha || transparentCount > 4)
image->setTransparentPixel(true);
Expand Down
1 change: 1 addition & 0 deletions src/client/thing.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ class Thing : public AttachableObject
bool isTopEffect() { return getThingType()->isTopEffect(); }
bool isPodium() const { return getThingType()->isPodium(); }
bool isOpaque() const { return getThingType()->isOpaque(); }
bool isLoading() const { return getThingType()->isLoading(); }
bool isSingleDimension() const { return getThingType()->isSingleDimension(); }
bool isTall(const bool useRealSize = false) const { return getThingType()->isTall(useRealSize); }

Expand Down
3 changes: 2 additions & 1 deletion src/client/thingtype.h
Original file line number Diff line number Diff line change
Expand Up @@ -439,8 +439,9 @@ class ThingType final : public LuaObject
bool isPodium() { return (m_flags & ThingFlagAttrPodium); }
bool isTopEffect() { return (m_flags & ThingFlagAttrTopEffect); }
bool hasAction() { return (m_flags & ThingFlagAttrDefaultAction); }
bool isOpaque() { if (m_opaque == -1) getTexture(0); return m_opaque == 1; }
bool isOpaque() { return m_opaque == 1; }
bool isDecoKit() { return (m_flags & ThingFlagAttrDecoKit); }
bool isLoading() const { return m_loading.load(std::memory_order_acquire); }

bool isItem() const { return m_category == ThingCategoryItem; }
bool isEffect() const { return m_category == ThingCategoryEffect; }
Expand Down
43 changes: 38 additions & 5 deletions src/client/tile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -623,11 +623,19 @@ bool Tile::isCompletelyCovered(const uint8_t firstFloor, const bool resetCache)
const uint32_t idState = 1 << (firstFloor + g_gameConfig.getMapMaxZ());
if ((m_isCompletelyCovered & idChecked) == 0) {
m_isCompletelyCovered |= idChecked;
if (g_map.isCompletelyCovered(m_position, firstFloor)) {
bool isLoading = false;
if (g_map.isCompletelyCovered(m_position, isLoading, firstFloor)) {
m_isCompletelyCovered |= idState;
m_isCovered |= idChecked; // Set covered is Checked
m_isCovered |= idState;
}

if (isLoading) {
m_isCompletelyCovered &= ~idState;
m_isCovered &= ~idChecked;
m_isCovered &= ~idState;
return false;
}
}

return (m_isCompletelyCovered & idState) == idState;
Expand All @@ -642,8 +650,15 @@ bool Tile::isCovered(const int8_t firstFloor)

if ((m_isCovered & idChecked) == 0) {
m_isCovered |= idChecked;
if (g_map.isCovered(m_position, firstFloor))
bool isLoading = false;
if (g_map.isCovered(m_position, isLoading, firstFloor))
m_isCovered |= idState;

if (isLoading) {
m_isCovered &= ~idChecked;
m_isCovered &= ~idState;
return false;
}
}

return (m_isCovered & idState) == idState;
Expand Down Expand Up @@ -878,9 +893,6 @@ void Tile::setThingFlag(const ThingPtr& thing)
if (thing->isFullGround())
m_thingTypeFlag |= FULL_GROUND;

if (thing->isOpaque())
m_thingTypeFlag |= IS_OPAQUE;

if (thing->hasElevation())
++m_elevation;
}
Expand Down Expand Up @@ -1004,4 +1016,25 @@ bool Tile::canShoot(int distance)
if (distance > 0 && std::max<int>(std::abs(m_position.x - playerPos.x), std::abs(m_position.y - playerPos.y)) > distance)
return false;
return g_map.isSightClear(playerPos, m_position);
}

bool Tile::isFullyOpaque() {
if (isFullGround())
return true;

for (const auto& thing : m_things) {
if (thing->isOpaque())
return true;
}

return false;
}

bool Tile::isLoading() const {
for (const auto& thing : m_things) {
if (thing->isLoading())
return true;
}

return false;
}
5 changes: 3 additions & 2 deletions src/client/tile.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ enum TileThingType : uint32_t
HAS_DISPLACEMENT = 1 << 5,
IS_NOT_PATHAB = 1 << 6,
ELEVATION = 1 << 7,
IS_OPAQUE = 1 << 8,
// IS_OPAQUE = 1 << 8,
HAS_LIGHT = 1 << 9,
HAS_TALL_THINGS = 1 << 10,
HAS_WIDE_THINGS = 1 << 11,
Expand Down Expand Up @@ -137,13 +137,14 @@ class Tile final : public AttachableObject
bool isClickable();
bool isPathable() { return (m_thingTypeFlag & NOT_PATHABLE) == 0; }
bool isFullGround() { return m_thingTypeFlag & FULL_GROUND; }
bool isFullyOpaque() { return m_thingTypeFlag & IS_OPAQUE; }
bool isFullyOpaque();
bool isSingleDimension() { return (m_thingTypeFlag & NOT_SINGLE_DIMENSION) == 0 && m_walkingCreatures.empty(); }
bool isLookPossible() { return (m_thingTypeFlag & BLOCK_PROJECTTILE) == 0; }
bool isEmpty() { return m_things.empty(); }
bool isDrawable() { return !isEmpty() || !m_walkingCreatures.empty() || hasEffect() || hasAttachedEffects(); }
bool isCovered(int8_t firstFloor);
bool isCompletelyCovered(uint8_t firstFloor, bool resetCache);
bool isLoading() const;

bool hasBlockingCreature() const;

Expand Down
Loading