1+ using Celeste . Mod . Entities ;
2+ using Microsoft . Xna . Framework ;
3+ using Monocle ;
4+ using System ;
5+ using System . Collections ;
6+ using System . Collections . Generic ;
7+
8+ namespace Celeste . Mod . SpringCollab2020 . Entities {
9+ [ CustomEntity ( "SpringCollab2020/variableCrumbleBlock" ) ]
10+ public class VariableCrumblePlatform : Solid {
11+ public static ParticleType P_Crumble = CrumblePlatform . P_Crumble ;
12+
13+ private List < Image > images ;
14+
15+ private List < Image > outline ;
16+
17+ private List < Coroutine > falls ;
18+
19+ private List < int > fallOrder ;
20+
21+ private ShakerList shaker ;
22+
23+ private LightOcclude occluder ;
24+
25+ private Coroutine outlineFader ;
26+
27+ public float crumbleTime = 0.4f ;
28+
29+ public string OverrideTexture ;
30+
31+ public VariableCrumblePlatform ( Vector2 position , float width , float timer )
32+ : base ( position , width , 8f , false ) {
33+ EnableAssistModeChecks = false ;
34+ crumbleTime = timer ;
35+ }
36+
37+ public VariableCrumblePlatform ( EntityData data , Vector2 offset )
38+ : this ( data . Position + offset , ( float ) data . Width , data . Float ( "timer" , 0.4f ) ) {
39+ }
40+
41+ public override void Added ( Scene scene ) {
42+ AreaData areaData = AreaData . Get ( scene ) ;
43+ string crumbleBlock = areaData . CrumbleBlock ;
44+ if ( OverrideTexture != null ) {
45+ areaData . CrumbleBlock = OverrideTexture ;
46+ }
47+ base . Added ( scene ) ;
48+ MTexture mTexture = GFX . Game [ "objects/crumbleBlock/outline" ] ;
49+ outline = new List < Image > ( ) ;
50+ if ( base . Width <= 8f ) {
51+ Image image = new Image ( mTexture . GetSubtexture ( 24 , 0 , 8 , 8 ) ) ;
52+ image . Color = Color . White * 0f ;
53+ Add ( image ) ;
54+ outline . Add ( image ) ;
55+ } else {
56+ for ( int i = 0 ; ( float ) i < base . Width ; i += 8 ) {
57+ int num = ( i != 0 ) ? ( ( i > 0 && ( float ) i < base . Width - 8f ) ? 1 : 2 ) : 0 ;
58+ Image image2 = new Image ( mTexture . GetSubtexture ( num * 8 , 0 , 8 , 8 ) ) ;
59+ image2 . Position = new Vector2 ( i , 0f ) ;
60+ image2 . Color = Color . White * 0f ;
61+ Add ( image2 ) ;
62+ outline . Add ( image2 ) ;
63+ }
64+ }
65+ Add ( outlineFader = new Coroutine ( ) ) ;
66+ outlineFader . RemoveOnComplete = false ;
67+ images = new List < Image > ( ) ;
68+ falls = new List < Coroutine > ( ) ;
69+ fallOrder = new List < int > ( ) ;
70+ MTexture mTexture2 = GFX . Game [ "objects/crumbleBlock/" + AreaData . Get ( scene ) . CrumbleBlock ] ;
71+ for ( int j = 0 ; ( float ) j < base . Width ; j += 8 ) {
72+ int num2 = ( int ) ( ( Math . Abs ( base . X ) + ( float ) j ) / 8f ) % 4 ;
73+ Image image3 = new Image ( mTexture2 . GetSubtexture ( num2 * 8 , 0 , 8 , 8 ) ) ;
74+ image3 . Position = new Vector2 ( 4 + j , 4f ) ;
75+ image3 . CenterOrigin ( ) ;
76+ Add ( image3 ) ;
77+ images . Add ( image3 ) ;
78+ Coroutine coroutine = new Coroutine ( ) ;
79+ coroutine . RemoveOnComplete = false ;
80+ falls . Add ( coroutine ) ;
81+ Add ( coroutine ) ;
82+ fallOrder . Add ( j / 8 ) ;
83+ }
84+ fallOrder . Shuffle ( ) ;
85+ Add ( new Coroutine ( Sequence ( ) ) ) ;
86+ Add ( shaker = new ShakerList ( images . Count , false , delegate ( Vector2 [ ] v ) {
87+ for ( int k = 0 ; k < images . Count ; k ++ ) {
88+ images [ k ] . Position = new Vector2 ( 4 + k * 8 , 4f ) + v [ k ] ;
89+ }
90+ } ) ) ;
91+ Add ( occluder = new LightOcclude ( 0.2f ) ) ;
92+ areaData . CrumbleBlock = crumbleBlock ;
93+ }
94+
95+ private IEnumerator Sequence ( ) {
96+ while ( true ) {
97+ Player player = GetPlayerOnTop ( ) ;
98+ bool onTop ;
99+ if ( player != null ) {
100+ onTop = true ;
101+ Input . Rumble ( RumbleStrength . Medium , RumbleLength . Medium ) ;
102+ } else {
103+ player = GetPlayerClimbing ( ) ;
104+ if ( player == null ) {
105+ yield return null ;
106+ continue ;
107+ }
108+ onTop = false ;
109+ Input . Rumble ( RumbleStrength . Medium , RumbleLength . Medium ) ;
110+ }
111+ Audio . Play ( "event:/game/general/platform_disintegrate" , Center ) ;
112+ shaker . ShakeFor ( onTop ? crumbleTime + 0.4f : crumbleTime + 0.8f , removeOnFinish : false ) ;
113+ foreach ( Image img2 in images ) {
114+ SceneAs < Level > ( ) . Particles . Emit ( P_Crumble , 2 , Position + img2 . Position + new Vector2 ( 0f , 2f ) , Vector2 . One * 3f ) ;
115+ }
116+ for ( int l = 0 ; l < ( onTop ? 1 : 3 ) ; l ++ ) {
117+ yield return 0.2f ;
118+ foreach ( Image img in images ) {
119+ SceneAs < Level > ( ) . Particles . Emit ( P_Crumble , 2 , Position + img . Position + new Vector2 ( 0f , 2f ) , Vector2 . One * 3f ) ;
120+ }
121+ }
122+ float timer = crumbleTime ;
123+ if ( onTop ) {
124+ while ( timer > 0f && GetPlayerOnTop ( ) != null ) {
125+ yield return null ;
126+ timer -= Engine . DeltaTime ;
127+ }
128+ } else {
129+ while ( timer > 0f ) {
130+ yield return null ;
131+ timer -= Engine . DeltaTime ;
132+ }
133+ }
134+ outlineFader . Replace ( OutlineFade ( 1f ) ) ;
135+ occluder . Visible = false ;
136+ Collidable = false ;
137+ float delay = 0.05f ;
138+ for ( int m = 0 ; m < 4 ; m ++ ) {
139+ for ( int i = 0 ; i < images . Count ; i ++ ) {
140+ if ( i % 4 - m == 0 ) {
141+ falls [ i ] . Replace ( TileOut ( images [ fallOrder [ i ] ] , delay * ( float ) m ) ) ;
142+ }
143+ }
144+ }
145+ yield return 2f ;
146+ while ( CollideCheck < Actor > ( ) || CollideCheck < Solid > ( ) ) {
147+ yield return null ;
148+ }
149+ outlineFader . Replace ( OutlineFade ( 0f ) ) ;
150+ occluder . Visible = true ;
151+ Collidable = true ;
152+ for ( int k = 0 ; k < 4 ; k ++ ) {
153+ for ( int j = 0 ; j < images . Count ; j ++ ) {
154+ if ( j % 4 - k == 0 ) {
155+ falls [ j ] . Replace ( TileIn ( j , images [ fallOrder [ j ] ] , 0.05f * ( float ) k ) ) ;
156+ }
157+ }
158+ }
159+ }
160+ }
161+
162+ private IEnumerator OutlineFade ( float to ) {
163+ float from = 1f - to ;
164+ for ( float t = 0f ; t < 1f ; t += Engine . DeltaTime * 2f ) {
165+ Color color = Color . White * ( from + ( to - from ) * Ease . CubeInOut ( t ) ) ;
166+ foreach ( Image img in outline ) {
167+ img . Color = color ;
168+ }
169+ yield return null ;
170+ }
171+ }
172+
173+ private IEnumerator TileOut ( Image img , float delay ) {
174+ img . Color = Color . Gray ;
175+ yield return delay ;
176+ float distance = ( img . X * 7f % 3f + 1f ) * 12f ;
177+ Vector2 from = img . Position ;
178+ for ( float time = 0f ; time < 1f ; time += Engine . DeltaTime / 0.4f ) {
179+ yield return null ;
180+ img . Position = from + Vector2 . UnitY * Ease . CubeIn ( time ) * distance ;
181+ img . Color = Color . Gray * ( 1f - time ) ;
182+ img . Scale = Vector2 . One * ( 1f - time * 0.5f ) ;
183+ }
184+ img . Visible = false ;
185+ }
186+
187+ private IEnumerator TileIn ( int index , Image img , float delay ) {
188+ yield return delay ;
189+ Audio . Play ( "event:/game/general/platform_return" , Center ) ;
190+ img . Visible = true ;
191+ img . Color = Color . White ;
192+ img . Position = new Vector2 ( index * 8 + 4 , 4f ) ;
193+ for ( float time = 0f ; time < 1f ; time += Engine . DeltaTime / 0.25f ) {
194+ yield return null ;
195+ img . Scale = Vector2 . One * ( 1f + Ease . BounceOut ( 1f - time ) * 0.2f ) ;
196+ }
197+ img . Scale = Vector2 . One ;
198+ }
199+ }
200+ }
0 commit comments