From fb6b82aedcd9154eef13cbddccd52914ea7ba701 Mon Sep 17 00:00:00 2001 From: Robotgiggle <88736742+Robotgiggle@users.noreply.github.com> Date: Sun, 10 May 2026 17:48:27 -0400 Subject: [PATCH 1/5] Rebalance flight costs --- .../hexcasting/common/casting/actions/spells/OpFlight.kt | 7 ++----- .../resources/assets/hexcasting/lang/en_us.flatten.json5 | 4 ++-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt index 9258cc059e..328f80c923 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt @@ -35,11 +35,8 @@ class OpFlight(val type: Type) : SpellAction { val theArg = args.getPositiveDouble(1, argc) env.assertEntityInRange(target) - val cost = when (this.type) { - Type.LimitRange -> theArg * MediaConstants.DUST_UNIT - // A second of flight should cost 1 shard - Type.LimitTime -> theArg * MediaConstants.SHARD_UNIT - }.roundToLong() + // One block of radius, or one second of duration, costs 2 dust + val cost = (theArg * 2 * MediaConstants.DUST_UNIT).roundToLong() // Convert to ticks return SpellAction.Result( diff --git a/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 b/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 index 298e680936..81a59bf626 100644 --- a/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 +++ b/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 @@ -2103,10 +2103,10 @@ "2": "Other forms of flight do exist, of course. For example, a combination of $(l:patterns/spells/basic#hexcasting:add_motion)$(action)Impulse/$ and $(l:patterns/spells/nadirs#hexcasting:potion/levitation)$(action)Blue Sun's Nadir/$ has been used since antiquity for a flight of sorts.$(br2)I've also heard tell of a thin membrane worn on the back that allows the ability to glide. From my research, I believe the Great spell $(l:patterns/great_spells/altiora)$(action)Altiora/$ may be used to mimic it.", "range.1": "A flight limited in its range.", - "range.2": "The second argument is a horizontal radius, in meters, in which the spell is stable. Moving outside of that radius will end the spell, dropping me out of the sky. As long as I stay inside the safe zone, however, the spell lasts indefinitely. An additional shimmer of _media marks the origin point of the safe zone. $(br2)Costs about 1 $(l:items/amethyst)$(item)Amethyst Dust/$ per meter of safety.", + "range.2": "The second argument is a horizontal radius, in meters, in which the spell is stable. Moving outside of that radius will end the spell, dropping me out of the sky. As long as I stay inside the safe zone, however, the spell lasts indefinitely. An additional shimmer of _media marks the origin point of the safe zone. $(br2)Costs about 2 $(l:items/amethyst)$(item)Amethyst Dust/$ per meter of safety, with a minimum radius of 1 meter.", "time.1": "A flight limited in its duration.", - "time.2": "The second argument is an amount of time in seconds for which the spell is stable. After that time, the spell ends and I am dropped from the sky. $(br2)It is relatively expensive at about 1 $(l:items/amethyst)$(item)Amethyst Shard/$ per second of flight; I believe it is best suited for travel.", + "time.2": "The second argument is an amount of time in seconds for which the spell is stable. After that time, the spell ends and I am dropped from the sky. $(br2)Costs about 2 $(l:items/amethyst)$(item)Amethyst Dust/$ per second of flight; I believe it is best suited for travel.", // Putting this in this category instead of elsewhere -- see sentinel chapter also containing some reflections/nonspells "can_fly.1": "Returns whether the given player is under the effects of $(l:patterns/spells/flight#hexcasting:flight/range)Anchorite's/$ or $(l:patterns/spells/flight#hexcasting:flight/time)Wayfarer's Flight/$.", From 8c554307cd4c96491c4c15a0f7f83b601def4622 Mon Sep 17 00:00:00 2001 From: Robotgiggle <88736742+Robotgiggle@users.noreply.github.com> Date: Sun, 10 May 2026 17:50:10 -0400 Subject: [PATCH 2/5] Minimum radius for anchorite --- .../at/petrak/hexcasting/api/casting/ActionUtils.kt | 11 +++++++++++ .../common/casting/actions/spells/OpFlight.kt | 6 +++++- .../assets/hexcasting/lang/en_us.flatten.json5 | 1 + 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt index c6dda37c9a..1e7631d703 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt @@ -152,6 +152,17 @@ fun List.getPositiveDoubleUnderInclusive(idx: Int, max: Double, argc: Int throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "double.positive.less.equal", max) } +fun List.getDoubleAboveInclusive(idx: Int, min: Double, argc: Int = 0): Double { + val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } + if (x is DoubleIota) { + val double = x.double + if (double >= min) { + return double + } + } + throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "double.greater.equal", min) +} + fun List.getDoubleBetween(idx: Int, min: Double, max: Double, argc: Int = 0): Double { val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } if (x is DoubleIota) { diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt index 328f80c923..7d08d0db52 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt @@ -4,6 +4,7 @@ import at.petrak.hexcasting.api.casting.ParticleSpray import at.petrak.hexcasting.api.casting.RenderedSpell import at.petrak.hexcasting.api.casting.castables.SpellAction import at.petrak.hexcasting.api.casting.eval.CastingEnvironment +import at.petrak.hexcasting.api.casting.getDoubleAboveInclusive import at.petrak.hexcasting.api.casting.getPlayer import at.petrak.hexcasting.api.casting.getPositiveDouble import at.petrak.hexcasting.api.casting.iota.Iota @@ -32,7 +33,10 @@ class OpFlight(val type: Type) : SpellAction { env: CastingEnvironment ): SpellAction.Result { val target = args.getPlayer(0, argc) - val theArg = args.getPositiveDouble(1, argc) + val theArg = when (this.type) { + Type.LimitRange -> args.getDoubleAboveInclusive(1, 1.0, argc) + Type.LimitTime -> args.getPositiveDouble(1, argc) + } env.assertEntityInRange(target) // One block of radius, or one second of duration, costs 2 dust diff --git a/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 b/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 index 81a59bf626..e904452cee 100644 --- a/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 +++ b/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 @@ -1124,6 +1124,7 @@ less: "a positive number less than %d", "less.equal": "a positive number less than or equal to %d", }, + "greater.equal": "a number greater than or equal to %d", between: "a number between %d and %d", }, From 934d01176cf40911720a6a8608c8a4c6968196f5 Mon Sep 17 00:00:00 2001 From: Robotgiggle <88736742+Robotgiggle@users.noreply.github.com> Date: Sun, 10 May 2026 20:25:15 -0400 Subject: [PATCH 3/5] Change minimum radius to minimum cost --- .../at/petrak/hexcasting/api/casting/ActionUtils.kt | 11 ----------- .../common/casting/actions/spells/OpFlight.kt | 10 ++++------ .../assets/hexcasting/lang/en_us.flatten.json5 | 2 +- 3 files changed, 5 insertions(+), 18 deletions(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt index 1e7631d703..c6dda37c9a 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt @@ -152,17 +152,6 @@ fun List.getPositiveDoubleUnderInclusive(idx: Int, max: Double, argc: Int throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "double.positive.less.equal", max) } -fun List.getDoubleAboveInclusive(idx: Int, min: Double, argc: Int = 0): Double { - val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } - if (x is DoubleIota) { - val double = x.double - if (double >= min) { - return double - } - } - throw MishapInvalidIota.of(x, if (argc == 0) idx else argc - (idx + 1), "double.greater.equal", min) -} - fun List.getDoubleBetween(idx: Int, min: Double, max: Double, argc: Int = 0): Double { val x = this.getOrElse(idx) { throw MishapNotEnoughArgs(idx + 1, this.size) } if (x is DoubleIota) { diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt index 7d08d0db52..58b955aa62 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt @@ -4,7 +4,6 @@ import at.petrak.hexcasting.api.casting.ParticleSpray import at.petrak.hexcasting.api.casting.RenderedSpell import at.petrak.hexcasting.api.casting.castables.SpellAction import at.petrak.hexcasting.api.casting.eval.CastingEnvironment -import at.petrak.hexcasting.api.casting.getDoubleAboveInclusive import at.petrak.hexcasting.api.casting.getPlayer import at.petrak.hexcasting.api.casting.getPositiveDouble import at.petrak.hexcasting.api.casting.iota.Iota @@ -33,14 +32,13 @@ class OpFlight(val type: Type) : SpellAction { env: CastingEnvironment ): SpellAction.Result { val target = args.getPlayer(0, argc) - val theArg = when (this.type) { - Type.LimitRange -> args.getDoubleAboveInclusive(1, 1.0, argc) - Type.LimitTime -> args.getPositiveDouble(1, argc) - } + val theArg = args.getPositiveDouble(1, argc) env.assertEntityInRange(target) // One block of radius, or one second of duration, costs 2 dust - val cost = (theArg * 2 * MediaConstants.DUST_UNIT).roundToLong() + var cost = (theArg * 2 * MediaConstants.DUST_UNIT).roundToLong() + // Cost for anchorite does not decrease below 1 meter + if (type == Type.LimitRange) cost = max(cost, 2 * MediaConstants.DUST_UNIT) // Convert to ticks return SpellAction.Result( diff --git a/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 b/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 index e904452cee..c04d48b1a0 100644 --- a/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 +++ b/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 @@ -2104,7 +2104,7 @@ "2": "Other forms of flight do exist, of course. For example, a combination of $(l:patterns/spells/basic#hexcasting:add_motion)$(action)Impulse/$ and $(l:patterns/spells/nadirs#hexcasting:potion/levitation)$(action)Blue Sun's Nadir/$ has been used since antiquity for a flight of sorts.$(br2)I've also heard tell of a thin membrane worn on the back that allows the ability to glide. From my research, I believe the Great spell $(l:patterns/great_spells/altiora)$(action)Altiora/$ may be used to mimic it.", "range.1": "A flight limited in its range.", - "range.2": "The second argument is a horizontal radius, in meters, in which the spell is stable. Moving outside of that radius will end the spell, dropping me out of the sky. As long as I stay inside the safe zone, however, the spell lasts indefinitely. An additional shimmer of _media marks the origin point of the safe zone. $(br2)Costs about 2 $(l:items/amethyst)$(item)Amethyst Dust/$ per meter of safety, with a minimum radius of 1 meter.", + "range.2": "The second argument is a horizontal radius, in meters, in which the spell is stable. Moving outside of that radius will end the spell, dropping me out of the sky. As long as I stay inside the safe zone, however, the spell lasts indefinitely. An additional shimmer of _media marks the origin point of the safe zone. $(br2)Costs about 2 $(l:items/amethyst)$(item)Amethyst Dust/$ per meter of safety, though any radius less than 1 meter will still cost 2 $(l:items/amethyst)$(item)Amethyst Dust/$.", "time.1": "A flight limited in its duration.", "time.2": "The second argument is an amount of time in seconds for which the spell is stable. After that time, the spell ends and I am dropped from the sky. $(br2)Costs about 2 $(l:items/amethyst)$(item)Amethyst Dust/$ per second of flight; I believe it is best suited for travel.", From d0e75ef9f545597a703546730b1a2680dec6b082 Mon Sep 17 00:00:00 2001 From: Robotgiggle <88736742+Robotgiggle@users.noreply.github.com> Date: Sun, 10 May 2026 20:30:12 -0400 Subject: [PATCH 4/5] Update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4498b2755..09e2aa712d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ### Changed - Changed the `media_consumption` attribute to only apply to player-based casting, by Robotgiggle in [987](https://github.com/FallingColors/HexMod/pull/987). +- Decreased the cost of Wayfarer's Flight to 2 dust per second, by Robotgiggle in [#1040](https://github.com/FallingColors/HexMod/pull/1040). +- Increased the cost of Anchorite's Flight to 2 dust per meter and capped the cost at 2 dust for radii below 1 meter, by Robotgiggle in [#1040](https://github.com/FallingColors/HexMod/pull/1040). ### Fixed From 2b2c1eea348d1c0abce32f194d33dd9bfc6b44b5 Mon Sep 17 00:00:00 2001 From: Robotgiggle <88736742+Robotgiggle@users.noreply.github.com> Date: Sun, 10 May 2026 23:33:16 -0400 Subject: [PATCH 5/5] Apply feedback, remove unused lang key --- CHANGELOG.md | 3 +-- .../hexcasting/common/casting/actions/spells/OpFlight.kt | 5 +++-- .../resources/assets/hexcasting/lang/en_us.flatten.json5 | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 09e2aa712d..c56d54f120 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,8 +13,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ### Changed - Changed the `media_consumption` attribute to only apply to player-based casting, by Robotgiggle in [987](https://github.com/FallingColors/HexMod/pull/987). -- Decreased the cost of Wayfarer's Flight to 2 dust per second, by Robotgiggle in [#1040](https://github.com/FallingColors/HexMod/pull/1040). -- Increased the cost of Anchorite's Flight to 2 dust per meter and capped the cost at 2 dust for radii below 1 meter, by Robotgiggle in [#1040](https://github.com/FallingColors/HexMod/pull/1040). +- Changed Wayfarer's Flight and Anchorite's Flight to both cost 2 dust per unit and enforced a minimum cost for Anchorite's Flight, by Robotgiggle in [#1040](https://github.com/FallingColors/HexMod/pull/1040). ### Fixed diff --git a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt index 58b955aa62..0bf708bce6 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt +++ b/Common/src/main/java/at/petrak/hexcasting/common/casting/actions/spells/OpFlight.kt @@ -36,9 +36,10 @@ class OpFlight(val type: Type) : SpellAction { env.assertEntityInRange(target) // One block of radius, or one second of duration, costs 2 dust - var cost = (theArg * 2 * MediaConstants.DUST_UNIT).roundToLong() + val costUnit = 2 * MediaConstants.DUST_UNIT + var cost = (theArg * costUnit).roundToLong() // Cost for anchorite does not decrease below 1 meter - if (type == Type.LimitRange) cost = max(cost, 2 * MediaConstants.DUST_UNIT) + if (type == Type.LimitRange) cost = max(cost, costUnit) // Convert to ticks return SpellAction.Result( diff --git a/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 b/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 index c04d48b1a0..dd39d0e0c5 100644 --- a/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 +++ b/Common/src/main/resources/assets/hexcasting/lang/en_us.flatten.json5 @@ -1124,7 +1124,6 @@ less: "a positive number less than %d", "less.equal": "a positive number less than or equal to %d", }, - "greater.equal": "a number greater than or equal to %d", between: "a number between %d and %d", },