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>
BIN
android/Images.Construction/BuildingIcons/Ceilidh Hall.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
android/Images.Construction/UnitIcons/Pictish Warrior.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
android/Images/NationIcons/Celts.png
Normal file
After Width: | Height: | Size: 8.6 KiB |
BIN
android/Images/UnitPromotionIcons/Pictish Courage.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 654 KiB After Width: | Height: | Size: 664 KiB |
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 1.0 MiB |
@ -669,6 +669,19 @@
|
||||
"requiredTech": "Acoustics",
|
||||
"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",
|
||||
"culture": 1,
|
||||
|
@ -347,7 +347,6 @@
|
||||
"Recklinghausen","Göttingen","Wolfsburg","Koblenz","Hildesheim","Erlangen"]
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
"name": "The Ottomans",
|
||||
"leaderName": "Suleiman I",
|
||||
@ -826,8 +825,44 @@
|
||||
"Tyana", "Gaza", "Kerkyra", "Phoenice", "Selymbria", "Sillyon", "Chrysopolis", "Vodena", "Caesarea", "Traianoupoli", "Constantia", "Athens",
|
||||
"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
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
@ -534,5 +534,9 @@
|
||||
{
|
||||
"name": "Ignore 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]"]
|
||||
}
|
||||
]
|
||||
|
@ -301,7 +301,7 @@
|
||||
"requiredTech": "Bronze Working",
|
||||
"obsoleteTech": "Civil Service",
|
||||
"upgradesTo": "Pikeman",
|
||||
"uniques": ["[+50]% Strength <vs [Mounted] units>","[+10] HP when healing"],
|
||||
"uniques": ["[+50]% Strength <vs [Mounted] units>", "[+10] HP when healing"],
|
||||
"attackSound": "metalhit"
|
||||
},
|
||||
{
|
||||
@ -319,7 +319,22 @@
|
||||
"-[1] Visibility Range", "Can only attack [City] units"],
|
||||
"promotions": ["Cover I"],
|
||||
"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",
|
||||
|
@ -7,7 +7,6 @@ import com.unciv.logic.map.RoadStatus
|
||||
import com.unciv.models.Counter
|
||||
import com.unciv.models.ruleset.Building
|
||||
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.UniqueType
|
||||
import com.unciv.models.ruleset.unit.BaseUnit
|
||||
@ -227,7 +226,7 @@ class CityStats(val cityInfo: CityInfo) {
|
||||
|
||||
if (unique.isOfType(UniqueType.StatsPerCity)
|
||||
&& cityInfo.matchesFilter(unique.params[1])
|
||||
&& unique.conditionalsApply(cityInfo.civInfo)
|
||||
&& unique.conditionalsApply(cityInfo.civInfo, cityInfo)
|
||||
) {
|
||||
stats.add(unique.stats)
|
||||
}
|
||||
|
@ -455,7 +455,7 @@ open class TileInfo {
|
||||
fun matchesFilter(filter: String, civInfo: CivilizationInfo? = null): Boolean {
|
||||
if (matchesTerrainFilter(filter, civInfo)) 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 {
|
||||
|
@ -43,17 +43,28 @@ class Unique(val text: String, val sourceObjectType: UniqueTarget? = null, val s
|
||||
condition: Unique,
|
||||
state: StateForConditionals
|
||||
): Boolean {
|
||||
return when (condition.placeholderText) {
|
||||
UniqueType.ConditionalNotWar.placeholderText -> state.civInfo?.isAtWar() == false
|
||||
UniqueType.ConditionalWar.placeholderText -> state.civInfo?.isAtWar() == true
|
||||
UniqueType.ConditionalSpecialistCount.placeholderText ->
|
||||
return when (condition.type) {
|
||||
UniqueType.ConditionalNotWar -> state.civInfo?.isAtWar() == false
|
||||
UniqueType.ConditionalWar -> state.civInfo?.isAtWar() == true
|
||||
UniqueType.ConditionalSpecialistCount ->
|
||||
state.cityInfo != null && state.cityInfo.population.getNumberOfSpecialists() >= condition.params[0].toInt()
|
||||
UniqueType.ConditionalHappy.placeholderText ->
|
||||
UniqueType.ConditionalHappy ->
|
||||
state.civInfo != null && state.civInfo.statsForNextTurn.happiness >= 0
|
||||
UniqueType.ConditionalVsCity.placeholderText ->
|
||||
UniqueType.ConditionalVsCity ->
|
||||
state.defender != null && state.defender.matchesCategory("City")
|
||||
UniqueType.ConditionalVsUnits.placeholderText ->
|
||||
UniqueType.ConditionalVsUnits ->
|
||||
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
|
||||
}
|
||||
}
|
||||
@ -62,16 +73,15 @@ 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) {
|
||||
if (!containsKey(unique.placeholderText)) this[unique.placeholderText] = ArrayList()
|
||||
this[unique.placeholderText]!!.add(unique)
|
||||
}
|
||||
|
||||
fun getUniques(placeholderText: String): Sequence<Unique> {
|
||||
val result = this[placeholderText]
|
||||
if (result == null) return sequenceOf()
|
||||
else return result.asSequence()
|
||||
return this[placeholderText]?.asSequence() ?: sequenceOf()
|
||||
}
|
||||
|
||||
fun getUniques(uniqueType: UniqueType) = getUniques(uniqueType.placeholderText)
|
||||
|
@ -90,6 +90,15 @@ enum class UniqueParameterType(val parameterName:String) {
|
||||
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 */
|
||||
SimpleTerrain("simpleTerrain") {
|
||||
private val knownValues = setOf("Elevated", "Water", "Land")
|
||||
|
@ -159,6 +159,9 @@ enum class UniqueType(val text:String, vararg targets: UniqueTarget) {
|
||||
// ConditionalAttacking("when attacking", UniqueTarget.Conditional),
|
||||
// ConditionalDefending("when defending", 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
|
||||
|
@ -218,7 +218,8 @@ object TranslationFileWriter {
|
||||
"non-fresh water",
|
||||
"Open Terrain",
|
||||
"Rough Terrain",
|
||||
"Natural Wonder"
|
||||
"Natural Wonder",
|
||||
"unimproved"
|
||||
)) }
|
||||
val tileImprovementMap = ruleset.tileImprovements.keys.toMutableSet().apply { add("Great Improvement") }
|
||||
val buildingMap = ruleset.buildings.keys.toMutableSet().apply { addAll(sequenceOf(
|
||||
|
@ -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
|
||||
* [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
|
||||
* [warrior](https://thenounproject.com/term/warrior/988830/) By DinosoftLab for Pictish Warrior (combined with Shamrock, see Promotions)
|
||||
|
||||
### 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
|
||||
* [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
|
||||
* [Ceilidh](https://thenounproject.com/term/ceilidh/403422/) By P Thanga Vignesh for Ceilidh Hall
|
||||
|
||||
### 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
|
||||
* [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
|
||||
* [Celtic Knot](https://thenounproject.com/term/celtic/168483/) by Ervin Bolat for the Celts
|
||||
|
||||
|
||||
## 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
|
||||
* [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
|
||||
* [Shamrock](https://thenounproject.com/term/shamrock/358507/) By P Thanga Vignesh for Pictish Courage
|
||||
|
||||
|
||||
## Religions
|
||||
|
||||
|