Add Austrian civ (#5026)

* Json definition for nation, images

* Jsons, Hussar and Coffee House

* Diplomatic Marriage Button

* Implement Marriage

* AI Marriage

* template.properties

* Popups etc

* Strings

* reviews

* reviews pt 2
This commit is contained in:
SimonCeder 2021-08-30 22:21:02 +02:00 committed by GitHub
parent 1771604a4a
commit a7c4895985
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 223 additions and 21 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

@ -775,6 +775,18 @@
"uniques": ["Must not be on [Hill]", "+[10]% Production when constructing [Buildings] [in this city]"],
"requiredTech": "Economics"
},
{
"name": "Coffee House",
"replaces": "Windmill",
"uniqueTo": "Austria",
"production": 2,
"percentStatBonus": {"production": 10},
"specialistSlots": {"Engineer": 1},
"hurryCostModifier": 25,
"maintenance": 2,
"uniques": ["[+25]% great person generation [in this city]"],
"requiredTech": "Economics"
},
{
"name": "Arsenal",
"cost": 300,

View File

@ -743,6 +743,34 @@
"Södertälje","Mariestad","Östersund","Borås","Sundsvall","Vimmerby","Köping","Mora","Arboga","Växjö","Gränna",
"Kiruna","Borgholm","Strängnäs","Sveg"]
},
{
"name": "Austria",
"leaderName": "Maria Theresa",
"adjective": ["Austrian"],
"startBias": ["Hill"],
"preferredVictoryType": "Diplomatic",
"startIntroPart1": "Noble and virtuous Queen Maria Theresa, Holy Roman Empress and sovereign of Austria, the people bow to your gracious will. Following the death of your father King Charles VI, you ascended the thone of Austria during a time of great instability, but the empty coffers and diminished military did litle to dissuade your ambitions. Faced with war almost immediately upon your succession to the thron, you managed to fend off your foes, and in naming your husband Francis Stephen co-ruler, assured your place as Empress of the Holy Roman Empire. During your reigh, you guided Austria on a new path of reform - strengthening the military, replenishing the treasury, and improving the educational system of the kingdom.",
"startIntroPart2": "Oh great queen, bold and dignified, the time has come for you to rise and guide the kingdom once again. Can you return your people to the height of prosperity and splendor? Will you build a civilization that stands the test of time?",
"declaringWar": "Shame that it has come this far. But ye wished it so. Next time, be so good, choose your words more wisely. ",
"attacked": "What a fool ye are! Ye will end swiftly and miserably.",
"defeated": "The world is pitiful! There's no beauty in it, no wisdom. I am almost glad to go.",
"introduction": "The archduchess of Austria welcomes your Eminence to... Oh let's get this over with! I have a luncheon at four o'clock.",
"neutralHello": "Hello!",
"hateHello": "Oh, it's ye!",
"tradeRequest": "I see you admire my new damask. Nobody should say that I am an unjust woman. Let's reach an agreement!",
"outerColor": [234,0,0],
"innerColor": [255,255,255],
"uniqueName": "Diplomatic Marriage",
"uniques": ["Can spend Gold to annex or puppet a City-State that has been your ally for [5] turns."],
"cities": ["Vienna", "Salzburg", "Graz", "Linz", "Klagenfurt", "Bregenz", "Innsbruck", "Kitzbühel",
"St. Pölten", "Eisenstadt", "Villach", "Zwettl", "Traun", "Wels", "Dornbirn", "Feldkirch",
"Amstetten", "Bad Ischl", "Wolfsberg", "Kufstein", "Leoben", "Klosterneuburg", "Leonding",
"Kapfenberg", "Hallein", "Bischofshofen", "Waidhofen", "Saalbach", "Lienz", "Steyr"
]
},

View File

@ -995,6 +995,22 @@
"-[33]% Strength vs [City]", "+[50]% Strength vs [wounded units]"],
"attackSound": "horse"
},
{
"name": "Hussar",
"unitType": "Mounted",
"replaces": "Cavalry",
"uniqueTo": "Austria",
"movement": 5,
"strength": 34,
"cost": 225,
"requiredTech": "Military Science",
"obsoleteTech": "Combustion",
"requiredResource": "Horses",
"upgradesTo": "Landship",
"uniques": ["Can move after attacking","No defensive terrain bonus","-[33]% Strength vs [City]" ,
"[+1] Visibility Range", "[+50]% to Flank Attack bonuses" ],
"attackSound": "horse"
},
{
"name": "Ironclad",
"unitType": "Melee Water",

View File

@ -162,6 +162,10 @@ Declare Protection of [cityStateName]? =
Build [improvementName] on [resourceName] (200 Gold) =
Gift Improvement =
Diplomatic Marriage ([amount] Gold) =
We have married into the ruling family of [civName], bringing them under our control. =
[civName] has married into the ruling family of [civName2], bringing them under their control. =
Cultured =
Maritime =
Mercantile =

View File

@ -125,6 +125,25 @@ object NextTurnAutomation {
/** allow AI to spend money to purchase city-state friendship, buildings & unit */
private fun useGold(civInfo: CivilizationInfo) {
if (civInfo.getHappiness() > 0
&& civInfo.hasUnique("Can spend Gold to annex or puppet a City-State that has been your ally for [] turns.")) {
for (cityState in civInfo.getKnownCivs().filter { it.isCityState() } ) {
if (cityState.canBeMarriedBy(civInfo))
cityState.diplomaticMarriage(civInfo)
if (civInfo.getHappiness() <= 0) break // Stop marrying if happiness is getting too low
}
}
if (civInfo.victoryType() == VictoryType.Cultural) {
for (cityState in civInfo.getKnownCivs()
.filter { it.isCityState() && it.cityStateType == CityStateType.Cultured }) {
val diploManager = cityState.getDiplomacyManager(civInfo)
if (diploManager.influence < 40) { // we want to gain influence with them
tryGainInfluence(civInfo, cityState)
return
}
}
}
if (!civInfo.isCityState()) {
val potentialAllies = civInfo.getKnownCivs().filter { it.isCityState() }

View File

@ -130,9 +130,13 @@ object BattleDamage {
&& it.militaryUnit!!.owner == attacker.getCivInfo().civName
&& MapUnitCombatant(it.militaryUnit!!).isMelee()
}
if (numberOfAttackersSurroundingDefender > 1)
if (numberOfAttackersSurroundingDefender > 1) {
var flankingBonus = 10f //https://www.carlsguides.com/strategy/civilization5/war/combatbonuses.php
for (unique in attacker.unit.getMatchingUniques("[]% to Flank Attack bonuses"))
flankingBonus *= unique.params[0].toPercent()
modifiers["Flanking"] =
10 * (numberOfAttackersSurroundingDefender - 1) //https://www.carlsguides.com/strategy/civilization5/war/combatbonuses.php
(flankingBonus * (numberOfAttackersSurroundingDefender - 1)).toInt()
}
if (attacker.getTile()
.aerialDistanceTo(defender.getTile()) == 1 && attacker.getTile()
.isConnectedByRiver(defender.getTile())

View File

@ -249,6 +249,7 @@ class CityInfoConquestFunctions(val city: CityInfo){
if (civInfo.gameInfo.hasReligionEnabled()) religion.removeUnknownPantheons()
tryUpdateRoadStatus()
cityStats.update()
}
}

View File

@ -192,7 +192,7 @@ class CityStats(val cityInfo: CityInfo) {
}
fun hasExtraAnnexUnhappiness(): Boolean {
if (cityInfo.civInfo.civName == cityInfo.foundingCiv || cityInfo.foundingCiv == "" || cityInfo.isPuppet) return false
if (cityInfo.civInfo.civName == cityInfo.foundingCiv || cityInfo.isPuppet) return false
return !cityInfo.containsBuildingUnique("Remove extra unhappiness from annexed cities")
}

View File

@ -979,6 +979,8 @@ class CivilizationInfo {
else newAllyCiv.addNotification(text, civName, NotificationIcon.Diplomacy)
newAllyCiv.updateViewableTiles()
newAllyCiv.updateDetailedCivResources()
for (unique in newAllyCiv.getMatchingUniques("Can spend Gold to annex or puppet a City-State that has been your ally for [] turns."))
newAllyCiv.getDiplomacyManager(civName).setFlag(DiplomacyFlags.MarriageCooldown, unique.params[0].toInt())
}
if (oldAllyName != null) {
val oldAllyCiv = gameInfo.getCivilization(oldAllyName)
@ -991,6 +993,50 @@ class CivilizationInfo {
}
}
fun getDiplomaticMarriageCost(): Int {
// https://github.com/Gedemon/Civ5-DLL/blob/master/CvGameCoreDLL_Expansion1/CvMinorCivAI.cpp, line 7812
var cost = (500 * gameInfo.gameParameters.gameSpeed.modifier).toInt()
// Plus disband value of all units
for (unit in units) {
cost += unit.baseUnit.getDisbandGold(this)
}
// Round to lower multiple of 5
cost /= 5
cost *= 5
return cost
}
fun canBeMarriedBy(otherCiv: CivilizationInfo): Boolean {
return (!isDefeated()
&& isCityState()
&& getDiplomacyManager(otherCiv).relationshipLevel() == RelationshipLevel.Ally
&& !otherCiv.getDiplomacyManager(this).hasFlag(DiplomacyFlags.MarriageCooldown)
&& otherCiv.getMatchingUniques("Can spend Gold to annex or puppet a City-State that has been your ally for [] turns.").any()
&& otherCiv.gold >= getDiplomaticMarriageCost())
}
fun diplomaticMarriage(otherCiv: CivilizationInfo) {
if (!canBeMarriedBy(otherCiv)) // Just in case
return
otherCiv.gold -= getDiplomaticMarriageCost()
otherCiv.addNotification("We have married into the ruling family of [${civName}], bringing them under our control.",
getCapital().location, civName, NotificationIcon.Diplomacy, otherCiv.civName)
for (civ in gameInfo.civilizations.filter { it != otherCiv })
civ.addNotification("[${otherCiv.civName}] has married into the ruling family of [${civName}], bringing them under their control.",
getCapital().location, civName, NotificationIcon.Diplomacy, otherCiv.civName)
for (unit in units)
unit.gift(otherCiv)
for (city in cities) {
city.moveToCiv(otherCiv)
city.isPuppet = true // Human players get a popup that allows them to annex instead
city.foundingCiv = "" // This is no longer a city-state
}
destroy()
}
fun getTributeWillingness(demandingCiv: CivilizationInfo, demandingWorker: Boolean = false): Int {
return getTributeModifiers(demandingCiv, demandingWorker).values.sum()
}

View File

@ -13,6 +13,7 @@ enum class AlertType {
GoldenAge,
DeclarationOfFriendship,
StartIntro,
DiplomaticMarriage,
}
class PopupAlert {

View File

@ -39,6 +39,7 @@ enum class DiplomacyFlags{
IgnoreThemSettlingNearUs,
ProvideMilitaryUnit,
EverBeenFriends,
MarriageCooldown,
NotifiedAfraid
}

View File

@ -462,7 +462,7 @@ class Building : NamedStats(), INonPerpetualConstruction, ICivilopediaText {
"Must have an owned [] within [] tiles" -> if (cityCenter.getTilesInDistance(unique.params[1].toInt()).none {
it.matchesFilter(unique.params[0], civInfo) && it.getOwner() == construction.cityInfo.civInfo
}) return unique.text
"Can only be built in annexed cities" -> if (construction.cityInfo.isPuppet || construction.cityInfo.foundingCiv == ""
"Can only be built in annexed cities" -> if (construction.cityInfo.isPuppet
|| construction.cityInfo.civInfo.civName == construction.cityInfo.foundingCiv) return unique.text
"Obsolete with []" -> if (civInfo.tech.isResearched(unique.params[0])) return unique.text
Constants.hiddenWithoutReligionUnique -> if (!civInfo.gameInfo.hasReligionEnabled()) return unique.text

View File

@ -298,6 +298,9 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() {
}
}
val diplomaticMarriageButton = getDiplomaticMarriageButton(otherCiv)
if (diplomaticMarriageButton != null) diplomacyTable.add(diplomaticMarriageButton).row()
for (assignedQuest in otherCiv.questManager.assignedQuests.filter { it.assignee == viewingCiv.civName }) {
diplomacyTable.addSeparator()
diplomacyTable.add(getQuestTable(assignedQuest)).row()
@ -341,6 +344,23 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() {
return improveTileButton
}
private fun getDiplomaticMarriageButton(otherCiv: CivilizationInfo): TextButton? {
if (!viewingCiv.hasUnique("Can spend Gold to annex or puppet a City-State that has been your ally for [] turns."))
return null
val diplomaticMarriageButton =
"Diplomatic Marriage ([${otherCiv.getDiplomaticMarriageCost()}] Gold)".toTextButton()
diplomaticMarriageButton.onClick {
val newCities = otherCiv.cities
otherCiv.diplomaticMarriage(viewingCiv)
UncivGame.Current.setWorldScreen() // The other civ will no longer exist
for (city in newCities)
viewingCiv.popupAlerts.add(PopupAlert(AlertType.DiplomaticMarriage, city.id)) // Player gets to choose between annex and puppet
}
if (isNotPlayersTurn() || !otherCiv.canBeMarriedBy(viewingCiv)) diplomaticMarriageButton.disable()
return diplomaticMarriageButton
}
private fun getGoldGiftTable(otherCiv: CivilizationInfo): Table {
val diplomacyTable = getCityStateDiplomacyTableHeader(otherCiv)
diplomacyTable.addSeparator()

View File

@ -8,6 +8,7 @@ import com.unciv.logic.civilization.AlertType
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.civilization.PopupAlert
import com.unciv.models.translations.fillPlaceholders
import com.unciv.models.translations.tr
import com.unciv.ui.trade.LeaderIntroTable
import com.unciv.ui.utils.*
@ -91,10 +92,7 @@ class AlertPopup(val worldScreen: WorldScreen, val popupAlert: PopupAlert): Popu
worldScreen.shouldUpdate = true
close()
}
val liberateText = "Liberate (city returns to [originalOwner])".fillPlaceholders(city.foundingCiv)
add(liberateText.toTextButton().onClick(function = liberateAction)).row()
keyPressDispatcher['l'] = liberateAction
addGoodSizedLabel("Liberating a city returns it to its original owner, giving you a massive relationship boost with them!")
addLiberateOption(city.foundingCiv, liberateAction)
addSeparator()
}
@ -105,9 +103,7 @@ class AlertPopup(val worldScreen: WorldScreen, val popupAlert: PopupAlert): Popu
worldScreen.shouldUpdate = true
close()
}
add("Destroy".toTextButton().onClick(function = destroyAction)).row()
keyPressDispatcher['d'] = destroyAction
addGoodSizedLabel("Destroying the city instantly razes the city to the ground.").row()
addDestroyOption(destroyAction)
} else {
val annexAction = {
city.puppetCity(conqueringCiv)
@ -115,10 +111,7 @@ class AlertPopup(val worldScreen: WorldScreen, val popupAlert: PopupAlert): Popu
worldScreen.shouldUpdate = true
close()
}
add("Annex".toTextButton().onClick(function = annexAction)).row()
keyPressDispatcher['a'] = annexAction
addGoodSizedLabel("Annexed cities become part of your regular empire.").row()
addGoodSizedLabel("Their citizens generate 2x the unhappiness, unless you build a courthouse.").row()
addAnnexOption(annexAction)
addSeparator()
val puppetAction = {
@ -126,12 +119,7 @@ class AlertPopup(val worldScreen: WorldScreen, val popupAlert: PopupAlert): Popu
worldScreen.shouldUpdate = true
close()
}
add("Puppet".toTextButton().onClick(function = puppetAction) ).row()
keyPressDispatcher['p'] = puppetAction
addGoodSizedLabel("Puppeted cities do not increase your tech or policy cost, but their citizens generate 1.5x the regular unhappiness.").row()
addGoodSizedLabel("You have no control over the the production of puppeted cities.").row()
addGoodSizedLabel("Puppeted cities also generate 25% less Gold and Science.").row()
addGoodSizedLabel("A puppeted city can be annexed at any time.").row()
addPuppetOption(puppetAction)
addSeparator()
val razeAction = {
@ -244,7 +232,66 @@ class AlertPopup(val worldScreen: WorldScreen, val popupAlert: PopupAlert): Popu
addGoodSizedLabel(civInfo.nation.startIntroPart2).row()
add(getCloseButton("Let's begin!"))
}
AlertType.DiplomaticMarriage -> {
val city = worldScreen.gameInfo.getCities().first { it.id == popupAlert.value }
addGoodSizedLabel(city.name.tr() + ": " + "What would you like to do with the city?".tr(), 24) // Add name because there might be several cities
.padBottom(20f).row()
val marryingCiv = worldScreen.gameInfo.currentPlayerCiv
if (marryingCiv.isOneCityChallenger()) {
val destroyAction = {
city.destroyCity(overrideSafeties = true)
worldScreen.shouldUpdate = true
close()
}
addDestroyOption(destroyAction)
} else {
val annexAction = {
city.annexCity()
close()
}
addAnnexOption(annexAction)
addSeparator()
val puppetAction = {
city.isPuppet = true
city.cityStats.update()
worldScreen.shouldUpdate = true
close()
}
addPuppetOption(puppetAction)
}
}
}
}
private fun addDestroyOption(destroyAction: () -> Unit) {
add("Destroy".toTextButton().onClick(function = destroyAction)).row()
keyPressDispatcher['d'] = destroyAction
addGoodSizedLabel("Destroying the city instantly razes the city to the ground.").row()
}
private fun addAnnexOption(annexAction: () -> Unit) {
add("Annex".toTextButton().onClick(function = annexAction)).row()
keyPressDispatcher['a'] = annexAction
addGoodSizedLabel("Annexed cities become part of your regular empire.").row()
addGoodSizedLabel("Their citizens generate 2x the unhappiness, unless you build a courthouse.").row()
}
private fun addPuppetOption(puppetAction: () -> Unit) {
add("Puppet".toTextButton().onClick(function = puppetAction) ).row()
keyPressDispatcher['p'] = puppetAction
addGoodSizedLabel("Puppeted cities do not increase your tech or policy cost, but their citizens generate 1.5x the regular unhappiness.").row()
addGoodSizedLabel("You have no control over the the production of puppeted cities.").row()
addGoodSizedLabel("Puppeted cities also generate 25% less Gold and Science.").row()
addGoodSizedLabel("A puppeted city can be annexed at any time.").row()
}
private fun addLiberateOption(foundingCiv: String, liberateAction: () -> Unit) {
val liberateText = "Liberate (city returns to [originalOwner])".fillPlaceholders(foundingCiv)
add(liberateText.toTextButton().onClick(function = liberateAction)).row()
keyPressDispatcher['l'] = liberateAction
addGoodSizedLabel("Liberating a city returns it to its original owner, giving you a massive relationship boost with them!")
}
override fun close() {

View File

@ -99,6 +99,7 @@ Unless otherwise specified, all the following are from [the Noun Project](https:
* [Bayonet](https://thenounproject.com/term/bayonet/3101681/) By food lover for Carolean
* [Horse](https://thenounproject.com/search/?q=Horse&i=1023745) By Bakunetso Kaito for Cavalry
* [horse racing](https://thenounproject.com/antimso/uploads/?i=2427932) By Sergio Morozov for Cossack
* [Marching Band](https://thenounproject.com/term/marching-band/871426/) by Darrin Loeliger, US for Hussar
* [Artillery](https://thenounproject.com/search/?q=Artillery&i=1165261) By Creative Mania
* [Ship](https://thenounproject.com/term/ship/1594793/) By Aisyah for Ironclad
@ -274,6 +275,7 @@ Unless otherwise specified, all the following are from [the Noun Project](https:
* [Tower of Pisa](https://thenounproject.com/search/?q=leaning%20tower%20of%20pisa&i=1002578) By Pedro Santos
* [Himeji Castle](https://thenounproject.com/search/?q=himeji&i=1125277) By Chanut is Industries
* [Windmill](https://thenounproject.com/term/windmill/1705107/) By corpus delicti
* [Coffee](https://thenounproject.com/term/coffee/3954451/) by SURYANI, ID for Coffee House
* [Taj Mahal](https://thenounproject.com/term/taj-mahal/1907755/) By Felipe Alvarado
* [Observatory](https://thenounproject.com/term/observatory/1259/) By Nathan Driskell
* [Opera House](https://thenounproject.com/term/opera-house/446672/) By Xinh Studio
@ -549,6 +551,7 @@ Unless otherwise specified, all the following are from [the Noun Project](https:
* [Sun symbol black](https://en.wikiquote.org/wiki/File:Sun_symbol_black.svg) by Eddo for The Huns
* [Lion](https://thenounproject.com/search/?q=lion&i=76154) by Nikki Rodriguez for The Netherlands
* [Three Crowns](https://thenounproject.com/search/?q=three+crowns&i=1155972) by Daniel Falk for Sweden
* [Flag of Austria](https://thenounproject.com/term/flag-of-austria/3292053/) by Olena Panasovska, UA for Austria
## Promotions