Skip to content

Commit

Permalink
Add multiplayer turn sound notification (#6995)
Browse files Browse the repository at this point in the history
* Refactor: Extract methods & reduce code duplication

* Refactor: Rename Sounds to SoundPlayer

* Refactor: Make UncivSound a data class

As far as I can see, UncivSoundConstants served no purpose

* Refactor: Reorder sounds

* Refactor: Split up ExtensionFunctions and move into own package

* Add multiplayer turn sound notification

* Refactor: Remove unnecessary double translation

* Refactor: Reduce code duplication

* Refactor: No if for boolean logic
  • Loading branch information
Azzurite authored Jun 10, 2022
1 parent 9918353 commit 3e6fc0e
Show file tree
Hide file tree
Showing 182 changed files with 1,732 additions and 974 deletions.
17 changes: 13 additions & 4 deletions android/assets/jsons/translations/template.properties
Original file line number Diff line number Diff line change
Expand Up @@ -602,12 +602,16 @@ Resign =
Are you sure you want to resign? =
You can only resign if it's your turn =
[civName] resigned and is now controlled by AI =
Last refresh: [time] [timeUnit] ago =
Current Turn: [civName] since [time] [timeUnit] ago =
Last refresh: [duration] ago =
Current Turn: [civName] since [duration] ago =
Seconds =
Minutes =
Hours =
Days =
[amount] Seconds =
[amount] Minutes =
[amount] Hours =
[amount] Days =
Server limit reached! Please wait for [time] seconds =
File could not be found on the multiplayer server =
Unhandled problem, [errorMessage] =
Expand Down Expand Up @@ -1395,7 +1399,7 @@ Doing this will reset your current user ID to the clipboard contents - are you s
ID successfully set! =
Invalid ID! =
# Multiplayer options menu
# Multiplayer options tab
Enable multiplayer status button in singleplayer games =
Update status of currently played game every: =
Expand All @@ -1406,7 +1410,12 @@ Check connection to server =
Awaiting response... =
Success! =
Failed! =
Sound notification for when it's your turn in your currently open game: =
Sound notification for when it's your turn in any other game: =
Notification [number] =
Chimes =
Choir =
[unit] Attack Sound =
# Mods
Expand Down
Binary file added android/assets/sounds/notification1.mp3
Binary file not shown.
Binary file added android/assets/sounds/notification2.mp3
Binary file not shown.
25 changes: 19 additions & 6 deletions core/src/com/unciv/MainMenuScreen.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.unciv

import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.Input
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.actions.Actions
import com.badlogic.gdx.scenes.scene2d.ui.Table
Expand All @@ -14,22 +14,35 @@ import com.unciv.logic.map.MapSizeNew
import com.unciv.logic.map.MapType
import com.unciv.logic.map.mapgenerator.MapGenerator
import com.unciv.models.metadata.BaseRuleset
import com.unciv.models.ruleset.RulesetCache
import com.unciv.ui.multiplayer.MultiplayerScreen
import com.unciv.ui.mapeditor.*
import com.unciv.models.metadata.GameSetupInfo
import com.unciv.models.ruleset.RulesetCache
import com.unciv.ui.civilopedia.CivilopediaScreen
import com.unciv.ui.crashhandling.launchCrashHandling
import com.unciv.ui.crashhandling.postCrashHandlingRunnable
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.mapeditor.EditorMapHolder
import com.unciv.ui.mapeditor.MapEditorScreen
import com.unciv.ui.multiplayer.MultiplayerScreen
import com.unciv.ui.map.TileGroupMap
import com.unciv.ui.newgamescreen.NewGameScreen
import com.unciv.ui.pickerscreens.ModManagementScreen
import com.unciv.ui.popup.*
import com.unciv.ui.popup.ExitGamePopup
import com.unciv.ui.popup.Popup
import com.unciv.ui.popup.ToastPopup
import com.unciv.ui.popup.closeAllPopups
import com.unciv.ui.popup.hasOpenPopups
import com.unciv.ui.popup.popups
import com.unciv.ui.saves.LoadGameScreen
import com.unciv.ui.saves.QuickSave
import com.unciv.ui.utils.*
import com.unciv.ui.utils.AutoScrollPane
import com.unciv.ui.utils.BaseScreen
import com.unciv.ui.utils.KeyCharAndCode
import com.unciv.ui.utils.UncivTooltip.Companion.addTooltip
import com.unciv.ui.utils.extensions.center
import com.unciv.ui.utils.extensions.onClick
import com.unciv.ui.utils.extensions.setFontSize
import com.unciv.ui.utils.extensions.surroundWithCircle
import com.unciv.ui.utils.extensions.toLabel
import com.unciv.ui.worldscreen.mainmenu.WorldScreenMenuPopup
import kotlin.math.min

Expand Down
52 changes: 30 additions & 22 deletions core/src/com/unciv/UncivGame.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,28 @@ import com.badlogic.gdx.utils.Align
import com.unciv.logic.GameInfo
import com.unciv.logic.GameSaver
import com.unciv.logic.civilization.PlayerType
import com.unciv.logic.multiplayer.OnlineMultiplayer
import com.unciv.models.metadata.GameSettings
import com.unciv.models.ruleset.RulesetCache
import com.unciv.models.tilesets.TileSetCache
import com.unciv.models.translations.Translations
import com.unciv.ui.LanguagePickerScreen
import com.unciv.ui.audio.GameSounds
import com.unciv.ui.audio.MusicController
import com.unciv.ui.audio.MusicMood
import com.unciv.ui.utils.*
import com.unciv.ui.worldscreen.PlayerReadyScreen
import com.unciv.ui.worldscreen.WorldScreen
import com.unciv.logic.multiplayer.OnlineMultiplayer
import com.unciv.ui.LanguagePickerScreen
import com.unciv.ui.audio.Sounds
import com.unciv.ui.audio.SoundPlayer
import com.unciv.ui.crashhandling.closeExecutors
import com.unciv.ui.crashhandling.launchCrashHandling
import com.unciv.ui.crashhandling.postCrashHandlingRunnable
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.multiplayer.LoadDeepLinkScreen
import com.unciv.ui.multiplayer.MultiplayerHelpers
import com.unciv.ui.popup.Popup
import com.unciv.ui.utils.BaseScreen
import com.unciv.ui.utils.extensions.center
import com.unciv.ui.crashhandling.wrapCrashHandlingUnit
import com.unciv.ui.worldscreen.PlayerReadyScreen
import com.unciv.ui.worldscreen.WorldScreen
import com.unciv.utils.debug
import kotlinx.coroutines.runBlocking
import java.util.*
Expand Down Expand Up @@ -103,6 +106,7 @@ class UncivGame(parameters: UncivGameParameters) : Game() {
*/
settings = gameSaver.getGeneralSettings() // needed for the screen
screen = LoadingScreen() // NOT dependent on any atlas or skin
GameSounds.init()
musicController = MusicController() // early, but at this point does only copy volume from settings
audioExceptionHelper?.installHooks(
musicController.getAudioLoopCallback(),
Expand Down Expand Up @@ -194,23 +198,25 @@ class UncivGame(parameters: UncivGameParameters) : Game() {
}

private fun tryLoadDeepLinkedGame() = launchCrashHandling("LoadDeepLinkedGame") {
if (deepLinkedMultiplayerGame != null) {
if (deepLinkedMultiplayerGame == null) return@launchCrashHandling

postCrashHandlingRunnable {
setScreen(LoadDeepLinkScreen())
}
try {
onlineMultiplayer.loadGame(deepLinkedMultiplayerGame!!)
} catch (ex: Exception) {
postCrashHandlingRunnable {
setScreen(LoadDeepLinkScreen())
}
try {
onlineMultiplayer.loadGame(deepLinkedMultiplayerGame!!)
} catch (ex: Exception) {
postCrashHandlingRunnable {
val mainMenu = MainMenuScreen()
setScreen(mainMenu)
val popup = Popup(mainMenu)
popup.addGoodSizedLabel(MultiplayerHelpers.getLoadExceptionMessage(ex))
popup.row()
popup.addCloseButton()
popup.open()
}
val mainMenu = MainMenuScreen()
setScreen(mainMenu)
val popup = Popup(mainMenu)
popup.addGoodSizedLabel(MultiplayerHelpers.getLoadExceptionMessage(ex))
popup.row()
popup.addCloseButton()
popup.open()
}
} finally {
deepLinkedMultiplayerGame = null
}
}

Expand Down Expand Up @@ -242,7 +248,7 @@ class UncivGame(parameters: UncivGameParameters) : Game() {
Gdx.input.inputProcessor = null // don't allow ANRs when shutting down, that's silly

cancelDiscordEvent?.invoke()
Sounds.clearCache()
SoundPlayer.clearCache()
if (::musicController.isInitialized) musicController.gracefulShutdown() // Do allow fade-out
closeExecutors()

Expand Down Expand Up @@ -274,6 +280,8 @@ class UncivGame(parameters: UncivGameParameters) : Game() {
companion object {
lateinit var Current: UncivGame
fun isCurrentInitialized() = this::Current.isInitialized
fun isCurrentGame(gameId: String): Boolean = isCurrentInitialized() && Current.isGameInfoInitialized() && Current.gameInfo.gameId == gameId
fun isDeepLinkedGameLoading() = isCurrentInitialized() && Current.deepLinkedMultiplayerGame != null
}
}

Expand Down
2 changes: 1 addition & 1 deletion core/src/com/unciv/logic/BarbarianManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import com.unciv.logic.map.TileInfo
import com.unciv.logic.map.TileMap
import com.unciv.models.metadata.GameSpeed
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.ui.utils.randomWeighted
import com.unciv.ui.utils.extensions.randomWeighted
import java.util.*
import kotlin.math.max
import kotlin.math.min
Expand Down
11 changes: 8 additions & 3 deletions core/src/com/unciv/logic/battle/Battle.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ package com.unciv.logic.battle
import com.badlogic.gdx.math.Vector2
import com.unciv.Constants
import com.unciv.UncivGame
import com.unciv.utils.debug
import com.unciv.logic.city.CityInfo
import com.unciv.logic.civilization.*
import com.unciv.logic.civilization.AlertType
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.civilization.LocationAction
import com.unciv.logic.civilization.NotificationIcon
import com.unciv.logic.civilization.PlayerType
import com.unciv.logic.civilization.PopupAlert
import com.unciv.logic.civilization.diplomacy.DiplomaticModifiers
import com.unciv.logic.civilization.diplomacy.DiplomaticStatus
import com.unciv.logic.map.RoadStatus
Expand All @@ -18,7 +22,8 @@ import com.unciv.models.ruleset.unique.Unique
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.stats.Stat
import com.unciv.models.stats.Stats
import com.unciv.ui.utils.toPercent
import com.unciv.ui.utils.extensions.toPercent
import com.unciv.utils.debug
import java.util.*
import kotlin.math.max
import kotlin.math.min
Expand Down
2 changes: 1 addition & 1 deletion core/src/com/unciv/logic/battle/BattleDamage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import com.unciv.models.ruleset.unique.Unique
import com.unciv.models.ruleset.unique.UniqueTarget
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.translations.tr
import com.unciv.ui.utils.toPercent
import com.unciv.ui.utils.extensions.toPercent
import java.util.*
import kotlin.collections.set
import kotlin.math.max
Expand Down
8 changes: 4 additions & 4 deletions core/src/com/unciv/logic/battle/CityCombatant.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import com.unciv.models.UncivSound
import com.unciv.models.ruleset.unique.StateForConditionals
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.models.ruleset.unit.UnitType
import com.unciv.ui.utils.toPercent
import com.unciv.ui.utils.extensions.toPercent
import kotlin.math.pow
import kotlin.math.roundToInt

Expand Down Expand Up @@ -54,14 +54,14 @@ class CityCombatant(val city: CityInfo) : ICombatant {
// The way all of this adds up...
// All ancient techs - 0.5 extra, Classical - 2.7, Medieval - 8, Renaissance - 17.5,
// Industrial - 32.4, Modern - 51, Atomic - 72.5, All - 118.3

// Garrisoned unit gives up to 20% of strength to city, health-dependant
if (cityTile.militaryUnit != null)
strength += cityTile.militaryUnit!!.baseUnit().strength * (cityTile.militaryUnit!!.health / 100f) * modConstants.cityStrengthFromGarrison

var buildingsStrength = city.cityConstructions.getBuiltBuildings().sumOf { it.cityStrength }.toFloat()
val stateForConditionals = StateForConditionals(getCivInfo(), city, ourCombatant = this, combatAction = combatAction)

for (unique in getCivInfo().getMatchingUniques(UniqueType.BetterDefensiveBuildings, stateForConditionals))
buildingsStrength *= unique.params[0].toPercent()
strength += buildingsStrength
Expand All @@ -70,4 +70,4 @@ class CityCombatant(val city: CityInfo) : ICombatant {
}

override fun toString() = city.name // for debug
}
}
8 changes: 4 additions & 4 deletions core/src/com/unciv/logic/battle/MapUnitCombatant.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ class MapUnitCombatant(val unit: MapUnit) : ICombatant {
override fun isInvisible(to: CivilizationInfo): Boolean = unit.isInvisible(to)
override fun canAttack(): Boolean = unit.canAttack()
override fun matchesCategory(category: String) = unit.matchesFilter(category)
override fun getAttackSound() = unit.baseUnit.attackSound.let {
if (it==null) UncivSound.Click else UncivSound.custom(it)
override fun getAttackSound() = unit.baseUnit.attackSound.let {
if (it == null) UncivSound.Click else UncivSound(it)
}

override fun takeDamage(damage: Int) {
Expand Down Expand Up @@ -50,10 +50,10 @@ class MapUnitCombatant(val unit: MapUnit) : ICombatant {
return unit.name+" of "+unit.civInfo.civName
}

fun getMatchingUniques(uniqueType: UniqueType, conditionalState: StateForConditionals, checkCivUniques: Boolean): Sequence<Unique> =
fun getMatchingUniques(uniqueType: UniqueType, conditionalState: StateForConditionals, checkCivUniques: Boolean): Sequence<Unique> =
unit.getMatchingUniques(uniqueType, conditionalState, checkCivUniques)

fun hasUnique(uniqueType: UniqueType, conditionalState: StateForConditionals? = null): Boolean =
if (conditionalState == null) unit.hasUnique(uniqueType)
else unit.hasUnique(uniqueType, conditionalState)
}
}
10 changes: 4 additions & 6 deletions core/src/com/unciv/logic/city/CityConstructions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import com.unciv.logic.automation.ConstructionAutomation
import com.unciv.logic.civilization.AlertType
import com.unciv.logic.civilization.NotificationIcon
import com.unciv.logic.civilization.PopupAlert
import com.unciv.logic.map.MapUnit // for Kdoc only
import com.unciv.logic.map.MapUnit
import com.unciv.logic.map.TileInfo
import com.unciv.models.ruleset.Building
import com.unciv.models.ruleset.Ruleset
Expand All @@ -21,11 +21,9 @@ import com.unciv.models.translations.tr
import com.unciv.ui.civilopedia.CivilopediaCategories
import com.unciv.ui.civilopedia.FormattedLine
import com.unciv.ui.utils.Fonts
import com.unciv.ui.utils.withItem
import com.unciv.ui.utils.withoutItem
import com.unciv.ui.worldscreen.unit.UnitActions // for Kdoc only
import java.util.*
import kotlin.collections.ArrayList
import com.unciv.ui.utils.extensions.withItem
import com.unciv.ui.utils.extensions.withoutItem
import com.unciv.ui.worldscreen.unit.UnitActions
import kotlin.math.ceil
import kotlin.math.roundToInt

Expand Down
12 changes: 6 additions & 6 deletions core/src/com/unciv/logic/city/CityExpansionManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import com.unciv.logic.civilization.NotificationIcon
import com.unciv.logic.map.TileInfo
import com.unciv.models.ruleset.unique.LocalUniqueCache
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.ui.utils.toPercent
import com.unciv.ui.utils.withItem
import com.unciv.ui.utils.withoutItem
import com.unciv.ui.utils.extensions.toPercent
import com.unciv.ui.utils.extensions.withItem
import com.unciv.ui.utils.extensions.withoutItem
import kotlin.math.max
import kotlin.math.pow
import kotlin.math.roundToInt
Expand Down Expand Up @@ -64,18 +64,18 @@ class CityExpansionManager {
val baseCost = 50
val distanceFromCenter = tileInfo.aerialDistanceTo(cityInfo.getCenterTile())
var cost = baseCost * (distanceFromCenter - 1) + tilesClaimed() * 5.0

for (unique in cityInfo.getMatchingUniques(UniqueType.TileCostPercentage)) {
if (cityInfo.matchesFilter(unique.params[1]))
cost *= unique.params[0].toPercent()
}

return cost.roundToInt()
}

fun getChoosableTiles() = cityInfo.getCenterTile().getTilesInDistance(5)
.filter { it.getOwner() == null }

fun chooseNewTileToOwn(): TileInfo? {
// Technically, in the original a random tile with the lowest score was selected
// However, doing this requires either caching it, which is way more work,
Expand Down
4 changes: 2 additions & 2 deletions core/src/com/unciv/logic/city/CityInfoConquestFunctions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import com.unciv.Constants
import com.unciv.UncivGame
import com.unciv.utils.debug
import com.unciv.logic.battle.Battle
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.civilization.NotificationIcon
Expand All @@ -12,7 +11,8 @@ import com.unciv.logic.trade.TradeLogic
import com.unciv.logic.trade.TradeOffer
import com.unciv.logic.trade.TradeType
import com.unciv.models.ruleset.unique.UniqueType
import com.unciv.ui.utils.withoutItem
import com.unciv.ui.utils.extensions.withoutItem
import com.unciv.utils.debug
import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToInt
Expand Down
Loading

0 comments on commit 3e6fc0e

Please sign in to comment.