-
Notifications
You must be signed in to change notification settings - Fork 72
Utility Systems
The Minecraft player client controls sprinting. The server cannot reliably control it. Instead, you have to use some tricks to cancel or prevent sprinting. Players can sprint by double-tapping their Forward control (W by default) or using their Sprint key.
You can cancel sprinting for a player by:
- flashing a menu at them
- giving them the
blindnesspotion effect for a short duration - setting their food level to 6 (3 bars), which is under the sprint requirement
If they have Sprinting set to the Hold option, then double-tab only initiates sprint on that action, not if they stop sprinting at a later point. Other actions that let the player sprint try to ensure that whatever stops them from sprinting (like being stopped by a block) restarts sprinting if that sprint action is active. So, most of the ways that cancel sprinting will just resume them if you don't ensure they happen every time the player starts sprinting and end when they stop.
The easiest way to cancel sprinting is by removing the sprinting modifier from their movement attribute. The player remains in "sprinting" mode, but the speed is modified as if they are not sprinting.
Modifier details:
Attribute: "minecraft:movement_speed"
ID: "minecraft:sprinting"
Operation: add
Value: 0.3Example spell:
sprint_cancel:
spell-class: ".targeted.EntityEditSpell"
helper-spell: true
target-self: true
remove: true
attributes:
# Remove action only cares about the ID, but I left the value anyway.
- movement_speed 0.3 add_number * minecraft:sprintingMagicSpells had a "dance casting" system that has been abandoned because it was always quite hard-coded and inflexible. This is a system that required you to perform certain actions or movements in sequence in order to cast a spell of that sequence. Here's how you can replicate a system like that.
We can make a PassiveSpell per input movement, and track recent movements in a variable by appending the last movement to the sequence.
variables:
dance_sequence:
type: playerstring
dance_input_forward:
spell-class: ".PassiveSpell"
always-granted: true
spells: . . .
variable-mods-cast: [dance_sequence +F]
triggers:
- trigger: input
on-press: [forward]Assuming a table of movements:
F - forward
B - backward
L - left
R - right
J - jump
S - sneak
We can use the sequence FRBL to refer to the sequence: forward, right, back, left.
We can use a ParseSpell to validate if the last bit of the sequence matches any valid sequence, by using the regex pattern (dance pattern)$, where $ marks the ending of the string, therefore requiring that the pattern is only found at the ending of the variable.
variables:
dance_sequence:
type: playerstring
dance_sequence_valid:
type: playerstring
dance_check_regex:
spell-class: ".targeted.ParseSpell"
helper-spell: true
target-self: true
operation: regex
variable-to-parse: dance_sequence
expected-value: "FRBL$"
parse-to-variable: dance_sequence_validInstead of needing to configure a Parse spell per valid sequence, we can use variables and variable replacement, so all our magic is done with one spell.
Here we shortened the logic further, using the cast modifier condition, which casts a spell and passes if the spell succeeds. The dance_check only succeeds if the regex pattern matches the one passed; otherwise, it fails.
variables:
dance_sequence:
type: playerstring
dance_sequence_temp:
type: playerstring
dance_sequence_valid:
type: playerstring
dance_check_all:
spell-class: ".instant.DummySpell"
helper-spell: true
modifiers:
- cast dance_check(args=[FRBL]) cast dance_spell_1(mode=full)
- cast dance_check(args=[BFFJ]) cast dance_spell_2(mode=full)
dance_check:
spell-class: ".instant.DummySpell"
helper-spell: true
modifiers:
- always string dance_sequence_temp %arg:1%
- always cast dance_check_regex
- variablestringequals dance_sequence_valid=dance_sequence_temp require
dance_check_regex:
spell-class: ".targeted.ParseSpell"
helper-spell: true
target-self: true
operation: regex
variable-to-parse: dance_sequence
expected-value: "%var:dance_sequence_temp%$"
parse-to-variable: dance_sequence_validIn the final version you can reveal below, we just attached the dance_check_all to be cast by every input Passive spell, made all the input trackers we want to have, and made a "control" duration spell called dance. I made that spell to showcase how we can make our input Passive spells not constantly record and attach movement to the variable, but only for a short duration, by using the buffactive dance require condition on them. Otherwise, you should probably occasionally clear the variable to avoid taking up unnecessary memory.
Full System example
variables:
dance_sequence:
type: playerstring
dance_sequence_temp:
type: playerstring
dance_sequence_valid:
type: playerstring
dance:
spell-class: ".buff.DummySpell"
always-granted: true
duration: 10
str-cast-self: "You begin to dance."
str-fade: "Your dancing no longer has an effect."
variable-mods-cast: ["dance_sequence ="]
dance_spell_1:
spell-class: ".instant.DummySpell"
helper-spell: true
str-cast-self: "Cast spell #1"
dance_spell_2:
spell-class: ".instant.DummySpell"
helper-spell: true
str-cast-self: "Cast spell #2"
# --- [ Validate dances ] ---
dance_check_all:
spell-class: ".instant.DummySpell"
helper-spell: true
modifiers:
- cast dance_check(args=[FRBL]) cast dance_spell_1(mode=full)
- cast dance_check(args=[BFFJ]) cast dance_spell_2(mode=full)
dance_check:
spell-class: ".instant.DummySpell"
helper-spell: true
modifiers:
- always string dance_sequence_temp %arg:1%
- always cast dance_check_regex
- variablestringequals dance_sequence_valid=dance_sequence_temp require
dance_check_regex:
spell-class: ".targeted.ParseSpell"
helper-spell: true
target-self: true
operation: regex
variable-to-parse: dance_sequence
expected-value: "%var:dance_sequence_temp%$"
parse-to-variable: dance_sequence_valid
# --- [ Inputs ] ---
# F - forward
# B - backward
# L - left
# R - right
# J - jump
# S - sneak
dance_input_forward:
spell-class: ".PassiveSpell"
always-granted: true
spells: [dance_check_all]
modifiers: [buffactive dance require]
variable-mods-cast: [dance_sequence +F]
triggers:
- trigger: input
on-press: [forward]
dance_input_backward:
spell-class: ".PassiveSpell"
always-granted: true
spells: [dance_check_all]
modifiers: [buffactive dance require]
variable-mods-cast: [dance_sequence +B]
triggers:
- trigger: input
on-press: [backward]
dance_input_left:
spell-class: ".PassiveSpell"
always-granted: true
spells: [dance_check_all]
modifiers: [buffactive dance require]
variable-mods-cast: [dance_sequence +L]
triggers:
- trigger: input
on-press: [left]
dance_input_right:
spell-class: ".PassiveSpell"
always-granted: true
spells: [dance_check_all]
modifiers: [buffactive dance require]
variable-mods-cast: [dance_sequence +R]
triggers:
- trigger: input
on-press: [right]
dance_input_jump:
spell-class: ".PassiveSpell"
always-granted: true
spells: [dance_check_all]
modifiers: [buffactive dance require]
variable-mods-cast: [dance_sequence +J]
triggers:
- trigger: input
on-press: [jump]
dance_input_sneak:
spell-class: ".PassiveSpell"
always-granted: true
spells: [dance_check_all]
modifiers: [buffactive dance require]
variable-mods-cast: [dance_sequence +S]
triggers:
- trigger: input
on-press: [sneak]