Skip to content

Commit

Permalink
Fix draw order problems with south walk (diasurgical#7053)
Browse files Browse the repository at this point in the history
  • Loading branch information
kphoenix137 authored Apr 7, 2024
1 parent 0a2d488 commit 6d5bbe6
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 42 deletions.
80 changes: 60 additions & 20 deletions Source/engine/render/scrollrt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -632,12 +632,11 @@ void DrawItem(const Surface &out, int8_t itemIndex, Point targetBufferPosition)
void DrawMonsterHelper(const Surface &out, Point tilePosition, Point targetBufferPosition)
{
int mi = dMonster[tilePosition.x][tilePosition.y];
bool isNegativeMonster = mi < 0;
mi = std::abs(mi) - 1;
if (mi < 0) // negative monster (moving into tile)
return;

if (leveltype == DTYPE_TOWN) {
if (isNegativeMonster)
return;
auto &towner = Towners[mi];
const Point position = targetBufferPosition + towner.getRenderingOffset();
const ClxSprite sprite = towner.currentSprite();
Expand All @@ -662,19 +661,7 @@ void DrawMonsterHelper(const Surface &out, Point tilePosition, Point targetBuffe
}

const ClxSprite sprite = monster.animInfo.currentSprite();

Displacement offset = monster.getRenderingOffset(sprite);
if (monster.isWalking()) {
bool isSideWalkingToLeft = monster.mode == MonsterMode::MoveSideways && monster.direction == Direction::West;
if (isNegativeMonster && !isSideWalkingToLeft)
return;
if (!isNegativeMonster && isSideWalkingToLeft)
return;
if (isSideWalkingToLeft)
offset -= Displacement { 64, 0 };
} else if (isNegativeMonster) {
return;
}

const Point monsterRenderPosition = targetBufferPosition + offset;
if (mi == pcursmonst) {
Expand Down Expand Up @@ -747,13 +734,66 @@ void DrawDungeon(const Surface &out, Point tilePosition, Point targetBufferPosit
if (TileContainsDeadPlayer(tilePosition)) {
DrawDeadPlayer(out, tilePosition, targetBufferPosition);
}
int8_t playerId = dPlayer[tilePosition.x][tilePosition.y];
if (static_cast<size_t>(playerId - 1) < Players.size()) {
DrawPlayerHelper(out, Players[playerId - 1], tilePosition, targetBufferPosition);
Player *player = PlayerAtPosition(tilePosition);
if (player != nullptr) {
// If sprite is moving southwards, we want to draw it offset from the tile it's moving to, so we need negative ID
int8_t playerId = static_cast<int8_t>(player->getId() + 1);

if (player->_pmode == PM_WALK_SOUTHWARDS)
playerId = -playerId;
if (dPlayer[tilePosition.x][tilePosition.y] == playerId) {
auto tempTilePosition = tilePosition;
auto tempTargetBufferPosition = targetBufferPosition;

// Offset the sprite to the tile it's moving from
if (player->_pmode == PM_WALK_SOUTHWARDS) {
switch (player->_pdir) {
case Direction::SouthWest:
tempTargetBufferPosition += { TILE_WIDTH / 2, -TILE_HEIGHT / 2 };
break;
case Direction::South:
tempTargetBufferPosition += { 0, -TILE_HEIGHT };
break;
case Direction::SouthEast:
tempTargetBufferPosition += { -TILE_WIDTH / 2, -TILE_HEIGHT / 2 };
break;
}
tempTilePosition += Opposite(player->_pdir);
}
DrawPlayerHelper(out, *player, tempTilePosition, tempTargetBufferPosition); // BUGFIX: Player sprite gets cut off walking in front of certain corners in caves
}
}
if (dMonster[tilePosition.x][tilePosition.y] != 0) {
DrawMonsterHelper(out, tilePosition, targetBufferPosition);

Monster *monster = FindMonsterAtPosition(tilePosition);
if (monster != nullptr) {
// If sprite is moving southwards, we want to draw it offset from the tile it's moving to, so we need negative ID
int8_t monsterId = static_cast<int8_t>(monster->getId() + 1);

if (monster->mode == MonsterMode::MoveSouthwards)
monsterId = -monsterId;
if (dMonster[tilePosition.x][tilePosition.y] == monsterId) {
auto tempTilePosition = tilePosition;
auto tempTargetBufferPosition = targetBufferPosition;

// Offset the sprite to the tile it's moving from
if (monster->mode == MonsterMode::MoveSouthwards) {
switch (monster->direction) {
case Direction::SouthWest:
tempTargetBufferPosition += { TILE_WIDTH / 2, -TILE_HEIGHT / 2 };
break;
case Direction::South:
tempTargetBufferPosition += { 0, -TILE_HEIGHT };
break;
case Direction::SouthEast:
tempTargetBufferPosition += { -TILE_WIDTH / 2, -TILE_HEIGHT / 2 };
break;
}
tempTilePosition += Opposite(monster->direction);
}
DrawMonsterHelper(out, tempTilePosition, tempTargetBufferPosition); // BUGFIX: Monster sprite gets cut off walking in front of certain corners in caves
}
}

DrawMissile(out, tilePosition, targetBufferPosition, false);

if (object != nullptr && !object->_oPreFlag) {
Expand Down
47 changes: 25 additions & 22 deletions Source/monster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -718,7 +718,24 @@ void WalkInDirection(Monster &monster, Direction endDir)
const auto fx = static_cast<WorldTileCoord>(monster.position.tile.x + dir.x);
const auto fy = static_cast<WorldTileCoord>(monster.position.tile.y + dir.y);

monster.mode = MonsterMode::MoveNorthwards;
MonsterMode mode;
switch (endDir) {
case Direction::NorthWest:
case Direction::North:
case Direction::NorthEast:
mode = MonsterMode::MoveNorthwards;
break;
case Direction::West:
case Direction::East:
mode = MonsterMode::MoveSideways;
break;
case Direction::SouthWest:
case Direction::South:
case Direction::SouthEast:
mode = MonsterMode::MoveSouthwards;
break;
}
monster.mode = mode;
monster.position.old = monster.position.tile;
monster.position.future = { fx, fy };
monster.occupyTile(monster.position.future, true);
Expand Down Expand Up @@ -995,30 +1012,16 @@ void MonsterIdle(Monster &monster)
/**
* @brief Continue movement towards new tile
*/
bool MonsterWalk(Monster &monster, MonsterMode variant)
bool MonsterWalk(Monster &monster)
{
// Check if we reached new tile
const bool isAnimationEnd = monster.animInfo.isLastFrame();
if (isAnimationEnd) {
switch (variant) {
case MonsterMode::MoveNorthwards:
dMonster[monster.position.tile.x][monster.position.tile.y] = 0;
monster.position.tile.x += monster.var1;
monster.position.tile.y += monster.var2;
monster.occupyTile(monster.position.tile, false);
break;
case MonsterMode::MoveSouthwards:
dMonster[monster.var1][monster.var2] = 0;
break;
case MonsterMode::MoveSideways:
dMonster[monster.position.tile.x][monster.position.tile.y] = 0;
monster.position.tile = WorldTilePosition { static_cast<WorldTileCoord>(monster.var1), static_cast<WorldTileCoord>(monster.var2) };
// dMonster is set here for backwards comparability, without it the monster would be invisible if loaded from a vanilla save.
monster.occupyTile(monster.position.tile, false);
break;
default:
break;
}
dMonster[monster.position.tile.x][monster.position.tile.y] = 0;
monster.position.tile.x += monster.var1;
monster.position.tile.y += monster.var2;
// dMonster is set here for backwards compatibility; without it, the monster would be invisible if loaded from a vanilla save.
monster.occupyTile(monster.position.tile, false);
if (monster.lightId != NO_LIGHT)
ChangeLightXY(monster.lightId, monster.position.tile);
M_StartStand(monster, monster.direction);
Expand Down Expand Up @@ -3024,7 +3027,7 @@ bool UpdateModeStance(Monster &monster)
case MonsterMode::MoveNorthwards:
case MonsterMode::MoveSouthwards:
case MonsterMode::MoveSideways:
return MonsterWalk(monster, monster.mode);
return MonsterWalk(monster);
case MonsterMode::MeleeAttack:
return MonsterAttack(monster);
case MonsterMode::HitRecovery:
Expand Down

0 comments on commit 6d5bbe6

Please sign in to comment.