The Celtic People Reboot (#5367)

* The Celtic People Reboot

* Redid the Shamrock sword of the Pictish Warrior

* The Celtic People Reboot - one comment

Co-authored-by: Yair Morgenstern <yairm210@hotmail.com>
This commit is contained in:
SomeTroglodyte 2021-10-03 11:02:58 +02:00 committed by GitHub
parent a0f6596ee8
commit 71405b93aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 966 additions and 844 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 654 KiB

After

Width:  |  Height:  |  Size: 664 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

After

Width:  |  Height:  |  Size: 1.0 MiB

View File

@ -669,6 +669,19 @@
"requiredTech": "Acoustics", "requiredTech": "Acoustics",
"uniques": ["Destroyed when the city is captured"] "uniques": ["Destroyed when the city is captured"]
}, },
{
"name": "Ceilidh Hall",
"replaces": "Opera House",
"uniqueTo": "Celts",
"culture": 4,
"happiness": 3,
"specialistSlots": {"Artist": 1},
"hurryCostModifier": 10,
"requiredBuilding": "Amphitheater",
"maintenance": 2,
"requiredTech": "Acoustics",
"uniques": ["Destroyed when the city is captured"]
},
{ {
"name": "Sistine Chapel", "name": "Sistine Chapel",
"culture": 1, "culture": 1,

View File

@ -347,7 +347,6 @@
"Recklinghausen","Göttingen","Wolfsburg","Koblenz","Hildesheim","Erlangen"] "Recklinghausen","Göttingen","Wolfsburg","Koblenz","Hildesheim","Erlangen"]
}, },
{ {
"name": "The Ottomans", "name": "The Ottomans",
"leaderName": "Suleiman I", "leaderName": "Suleiman I",
@ -826,8 +825,44 @@
"Tyana", "Gaza", "Kerkyra", "Phoenice", "Selymbria", "Sillyon", "Chrysopolis", "Vodena", "Caesarea", "Traianoupoli", "Constantia", "Athens", "Tyana", "Gaza", "Kerkyra", "Phoenice", "Selymbria", "Sillyon", "Chrysopolis", "Vodena", "Caesarea", "Traianoupoli", "Constantia", "Athens",
"Patra", "Korinthos"] "Patra", "Korinthos"]
}, },
{
"name": "Celts",
"leaderName": "Boudicca",
"adjective": ["celtic"],
"startBias": ["Forest"],
"preferredVictoryType": "Domination",
"startIntroPart1": "Eternal glory and praise for you, fierce and vengeful Warrior Queen! In a time dominated by men, you not only secured your throne and sovereign rule, but also successfully defied the power of the Roman Empire. After suffering terrible punishment and humiliation at the hand of the Roman invaders, you rallied your people in a bloody and terrifying revolt. Legions fell under your chariot wheels and the city of London burned. While in the end the Romans retained ownership of the isles, you alone made Nero consider withdrawing all troops and leaving Britain forever.",
"startIntroPart2": "Oh sleeping lioness, your people desire that you rise and lead them again in the calling that is your namesake. Will you meet their challenge on the open field and lead the Celts to everlasting victory? Will you restore your lands and build an empire to stand the test of time?",
"declaringWar": "You shall stain this land no longer with your vileness! To arms, my countrymen. We ride to war!",
"attacked": "Traitorous man! The Celtic peoples will not stand for such wanton abuse and slander - I shall have your balls!",
"defeated": "Vile ruler, know you have won this war in name alone. Your cities lie buried and your troops defeated. I have my own victory.",
"introduction": "I am Boudicca, Queen of the Celts. Let no-one underestimate me!",
"tradeRequest": "Let us join our forces together and reap the rewards.",
"afterPeace": "Well played, fellow warrior.",
"neutralHello": "God has given good to you.",
"neutralLetsHearIt": ["We are all ears…","We are all ears…","Forward."],
"neutralNo": ["We must decline.","No.","We refuse."],
"neutralYes": ["Okay.","Sure, it shall be so.","Accepted."],
"hateHello": "Well?",
"hateLetsHearIt": ["Forward! Before I change my mind!","And?","Speak!"],
"hateNo": ["That's unacceptable!","A thousand times no!","Never!"],
"hateYes": ["Eugh! Fine then…","Disgusting! Okay then…","But if I have to…"],
"outerColor": [12,75,25],
"innerColor": [157,172,255],
"uniqueName": "Druidic Lore",
"uniques": ["[+1 Faith] [in all cities] <with [1] to [2] neighboring [unimproved] [Forest] tiles>",
"[+2 Faith] [in all cities] <with [3] to [6] neighboring [unimproved] [Forest] tiles>"],
"cities": ["Edinburgh","Dublin","Cardiff","Truro","Nantes","Douglas","Glasgow","Cork","Aberystwyth",
"Penzance","Rennes","Ramsey","Inverness","Limerick","Swansea","St. Ives","Brest","Peel","Aberdeen",
"Belfast","Caernarfon","Newquay","Saint-Nazaire","Castletown","Stirling","Galway","Conwy",
"St. Austell","Saint-Malo","Onchan","Dundee","Londonderry","Llanfairpwllgwyngyll","Falmouth","Lorient"]
// Llanfairpwllgwyngyll should actually be Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch
},

View File

@ -534,5 +534,9 @@
{ {
"name": "Ignore terrain cost", "name": "Ignore terrain cost",
"uniques": ["Ignores terrain cost"] "uniques": ["Ignores terrain cost"]
},
{
"name": "Pictish Courage", // only for Pictish Warrior and subsequent upgrades
"uniques": ["No movement cost to pillage", "+[20]% Strength in [Foreign Land]"]
} }
] ]

View File

@ -319,7 +319,22 @@
"-[1] Visibility Range", "Can only attack [City] units"], "-[1] Visibility Range", "Can only attack [City] units"],
"promotions": ["Cover I"], "promotions": ["Cover I"],
"attackSound": "throw" "attackSound": "throw"
} },
{
"name": "Pictish Warrior",
"unitType": "Sword",
"replaces": "Spearman",
"uniqueTo": "Celts",
"movement": 2,
"strength": 11,
"cost": 56,
"requiredTech": "Bronze Working",
"obsoleteTech": "Civil Service",
"upgradesTo": "Pikeman",
"uniques": ["Earn [50]% of killed [Military] unit's [Strength] as [Faith]"],
"promotions": ["Pictish Courage"],
"attackSound": "metalhit"
},
/* /*
{ {
"name": "Spearman", "name": "Spearman",

View File

@ -7,7 +7,6 @@ import com.unciv.logic.map.RoadStatus
import com.unciv.models.Counter import com.unciv.models.Counter
import com.unciv.models.ruleset.Building import com.unciv.models.ruleset.Building
import com.unciv.models.ruleset.ModOptionsConstants import com.unciv.models.ruleset.ModOptionsConstants
import com.unciv.models.ruleset.unique.StateForConditionals
import com.unciv.models.ruleset.unique.Unique import com.unciv.models.ruleset.unique.Unique
import com.unciv.models.ruleset.unique.UniqueType import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.ruleset.unit.BaseUnit import com.unciv.models.ruleset.unit.BaseUnit
@ -227,7 +226,7 @@ class CityStats(val cityInfo: CityInfo) {
if (unique.isOfType(UniqueType.StatsPerCity) if (unique.isOfType(UniqueType.StatsPerCity)
&& cityInfo.matchesFilter(unique.params[1]) && cityInfo.matchesFilter(unique.params[1])
&& unique.conditionalsApply(cityInfo.civInfo) && unique.conditionalsApply(cityInfo.civInfo, cityInfo)
) { ) {
stats.add(unique.stats) stats.add(unique.stats)
} }

View File

@ -455,7 +455,7 @@ open class TileInfo {
fun matchesFilter(filter: String, civInfo: CivilizationInfo? = null): Boolean { fun matchesFilter(filter: String, civInfo: CivilizationInfo? = null): Boolean {
if (matchesTerrainFilter(filter, civInfo)) return true if (matchesTerrainFilter(filter, civInfo)) return true
if (improvement != null && ruleset.tileImprovements[improvement]!!.matchesFilter(filter)) return true if (improvement != null && ruleset.tileImprovements[improvement]!!.matchesFilter(filter)) return true
return false return improvement == null && filter == "unimproved"
} }
fun matchesTerrainFilter(filter: String, observingCiv: CivilizationInfo? = null): Boolean { fun matchesTerrainFilter(filter: String, observingCiv: CivilizationInfo? = null): Boolean {

View File

@ -43,17 +43,28 @@ class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val s
condition: Unique, condition: Unique,
state: StateForConditionals state: StateForConditionals
): Boolean { ): Boolean {
return when (condition.placeholderText) { return when (condition.type) {
UniqueType.ConditionalNotWar.placeholderText -> state.civInfo?.isAtWar() == false UniqueType.ConditionalNotWar -> state.civInfo?.isAtWar() == false
UniqueType.ConditionalWar.placeholderText -> state.civInfo?.isAtWar() == true UniqueType.ConditionalWar -> state.civInfo?.isAtWar() == true
UniqueType.ConditionalSpecialistCount.placeholderText -> UniqueType.ConditionalSpecialistCount ->
state.cityInfo != null && state.cityInfo.population.getNumberOfSpecialists() >= condition.params[0].toInt() state.cityInfo != null && state.cityInfo.population.getNumberOfSpecialists() >= condition.params[0].toInt()
UniqueType.ConditionalHappy.placeholderText -> UniqueType.ConditionalHappy ->
state.civInfo != null && state.civInfo.statsForNextTurn.happiness >= 0 state.civInfo != null && state.civInfo.statsForNextTurn.happiness >= 0
UniqueType.ConditionalVsCity.placeholderText -> UniqueType.ConditionalVsCity ->
state.defender != null && state.defender.matchesCategory("City") state.defender != null && state.defender.matchesCategory("City")
UniqueType.ConditionalVsUnits.placeholderText -> UniqueType.ConditionalVsUnits ->
state.defender != null && state.defender.matchesCategory(condition.params[0]) state.defender != null && state.defender.matchesCategory(condition.params[0])
UniqueType.ConditionalNeighborTiles ->
state.cityInfo != null &&
state.cityInfo.getCenterTile().neighbors.count {
it.matchesFilter(condition.params[2], state.civInfo)
} in (condition.params[0].toInt())..(condition.params[1].toInt())
UniqueType.ConditionalNeighborTilesAnd ->
state.cityInfo != null &&
state.cityInfo.getCenterTile().neighbors.count {
it.matchesFilter(condition.params[2], state.civInfo) &&
it.matchesFilter(condition.params[3], state.civInfo)
} in (condition.params[0].toInt())..(condition.params[1].toInt())
else -> false else -> false
} }
} }
@ -63,15 +74,14 @@ class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val s
class UniqueMap: HashMap<String, ArrayList<Unique>>() { class UniqueMap: HashMap<String, ArrayList<Unique>>() {
//todo Once all untyped Uniques are converted, this should be HashMap<UniqueType, *>
fun addUnique(unique: Unique) { fun addUnique(unique: Unique) {
if (!containsKey(unique.placeholderText)) this[unique.placeholderText] = ArrayList() if (!containsKey(unique.placeholderText)) this[unique.placeholderText] = ArrayList()
this[unique.placeholderText]!!.add(unique) this[unique.placeholderText]!!.add(unique)
} }
fun getUniques(placeholderText: String): Sequence<Unique> { fun getUniques(placeholderText: String): Sequence<Unique> {
val result = this[placeholderText] return this[placeholderText]?.asSequence() ?: sequenceOf()
if (result == null) return sequenceOf()
else return result.asSequence()
} }
fun getUniques(uniqueType: UniqueType) = getUniques(uniqueType.placeholderText) fun getUniques(uniqueType: UniqueType) = getUniques(uniqueType.placeholderText)

View File

@ -90,6 +90,15 @@ enum class UniqueParameterType(val parameterName:String) {
return UniqueType.UniqueComplianceErrorSeverity.WarningOnly return UniqueType.UniqueComplianceErrorSeverity.WarningOnly
} }
}, },
TileFilter("tileFilter") {
private val knownValues = setOf("unimproved", "All Road", "Great Improvement")
override fun getErrorSeverity(parameterText: String, ruleset: Ruleset):
UniqueType.UniqueComplianceErrorSeverity? {
if (parameterText in knownValues) return null
if (ruleset.tileImprovements.containsKey(parameterText)) return null
return TerrainFilter.getErrorSeverity(parameterText, ruleset)
}
},
/** Used by NaturalWonderGenerator, only tests base terrain or a feature */ /** Used by NaturalWonderGenerator, only tests base terrain or a feature */
SimpleTerrain("simpleTerrain") { SimpleTerrain("simpleTerrain") {
private val knownValues = setOf("Elevated", "Water", "Land") private val knownValues = setOf("Elevated", "Water", "Land")

View File

@ -159,6 +159,9 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget) {
// ConditionalAttacking("when attacking", UniqueTarget.Conditional), // ConditionalAttacking("when attacking", UniqueTarget.Conditional),
// ConditionalDefending("when defending", UniqueTarget.Conditional), // ConditionalDefending("when defending", UniqueTarget.Conditional),
// ConditionalIntercepting("when intercepting", UniqueTarget.Conditional), // ConditionalIntercepting("when intercepting", UniqueTarget.Conditional),
ConditionalNeighborTiles("with [amount] to [amount] neighboring [tileFilter] tiles", UniqueTarget.Conditional),
ConditionalNeighborTilesAnd("with [amount] to [amount] neighboring [tileFilter] [tileFilter] tiles", UniqueTarget.Conditional),
; ;
/** For uniques that have "special" parameters that can accept multiple types, we can override them manually /** For uniques that have "special" parameters that can accept multiple types, we can override them manually

View File

@ -218,7 +218,8 @@ object TranslationFileWriter {
"non-fresh water", "non-fresh water",
"Open Terrain", "Open Terrain",
"Rough Terrain", "Rough Terrain",
"Natural Wonder" "Natural Wonder",
"unimproved"
)) } )) }
val tileImprovementMap = ruleset.tileImprovements.keys.toMutableSet().apply { add("Great Improvement") } val tileImprovementMap = ruleset.tileImprovements.keys.toMutableSet().apply { add("Great Improvement") }
val buildingMap = ruleset.buildings.keys.toMutableSet().apply { addAll(sequenceOf( val buildingMap = ruleset.buildings.keys.toMutableSet().apply { addAll(sequenceOf(

View File

@ -53,6 +53,7 @@ Unless otherwise specified, all the following are from [the Noun Project](https:
* [Spiked club](https://thenounproject.com/search/?q=club%20weapon&creator=1933477&i=831794) for Brute * [Spiked club](https://thenounproject.com/search/?q=club%20weapon&creator=1933477&i=831794) for Brute
* [Hoplite](https://www.flaticon.com/free-icon/hoplite_659126#term=hoplite&page=1&position=20) by Eucalyp for Immortal * [Hoplite](https://www.flaticon.com/free-icon/hoplite_659126#term=hoplite&page=1&position=20) by Eucalyp for Immortal
* [Slingshot](https://thenounproject.com/term/slingshot/9106/) by James Keuning for Slinger * [Slingshot](https://thenounproject.com/term/slingshot/9106/) by James Keuning for Slinger
* [warrior](https://thenounproject.com/term/warrior/988830/) By DinosoftLab for Pictish Warrior (combined with Shamrock, see Promotions)
### Classical Era ### Classical Era
@ -290,6 +291,7 @@ Unless otherwise specified, all the following are from [the Noun Project](https:
* [Mansion](https://www.flaticon.com/free-icon/mansion_509903#term=persian&page=1&position=19) by Freepik for Satrap's Court * [Mansion](https://www.flaticon.com/free-icon/mansion_509903#term=persian&page=1&position=19) by Freepik for Satrap's Court
* [Bullets](https://thenounproject.com/term/bullets/810156/) By Aldric Rodriguez for Arsenal * [Bullets](https://thenounproject.com/term/bullets/810156/) By Aldric Rodriguez for Arsenal
* [St. Petersburg](https://thenounproject.com/search/?q=kremlin&i=1569704) By Carpe Diem for Kremlin * [St. Petersburg](https://thenounproject.com/search/?q=kremlin&i=1569704) By Carpe Diem for Kremlin
* [Ceilidh](https://thenounproject.com/term/ceilidh/403422/) By P Thanga Vignesh for Ceilidh Hall
### Industrial Era ### Industrial Era
@ -561,6 +563,7 @@ Unless otherwise specified, all the following are from [the Noun Project](https:
* [Orthodox Cross](https://thenounproject.com/search/?q=orthodox&i=2069822) by Avana Vana for Byzantium * [Orthodox Cross](https://thenounproject.com/search/?q=orthodox&i=2069822) by Avana Vana for Byzantium
* [Iroquois](https://github.com/ravignir/5Hex-Tileset/blob/master/Images/NationIcons/Iroquois.png) by Ravignir for Iroquois * [Iroquois](https://github.com/ravignir/5Hex-Tileset/blob/master/Images/NationIcons/Iroquois.png) by Ravignir for Iroquois
* [Songhai](https://github.com/ravignir/5Hex-Tileset/blob/master/Images/NationIcons/Songhai.png) by Ravignir for Songhai * [Songhai](https://github.com/ravignir/5Hex-Tileset/blob/master/Images/NationIcons/Songhai.png) by Ravignir for Songhai
* [Celtic Knot](https://thenounproject.com/term/celtic/168483/) by Ervin Bolat for the Celts
## Promotions ## Promotions
@ -594,6 +597,8 @@ Unless otherwise specified, all the following are from [the Noun Project](https:
* [Slingshot](https://thenounproject.com/term/slingshot/9106/) by James Keuning for Slinger Withdraw * [Slingshot](https://thenounproject.com/term/slingshot/9106/) by James Keuning for Slinger Withdraw
* [Anchor](https://thenounproject.com/term/anchor/676586) by Gregor Cresnar for Amphibious * [Anchor](https://thenounproject.com/term/anchor/676586) by Gregor Cresnar for Amphibious
* [survival knife](https://thenounproject.com/search/?q=survival&i=2663392) by b faris for Survivalism * [survival knife](https://thenounproject.com/search/?q=survival&i=2663392) by b faris for Survivalism
* [Shamrock](https://thenounproject.com/term/shamrock/358507/) By P Thanga Vignesh for Pictish Courage
## Religions ## Religions