Noah Petherbridge
fc736abd5f
Adds several new doodads to the game and 5 new wallpapers (parchment paper in blue, green, red, white and yellow). New doodads: * Crusher: A purple block-headed mob wearing an iron helmet. It tries to crush the player when you get underneath. Its flat helmet can be ridden on like an elevator back up. * Snake: A green stationary mob that always faces toward the player. If the player is nearby and jumps, the Snake will jump too and hope to catch the player in mid-air. * Gems and Totems: A new key & lock collectible. Gems have quantity so you can collect multiple, and place them into matching Totems. A Totem gives off a power signal when its gem is placed and all other Totems it is linked to have also been activated. A single Totem may link to an Electric Door and require only one gem to open it, or it can link to other Totems and they all require gems before the power signal is sent out.
108 lines
3.1 KiB
JavaScript
108 lines
3.1 KiB
JavaScript
// Gem stone totem socket.
|
|
|
|
/*
|
|
The Totem is a type of key-door that holds onto its corresponding
|
|
Gemstone. When a doodad holding the right Gemstone touches the
|
|
totem, the totem takes the gemstone and activates.
|
|
|
|
If the Totem is not linked to any other Totems, it immediately
|
|
sends a power(true) signal upon activation.
|
|
|
|
If the Totem is linked to other Totems, it waits until all totems
|
|
have been activated before it will emit a power signal. Only one
|
|
such totem needs to be linked to e.g. an Electric Door - no matter
|
|
which totem is solved last, they'll all emit a power signal when
|
|
all of their linked totems are activated.
|
|
*/
|
|
|
|
let color = Self.GetTag("color"),
|
|
keyname = "gem-"+color+".doodad",
|
|
activated = false,
|
|
linkedReceiver = false, // is linked to a non-totem which might want power
|
|
totems = {}, // linked totems
|
|
shimmerFreq = 1000;
|
|
|
|
function main() {
|
|
// Show the hollow socket on level load (last layer)
|
|
Self.ShowLayer(4);
|
|
|
|
// Find any linked totems.
|
|
for (let link of Self.GetLinks()) {
|
|
if (link.Filename.indexOf("gem-totem") > -1) {
|
|
totems[link.ID()] = false;
|
|
} else {
|
|
linkedReceiver = true;
|
|
}
|
|
}
|
|
|
|
console.log("Totem %s is linked to %d neighbors", Self.ID(), Object.keys(totems).length);
|
|
|
|
// Shimmer animation is just like the gemstones: first 4 frames
|
|
// are the filled socket sprites.
|
|
Self.AddAnimation("shimmer", 100, [0, 1, 2, 3, 0]);
|
|
|
|
Events.OnCollide((e) => {
|
|
if (activated) return;
|
|
|
|
if (e.Actor.IsMobile() && e.Settled) {
|
|
// Do they have our gemstone?
|
|
let hasKey = e.Actor.HasItem(keyname) >= 0;
|
|
if (!hasKey) {
|
|
return;
|
|
}
|
|
|
|
// Take the gemstone.
|
|
e.Actor.RemoveItem(keyname, 1);
|
|
Self.ShowLayer(0);
|
|
|
|
// Emit to our linked totem neighbors.
|
|
activated = true;
|
|
Message.Publish("gem-totem:activated", Self.ID());
|
|
tryPower();
|
|
}
|
|
});
|
|
|
|
Message.Subscribe("gem-totem:activated", (totemId) => {
|
|
totems[totemId] = true;
|
|
tryPower();
|
|
})
|
|
|
|
setInterval(() => {
|
|
if (activated) {
|
|
Self.PlayAnimation("shimmer", null);
|
|
}
|
|
}, shimmerFreq);
|
|
}
|
|
|
|
// Try to send a power signal for an activated totem.
|
|
function tryPower() {
|
|
// Only emit power if we are linked to something other than a totem.
|
|
if (!linkedReceiver) {
|
|
return;
|
|
}
|
|
|
|
console.log("Totem %s (%s) tries power", Self.ID(), Self.Filename);
|
|
|
|
// Can't if any of our linked totems aren't activated.
|
|
try {
|
|
for (let totemId of Object.keys(totems)) {
|
|
console.log("Totem %s (%s) sees linked totem %s", Self.ID(), Self.Filename, totemId);
|
|
if (totems[totemId] === false) {
|
|
console.log("Can't, a linked totem not active!");
|
|
return;
|
|
}
|
|
}
|
|
} catch(e) {
|
|
console.error("Caught: %s", e);
|
|
}
|
|
|
|
// Can't if we aren't powered.
|
|
if (activated === false) {
|
|
console.log("Can't, we are not active!");
|
|
return;
|
|
}
|
|
|
|
// Emit power!
|
|
console.log("POWER!");
|
|
Message.Publish("power", true);
|
|
} |