Skip to content

Commit 9094a6d

Browse files
committed
Modding: "Costs [amount] [stockpiledResource]" accepts game speed modifier
1 parent 8e4763a commit 9094a6d

File tree

7 files changed

+33
-31
lines changed

7 files changed

+33
-31
lines changed

core/src/com/unciv/logic/city/CityConstructions.kt

+5-16
Original file line numberDiff line numberDiff line change
@@ -373,15 +373,12 @@ class CityConstructions : IsPartOfGameInfoSerialization {
373373
val construction = getConstruction(constructionName)
374374
// First construction will be built next turn, we need to make sure it has the correct resources
375375
if (constructionQueue.isEmpty() && getWorkDone(constructionName) == 0) {
376-
val costUniques = construction.getMatchingUniquesNotConflicting(UniqueType.CostsResources,
377-
city.state
378-
)
376+
val stockpileCosts = construction.getStockpiledResourceRequirements(city.state)
379377
val civResources = city.civ.getCivResourcesByName()
380378

381-
if (costUniques.any {
382-
val resourceName = it.params[1]
379+
if (stockpileCosts.any { (resourceName, amount) ->
383380
civResources[resourceName] == null
384-
|| it.params[0].toInt() > civResources[resourceName]!! })
381+
|| amount > civResources[resourceName]!! })
385382
continue // Removes this construction from the queue
386383
}
387384
if (construction.isBuildable(this))
@@ -431,11 +428,7 @@ class CityConstructions : IsPartOfGameInfoSerialization {
431428
}
432429

433430
private fun constructionBegun(construction: IConstruction) {
434-
val costUniques = construction.getMatchingUniquesNotConflicting(UniqueType.CostsResources, city.state)
435-
436-
for (unique in costUniques) {
437-
val amount = unique.params[0].toInt()
438-
val resourceName = unique.params[1]
431+
for ((resourceName, amount) in construction.getStockpiledResourceRequirements(city.state)) {
439432
val resource = city.civ.gameInfo.ruleset.tileResources[resourceName] ?: continue
440433
city.gainStockpiledResource(resource, -amount)
441434
}
@@ -735,11 +728,7 @@ class CityConstructions : IsPartOfGameInfoSerialization {
735728

736729
// Consume stockpiled resources - usually consumed when construction starts, but not when bought
737730
if (getWorkDone(construction.name) == 0){ // we didn't pay the resources when we started building
738-
val costUniques = construction.getMatchingUniques(UniqueType.CostsResources, conditionalState)
739-
740-
for (unique in costUniques) {
741-
val amount = unique.params[0].toInt()
742-
val resourceName = unique.params[1]
731+
for ((resourceName, amount) in construction.getStockpiledResourceRequirements(conditionalState)) {
743732
val resource = city.civ.gameInfo.ruleset.tileResources[resourceName] ?: continue
744733
city.gainStockpiledResource(resource, -amount)
745734
}

core/src/com/unciv/logic/map/tile/TileImprovementFunctions.kt

+5-2
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ class TileImprovementFunctions(val tile: Tile) {
7878
yield(ImprovementBuildingProblem.MissingResources)
7979

8080
if (improvement.getMatchingUniques(UniqueType.CostsResources)
81-
.any { civInfo.getResourceAmount(it.params[1]) < it.params[0].toInt() })
81+
.any { civInfo.getResourceAmount(it.params[1]) < it.params[0].toInt() *
82+
(if (it.isModifiedByGameSpeed()) civInfo.gameInfo.speed.modifier else 1f) })
8283
yield(ImprovementBuildingProblem.MissingResources)
8384

8485
val knownFeatureRemovals = tile.ruleset.nonRoadTileRemovals
@@ -258,7 +259,9 @@ class TileImprovementFunctions(val tile: Tile) {
258259

259260
for (unique in improvement.getMatchingUniques(UniqueType.CostsResources, stateForConditionals)) {
260261
val resource = tile.ruleset.tileResources[unique.params[1]] ?: continue
261-
civ.gainStockpiledResource(resource, -unique.params[0].toInt())
262+
var amount = unique.params[0].toInt()
263+
if (unique.isModifiedByGameSpeed()) amount = (amount * civ.gameInfo.speed.modifier).toInt()
264+
civ.gainStockpiledResource(resource, -amount)
262265
}
263266

264267
for (unique in improvement.uniqueObjects.filter { !it.hasTriggerConditional()

core/src/com/unciv/models/ruleset/Building.kt

+1-3
Original file line numberDiff line numberDiff line change
@@ -394,9 +394,7 @@ class Building : RulesetStatsObject(), INonPerpetualConstruction {
394394

395395
// If we've already paid the unit costs, we don't need to pay it again
396396
if (cityConstructions.getWorkDone(name) == 0)
397-
for (unique in getMatchingUniques(UniqueType.CostsResources, stateForConditionals)) {
398-
val amount = unique.params[0].toInt()
399-
val resourceName = unique.params[1]
397+
for ((resourceName, amount) in getStockpiledResourceRequirements(stateForConditionals)) {
400398
val availableResources = cityConstructions.city.getAvailableResourceAmount(resourceName)
401399
if (availableResources < amount)
402400
yield(RejectionReasonType.ConsumesResources.toInstance(resourceName.getNeedMoreAmountString(amount - availableResources)))

core/src/com/unciv/models/ruleset/IConstruction.kt

+15-2
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@ import kotlin.math.roundToInt
1919
interface IConstruction : INamed {
2020
fun isBuildable(cityConstructions: CityConstructions): Boolean
2121
fun shouldBeDisplayed(cityConstructions: CityConstructions): Boolean
22+
/** We can't call this getMatchingUniques because then it would conflict with IHasUniques */
23+
fun getMatchingUniquesNotConflicting(uniqueType: UniqueType, stateForConditionals: StateForConditionals) = sequenceOf<Unique>()
24+
2225
/** Gets *per turn* resource requirements - does not include immediate costs for stockpiled resources.
2326
* Uses [state] to determine which civ or city this is built for*/
2427
fun getResourceRequirementsPerTurn(state: StateForConditionals? = null): Counter<String>
2528
fun requiredResources(state: StateForConditionals = StateForConditionals.EmptyState): Set<String>
26-
/** We can't call this getMatchingUniques because then it would conflict with IHasUniques */
27-
fun getMatchingUniquesNotConflicting(uniqueType: UniqueType, stateForConditionals: StateForConditionals) = sequenceOf<Unique>()
29+
fun getStockpiledResourceRequirements(state: StateForConditionals): Counter<String>
2830
}
2931

3032
interface INonPerpetualConstruction : IConstruction, INamed, IHasUniques {
@@ -117,6 +119,16 @@ interface INonPerpetualConstruction : IConstruction, INamed, IHasUniques {
117119
return getResourceRequirementsPerTurn(state).keys +
118120
getMatchingUniques(UniqueType.CostsResources, state).map { it.params[1] }
119121
}
122+
123+
override fun getStockpiledResourceRequirements(state: StateForConditionals): Counter<String> {
124+
val counter = Counter<String>()
125+
for (unique in getMatchingUniquesNotConflicting(UniqueType.CostsResources, state)){
126+
var amount = unique.params[0].toInt()
127+
if (unique.isModifiedByGameSpeed()) amount = (amount * state.gameInfo!!.speed.modifier).toInt()
128+
counter.add(unique.params[1], amount)
129+
}
130+
return counter
131+
}
120132
}
121133

122134
enum class PurchaseReason(val purchasable: Boolean) {
@@ -270,6 +282,7 @@ open class PerpetualConstruction(override var name: String, val description: Str
270282

271283
override fun shouldBeDisplayed(cityConstructions: CityConstructions) = isBuildable(cityConstructions)
272284
open fun getProductionTooltip(city: City, withIcon: Boolean = false) : String = ""
285+
override fun getStockpiledResourceRequirements(state: StateForConditionals) = Counter.ZERO
273286

274287
companion object {
275288
val science = PerpetualStatConversion(Stat.Science)

core/src/com/unciv/models/ruleset/unique/UniqueType.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,8 @@ enum class UniqueType(
208208
/** @see UnitActionStockpileCost */
209209
CostsResources("Costs [amount] [stockpiledResource]", UniqueTarget.Improvement, UniqueTarget.Building, UniqueTarget.Unit,
210210
docDescription = "These resources are removed *when work begins* on the construction. " +
211-
"Do not confuse with \"costs [amount] [stockpiledResource]\" (lowercase 'c'), the Unit Action Modifier."),
211+
"Do not confuse with \"costs [amount] [stockpiledResource]\" (lowercase 'c'), the Unit Action Modifier.",
212+
flags = setOf(UniqueFlag.AcceptsSpeedModifier)),
212213
// Todo: Get rid of forced sign (+[relativeAmount]) and unify these two, e.g.: "[relativeAmount]% [resource/resourceType] production"
213214
// Note that the parameter type 'resourceType' (strategic, luxury, bonus) currently doesn't exist and should then be added as well
214215
StrategicResourcesIncrease("Quantity of strategic resources produced by the empire +[relativeAmount]%", UniqueTarget.Global), // used by Policies

core/src/com/unciv/models/ruleset/unit/BaseUnit.kt

+1-3
Original file line numberDiff line numberDiff line change
@@ -267,9 +267,7 @@ class BaseUnit : RulesetObject(), INonPerpetualConstruction {
267267

268268
// If we've already paid the unit costs, we don't need to pay it again
269269
if (city == null || city.cityConstructions.getWorkDone(name) == 0)
270-
for (unique in getMatchingUniques(UniqueType.CostsResources, stateForConditionals)) {
271-
val amount = unique.params[0].toInt()
272-
val resourceName = unique.params[1]
270+
for ((resourceName, amount) in getStockpiledResourceRequirements(stateForConditionals)) {
273271
val availableResources = city?.getAvailableResourceAmount(resourceName) ?: civ.getResourceAmount(resourceName)
274272
if (availableResources < amount)
275273
yield(RejectionReasonType.ConsumesResources.toInstance(resourceName.getNeedMoreAmountString(amount - availableResources)))

core/src/com/unciv/ui/screens/cityscreen/CityConstructionsTable.kt

+4-4
Original file line numberDiff line numberDiff line change
@@ -533,12 +533,12 @@ class CityConstructionsTable(private val cityScreen: CityScreen) {
533533
resourceTable.add(ImageGetter.getResourcePortrait(resource, 15f)).padBottom(1f)
534534
}
535535
}
536-
for (unique in constructionButtonDTO.construction
537-
.getMatchingUniquesNotConflicting(UniqueType.CostsResources, cityScreen.city.state)) {
536+
for ((resourceName, amount) in constructionButtonDTO.construction
537+
.getStockpiledResourceRequirements(cityScreen.city.state)) {
538538
val color = if (constructionButtonDTO.rejectionReason?.type == RejectionReasonType.ConsumesResources)
539539
Color.RED else Color.WHITE
540-
resourceTable.add(ColorMarkupLabel(unique.params[0], color)).expandX().left().padLeft(5f)
541-
resourceTable.add(ImageGetter.getResourcePortrait(unique.params[1], 15f)).padBottom(1f)
540+
resourceTable.add(ColorMarkupLabel(amount.toString(), color)).expandX().left().padLeft(5f)
541+
resourceTable.add(ImageGetter.getResourcePortrait(resourceName, 15f)).padBottom(1f)
542542
}
543543
constructionTable.add(resourceTable).expandX().left()
544544

0 commit comments

Comments
 (0)