@@ -17,7 +17,10 @@ use crate::{
1717 enemy_ai,
1818 fighter:: { Attached , AvailableAttacks , Inventory } ,
1919 input:: PlayerAction ,
20- item:: { Drop , Item , ItemBundle , Projectile , ScriptItemGrabEvent , ScriptItemThrowEvent } ,
20+ item:: {
21+ AnimatedProjectile , Drop , Explodable , Item , ItemBundle , Projectile , ScriptItemGrabEvent ,
22+ ScriptItemThrowEvent ,
23+ } ,
2124 lifetime:: Lifetime ,
2225 metadata:: { AttackMeta , AudioMeta , FighterMeta , ItemKind , ItemMeta , ItemSpawnMeta } ,
2326 movement:: LinearVelocity ,
@@ -63,6 +66,7 @@ impl Plugin for FighterStatePlugin {
6366 . with_system ( transition_from_hitstun)
6467 . with_system ( transition_from_melee_attacking)
6568 . with_system ( transition_from_shooting)
69+ . with_system ( transition_from_bomb_throw)
6670 . into ( ) ,
6771 )
6872 // State handler systems
@@ -82,6 +86,7 @@ impl Plugin for FighterStatePlugin {
8286 . with_system ( holding)
8387 . with_system ( melee_attacking)
8488 . with_system ( shooting)
89+ . with_system ( bomb_throw)
8590 . into ( ) ,
8691 ) ;
8792 }
@@ -248,6 +253,18 @@ impl GroundSlam {
248253 pub const ANIMATION : & ' static str = "attacking" ;
249254}
250255
256+ #[ derive( Component , Reflect , Default , Debug ) ]
257+ #[ component( storage = "SparseSet" ) ]
258+ pub struct BossBombThrow {
259+ pub has_started : bool ,
260+ pub is_finished : bool ,
261+ pub thrown : bool ,
262+ }
263+ impl BossBombThrow {
264+ pub const PRIORITY : i32 = 30 ;
265+ pub const ANIMATION : & ' static str = "bomb_throw" ;
266+ }
267+
251268#[ derive( Component , Reflect , Default , Debug ) ]
252269#[ component( storage = "SparseSet" ) ]
253270pub struct Punching {
@@ -542,6 +559,35 @@ fn transition_from_ground_slam(
542559 }
543560}
544561
562+ fn transition_from_bomb_throw (
563+ mut commands : Commands ,
564+ mut fighters : Query < ( Entity , & mut StateTransitionIntents , & BossBombThrow ) > ,
565+ ) {
566+ ' entity: for ( entity, mut transition_intents, bomb_throw) in & mut fighters {
567+ // Transition to any higher priority states
568+ let current_state_removed = transition_intents
569+ . transition_to_higher_priority_states :: < BossBombThrow > (
570+ entity,
571+ BossBombThrow :: PRIORITY ,
572+ & mut commands,
573+ ) ;
574+
575+ // If our current state was removed, don't continue processing this fighter
576+ if current_state_removed {
577+ continue ' entity;
578+ }
579+
580+ // If we're done flopping
581+ if bomb_throw. is_finished {
582+ // Go back to idle
583+ commands
584+ . entity ( entity)
585+ . remove :: < BossBombThrow > ( )
586+ . insert ( Idling ) ;
587+ }
588+ }
589+ }
590+
545591// Initiate any transitions from the hit stun state
546592fn transition_from_hitstun (
547593 mut commands : Commands ,
@@ -999,6 +1045,112 @@ fn ground_slam(
9991045 }
10001046}
10011047
1048+ fn bomb_throw (
1049+ mut commands : Commands ,
1050+ mut fighters : Query <
1051+ (
1052+ & mut Animation ,
1053+ & mut LinearVelocity ,
1054+ & Facing ,
1055+ & Transform ,
1056+ & Handle < FighterMeta > ,
1057+ & mut BossBombThrow ,
1058+ & AvailableAttacks ,
1059+ ) ,
1060+ With < Boss > ,
1061+ > ,
1062+ fighter_assets : Res < Assets < FighterMeta > > ,
1063+ item_assets : Res < Assets < ItemMeta > > ,
1064+ ) {
1065+ for (
1066+ mut animation,
1067+ mut velocity,
1068+ facing,
1069+ transform,
1070+ meta_handle,
1071+ mut bomb_throw,
1072+ available_attacks,
1073+ ) in & mut fighters
1074+ {
1075+ // Start the attack
1076+ if let Some ( fighter) = fighter_assets. get ( meta_handle) {
1077+ let attack = available_attacks. current_attack ( ) ;
1078+ let item = item_assets
1079+ . get ( & attack. item_handle )
1080+ . expect ( "Fighter has no item" ) ;
1081+
1082+ let ( mut sprite, mut frames) = ( None , None ) ;
1083+ if let ItemKind :: Bomb {
1084+ attack_frames,
1085+ spritesheet,
1086+ } = & item. kind
1087+ {
1088+ sprite = Some ( spritesheet) ;
1089+ frames = Some ( attack_frames) ;
1090+ }
1091+ let ( spritesheet, attack_frames) = (
1092+ sprite. expect ( "No bomb item found." ) ,
1093+ frames. expect ( "No bomb item found;." ) ,
1094+ ) ;
1095+
1096+ let mut translation = transform. translation ;
1097+ translation. z += 0.2 ; // Get above boss
1098+ translation. x +=
1099+ ( spritesheet. tile_size . x / 3 ) as f32 * if facing. is_left ( ) { -1. } else { 1. } ;
1100+ translation. y += ( spritesheet. tile_size . y / 2 ) as f32 ;
1101+ let mut animated_sprite = AnimatedSpriteSheetBundle {
1102+ sprite_sheet : SpriteSheetBundle {
1103+ texture_atlas : spritesheet. atlas_handle [ 0 ] . clone ( ) ,
1104+ transform : Transform :: from_translation ( translation) ,
1105+ ..Default :: default ( )
1106+ } ,
1107+ animation : Animation :: new (
1108+ spritesheet. animation_fps ,
1109+ spritesheet. animations . clone ( ) ,
1110+ ) ,
1111+ } ;
1112+ animated_sprite. animation . current_animation = Some ( "bomb" . to_string ( ) ) ;
1113+
1114+ let mut offset = attack. hitbox . offset ;
1115+ if facing. is_left ( ) {
1116+ offset. x *= -1.0
1117+ }
1118+ offset. y += fighter. collision_offset ;
1119+
1120+ if !bomb_throw. has_started {
1121+ bomb_throw. has_started = true ;
1122+
1123+ // Start the attack from the beginning
1124+ animation. play ( BossBombThrow :: ANIMATION , false ) ;
1125+ }
1126+
1127+ if !animation. is_finished ( ) {
1128+ // Frames that each bomb is thrown
1129+ if ( animation. current_frame == attack. frames . startup && !bomb_throw. thrown )
1130+ || ( animation. current_frame == attack. frames . active && bomb_throw. thrown )
1131+ {
1132+ // Spawn bomb
1133+ commands
1134+ . spawn_bundle ( AnimatedProjectile :: new ( 0 , facing, animated_sprite. clone ( ) ) )
1135+ . insert ( Explodable {
1136+ attack : attack. clone ( ) ,
1137+ timer : Timer :: from_seconds ( consts:: THROW_ITEM_LIFETIME , false ) ,
1138+ fusing : false ,
1139+ animated_sprite,
1140+ explosion_frames : * attack_frames,
1141+ } ) ;
1142+ bomb_throw. thrown = !bomb_throw. thrown ;
1143+ }
1144+ } else if animation. is_finished ( ) {
1145+ bomb_throw. is_finished = true ;
1146+ }
1147+
1148+ // Stop boss
1149+ * * velocity = Vec2 :: ZERO ;
1150+ }
1151+ }
1152+ }
1153+
10021154/// Handle fighter moving state
10031155fn moving (
10041156 mut commands : Commands ,
@@ -1206,6 +1358,9 @@ fn throwing(
12061358 }
12071359 }
12081360 }
1361+ ItemKind :: Bomb { .. } => {
1362+ panic ! ( "Can't throw bomb" )
1363+ }
12091364 }
12101365 }
12111366
@@ -1403,6 +1558,9 @@ fn grabbing(
14031558 . id ( ) ;
14041559 commands. entity ( fighter_ent) . add_child ( weapon) ;
14051560 }
1561+ ItemKind :: Bomb { .. } => {
1562+ panic ! ( "Can't pick up bomb" )
1563+ }
14061564 }
14071565 }
14081566 break ;
0 commit comments