diff --git a/doors/build.sh b/doors/build.sh index 7615a8d..d38ef5b 100755 --- a/doors/build.sh +++ b/doors/build.sh @@ -43,8 +43,23 @@ doodad edit-doodad -q --tag color=small small-key.doodad doodad install-script keys.js small-key.doodad doodad convert -t "Electric Door" electric{1,2,3,4}.png door-electric.doodad +doodad edit-doodad -q --option "opened=bool" door-electric.doodad doodad install-script electric-door.js door-electric.doodad +# All locked doors have an option to unlock. +doodad edit-doodad -q --option "unlocked=bool" door-green.doodad +doodad edit-doodad -q --option "unlocked=bool" door-blue.doodad +doodad edit-doodad -q --option "unlocked=bool" door-yellow.doodad +doodad edit-doodad -q --option "unlocked=bool" door-red.doodad +doodad edit-doodad -q --option "unlocked=bool" small-key-door.doodad + +# All keys may be subject to gravity. +doodad edit-doodad -q --option "has gravity=bool" key-green.doodad +doodad edit-doodad -q --option "has gravity=bool" key-blue.doodad +doodad edit-doodad -q --option "has gravity=bool" key-yellow.doodad +doodad edit-doodad -q --option "has gravity=bool" key-red.doodad +doodad edit-doodad -q --option "has gravity=bool" small-key.doodad + # Tag the category for these doodads for i in *.doodad; do doodad edit-doodad --tag "category=doors" $i; done doodad edit-doodad --tag "category=doors,gizmos" door-electric.doodad diff --git a/doors/colored-door.js b/doors/colored-door.js index 1c47ab6..b529d57 100644 --- a/doors/colored-door.js +++ b/doors/colored-door.js @@ -1,7 +1,17 @@ -// Colored Locked Doors. +/* +Colored Locked Doors + +This script handles the blue, green, red, yellow and small-key doors. + +Each door has a corresponding key that will unlock it. Small Key doors consume a +small key when unlocked for the first time. + +Options: "unlocked" can make the door unlocked by default when the level begins. +*/ const color = Self.GetTag("color"), - keyname = color === "small" ? "small-key.doodad" : "key-" + color + ".doodad"; + keyname = color === "small" ? "small-key.doodad" : "key-" + color + ".doodad", + isUnlocked = Self.GetOption("unlocked"); function main() { // Layers in the doodad image. @@ -19,6 +29,12 @@ function main() { Self.SetHitbox(34, 0, 13, 76); + // Options: door is unlocked at level start? + if (isUnlocked) { + unlocked = true; + Self.ShowLayer(layer.unlocked); + } + Events.OnCollide((e) => { // Record the side that this actor has touched us, in case the door // needs to open. diff --git a/doors/electric-door.js b/doors/electric-door.js index 5c35201..07e274b 100644 --- a/doors/electric-door.js +++ b/doors/electric-door.js @@ -1,8 +1,16 @@ -// Electric Door +/* +Electric Door -let animating = false; -let opened = false; -let powerState = false; +Opens when it receives power. Closes when power is removed. + +Always toggles when activated by a switch. + +Options: opened (bool) to make it opened by default on level start. +*/ + +let animating = false, + opened = Self.GetOption("opened") === true, + powerState = false; // Function to handle the door opening or closing. function setPoweredState(powered) { @@ -35,6 +43,12 @@ function main() { Self.SetHitbox(0, 0, 34, 76); + // If the player has configured the door to be opened by default, make it so. + if (opened) { + powerState = true; + Self.ShowLayer(3); + } + // A linked Switch that activates the door will send the Toggle signal // immediately before the Power signal. The door can just invert its // state on this signal, and ignore the very next Power signal. Ordinary diff --git a/doors/keys.js b/doors/keys.js index c51154d..23be9fe 100644 --- a/doors/keys.js +++ b/doors/keys.js @@ -1,9 +1,19 @@ -// Colored Keys and Small Key +/* +Colored Keys and Small Key + +Options: "has gravity" will make the key subject to gravity. +*/ const color = Self.GetTag("color"), - quantity = color === "small" ? 1 : 0; + quantity = color === "small" ? 1 : 0, + hasGravity = Self.GetOption("has gravity") === true; function main() { + if (hasGravity) { + Self.SetGravity(hasGravity); + Self.SetMobile(true); + } + Events.OnCollide((e) => { if (e.Settled) { if (e.Actor.HasInventory()) { diff --git a/gems/Makefile b/gems/Makefile index f9e5d87..1765147 100644 --- a/gems/Makefile +++ b/gems/Makefile @@ -55,4 +55,15 @@ build: doodad edit-doodad --tag "category=doors" $${i};\ done + # Gemstones have gravity by default, but make it configurable. + doodad edit-doodad -q --option "has gravity=bool=true" gem-green.doodad + doodad edit-doodad -q --option "has gravity=bool=true" gem-yellow.doodad + doodad edit-doodad -q --option "has gravity=bool=true" gem-red.doodad + doodad edit-doodad -q --option "has gravity=bool=true" gem-blue.doodad + + # Totems have an option to mark them unlocked by default. + for i in gem-totem-*.doodad; do\ + doodad edit-doodad -q --option "has gemstone=bool" $${i};\ + done + cp *.doodad ../../../assets/doodads/ \ No newline at end of file diff --git a/gems/gemstone.js b/gems/gemstone.js index efb9361..73ec353 100644 --- a/gems/gemstone.js +++ b/gems/gemstone.js @@ -1,11 +1,14 @@ // Gem stone collectibles/keys. const color = Self.GetTag("color"), - shimmerFreq = 1000; + shimmerFreq = 1000, + hasGravity = Self.GetOption("has gravity") === true; function main() { - Self.SetMobile(true); - Self.SetGravity(true); + if (hasGravity) { + Self.SetMobile(true); + Self.SetGravity(true); + } Self.AddAnimation("shimmer", 100, [0, 1, 2, 3, 0]); Events.OnCollide((e) => { diff --git a/gems/totem.js b/gems/totem.js index 3598f50..be526e8 100644 --- a/gems/totem.js +++ b/gems/totem.js @@ -20,7 +20,8 @@ let color = Self.GetTag("color"), activated = false, linkedReceiver = false, // is linked to a non-totem which might want power totems = {}, // linked totems - shimmerFreq = 1000; + shimmerFreq = 1000, + isUnlocked = Self.GetOption("has gemstone") === true; function main() { // Show the hollow socket on level load (last layer) @@ -39,6 +40,12 @@ function main() { // are the filled socket sprites. Self.AddAnimation("shimmer", 100, [0, 1, 2, 3, 0]); + // Options: if it already has its gemstone, set its state accordingly. + if (isUnlocked) { + activated = true; + Self.ShowLayer(0); + } + Events.OnCollide((e) => { if (activated) return; diff --git a/options_test.js b/options_test.js new file mode 100644 index 0000000..3a84128 --- /dev/null +++ b/options_test.js @@ -0,0 +1,15 @@ +// Test doodad script for Options. +function main() { + console.error("OptionsTest Doodad: %s (%s)", Self.Title, Self.ID()); + const options = Self.Options(); + for (let item of options) { + let value = Self.GetOption(item); + console.log("Option %s = %+v", item, value); + + if (value === true) { + console.log("It is a true boolean!"); + } else if (value === false) { + console.log("It is a false boolean!"); + } + } +} \ No newline at end of file diff --git a/regions/Makefile b/regions/Makefile index 890ecf4..afdd10c 100644 --- a/regions/Makefile +++ b/regions/Makefile @@ -13,6 +13,7 @@ build: # Fire Region doodad convert -t "Fire Region" fire-128.png reg-fire.doodad doodad install-script fire.js reg-fire.doodad + doodad edit-doodad -q --option "name=str=fire" reg-fire.doodad # Stall Region doodad convert -t "Stall Player (250ms)" stall-128.png reg-stall-250.doodad @@ -29,7 +30,7 @@ build: # Warp Door doodad convert -t "Invisible Warp Door" warp-door-64.png reg-warp-door.doodad - doodad edit-doodad --tag "color=invisible" reg-warp-door.doodad + doodad edit-doodad --tag "color=invisible" --option "locked (exit only)=bool" reg-warp-door.doodad doodad install-script ../warp-door/warp-door.js reg-warp-door.doodad # Reset Level Timer diff --git a/regions/fire.js b/regions/fire.js index 977537a..452e53d 100644 --- a/regions/fire.js +++ b/regions/fire.js @@ -1,4 +1,6 @@ -// Goal Region. +// Fire Region +const name = Self.GetOption("name"); + function main() { Self.Hide(); @@ -13,7 +15,7 @@ function main() { } if (e.InHitbox) { - FailLevel("You have died!"); + FailLevel(`Watch out for ${name}!`); } }); } diff --git a/trapdoors/Makefile b/trapdoors/Makefile index 596c1b2..718118c 100644 --- a/trapdoors/Makefile +++ b/trapdoors/Makefile @@ -29,6 +29,6 @@ build: # Build the Electric Trapdoor. doodad convert -t "Electric Trapdoor" electric{1,2,3,4}.png electric-trapdoor.doodad doodad install-script electric-trapdoor.js electric-trapdoor.doodad - doodad edit-doodad -q --tag "category=doors,gizmos" electric-trapdoor.doodad + doodad edit-doodad -q --tag "category=doors,gizmos" --option "opened=bool" electric-trapdoor.doodad cp *.doodad ../../../assets/doodads/ diff --git a/trapdoors/electric-trapdoor.js b/trapdoors/electric-trapdoor.js index 836f662..8f69dc9 100644 --- a/trapdoors/electric-trapdoor.js +++ b/trapdoors/electric-trapdoor.js @@ -3,7 +3,7 @@ var animationSpeed = 100, spriteWidth = 114, thickness = 7, - isOpen = false, + isOpen = Self.GetOption("opened") === true, animating = false, powerState = false; @@ -13,6 +13,12 @@ function main() { Self.AddAnimation("open", animationSpeed, [0, 1, 2, 3]); Self.AddAnimation("close", animationSpeed, [3, 2, 1, 0]); + // Options: if the player marked it "opened" make it open by default. + if (isOpen) { + Self.ShowLayer(3); + powerState = true; + } + // Subscribe to Switches and other power sources. Note: if a // switch toggles us, we ignore the immediately following // power signal which will be coming from the same switch. diff --git a/warp-door/Makefile b/warp-door/Makefile index 90d80b2..f541d65 100644 --- a/warp-door/Makefile +++ b/warp-door/Makefile @@ -17,7 +17,7 @@ build: doodad install-script warp-door.js warp-door-orange.doodad for i in *.doodad; do\ - doodad edit-doodad --tag "category=doors" --hitbox=34,76 $${i};\ + doodad edit-doodad --tag "category=doors" --option "locked (exit only)=bool" --hitbox=34,76 $${i};\ done for i in warp-door-*.doodad; do\ doodad edit-doodad --tag "category=doors,gizmos" $${i};\ diff --git a/warp-door/warp-door.js b/warp-door/warp-door.js index 2bde9f3..0e1965c 100644 --- a/warp-door/warp-door.js +++ b/warp-door/warp-door.js @@ -1,7 +1,18 @@ -// Warp Doors +/* +Warp Doors + +Link it to another Warp Door and the player can travel between them. + +Doors without links will behave as 'locked' doors and cannot be opened. + +Options: "locked (exit only)" bool will make the door behave as locked +even if linked - it can be an exit-only door that the player can come +out of but can not open. +*/ const color = Self.GetTag("color"), - isStateDoor = color === 'blue' || color === 'orange'; + isStateDoor = color === 'blue' || color === 'orange', + isLocked = Self.GetOption("locked (exit only)") === true; // State in case we're a blue warp door. let state = color === 'blue', @@ -63,7 +74,7 @@ function main() { } // Doors without linked exits are not usable. - if (linkedDoor === null) { + if (linkedDoor === null || isLocked) { if (!flashedCooldown) { Flash("This door is locked."); flashedCooldown = true;