1- import { ButtonState , EntityDamageCause , EntityHealthComponent , EntityInventoryComponent , EquipmentSlot , InputButton , InputPermissionCategory , ItemLockMode , ItemStack , MolangVariableMap , Player , StartupEvent , system , Vector3 , world } from "@minecraft/server" ;
1+ import { ButtonState , Dimension , EntityDamageCause , EntityHealthComponent , EntityInventoryComponent , EquipmentSlot , InputButton , InputPermissionCategory , ItemLockMode , ItemStack , MolangVariableMap , Player , StartupEvent , system , Vector3 , world } from "@minecraft/server" ;
22import { MinecraftEffectTypes } from "@minecraft/vanilla-data" ;
3- import { directionVector , drawLine , EFFECT_INFINITE , entityCenter , entityHasSlotTag , playSoundFrom } from "../../utility" ;
3+ import { directionVector , drawLine , EFFECT_INFINITE , entityCenter , entityHasSlotTag , playSoundFrom , spawnLine } from "../../utility" ;
44import { V3 } from "../../math/vectorUtils" ;
55import { deg2Rad , PI , remap , TAU } from "../../math/general" ;
6- import { VECTOR3_ZERO } from "@minecraft/math" ;
6+ import { VECTOR3_UP , VECTOR3_ZERO } from "@minecraft/math" ;
77
88enum States {
99 NORMAL ,
1010 WEAK ,
1111 FLYING ,
1212 MOON_JUMP ,
13- DASH
13+ DASH ,
14+ CHARGE_V ,
15+ USE_V ,
16+ CHARGE_Z ,
17+ USE_Z ,
18+ USE_X ,
19+ HOLD_C ,
20+ USE_C
1421}
1522
1623let light : ItemStack
@@ -43,6 +50,15 @@ const spinTrailTurnsPerSecond = 1.5
4350const spinTrailRadius = 0.5
4451const flySoundDuration = 7 //8.58
4552
53+ const ZChargeIncrease = 20
54+ const ZChargeAmountMax = 3
55+
56+ const lightRayMaxLength = 25
57+ const lightRayDuration = 20 * 4
58+ const lightRayCooldown = 80
59+
60+ const zCooldownTime = 80
61+
4662class LightFlightVisual {
4763 lastSpin1 : Vector3 | undefined
4864 lastSpin2 : Vector3 | undefined
@@ -54,6 +70,9 @@ const flySoundCooldown: Map<string, number> = new Map()
5470const airTime : Map < string , number > = new Map ( )
5571const ignoreFall : Map < string , boolean > = new Map ( )
5672const dashCooldown : Map < string , number > = new Map ( )
73+ const holdZTime : Map < string , number > = new Map ( )
74+ const holdXTime : Map < string , number > = new Map ( )
75+ const ZChargeAmount : Map < string , number > = new Map ( )
5776const flyingAngles : Map < string , Vector3 > = new Map ( )
5877const lightFlightVisuals : Map < string , LightFlightVisual > = new Map ( )
5978
@@ -117,7 +136,19 @@ Object.defineProperties(Player.prototype, {
117136 dashCooldown : {
118137 get ( ) { return dashCooldown . get ( this . id ) ?? 0 } ,
119138 set ( v : number ) { dashCooldown . set ( this . id , v ) }
120- }
139+ } ,
140+ holdZTime : {
141+ get ( ) { return holdZTime . get ( this . id ) ?? 0 } ,
142+ set ( v : number ) { holdZTime . set ( this . id , v ) }
143+ } ,
144+ ZChargeAmount : {
145+ get ( ) { return ZChargeAmount . get ( this . id ) ?? 0 } ,
146+ set ( v : number ) { ZChargeAmount . set ( this . id , v ) }
147+ } ,
148+ holdXTime : {
149+ get ( ) { return holdXTime . get ( this . id ) ?? 0 } ,
150+ set ( v : number ) { holdXTime . set ( this . id , v ) }
151+ } ,
121152} ) ;
122153
123154function playerHasLight ( player : Player ) {
@@ -195,9 +226,62 @@ function changeState(player: Player, state: States) {
195226 case States . WEAK :
196227 break ;
197228
229+ case States . USE_Z :
230+ let angles : number [ ] = [ ]
231+ if ( player . ZChargeAmount == 1 ) angles = [ 0 ]
232+ if ( player . ZChargeAmount == 2 ) angles = [ - 15 , 15 ]
233+ if ( player . ZChargeAmount == 3 ) angles = [ - 20 , 0 , 20 ]
234+ const matrix = V3 . getBasisMatrix ( player . getViewDirection ( ) )
235+ for ( const angle of angles ) {
236+ let rad = deg2Rad ( angle )
237+ let angleRot = V3 . directionToRotation ( player . getViewDirection ( ) )
238+
239+ angleRot . y += rad
240+ let newDir = V3 . rotationToDirection ( angleRot )
241+
242+ const blockHit = player . dimension . getBlockFromRay ( player . getHeadLocation ( ) , newDir , { includePassableBlocks : false } )
243+ if ( ! blockHit ) continue
244+ let p = V3 . add ( blockHit . block . location , blockHit . faceLocation )
245+ drawLine ( "whynot:light_trail" , player . dimension , player . getHeadLocation ( ) , p , 0.25 )
246+ player . dimension . createExplosion ( p , 1 , { breaksBlocks : false } )
247+ }
248+ changeState ( player , States . NORMAL )
249+ break ;
250+
251+ case States . USE_C :
252+ player . teleport ( V3 . add ( player . location , VECTOR3_UP ) )
253+ changeState ( player , States . NORMAL )
254+ break
255+
256+ case States . USE_V :
257+ world . sendMessage ( "Used V" )
258+ changeState ( player , States . NORMAL )
259+ break
260+
261+ case States . CHARGE_Z :
262+ player . inputPermissions . setPermissionCategory ( InputPermissionCategory . Movement , false )
263+ player . triggerEvent ( "whynot:add_static_player" ) ;
264+ player . ZChargeAmount = 0
265+ player . holdZTime = ZChargeIncrease
266+ break ;
267+
268+ case States . CHARGE_V :
269+ case States . HOLD_C :
270+ player . inputPermissions . setPermissionCategory ( InputPermissionCategory . Movement , false )
271+ player . triggerEvent ( "whynot:add_static_player" ) ;
272+ break ;
273+
274+ case States . USE_X :
275+ player . holdXTime = 0
276+ playSoundFrom ( player , "light_beam_start" )
277+ player . flySoundCooldown = 0
278+ player . inputPermissions . setPermissionCategory ( InputPermissionCategory . Movement , false )
279+ player . triggerEvent ( "whynot:add_static_player" ) ;
280+ break ;
198281 }
199282
200283 if ( oldState == player . state ) return
284+ // Exiting state
201285 switch ( oldState ) {
202286 case States . FLYING :
203287 player . triggerEvent ( "whynot:remove_static_player" ) ;
@@ -210,6 +294,23 @@ function changeState(player: Player, state: States) {
210294 case States . WEAK :
211295 player . inputPermissions . setPermissionCategory ( InputPermissionCategory . Movement , true )
212296 break ;
297+
298+ case States . CHARGE_V :
299+ case States . HOLD_C :
300+ player . inputPermissions . setPermissionCategory ( InputPermissionCategory . Movement , true )
301+ player . triggerEvent ( "whynot:remove_static_player" ) ;
302+ break ;
303+
304+ case States . USE_X :
305+ player . inputPermissions . setPermissionCategory ( InputPermissionCategory . Movement , true )
306+ player . triggerEvent ( "whynot:remove_static_player" ) ;
307+ break ;
308+
309+ case States . CHARGE_Z :
310+ player . inputPermissions . setPermissionCategory ( InputPermissionCategory . Movement , true )
311+ player . triggerEvent ( "whynot:remove_static_player" ) ;
312+ break ;
313+
213314 }
214315}
215316
@@ -325,7 +426,65 @@ function processState(player: Player) {
325426 player . airTime = 0
326427 player . dashCooldown = dashCooldownTime
327428 break ;
429+
430+ case States . CHARGE_Z :
431+ player . zCooldown = zCooldownTime
432+ player . clearVelocity ( )
433+ player . holdZTime ++
434+ if ( player . holdZTime > ZChargeIncrease && player . ZChargeAmount < ZChargeAmountMax ) {
435+ playSoundFrom ( player , "random.burp" )
436+ player . spawnParticle ( "minecraft:bleach" , player . getHeadLocation ( ) )
437+ player . ZChargeAmount ++ ;
438+ player . holdZTime = 0
439+ }
440+ break ;
441+
442+ case States . USE_X :
443+ player . clearVelocity ( )
444+ player . xCooldown = lightRayCooldown
445+ if ( player . flySoundCooldown <= 0 ) {
446+ playSoundFrom ( player , "light_beam_loop" )
447+ player . flySoundCooldown = 7
448+ }
449+ player . flySoundCooldown --
450+ const laserHit = player . getBlockFromViewDirection ( { maxDistance : lightRayMaxLength , includePassableBlocks : false } )
451+ const laserHitEntity = player . getEntitiesFromViewDirection ( { maxDistance : lightRayMaxLength } ) [ 0 ] ?. entity
452+
453+ const pviewDir = player . getViewDirection ( )
454+ const headLoc = player . getHeadLocation ( )
455+ const targetLocation : Vector3 = laserHitEntity ?
456+ entityCenter ( laserHitEntity ) ?? laserHitEntity . location :
457+ laserHit ?
458+ V3 . add ( laserHit . block . location , laserHit . faceLocation ) :
459+ V3 . add ( player . location , V3 . scale ( pviewDir , lightRayMaxLength ) )
460+ const targetDir = V3 . direction ( headLoc , targetLocation )
461+ if ( laserHitEntity ) {
462+ laserHitEntity . applyDamage ( 10 )
463+ }
464+ let offset_end = V3 . add ( targetLocation , V3 . scale ( targetDir , 1 ) )
465+ let offset_start = V3 . add ( headLoc , V3 . scale ( targetDir , - 1 ) )
466+ drawLine ( "whynot:light_trail" , player . dimension , offset_start , offset_end , 0.25 )
467+ const map = new MolangVariableMap ( )
468+ map . setFloat ( "size" , 1 )
469+ map . setFloat ( "frame" , system . currentTick % flightStarFrames )
470+ player . spawnParticle ( "whynot:light_star" , offset_end , map )
471+ player . spawnParticle ( "whynot:light_star" , offset_start , map )
472+ player . holdXTime ++
473+ if ( player . holdXTime > lightRayDuration ) {
474+ changeState ( player , States . NORMAL )
475+ }
476+ break ;
477+
478+ case States . CHARGE_V :
479+ player . clearVelocity ( )
480+ break ;
481+
482+ case States . HOLD_C :
483+ player . clearVelocity ( )
484+ break
485+
328486 }
487+
329488}
330489
331490export function main ( ) {
@@ -343,6 +502,29 @@ export function main() {
343502
344503 ev . cancel = true
345504 } )
505+ // world.afterEvents.playerSwingStart.subscribe(({heldItemStack, player}) => {
506+ // if (!heldItemStack?.hasTag("whynot:light")) return
507+ // if (player.state ==)
508+ // })
509+ world . afterEvents . itemStartUse . subscribe ( ( { itemStack, source} ) => {
510+ if ( ! itemStack ?. hasTag ( "whynot:light" ) ) return
511+ if ( ! source . isValid || source . typeId != "minecraft:player" ) return
512+ if ( source . state != States . NORMAL ) return
513+ if ( source . isSneaking ) {
514+ if ( source . zCooldown <= 0 ) changeState ( source , States . CHARGE_Z )
515+ } else {
516+ if ( source . xCooldown <= 0 ) changeState ( source , States . USE_X )
517+ }
518+ } )
519+ world . afterEvents . itemStopUse . subscribe ( ( { itemStack, source} ) => {
520+ if ( ! itemStack ?. hasTag ( "whynot:light" ) ) return
521+ if ( ! source . isValid || source . typeId != "minecraft:player" ) return
522+
523+ switch ( source . state ) {
524+ case States . CHARGE_Z : changeState ( source , States . USE_Z ) ; break ;
525+ case States . USE_X : changeState ( source , States . NORMAL ) ; break ;
526+ }
527+ } )
346528 world . afterEvents . playerButtonInput . subscribe ( ( { button, newButtonState, player} ) => {
347529 const pressed = newButtonState == ButtonState . Pressed
348530 if ( ! entityHasSlotTag ( player , EquipmentSlot . Mainhand , "whynot:light" ) ) return ;
0 commit comments