Merge branch 'master' into master

This commit is contained in:
divizdev 2019-04-14 21:22:14 +03:00 committed by GitHub
commit 8fe889dc96
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
48 changed files with 840 additions and 527 deletions

View file

@ -33,6 +33,7 @@ All the following are from [the Noun Project](https://thenounproject.com) licenc
* [Catapult](https://thenounproject.com/search/?q=Spear&i=1233840) By Jakub Ukrop * [Catapult](https://thenounproject.com/search/?q=Spear&i=1233840) By Jakub Ukrop
* [Unloaded Crossbow](https://thenounproject.com/term/unloaded-crossbow/815992/) By Hamish as Ballista * [Unloaded Crossbow](https://thenounproject.com/term/unloaded-crossbow/815992/) By Hamish as Ballista
* [Sword](https://thenounproject.com/search/?q=Sword&i=1215443) By Guilherme Furtado for Swordsman * [Sword](https://thenounproject.com/search/?q=Sword&i=1215443) By Guilherme Furtado for Swordsman
* [Roman Helmet](https://thenounproject.com/search/?q=legion&i=440134) By parkjisun for Legion
* [Horse](https://thenounproject.com/search/?q=Horse&i=1373793) By AFY Studio for Horseman * [Horse](https://thenounproject.com/search/?q=Horse&i=1373793) By AFY Studio for Horseman
* [Horse Head](https://thenounproject.com/search/?q=Cavalry&i=374037) By Juan Pablo Bravo for Companion Cavalry * [Horse Head](https://thenounproject.com/search/?q=Cavalry&i=374037) By Juan Pablo Bravo for Companion Cavalry
@ -55,6 +56,7 @@ All the following are from [the Noun Project](https://thenounproject.com) licenc
* [Black powder musket](https://thenounproject.com/term/black-powder-musket/1202078/) By Jarem Fyre for Minuteman * [Black powder musket](https://thenounproject.com/term/black-powder-musket/1202078/) By Jarem Fyre for Minuteman
* [Rapier](https://thenounproject.com/search/?q=musketeer&i=819822) By Hamish for Musketeer * [Rapier](https://thenounproject.com/search/?q=musketeer&i=819822) By Hamish for Musketeer
* [Ship](https://thenounproject.com/term/ship/1293899/) By Orin Zuu for Frigate * [Ship](https://thenounproject.com/term/ship/1293899/) By Orin Zuu for Frigate
* [Ship](https://thenounproject.com/search/?q=ship&i=800131) By Mungang Kim for Ship of the Line
* [Lance](https://thenounproject.com/search/?q=Lance&i=440122) By parkjisun for Lancer * [Lance](https://thenounproject.com/search/?q=Lance&i=440122) By parkjisun for Lancer
### Industrial ### Industrial
@ -67,6 +69,7 @@ All the following are from [the Noun Project](https://thenounproject.com) licenc
### Modern ### Modern
* [Helmet](https://thenounproject.com/term/helmet/25216/) By Daniel Turner for Great War Infantry * [Helmet](https://thenounproject.com/term/helmet/25216/) By Daniel Turner for Great War Infantry
* [Cap](https://thenounproject.com/search/?q=kepi&i=950267) By Creative Mania for Foreign Legion
* [Tank](https://thenounproject.com/term/tank/1287510/) By corpus delicti for Landship * [Tank](https://thenounproject.com/term/tank/1287510/) By corpus delicti for Landship
* [Warship](https://thenounproject.com/term/warship/1597474/) By zidney for Destroyer * [Warship](https://thenounproject.com/term/warship/1597474/) By zidney for Destroyer
* [Battleship](https://thenounproject.com/search/?q=battleship&i=1986807) By Vitaliy Gorbachev, KZ for Battleship * [Battleship](https://thenounproject.com/search/?q=battleship&i=1986807) By Vitaliy Gorbachev, KZ for Battleship
@ -136,6 +139,7 @@ All the following are from [the Noun Project](https://thenounproject.com) licenc
* [Storehouse](https://thenounproject.com/term/storehouse/966786/) By Pedro Santos for Granary * [Storehouse](https://thenounproject.com/term/storehouse/966786/) By Pedro Santos for Granary
* [Great Wall Of China](https://thenounproject.com/term/great-wall-of-china/146039/) By Arthur Shlain for Walls * [Great Wall Of China](https://thenounproject.com/term/great-wall-of-china/146039/) By Arthur Shlain for Walls
* [Markadan Tower](https://thenounproject.com/search/?q=fortification&i=2107694) by Vectors Market for Walls of Babylon
* [Block](https://thenounproject.com/term/block/1711553/) By Monjin Friends for Stone Works * [Block](https://thenounproject.com/term/block/1711553/) By Monjin Friends for Stone Works
* [korean palace](https://thenounproject.com/term/korean-palace/1797542/) By 1516 for Palace * [korean palace](https://thenounproject.com/term/korean-palace/1797542/) By 1516 for Palace
* [Obelisk](https://thenounproject.com/term/obelisk/749104/) By Eliricon for Monument * [Obelisk](https://thenounproject.com/term/obelisk/749104/) By Eliricon for Monument
@ -153,6 +157,7 @@ All the following are from [the Noun Project](https://thenounproject.com) licenc
* [Anubis](https://thenounproject.com/term/anubis/1080090/) By Carpe Diem for Burial Tomb * [Anubis](https://thenounproject.com/term/anubis/1080090/) By Carpe Diem for Burial Tomb
* [Parthenon](https://thenounproject.com/term/parthenon/493272/) By Christopher T. Howlett for The Oracle * [Parthenon](https://thenounproject.com/term/parthenon/493272/) By Christopher T. Howlett for The Oracle
* [Stadium](https://thenounproject.com/term/stadium/1500595/) By sandra for Colloseum * [Stadium](https://thenounproject.com/term/stadium/1500595/) By sandra for Colloseum
* [Terracotta Army](https://thenounproject.com/search/?q=terracotta&i=2306346) By Supalerk Laipawat
* [Stadium](https://thenounproject.com/term/stadium/1152530/) By Creaticca Creative Agency for Circus Maximus * [Stadium](https://thenounproject.com/term/stadium/1152530/) By Creaticca Creative Agency for Circus Maximus
* [Market](https://thenounproject.com/term/market/1723050/) By sofi * [Market](https://thenounproject.com/term/market/1723050/) By sofi
* [Bazaar](https://thenounproject.com/term/bazaar/902288/) By Tokka Elkholy * [Bazaar](https://thenounproject.com/term/bazaar/902288/) By Tokka Elkholy
@ -187,6 +192,7 @@ All the following are from [the Noun Project](https://thenounproject.com) licenc
* [Forbidden City](https://thenounproject.com/term/forbidden-city/1797540/) By 1516 * [Forbidden City](https://thenounproject.com/term/forbidden-city/1797540/) By 1516
* [Theatre](https://thenounproject.com/term/theatre/1780401/) By b farias * [Theatre](https://thenounproject.com/term/theatre/1780401/) By b farias
* [Tower of Pisa](https://thenounproject.com/search/?q=leaning%20tower%20of%20pisa&i=1002578) By Pedro Santos * [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 * [Windmill](https://thenounproject.com/term/windmill/1705107/) By corpus delicti
* [Taj Mahal](https://thenounproject.com/term/taj-mahal/1907755/) By Felipe Alvarado * [Taj Mahal](https://thenounproject.com/term/taj-mahal/1907755/) By Felipe Alvarado
* [Observatory](https://thenounproject.com/term/observatory/1259/) By Nathan Driskell * [Observatory](https://thenounproject.com/term/observatory/1259/) By Nathan Driskell
@ -211,6 +217,7 @@ All the following are from [the Noun Project](https://thenounproject.com) licenc
* [Statue of Liberty](https://thenounproject.com/search/?q=statue%20of%20liberty&i=1801199) By 1516 * [Statue of Liberty](https://thenounproject.com/search/?q=statue%20of%20liberty&i=1801199) By 1516
* [Christ the redeemer](https://thenounproject.com/term/christ-the-redeemer/56112/) By Stefan Spieler for Cristo Redentor * [Christ the redeemer](https://thenounproject.com/term/christ-the-redeemer/56112/) By Stefan Spieler for Cristo Redentor
* [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
* [Neuschwanstein](https://thenounproject.com/search/?q=Neuschwanstein&i=2107683) By Vectors Market
### Information Era ### Information Era

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 281 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 B

File diff suppressed because it is too large Load diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 947 KiB

After

Width:  |  Height:  |  Size: 979 KiB

View file

@ -82,25 +82,23 @@
hurryCostModifier:25, hurryCostModifier:25,
requiredTech:"Masonry" requiredTech:"Masonry"
}, },
/*
{ {
name:"Walls of Babylon", name:"Walls of Babylon",
replaces:"Walls", replaces:"Walls",
cost:65,
uniqueTo:"Babylon", uniqueTo:"Babylon",
cityStrength:6, cityStrength:6,
cityHealth:100, cityHealth:100,
hurryCostModifier:25, hurryCostModifier:25,
requiredTech:"Masonry" requiredTech:"Masonry"
//Babylonian unique building that replaces Walls.
}, },
*/
{ {
name:"The Pyramids", name:"The Pyramids",
culture:1, culture:1,
greatPersonPoints:{production:1}, greatPersonPoints:{production:1},
isWonder:true, isWonder:true,
uniques:["Worker construction increased 25%","Provides 2 free workers"], uniques:["Worker construction increased 25%","Provides 2 free workers"],
requiredTech:"Mathematics" requiredTech:"Masonry"
}, },
{ {
name:"Barracks", name:"Barracks",
@ -116,7 +114,7 @@
greatPersonPoints:{gold:1}, greatPersonPoints:{gold:1},
isWonder:true, isWonder:true,
uniques:["Can only be built in coastal cities", "+1 gold from worked water tiles in city"], uniques:["Can only be built in coastal cities", "+1 gold from worked water tiles in city"],
requiredTech:"Mathematics" requiredTech:"Iron Working"
}, },
{ {
name:"Krepost", name:"Krepost",
@ -180,6 +178,12 @@
hurryCostModifier:25, hurryCostModifier:25,
requiredTech:"Construction" requiredTech:"Construction"
}, },
{
name:"Terracotta Army",
culture:6,
isWonder:true,
requiredTech:"Construction"
},
{ {
name:"Temple", name:"Temple",
culture:3, culture:3,
@ -452,6 +456,15 @@
uniques:["Free Great Person"] uniques:["Free Great Person"]
requiredTech:"Printing Press" requiredTech:"Printing Press"
}, },
{
name:"Himeji Castle",
culture:1,
isWonder:true,
greatPersonPoints:{production:2}
providesFreeBuilding:"Castle",
uniques:["+15% combat strength for units fighting in friendly territory"] // todo
requiredTech:"Gunpowder"
},
{ {
name:"Museum", name:"Museum",
culture:5, culture:5,
@ -615,6 +628,15 @@
uniques:["Defensive buildings in all cities are 25% more effective"], uniques:["Defensive buildings in all cities are 25% more effective"],
requiredTech:"Railroad" requiredTech:"Railroad"
}, },
{
name:"Neuschwanstein",
happiness:2,
culture:4,
gold:6,
isWonder:true,
uniques:["+1 happiness, +2 culture and +3 gold from every Castle"],
requiredTech:"Railroad"
},
// Information Era // Information Era

View file

@ -303,6 +303,8 @@
mainColor:[ 41,83,42], mainColor:[ 41,83,42],
secondaryColor:[146,221,9], secondaryColor:[146,221,9],
uniqueName:"Trade Caravans",
unique:"+1 Gold from each Trade Route, Oil resources provide double quantity"
cities:["Mecca","Medina","Damascus","Baghdad","Najran","Kufah","Basra","Khurasan","Anjar","Fustat", cities:["Mecca","Medina","Damascus","Baghdad","Najran","Kufah","Basra","Khurasan","Anjar","Fustat",
"Aden","Yamama","Muscat","Mansura","Bukhara","Fez","Shiraz","Merw","Balkh","Mosul", "Aden","Yamama","Muscat","Mansura","Bukhara","Fez","Shiraz","Merw","Balkh","Mosul",
"Aydab","Bayt","Suhar","Taif","Hama","Tabuk","Sana'a","Shihr","Tripoli","Tunis"] "Aydab","Bayt","Suhar","Taif","Hama","Tabuk","Sana'a","Shihr","Tripoli","Tunis"]

View file

@ -352,8 +352,8 @@
leaderName:"Oda Nobunaga", leaderName:"Oda Nobunaga",
adjective:["giapponese"], adjective:["giapponese"],
startIntroPart1: "Tu sia benedetto, nobile Oda Nobunaga, signore del Giappone, la terra del Sol Levante! Possa tu camminare a lungo in mezzo ai suoi meravigliosi boccioli di ciliegio. I giapponesi sono un popolo isolano, fiero e pio con una ricca cultura artistica e letteraria. La tua civiltà esiste per migliaia di anni, anni di sanguinose lotte, espansioni ed isolazioni, di grandi ricchezze e povertà. Oltre alla loro prodezza sul campo di battaglia, il tuo popolo è abile anche nell'industria, e le loro innovazioni tecnologiche e le loro grandi fabbriche sono l'invidia degli altri popoli in tutto il globo." startIntroPart1: "Salute a te, nobile Oda Nobunaga, sovrano del Giappone, la terra del Sol Levante, dove sorge il Sole! Possa tu a lungo passeggiare in mezzo ai suoi prati in fiore. I giapponesi sono un popolo isolano, fiero e pio, dalla ricca cultura artistica e letteraria. La tua civiltà è millenaria. Sono stati anni di lotte sanguinose, di espansioni ed isolamenti, di grandi ricchezze e povertà. Oltre alla sua prodezza sul campo di battaglia, il tuo popolo può anche vantare una stupefacente operosità. La sua superiorità tecnologiche e le sue grandiose fabbriche sono l'invidia degli altri popoli di tutte le latitudini."
startIntroPart2: "Leggendario damiyo, prenderai le redini del destino? Porterai alla tua famiglia e al tuo popolo l'onore e la gloria che meritano? Alzerai di nuovo la tua spada e marcerai verso il trionfo? Riuscirai a plasmare una civiltà in grado di superare la prova del tempo?" startIntroPart2: "O leggendario damiyo, prenderai in mano le redini del destino? Porterai alla tua famiglia e al tuo popolo l'onore e la gloria che meritano? Alzerai di nuovo la tua spada e marcerai verso il trionfo? Riuscirai a plasmare una civiltà in grado di superare la prova del tempo?"
declaringWar:"Come samurai siamo gente onesta, e noi troviamo onesto volerti esprimere la nostra intenzione di cancellarti dalla faccia della terra con questo messaggio." declaringWar:"Come samurai siamo gente onesta, e noi troviamo onesto volerti esprimere la nostra intenzione di cancellarti dalla faccia della terra con questo messaggio."
attacked:"Fatti pure avanti! Il kamikaze (vento divino) ci proteggerà, e tu cadrai, come altri prima di te!" attacked:"Fatti pure avanti! Il kamikaze (vento divino) ci proteggerà, e tu cadrai, come altri prima di te!"

View file

@ -29,14 +29,6 @@
Simplified_Chinese:"下一回合" Simplified_Chinese:"下一回合"
Portuguese:"Proximo turno" Portuguese:"Proximo turno"
Japanese:"次のターン" Japanese:"次のターン"
Polish:"Następna tura"
Indonesian:"Giliran berikutnya"
Philippino:"Susunod na pagliko"
Czech:"Další otočení"
Slovak:"Ďalšie otočenie"
Sloven:"Naslednji zavoj"
Croatian:"Sljedeći red"
Danish:"Næste tur"
} }
"Working...":{ // Displayed when next turn is being...turned "Working...":{ // Displayed when next turn is being...turned
@ -194,7 +186,7 @@
Dutch:"Verbetering bouwen" Dutch:"Verbetering bouwen"
Spanish:"Construir mejora" Spanish:"Construir mejora"
Simplified_Chinese:"建造建筑" Simplified_Chinese:"建造建筑"
Portuguese:"Construir melhoria" Portuguese:"Construir melhoria"
Japanese:"構造改善" Japanese:"構造改善"
} }
@ -725,7 +717,7 @@
} }
"Worked tiles":{ "Worked tiles":{
Italian:"celle sfruttate" Italian:"Celle sfruttate"
Russian:"обработанные клетки" Russian:"обработанные клетки"
French:"cases exploités" French:"cases exploités"
Romanian:"celule lucrate" Romanian:"celule lucrate"
@ -2517,7 +2509,7 @@
German:"Dschungel abholzen" German:"Dschungel abholzen"
} }
"Remove Marsh":{ "Remove Marsh":{
Italian:"Rimuovi palude" Italian:"Bonifica palude"
Russian:"Осушить болото" Russian:"Осушить болото"
French:"Assécher le marais" French:"Assécher le marais"
Romanian:"Asanează mlaștina" Romanian:"Asanează mlaștina"
@ -4052,7 +4044,7 @@
// Policy picker screen // Policy picker screen
"You have entered the [newEra] era!":{ "You have entered the [newEra] era!":{
Italian:"Sei entrato in una nuova era, [newEra]!" Italian:"Sei entrato in una nuova era, l'[newEra]!" //[newEra] not translated in Italian
Russian:"Вы вошли в эпоху [newEra]!" Russian:"Вы вошли в эпоху [newEra]!"
French:"Vous êtes entré dans l'ère [newEra]!" French:"Vous êtes entré dans l'ère [newEra]!"
Romanian:"Ai intrat în epoca [newEra]!" Romanian:"Ai intrat în epoca [newEra]!"
@ -4261,6 +4253,10 @@
Russian:"заменяет" Russian:"заменяет"
} }
"[resourceName] not required":{
Italian:"Risorsa [resourceName] non richiesta"
}
"National ability":{ // the unique ability that each nation has "National ability":{ // the unique ability that each nation has
Italian:"Abilità della civiltà" Italian:"Abilità della civiltà"
Romanian:"Abilitate a națiunii" Romanian:"Abilitate a națiunii"
@ -5030,7 +5026,7 @@
German:"Name" German:"Name"
} }
"Closest city":{ "Closest city":{
Italian:"La città più vicina" Italian:"Città più vicina"
Russian:"Ближайший город" Russian:"Ближайший город"
French:"Ville la plus proche" French:"Ville la plus proche"
Romanian:"Cel mai apropiat oraș" Romanian:"Cel mai apropiat oraș"
@ -5172,6 +5168,9 @@
Portuguese:"Muralhas" Portuguese:"Muralhas"
German:"Mauern" German:"Mauern"
} }
"Walls of Babylon":{
Italian:"Mura di Babilonia"
}
"The Pyramids":{ "The Pyramids":{
Italian:"Grandi Piramidi" Italian:"Grandi Piramidi"
@ -5236,8 +5235,12 @@
French:"Cout d'acquisition en or et en culture de nouvelle cases réduit de 25% dans cette ville" French:"Cout d'acquisition en or et en culture de nouvelle cases réduit de 25% dans cette ville"
} }
"Colossus":{} "Colossus":{
"+1 gold from worked water tiles in city":{} Italian:"Colosso"
}
"+1 gold from worked water tiles in city":{
Italian:"+1 Oro per ogni risorsa anfibia sfruttata dalla città."
}
"Temple":{ "Temple":{
Italian:"Tempio" Italian:"Tempio"
@ -5422,6 +5425,11 @@
Portuguese:"Coliseu" Portuguese:"Coliseu"
German:"Collosseum" German:"Collosseum"
} }
"Terracotta Army":{
Italian:"Esercito di terracotta"
}
"Market":{ "Market":{
Italian:"Mercato" Italian:"Mercato"
Russian:"Рынок" Russian:"Рынок"
@ -5560,8 +5568,12 @@
Portuguese:"40% da comida é mantida depois de um novo cidadão nascer" Portuguese:"40% da comida é mantida depois de um novo cidadão nascer"
} }
"Great Wall":{} "Great Wall":{
"Enemy land units must spend 1 extra movement point when inside your territory (obsolete upon Dynamite)":{} Italian:"Grande Muraglia"
}
"Enemy land units must spend 1 extra movement point when inside your territory (obsolete upon Dynamite)":{
Italian:"Le unità nemiche impiegano un punto Movimento extra se all'interno del tuo territorio (diventa obsoleta con la Dinamite)."
}
"Workshop":{ "Workshop":{
Italian:"Bottega" Italian:"Bottega"
@ -5687,19 +5699,6 @@
Simplified_Chinese:"购买新地块的成本降低了25%" Simplified_Chinese:"购买新地块的成本降低了25%"
Portuguese:"Custa de comprar novos terrenos reduzido em 25%" Portuguese:"Custa de comprar novos terrenos reduzido em 25%"
} }
/*
//New Wonder projected: Himeji Castle! Free Castle in City which possessed it, and +15% Strenght for units in friendly territory
//Also, +1 Culture and +2 Great Engineer Points. Requires Gunpowder
"Himeji Castle":{
Italian:"Castello di Himeji"
French:"Château d'Himeji"
}
"+15% Combat Strenght for units fighting in friendly territory":{
Italian:"+15% Forza per le unità che combattono in territorio amico"
French:"+15% force pour toutes les unités dans un territoire allié"
}
*/
"Porcelain Tower":{ "Porcelain Tower":{
Italian:"Torre di Porcellana" Italian:"Torre di Porcellana"
@ -5834,8 +5833,7 @@
Spanish:"La Torre Inclinada De Pizza" Spanish:"La Torre Inclinada De Pizza"
German:"Schiefer Turm von Pisa" German:"Schiefer Turm von Pisa"
French:"Tour de Pise" French:"Tour de Pise"
} }
"Free Great Person":{ "Free Great Person":{
Italian:"Ottieni un Grande Personaggio gratuito" Italian:"Ottieni un Grande Personaggio gratuito"
Romanian:"Persoană mare gratuită" Romanian:"Persoană mare gratuită"
@ -5844,6 +5842,13 @@
French:"Personnage illustre gratuit" French:"Personnage illustre gratuit"
} }
"Himeji Castle":{
Italian:"Castello di Himeji"
}
"+15% combat strength for units fighting in friendly territory":{
Italian:"+15% Forza per le unità che combattono in territorio amico"
}
"Taj Mahal":{ "Taj Mahal":{
Italian:"Taj Mahal" //same in Italian Italian:"Taj Mahal" //same in Italian
Russian:"Тадж-Махал" Russian:"Тадж-Махал"
@ -6036,6 +6041,13 @@
Italian:"+25% efficacia delle strutture difensive in tutte le città" Italian:"+25% efficacia delle strutture difensive in tutte le città"
} }
"Neuschwanstein":{
Italian:"Castello di Neuschwanstein"
}
"+1 happiness, +2 culture and +3 gold from every Castle":{
Italian:"+1 Felicitù, +2 Cultura e +3 Oro per ogni Castello"
}
"Military Academy":{ "Military Academy":{
Italian:"Accademia militare" Italian:"Accademia militare"
Russian:"Военная академия" Russian:"Военная академия"
@ -6470,6 +6482,7 @@
Portuguese:"Espadachin" // may replace with guerreiro com espada if nescessary Portuguese:"Espadachin" // may replace with guerreiro com espada if nescessary
German:"Schwertkämpfer" German:"Schwertkämpfer"
} }
"Legion":{ "Legion":{
Italian:"Legionario" Italian:"Legionario"
Romanian:"Legionar" Romanian:"Legionar"
@ -6477,7 +6490,14 @@
Simplified_Chinese:"古罗马军团" Simplified_Chinese:"古罗马军团"
German:"Legionär" German:"Legionär"
French:"Légion" French:"Légion"
} // Rome unique }
"Can construct roads":{
Italian:"Può costruire Strade"
}
"Construct road":{
Italian:"Costruisci Strada"
} // for unit action button
"Horseman":{ "Horseman":{
Italian:"Guerriero a cavallo" //wrong translation by Smashfanful Italian:"Guerriero a cavallo" //wrong translation by Smashfanful
Russian:"Всадник" Russian:"Всадник"
@ -6587,6 +6607,14 @@
German:"Kamel-Bogenschütze" German:"Kamel-Bogenschütze"
French:"Archer méhariste" French:"Archer méhariste"
} }
"Samurai":{
Italian:"Samurai" //Same as in Italian
}
"Combat very likely to create Great Generals":{
Italian:"Può generare un Grande Generale combattendo"
}
// Renaissance units // Renaissance units
"Caravel":{ "Caravel":{
@ -6701,6 +6729,7 @@
Portuguese:"Cavalaria" Portuguese:"Cavalaria"
German:"Kavallerie" German:"Kavallerie"
} }
"Cossack":{ "Cossack":{
Italian:"Cosacco" Italian:"Cosacco"
Romanian:"Cazac" Romanian:"Cazac"
@ -6709,7 +6738,7 @@
Russian:"Казаки" Russian:"Казаки"
German:"Kosak" German:"Kosak"
French:"Cosaque" French:"Cosaque"
} // Russia unique }
"Artillery":{ "Artillery":{
Italian:"Artiglieria" Italian:"Artiglieria"
@ -6732,7 +6761,7 @@
German:"Panzerschiff" German:"Panzerschiff"
} }
// Modern units (do these, yes) // Modern units
"Landship":{ "Landship":{
Italian:"Nave di terra" Italian:"Nave di terra"
Romanian:"Vehicul terestru" Romanian:"Vehicul terestru"
@ -6742,6 +6771,7 @@
German:"Landschiff" German:"Landschiff"
French:"Véhicule terrestre" //official translation but ugly French:"Véhicule terrestre" //official translation but ugly
} }
"Great War Infantry":{ "Great War Infantry":{
Italian:"Fante della Grande Guerra" Italian:"Fante della Grande Guerra"
Romanian:"Infanteria Marelui Război" Romanian:"Infanteria Marelui Război"
@ -6751,6 +6781,19 @@
German:"Weltkriegs Infanterie" German:"Weltkriegs Infanterie"
French:"Infanterie de la grande guerre" French:"Infanterie de la grande guerre"
} }
"Foreign Legion":{
Italian:"Legione Straniera"
}
"+20% bonus outside friendly territory":{
Italian:"+20% Forza fuori da territorio amico"
}
"Foreign Land":{ // for battle table combat percentage
Italian:"Terra Straniera"
}
"Destroyer":{ "Destroyer":{
Italian:"Cacciatorpediniere" Italian:"Cacciatorpediniere"
Romanian:"Distrugător" Romanian:"Distrugător"
@ -8202,7 +8245,7 @@
Russian:"Вы одержали победу завоевания!" Russian:"Вы одержали победу завоевания!"
} }
"One more turn...!":{ "One more turn...!":{
Italian:"Solo un altro turno..." Italian:"Aspetta! Solo un altro turno..."
German:"Nur noch eine Runde..." German:"Nur noch eine Runde..."
French:"Un autre tour... !" French:"Un autre tour... !"
Russian:"Еще один ход...!" Russian:"Еще один ход...!"
@ -8376,10 +8419,17 @@
German:"Angriff" German:"Angriff"
French:"Charge" French:"Charge"
} }
"Bonus vs wounded units 33%":{ "Bonus vs wounded units 33%":{
Italian:"+33% forza contro unità ferite" Italian:"+33% forza contro unità ferite"
French:"+33% force contre les unités montées" French:"+33% force contre les unités montées"
Russian:"Бонус против раненых 33%" Russian:"Бонус против раненых 33%"
}
"wounded units":{
Italian:"unità ferite"
French:"unités montées"
} }
"Mobility":{ "Mobility":{
Italian:"Mobilità" Italian:"Mobilità"
@ -8663,4 +8713,7 @@
Italian:"Editor mappe" Italian:"Editor mappe"
Russian:"Редактор карт" Russian:"Редактор карт"
} }
"Language":{
Italian:"Lingua"
}
} }

View file

@ -73,8 +73,8 @@
{ {
name:"Maori Warrior", name:"Maori Warrior",
unitType:"Melee", unitType:"Melee",
uniqueTo:"Aztec", uniqueTo:"Polynesia",
replaces:"Polynesia", replaces:"Warrior",
movement:2, movement:2,
strength:8, strength:8,
cost: 40, cost: 40,
@ -85,6 +85,19 @@
attackSound:"nonmetalhit" attackSound:"nonmetalhit"
//Polynesian unique unit. All Units near him have -10% strenght //Polynesian unique unit. All Units near him have -10% strenght
}, },
{
name:"Brute",
unitType:"Melee",
uniqueTo:"Barbarian",
replaces:"Warrior",
movement:2,
strength:8,
cost: 20,
obsoleteTech:"Metal Casting",
upgradesTo:"Swordsman",
attackSound:"nonmetalhit"
//Barbarian unique unit
},
*/ */
{ {
name:"Archer", name:"Archer",
@ -205,7 +218,6 @@
hurryCostModifier:20, hurryCostModifier:20,
attackSound:"arrow" attackSound:"arrow"
}, },
/*
{ {
name:"War Chariot", name:"War Chariot",
unitType:"Ranged", unitType:"Ranged",
@ -221,8 +233,8 @@
uniques:["No defensive terrain bonus","Rough terrain penalty"], uniques:["No defensive terrain bonus","Rough terrain penalty"],
hurryCostModifier:20, hurryCostModifier:20,
attackSound:"arrow" attackSound:"arrow"
//This is the Egyptian unique unit. It replaces Chariot Archer, moves faster and needs no horses.
}, },
/*
{ {
name:"War Elephant", name:"War Elephant",
unitType:"Ranged", unitType:"Ranged",
@ -333,7 +345,6 @@
hurryCostModifier:20, hurryCostModifier:20,
attackSound:"metalhit" attackSound:"metalhit"
}, },
/*
{ {
name:"Legion", name:"Legion",
unitType:"Melee", unitType:"Melee",
@ -346,10 +357,11 @@
upgradesTo:"Longswordsman", upgradesTo:"Longswordsman",
obsoleteTech:"Steel", obsoleteTech:"Steel",
requiredResource:"Iron", requiredResource:"Iron",
uniques:["Can construct roads"]
hurryCostModifier:20, hurryCostModifier:20,
attackSound:"metalhit" attackSound:"metalhit"
//Roman unique unit. It is stronger than Swordsman. It should also build roads (maybe railroads, too). It takes more to Steel to make it obsolete.
}, },
/*
{ {
name:"Mohawk Warrior", name:"Mohawk Warrior",
unitType:"Melee", unitType:"Melee",
@ -431,9 +443,8 @@
hurryCostModifier:20, hurryCostModifier:20,
attackSound:"arrow" attackSound:"arrow"
}, },
/*
{ {
name:"Chu-ko-nu", name:"Chu-Ko-Nu",
unitType:"Ranged", unitType:"Ranged",
uniqueTo:"China", uniqueTo:"China",
movement:2, movement:2,
@ -444,11 +455,10 @@
requiredTech:"Machinery", requiredTech:"Machinery",
upgradesTo:"Gatling Gun", upgradesTo:"Gatling Gun",
obsoleteTech:"Industrialization", obsoleteTech:"Industrialization",
promotions:["Logistics"],
hurryCostModifier:20, hurryCostModifier:20,
attackSound:"arrow" attackSound:"arrow"
//Chinese unique unit. It is weaker than Crossbowman but can attack twice.
}, },
*/
{ {
name:"Longbowman", name:"Longbowman",
unitType:"Ranged", unitType:"Ranged",
@ -763,7 +773,6 @@
upgradesTo:"Battleship", upgradesTo:"Battleship",
hurryCostModifier:20 hurryCostModifier:20
}, },
/*
{ {
name:"Ship of the Line", name:"Ship of the Line",
unitType:"WaterRanged", unitType:"WaterRanged",
@ -774,13 +783,12 @@
rangedStrength:35, rangedStrength:35,
cost: 185, cost: 185,
requiredResource:"Iron", requiredResource:"Iron",
uniques:["Extra sight 1"] uniques:["+1 Visibility Range"]
requiredTech:"Navigation", requiredTech:"Navigation",
obsoleteTech:"Electronics", obsoleteTech:"Electronics",
upgradesTo:"Battleship", upgradesTo:"Battleship",
hurryCostModifier:20 hurryCostModifier:20
}, },
*/
{ {
name:"Lancer", name:"Lancer",
unitType:"Mounted", unitType:"Mounted",
@ -873,7 +881,6 @@
hurryCostModifier:20, hurryCostModifier:20,
attackSound:"horse" attackSound:"horse"
}, },
/*
{ {
name:"Cossack", name:"Cossack",
unitType:"Mounted", unitType:"Mounted",
@ -885,11 +892,11 @@
requiredTech:"Military Science", requiredTech:"Military Science",
requiredResource:"Horses", requiredResource:"Horses",
upgradesTo:"Landship", upgradesTo:"Landship",
uniques:["Can move after attacking","No defensive terrain bonus","Penalty vs City 33%","Damaged Enemy Bonus 33%" ], uniques:["Can move after attacking","No defensive terrain bonus","Penalty vs City 33%","Bonus vs wounded units 33%" ],
hurryCostModifier:20, hurryCostModifier:20,
attackSound:"horse" attackSound:"horse"
//This Russian unique unit should replace Cavalry and also deal +33% damage to damaged units.
}, },
/*
{ {
name:"Comanche Rider", name:"Comanche Rider",
unitType:"Mounted", unitType:"Mounted",
@ -996,6 +1003,21 @@
obsoleteTech:"Plastics" obsoleteTech:"Plastics"
attackSound:"shot" attackSound:"shot"
}, },
{
name:"Foreign Legion",
unitType:"Melee",
replaces:"Great War Infantry",
uniqueTo:"France",
movement:2,
strength:50,
cost: 320,
requiredTech:"Replaceable Parts",
hurryCostModifier:20,
upgradesTo:"Infantry",
obsoleteTech:"Plastics",
uniques:["+20% bonus outside friendly territory"],
attackSound:"shot"
},
{ {
name:"Infantry", name:"Infantry",
unitType:"Melee", unitType:"Melee",

View file

@ -21,8 +21,8 @@ android {
applicationId "com.unciv.app" applicationId "com.unciv.app"
minSdkVersion 14 minSdkVersion 14
targetSdkVersion 28 targetSdkVersion 28
versionCode 224 versionCode 227
versionName "2.14.4" versionName "2.14.7"
} }
// Had to add this crap for Travis to build, it wanted to sign the app // Had to add this crap for Travis to build, it wanted to sign the app

View file

@ -20,6 +20,7 @@ class GameParameters{
var humanNations=ArrayList<String>().apply { add("Babylon") } var humanNations=ArrayList<String>().apply { add("Babylon") }
var numberOfEnemies=3 var numberOfEnemies=3
var mapType= MapType.Perlin var mapType= MapType.Perlin
var noBarbarians=false
var mapFileName :String?=null var mapFileName :String?=null
} }

View file

@ -47,7 +47,7 @@ class GameInfo {
currentPlayerIndex = (currentPlayerIndex+1) % civilizations.size currentPlayerIndex = (currentPlayerIndex+1) % civilizations.size
if(currentPlayerIndex==0){ if(currentPlayerIndex==0){
turns++ turns++
if (turns % 10 == 0) { // every 10 turns add a barbarian in a random place if (turns % 10 == 0 && !gameParameters.noBarbarians) { // every 10 turns add a barbarian in a random place
placeBarbarianUnit(null) placeBarbarianUnit(null)
} }
} }

View file

@ -28,11 +28,11 @@ class NextTurnAutomation{
automateUnits(civInfo) automateUnits(civInfo)
reassignWorkedTiles(civInfo) reassignWorkedTiles(civInfo)
trainSettler(civInfo) trainSettler(civInfo)
civInfo.diplomaticIncidents.clear() civInfo.popupAlerts.clear()
} }
private fun buyBuildingOrUnit(civInfo: CivilizationInfo) { private fun buyBuildingOrUnit(civInfo: CivilizationInfo) {
//allow ai spending money to purchase building & unit. Buying staff has slightly lower priority than buying tech. //allow AI spending money to purchase building & unit. Buying staff has slightly lower priority than buying tech.
for (city in civInfo.cities.sortedByDescending{ it.population.population }) { for (city in civInfo.cities.sortedByDescending{ it.population.population }) {
val construction = city.cityConstructions.getCurrentConstruction() val construction = city.cityConstructions.getCurrentConstruction()
if (construction.canBePurchased() if (construction.canBePurchased()

View file

@ -4,8 +4,8 @@ import com.badlogic.gdx.graphics.Color
import com.unciv.logic.GameInfo import com.unciv.logic.GameInfo
import com.unciv.logic.automation.UnitAutomation import com.unciv.logic.automation.UnitAutomation
import com.unciv.logic.city.CityInfo import com.unciv.logic.city.CityInfo
import com.unciv.logic.civilization.diplomacy.DiplomaticIncident import com.unciv.logic.civilization.AlertType
import com.unciv.logic.civilization.diplomacy.DiplomaticIncidentType import com.unciv.logic.civilization.PopupAlert
import com.unciv.logic.map.TileInfo import com.unciv.logic.map.TileInfo
import com.unciv.models.gamebasics.unit.UnitType import com.unciv.models.gamebasics.unit.UnitType
import java.util.* import java.util.*
@ -162,6 +162,7 @@ class Battle(val gameInfo:GameInfo) {
private fun conquerCity(city: CityInfo, attacker: ICombatant) { private fun conquerCity(city: CityInfo, attacker: ICombatant) {
val enemyCiv = city.civInfo val enemyCiv = city.civInfo
attacker.getCivInfo().addNotification("We have conquered the city of [${city.name}]!",city.location, Color.RED) attacker.getCivInfo().addNotification("We have conquered the city of [${city.name}]!",city.location, Color.RED)
attacker.getCivInfo().popupAlerts.add(PopupAlert(AlertType.CityConquered,city.name))
city.getCenterTile().apply { city.getCenterTile().apply {
if(militaryUnit!=null) militaryUnit!!.destroy() if(militaryUnit!=null) militaryUnit!!.destroy()
@ -185,6 +186,9 @@ class Battle(val gameInfo:GameInfo) {
city.moveToCiv(attacker.getCivInfo()) city.moveToCiv(attacker.getCivInfo())
city.resistanceCounter = city.population.population city.resistanceCounter = city.population.population
city.workedTiles = hashSetOf() //reassign 1st working tile
city.population.specialists.clear()
city.population.autoAssignPopulation()
city.cityStats.update() city.cityStats.update()
} }
@ -194,7 +198,7 @@ class Battle(val gameInfo:GameInfo) {
for(civ in gameInfo.civilizations) for(civ in gameInfo.civilizations)
civ.addNotification("The civilization of [${enemyCiv.civName}] has been destroyed!", null, Color.RED) civ.addNotification("The civilization of [${enemyCiv.civName}] has been destroyed!", null, Color.RED)
enemyCiv.getCivUnits().forEach { it.destroy() } enemyCiv.getCivUnits().forEach { it.destroy() }
attacker.getCivInfo().diplomaticIncidents.add(DiplomaticIncident(enemyCiv.civName,DiplomaticIncidentType.Defeated)) attacker.getCivInfo().popupAlerts.add(PopupAlert(AlertType.Defeated,enemyCiv.civName))
} }
else if(enemyCiv.cities.isNotEmpty()){ else if(enemyCiv.cities.isNotEmpty()){
enemyCiv.cities.first().cityConstructions.addBuilding("Palace") // relocate palace enemyCiv.cities.first().cityConstructions.addBuilding("Palace") // relocate palace

View file

@ -1,6 +1,7 @@
package com.unciv.logic.battle package com.unciv.logic.battle
import com.unciv.logic.map.MapUnit import com.unciv.logic.map.MapUnit
import com.unciv.logic.map.TileInfo
import com.unciv.models.gamebasics.unit.UnitType import com.unciv.models.gamebasics.unit.UnitType
import kotlin.math.max import kotlin.math.max
@ -88,6 +89,8 @@ class BattleDamage{
val modifiers = getGeneralModifiers(attacker, defender) val modifiers = getGeneralModifiers(attacker, defender)
if(attacker is MapUnitCombatant) { if(attacker is MapUnitCombatant) {
modifiers.putAll(getTileSpecificModifiers(attacker,defender.getTile()))
val defenderTile = defender.getTile() val defenderTile = defender.getTile()
val isDefenderInRoughTerrain = defenderTile.baseTerrain=="Hill" || defenderTile.terrainFeature == "Forest" || defenderTile.terrainFeature == "Jungle" val isDefenderInRoughTerrain = defenderTile.baseTerrain=="Hill" || defenderTile.terrainFeature == "Forest" || defenderTile.terrainFeature == "Jungle"
for (BDM in getBattleDamageModifiersOfUnit(attacker.unit)) { for (BDM in getBattleDamageModifiersOfUnit(attacker.unit)) {
@ -113,6 +116,7 @@ class BattleDamage{
else modifiers["Attacker Bonus"] = bonus else modifiers["Attacker Bonus"] = bonus
} }
} }
else if (attacker is CityCombatant) { else if (attacker is CityCombatant) {
if (attacker.getCivInfo().policies.isAdopted("Oligarchy") && attacker.city.getCenterTile().militaryUnit != null) if (attacker.getCivInfo().policies.isAdopted("Oligarchy") && attacker.city.getCenterTile().militaryUnit != null)
modifiers["Oligarchy"] = 0.5f modifiers["Oligarchy"] = 0.5f
@ -140,7 +144,9 @@ class BattleDamage{
val modifiers = getGeneralModifiers(defender, attacker) val modifiers = getGeneralModifiers(defender, attacker)
if (!(defender.unit.hasUnique("No defensive terrain bonus"))) { modifiers.putAll(getTileSpecificModifiers(defender, defender.getTile()))
if (!defender.unit.hasUnique("No defensive terrain bonus")) {
val tileDefenceBonus = defender.getTile().getDefensiveBonus() val tileDefenceBonus = defender.getTile().getDefensiveBonus()
if (tileDefenceBonus > 0) modifiers["Terrain"] = tileDefenceBonus if (tileDefenceBonus > 0) modifiers["Terrain"] = tileDefenceBonus
} }
@ -172,6 +178,17 @@ class BattleDamage{
return modifiers return modifiers
} }
private fun getTileSpecificModifiers(unit: MapUnitCombatant, tile: TileInfo): HashMap<String,Float> {
val modifiers = HashMap<String,Float>()
val isFriendlyTerritory = tile.getOwner()!=null && !unit.getCivInfo().isAtWarWith(tile.getOwner()!!)
if(isFriendlyTerritory && unit.getCivInfo().getBuildingUniques().contains("+15% combat strength for units fighting in friendly territory"))
modifiers["Himeji Castle"] = 0.15f
if(!isFriendlyTerritory && unit.unit.hasUnique("+20% bonus outside friendly territory"))
modifiers["Foreign Land"] = 0.2f
return modifiers
}
private fun modifiersToMultiplicationBonus(modifiers: HashMap<String, Float>): Float { private fun modifiersToMultiplicationBonus(modifiers: HashMap<String, Float>): Float {
// modifiers are like 0.1 for a 10% bonus, -0.1 for a 10% loss // modifiers are like 0.1 for a 10% bonus, -0.1 for a 10% loss
var finalModifier = 1f var finalModifier = 1f

View file

@ -38,7 +38,7 @@ class CityConstructions {
fun getStats(): Stats { fun getStats(): Stats {
val stats = Stats() val stats = Stats()
for (building in getBuiltBuildings()) for (building in getBuiltBuildings())
stats.add(building.getStats(cityInfo.civInfo.policies.adoptedPolicies)) stats.add(building.getStats(cityInfo.civInfo))
stats.science += (cityInfo.getBuildingUniques().count { it == "+1 Science Per 2 Population" } * cityInfo.population.population / 2).toFloat() stats.science += (cityInfo.getBuildingUniques().count { it == "+1 Science Per 2 Population" } * cityInfo.population.population / 2).toFloat()
return stats return stats
} }
@ -199,7 +199,7 @@ class CityConstructions {
cityInfo.civInfo.gold -= getConstruction(buildingName).getGoldCost(cityInfo.civInfo.policies.adoptedPolicies) cityInfo.civInfo.gold -= getConstruction(buildingName).getGoldCost(cityInfo.civInfo.policies.adoptedPolicies)
getConstruction(buildingName).postBuildEvent(this) getConstruction(buildingName).postBuildEvent(this)
if (currentConstruction == buildingName) { if (currentConstruction == buildingName) {
currentConstruction="" currentConstruction = ""
chooseNextConstruction() chooseNextConstruction()
} }
cityInfo.cityStats.update() cityInfo.cityStats.update()

View file

@ -73,6 +73,7 @@ class CityInfo {
if (listOf("Forest", "Jungle", "Marsh").contains(tile.terrainFeature)) if (listOf("Forest", "Jungle", "Marsh").contains(tile.terrainFeature))
tile.terrainFeature = null tile.terrainFeature = null
workedTiles = hashSetOf() //reassign 1st working tile
population.autoAssignPopulation() population.autoAssignPopulation()
cityStats.update() cityStats.update()
} }
@ -114,7 +115,9 @@ class CityInfo {
if(civInfo.policies.isAdopted("Facism")) amountToAdd*=2 if(civInfo.policies.isAdopted("Facism")) amountToAdd*=2
if(civInfo.getNation().unique=="Strategic Resources provide +1 Production, and Horses, Iron and Uranium Resources provide double quantity" if(civInfo.getNation().unique=="Strategic Resources provide +1 Production, and Horses, Iron and Uranium Resources provide double quantity"
&& resource.name in listOf("Horses","Iron","Uranium")) && resource.name in listOf("Horses","Iron","Uranium"))
amountToAdd*=2 amountToAdd *= 2
if(resource.name=="Oil" && civInfo.getNation().unique=="+1 Gold from each Trade Route, Oil resources provide double quantity")
amountToAdd *= 2
} }
if(resource.resourceType == ResourceType.Luxury if(resource.resourceType == ResourceType.Luxury
&& getBuildingUniques().contains("Provides 1 extra copy of each improved luxury resource near this City")) && getBuildingUniques().contains("Provides 1 extra copy of each improved luxury resource near this City"))

View file

@ -34,7 +34,8 @@ class CityStats {
if (!cityInfo.isCapital() && isConnectedToCapital(RoadStatus.Road)) { if (!cityInfo.isCapital() && isConnectedToCapital(RoadStatus.Road)) {
val civInfo = cityInfo.civInfo val civInfo = cityInfo.civInfo
var goldFromTradeRoute = civInfo.getCapital().population.population * 0.15 + cityInfo.population.population * 1.1 - 1 // Calculated by http://civilization.wikia.com/wiki/Trade_route_(Civ5) var goldFromTradeRoute = civInfo.getCapital().population.population * 0.15 + cityInfo.population.population * 1.1 - 1 // Calculated by http://civilization.wikia.com/wiki/Trade_route_(Civ5)
if (civInfo.policies.isAdopted("Trade Unions")) goldFromTradeRoute += 2.0 if(civInfo.getNation().unique=="+1 Gold from each Trade Route, Oil resources provide double quantity") goldFromTradeRoute += 1
if (civInfo.policies.isAdopted("Trade Unions")) goldFromTradeRoute += 2
if (civInfo.getBuildingUniques().contains("Gold from all trade routes +25%")) goldFromTradeRoute *= 1.25 // Machu Pichu speciality if (civInfo.getBuildingUniques().contains("Gold from all trade routes +25%")) goldFromTradeRoute *= 1.25 // Machu Pichu speciality
stats.gold += goldFromTradeRoute.toFloat() stats.gold += goldFromTradeRoute.toFloat()
} }

View file

@ -7,8 +7,6 @@ import com.unciv.UnCivGame
import com.unciv.logic.GameInfo import com.unciv.logic.GameInfo
import com.unciv.logic.city.CityInfo import com.unciv.logic.city.CityInfo
import com.unciv.logic.civilization.diplomacy.DiplomacyManager import com.unciv.logic.civilization.diplomacy.DiplomacyManager
import com.unciv.logic.civilization.diplomacy.DiplomaticIncident
import com.unciv.logic.civilization.diplomacy.DiplomaticIncidentType
import com.unciv.logic.civilization.diplomacy.DiplomaticStatus import com.unciv.logic.civilization.diplomacy.DiplomaticStatus
import com.unciv.logic.map.BFS import com.unciv.logic.map.BFS
import com.unciv.logic.map.MapUnit import com.unciv.logic.map.MapUnit
@ -63,7 +61,7 @@ class CivilizationInfo {
var victoryManager=VictoryManager() var victoryManager=VictoryManager()
var diplomacy = HashMap<String, DiplomacyManager>() var diplomacy = HashMap<String, DiplomacyManager>()
var notifications = ArrayList<Notification>() var notifications = ArrayList<Notification>()
val diplomaticIncidents = ArrayList<DiplomaticIncident>() val popupAlerts = ArrayList<PopupAlert>()
// if we only use lists, and change the list each time the cities are changed, // if we only use lists, and change the list each time the cities are changed,
// we won't get concurrent modification exceptions. // we won't get concurrent modification exceptions.
@ -296,12 +294,13 @@ class CivilizationInfo {
fun meetCivilization(otherCiv: CivilizationInfo) { fun meetCivilization(otherCiv: CivilizationInfo) {
diplomacy[otherCiv.civName] = DiplomacyManager(this, otherCiv.civName) diplomacy[otherCiv.civName] = DiplomacyManager(this, otherCiv.civName)
.apply { diplomaticStatus = DiplomaticStatus.Peace } .apply { diplomaticStatus = DiplomaticStatus.Peace }
otherCiv.diplomaticIncidents.add(DiplomaticIncident(civName, DiplomaticIncidentType.FirstContact))
otherCiv.popupAlerts.add(PopupAlert(AlertType.FirstContact,civName))
otherCiv.diplomacy[civName] = DiplomacyManager(otherCiv, civName) otherCiv.diplomacy[civName] = DiplomacyManager(otherCiv, civName)
.apply { diplomaticStatus = DiplomaticStatus.Peace } .apply { diplomaticStatus = DiplomaticStatus.Peace }
diplomaticIncidents.add(DiplomaticIncident(otherCiv.civName, DiplomaticIncidentType.FirstContact)) popupAlerts.add(PopupAlert(AlertType.FirstContact,otherCiv.civName))
} }
override fun toString(): String {return civName} // for debug override fun toString(): String {return civName} // for debug

View file

@ -0,0 +1,10 @@
package com.unciv.logic.civilization
enum class AlertType{
WarDeclaration,
Defeated,
FirstContact,
CityConquered
}
class PopupAlert (val type:AlertType, val value:String)

View file

@ -1,7 +1,9 @@
package com.unciv.logic.civilization.diplomacy package com.unciv.logic.civilization.diplomacy
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import com.unciv.logic.civilization.AlertType
import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.civilization.PopupAlert
import com.unciv.logic.trade.Trade import com.unciv.logic.trade.Trade
import com.unciv.logic.trade.TradeType import com.unciv.logic.trade.TradeType
import com.unciv.models.Counter import com.unciv.models.Counter
@ -97,9 +99,11 @@ class DiplomacyManager() {
fun declareWar(){ fun declareWar(){
diplomaticStatus = DiplomaticStatus.War diplomaticStatus = DiplomaticStatus.War
otherCiv().diplomacy[civInfo.civName]!!.diplomaticStatus = DiplomaticStatus.War val otherCiv = otherCiv()
otherCiv().addNotification("[${civInfo.civName}] has declared war on us!",null, Color.RED)
otherCiv().diplomaticIncidents.add(DiplomaticIncident(civInfo.civName,DiplomaticIncidentType.WarDeclaration)) otherCiv.diplomacy[civInfo.civName]!!.diplomaticStatus = DiplomaticStatus.War
otherCiv.addNotification("[${civInfo.civName}] has declared war on us!",null, Color.RED)
otherCiv.popupAlerts.add(PopupAlert(AlertType.WarDeclaration,civInfo.civName))
} }
//endregion //endregion
} }

View file

@ -1,5 +0,0 @@
package com.unciv.logic.civilization.diplomacy
import com.unciv.logic.trade.Trade
class DiplomaticIncident(val civName:String, val type: DiplomaticIncidentType, val trade: Trade?=null)

View file

@ -1,7 +0,0 @@
package com.unciv.logic.civilization.diplomacy
enum class DiplomaticIncidentType{
WarDeclaration,
Defeated,
FirstContact
}

View file

@ -176,6 +176,7 @@ class MapUnit {
fun isIdle(): Boolean { fun isIdle(): Boolean {
if (currentMovement == 0f) return false if (currentMovement == 0f) return false
if (name == "Worker" && getTile().improvementInProgress != null) return false if (name == "Worker" && getTile().improvementInProgress != null) return false
if (hasUnique("Can construct roads") && currentTile.improvementInProgress=="Road") return false
if (isFortified()) return false if (isFortified()) return false
if (action=="Sleep") return false if (action=="Sleep") return false
return true return true
@ -301,6 +302,7 @@ class MapUnit {
private fun doPostTurnAction() { private fun doPostTurnAction() {
if (name == "Worker" && getTile().improvementInProgress != null) workOnImprovement() if (name == "Worker" && getTile().improvementInProgress != null) workOnImprovement()
if(hasUnique("Can construct roads") && currentTile.improvementInProgress=="Road") workOnImprovement()
if(currentMovement== getMaxMovement().toFloat() if(currentMovement== getMaxMovement().toFloat()
&& isFortified()){ && isFortified()){
val currentTurnsFortified = getFortificationTurns() val currentTurnsFortified = getFortificationTurns()

View file

@ -21,6 +21,7 @@ enum class MapType {
File File
} }
class CelluarAutomataRandomMapGenerator(): SeedRandomMapGenerator() { class CelluarAutomataRandomMapGenerator(): SeedRandomMapGenerator() {
var landProb = 0.55f var landProb = 0.55f
var numSmooth = 4 var numSmooth = 4
@ -28,7 +29,7 @@ class CelluarAutomataRandomMapGenerator(): SeedRandomMapGenerator() {
constructor(type: MapType): this() { constructor(type: MapType): this() {
mapType = type mapType = type
if (mapType < MapType.Default) { if (mapType != MapType.Default && mapType !=MapType.Pangaea) {
mapType = MapType.Default mapType = MapType.Default
} }
} }
@ -77,6 +78,8 @@ class CelluarAutomataRandomMapGenerator(): SeedRandomMapGenerator() {
for(tile in mapToReturn.values) randomizeTile(tile,mapToReturn) for(tile in mapToReturn.values) randomizeTile(tile,mapToReturn)
randomizeStrategicResources(mapToReturn,distance)
return mapToReturn return mapToReturn
} }
@ -227,6 +230,8 @@ class PerlinNoiseRandomMapGenerator:SeedRandomMapGenerator(){
for(tile in mapToReturn.values) randomizeTile(tile,mapToReturn) for(tile in mapToReturn.values) randomizeTile(tile,mapToReturn)
randomizeStrategicResources(mapToReturn,distance)
return mapToReturn return mapToReturn
} }
@ -333,6 +338,7 @@ open class SeedRandomMapGenerator : RandomMapGenerator() {
for (entry in map) randomizeTile(entry.value, mapToReturn) for (entry in map) randomizeTile(entry.value, mapToReturn)
setWaterTiles(mapToReturn) setWaterTiles(mapToReturn)
randomizeStrategicResources(mapToReturn,distance)
return mapToReturn return mapToReturn
} }
@ -357,15 +363,6 @@ open class SeedRandomMapGenerator : RandomMapGenerator() {
} }
expandAreas(areas, map) expandAreas(areas, map)
// After we've assigned all the tiles, there will be some areas that contain only 1 or 2 tiles.
// So, we kill those areas, and have the world expand on and cover them too
// for (area in areas.toList()) {
// if (area.locations.size < 3) {
// areas -= area
// for (location in area.locations) map[location]!!.baseTerrain = ""
// }
// }
expandAreas(areas, map) expandAreas(areas, map)
} }
@ -450,7 +447,7 @@ open class RandomMapGenerator {
var resource: TileResource? = null var resource: TileResource? = null
when { when {
Math.random() < 1 / 5f -> resource = getRandomResource(tileResources, ResourceType.Bonus) Math.random() < 1 / 15f -> resource = getRandomResource(tileResources, ResourceType.Bonus)
Math.random() < 1 / 15f -> resource = getRandomResource(tileResources, ResourceType.Strategic) Math.random() < 1 / 15f -> resource = getRandomResource(tileResources, ResourceType.Strategic)
Math.random() < 1 / 15f -> resource = getRandomResource(tileResources, ResourceType.Luxury) Math.random() < 1 / 15f -> resource = getRandomResource(tileResources, ResourceType.Luxury)
} }
@ -504,4 +501,40 @@ open class RandomMapGenerator {
addRandomResourceToTile(tileInfo) addRandomResourceToTile(tileInfo)
maybeAddAncientRuins(tileInfo) maybeAddAncientRuins(tileInfo)
} }
fun randomizeStrategicResources(mapToReturn: HashMap<String, TileInfo>,distance: Int) {
for(tile in mapToReturn.values)
if(tile.resource!=null && tile.getTileResource().resourceType==ResourceType.Strategic)
tile.resource=null
for(resource in GameBasics.TileResources.values.filter { it.resourceType==ResourceType.Strategic }){
val suitableTiles = mapToReturn.values
.filter { it.resource==null && resource.terrainsCanBeFoundOn.contains(it.getLastTerrain().name) }
val numberOfResources = mapToReturn.count() / 100
val locations = chooseSpreadOutLocations(numberOfResources,suitableTiles, distance)
for(location in locations) location.resource = resource.name
}
}
fun chooseSpreadOutLocations(numberOfResources: Int, suitableTiles: List<TileInfo>, initialDistance:Int): ArrayList<TileInfo> {
for(distanceBetweenResources in initialDistance downTo 1){
var availableTiles = suitableTiles.toList()
val chosenTiles = ArrayList<TileInfo>()
for(i in 1..numberOfResources){
if(availableTiles.isEmpty()) break
val chosenTile = availableTiles.random()
availableTiles = availableTiles.filter { it.arialDistanceTo(chosenTile)>distanceBetweenResources }
chosenTiles.add(chosenTile)
}
if(chosenTiles.size == numberOfResources) return chosenTiles
}
throw Exception("ArgleBargle")
}
} }

View file

@ -43,7 +43,6 @@ class TileMap {
mapValues = CelluarAutomataRandomMapGenerator(newGameParameters.mapType).generateMap(newGameParameters.mapRadius).values mapValues = CelluarAutomataRandomMapGenerator(newGameParameters.mapType).generateMap(newGameParameters.mapRadius).values
tileList.addAll(mapValues) tileList.addAll(mapValues)
// tileList.addAll(AlexanderRandomMapGenerator().generateMap(distance,0.8f).values)
setTransients() setTransients()
} }

View file

@ -2,6 +2,7 @@ package com.unciv.models.gamebasics
import com.unciv.logic.city.CityConstructions import com.unciv.logic.city.CityConstructions
import com.unciv.logic.city.IConstruction import com.unciv.logic.city.IConstruction
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.gamebasics.tech.Technology import com.unciv.models.gamebasics.tech.Technology
import com.unciv.models.stats.NamedStats import com.unciv.models.stats.NamedStats
import com.unciv.models.stats.Stats import com.unciv.models.stats.Stats
@ -10,7 +11,7 @@ import com.unciv.ui.utils.getRandom
class Building : NamedStats(), IConstruction{ class Building : NamedStats(), IConstruction{
override val description: String override val description: String
get() = getDescription(false, hashSetOf()) get() = getDescription(false, null)
var requiredTech: String? = null var requiredTech: String? = null
@ -50,7 +51,7 @@ class Building : NamedStats(), IConstruction{
fun getShortDescription(): String { // should fit in one line fun getShortDescription(): String { // should fit in one line
val infoList= mutableListOf<String>() val infoList= mutableListOf<String>()
val str = getStats(hashSetOf()).toString() val str = getStats(null).toString()
if(str.isNotEmpty()) infoList += str if(str.isNotEmpty()) infoList += str
if(percentStatBonus!=null){ if(percentStatBonus!=null){
for(stat in percentStatBonus!!.toHashMap()) for(stat in percentStatBonus!!.toHashMap())
@ -70,8 +71,8 @@ class Building : NamedStats(), IConstruction{
return infoList.joinToString() return infoList.joinToString()
} }
fun getDescription(forBuildingPickerScreen: Boolean, adoptedPolicies: HashSet<String>): String { fun getDescription(forBuildingPickerScreen: Boolean, civInfo: CivilizationInfo?): String {
val stats = getStats(adoptedPolicies) val stats = getStats(civInfo)
val stringBuilder = StringBuilder() val stringBuilder = StringBuilder()
if(uniqueTo!=null) stringBuilder.appendln("Unique to [$uniqueTo], replaces [$replaces]".tr()) if(uniqueTo!=null) stringBuilder.appendln("Unique to [$uniqueTo], replaces [$replaces]".tr())
if (!forBuildingPickerScreen) stringBuilder.appendln("{Cost}: $cost".tr()) if (!forBuildingPickerScreen) stringBuilder.appendln("{Cost}: $cost".tr())
@ -118,35 +119,44 @@ class Building : NamedStats(), IConstruction{
} }
val cultureBuildings = hashSetOf("Monument", "Temple", "Monastery") val cultureBuildings = hashSetOf("Monument", "Temple", "Monastery")
fun getStats(adoptedPolicies: HashSet<String>): Stats {
fun getStats(civInfo: CivilizationInfo?): Stats {
val stats = this.clone() val stats = this.clone()
if (adoptedPolicies.contains("Organized Religion") && cultureBuildings.contains(name)) if(civInfo != null) {
stats.happiness += 1 val adoptedPolicies = civInfo.policies.adoptedPolicies
if (adoptedPolicies.contains("Organized Religion") && cultureBuildings.contains(name))
stats.happiness += 1
if (adoptedPolicies.contains("Free Religion") && cultureBuildings.contains(name)) if (adoptedPolicies.contains("Free Religion") && cultureBuildings.contains(name))
stats.culture += 1f stats.culture += 1f
if (adoptedPolicies.contains("Entrepreneurship") && hashSetOf("Mint", "Market", "Bank", "Stock Market").contains(name)) if (adoptedPolicies.contains("Entrepreneurship") && hashSetOf("Mint", "Market", "Bank", "Stock Market").contains(name))
stats.science += 1f stats.science += 1f
if (adoptedPolicies.contains("Humanism") && hashSetOf("University", "Observatory", "Public School").contains(name)) if (adoptedPolicies.contains("Humanism") && hashSetOf("University", "Observatory", "Public School").contains(name))
stats.happiness += 1f stats.happiness += 1f
if (adoptedPolicies.contains("Theocracy") && name == "Temple") if (adoptedPolicies.contains("Theocracy") && name == "Temple")
percentStatBonus = Stats().apply { gold=10f } percentStatBonus = Stats().apply { gold = 10f }
if (adoptedPolicies.contains("Free Thought") && name == "University") if (adoptedPolicies.contains("Free Thought") && name == "University")
percentStatBonus!!.science = 50f percentStatBonus!!.science = 50f
if (adoptedPolicies.contains("Rationalism Complete") && !isWonder && stats.science > 0) if (adoptedPolicies.contains("Rationalism Complete") && !isWonder && stats.science > 0)
stats.gold += 1f stats.gold += 1f
if (adoptedPolicies.contains("Constitution") && isWonder) if (adoptedPolicies.contains("Constitution") && isWonder)
stats.culture += 2f stats.culture += 2f
if(adoptedPolicies.contains("Autocracy Complete") && cityStrength>0) if (adoptedPolicies.contains("Autocracy Complete") && cityStrength > 0)
stats.happiness+=1 stats.happiness += 1
if (name == "Castle" && civInfo.getBuildingUniques().contains("+1 happiness, +2 culture and +3 gold from every Castle")){
stats.happiness+=1
stats.culture+=2
stats.gold+=3
}
}
return stats return stats
} }

View file

@ -60,6 +60,12 @@ class NationTable(val nation: Nation, val newGameParameters: GameParameters, ski
textList += " "+unique.tr() textList += " "+unique.tr()
if (building.maintenance != originalBuilding.maintenance) if (building.maintenance != originalBuilding.maintenance)
textList += " {Maintenance} " + building.maintenance + " vs " + originalBuilding.maintenance textList += " {Maintenance} " + building.maintenance + " vs " + originalBuilding.maintenance
if(building.cost != originalBuilding.cost)
textList += " {Cost} " + building.cost + " vs " + originalBuilding.cost
if(building.cityStrength != originalBuilding.cityStrength)
textList += " {City strength} " + building.cityStrength+ " vs " + originalBuilding.cityStrength
if(building.cityHealth!= originalBuilding.cityHealth)
textList += " {City health} " + building.cityHealth+ " vs " + originalBuilding.cityHealth
textList+="" textList+=""
} }
@ -76,10 +82,13 @@ class NationTable(val nation: Nation, val newGameParameters: GameParameters, ski
textList+= " {Range} " + unit.range+ " vs " + originalUnit.range textList+= " {Range} " + unit.range+ " vs " + originalUnit.range
if (unit.movement!= originalUnit.movement) if (unit.movement!= originalUnit.movement)
textList+= " {Movement} " + unit.movement+ " vs " + originalUnit.movement textList+= " {Movement} " + unit.movement+ " vs " + originalUnit.movement
if(originalUnit.requiredResource!=null && unit.requiredResource==null)
textList+= " "+"[${originalUnit.requiredResource}] not required".tr()
for(unique in unit.uniques.filterNot { it in originalUnit.uniques }) for(unique in unit.uniques.filterNot { it in originalUnit.uniques })
textList += " "+Translations.translateBonusOrPenalty(unique) textList += " "+Translations.translateBonusOrPenalty(unique)
for(promotions in unit.promotions.filter { it !in originalUnit.promotions}) for(promotion in unit.promotions.filter { it !in originalUnit.promotions})
textList += " "+promotions.tr() textList += " "+promotion.tr()+ " ("+Translations.translateBonusOrPenalty(GameBasics.UnitPromotions[promotion]!!.effect)+")"
textList+=""
} }

View file

@ -2,10 +2,7 @@ package com.unciv.ui
import com.badlogic.gdx.Gdx import com.badlogic.gdx.Gdx
import com.badlogic.gdx.scenes.scene2d.Actor import com.badlogic.gdx.scenes.scene2d.Actor
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane import com.badlogic.gdx.scenes.scene2d.ui.*
import com.badlogic.gdx.scenes.scene2d.ui.SelectBox
import com.badlogic.gdx.scenes.scene2d.ui.Skin
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener
import com.badlogic.gdx.utils.Array import com.badlogic.gdx.utils.Array
import com.unciv.GameStarter import com.unciv.GameStarter
@ -74,17 +71,50 @@ class NewGameScreen: PickerScreen(){
val newGameOptionsTable = Table() val newGameOptionsTable = Table()
newGameOptionsTable.skin = skin newGameOptionsTable.skin = skin
addMapTypeSizeAndFile(newGameOptionsTable)
addNumberOfHumansAndEnemies(newGameOptionsTable)
addDifficultySelectBox(newGameOptionsTable)
val noBarbariansCheckbox = CheckBox("No barbarians",skin)
noBarbariansCheckbox.isChecked=newGameParameters.noBarbarians
noBarbariansCheckbox.addListener(object : ChangeListener() {
override fun changed(event: ChangeEvent?, actor: Actor?) {
newGameParameters.noBarbarians = noBarbariansCheckbox.isChecked
}
})
newGameOptionsTable.add(noBarbariansCheckbox).colspan(2).row()
rightSideButton.enable()
rightSideButton.setText("Start game!".tr())
rightSideButton.onClick {
Gdx.input.inputProcessor = null // remove input processing - nothing will be clicked!
rightSideButton.disable()
rightSideButton.setText("Working...".tr())
thread { // Creating a new game can take a while and we don't want ANRs
newGame = GameStarter().startNewGame(newGameParameters)
}
}
newGameOptionsTable.pack()
return newGameOptionsTable
}
private fun addMapTypeSizeAndFile(newGameOptionsTable: Table) {
newGameOptionsTable.add("{Map type}:".tr()) newGameOptionsTable.add("{Map type}:".tr())
val mapTypes = LinkedHashMap<String, MapType>() val mapTypes = LinkedHashMap<String, MapType>()
for (type in MapType.values()) { for (type in MapType.values()) {
if(type==MapType.File && GameSaver().getMaps().isEmpty()) continue if (type == MapType.File && GameSaver().getMaps().isEmpty()) continue
mapTypes[type.toString()] = type mapTypes[type.toString()] = type
} }
val mapFileLabel = "{Map file}:".toLabel() val mapFileLabel = "{Map file}:".toLabel()
val mapFileSelectBox = getMapFileSelectBox() val mapFileSelectBox = getMapFileSelectBox()
mapFileLabel.isVisible=false mapFileLabel.isVisible = false
mapFileSelectBox.isVisible=false mapFileSelectBox.isVisible = false
val mapTypeSelectBox = TranslatedSelectBox(mapTypes.keys, newGameParameters.mapType.toString(), skin) val mapTypeSelectBox = TranslatedSelectBox(mapTypes.keys, newGameParameters.mapType.toString(), skin)
@ -98,13 +128,13 @@ class NewGameScreen: PickerScreen(){
worldSizeSelectBox.isVisible = false worldSizeSelectBox.isVisible = false
worldSizeLabel.isVisible = false worldSizeLabel.isVisible = false
mapFileSelectBox.isVisible = true mapFileSelectBox.isVisible = true
mapFileLabel.isVisible=true mapFileLabel.isVisible = true
newGameParameters.mapFileName = mapFileSelectBox.selected newGameParameters.mapFileName = mapFileSelectBox.selected
} else { } else {
worldSizeSelectBox.isVisible = true worldSizeSelectBox.isVisible = true
worldSizeLabel.isVisible = true worldSizeLabel.isVisible = true
mapFileSelectBox.isVisible = false mapFileSelectBox.isVisible = false
mapFileLabel.isVisible=false mapFileLabel.isVisible = false
newGameParameters.mapFileName = null newGameParameters.mapFileName = null
} }
} }
@ -117,8 +147,9 @@ class NewGameScreen: PickerScreen(){
newGameOptionsTable.add(mapFileLabel) newGameOptionsTable.add(mapFileLabel)
newGameOptionsTable.add(mapFileSelectBox).pad(10f).row() newGameOptionsTable.add(mapFileSelectBox).pad(10f).row()
}
private fun addNumberOfHumansAndEnemies(newGameOptionsTable: Table) {
newGameOptionsTable.add("{Number of human players}:".tr()) newGameOptionsTable.add("{Number of human players}:".tr())
val humanPlayers = SelectBox<Int>(skin) val humanPlayers = SelectBox<Int>(skin)
val humanPlayersArray = Array<Int>() val humanPlayersArray = Array<Int>()
@ -131,7 +162,7 @@ class NewGameScreen: PickerScreen(){
newGameOptionsTable.add("{Number of enemies}:".tr()) newGameOptionsTable.add("{Number of enemies}:".tr())
val enemiesSelectBox = SelectBox<Int>(skin) val enemiesSelectBox = SelectBox<Int>(skin)
val enemiesArray = Array<Int>() val enemiesArray = Array<Int>()
(0..GameBasics.Nations.size-1).forEach { enemiesArray.add(it) } (0..GameBasics.Nations.size - 1).forEach { enemiesArray.add(it) }
enemiesSelectBox.items = enemiesArray enemiesSelectBox.items = enemiesArray
enemiesSelectBox.selected = newGameParameters.numberOfEnemies enemiesSelectBox.selected = newGameParameters.numberOfEnemies
newGameOptionsTable.add(enemiesSelectBox).pad(10f).row() newGameOptionsTable.add(enemiesSelectBox).pad(10f).row()
@ -153,32 +184,17 @@ class NewGameScreen: PickerScreen(){
removeExtraHumanNations(humanPlayers) removeExtraHumanNations(humanPlayers)
} }
}) })
}
private fun addDifficultySelectBox(newGameOptionsTable: Table) {
newGameOptionsTable.add("{Difficulty}:".tr()) newGameOptionsTable.add("{Difficulty}:".tr())
val difficultySelectBox = TranslatedSelectBox(GameBasics.Difficulties.keys, newGameParameters.difficulty , skin) val difficultySelectBox = TranslatedSelectBox(GameBasics.Difficulties.keys, newGameParameters.difficulty, skin)
difficultySelectBox.addListener(object : ChangeListener() { difficultySelectBox.addListener(object : ChangeListener() {
override fun changed(event: ChangeEvent?, actor: Actor?) { override fun changed(event: ChangeEvent?, actor: Actor?) {
newGameParameters.difficulty = difficultySelectBox.selected.value newGameParameters.difficulty = difficultySelectBox.selected.value
} }
}) })
newGameOptionsTable.add(difficultySelectBox).pad(10f).row() newGameOptionsTable.add(difficultySelectBox).pad(10f).row()
rightSideButton.enable()
rightSideButton.setText("Start game!".tr())
rightSideButton.onClick {
Gdx.input.inputProcessor = null // remove input processing - nothing will be clicked!
rightSideButton.disable()
rightSideButton.setText("Working...".tr())
thread {
// Creating a new game can tke a while and we don't want ANRs
newGame = GameStarter().startNewGame(newGameParameters)
}
}
newGameOptionsTable.pack()
return newGameOptionsTable
} }
private fun getMapFileSelectBox(): SelectBox<String> { private fun getMapFileSelectBox(): SelectBox<String> {

View file

@ -60,7 +60,7 @@ class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseS
wonderDetailsTable.clear() wonderDetailsTable.clear()
else{ else{
val detailsString = building.getDescription(true, val detailsString = building.getDescription(true,
cityScreen.city.civInfo.policies.adoptedPolicies) cityScreen.city.civInfo)
wonderDetailsTable.add(detailsString.toLabel().apply { setWrap(true)}) wonderDetailsTable.add(detailsString.toLabel().apply { setWrap(true)})
.width(cityScreen.stage.width/4 - 2*pad ).row() // when you set wrap, then you need to manually set the size of the label .width(cityScreen.stage.width/4 - 2*pad ).row() // when you set wrap, then you need to manually set the size of the label
if(!building.isWonder) { if(!building.isWonder) {

View file

@ -18,6 +18,7 @@ import com.unciv.ui.worldscreen.optionstable.YesNoPopupTable
class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScreen.skin){ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScreen.skin){
var constructionScrollPane:ScrollPane?=null var constructionScrollPane:ScrollPane?=null
var lastConstruction = ""
private fun getProductionButton(construction: String, buttonText: String, rejectionReason: String=""): Table { private fun getProductionButton(construction: String, buttonText: String, rejectionReason: String=""): Table {
val pickProductionButton = Table() val pickProductionButton = Table()
@ -35,6 +36,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
if(rejectionReason=="") { if(rejectionReason=="") {
pickProductionButton.onClick { pickProductionButton.onClick {
lastConstruction = cityScreen.city.cityConstructions.currentConstruction
cityScreen.city.cityConstructions.currentConstruction = construction cityScreen.city.cityConstructions.currentConstruction = construction
cityScreen.city.cityStats.update() cityScreen.city.cityStats.update()
cityScreen.update() cityScreen.update()
@ -131,7 +133,8 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
} }
private fun addCurrentConstructionTable(city: CityInfo) { private fun addCurrentConstructionTable(city: CityInfo) {
val construction = city.cityConstructions.getCurrentConstruction() val cityConstructions = city.cityConstructions
val construction = cityConstructions.getCurrentConstruction()
row() row()
val purchaseConstructionButton: TextButton val purchaseConstructionButton: TextButton
@ -140,7 +143,9 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
purchaseConstructionButton = TextButton("Buy for [$buildingGoldCost] gold".tr(), CameraStageBaseScreen.skin) purchaseConstructionButton = TextButton("Buy for [$buildingGoldCost] gold".tr(), CameraStageBaseScreen.skin)
purchaseConstructionButton.onClick("coin") { purchaseConstructionButton.onClick("coin") {
YesNoPopupTable("Would you like to purchase [${construction.name}] for [$buildingGoldCost] gold?".tr(), { YesNoPopupTable("Would you like to purchase [${construction.name}] for [$buildingGoldCost] gold?".tr(), {
city.cityConstructions.purchaseBuilding(construction.name) cityConstructions.purchaseBuilding(construction.name)
if(lastConstruction!="" && cityConstructions.getConstruction(lastConstruction).isBuildable(cityConstructions))
city.cityConstructions.currentConstruction = lastConstruction
update() update()
}, cityScreen) }, cityScreen)
} }
@ -170,7 +175,7 @@ class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScre
if (currentConstruction is BaseUnit) if (currentConstruction is BaseUnit)
description = currentConstruction.getDescription(true) description = currentConstruction.getDescription(true)
else if (currentConstruction is Building) else if (currentConstruction is Building)
description = currentConstruction.getDescription(true, city.civInfo.policies.adoptedPolicies) description = currentConstruction.getDescription(true, city.civInfo)
else description = currentConstruction.description.tr() else description = currentConstruction.description.tr()
val descriptionLabel = description.toLabel() val descriptionLabel = description.toLabel()

View file

@ -93,8 +93,9 @@ class CityButton(val city: CityInfo, internal val tileGroup: WorldTileGroup, ski
group.addActor(image) group.addActor(image)
val secondaryColor = cityConstructions.cityInfo.civInfo.getNation().getSecondaryColor() val secondaryColor = cityConstructions.cityInfo.civInfo.getNation().getSecondaryColor()
if(cityConstructions.getCurrentConstruction() !is SpecialConstruction) { val cityCurrentConstruction = cityConstructions.getCurrentConstruction()
val turnsToConstruction = cityConstructions.turnsToConstruction(cityConstructions.currentConstruction) if(cityCurrentConstruction !is SpecialConstruction) {
val turnsToConstruction = cityConstructions.turnsToConstruction(cityCurrentConstruction.name)
val label = turnsToConstruction.toString().toLabel() val label = turnsToConstruction.toString().toLabel()
label.setFontColor(secondaryColor) label.setFontColor(secondaryColor)
label.setFontSize(10) label.setFontSize(10)

View file

@ -3,6 +3,7 @@ package com.unciv.ui.tilegroups
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.Actor import com.badlogic.gdx.scenes.scene2d.Actor
import com.badlogic.gdx.scenes.scene2d.Group import com.badlogic.gdx.scenes.scene2d.Group
import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.ui.Image import com.badlogic.gdx.scenes.scene2d.ui.Image
import com.badlogic.gdx.utils.Align import com.badlogic.gdx.utils.Align
import com.unciv.UnCivGame import com.unciv.UnCivGame
@ -49,6 +50,8 @@ open class TileGroup(var tileInfo: TileInfo) : Group() {
var populationImage: Image? = null //reuse for acquire icon var populationImage: Image? = null //reuse for acquire icon
private val roadImages = HashMap<TileInfo, RoadImage>() private val roadImages = HashMap<TileInfo, RoadImage>()
private val borderImages = HashMap<TileInfo, List<Image>>() // map of neighboring tile to border images private val borderImages = HashMap<TileInfo, List<Image>>() // map of neighboring tile to border images
val unitLayerGroup = Group().apply { isTransform=false; setSize(groupSize,groupSize);touchable=Touchable.disabled }
protected var civilianUnitImage: UnitGroup? = null protected var civilianUnitImage: UnitGroup? = null
protected var militaryUnitImage: UnitGroup? = null protected var militaryUnitImage: UnitGroup? = null
@ -71,6 +74,7 @@ open class TileGroup(var tileInfo: TileInfo) : Group() {
this.addActor(baseLayerGroup) this.addActor(baseLayerGroup)
this.addActor(featureLayerGroup) this.addActor(featureLayerGroup)
this.addActor(miscLayerGroup) this.addActor(miscLayerGroup)
this.addActor(unitLayerGroup)
this.addActor(circleCrosshairFogLayerGroup) this.addActor(circleCrosshairFogLayerGroup)
updateTileImage(false) updateTileImage(false)
@ -426,7 +430,7 @@ open class TileGroup(var tileInfo: TileInfo) : Group() {
newImage.blackSpinningCircle = ImageGetter.getCircle() newImage.blackSpinningCircle = ImageGetter.getCircle()
.apply { rotation= oldUnitGroup.blackSpinningCircle!!.rotation} .apply { rotation= oldUnitGroup.blackSpinningCircle!!.rotation}
} }
miscLayerGroup.addActor(newImage) unitLayerGroup.addActor(newImage)
newImage.center(this) newImage.center(this)
newImage.y += yFromCenter newImage.y += yFromCenter

View file

@ -30,6 +30,7 @@ class TileGroupMap<T: TileGroup>(tileGroups:Collection<T>, padding:Float): Group
val baseLayers = ArrayList<Group>() val baseLayers = ArrayList<Group>()
val featureLayers = ArrayList<Group>() val featureLayers = ArrayList<Group>()
val miscLayers = ArrayList<Group>() val miscLayers = ArrayList<Group>()
val unitLayers = ArrayList<Group>()
val circleCrosshairFogLayers = ArrayList<Group>() val circleCrosshairFogLayers = ArrayList<Group>()
for(group in tileGroups.sortedByDescending { it.tileInfo.position.x + it.tileInfo.position.y }){ for(group in tileGroups.sortedByDescending { it.tileInfo.position.x + it.tileInfo.position.y }){
@ -37,13 +38,15 @@ class TileGroupMap<T: TileGroup>(tileGroups:Collection<T>, padding:Float): Group
baseLayers.add(group.baseLayerGroup.apply { setPosition(group.x,group.y) }) baseLayers.add(group.baseLayerGroup.apply { setPosition(group.x,group.y) })
featureLayers.add(group.featureLayerGroup.apply { setPosition(group.x,group.y) }) featureLayers.add(group.featureLayerGroup.apply { setPosition(group.x,group.y) })
miscLayers.add(group.miscLayerGroup.apply { setPosition(group.x,group.y) }) miscLayers.add(group.miscLayerGroup.apply { setPosition(group.x,group.y) })
unitLayers.add(group.unitLayerGroup.apply { setPosition(group.x,group.y) })
circleCrosshairFogLayers.add(group.circleCrosshairFogLayerGroup.apply { setPosition(group.x,group.y) }) circleCrosshairFogLayers.add(group.circleCrosshairFogLayerGroup.apply { setPosition(group.x,group.y) })
} }
for(group in baseLayers) addActor(group) for(group in baseLayers) addActor(group)
for(group in featureLayers) addActor(group) for(group in featureLayers) addActor(group)
for(group in miscLayers) addActor(group) for(group in miscLayers) addActor(group)
for(group in circleCrosshairFogLayers) addActor(group) for(group in circleCrosshairFogLayers) addActor(group)
for(group in tileGroups) addActor(group) // The above layers are for the visual layers, this is for the cli for(group in tileGroups) addActor(group) // The above layers are for the visual layers, this is for the clickability
for(group in unitLayers) addActor(group) // Aaand units above everything else.
// there are tiles "below the zero", // there are tiles "below the zero",

View file

@ -8,11 +8,12 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.ui.TextButton import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.unciv.UnCivGame import com.unciv.UnCivGame
import com.unciv.logic.GameSaver import com.unciv.logic.GameSaver
import com.unciv.logic.civilization.AlertType
import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.civilization.diplomacy.DiplomaticIncident import com.unciv.logic.civilization.PopupAlert
import com.unciv.logic.civilization.diplomacy.DiplomaticIncidentType
import com.unciv.logic.civilization.diplomacy.DiplomaticStatus import com.unciv.logic.civilization.diplomacy.DiplomaticStatus
import com.unciv.models.gamebasics.GameBasics import com.unciv.models.gamebasics.GameBasics
import com.unciv.models.gamebasics.Nation
import com.unciv.models.gamebasics.tile.ResourceType import com.unciv.models.gamebasics.tile.ResourceType
import com.unciv.models.gamebasics.tr import com.unciv.models.gamebasics.tr
import com.unciv.models.gamebasics.unit.UnitType import com.unciv.models.gamebasics.unit.UnitType
@ -171,8 +172,8 @@ class WorldScreen : CameraStageBaseScreen() {
else if(currentPlayerCiv.greatPeople.freeGreatPeople>0) game.screen = GreatPersonPickerScreen() else if(currentPlayerCiv.greatPeople.freeGreatPeople>0) game.screen = GreatPersonPickerScreen()
if(game.screen==this && !tutorials.isTutorialShowing if(game.screen==this && !tutorials.isTutorialShowing
&& currentPlayerCiv.diplomaticIncidents.any() && !DiplomaticIncidentPopup.isOpen){ && currentPlayerCiv.popupAlerts.any() && !AlertPopup.isOpen){
DiplomaticIncidentPopup(this,currentPlayerCiv.diplomaticIncidents.first()) AlertPopup(this,currentPlayerCiv.popupAlerts.first())
} }
} }
@ -329,43 +330,59 @@ class WorldScreen : CameraStageBaseScreen() {
} }
class DiplomaticIncidentPopup(val worldScreen: WorldScreen, val diplomaticIncident: DiplomaticIncident):PopupTable(worldScreen){ class AlertPopup(val worldScreen: WorldScreen, val popupAlert: PopupAlert):PopupTable(worldScreen){
fun getCloseButton(text:String): TextButton { fun getCloseButton(text:String): TextButton {
val button = TextButton(text.tr(), skin) val button = TextButton(text.tr(), skin)
button.onClick { close() } button.onClick { close() }
return button return button
} }
init { fun addLeaderName(translatedNation:Nation){
val otherCiv = worldScreen.gameInfo.getCivilization(diplomaticIncident.civName)
val translatedNation = otherCiv.getTranslatedNation()
val otherCivLeaderName = "[${translatedNation.leaderName}] of [${translatedNation.getNameTranslation()}]".tr() val otherCivLeaderName = "[${translatedNation.leaderName}] of [${translatedNation.getNameTranslation()}]".tr()
add(otherCivLeaderName.toLabel()) add(otherCivLeaderName.toLabel())
addSeparator() addSeparator()
}
when(diplomaticIncident.type){ init {
DiplomaticIncidentType.WarDeclaration -> {
when(popupAlert.type){
AlertType.WarDeclaration -> {
val translatedNation = worldScreen.gameInfo.getCivilization(popupAlert.value).getTranslatedNation()
addLeaderName(translatedNation)
addGoodSizedLabel(translatedNation.declaringWar).row() addGoodSizedLabel(translatedNation.declaringWar).row()
val responseTable = Table() val responseTable = Table()
responseTable.add(getCloseButton("You'll pay for this!")) responseTable.add(getCloseButton("You'll pay for this!"))
responseTable.add(getCloseButton("Very well.")) responseTable.add(getCloseButton("Very well."))
add(responseTable) add(responseTable)
} }
DiplomaticIncidentType.Defeated -> { AlertType.Defeated -> {
val translatedNation = worldScreen.gameInfo.getCivilization(popupAlert.value).getTranslatedNation()
addLeaderName(translatedNation)
addGoodSizedLabel(translatedNation.defeated).row() addGoodSizedLabel(translatedNation.defeated).row()
add(getCloseButton("Farewell.")) add(getCloseButton("Farewell."))
} }
DiplomaticIncidentType.FirstContact -> { AlertType.FirstContact -> {
val translatedNation = worldScreen.gameInfo.getCivilization(popupAlert.value).getTranslatedNation()
addLeaderName(translatedNation)
addGoodSizedLabel(translatedNation.introduction).row() addGoodSizedLabel(translatedNation.introduction).row()
add(getCloseButton("A pleasure to meet you.")) add(getCloseButton("A pleasure to meet you."))
} }
AlertType.CityConquered -> {
addGoodSizedLabel("What would you like to do with the city?").row()
add(getCloseButton("Annex")).row()
add(TextButton("Raze",skin).onClick {
worldScreen.currentPlayerCiv.cities.first { it.name==popupAlert.value }.isBeingRazed=true
worldScreen.shouldUpdate=true
close()
})
}
} }
open() open()
isOpen = true isOpen = true
} }
fun close(){ fun close(){
worldScreen.currentPlayerCiv.diplomaticIncidents.remove(diplomaticIncident) worldScreen.currentPlayerCiv.popupAlerts.remove(popupAlert)
isOpen = false isOpen = false
remove() remove()
} }

View file

@ -5,6 +5,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Cell
import com.badlogic.gdx.scenes.scene2d.ui.Label import com.badlogic.gdx.scenes.scene2d.ui.Label
import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.ui.TextButton import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.badlogic.gdx.utils.Align
import com.unciv.UnCivGame import com.unciv.UnCivGame
import com.unciv.models.gamebasics.tr import com.unciv.models.gamebasics.tr
import com.unciv.ui.utils.* import com.unciv.ui.utils.*
@ -27,6 +28,7 @@ open class PopupTable(val screen: CameraStageBaseScreen): Table(CameraStageBaseS
fun addGoodSizedLabel(text: String): Cell<Label> { fun addGoodSizedLabel(text: String): Cell<Label> {
val label = text.toLabel() val label = text.toLabel()
label.setWrap(true) label.setWrap(true)
label.setAlignment(Align.center)
return add(label).width(screen.stage.width/2) return add(label).width(screen.stage.width/2)
} }
@ -43,7 +45,6 @@ class YesNoPopupTable(question:String, action:()->Unit,
if(!screen.hasPopupOpen) { if(!screen.hasPopupOpen) {
screen.hasPopupOpen=true screen.hasPopupOpen=true
add(question.toLabel()).colspan(2).row() add(question.toLabel()).colspan(2).row()
add(TextButton("No".tr(), skin).onClick { close() }) add(TextButton("No".tr(), skin).onClick { close() })
add(TextButton("Yes".tr(), skin).onClick { close(); action() }) add(TextButton("Yes".tr(), skin).onClick { close(); action() })
open() open()

View file

@ -5,6 +5,7 @@ import com.unciv.UnCivGame
import com.unciv.logic.automation.UnitAutomation import com.unciv.logic.automation.UnitAutomation
import com.unciv.logic.automation.WorkerAutomation import com.unciv.logic.automation.WorkerAutomation
import com.unciv.logic.map.MapUnit import com.unciv.logic.map.MapUnit
import com.unciv.logic.map.RoadStatus
import com.unciv.models.gamebasics.Building import com.unciv.models.gamebasics.Building
import com.unciv.models.gamebasics.GameBasics import com.unciv.models.gamebasics.GameBasics
import com.unciv.models.gamebasics.tr import com.unciv.models.gamebasics.tr
@ -140,6 +141,14 @@ class UnitActions {
} }
} }
if(unit.hasUnique("Can construct roads") && tile.roadStatus==RoadStatus.None
&& tile.improvementInProgress != "Road"
&& unit.civInfo.tech.isResearched(GameBasics.TileImprovements["Road"]!!.techRequired!!))
actionList+=UnitAction("Construct road", unit.currentMovement >0){
tile.improvementInProgress="Road"
tile.turnsToImprovement=4
}
for(improvement in listOf("Fishing Boats","Oil well")) { for(improvement in listOf("Fishing Boats","Oil well")) {
if (unit.hasUnique("May create improvements on water resources") && tile.resource != null if (unit.hasUnique("May create improvements on water resources") && tile.resource != null
&& tile.improvement==null && tile.improvement==null

View file

@ -45,6 +45,7 @@ class UnitActionsTable(val worldScreen: WorldScreen) : Table(){
"Create Fishing Boats" -> return ImageGetter.getImprovementIcon("Fishing Boats") "Create Fishing Boats" -> return ImageGetter.getImprovementIcon("Fishing Boats")
"Create Oil well" -> return ImageGetter.getImprovementIcon("Oil well") "Create Oil well" -> return ImageGetter.getImprovementIcon("Oil well")
"Pillage" -> return ImageGetter.getImage("OtherIcons/Pillage") "Pillage" -> return ImageGetter.getImage("OtherIcons/Pillage")
"Construct road" -> return ImageGetter.getImprovementIcon("Road")
else -> return ImageGetter.getImage("OtherIcons/Star") else -> return ImageGetter.getImage("OtherIcons/Star")
} }
} }