From ce72943163107224aacf1805cd69e0ce6c980d63 Mon Sep 17 00:00:00 2001 From: Noah Petherbridge Date: Mon, 30 Dec 2019 18:13:28 -0800 Subject: [PATCH] Doodads: Crumbly Floor, Start Flag & State Blocks Add new doodads: * Start Flag: place this in a level to set the spawn point of the player character. If no flag is found, the player spawns at 0,0 in the top corner of the map. Only use one Start Flag per level, otherwise the player will randomly spawn at one of them. * Crumbly Floor: a solid floor that begins to shake and then fall apart after a moment when a mobile character steps on it. The floor respawns after 5 seconds. * State Blocks: blue and orange blocks that toggle between solid and pass-thru whenever a State Button is activated. * State Button: a solid "ON/OFF" block that toggles State Blocks back and forth when touched. Only activates if touched on the side or bottom; acts as a solid floor when walked on from the top. New features for doodad scripts: * Actor scripts: call SetMobile(true) to mark an actor as a mobile mob (i.e. player character or enemy). Other doodads can check if the actor colliding with them IsMobile so they don't activate if placed too close to other (non-mobile) doodads in a level. The Blue and Red Azulians are the only mobile characters so far. * Message.Broadcast allows sending a pub/sub message out to ALL doodads in the level, instead of only to linked doodads as Message.Publish does. This is used for the State Blocks to globally communicate on/off status without needing to link them all together manually. --- dev-assets/doodads/azulian/azulian-red.js | 1 + dev-assets/doodads/azulian/azulian.js | 1 + dev-assets/doodads/build.sh | 28 ++++++++ .../doodads/crumbly-floor/crumbly-floor.js | 60 ++++++++++++++++++ dev-assets/doodads/crumbly-floor/fall1.png | Bin 0 -> 1021 bytes dev-assets/doodads/crumbly-floor/fall2.png | Bin 0 -> 986 bytes dev-assets/doodads/crumbly-floor/fall3.png | Bin 0 -> 957 bytes dev-assets/doodads/crumbly-floor/fall4.png | Bin 0 -> 855 bytes dev-assets/doodads/crumbly-floor/fallen.png | Bin 0 -> 652 bytes dev-assets/doodads/crumbly-floor/floor.png | Bin 0 -> 868 bytes dev-assets/doodads/crumbly-floor/shake1.png | Bin 0 -> 897 bytes dev-assets/doodads/crumbly-floor/shake2.png | Bin 0 -> 891 bytes dev-assets/doodads/doors/electric-door.js | 2 +- dev-assets/doodads/objects/start-flag.png | Bin 0 -> 6541 bytes dev-assets/doodads/on-off/blue-button.png | Bin 0 -> 741 bytes dev-assets/doodads/on-off/blue-off.png | Bin 0 -> 648 bytes dev-assets/doodads/on-off/blue-on.png | Bin 0 -> 683 bytes dev-assets/doodads/on-off/orange-button.png | Bin 0 -> 751 bytes dev-assets/doodads/on-off/orange-off.png | Bin 0 -> 650 bytes dev-assets/doodads/on-off/orange-on.png | Bin 0 -> 687 bytes dev-assets/doodads/on-off/state-block-blue.js | 28 ++++++++ .../doodads/on-off/state-block-orange.js | 28 ++++++++ dev-assets/doodads/on-off/state-button.js | 47 ++++++++++++++ 23 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 dev-assets/doodads/crumbly-floor/crumbly-floor.js create mode 100644 dev-assets/doodads/crumbly-floor/fall1.png create mode 100644 dev-assets/doodads/crumbly-floor/fall2.png create mode 100644 dev-assets/doodads/crumbly-floor/fall3.png create mode 100644 dev-assets/doodads/crumbly-floor/fall4.png create mode 100644 dev-assets/doodads/crumbly-floor/fallen.png create mode 100644 dev-assets/doodads/crumbly-floor/floor.png create mode 100644 dev-assets/doodads/crumbly-floor/shake1.png create mode 100644 dev-assets/doodads/crumbly-floor/shake2.png create mode 100644 dev-assets/doodads/objects/start-flag.png create mode 100644 dev-assets/doodads/on-off/blue-button.png create mode 100644 dev-assets/doodads/on-off/blue-off.png create mode 100644 dev-assets/doodads/on-off/blue-on.png create mode 100644 dev-assets/doodads/on-off/orange-button.png create mode 100644 dev-assets/doodads/on-off/orange-off.png create mode 100644 dev-assets/doodads/on-off/orange-on.png create mode 100644 dev-assets/doodads/on-off/state-block-blue.js create mode 100644 dev-assets/doodads/on-off/state-block-orange.js create mode 100644 dev-assets/doodads/on-off/state-button.js diff --git a/dev-assets/doodads/azulian/azulian-red.js b/dev-assets/doodads/azulian/azulian-red.js index a138408..f631e40 100644 --- a/dev-assets/doodads/azulian/azulian-red.js +++ b/dev-assets/doodads/azulian/azulian-red.js @@ -7,6 +7,7 @@ function main() { var direction = "right"; + Self.SetMobile(true); Self.SetGravity(true); Self.AddAnimation("walk-left", 100, ["red-wl1", "red-wl2", "red-wl3", "red-wl4"]); Self.AddAnimation("walk-right", 100, ["red-wr1", "red-wr2", "red-wr3", "red-wr4"]); diff --git a/dev-assets/doodads/azulian/azulian.js b/dev-assets/doodads/azulian/azulian.js index 1599b48..a01881c 100644 --- a/dev-assets/doodads/azulian/azulian.js +++ b/dev-assets/doodads/azulian/azulian.js @@ -7,6 +7,7 @@ function main() { var animStart = animEnd = 0; var animFrame = animStart; + Self.SetMobile(true); Self.SetGravity(true); Self.SetHitbox(7, 4, 17, 28); Self.AddAnimation("walk-left", 100, ["blu-wl1", "blu-wl2", "blu-wl3", "blu-wl4"]); diff --git a/dev-assets/doodads/build.sh b/dev-assets/doodads/build.sh index c50d5dd..5a72c6a 100755 --- a/dev-assets/doodads/build.sh +++ b/dev-assets/doodads/build.sh @@ -115,6 +115,33 @@ objects() { doodad convert -t "Exit Flag" exit-flag.png exit-flag.doodad doodad install-script exit-flag.js exit-flag.doodad + doodad convert -t "Start Flag" start-flag.png start-flag.doodad + + cp *.doodad ../../../assets/doodads/ + + cd ../crumbly-floor + + doodad convert -t "Crumbly Floor" floor.png shake1.png shake2.png \ + fall1.png fall2.png fall3.png fall4.png fallen.png \ + crumbly-floor.doodad + doodad install-script crumbly-floor.js crumbly-floor.doodad + cp *.doodad ../../../assets/doodads/ + + cd .. +} + +onoff() { + cd on-off/ + + doodad convert -t "State Button" blue-button.png orange-button.png state-button.doodad + doodad install-script state-button.js state-button.doodad + + doodad convert -t "State Block (Blue)" blue-on.png blue-off.png state-block-blue.doodad + doodad install-script state-block-blue.js state-block-blue.doodad + + doodad convert -t "State Block (Orange)" orange-off.png orange-on.png state-block-orange.doodad + doodad install-script state-block-orange.js state-block-orange.doodad + cp *.doodad ../../../assets/doodads/ cd .. @@ -126,5 +153,6 @@ doors trapdoors azulians objects +onoff doodad edit-doodad -quiet -lock -author "Noah" ../../assets/doodads/*.doodad doodad edit-doodad -hide ../../assets/doodads/azu-blu.doodad diff --git a/dev-assets/doodads/crumbly-floor/crumbly-floor.js b/dev-assets/doodads/crumbly-floor/crumbly-floor.js new file mode 100644 index 0000000..155be86 --- /dev/null +++ b/dev-assets/doodads/crumbly-floor/crumbly-floor.js @@ -0,0 +1,60 @@ +// Crumbly Floor. +function main() { + Self.SetHitbox(0, 0, 65, 7); + + Self.AddAnimation("shake", 100, ["shake1", "shake2", "floor", "shake1", "shake2", "floor"]); + Self.AddAnimation("fall", 100, ["fall1", "fall2", "fall3", "fall4"]); + + // Recover time for the floor to respawn. + var recover = 5000; + + // States of the floor. + var stateSolid = 0; + var stateShaking = 1; + var stateFalling = 2; + var stateFallen = 3; + var state = stateSolid; + + // Started the animation? + var startedAnimation = false; + + Events.OnCollide(function(e) { + // Only trigger for mobile characters. + if (!e.Actor.IsMobile()) { + return; + } + + // If the floor is falling, the player passes right thru. + if (state === stateFalling || state === stateFallen) { + return; + } + + // Floor is solid until it begins to fall. + if (e.InHitbox && (state === stateSolid || state === stateShaking)) { + // Only activate when touched from the top. + if (e.Overlap.Y > 0) { + return false; + } + + // Begin the animation sequence if we're in the solid state. + if (state === stateSolid) { + state = stateShaking; + Self.PlayAnimation("shake", function() { + state = stateFalling; + Self.PlayAnimation("fall", function() { + state = stateFallen; + Self.ShowLayerNamed("fallen"); + + // Recover after a while. + setTimeout(function() { + Self.ShowLayer(0); + state = stateSolid; + }, recover); + }); + }) + } + + return false; + } + }); +} diff --git a/dev-assets/doodads/crumbly-floor/fall1.png b/dev-assets/doodads/crumbly-floor/fall1.png new file mode 100644 index 0000000000000000000000000000000000000000..bc9710c3ae72e969b73fd46d463cd39a4ce41912 GIT binary patch literal 1021 zcmeAS@N?(olHy`uVBq!ia0vp^jv&mz1|<8wpLAtlU~I{Bb`J1#c2+1T%1_J8No8Qr zm{>c}*5j~)%+dJhrAngg+8%-@1Lo><#9L&Eb_FP2;aY1oBjy*Yuhb+Farc8;A3Qjo zboJoT$Z+;>M}a>Kg@vU-B@>1IPZxKe)^6_t2Xe zqiRs3vw%r-(qs1j&G+xl`q^1%t|`K96`%7vS%TvoQ}3+YdimRBk6Acun8Tw^$FF2I zp1c zvU2qk-hu*-9ubY|yN~b2zTNw`dfCnU{HMB#PBoc`NCTsVEy>&6h2cL4F4((#GEjuG zz$3Dlfq`2Xgc%uT&5-~KvX^-Jy0Sm!krQV#G`}yC0Thxfag8W(&d<$F%`0JWE=o-- zNlj5G&n(GMaQE~L2yf&Q2S)c*PZ!6Kid%1|ZVWnXz|;0tF8^Zqi7@@AlD8ge|FmnJI^O$JT(y_(IkmXH z{`eccyWhqC&szJp<87qf`VNik#GXJe&Ct-PKmL9G>sqrf-``7f>8wp2zvABa6$Z`f zs8Qq7RlP8!_56>kr+=1w_?P$l%IWpRI;;oy*R5KW{&~$Pdfa(S6h84 zNavVD?%KDut6%Tx?*0A$!u69%hKwb_Vs)3MwC0~WbevNA9B?4a;e|7phSH!;uDfM*qb6Mw<&;$Uj_P@pe literal 0 HcmV?d00001 diff --git a/dev-assets/doodads/crumbly-floor/fall2.png b/dev-assets/doodads/crumbly-floor/fall2.png new file mode 100644 index 0000000000000000000000000000000000000000..1524b6d991e736b351dbfe6010b7ee7dc3c02b2d GIT binary patch literal 986 zcmV<0110>4P)EX>4Tx04R}tkv&MmKpe$iTcsiu2P;Ss$xxjvh+jBr6^c+H)C#RSm|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfadlF3krMxx6k5c1aNLh~_a1le0DryARI_6YP&La) zCE`LRyD9`<5yBAq5y6ziOnpuilkgm0_we!cF2=LG&;2=il$^-`pFljzbi*RvAfDc| zbk6(4VOEqB;&b9rgDyz?$aUG}H_ioz{X8>lq*L?6VPc`s#&R38qM;H`5=RwPqkMnH zWrgz=XSG~q&3p0}hH~1 zax9<%6_Voz|AXJ%n)!)wHz^bcI$v!2V;BhT0*#t&e;?a+;{*si16NwhU#SB#pQP7X zTJ#9$-3BhMTbjHFTnGy0}1(02=TuerT7_i_3Fq^Yaq4RCM> zj1(w)-Q(R|?Y;ebrrF;Q%8GKzf;1Ex00006VoOIv0RI600RN!9r;`8x010qNS#tmY z3ljhU3ljkVnw%H_000McNliru;|v}b1~#d?iOT>002y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00FW|L_t(|+U=ITalFhDVXMeg3aQ)5XW@Zkew5s)MzQfqC|13Bj;BC;&Y-81XDro(>c zzI(o0lZeRa>CwIa{PvN&-@ROV4yBaaz2os1#@DfJe&@?I=`(W9DMg3(gDqMNPlR5) zMJF2x;E9oQPP%w4fEU|~uXB8PeIM62a)c*>KHQ42EKBp;V-r5?cdcJr`B*V*+!2B@jGE=0U2ARqz0=cUd+5bPvpd^~NC1yWfXF=~ zhitjmi>Cz;5qa<|+sgi=cLzAElchz{??*y2Y?%?M}X>g2s#HaGmn z7+WFI*351#tjLNsxhRntk$OHl7rop@&&>$&D_h(C`Iw!{XwinC_({FM*@0000000000000000000000000000000Pqj_1QHi;YHCWq7ytkO07*qo IM6N<$fEX>4Tx04R}tkv&MmKpe$iTcsiu2P;Ss$xxjvh+jBr6^c+H)C#RSm|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfadlF3krMxx6k5c1aNLh~_a1le0DryARI_6YP&La) zCE`LRyD9`<5yBAq5y6ziOnpuilkgm0_we!cF2=LG&;2=il$^-`pFljzbi*RvAfDc| zbk6(4VOEqB;&b9rgDyz?$aUG}H_ioz{X8>lq*L?6VPc`s#&R38qM;H`5=RwPqkMnH zWrgz=XSG~q&3p0}hH~1 zax9<%6_Voz|AXJ%n)!)wHz^bcI$v!2V;BhT0*#t&e;?a+;{*si16NwhU#SB#pQP7X zTJ#9$-3BhMTbjHFTnGy0}1(02=TuerT7_i_3Fq^Yaq4RCM> zj1(w)-Q(R|?Y;ebrrF;Q%8GKzf;1Ex00006VoOIv0RI600RN!9r;`8x010qNS#tmY z3ljhU3ljkVnw%H_000McNliru;|v}b20EY(#ozz{02y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00EUrL_t(|+U?iDZNnfG#&KTMEwVz7xnzipQ8Gc#9iYdY zaHps|L@qvd1EP*fTE?xl%lI%1 zl79AbJ}%?qef~54`S!Yuy?^~kO<|#)xCZB(H^!Lj^(wVNecFoeQo5mBSZl+3ro%G=*h>(# z*FUUXqG9i8-;FO`+CJgt<33Vbc&VW`uY{HWv^}XcqR=#lVUW^EGTvv=8mYC`KMG@- zCSM95d_Ol&+&?4@A=kO%0JIL>>T*8%+(}}s^=WwV=UYxP?IEOFT3U{-bS2b=;hgh5 z!KFvA_72h0+obi0wcb$g3d+5M#P1MKtsyk8ExNaJ&X>;l|2REzHAw3dsC~uVEA7ow zwhAEkKSxh-TQ}UC7wwPZeU{qE!VRxo4Qsc^mfJ@5xeXk85e000000000000000 f000000DJNaoeVRA5@15q00000NkvXXu0mjfjoYSb literal 0 HcmV?d00001 diff --git a/dev-assets/doodads/crumbly-floor/fall4.png b/dev-assets/doodads/crumbly-floor/fall4.png new file mode 100644 index 0000000000000000000000000000000000000000..97e8ee0a411680b6958eda2260f596436505919f GIT binary patch literal 855 zcmV-d1E~CoP)EX>4Tx04R}tkv&MmKpe$iTcsiu2P;Ss$xxjvh+jBr6^c+H)C#RSm|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfadlF3krMxx6k5c1aNLh~_a1le0DryARI_6YP&La) zCE`LRyD9`<5yBAq5y6ziOnpuilkgm0_we!cF2=LG&;2=il$^-`pFljzbi*RvAfDc| zbk6(4VOEqB;&b9rgDyz?$aUG}H_ioz{X8>lq*L?6VPc`s#&R38qM;H`5=RwPqkMnH zWrgz=XSG~q&3p0}hH~1 zax9<%6_Voz|AXJ%n)!)wHz^bcI$v!2V;BhT0*#t&e;?a+;{*si16NwhU#SB#pQP7X zTJ#9$-3BhMTbjHFTnGy0}1(02=TuerT7_i_3Fq^Yaq4RCM> zj1(w)-Q(R|?Y;ebrrF;Q%8GKzf;1Ex00006VoOIv0RI600RN!9r;`8x010qNS#tmY z3ljhU3ljkVnw%H_000McNliru;|v}b2Lh24Og{hs02y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00A#aL_t(|+U?lQ5rQxfhT&ivwBV78MNo$6z$&O9*b+zk zSx?R|3MQK@QS^OgyoeK$FPopyIRIEOO_R(&^Jm_B@!m^LyTkb?!}%!MzASwoLJ&>c z{i&7y)Jkgm@rScOQeLzcNNy0%0ce8Ij!_lB+KVhgh*g0mj7R^91AuZ?Q}>V53fj_P zivXN+ZXCyEPeBw_!crLX!D~+x?e9On#&efL%4w1s###umBmHFpOLpvB??Q+LkUIOx zRiz0ac0|>@)LB;Z!RidJSvg(THC91fuD2#@@Y;&7s36U)baS->uo!&tBv_`O+Zn4q zWQXxpWmtPMer@3DYqKVR=l>o`c5SN-w8~}1^85}Vh~@obw-sz%0spj=0RR9100000 h000000002+3-0%??gF?RbwU6D002ovPDHLkV1jpoZPEY$ literal 0 HcmV?d00001 diff --git a/dev-assets/doodads/crumbly-floor/fallen.png b/dev-assets/doodads/crumbly-floor/fallen.png new file mode 100644 index 0000000000000000000000000000000000000000..dd5e57f357fc9decc291d98dd48998b8ceaeb5f5 GIT binary patch literal 652 zcmeAS@N?(olHy`uVBq!ia0vp^jv&mz1|<8wpLAtlU~I{Bb`J1#c2+1T%1_J8No8Qr zm{>c}*5j~)%+dJhrAngg+8%-@1Lo><#9L&Eb_FP2;aY1oBjy*Yuhb+Farc8;A3Qjo zboJoT$Z+;>M}a>Kg@vU-B@>1IPZxKe)^6_t2Xe zqiRs3vw%r-(qs1j&G+xl`q^1%t|`K96`%7vS%TvoQ}3+YdimRBk6Acun8Tw^$FF2I zp1c zvU2qk-hu*-9ubY|yN~b2zTNw`dfCnU{HMB#PBoc`NCTsVEy>&6h2cL4F4((#GEjuG zz$3Dlfq`2Xgc%uT&5-~KvX^-Jy0Sm!krUVE@c3}9A1EYQ;u=xnoS&PUnpeW$T$Gwv zlA5AWo>`Ki;O^-g5Z=fq4pfxl>EaktaqH~`MnMJ!78Zjq@Bb88M7NYqx>6kMF+stx giG@>0g)&B7w7NMF`#`6p00i_>zopr0Q(R6EdT%j literal 0 HcmV?d00001 diff --git a/dev-assets/doodads/crumbly-floor/floor.png b/dev-assets/doodads/crumbly-floor/floor.png new file mode 100644 index 0000000000000000000000000000000000000000..f89f16ea50e7f622b27a4a049e4e6a6db588c749 GIT binary patch literal 868 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 z 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 XZ-#CO$x|&V00000NkvXXu0mjf-qJT! literal 0 HcmV?d00001 diff --git a/dev-assets/doodads/on-off/blue-off.png b/dev-assets/doodads/on-off/blue-off.png new file mode 100644 index 0000000000000000000000000000000000000000..6275e2b86b300a6edcee0eb6ce5994a426b301bf GIT binary patch literal 648 zcmV;30(bq1P)EX>4Tx04R}tkv&MmKpe$iTcsiu2P;Ss$xxjvh+jBr6^c+H)C#RSm|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfadlF3krMxx6k5c1aNLh~_a1le0DryARI_6YP&La) zCE`LRyD9`<5yBAq5y6ziOnpuilkgm0_we!cF2=LG&;2=il$^-`pFljzbi*RvAfDc| zbk6(4VOEqB;&b9rgDyz?$aUG}H_ioz{X8>lq*L?6VPc`s#&R38qM;H`5=RwPqkMnH zWrgz=XSG~q&3p0}hH~1 zax9<%6_Voz|AXJ%n)!)wHz^bcI$v!2V;BhT0*#t&e;?a+;{*si16NwhU#SB#pQP7X zTJ#9$-3BhMTbjHFTnGy0}1(02=TuerT7_i_3Fq^Yaq4RCM> zj1(w)-Q(R|?Y;ebrrF;Q%8GKzf;1Ex00006VoOIv0RI600RN!9r;`8x010qNS#tmY z3ljhU3ljkVnw%H_000McNliru;|v}a4i_xRd8z;a02y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{003Y~L_t(o!|jwY4uCKW1MPgaZ{oFOX$PQ;m=1SaqDYM* zU#-c}yPAEeCtvkPU5~*e0hJOB7)M?7$Ad4(tHzzz&Gp5$sn~ i%N5P8`2TQQK$1@5h(;1h{|PVv0000EX>4Tx04R}tkv&MmKpe$iTcsiu2P;Ss$xxjvh+jBr6^c+H)C#RSm|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfadlF3krMxx6k5c1aNLh~_a1le0DryARI_6YP&La) zCE`LRyD9`<5yBAq5y6ziOnpuilkgm0_we!cF2=LG&;2=il$^-`pFljzbi*RvAfDc| zbk6(4VOEqB;&b9rgDyz?$aUG}H_ioz{X8>lq*L?6VPc`s#&R38qM;H`5=RwPqkMnH zWrgz=XSG~q&3p0}hH~1 zax9<%6_Voz|AXJ%n)!)wHz^bcI$v!2V;BhT0*#t&e;?a+;{*si16NwhU#SB#pQP7X zTJ#9$-3BhMTbjHFTnGy0}1(02=TuerT7_i_3Fq^Yaq4RCM> zj1(w)-Q(R|?Y;ebrrF;Q%8GKzf;1Ex00006VoOIv0RI600RN!9r;`8x010qNS#tmY z3ljhU3ljkVnw%H_000McNliru;|v}a4mgJxMDqXu02y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{004tYL_t(o!|j;S4S*mJLwkft&RHDJnRJ$01wV|4A1YDf z5z~H?-U~FOAXqh~gs;_$0D!mw6d;lT%mKibp#cr335a;MO*^UH-tH@(cxX^A)(4rX z@L?t@j^m{X6+XNt7)(MCf)IpYvtqMivtqOQWhS;)`D8u>Lnop9C-49OfElcKDb6dC R_0RwS002ovPDHLkV1h1D7g+!R literal 0 HcmV?d00001 diff --git a/dev-assets/doodads/on-off/orange-button.png b/dev-assets/doodads/on-off/orange-button.png new file mode 100644 index 0000000000000000000000000000000000000000..ec5ef16c1d141d60d8c2b02487901a69048a07b3 GIT binary patch literal 751 zcmVEX>4Tx04R}tkv&MmKpe$iTcsiu2P;Ss$xxjvh+jBr6^c+H)C#RSm|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfadlF3krMxx6k5c1aNLh~_a1le0DryARI_6YP&La) zCE`LRyD9`<5yBAq5y6ziOnpuilkgm0_we!cF2=LG&;2=il$^-`pFljzbi*RvAfDc| zbk6(4VOEqB;&b9rgDyz?$aUG}H_ioz{X8>lq*L?6VPc`s#&R38qM;H`5=RwPqkMnH zWrgz=XSG~q&3p0}hH~1 zax9<%6_Voz|AXJ%n)!)wHz^bcI$v!2V;BhT0*#t&e;?a+;{*si16NwhU#SB#pQP7X zTJ#9$-3BhMTbjHFTnGy0}1(02=TuerT7_i_3Fq^Yaq4RCM> zj1(w)-Q(R|?Y;ebrrF;Q%8GKzf;1Ex00006VoOIv0RI600RN!9r;`8x010qNS#tmY z3ljhU3ljkVnw%H_000McNliru;|v}a5Df+DzYhQa02y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{0075HL_t(o!|hjX3d0}_eNT20cR0_~v+OMOD%p>zq);|( z>$H%7peZ!Zmrsc#vOwqst!C;(a>nIcWwzl3o`amQ$x0>l(C zVeYW(xOa9iY|8EKw_5!nCNzM(^Dq5rcj(*Xbu|!2FPj#7vMV-c2jki&Fk9J}qgY*C zq-6OpQNxD#XB`td5cSW$`M)(b+>wB*G13Brc!^l=u*u3ME1Rq=JE|(CejO(t>E_Z~ h&j7l-8Nxua`vwB$aRbfzH+292002ovPDHLkV1nUJK8yeW literal 0 HcmV?d00001 diff --git a/dev-assets/doodads/on-off/orange-off.png b/dev-assets/doodads/on-off/orange-off.png new file mode 100644 index 0000000000000000000000000000000000000000..1ce8f1ebe33526d52aa9300fa43a7229ca69b95b GIT binary patch literal 650 zcmV;50(Jd~P)EX>4Tx04R}tkv&MmKpe$iTcsiu2P;Ss$xxjvh+jBr6^c+H)C#RSm|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfadlF3krMxx6k5c1aNLh~_a1le0DryARI_6YP&La) zCE`LRyD9`<5yBAq5y6ziOnpuilkgm0_we!cF2=LG&;2=il$^-`pFljzbi*RvAfDc| zbk6(4VOEqB;&b9rgDyz?$aUG}H_ioz{X8>lq*L?6VPc`s#&R38qM;H`5=RwPqkMnH zWrgz=XSG~q&3p0}hH~1 zax9<%6_Voz|AXJ%n)!)wHz^bcI$v!2V;BhT0*#t&e;?a+;{*si16NwhU#SB#pQP7X zTJ#9$-3BhMTbjHFTnGy0}1(02=TuerT7_i_3Fq^Yaq4RCM> zj1(w)-Q(R|?Y;ebrrF;Q%8GKzf;1Ex00006VoOIv0RI600RN!9r;`8x010qNS#tmY z3ljhU3ljkVnw%H_000McNliru;|v}a4<=*`NYMZQ02y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{003f1L_t(o!|jwo3cw%?1ULIx-_+OIONAo#*ww?#$ppa= zb}T*gOTC)vU61o${ZV_qm}I=`T?4E(1xHX{=}l(ACv3um0k8u*06VY)umd|FZAY^2 kq?XGqG?ml;!#sc_-4l&Q5=FR-6#xJL07*qoM6N<$f-RX0kpKVy literal 0 HcmV?d00001 diff --git a/dev-assets/doodads/on-off/orange-on.png b/dev-assets/doodads/on-off/orange-on.png new file mode 100644 index 0000000000000000000000000000000000000000..c56e09ea48740edbc0566598f7bc56349fb234f1 GIT binary patch literal 687 zcmV;g0#N;lP)EX>4Tx04R}tkv&MmKpe$iTcsiu2P;Ss$xxjvh+jBr6^c+H)C#RSm|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfadlF3krMxx6k5c1aNLh~_a1le0DryARI_6YP&La) zCE`LRyD9`<5yBAq5y6ziOnpuilkgm0_we!cF2=LG&;2=il$^-`pFljzbi*RvAfDc| zbk6(4VOEqB;&b9rgDyz?$aUG}H_ioz{X8>lq*L?6VPc`s#&R38qM;H`5=RwPqkMnH zWrgz=XSG~q&3p0}hH~1 zax9<%6_Voz|AXJ%n)!)wHz^bcI$v!2V;BhT0*#t&e;?a+;{*si16NwhU#SB#pQP7X zTJ#9$-3BhMTbjHFTnGy0}1(02=TuerT7_i_3Fq^Yaq4RCM> zj1(w)-Q(R|?Y;ebrrF;Q%8GKzf;1Ex00006VoOIv0RI600RN!9r;`8x010qNS#tmY z3ljhU3ljkVnw%H_000McNliru;|v}a4>JkTtU3Sy02y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{004(cL_t(o!|j;S4S*mFM6ZNN>MRcDOgamz;D?0N4}}l| z#N2)GMcS8gAqRq_xFe#oWQ72@mJt9JL^43=4-isMhY2(Vgnt{8m1_IAOLhEHf!k(n z_e@P4dZKt7(2qJ))ZslrV-kW8gdhZy6_XW{6_eF3J&|AK;TQw3Y!GMv2}S?_zzN9y VDbBO|<5>Uz002ovPDHLkV1kX=7@q(D literal 0 HcmV?d00001 diff --git a/dev-assets/doodads/on-off/state-block-blue.js b/dev-assets/doodads/on-off/state-block-blue.js new file mode 100644 index 0000000..0b287e3 --- /dev/null +++ b/dev-assets/doodads/on-off/state-block-blue.js @@ -0,0 +1,28 @@ +// Blue State Block +function main() { + Self.SetHitbox(0, 0, 33, 33); + + // Blue block is ON by default. + var state = true; + + Message.Subscribe("broadcast:state-change", function(newState) { + state = !newState; + console.warn("BLUE BLOCK Received state=%+v, set mine to %+v", newState, state); + + // Layer 0: ON + // Layer 1: OFF + if (state) { + Self.ShowLayer(0); + } else { + Self.ShowLayer(1); + } + }); + + Events.OnCollide(function(e) { + if (e.Actor.IsMobile() && e.InHitbox) { + if (state) { + return false; + } + } + }); +} diff --git a/dev-assets/doodads/on-off/state-block-orange.js b/dev-assets/doodads/on-off/state-block-orange.js new file mode 100644 index 0000000..634d5e8 --- /dev/null +++ b/dev-assets/doodads/on-off/state-block-orange.js @@ -0,0 +1,28 @@ +// Orange State Block +function main() { + Self.SetHitbox(0, 0, 33, 33); + + // Orange block is OFF by default. + var state = false; + + Message.Subscribe("broadcast:state-change", function(newState) { + state = newState; + console.warn("ORANGE BLOCK Received state=%+v, set mine to %+v", newState, state); + + // Layer 0: OFF + // Layer 1: ON + if (state) { + Self.ShowLayer(1); + } else { + Self.ShowLayer(0); + } + }); + + Events.OnCollide(function(e) { + if (e.Actor.IsMobile() && e.InHitbox) { + if (state) { + return false; + } + } + }); +} diff --git a/dev-assets/doodads/on-off/state-button.js b/dev-assets/doodads/on-off/state-button.js new file mode 100644 index 0000000..51a2af3 --- /dev/null +++ b/dev-assets/doodads/on-off/state-button.js @@ -0,0 +1,47 @@ +// State Block Control Button +function main() { + console.log("%s initialized!", Self.Doodad.Title); + Self.SetHitbox(0, 0, 33, 33); + + // When the button is activated, don't keep toggling state until we're not + // being touched again. + var colliding = false; + + // Button is "OFF" by default. + var state = false; + + Events.OnCollide(function(e) { + if (colliding) { + return false; + } + + // Only trigger for mobile characters. + if (e.Actor.IsMobile()) { + console.log("Mobile actor %s touched the on/off button!", e.Actor.Actor.Filename); + + // Only activate if touched from the bottom or sides. + if (e.Overlap.Y === 0) { + console.log("... but touched the top!"); + return false; + } + + colliding = true; + console.log(" -> emit state change"); + state = !state; + Message.Broadcast("broadcast:state-change", state); + + if (state) { + Self.ShowLayer(1); + } else { + Self.ShowLayer(0); + } + } + + // Always a solid button. + return false; + }); + + Events.OnLeave(function(e) { + colliding = false; + }) +}