fix(char): range checks use sprite frame hitbox (CON-30)#5
Conversation
…ogic Use frame_width/frame_height for circle-rect collisions instead of the full preview image so melee range matches the on-map sprite. Center attack and perception circles on the hitbox center and use radii that match collision (half of configured range). Fix get_nearest_enemy clearing the target when a farther enemy appeared later in iteration order. Co-authored-by: Rodrigo Stramantinoli <rodrigostramantinoli@gmail.com>
Resolve char.lua conflict by keeping matchmaking rendering (RENDER_SCALE, char_range_center, scaled draw/update) and re-applying CON-30 range fixes using scaled frame hitboxes instead of preview image dimensions. Co-authored-by: Rodrigo Stramantinoli <rodrigostramantinoli@gmail.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 0015c8d. Configure here.
| else | ||
| self.enemies_around[k] = nil | ||
| end | ||
| end |
There was a problem hiding this comment.
Stale enemies_around entries after direct card removal
Medium Severity
get_enemies_in_range only iterates keys present in the current enemies table, so any key previously stored in self.enemies_around that has since been directly removed from the cards table (e.g., via reject_intent which does self.cards[...][card_id] = nil) is never cleaned up. The stale reference persists indefinitely and can be selected by get_nearest_enemy, causing the character to target and attack a phantom enemy that no longer exists in the game.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 0015c8d. Configure here.
| end | ||
| for _, tower in ipairs(self.cards[Constants.ENEMY_ID]) do | ||
| tower:draw(tower.current_life) | ||
| end |
There was a problem hiding this comment.
Towers rendered twice per frame in draw loop
Low Severity
Towers are stored with numeric keys (via table.insert) in the same table as char cards (stored with string keys). The main pairs() draw loops iterate all entries including towers, and then draw_towers() draws towers again using ipairs(). The new code extends this double-draw to enemy towers by adding the Constants.ENEMY_ID loop to draw_towers.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 0015c8d. Configure here.


Summary
Resolves CON-30 (char cards attacking out of range).
Merged with
feat/matchmaking.Root cause
img_previewdimensions instead of in-world sprite frame size, inflating the target rectangle.get_nearest_enemycould clear the closest enemy depending on iteration order.Changes
frame_width/frame_height(withRENDER_SCALEfrom matchmaking) for hitbox bounds.char_range_centerso they match on-map rendering.get_nearest_enemyto always keep the closest enemy.Verification
luacheck src/entities/cards/char.luachar.luaresolved againstfeat/matchmakingLinear Issue: CON-30