Skip to content

Commit 86bf836

Browse files
authored
Merge pull request #4 from fmasa/traits
Traits
2 parents 2368fe4 + 5bd84ef commit 86bf836

File tree

45 files changed

+1453
-27
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1453
-27
lines changed

common/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ kotlin {
8686
implementation("com.halilibo.compose-richtext:richtext-commonmark:$richtextVersion")
8787
implementation("com.halilibo.compose-richtext:richtext-ui-material:$richtextVersion")
8888
implementation("io.github.z4kn4fein:semver:1.3.3")
89+
90+
implementation("org.jsoup:jsoup:1.15.3")
8991
}
9092
}
9193

common/firebase/src/androidMain/kotlin/cz/frantisekmasa/wfrp_master/common/firebase/firestore/Transaction.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,8 @@ actual class Transaction(private val transaction: NativeTransaction) {
66
actual fun set(documentReference: DocumentReference, fields: Map<String, Any?>, options: SetOptions) {
77
transaction.set(documentReference.toNative(), fields, options.toNative())
88
}
9+
10+
actual fun delete(documentReference: DocumentReference) {
11+
transaction.delete(documentReference.toNative())
12+
}
913
}

common/firebase/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/firebase/firestore/Transaction.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ package cz.frantisekmasa.wfrp_master.common.firebase.firestore
22

33
expect class Transaction {
44
fun set(documentReference: DocumentReference, fields: Map<String, Any?>, options: SetOptions)
5+
fun delete(documentReference: DocumentReference)
56
}

common/firebase/src/jvmMain/kotlin/cz/frantisekmasa/wfrp_master/common/firebase/firestore/Transaction.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,8 @@ actual class Transaction(private val batch: WriteBatch) {
66
actual fun set(documentReference: DocumentReference, fields: Map<String, Any?>, options: SetOptions) {
77
batch.set(documentReference.toNative(), fields, options.toNative())
88
}
9+
10+
actual fun delete(documentReference: DocumentReference) {
11+
batch.delete(documentReference.toNative())
12+
}
913
}

common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/DependencyInjection.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ import cz.frantisekmasa.wfrp_master.common.character.CharacterPickerScreenModel
55
import cz.frantisekmasa.wfrp_master.common.character.CharacterScreenModel
66
import cz.frantisekmasa.wfrp_master.common.character.characteristics.CharacteristicsScreenModel
77
import cz.frantisekmasa.wfrp_master.common.character.combat.CharacterCombatScreenModel
8+
import cz.frantisekmasa.wfrp_master.common.character.effects.TraitEffectFactory
89
import cz.frantisekmasa.wfrp_master.common.character.religion.blessings.BlessingsScreenModel
910
import cz.frantisekmasa.wfrp_master.common.character.religion.miracles.MiraclesScreenModel
1011
import cz.frantisekmasa.wfrp_master.common.character.skills.SkillsScreenModel
1112
import cz.frantisekmasa.wfrp_master.common.character.spells.SpellsScreenModel
1213
import cz.frantisekmasa.wfrp_master.common.character.talents.TalentsScreenModel
14+
import cz.frantisekmasa.wfrp_master.common.character.traits.TraitsScreenModel
1315
import cz.frantisekmasa.wfrp_master.common.character.trappings.TrappingsScreenModel
1416
import cz.frantisekmasa.wfrp_master.common.characterCreation.CharacterCreationScreenModel
1517
import cz.frantisekmasa.wfrp_master.common.combat.CombatScreenModel
@@ -19,6 +21,7 @@ import cz.frantisekmasa.wfrp_master.common.compendium.domain.Miracle
1921
import cz.frantisekmasa.wfrp_master.common.compendium.domain.Skill
2022
import cz.frantisekmasa.wfrp_master.common.compendium.domain.Spell
2123
import cz.frantisekmasa.wfrp_master.common.compendium.domain.Talent
24+
import cz.frantisekmasa.wfrp_master.common.compendium.domain.Trait
2225
import cz.frantisekmasa.wfrp_master.common.core.PartyScreenModel
2326
import cz.frantisekmasa.wfrp_master.common.core.cache.CharacterRepositoryIdentityMap
2427
import cz.frantisekmasa.wfrp_master.common.core.cache.PartyRepositoryIdentityMap
@@ -37,6 +40,7 @@ import cz.frantisekmasa.wfrp_master.common.core.domain.religion.MiracleRepositor
3740
import cz.frantisekmasa.wfrp_master.common.core.domain.skills.SkillRepository
3841
import cz.frantisekmasa.wfrp_master.common.core.domain.spells.SpellRepository
3942
import cz.frantisekmasa.wfrp_master.common.core.domain.talents.TalentRepository
43+
import cz.frantisekmasa.wfrp_master.common.core.domain.traits.TraitRepository
4044
import cz.frantisekmasa.wfrp_master.common.core.domain.trappings.InventoryItemRepository
4145
import cz.frantisekmasa.wfrp_master.common.core.firebase.Schema
4246
import cz.frantisekmasa.wfrp_master.common.core.firebase.functions.CloudFunctionCharacterAvatarChanger
@@ -111,6 +115,10 @@ val appModule = DI.Module("Common") {
111115
FirestoreCompendium(Schema.Compendium.Miracles, instance(), mapper())
112116
}
113117

118+
bindSingleton<Compendium<Trait>> {
119+
FirestoreCompendium(Schema.Compendium.Traits, instance(), mapper())
120+
}
121+
114122
bindSingleton { DismissedUserTipsHolder(instance()) }
115123

116124
bindSingleton<InvitationProcessor> { FirestoreInvitationProcessor(instance(), instance()) }
@@ -120,6 +128,7 @@ val appModule = DI.Module("Common") {
120128
bindSingleton<BlessingRepository> { characterItemRepository(Schema.Character.Blessings) }
121129
bindSingleton<MiracleRepository> { characterItemRepository(Schema.Character.Miracles) }
122130
bindSingleton<InventoryItemRepository> { characterItemRepository(Schema.Character.InventoryItems) }
131+
bindSingleton<TraitRepository> { characterItemRepository(Schema.Character.Traits) }
123132

124133
bindSingleton<CharacterRepository> {
125134
CharacterRepositoryIdentityMap(10, FirestoreCharacterRepository(instance(), mapper()))
@@ -173,6 +182,11 @@ val appModule = DI.Module("Common") {
173182
bindFactory { characterId: CharacterId ->
174183
BlessingsScreenModel(characterId, instance(), instance())
175184
}
185+
186+
bindSingleton { TraitEffectFactory() }
187+
bindFactory { characterId: CharacterId ->
188+
TraitsScreenModel(characterId, instance(), instance(), instance(), instance(), instance())
189+
}
176190
bindProvider { InvitationScreenModel(instance(), instance(), instance()) }
177191
bindProvider { PartyListScreenModel(instance()) }
178192
bindProvider { SettingsScreenModel(instance(), instance()) }
@@ -186,6 +200,7 @@ val appModule = DI.Module("Common") {
186200
instance(),
187201
instance(),
188202
instance(),
203+
instance(),
189204
)
190205
}
191206
bindFactory { partyId: PartyId -> GameMasterScreenModel(partyId, instance(), instance()) }
@@ -205,6 +220,7 @@ val appModule = DI.Module("Common") {
205220
instance(),
206221
instance(),
207222
instance(),
223+
instance(),
208224
)
209225
}
210226
bindFactory { partyId: PartyId -> PartySettingsScreenModel(partyId, instance()) }

common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/character/CharacterDetailScreen.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ data class CharacterDetailScreen(
329329
screenModel = screenModel,
330330
skillsScreenModel = rememberScreenModel(arg = characterId),
331331
talentsScreenModel = rememberScreenModel(arg = characterId),
332+
traitsScreenModel = rememberScreenModel(arg = characterId),
332333
modifier = modifier,
333334
)
334335
}

common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/character/CompendiumItemChooser.kt

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ internal fun <A : CharacterItem, B : CompendiumItem<B>> CompendiumItemChooser(
3737
icon: @Composable (B) -> Resources.Drawable,
3838
screenModel: CharacterItemScreenModel<A, B>,
3939
onSelect: suspend (B) -> Unit,
40-
onCustomItemRequest: () -> Unit,
40+
onCustomItemRequest: (() -> Unit)? = null,
4141
onDismissRequest: () -> Unit,
42-
customItemButtonText: String,
42+
customItemButtonText: String = "",
4343
emptyUiIcon: Resources.Drawable,
4444
) {
4545
val compendiumItems =
@@ -85,14 +85,16 @@ internal fun <A : CharacterItem, B : CompendiumItem<B>> CompendiumItemChooser(
8585
)
8686
}
8787

88-
Surface(elevation = 8.dp) {
89-
OutlinedButton(
90-
modifier = Modifier
91-
.fillMaxWidth()
92-
.padding(Spacing.bodyPadding),
93-
onClick = onCustomItemRequest,
94-
) {
95-
Text(customItemButtonText)
88+
if (onCustomItemRequest != null && customItemButtonText != "") {
89+
Surface(elevation = 8.dp) {
90+
OutlinedButton(
91+
modifier = Modifier
92+
.fillMaxWidth()
93+
.padding(Spacing.bodyPadding),
94+
onClick = onCustomItemRequest,
95+
) {
96+
Text(customItemButtonText)
97+
}
9698
}
9799
}
98100
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package cz.frantisekmasa.wfrp_master.common.character.effects
2+
3+
import cz.frantisekmasa.wfrp_master.common.core.domain.character.Character
4+
5+
interface CharacterEffect {
6+
fun apply(character: Character, otherEffects: List<CharacterEffect>): Character
7+
fun revert(character: Character, otherEffects: List<CharacterEffect>): Character
8+
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package cz.frantisekmasa.wfrp_master.common.character.effects
2+
3+
import cz.frantisekmasa.wfrp_master.common.core.domain.Stats
4+
import cz.frantisekmasa.wfrp_master.common.core.domain.character.Character
5+
6+
open class CharacteristicChange(
7+
private val plus: Stats = Stats.ZERO,
8+
private val minus: Stats = Stats.ZERO,
9+
) : CharacterEffect {
10+
11+
override fun apply(character: Character, otherEffects: List<CharacterEffect>): Character {
12+
return character.updateCharacteristics(
13+
base = character.characteristicsBase + plus - minus,
14+
advances = character.characteristicsAdvances,
15+
)
16+
}
17+
18+
override fun revert(character: Character, otherEffects: List<CharacterEffect>): Character {
19+
return character.updateCharacteristics(
20+
base = character.characteristicsBase + minus - plus,
21+
advances = character.characteristicsAdvances,
22+
)
23+
}
24+
25+
companion object {
26+
fun fromTraitNameOrNull(name: String): CharacteristicChange? {
27+
val cleanName = name.lowercase()
28+
29+
if (cleanName == "big") {
30+
return CharacteristicChange(
31+
plus = Stats.ZERO.copy(
32+
strength = 10,
33+
toughness = 10,
34+
),
35+
minus = Stats.ZERO.copy(
36+
agility = 5,
37+
),
38+
)
39+
}
40+
41+
if (cleanName == "brute") {
42+
return CharacteristicChange(
43+
plus = Stats.ZERO.copy(
44+
toughness = 10,
45+
strength = 10,
46+
),
47+
minus = Stats.ZERO.copy(
48+
agility = 10,
49+
),
50+
)
51+
}
52+
53+
if (cleanName == "clever") {
54+
return CharacteristicChange(
55+
plus = Stats.ZERO.copy(
56+
intelligence = 10,
57+
initiative = 10,
58+
),
59+
)
60+
}
61+
62+
if (cleanName == "cunning") {
63+
return CharacteristicChange(
64+
plus = Stats.ZERO.copy(
65+
intelligence = 10,
66+
fellowship = 10,
67+
initiative = 10,
68+
)
69+
)
70+
}
71+
72+
if (cleanName == "elite") {
73+
return CharacteristicChange(
74+
plus = Stats.ZERO.copy(
75+
weaponSkill = 20,
76+
ballisticSkill = 20,
77+
willPower = 20,
78+
)
79+
)
80+
}
81+
82+
if (cleanName == "leader") {
83+
return CharacteristicChange(
84+
plus = Stats.ZERO.copy(
85+
fellowship = 10,
86+
willPower = 10,
87+
)
88+
)
89+
}
90+
91+
if (cleanName == "tough") {
92+
return CharacteristicChange(
93+
plus = Stats.ZERO.copy(
94+
toughness = 10,
95+
willPower = 10,
96+
)
97+
)
98+
}
99+
100+
if (cleanName == "swarm") {
101+
return CharacteristicChange(
102+
plus = Stats.ZERO.copy(
103+
weaponSkill = 10,
104+
)
105+
)
106+
}
107+
108+
return null
109+
}
110+
}
111+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package cz.frantisekmasa.wfrp_master.common.character.effects
2+
3+
import cz.frantisekmasa.wfrp_master.common.core.domain.Size
4+
import cz.frantisekmasa.wfrp_master.common.core.domain.character.Character
5+
6+
/**
7+
* Change character size to according to largest Size(...) trait
8+
*/
9+
class SizeChange(private val size: Size) : CharacterEffect {
10+
11+
override fun apply(character: Character, otherEffects: List<CharacterEffect>): Character {
12+
return character.changeSize(
13+
(otherEffects.filterIsInstance<SizeChange>() + this)
14+
.maxOf { it.size }
15+
)
16+
}
17+
18+
override fun revert(character: Character, otherEffects: List<CharacterEffect>): Character {
19+
return character.changeSize(
20+
otherEffects.filterIsInstance<SizeChange>()
21+
.maxOfOrNull { it.size }
22+
)
23+
}
24+
25+
companion object {
26+
fun fromTraitNameOrNull(name: String): SizeChange? {
27+
val match = Regex("Size \\((.*)\\)", RegexOption.IGNORE_CASE).matchEntire(name)
28+
?: return null
29+
30+
val size = match.groupValues[1].trim()
31+
32+
return Size.values().firstOrNull { it.name.equals(size, ignoreCase = true) }
33+
?.let { SizeChange(it) }
34+
}
35+
}
36+
}

0 commit comments

Comments
 (0)