Add emphasis alteration.

This commit is contained in:
Thomas Andres Gomez 2024-01-07 19:26:50 +01:00
parent bc7838f8a3
commit aa82fc2347
11 changed files with 85 additions and 9 deletions

View file

@ -22,6 +22,7 @@ import com.pixelized.rplexicon.utilitary.extentions.icon
import com.pixelized.rplexicon.utilitary.extentions.local.advantage
import com.pixelized.rplexicon.utilitary.extentions.local.critical
import com.pixelized.rplexicon.utilitary.extentions.local.disadvantage
import com.pixelized.rplexicon.utilitary.extentions.local.emphasis
import com.pixelized.rplexicon.utilitary.extentions.local.fail
import com.pixelized.rplexicon.utilitary.extentions.local.isBrutalCritical
import com.pixelized.rplexicon.utilitary.extentions.local.isCritical
@ -32,8 +33,10 @@ import com.pixelized.rplexicon.utilitary.extentions.local.toStatus
import com.pixelized.rplexicon.utilitary.extentions.modifier
import com.pixelized.rplexicon.utilitary.extentions.toLabel
import javax.inject.Inject
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min
import kotlin.random.Random
data class DiceThrowResult(
val dice: RollDiceUio,
@ -546,10 +549,12 @@ class DiceThrowUseCase @Inject constructor(
// check if the roll is affected by some status.
val advantage = status[ability].advantage
val disadvantage = status[ability].disadvantage
val emphasis = status[ability].emphasis
// main roll
val result = roll(
advantage = advantage,
disadvantage = disadvantage,
emphasis = emphasis,
fail = status[ability].fail,
critical = status[ability].critical,
)
@ -659,6 +664,7 @@ class DiceThrowUseCase @Inject constructor(
dice = R.drawable.ic_d20_24,
advantage = advantage,
disadvantage = disadvantage,
emphasis = emphasis,
roll = "1d20",
result = result.label,
),
@ -693,6 +699,7 @@ class DiceThrowUseCase @Inject constructor(
// check if the roll is affected by some status.
val advantage = status[ability].advantage
val disadvantage = status[ability].disadvantage
val emphasis = status[ability].emphasis
// compute the amount of main dice to throw.
val amount = if (status.isCritical) {
@ -712,6 +719,7 @@ class DiceThrowUseCase @Inject constructor(
faces = diceThrow?.faces ?: 20,
advantage = advantage,
disadvantage = disadvantage,
emphasis = emphasis,
fail = status[ability].fail,
critical = status[ability].critical,
)
@ -767,6 +775,7 @@ class DiceThrowUseCase @Inject constructor(
dice = diceThrow?.faces?.icon ?: R.drawable.ic_d20_24,
advantage = advantage,
disadvantage = disadvantage,
emphasis = emphasis,
roll = "${diceThrow?.amount}d${diceThrow?.faces}",
result = result.label,
),
@ -791,12 +800,14 @@ class DiceThrowUseCase @Inject constructor(
val advantage = status[Property.SPELL_EFFECT].advantage
val disadvantage = status[Property.SPELL_EFFECT].disadvantage
val emphasis = status[Property.SPELL_EFFECT].emphasis
// main roll
val result = roll(
amount = spell?.effect?.amount ?: 1,
faces = spell?.effect?.faces ?: 4,
advantage = advantage,
disadvantage = disadvantage,
emphasis = emphasis,
fail = status[Property.SPELL_EFFECT].fail,
critical = status[Property.SPELL_EFFECT].critical,
)
@ -809,6 +820,7 @@ class DiceThrowUseCase @Inject constructor(
faces = spell.level.faces,
advantage = advantage,
disadvantage = disadvantage,
emphasis = emphasis,
fail = status[Property.SPELL_EFFECT].fail,
critical = status[Property.SPELL_EFFECT].critical,
)
@ -819,6 +831,7 @@ class DiceThrowUseCase @Inject constructor(
roll = "${spell.level.amount}d${spell.level.faces}",
advantage = advantage,
disadvantage = disadvantage,
emphasis = emphasis,
result = localRoll.label,
),
result = "${localRoll.value}",
@ -855,6 +868,7 @@ class DiceThrowUseCase @Inject constructor(
roll = "${spell?.effect?.amount ?: 1}d${spell?.effect?.faces ?: 4}",
advantage = advantage,
disadvantage = disadvantage,
emphasis = emphasis,
result = result.label,
),
result = "${result.value}",
@ -877,12 +891,14 @@ class DiceThrowUseCase @Inject constructor(
val advantage = status[Property.SKILL].advantage
val disadvantage = status[Property.SKILL].disadvantage
val emphasis = status[Property.SKILL].emphasis
// main roll
val result = roll(
amount = skill?.effect?.amount ?: 1,
faces = skill?.effect?.faces ?: 4,
advantage = advantage,
disadvantage = disadvantage,
emphasis = emphasis,
fail = status[Property.SKILL].fail,
critical = status[Property.SKILL].critical,
)
@ -920,6 +936,7 @@ class DiceThrowUseCase @Inject constructor(
roll = "${skill?.effect?.amount ?: 1}d${skill?.effect?.faces ?: 4}",
advantage = advantage,
disadvantage = disadvantage,
emphasis = emphasis,
result = result.label,
),
result = "${result.value}",
@ -994,6 +1011,7 @@ class DiceThrowUseCase @Inject constructor(
faces = dice.faces,
advantage = dice.advantage,
disadvantage = dice.disadvantage,
emphasis = dice.emphasis,
fail = status.fail,
critical = status.critical,
)
@ -1003,6 +1021,7 @@ class DiceThrowUseCase @Inject constructor(
dice = dice.faces.icon,
advantage = dice.advantage,
disadvantage = dice.disadvantage,
emphasis = dice.emphasis,
roll = "${dice.count}d${dice.faces}",
result = localRoll.label,
),
@ -1029,17 +1048,25 @@ class DiceThrowUseCase @Inject constructor(
/**
* Make a roll of dices.
* @param amount the number of dice.
* @param faces the number of faces on the dices.
* @param advantage does the throws have advantage (roll 2 keep max)
* @param disadvantage does the throws have disadvantage (roll 2 keep min)
* @param emphasis does the throw have emphasis (roll 2, keep furthest away from 10)
* @param fail force the result to be 1
* @param critical force the result to amount.
*/
fun roll(
amount: Int = 1,
faces: Int = 20,
advantage: Boolean = false,
disadvantage: Boolean = false,
emphasis: Boolean,
fail: Boolean = false,
critical: Boolean = false,
): DiceRollResult {
val result = when {
advantage && !disadvantage -> {
advantage && !disadvantage && !emphasis -> {
val roll = List(amount) {
val first = random(faces = faces, fail = fail, critical = critical)
val second = random(faces = faces, fail = fail, critical = critical)
@ -1051,7 +1078,7 @@ class DiceThrowUseCase @Inject constructor(
)
}
disadvantage && !advantage -> {
!advantage && disadvantage && !emphasis -> {
val roll = List(amount) {
val first = random(faces = faces, fail = fail, critical = critical)
val second = random(faces = faces, fail = fail, critical = critical)
@ -1063,6 +1090,27 @@ class DiceThrowUseCase @Inject constructor(
)
}
!advantage && !disadvantage && emphasis -> {
val roll = List(amount) {
var first: Int
var second: Int
do {
first = random(faces = faces, fail = fail, critical = critical)
second = random(faces = faces, fail = fail, critical = critical)
} while (abs(first - 10) == abs(second - 10))
if (abs(first - 10) < abs(second - 10)) {
second to first
} else {
first to second
}
}
DiceRollResult(
label = roll.joinToString(" + ") { "${it.first}~${it.second}" },
value = roll.sumOf { it.first },
)
}
else -> {
val roll = List(amount) {
random(faces = faces, fail = fail, critical = critical)

View file

@ -10,6 +10,7 @@ data class Alteration(
val name: String,
val advantage: Boolean = false,
val disadvantage: Boolean = false,
val emphasis: Boolean = false,
val mastery: Boolean = false,
val expertise: Boolean = false,
val fail: Boolean = false,

View file

@ -12,6 +12,7 @@ data class Roll(
val title: String? = null,
val advantage: Boolean = false,
val disadvantage: Boolean = false,
val emphasis: Boolean,
val count: Int,
val faces: Int,
) {

View file

@ -80,6 +80,10 @@ data class NetworkThrow(
@set:PropertyName(DISADVANTAGE)
var disadvantage: Boolean? = null,
@get:PropertyName(EMPHASIS)
@set:PropertyName(EMPHASIS)
var emphasis: Boolean? = null,
@get:PropertyName(ROLL)
@set:PropertyName(ROLL)
var roll: String = "",
@ -92,6 +96,7 @@ data class NetworkThrow(
const val DICE = "dice"
const val ADVANTAGE = "adv"
const val DISADVANTAGE = "dis"
const val EMPHASIS = "emp"
const val ROLL = "roll"
const val RESULT = "result"
}

View file

@ -86,6 +86,7 @@ class AlterationParser @Inject constructor(
when (value) {
ADVANTAGE -> Alteration.Status(name = name, advantage = true)
DISADVANTAGE -> Alteration.Status(name = name, disadvantage = true)
EMPHASIS -> Alteration.Status(name = name, emphasis = true)
MASTERY -> Alteration.Status(name = name, mastery = true)
EXPERTISE -> Alteration.Status(name = name, expertise = true)
FAIL -> Alteration.Status(name = name, fail = true)
@ -104,6 +105,7 @@ class AlterationParser @Inject constructor(
private const val ALL = "Tous"
private const val ADVANTAGE = "adv"
private const val DISADVANTAGE = "dis"
private const val EMPHASIS = "emp"
private const val MASTERY = "mas"
private const val EXPERTISE = "exp"
private const val FAIL = "fail"

View file

@ -6,7 +6,7 @@ import javax.inject.Inject
class DiceParser @Inject constructor() {
companion object {
private val DICE_REGEX = Regex("(a|adv|d|dis)*(\\d+)d(\\d+)")
private val DICE_REGEX = Regex("(a|adv|d|dis|e|emp)*(\\d+)d(\\d+)")
}
fun findAll(title: String? = null, value: String): List<Roll.Dice> =
@ -20,6 +20,7 @@ class DiceParser @Inject constructor() {
title = title,
advantage = status == "a" || status == "adv",
disadvantage = status == "d" || status == "dis",
emphasis = status == "e" || status == "emp",
count = count.toIntOrNull() ?: 0,
faces = faces.toIntOrNull() ?: 0,
)

View file

@ -403,7 +403,7 @@ private class RollOverlayPreviewProvider : PreviewParameterProvider<RollOverlayP
throws = ThrowsCardUio.Throw(
dice = R.drawable.ic_d20_24,
roll = "1d20",
result = "20"
result = "20",
),
result = "20"
),

View file

@ -25,6 +25,7 @@ class ThrowCardFactory @Inject constructor() {
dice = dice.dice.icon,
advantage = dice.advantage == true,
disadvantage = dice.disadvantage == true,
emphasis = dice.emphasis == true,
roll = dice.roll,
result = dice.result,
)

View file

@ -49,6 +49,7 @@ import com.pixelized.rplexicon.R
import com.pixelized.rplexicon.ui.theme.LexiconTheme
import com.pixelized.rplexicon.utilitary.extentions.annotatedSpan
import com.pixelized.rplexicon.utilitary.extentions.ddBorder
import com.pixelized.rplexicon.utilitary.extentions.lexicon
import com.pixelized.rplexicon.utilitary.highlightRegex
import java.util.UUID
@ -76,6 +77,7 @@ data class ThrowsCardUio(
@DrawableRes val dice: Int, // the throw dice icon
val advantage: Boolean = false, // highlight if advantage
val disadvantage: Boolean = false, // highlight if disadvantage
val emphasis: Boolean = false, // highlight if emphasis
val roll: String, // the roll (1d20, 2d20)
val result: String, // the result
)
@ -226,8 +228,9 @@ private fun ThrowsRollDetail(
.align(alignment = Alignment.Bottom)
.padding(bottom = 2.dp),
tint = when {
it.advantage && !it.disadvantage -> MaterialTheme.colorScheme.primary
it.disadvantage && !it.advantage -> Color.Red
it.advantage && !it.disadvantage && !it.emphasis -> MaterialTheme.lexicon.colorScheme.throwsColor.advantage
!it.advantage && it.disadvantage && !it.emphasis -> MaterialTheme.lexicon.colorScheme.throwsColor.disadvantage
!it.advantage && !it.disadvantage && it.emphasis -> MaterialTheme.lexicon.colorScheme.throwsColor.emphasis
else -> MaterialTheme.colorScheme.onSurface
},
painter = painterResource(id = it.dice),
@ -239,8 +242,6 @@ private fun ThrowsRollDetail(
.weight(1f, false),
color = MaterialTheme.colorScheme.onSurface,
style = MaterialTheme.typography.bodySmall,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
text = it.result,
)
}

View file

@ -7,12 +7,12 @@ import androidx.compose.runtime.Immutable
import androidx.compose.runtime.Stable
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import com.google.accompanist.placeholder.PlaceholderHighlight
@Stable
@Immutable
data class LexiconColors(
val base: ColorScheme,
val throwsColor: ThrowColors,
val placeholder: Color,
val shadow: Color,
val status: Color,
@ -23,6 +23,13 @@ data class LexiconColors(
val characterSheet: CharacterSheet,
val search: Search,
) {
@Stable
data class ThrowColors(
val advantage: Color,
val disadvantage: Color,
val emphasis: Color,
)
@Stable
data class Dice(
val tint: Color,
@ -115,6 +122,11 @@ fun colorScheme(
unSelected = base.onSurface.copy(alpha = 0.5f),
),
),
throwsColor: LexiconColors.ThrowColors = LexiconColors.ThrowColors(
advantage = base.primary,
disadvantage = Color.Red,
emphasis = BaseColorPalette.Purple40,
)
) = LexiconColors(
base = base,
shadow = shadow,
@ -126,4 +138,5 @@ fun colorScheme(
dice = dice,
characterSheet = sheet,
search = search,
throwsColor = throwsColor,
)

View file

@ -22,6 +22,9 @@ val List<Alteration.Status>?.advantage: Boolean
val List<Alteration.Status>?.disadvantage: Boolean
get() = this?.any { it.disadvantage } ?: false
val List<Alteration.Status>?.emphasis: Boolean
get() = this?.any { it.emphasis } ?: false
val List<Alteration.Status>?.mastery: Int
get() = this?.maxOf {
when {