@@ -3,6 +3,7 @@ import { MinecraftEffectTypes } from "@minecraft/vanilla-data";
33import { directionVector , drawLine , entityCenter , entityGetSlot , entityHasSlotTag , spawnLine } from "../../utility" ;
44import { V3 } from "../../math/vectorUtils" ;
55import { deg2Rad , PI , remap , TAU } from "../../math/general" ;
6+ import { VECTOR2_ZERO , VECTOR3_BACK , VECTOR3_ZERO } from "@minecraft/math" ;
67
78let light : ItemStack
89const maxAirJumps : number = 10
@@ -14,12 +15,15 @@ const flyTurnThreshold = Math.cos(deg2Rad(60));
1415enum States {
1516 NORMAL ,
1617 FLYING ,
17- MOON_JUMP
18+ MOON_JUMP ,
19+ DASH
1820}
19- type Line = {
20- start : Vector3 ,
21- end : Vector3 ,
22- length : number
21+
22+ class LightVisual {
23+ lastSpin1 : Vector3 | undefined
24+ lastSpin2 : Vector3 | undefined
25+ lastTrail : Vector3 | undefined
26+ angle : number = 0.0
2327}
2428const flyTurnCooldownTime : number = 10
2529const flyTurnCooldown : Map < string , number > = new Map ( )
@@ -28,7 +32,7 @@ const airTime: Map<string, number> = new Map()
2832const ignoreFall : Map < string , boolean > = new Map ( )
2933const airJumps : Map < string , number > = new Map ( )
3034const flyingAngles : Map < string , Vector3 > = new Map ( )
31- const trails : Map < string , Line [ ] > = new Map ( )
35+ const visuals : Map < string , LightVisual > = new Map ( )
3236
3337// Defining setters for ability cooldowns
3438Object . defineProperties ( Player . prototype , {
@@ -76,13 +80,6 @@ export function startup(ev: StartupEvent) {
7680 } )
7781}
7882
79- function addTrail ( player : Player ) {
80- if ( ! trails . has ( player . id ) ) trails . set ( player . id , [ ] )
81- const trail = trails . get ( player . id ) as Line [ ]
82- const cent = entityCenter ( player ) ?? player . location
83- trail . push ( { start : cent , end : cent , length : 0 } )
84- }
85-
8683function changeState ( player : Player , state : States ) {
8784 const oldState = player . state
8885 player . state = state
@@ -95,8 +92,7 @@ function changeState(player: Player, state: States) {
9592
9693 player . playSound ( "light_dash" )
9794 player . playSound ( "light_beam_start" )
98- addTrail ( player )
99-
95+ visuals . set ( player . id , new LightVisual ( ) )
10096 flySoundCooldown . set ( player . id , 0 )
10197 flyTurnCooldown . set ( player . id , 0 )
10298 player . inputPermissions . setPermissionCategory ( InputPermissionCategory . Movement , false )
@@ -117,20 +113,33 @@ function changeState(player: Player, state: States) {
117113 changeState ( player , States . NORMAL )
118114 break ;
119115
116+ case States . DASH :
117+ const dir = player . getViewDirection ( )
118+ let vel = V3 . normalize ( V3 . make ( dir . x , 0 , dir . z ) )
119+ const dirMap = new MolangVariableMap ( ) ;
120+ dirMap . setVector3 ( "direction" , V3 . scale ( vel , - 1 ) )
121+ player . spawnParticle ( "whynot:dash" , entityCenter ( player ) ?? player . location , dirMap )
122+ player . addEffect ( MinecraftEffectTypes . SlowFalling , 5 , { showParticles : false } )
123+ player . playSound ( "dash" )
124+
125+ player . clearVelocity ( )
126+ player . applyImpulse ( V3 . add ( V3 . scale ( vel , 1.0 ) , V3 . make ( 0 , 0.1 , 0 ) ) )
127+
128+ changeState ( player , States . NORMAL )
129+ break ;
130+
120131 }
121132
122133 switch ( oldState ) {
123134 case States . FLYING :
124135 player . triggerEvent ( "whynot:remove_static_player" ) ;
125136
126137 player . inputPermissions . setPermissionCategory ( InputPermissionCategory . Movement , true )
127- trails . delete ( player . id )
128138
129139 player . removeEffect ( MinecraftEffectTypes . Invisibility )
130140 break ;
131141 }
132142}
133- let angle = 0
134143export function main ( ) {
135144 light = new ItemStack ( "whynot:light" , 1 ) ;
136145 light . lockMode = ItemLockMode . inventory ;
@@ -148,6 +157,9 @@ export function main() {
148157 const pressed = newButtonState == ButtonState . Pressed
149158 if ( ! entityHasSlotTag ( player , EquipmentSlot . Mainhand , "whynot:light" ) ) return ;
150159
160+ if ( button == InputButton . Sneak && newButtonState == ButtonState . Pressed && player . state == States . NORMAL ) {
161+ changeState ( player , States . DASH )
162+ }
151163 if ( button != InputButton . Jump ) return
152164 if ( ( ( airTime . get ( player . id ) ?? 0 ) > 2 ) && pressed && player . state == States . NORMAL ) {
153165 // Activate fly
@@ -172,9 +184,6 @@ export function main() {
172184 system . runInterval ( mainTick )
173185}
174186
175- let lastAdd1 : Vector3 | undefined = undefined
176- let lastAdd2 : Vector3 | undefined = undefined
177-
178187function mainTick ( ) {
179188 world . getAllPlayers ( ) . forEach ( player => {
180189 // Set Airtime
@@ -203,28 +212,7 @@ function mainTick() {
203212 player . clearVelocity ( ) ;
204213 player . applyImpulse ( vel ) ;
205214
206- // Trail construction
207- const trail : Line [ ] = trails . get ( player . id ) as Line [ ]
208- const line = trail [ trail . length - 1 ]
209- line . end = entityCenter ( player ) ?? player . location
210- line . length = V3 . distance ( line . start , line . end )
211-
212- let length = remap ( health . currentValue , health . effectiveMin , health . effectiveMax , lightTrailLengthMin , lightTrailLengthMax )
213- let i = trail . length - 1
214- while ( length > 0 && i >= 0 ) {
215- const line = trail [ i ]
216- const segmentLength = Math . min ( line . length , length )
217- const dir = V3 . direction ( line . end , line . start )
218- spawnLine (
219- "whynot:light_trail" ,
220- player . dimension , line . end ,
221- dir , segmentLength ,
222- lightTrailThickness
223- )
224-
225- length -= segmentLength
226- i -- ;
227- }
215+ // Particles
228216 const starMap = new MolangVariableMap ( )
229217 const center = entityCenter ( player ) ?? player . location
230218 starMap . setFloat ( "size" , 2.0 )
@@ -235,21 +223,28 @@ function mainTick() {
235223 starMap
236224 )
237225
238- const matrix = V3 . getBasisMatrix ( addVel )
239- angle += ( 1 / 20.0 ) * TAU * 1.5 * speed
240- const spin1 = V3 . make ( Math . cos ( angle ) * 0.5 , Math . sin ( angle ) * 0.5 , 0 )
241- const spin2 = V3 . make ( Math . cos ( angle + PI ) * 0.5 , Math . sin ( angle + PI ) * 0.5 , 0 )
242-
243- const add1 = V3 . add ( V3 . multiplyVectorByMatrix ( spin1 , matrix ) , center )
244- const add2 = V3 . add ( V3 . multiplyVectorByMatrix ( spin2 , matrix ) , center )
245- if ( lastAdd1 && lastAdd2 ) {
246- drawLine ( "whynot:light_spin_trail" , player . dimension , add1 , lastAdd1 , 0.075 )
247- drawLine ( "whynot:light_spin_trail" , player . dimension , add2 , lastAdd2 , 0.075 )
226+ // Visuals
227+ const playerVisuals = visuals . get ( player . id )
228+ if ( playerVisuals ) {
229+ const matrix = V3 . getBasisMatrix ( addVel )
230+ playerVisuals . angle += ( 1 / 20.0 ) * TAU * 1.5 * speed
231+
232+ let angle = playerVisuals . angle
233+ const spin1 = V3 . make ( Math . cos ( angle ) * 0.5 , Math . sin ( angle ) * 0.5 , 0 )
234+ const spin2 = V3 . make ( Math . cos ( angle + PI ) * 0.5 , Math . sin ( angle + PI ) * 0.5 , 0 )
235+
236+ const add1 = V3 . add ( V3 . multiplyVectorByMatrix ( spin1 , matrix ) , center )
237+ const add2 = V3 . add ( V3 . multiplyVectorByMatrix ( spin2 , matrix ) , center )
238+ if ( playerVisuals . lastSpin1 && playerVisuals . lastSpin2 ) {
239+ drawLine ( "whynot:light_trail" , player . dimension , add1 , playerVisuals . lastSpin1 , 0.075 )
240+ drawLine ( "whynot:light_trail" , player . dimension , add2 , playerVisuals . lastSpin2 , 0.075 )
241+ }
242+ if ( playerVisuals . lastTrail )
243+ drawLine ( "whynot:light_trail" , player . dimension , center , playerVisuals . lastTrail , lightTrailThickness )
244+ playerVisuals . lastSpin1 = add1
245+ playerVisuals . lastSpin2 = add2
246+ playerVisuals . lastTrail = center
248247 }
249- lastAdd1 = add1
250- lastAdd2 = add2
251-
252-
253248
254249 // Get block in path and bounce if needed
255250 const blockHit = player . dimension . getBlockFromRay ( entityCenter ( player ) ?? player . location , vel , { maxDistance : 4 , includeLiquidBlocks :false , includePassableBlocks : false } )
@@ -258,16 +253,12 @@ function mainTick() {
258253 flyingAngles . set ( player . id , bounced ) ;
259254 flyTurnCooldown . set ( player . id , flyTurnCooldownTime )
260255 player . playSound ( "light_dash" )
261- // Cut off and end last trail, make new trail
262- addTrail ( player )
263256 }
264257
265258 // If viewing angle change is significant change direction and did not bounce
266259 else if ( V3 . dot ( viewDir , addVel ) < flyTurnThreshold && ( flyTurnCooldown . get ( player . id ) ?? 0 ) <= 0 ) {
267260 flyingAngles . set ( player . id , viewDir ) ;
268261 player . playSound ( "light_dash" )
269- // Cut off and end last trail, make new trail
270- addTrail ( player )
271262 }
272263
273264 // Reduce fly turn cooldown
@@ -294,7 +285,7 @@ function mainTick() {
294285 player . camera . clear ( )
295286 return
296287 }
297- player . camera . setCamera ( "minecraft :follow_orbit" )
288+ player . camera . setCamera ( "whynot :follow_orbit" )
298289 player . dimension . runCommand ( `/ability ${ player . name } mayfly false` )
299290 player . onScreenDisplay . setActionBar ( `Z: ${ player . zCooldown } X: ${ player . xCooldown } C: ${ player . cCooldown } V: ${ player . vCooldown } F: ${ player . fCooldown } ` )
300291 } )
0 commit comments