greater patterns now aren't just spells
Akashic Read is deliberately not a greater pattern, so you can distribute trinkets based on it on a server or something
This commit is contained in:
parent
37df5d3c56
commit
4f0e390c14
9 changed files with 86 additions and 42 deletions
|
@ -7,8 +7,7 @@ import net.minecraft.world.phys.Vec3
|
|||
/**
|
||||
* Manipulates the stack in some way, usually by popping some number of values off the stack
|
||||
* and pushing one new value.
|
||||
* For a more "traditional" pop arguments, push return experience, see
|
||||
* [SimpleOperator][at.petrak.hexcasting.api.spell.ConstManaOperator]
|
||||
* For a more "traditional" pop arguments, push return experience, see [ConstManaOperator].
|
||||
*
|
||||
* Implementors MUST NOT mutate the context.
|
||||
*/
|
||||
|
@ -25,10 +24,22 @@ interface Operator {
|
|||
fun operate(continuation: SpellContinuation, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult
|
||||
|
||||
/**
|
||||
* Do you need to be enlightened to use this operator?
|
||||
* Do you need to be enlightened to use this operator? (i.e. is this operator a Great Pattern)
|
||||
*/
|
||||
val isGreat: Boolean get() = false
|
||||
|
||||
/**
|
||||
* Should this Great Pattern process and have side effects, even if its user isn't enlightened?
|
||||
*
|
||||
* The pattern itself may modify its effects based on whether the user is enlightened or not, regardless of what this value is.
|
||||
*/
|
||||
val alwaysProcessGreatSpell: Boolean get() = this is SpellOperator
|
||||
|
||||
/**
|
||||
* Can this Great Pattern give you Blind Diversion?
|
||||
*/
|
||||
val causesBlindDiversion: Boolean get() = this is SpellOperator
|
||||
|
||||
companion object {
|
||||
// I see why vzakii did this: you can't raycast out to infinity!
|
||||
const val MAX_DISTANCE: Double = 32.0
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package at.petrak.hexcasting.api.spell
|
||||
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
|
||||
import at.petrak.hexcasting.api.spell.casting.OperatorSideEffect
|
||||
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
|
||||
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs
|
||||
|
||||
interface SpellOperator : Operator {
|
||||
|
@ -25,13 +25,17 @@ interface SpellOperator : Operator {
|
|||
val executeResult = this.execute(args, ctx) ?: return OperationResult(continuation, stack, local, listOf())
|
||||
val (spell, mana, particles) = executeResult
|
||||
|
||||
val sideEffects = mutableListOf(
|
||||
OperatorSideEffect.ConsumeMana(mana),
|
||||
OperatorSideEffect.AttemptSpell(spell, this.isGreat, this.hasCastingSound(ctx), this.awardsCastingStat(ctx))
|
||||
)
|
||||
for (spray in particles) {
|
||||
val sideEffects = mutableListOf<OperatorSideEffect>()
|
||||
|
||||
if (mana > 0)
|
||||
sideEffects.add(OperatorSideEffect.ConsumeMana(mana))
|
||||
|
||||
// Don't have an effect if the caster isn't enlightened, even if processing other side effects
|
||||
if (!isGreat || ctx.isCasterEnlightened)
|
||||
sideEffects.add(OperatorSideEffect.AttemptSpell(spell, this.hasCastingSound(ctx), this.awardsCastingStat(ctx)))
|
||||
|
||||
for (spray in particles)
|
||||
sideEffects.add(OperatorSideEffect.Particles(spray))
|
||||
}
|
||||
|
||||
return OperationResult(continuation, stack, local, sideEffects)
|
||||
}
|
||||
|
|
|
@ -147,15 +147,32 @@ class CastingHarness private constructor(
|
|||
if (!HexConfig.server().isActionAllowed(operatorIdPair.second)) {
|
||||
throw MishapDisallowedSpell()
|
||||
}
|
||||
val (cont2, stack2, local2, sideEffectsUnmut) = operatorIdPair.first.operate(
|
||||
continuation,
|
||||
this.stack.toMutableList(),
|
||||
this.localIota,
|
||||
this.ctx
|
||||
)
|
||||
this.localIota = local2
|
||||
val pattern = operatorIdPair.first
|
||||
|
||||
val unenlightened = pattern.isGreat && !ctx.isCasterEnlightened
|
||||
|
||||
val sideEffects = mutableListOf<OperatorSideEffect>()
|
||||
var stack2: List<SpellDatum<*>>? = null
|
||||
var cont2 = continuation
|
||||
|
||||
if (!unenlightened || pattern.alwaysProcessGreatSpell) {
|
||||
val result = pattern.operate(
|
||||
continuation,
|
||||
this.stack.toMutableList(),
|
||||
this.localIota,
|
||||
this.ctx
|
||||
)
|
||||
cont2 = result.newContinuation
|
||||
stack2 = result.newStack
|
||||
this.localIota = result.newLocalIota
|
||||
sideEffects.addAll(result.sideEffects)
|
||||
}
|
||||
|
||||
if (unenlightened) {
|
||||
sideEffects.add(OperatorSideEffect.RequiredEnlightenment(pattern.causesBlindDiversion))
|
||||
}
|
||||
|
||||
// Stick a poofy particle effect at the caster position
|
||||
val sideEffects = sideEffectsUnmut.toMutableList()
|
||||
if (this.ctx.spellCircle == null)
|
||||
sideEffects.add(
|
||||
OperatorSideEffect.Particles(
|
||||
|
@ -167,9 +184,11 @@ class CastingHarness private constructor(
|
|||
)
|
||||
)
|
||||
|
||||
val fd = this.getFunctionalData().copy(
|
||||
stack = stack2,
|
||||
)
|
||||
val fd = stack2?.let {
|
||||
this.getFunctionalData().copy(
|
||||
stack = it,
|
||||
)
|
||||
}
|
||||
|
||||
return CastResult(
|
||||
cont2,
|
||||
|
@ -177,6 +196,7 @@ class CastingHarness private constructor(
|
|||
ResolvedPatternType.EVALUATED,
|
||||
sideEffects,
|
||||
)
|
||||
|
||||
} catch (mishap: Mishap) {
|
||||
return CastResult(
|
||||
continuation,
|
||||
|
|
|
@ -22,23 +22,28 @@ sealed class OperatorSideEffect {
|
|||
/** Return whether to cancel all further [OperatorSideEffect] */
|
||||
abstract fun performEffect(harness: CastingHarness): Boolean
|
||||
|
||||
data class RequiredEnlightenment(val awardStat: Boolean) : OperatorSideEffect() {
|
||||
override fun performEffect(harness: CastingHarness): Boolean {
|
||||
harness.ctx.caster.sendMessage(
|
||||
TranslatableComponent("hexcasting.message.cant_great_spell"),
|
||||
Util.NIL_UUID
|
||||
)
|
||||
|
||||
if (awardStat)
|
||||
HexAdvancementTriggers.FAIL_GREAT_SPELL_TRIGGER.trigger(harness.ctx.caster)
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
/** Try to cast a spell */
|
||||
data class AttemptSpell(val spell: RenderedSpell, val isGreat: Boolean, val hasCastingSound: Boolean = true, val awardStat: Boolean = true) :
|
||||
data class AttemptSpell(val spell: RenderedSpell, val hasCastingSound: Boolean = true, val awardStat: Boolean = true) :
|
||||
OperatorSideEffect() {
|
||||
override fun performEffect(harness: CastingHarness): Boolean {
|
||||
return if (this.isGreat && !harness.ctx.isCasterEnlightened) {
|
||||
harness.ctx.caster.sendMessage(
|
||||
TranslatableComponent("hexcasting.message.cant_great_spell"),
|
||||
Util.NIL_UUID
|
||||
)
|
||||
HexAdvancementTriggers.FAIL_GREAT_SPELL_TRIGGER.trigger(harness.ctx.caster)
|
||||
true
|
||||
} else {
|
||||
this.spell.cast(harness.ctx)
|
||||
if (awardStat)
|
||||
harness.ctx.caster.awardStat(HexStatistics.SPELLS_CAST)
|
||||
false
|
||||
}
|
||||
this.spell.cast(harness.ctx)
|
||||
if (awardStat)
|
||||
harness.ctx.caster.awardStat(HexStatistics.SPELLS_CAST)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
package at.petrak.hexcasting.common.casting.operators.akashic
|
||||
|
||||
import at.petrak.hexcasting.api.misc.ManaConstants
|
||||
import at.petrak.hexcasting.api.spell.getChecked
|
||||
import at.petrak.hexcasting.api.spell.ParticleSpray
|
||||
import at.petrak.hexcasting.api.spell.RenderedSpell
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
import at.petrak.hexcasting.api.spell.SpellOperator
|
||||
import at.petrak.hexcasting.api.spell.*
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import at.petrak.hexcasting.api.spell.math.HexPattern
|
||||
import at.petrak.hexcasting.api.spell.mishaps.MishapNoAkashicRecord
|
||||
|
@ -19,6 +15,8 @@ import net.minecraft.world.phys.Vec3
|
|||
object OpAkashicWrite : SpellOperator {
|
||||
override val argc = 3
|
||||
|
||||
override val isGreat = true
|
||||
|
||||
override fun execute(
|
||||
args: List<SpellDatum<*>>,
|
||||
ctx: CastingContext
|
||||
|
|
|
@ -10,6 +10,8 @@ import net.minecraft.world.phys.Vec3
|
|||
class OpCircleBounds(val max: Boolean) : ConstManaOperator {
|
||||
override val argc = 0
|
||||
|
||||
override val isGreat = true
|
||||
|
||||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
|
||||
if (ctx.spellCircle == null)
|
||||
throw MishapNoSpellCircle()
|
||||
|
|
|
@ -10,6 +10,8 @@ import at.petrak.hexcasting.api.spell.mishaps.MishapNoSpellCircle
|
|||
object OpImpetusDir : ConstManaOperator {
|
||||
override val argc = 0
|
||||
|
||||
override val isGreat = true
|
||||
|
||||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
|
||||
if (ctx.spellCircle == null)
|
||||
throw MishapNoSpellCircle()
|
||||
|
|
|
@ -10,6 +10,8 @@ import net.minecraft.world.phys.Vec3
|
|||
object OpImpetusPos : ConstManaOperator {
|
||||
override val argc = 0
|
||||
|
||||
override val isGreat = true
|
||||
|
||||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
|
||||
if (ctx.spellCircle == null)
|
||||
throw MishapNoSpellCircle()
|
||||
|
|
|
@ -5,8 +5,8 @@ import at.petrak.hexcasting.api.spell.Operator
|
|||
import at.petrak.hexcasting.api.spell.RenderedSpell
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
|
||||
import at.petrak.hexcasting.api.spell.casting.OperatorSideEffect
|
||||
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
|
||||
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs
|
||||
import net.minecraft.Util
|
||||
|
||||
|
@ -18,7 +18,7 @@ object OpPrint : Operator {
|
|||
val datum = stack[stack.lastIndex]
|
||||
return OperationResult(
|
||||
continuation, stack, local, listOf(
|
||||
OperatorSideEffect.AttemptSpell(Spell(datum), false)
|
||||
OperatorSideEffect.AttemptSpell(Spell(datum), hasCastingSound = false, awardStat = false)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue