mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-27 13:55:54 -04:00
Solved movement bug where extra tiles you could move through, but not *to*, would end up *adding* movememnt.
Movement bugs are hard. So hard, in fact, that most of this commit is just adding the "amount of movement left after attacking" so I could ensure that there wasn't a problem in the "calculating attackable tiles" part. The actual fix is in UnitMovementAlgorithms.
This commit is contained in:
parent
55bed3bf30
commit
0309e51afd
@ -38,7 +38,7 @@ object BattleHelper {
|
|||||||
stayOnTile: Boolean = false
|
stayOnTile: Boolean = false
|
||||||
): ArrayList<AttackableTile> {
|
): ArrayList<AttackableTile> {
|
||||||
val tilesWithEnemies = (tilesToCheck ?: unit.civInfo.viewableTiles)
|
val tilesWithEnemies = (tilesToCheck ?: unit.civInfo.viewableTiles)
|
||||||
.filter { containsAttackableEnemy(it, MapUnitCombatant(unit)) }
|
.filter { containsAttackableEnemy(it, MapUnitCombatant(unit)) }
|
||||||
|
|
||||||
val rangeOfAttack = unit.getRange()
|
val rangeOfAttack = unit.getRange()
|
||||||
|
|
||||||
@ -50,27 +50,36 @@ object BattleHelper {
|
|||||||
// Silly floats, basically
|
// Silly floats, basically
|
||||||
|
|
||||||
val unitMustBeSetUp = unit.hasUnique("Must set up to ranged attack")
|
val unitMustBeSetUp = unit.hasUnique("Must set up to ranged attack")
|
||||||
val tilesToAttackFrom = if (stayOnTile || unit.baseUnit.movesLikeAirUnits()) sequenceOf(unit.currentTile)
|
val tilesToAttackFrom = if (stayOnTile || unit.baseUnit.movesLikeAirUnits())
|
||||||
|
sequenceOf(Pair(unit.currentTile, unit.currentMovement))
|
||||||
else
|
else
|
||||||
unitDistanceToTiles.asSequence()
|
unitDistanceToTiles.asSequence()
|
||||||
.filter {
|
.map {
|
||||||
val movementPointsToExpendAfterMovement = if (unitMustBeSetUp) 1 else 0
|
val tile = it.key
|
||||||
val movementPointsToExpendHere = if (unitMustBeSetUp && !unit.isSetUpForSiege()) 1 else 0
|
val movementPointsToExpendAfterMovement = if (unitMustBeSetUp) 1 else 0
|
||||||
val movementPointsToExpendBeforeAttack = if (it.key == unit.currentTile) movementPointsToExpendHere else movementPointsToExpendAfterMovement
|
val movementPointsToExpendHere =
|
||||||
unit.currentMovement - it.value.totalDistance - movementPointsToExpendBeforeAttack > 0.1
|
if (unitMustBeSetUp && !unit.isSetUpForSiege()) 1 else 0
|
||||||
} // still got leftover movement points after all that, to attack (0.1 is because of Float nonsense, see MapUnit.moveToTile(...)
|
val movementPointsToExpendBeforeAttack =
|
||||||
.map { it.key }
|
if (it.key == unit.currentTile) movementPointsToExpendHere else movementPointsToExpendAfterMovement
|
||||||
.filter { unit.movement.canMoveTo(it) || it == unit.getTile() }
|
val movementLeft =
|
||||||
|
unit.currentMovement - it.value.totalDistance - movementPointsToExpendBeforeAttack
|
||||||
|
Pair(tile, movementLeft)
|
||||||
|
}
|
||||||
|
// still got leftover movement points after all that, to attack (0.1 is because of Float nonsense, see MapUnit.moveToTile(...)
|
||||||
|
.filter { it.second > 0.1f }
|
||||||
|
.filter {
|
||||||
|
it.first == unit.getTile() || unit.movement.canMoveTo(it.first)
|
||||||
|
}
|
||||||
|
|
||||||
for (reachableTile in tilesToAttackFrom) { // tiles we'll still have energy after we reach there
|
for ((reachableTile, movementLeft) in tilesToAttackFrom) { // tiles we'll still have energy after we reach there
|
||||||
val tilesInAttackRange =
|
val tilesInAttackRange =
|
||||||
if (unit.hasUnique("Ranged attacks may be performed over obstacles") || unit.baseUnit.movesLikeAirUnits())
|
if (unit.hasUnique("Ranged attacks may be performed over obstacles") || unit.baseUnit.movesLikeAirUnits())
|
||||||
reachableTile.getTilesInDistance(rangeOfAttack)
|
reachableTile.getTilesInDistance(rangeOfAttack)
|
||||||
else reachableTile.getViewableTilesList(rangeOfAttack)
|
else reachableTile.getViewableTilesList(rangeOfAttack)
|
||||||
.asSequence()
|
.asSequence()
|
||||||
|
|
||||||
attackableTiles += tilesInAttackRange.filter { it in tilesWithEnemies }
|
attackableTiles += tilesInAttackRange.filter { it in tilesWithEnemies }
|
||||||
.map { AttackableTile(reachableTile, it) }
|
.map { AttackableTile(reachableTile, it, movementLeft) }
|
||||||
}
|
}
|
||||||
return attackableTiles
|
return attackableTiles
|
||||||
}
|
}
|
||||||
|
@ -372,15 +372,13 @@ object Battle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun postBattleAddXp(attacker: ICombatant, defender: ICombatant) {
|
private fun postBattleAddXp(attacker: ICombatant, defender: ICombatant) {
|
||||||
if (attacker.isMelee()) {
|
if (!attacker.isMelee()) { // ranged attack
|
||||||
if (!defender.isCivilian()) // unit was not captured but actually attacked
|
|
||||||
{
|
|
||||||
addXp(attacker, 5, defender)
|
|
||||||
addXp(defender, 4, attacker)
|
|
||||||
}
|
|
||||||
} else { // ranged attack
|
|
||||||
addXp(attacker, 2, defender)
|
addXp(attacker, 2, defender)
|
||||||
addXp(defender, 2, attacker)
|
addXp(defender, 2, attacker)
|
||||||
|
} else if (!defender.isCivilian()) // unit was not captured but actually attacked
|
||||||
|
{
|
||||||
|
addXp(attacker, 5, defender)
|
||||||
|
addXp(defender, 4, attacker)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,15 +470,19 @@ class UnitMovementAlgorithms(val unit:MapUnit) {
|
|||||||
passingMovementSpent = 0f
|
passingMovementSpent = 0f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
previousTile = tile
|
previousTile = tile
|
||||||
|
|
||||||
|
// We can't continue, stop here.
|
||||||
if (unit.isDestroyed || unit.currentMovement - passingMovementSpent < Constants.minimumMovementEpsilon) {
|
if (unit.isDestroyed || unit.currentMovement - passingMovementSpent < Constants.minimumMovementEpsilon) {
|
||||||
unit.currentMovement = passingMovementSpent // silly floats which are "almost zero"
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Silly floats which are almost zero
|
||||||
|
if (unit.currentMovement < Constants.minimumMovementEpsilon)
|
||||||
|
unit.currentMovement = 0f
|
||||||
|
|
||||||
|
|
||||||
if (!unit.isDestroyed)
|
if (!unit.isDestroyed)
|
||||||
unit.putInTile(lastReachedEnterableTile)
|
unit.putInTile(lastReachedEnterableTile)
|
||||||
|
|
||||||
|
@ -2,4 +2,5 @@ package com.unciv.models
|
|||||||
|
|
||||||
import com.unciv.logic.map.TileInfo
|
import com.unciv.logic.map.TileInfo
|
||||||
|
|
||||||
class AttackableTile(val tileToAttackFrom: TileInfo, val tileToAttack: TileInfo)
|
class AttackableTile(val tileToAttackFrom: TileInfo, val tileToAttack: TileInfo,
|
||||||
|
val movementLeftAfterMovingToAttackTile:Float)
|
@ -588,7 +588,7 @@ class Ruleset {
|
|||||||
lines.add("${promotion.name} requires promotion $prereq which does not exist!", RulesetErrorSeverity.Warning)
|
lines.add("${promotion.name} requires promotion $prereq which does not exist!", RulesetErrorSeverity.Warning)
|
||||||
for (unitType in promotion.unitTypes)
|
for (unitType in promotion.unitTypes)
|
||||||
if (!unitTypes.containsKey(unitType) && (unitTypes.isNotEmpty() || !baseRuleset.unitTypes.containsKey(unitType)))
|
if (!unitTypes.containsKey(unitType) && (unitTypes.isNotEmpty() || !baseRuleset.unitTypes.containsKey(unitType)))
|
||||||
lines.add("${promotion.name} references unit type ${unitType}, which does not exist!", RulesetErrorSeverity.Warning)
|
lines.add("${promotion.name} references unit type $unitType, which does not exist!", RulesetErrorSeverity.Warning)
|
||||||
checkUniques(promotion, lines, UniqueType.UniqueComplianceErrorSeverity.RulesetSpecific)
|
checkUniques(promotion, lines, UniqueType.UniqueComplianceErrorSeverity.RulesetSpecific)
|
||||||
}
|
}
|
||||||
for (unitType in unitTypes.values) {
|
for (unitType in unitTypes.values) {
|
||||||
|
@ -196,7 +196,7 @@ class BattleTable(val worldScreen: WorldScreen): Table() {
|
|||||||
{
|
{
|
||||||
val canBombard = UnitAutomation.getBombardTargets(attacker.city).contains(defender.getTile())
|
val canBombard = UnitAutomation.getBombardTargets(attacker.city).contains(defender.getTile())
|
||||||
if (canBombard) {
|
if (canBombard) {
|
||||||
attackableTile = AttackableTile(attacker.getTile(), defender.getTile())
|
attackableTile = AttackableTile(attacker.getTile(), defender.getTile(), 0f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user