Skip to content

Combat Precision Fix and Health UI Enhancement - #141

Merged
candour merged 5 commits into
mainfrom
fix-combat-precision-and-ui-enhancement-5785280520036751080
May 10, 2026
Merged

Combat Precision Fix and Health UI Enhancement#141
candour merged 5 commits into
mainfrom
fix-combat-precision-and-ui-enhancement-5785280520036751080

Conversation

@candour

@candour candour commented May 10, 2026

Copy link
Copy Markdown
Owner

This PR addresses a core combat logic bug where precision loss occurred during health and damage calculations due to the use of integers. By refactoring these fields to Float, we ensure that damage modifiers and armor buffs are applied accurately.

Additionally, this PR includes:

  • UI Enhancement: Enemies now display their health as a percentage next to their health bar, as requested.
  • Rendering Improvement: Projectiles and overhead visual effects (like Satay's gas cloud) now consistently render above ground entities (stalls, enemies), fixing depth sorting issues.
  • Maintenance: Updated StallConsole for cleaner integer-based display of stats and verified the entire fix with the existing test suite.

PR created automatically by Jules for task 5785280520036751080 started by @candour

Summary by CodeRabbit

  • New Features

    • Enemy health bars now show percentage text and improved visuals.
  • Bug Fixes

    • Damage and health use higher-precision values to prevent rounding errors.
  • Visual

    • Projectiles, overhead effects, selected-stall overlays and upgrade indicators render above world entities with refined visual effects and layering.
  • Documentation

    • Rendering/z-order docs updated with explicit layer groups and sorting rules.

Review Change Stack

- Refactored Enemy, Stall, and Projectile models to use Float for health and damage.
- Updated MainViewModel and StallUpgradeManager to maintain float precision in combat calculations.
- Improved rendering z-sorting in GameBoard.kt to keep overhead effects above ground entities.
- Added percentage health text display to enemy health bars.
- Updated unit tests and documentation (AGENTS.md, fixes.md).

Co-authored-by: candour <4670475+candour@users.noreply.github.com>
@google-labs-jules

Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@coderabbitai

coderabbitai Bot commented May 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 734acd83-9238-4120-88d6-e338eb4eecc0

📥 Commits

Reviewing files that changed from the base of the PR and between 13be935 and 8a922ab.

📒 Files selected for processing (3)
  • AGENTS.md
  • app/src/main/java/com/messark/hawker/ui/components/GameBoard.kt
  • fixes.md

📝 Walkthrough

Walkthrough

This PR refactors health and damage from Int to Float across models, gameplay logic, UI rendering, and tests; updates GameBoard z-order grouping/sorting and refactors enemy health-bar drawing to use a Float-based ratio.

Changes

Float Health/Damage Precision & Z-Order Rendering

Layer / File(s) Summary
Data Model & Type Contracts
app/src/main/java/com/messark/hawker/model/GameModels.kt, app/src/main/java/com/messark/hawker/registry/Registry.kt
Core game model data classes (Stall, Enemy, Projectile) and registry definitions (StallDefinition, EnemyDefinition) change health and damage properties from Int to Float. EnemyDefinition.getHp(wave) signature updated to return Float.
Game Logic & Calculations
app/src/main/java/com/messark/hawker/MainViewModel.kt, app/src/main/java/com/messark/hawker/utils/StallUpgradeManager.kt
getEnemyHP returns Float; temporary stall firing boost preserves Float-scaled damage; projectile impacts store floating-point currentHealth; calculateStatBoost accumulates totalBoostPercent as Float; applyUpgrade uses toFloat() for damage.
Rendering & UI Updates
app/src/main/java/com/messark/hawker/ui/components/GameBoard.kt, app/src/main/java/com/messark/hawker/ui/components/StallConsole.kt, AGENTS.md
Selected-stall overlay and upgrade indicator rendered as DrawableEntity with raised zOrder; effects and projectiles receive adjusted zOrder buckets; drawable sorting comparator uses explicit zOrder ranges; enemy health bar uses healthRatio and styled percent text via drawIntoCanvas; BAK_KUT_TEH boost formatting adjusted; AGENTS.md documents groups 04 and sorting rules.
Test Data & Documentation
app/src/test/java/com/messark/hawker/*.kt, fixes.md
Test fixtures updated to use Float literals (*f) for health, maxHealth, and damage; FIX-005 added to fixes.md documenting the Float refactor and rendering changes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • candour/towerpower#126: Modifies Bak Kut Teh stat-boost logic and overlaps with changes to calculateStatBoost/MainViewModel.
  • candour/towerpower#101: Touches projectile/enemy health handling in MainViewModel, related to Float health/damage changes.
  • candour/towerpower#72: Updates GameBoard enemy health-bar rendering and related UI drawing logic, overlapping rendering changes.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main changes: converting combat fields to Float for precision and adding enemy health percentage display.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-combat-precision-and-ui-enhancement-5785280520036751080

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

Copy link
Copy Markdown

Build Successful! 🚀

Download APK

Note: This link will be removed when the PR is closed.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/src/main/java/com/messark/hawker/MainViewModel.kt (1)

814-855: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Inconsistent death threshold causes kill-credit inflation across stalls.

In hits.forEach the early-exit at line 822 uses currentHealth <= 0, but the per-projectile kill check at line 843 (and the final death check at line 856) uses currentHealth < 1.0f. With Float health, a projectile that drops health to e.g. 0.5 does not trip the <= 0 early exit, so a later projectile in the same tick will also satisfy < 1.0f and award kills += 1 to its source stall — double-counting kills (which feeds into the legendary-suffix Level-10 unlock heuristics indirectly through stats and any leaderboard surfaces).

Suggest aligning the early exit with the kill threshold:

🛠 Proposed fix to align death thresholds
             hits.forEach { proj ->
-                if (currentHealth <= 0) return@forEach
+                if (currentHealth < 1.0f) return@forEach
🧹 Nitpick comments (2)
app/src/main/java/com/messark/hawker/MainViewModel.kt (1)

817-817: 💤 Low value

Redundant .toFloat() after Float migration.

enemy.health and proj.damage are already Float per the updated GameModels.kt, so .toFloat() here is a no-op and slightly misleading.

♻️ Proposed cleanup
-            var currentHealth = enemy.health.toFloat()
+            var currentHealth = enemy.health
@@
-                var damage = proj.damage.toFloat()
+                var damage = proj.damage

Also applies to: 824-824

app/src/main/java/com/messark/hawker/ui/components/GameBoard.kt (1)

670-678: ⚡ Quick win

Use theme-driven colors for health text rendering.

The new percentage text paint hardcodes white/black at Line 674 and Line 677. Please source these from theme colors to preserve light/dark behavior consistency.

As per coding guidelines "Avoid hardcoding colors in UI components; always prefer MaterialTheme.colorScheme (e.g., onSurface, surface, primary) for light and dark theme support".


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 87f58376-1cc0-4045-ad2f-c8e54da24ffa

📥 Commits

Reviewing files that changed from the base of the PR and between 01ebbc9 and 7e76503.

📒 Files selected for processing (13)
  • AGENTS.md
  • app/src/main/java/com/messark/hawker/MainViewModel.kt
  • app/src/main/java/com/messark/hawker/model/GameModels.kt
  • app/src/main/java/com/messark/hawker/registry/Registry.kt
  • app/src/main/java/com/messark/hawker/ui/components/GameBoard.kt
  • app/src/main/java/com/messark/hawker/ui/components/StallConsole.kt
  • app/src/main/java/com/messark/hawker/utils/StallUpgradeManager.kt
  • app/src/test/java/com/messark/hawker/KitchelinBonusTest.kt
  • app/src/test/java/com/messark/hawker/MilestoneBoostTest.kt
  • app/src/test/java/com/messark/hawker/StallStatsTest.kt
  • app/src/test/java/com/messark/hawker/UncleDoubleGrabTest.kt
  • app/src/test/java/com/messark/hawker/UndeadEnemyTest.kt
  • fixes.md

Comment thread app/src/main/java/com/messark/hawker/ui/components/GameBoard.kt Outdated
@candour

candour commented May 10, 2026

Copy link
Copy Markdown
Owner Author

If enemy.maxHealth <= 0f, Line 647 can produce NaN/Inf, which then propagates into filledHeight and draw calls (Line 662-667), risking unstable rendering.

@google-labs-jules

Copy link
Copy Markdown
Contributor

If enemy.maxHealth <= 0f, Line 647 can produce NaN/Inf, which then propagates into filledHeight and draw calls (Line 662-667), risking unstable rendering.

Good catch! I've added a check for enemy.maxHealth > 0f to prevent division by zero and ensure healthRatio defaults to 0f in that case.

- Added guard in GameBoard.kt to prevent NaN/Inf in healthRatio calculation.
- Verified that all unit tests still pass.

Co-authored-by: candour <4670475+candour@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown

Build Successful! 🚀

Download APK

Note: This link will be removed when the PR is closed.

@candour

candour commented May 10, 2026

Copy link
Copy Markdown
Owner Author

app/src/main/java/com/messark/hawker/MainViewModel.kt line 817

Redundant .toFloat() after Float migration.

enemy.health and proj.damage are already Float per the updated GameModels.kt, so .toFloat() here is a no-op and slightly misleading.

app/src/main/java/com/messark/hawker/MainViewModel.kt lines 814-855

Inconsistent death threshold causes kill-credit inflation across stalls.

In hits.forEach the early-exit at line 822 uses currentHealth <= 0, but the per-projectile kill check at line 843 (and the final death check at line 856) uses currentHealth < 1.0f. With Float health, a projectile that drops health to e.g. 0.5 does not trip the <= 0 early exit, so a later projectile in the same tick will also satisfy < 1.0f and award kills += 1 to its source stall — double-counting kills (which feeds into the legendary-suffix Level-10 unlock heuristics indirectly through stats and any leaderboard surfaces).

Suggest aligning the early exit with the kill threshold

@google-labs-jules

Copy link
Copy Markdown
Contributor

app/src/main/java/com/messark/hawker/MainViewModel.kt line 817

Redundant .toFloat() after Float migration.

enemy.health and proj.damage are already Float per the updated GameModels.kt, so .toFloat() here is a no-op and slightly misleading.

app/src/main/java/com/messark/hawker/MainViewModel.kt lines 814-855

Inconsistent death threshold causes kill-credit inflation across stalls.

In hits.forEach the early-exit at line 822 uses currentHealth <= 0, but the per-projectile kill check at line 843 (and the final death check at line 856) uses currentHealth < 1.0f. With Float health, a projectile that drops health to e.g. 0.5 does not trip the <= 0 early exit, so a later projectile in the same tick will also satisfy < 1.0f and award kills += 1 to its source stall — double-counting kills (which feeds into the legendary-suffix Level-10 unlock heuristics indirectly through stats and any leaderboard surfaces).

Suggest aligning the early exit with the kill threshold

Excellent points. I've removed the redundant .toFloat() calls and aligned the early-exit threshold in the hit loop to < 1.0f to match the death/kill criteria, preventing any kill double-counting.

- Refactored combat stats to Float to resolve rounding bugs.
- Implemented percentage health display for enemies.
- Optimized rendering z-sorting to keep projectiles/VFX above world entities.
- Cleaned up redundant casts and unified death thresholds in game engine.
- Added safety guards for potential division by zero in UI.
- Updated documentation and test suite.

Co-authored-by: candour <4670475+candour@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown

Build Successful! 🚀

Download APK

Note: This link will be removed when the PR is closed.

@candour
candour enabled auto-merge (squash) May 10, 2026 09:35
@candour

candour commented May 10, 2026

Copy link
Copy Markdown
Owner Author

In MainViewModel.kt (around the combat loop), lines like enemy.health.toFloat() and proj.damage.toFloat() are now no-ops.

@google-labs-jules

Copy link
Copy Markdown
Contributor

In MainViewModel.kt (around the combat loop), lines like enemy.health.toFloat() and proj.damage.toFloat() are now no-ops.

Acknowledged. I have removed the redundant .toFloat() calls from the health and damage fields in the combat loop in the latest update, as they are now correctly defined as Float in the models.

- Removed redundant .toFloat() calls on health and damage.
- Aligned hit-loop early exit with the < 1.0f death threshold to prevent kill double-counting.
- Verified all tests pass.

Co-authored-by: candour <4670475+candour@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown

Build Successful! 🚀

Download APK

Note: This link will be removed when the PR is closed.

@candour
candour merged commit 74444cd into main May 10, 2026
1 of 2 checks passed
@candour
candour deleted the fix-combat-precision-and-ui-enhancement-5785280520036751080 branch May 10, 2026 12:53
@coderabbitai coderabbitai Bot mentioned this pull request Jun 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant