woo, altiora works on fabric and forge
This commit is contained in:
parent
cefd9439db
commit
74690580f6
10 changed files with 76 additions and 26 deletions
|
@ -36,8 +36,8 @@ class OpFlight(val type: Type) : SpellAction {
|
||||||
|
|
||||||
val cost = when (this.type) {
|
val cost = when (this.type) {
|
||||||
Type.LimitRange -> theArg * MediaConstants.DUST_UNIT
|
Type.LimitRange -> theArg * MediaConstants.DUST_UNIT
|
||||||
// A minute of flight should cost a charged crystal?
|
// A second of flight should cost 1 shard
|
||||||
Type.LimitTime -> theArg / 60.0 * MediaConstants.CRYSTAL_UNIT
|
Type.LimitTime -> theArg * MediaConstants.SHARD_UNIT
|
||||||
}.roundToInt()
|
}.roundToInt()
|
||||||
|
|
||||||
// Convert to ticks
|
// Convert to ticks
|
||||||
|
@ -73,22 +73,16 @@ class OpFlight(val type: Type) : SpellAction {
|
||||||
IXplatAbstractions.INSTANCE.setFlight(target, flight)
|
IXplatAbstractions.INSTANCE.setFlight(target, flight)
|
||||||
|
|
||||||
target.abilities.mayfly = true
|
target.abilities.mayfly = true
|
||||||
target.abilities.flying = true
|
|
||||||
// On fabric it only seems to make them actually fly once every other time so let's try this
|
|
||||||
target.onUpdateAbilities()
|
target.onUpdateAbilities()
|
||||||
target.onUpdateAbilities()
|
|
||||||
// Launch the player into the air to really emphasize the flight
|
|
||||||
target.push(0.0, 1.0, 0.0)
|
|
||||||
target.hurtMarked = true // Whyyyyy
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
// danger particles up to 1 block from the edge
|
// blocks from the edge
|
||||||
private val DIST_DANGER_THRESHOLD = 2.0
|
private val DIST_DANGER_THRESHOLD = 4.0
|
||||||
|
|
||||||
// danger particles up to 7 seconds from the limit
|
// seconds left
|
||||||
private val TIME_DANGER_THRESHOLD = 7.0 * 20.0
|
private val TIME_DANGER_THRESHOLD = 7.0 * 20.0
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
@ -155,6 +149,15 @@ class OpFlight(val type: Type) : SpellAction {
|
||||||
|
|
||||||
if (player.level.random.nextFloat() < 0.02)
|
if (player.level.random.nextFloat() < 0.02)
|
||||||
player.level.playSound(null, player.x, player.y, player.z, HexSounds.FLIGHT_AMBIENCE, SoundSource.PLAYERS, 0.2f, 1f)
|
player.level.playSound(null, player.x, player.y, player.z, HexSounds.FLIGHT_AMBIENCE, SoundSource.PLAYERS, 0.2f, 1f)
|
||||||
|
|
||||||
|
if (flight.radius >= 0.0) {
|
||||||
|
// Show the origin
|
||||||
|
val spoofedOrigin = flight.origin.add(0.0, 1.0, 0.0)
|
||||||
|
ParticleSpray(spoofedOrigin, Vec3(0.0, 1.0, 0.0), 0.5, Math.PI * 0.1, count = 5)
|
||||||
|
.sprayParticles(player.getLevel(), color)
|
||||||
|
ParticleSpray(spoofedOrigin, Vec3(0.0, -1.0, 0.0), 1.5, Math.PI * 0.25, count = 5)
|
||||||
|
.sprayParticles(player.getLevel(), color)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,7 +90,7 @@ public interface IXplatAbstractions {
|
||||||
|
|
||||||
@Nullable FlightAbility getFlight(ServerPlayer player);
|
@Nullable FlightAbility getFlight(ServerPlayer player);
|
||||||
|
|
||||||
@Nullable AltioraAbility getAltiora(ServerPlayer player);
|
@Nullable AltioraAbility getAltiora(Player player);
|
||||||
|
|
||||||
FrozenColorizer getColorizer(Player player);
|
FrozenColorizer getColorizer(Player player);
|
||||||
|
|
||||||
|
|
|
@ -1136,6 +1136,14 @@
|
||||||
|
|
||||||
"hexcasting.page.colorize": "I must be holding a $(l:items/pigments)$(item)Pigment/$ in my other hand to cast this spell. When I do, it will consume the dye and permanently change my mind's coloration (at least, until I cast the spell again). Costs about one $(l:items/amethyst)$(item)Amethyst Dust/$.",
|
"hexcasting.page.colorize": "I must be holding a $(l:items/pigments)$(item)Pigment/$ in my other hand to cast this spell. When I do, it will consume the dye and permanently change my mind's coloration (at least, until I cast the spell again). Costs about one $(l:items/amethyst)$(item)Amethyst Dust/$.",
|
||||||
|
|
||||||
|
"hexcasting.entry.flights": "Flight",
|
||||||
|
"hexcasting.page.flights.1": "Although it seems that true, limitless flight is out of my grasp, I have nonetheless found some methods of holding one in the sky, each with their respective drawbacks.$(br2)All forms produce a shimmer of excess _media; as the spell gets closer to ending, the sparks are shot through with more red and black.",
|
||||||
|
"hexcasting.page.flights.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.",
|
||||||
|
"hexcasting.page.flights.range.1": "A flight limited in its range.",
|
||||||
|
"hexcasting.page.flights.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.",
|
||||||
|
"hexcasting.page.flights.time.1": "A flight limited in its duration.",
|
||||||
|
"hexcasting.page.flights.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)Charged Crystal/$ per second of flight; I believe it is best suited for travel.",
|
||||||
|
|
||||||
"hexcasting.page.create_lava.1": "Summon a block of lava (or insert up to a bucket's worth) into a block at the given position. Costs about one $(l:items/amethyst)$(item)Charged Amethyst/$.",
|
"hexcasting.page.create_lava.1": "Summon a block of lava (or insert up to a bucket's worth) into a block at the given position. Costs about one $(l:items/amethyst)$(item)Charged Amethyst/$.",
|
||||||
"hexcasting.page.create_lava.2": "It may be advisable to keep my knowledge of this spell secret. A certain faction of botanists get... touchy about it, or so I've heard.$(br2)Well, no one said tracing the deep secrets of the universe was going to be an easy time.",
|
"hexcasting.page.create_lava.2": "It may be advisable to keep my knowledge of this spell secret. A certain faction of botanists get... touchy about it, or so I've heard.$(br2)Well, no one said tracing the deep secrets of the universe was going to be an easy time.",
|
||||||
|
|
||||||
|
@ -1144,8 +1152,8 @@
|
||||||
"hexcasting.page.weather_manip.summon_rain": "I control the clouds! This spell will summon rain across the world I cast it upon. Costs about one $(l:items/amethyst)$(item)Charged Amethyst/$. Does nothing if it is already raining.",
|
"hexcasting.page.weather_manip.summon_rain": "I control the clouds! This spell will summon rain across the world I cast it upon. Costs about one $(l:items/amethyst)$(item)Charged Amethyst/$. Does nothing if it is already raining.",
|
||||||
"hexcasting.page.weather_manip.dispel_rain": "A counterpart to summoning rain. This spell will dispel rain across the world I cast it upon. Costs about one $(l:items/amethyst)$(item)Amethyst Shard/$. Does nothing if the skies are already clear.",
|
"hexcasting.page.weather_manip.dispel_rain": "A counterpart to summoning rain. This spell will dispel rain across the world I cast it upon. Costs about one $(l:items/amethyst)$(item)Amethyst Shard/$. Does nothing if the skies are already clear.",
|
||||||
|
|
||||||
"hexcasting.page.flight.1": "The power of flight! I have wrestled Nature to its knees. But Nature is vengeful, and itches for me to break its contract so it may break my shins.",
|
"hexcasting.page.altiora.1": "Summon a sheaf of _media about me in the shape of wings, endowed with enough substance to allow gliding.",
|
||||||
"hexcasting.page.flight.2": "The entity (which must be a player) will be endowed with flight. The first number is the number of seconds they may fly for, and the second number is the radius of the zone they may fly in. If the recipient exits that zone, or their timer runs out while midair, the gravity that they spurned will get its revenge. Painfully.$(br2)It costs one quarter of an $(l:items/amethyst)$(item)Amethyst Dust/$, per meter of radius, per second in flight.",
|
"hexcasting.page.altiora.2": "Using them is identical to using $(item)Elytra/$; the target (which must be a player) is lofted into the air, after which pressing $(k:jump) will deploy the wings. The wings are fragile, and break upon touching any surface. Longer flights may benefit from $(l:patterns/spells/basic#hexcasting:add_motion)$(action)Impulse/$ or (for the foolhardy) $(item)Fireworks/$.$(br2)Costs about one $(l:items/amethyst)$(item)Charged Crystal/$.",
|
||||||
|
|
||||||
"hexcasting.page.teleport.1": "Far more powerful than $(l:patterns/spells/basic#hexcasting:blink)$(action)Blink/$, this spell lets me teleport nearly anywhere in the entire world! There does seem to be a limit, but it is $(italic)much/$ greater than the normal radius of influence I am used to.",
|
"hexcasting.page.teleport.1": "Far more powerful than $(l:patterns/spells/basic#hexcasting:blink)$(action)Blink/$, this spell lets me teleport nearly anywhere in the entire world! There does seem to be a limit, but it is $(italic)much/$ greater than the normal radius of influence I am used to.",
|
||||||
"hexcasting.page.teleport.2": "The entity will be teleported by the given vector, which is an offset from its given position. No matter the distance, it always seems to cost about ten $(l:items/amethyst)$(item)Charged Amethyst/$.$(br2)The transference is not perfect, and it seems when teleporting something as complex as a player, their inventory doesn't $(italic)quite/$ stay attached, and tends to splatter everywhere at the destination. In addition, the target will be forcibly removed from anything inanimate they are riding or sitting on ... but I've read scraps that suggest animals can come along for the ride, so to speak.",
|
"hexcasting.page.teleport.2": "The entity will be teleported by the given vector, which is an offset from its given position. No matter the distance, it always seems to cost about ten $(l:items/amethyst)$(item)Charged Amethyst/$.$(br2)The transference is not perfect, and it seems when teleporting something as complex as a player, their inventory doesn't $(italic)quite/$ stay attached, and tends to splatter everywhere at the destination. In addition, the target will be forcibly removed from anything inanimate they are riding or sitting on ... but I've read scraps that suggest animals can come along for the ride, so to speak.",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "hexcasting.action.hexcasting:flight",
|
"name": "hexcasting.action.hexcasting:flight",
|
||||||
"category": "hexcasting:patterns/great_spells",
|
"category": "hexcasting:patterns/great_spells",
|
||||||
"icon": "minecraft:feather",
|
"icon": "minecraft:elytra",
|
||||||
"sortnum": 2,
|
"sortnum": 2,
|
||||||
"advancement": "hexcasting:root",
|
"advancement": "hexcasting:root",
|
||||||
"read_by_default": true,
|
"read_by_default": true,
|
||||||
|
@ -12,11 +12,11 @@
|
||||||
"anchor": "hexcasting:flight",
|
"anchor": "hexcasting:flight",
|
||||||
"input": "entity, number, number",
|
"input": "entity, number, number",
|
||||||
"output": "",
|
"output": "",
|
||||||
"text": "hexcasting.page.flight.1"
|
"text": "hexcasting.page.altiora.1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "patchouli:text",
|
"type": "patchouli:text",
|
||||||
"text": "hexcasting.page.flight.2"
|
"text": "hexcasting.page.altiora.2"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
"name": "hexcasting.entry.flights",
|
||||||
|
"category": "hexcasting:patterns/spells",
|
||||||
|
"icon": "minecraft:feather",
|
||||||
|
"advancement": "hexcasting:root",
|
||||||
|
"sortnum": 6,
|
||||||
|
"read_by_default": true,
|
||||||
|
"pages": [
|
||||||
|
"hexcasting.page.flights.1",
|
||||||
|
"hexcasting.page.flights.2",
|
||||||
|
{
|
||||||
|
"type": "hexcasting:pattern",
|
||||||
|
"op_id": "hexcasting:flight/range",
|
||||||
|
"anchor": "hexcasting:flight/range",
|
||||||
|
"input": "entity, number",
|
||||||
|
"output": "",
|
||||||
|
"text": "hexcasting.page.flights.range.1"
|
||||||
|
},
|
||||||
|
"hexcasting.page.flights.range.2",
|
||||||
|
{
|
||||||
|
"type": "hexcasting:pattern",
|
||||||
|
"op_id": "hexcasting:flight/time",
|
||||||
|
"anchor": "hexcasting:flight/time",
|
||||||
|
"input": "entity, number",
|
||||||
|
"output": "",
|
||||||
|
"text": "hexcasting.page.flights.time.1"
|
||||||
|
},
|
||||||
|
"hexcasting.page.flights.time.2"
|
||||||
|
]
|
||||||
|
}
|
|
@ -49,8 +49,8 @@ import net.fabricmc.fabric.api.registry.FlammableBlockRegistry
|
||||||
import net.minecraft.commands.synchronization.SingletonArgumentInfo
|
import net.minecraft.commands.synchronization.SingletonArgumentInfo
|
||||||
import net.minecraft.core.Registry
|
import net.minecraft.core.Registry
|
||||||
import net.minecraft.resources.ResourceLocation
|
import net.minecraft.resources.ResourceLocation
|
||||||
import net.minecraft.server.level.ServerPlayer
|
|
||||||
import net.minecraft.world.InteractionResult
|
import net.minecraft.world.InteractionResult
|
||||||
|
import net.minecraft.world.entity.player.Player
|
||||||
import java.util.function.BiConsumer
|
import java.util.function.BiConsumer
|
||||||
|
|
||||||
object FabricHexInitializer : ModInitializer {
|
object FabricHexInitializer : ModInitializer {
|
||||||
|
@ -108,7 +108,7 @@ object FabricHexInitializer : ModInitializer {
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityElytraEvents.CUSTOM.register { target, _ ->
|
EntityElytraEvents.CUSTOM.register { target, _ ->
|
||||||
if (target is ServerPlayer) {
|
if (target is Player) {
|
||||||
val altiora = IXplatAbstractions.INSTANCE.getAltiora(target)
|
val altiora = IXplatAbstractions.INSTANCE.getAltiora(target)
|
||||||
altiora != null
|
altiora != null
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -2,21 +2,20 @@ package at.petrak.hexcasting.fabric.cc;
|
||||||
|
|
||||||
import at.petrak.hexcasting.api.player.AltioraAbility;
|
import at.petrak.hexcasting.api.player.AltioraAbility;
|
||||||
import dev.onyxstudios.cca.api.v3.component.Component;
|
import dev.onyxstudios.cca.api.v3.component.Component;
|
||||||
|
import dev.onyxstudios.cca.api.v3.component.sync.AutoSyncedComponent;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public class CCAltiora implements Component {
|
public class CCAltiora implements Component, AutoSyncedComponent {
|
||||||
public static final String
|
public static final String
|
||||||
TAG_ALLOWED = "allowed",
|
TAG_ALLOWED = "allowed",
|
||||||
TAG_GRACE = "grace_period";
|
TAG_GRACE = "grace_period";
|
||||||
|
|
||||||
private final ServerPlayer owner;
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private AltioraAbility altiora = null;
|
private AltioraAbility altiora = null;
|
||||||
|
|
||||||
public CCAltiora(ServerPlayer owner) {
|
public CCAltiora(Player owner) {
|
||||||
this.owner = owner;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,9 @@ public class HexCardinalComponents implements EntityComponentInitializer, ItemCo
|
||||||
registry.registerFor(ServerPlayer.class, HARNESS, CCHarness::new);
|
registry.registerFor(ServerPlayer.class, HARNESS, CCHarness::new);
|
||||||
registry.registerFor(ServerPlayer.class, PATTERNS, CCPatterns::new);
|
registry.registerFor(ServerPlayer.class, PATTERNS, CCPatterns::new);
|
||||||
|
|
||||||
|
// On Fabric, this is needed on the client because the c/s need to agree on when wings are being deployed
|
||||||
|
registry.registerForPlayers(ALTIORA, CCAltiora::new, RespawnCopyStrategy.LOSSLESS_ONLY);
|
||||||
|
|
||||||
registry.registerFor(ItemEntity.class, IOTA_HOLDER, wrapItemEntityDelegate(
|
registry.registerFor(ItemEntity.class, IOTA_HOLDER, wrapItemEntityDelegate(
|
||||||
ItemDelegatingEntityIotaHolder.ToItemEntity::new));
|
ItemDelegatingEntityIotaHolder.ToItemEntity::new));
|
||||||
registry.registerFor(ItemFrame.class, IOTA_HOLDER, wrapItemEntityDelegate(
|
registry.registerFor(ItemFrame.class, IOTA_HOLDER, wrapItemEntityDelegate(
|
||||||
|
|
|
@ -169,6 +169,7 @@ public class FabricXplatImpl implements IXplatAbstractions {
|
||||||
public void setAltiora(ServerPlayer target, @Nullable AltioraAbility altiora) {
|
public void setAltiora(ServerPlayer target, @Nullable AltioraAbility altiora) {
|
||||||
var cc = HexCardinalComponents.ALTIORA.get(target);
|
var cc = HexCardinalComponents.ALTIORA.get(target);
|
||||||
cc.setAltiora(altiora);
|
cc.setAltiora(altiora);
|
||||||
|
HexCardinalComponents.ALTIORA.sync(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -196,7 +197,7 @@ public class FabricXplatImpl implements IXplatAbstractions {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable AltioraAbility getAltiora(ServerPlayer player) {
|
public @Nullable AltioraAbility getAltiora(Player player) {
|
||||||
var cc = HexCardinalComponents.ALTIORA.get(player);
|
var cc = HexCardinalComponents.ALTIORA.get(player);
|
||||||
return cc.getAltiora();
|
return cc.getAltiora();
|
||||||
}
|
}
|
||||||
|
|
|
@ -167,6 +167,7 @@ public class ForgeXplatImpl implements IXplatAbstractions {
|
||||||
tag.remove(TAG_ALTIORA_ALLOWED);
|
tag.remove(TAG_ALTIORA_ALLOWED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The elytra ability is done with an event on fabric
|
||||||
var elytraing = CaelusApi.getInstance().getFlightAttribute();
|
var elytraing = CaelusApi.getInstance().getFlightAttribute();
|
||||||
var inst = player.getAttributes().getInstance(elytraing);
|
var inst = player.getAttributes().getInstance(elytraing);
|
||||||
if (altiora != null) {
|
if (altiora != null) {
|
||||||
|
@ -243,7 +244,12 @@ public class ForgeXplatImpl implements IXplatAbstractions {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AltioraAbility getAltiora(ServerPlayer player) {
|
public AltioraAbility getAltiora(Player anyPlayer) {
|
||||||
|
if (!(anyPlayer instanceof ServerPlayer player)) {
|
||||||
|
// the check only needs to happen client-side on fabric
|
||||||
|
// which is great, cause it's not even synced on forge
|
||||||
|
return null;
|
||||||
|
}
|
||||||
CompoundTag tag = player.getPersistentData();
|
CompoundTag tag = player.getPersistentData();
|
||||||
boolean allowed = tag.getBoolean(TAG_ALTIORA_ALLOWED);
|
boolean allowed = tag.getBoolean(TAG_ALTIORA_ALLOWED);
|
||||||
if (allowed) {
|
if (allowed) {
|
||||||
|
|
Loading…
Reference in a new issue