290 lines
8.4 KiB
Go
290 lines
8.4 KiB
Go
package doodle
|
|
|
|
import (
|
|
"strings"
|
|
"time"
|
|
|
|
"git.kirsle.net/SketchyMaze/doodle/pkg/balance"
|
|
"git.kirsle.net/SketchyMaze/doodle/pkg/modal"
|
|
"git.kirsle.net/SketchyMaze/doodle/pkg/modal/loadscreen"
|
|
"git.kirsle.net/SketchyMaze/doodle/pkg/scripting"
|
|
"git.kirsle.net/SketchyMaze/doodle/pkg/shmem"
|
|
"git.kirsle.net/SketchyMaze/doodle/pkg/windows"
|
|
"git.kirsle.net/go/ui"
|
|
"github.com/dop251/goja"
|
|
)
|
|
|
|
// IsDefaultPlayerCharacter checks whether the DefaultPlayerCharacter doodad has
|
|
// been modified
|
|
|
|
// MakeCheatsWindow initializes the windows/cheats_menu.go window from anywhere you need it,
|
|
// binding all the variables in. If you pass a nil Supervisor, this function will attempt to
|
|
// find one based on your Scene and
|
|
func (d *Doodle) MakeCheatsWindow(supervisor *ui.Supervisor) *ui.Window {
|
|
// If not given a supervisor, try and find one.
|
|
if supervisor == nil {
|
|
if v, err := d.FindLikelySupervisor(); err != nil {
|
|
d.FlashError("Couldn't make cheats window: %s", err)
|
|
return nil
|
|
} else {
|
|
supervisor = v
|
|
}
|
|
}
|
|
|
|
cfg := windows.CheatsMenu{
|
|
Supervisor: supervisor,
|
|
Engine: d.Engine,
|
|
SceneName: func() string {
|
|
return d.Scene.Name()
|
|
},
|
|
RunCommand: func(command string) {
|
|
// If we are in Play Mode, every command out of here is cheating.
|
|
if playScene, ok := d.Scene.(*PlayScene); ok {
|
|
playScene.SetCheated()
|
|
}
|
|
d.shell.Execute(command)
|
|
},
|
|
OnSetPlayerCharacter: func(doodad string) {
|
|
if scene, ok := d.Scene.(*PlayScene); ok {
|
|
scene.SetCheated()
|
|
scene.SetPlayerCharacter(doodad)
|
|
} else {
|
|
shmem.FlashError("This only works during Play Mode.")
|
|
}
|
|
},
|
|
}
|
|
return windows.MakeCheatsMenu(cfg)
|
|
}
|
|
|
|
// SetPlayerCharacter -- this is designed to be called in-game with the developer
|
|
// console. Sets your player character to whatever doodad you want, not just the
|
|
// few that have cheat codes. If you set an invalid filename, you become the
|
|
// dummy default doodad sprite (a red "X").
|
|
func (d *Doodle) SetPlayerCharacter(filename string) {
|
|
balance.PlayerCharacterDoodad = filename
|
|
if playScene, isPlay := d.Scene.(*PlayScene); isPlay {
|
|
playScene.SetPlayerCharacter(balance.PlayerCharacterDoodad)
|
|
}
|
|
}
|
|
|
|
// cheatCommand is a subroutine of the Command.Run() method of the Doodle
|
|
// developer shell (commands.go). It looks for special cheat codes entered
|
|
// into the command shell and executes them.
|
|
//
|
|
// Returns true if a cheat was intercepted, false if the command is not a cheat.
|
|
func (c Command) cheatCommand(d *Doodle) bool {
|
|
// Some cheats only work in Play Mode.
|
|
playScene, isPlay := d.Scene.(*PlayScene)
|
|
|
|
// If a character cheat is used during Play Mode, replace the player NOW.
|
|
var setPlayerCharacter bool
|
|
|
|
// Cheat codes
|
|
switch c.Raw {
|
|
case balance.CheatUncapFPS:
|
|
if fpsDoNotCap {
|
|
d.Flash("Reset frame rate throttle to factory default FPS")
|
|
} else {
|
|
d.Flash("Unleashing as many frames as we can render!")
|
|
}
|
|
fpsDoNotCap = !fpsDoNotCap
|
|
|
|
case balance.CheatEditDuringPlay:
|
|
if isPlay {
|
|
playScene.drawing.Editable = true
|
|
playScene.SetCheated()
|
|
d.Flash("Level canvas is now editable. Don't edit and drive!")
|
|
} else {
|
|
d.FlashError("Use this cheat in Play Mode to make the level canvas editable.")
|
|
}
|
|
|
|
case balance.CheatScrollDuringPlay:
|
|
if isPlay {
|
|
playScene.drawing.Scrollable = true
|
|
playScene.SetCheated()
|
|
d.Flash("Level canvas is now scrollable with the arrow keys.")
|
|
} else {
|
|
d.FlashError("Use this cheat in Play Mode to make the level scrollable.")
|
|
}
|
|
|
|
case balance.CheatAntigravity:
|
|
if isPlay {
|
|
playScene.SetCheated()
|
|
|
|
playScene.antigravity = !playScene.antigravity
|
|
playScene.Player.SetGravity(!playScene.antigravity)
|
|
|
|
if playScene.antigravity {
|
|
d.Flash("Gravity disabled for player character.")
|
|
} else {
|
|
d.Flash("Gravity restored for player character.")
|
|
}
|
|
} else {
|
|
d.FlashError("Use this cheat in Play Mode to disable gravity for the player character.")
|
|
}
|
|
|
|
case balance.CheatNoclip:
|
|
if isPlay {
|
|
playScene.SetCheated()
|
|
|
|
playScene.noclip = !playScene.noclip
|
|
playScene.Player.SetNoclip(playScene.noclip)
|
|
|
|
playScene.antigravity = playScene.noclip
|
|
playScene.Player.SetGravity(!playScene.antigravity)
|
|
|
|
if playScene.noclip {
|
|
d.Flash("Clipping disabled for player character.")
|
|
} else {
|
|
d.Flash("Clipping and gravity restored for player character.")
|
|
}
|
|
} else {
|
|
d.FlashError("Use this cheat in Play Mode to disable clipping for the player character.")
|
|
}
|
|
|
|
case balance.CheatShowAllActors:
|
|
if isPlay {
|
|
playScene.SetCheated()
|
|
for _, actor := range playScene.drawing.Actors() {
|
|
actor.Show()
|
|
}
|
|
d.Flash("All invisible actors made visible.")
|
|
} else {
|
|
d.FlashError("Use this cheat in Play Mode to show hidden actors, such as technical doodads.")
|
|
}
|
|
|
|
case balance.CheatGiveKeys:
|
|
if isPlay {
|
|
playScene.SetCheated()
|
|
playScene.Player.AddItem("key-red.doodad", 0)
|
|
playScene.Player.AddItem("key-blue.doodad", 0)
|
|
playScene.Player.AddItem("key-green.doodad", 0)
|
|
playScene.Player.AddItem("key-yellow.doodad", 0)
|
|
playScene.Player.AddItem("small-key.doodad", 99)
|
|
d.Flash("Given all keys to the player character.")
|
|
} else {
|
|
d.FlashError("Use this cheat in Play Mode to get all colored keys.")
|
|
}
|
|
|
|
case balance.CheatGiveGems:
|
|
if isPlay {
|
|
playScene.SetCheated()
|
|
playScene.Player.AddItem("gem-red.doodad", 1)
|
|
playScene.Player.AddItem("gem-green.doodad", 1)
|
|
playScene.Player.AddItem("gem-blue.doodad", 1)
|
|
playScene.Player.AddItem("gem-yellow.doodad", 1)
|
|
d.Flash("Given all gemstones to the player character.")
|
|
} else {
|
|
d.FlashError("Use this cheat in Play Mode to get all gemstones.")
|
|
}
|
|
|
|
case balance.CheatDropItems:
|
|
if isPlay {
|
|
playScene.SetCheated()
|
|
playScene.Player.ClearInventory()
|
|
d.Flash("Cleared inventory of player character.")
|
|
} else {
|
|
d.FlashError("Use this cheat in Play Mode to clear your inventory.")
|
|
}
|
|
|
|
case balance.CheatGodMode:
|
|
if isPlay {
|
|
d.Flash("God mode toggled")
|
|
playScene.SetCheated()
|
|
playScene.godMode = !playScene.godMode
|
|
if playScene.godMode {
|
|
d.FlashError("God mode enabled.")
|
|
} else {
|
|
d.Flash("God mode disabled.")
|
|
}
|
|
} else {
|
|
d.FlashError("Use this cheat in Play Mode to toggle invincibility.")
|
|
}
|
|
|
|
case balance.CheatFreeEnergy:
|
|
if isPlay {
|
|
playScene.SetCheated()
|
|
d.Flash("Power toggle sent to all actors in the level.")
|
|
for _, a := range playScene.Canvas().Actors() {
|
|
// Hacky stuff here - just a fun cheat code anyway.
|
|
vm := playScene.ScriptSupervisor().To(a.ID())
|
|
value := vm.Get("__tesla")
|
|
if value == nil || !value.ToBoolean() {
|
|
vm.Set("__tesla", true)
|
|
value = vm.Get("__tesla")
|
|
} else if value.ToBoolean() {
|
|
vm.Set("__tesla", false)
|
|
value = vm.Get("__tesla")
|
|
}
|
|
vm.Inbound <- scripting.Message{
|
|
Name: "power",
|
|
SenderID: a.ID(),
|
|
Args: []goja.Value{value},
|
|
}
|
|
}
|
|
} else {
|
|
d.FlashError("Use this cheat in Play Mode to send power to all actors (chaotic!).")
|
|
}
|
|
|
|
case balance.CheatDebugLoadScreen:
|
|
loadscreen.ShowWithProgress()
|
|
loadscreen.SetSubtitle("Loading: /dev/null", "Loadscreen testing.")
|
|
go func() {
|
|
var i float64
|
|
for i = 0; i < 100; i++ {
|
|
time.Sleep(100 * time.Millisecond)
|
|
loadscreen.SetProgress(i / 100)
|
|
}
|
|
loadscreen.Hide()
|
|
}()
|
|
|
|
case balance.CheatDebugWaitScreen:
|
|
m := modal.Wait("Crunching some numbers...").WithTitle("Please hold").Then(func() {
|
|
d.Flash("Wait modal dismissed.")
|
|
})
|
|
go func() {
|
|
time.Sleep(10 * time.Second)
|
|
m.Dismiss(true)
|
|
}()
|
|
|
|
case balance.CheatUnlockLevels:
|
|
balance.CheatEnabledUnlockLevels = !balance.CheatEnabledUnlockLevels
|
|
if balance.CheatEnabledUnlockLevels {
|
|
d.Flash("All locked Story Mode levels can now be played.")
|
|
} else {
|
|
d.Flash("All locked Story Mode levels are again locked.")
|
|
}
|
|
|
|
case balance.CheatSkipLevel:
|
|
if isPlay {
|
|
playScene.SetCheated()
|
|
playScene.ShowEndLevelModal(
|
|
true,
|
|
"Level Completed",
|
|
"Great job, you cheated and 'won' the level!",
|
|
)
|
|
} else {
|
|
d.Flash("Use this cheat in Play Mode to instantly win the level.")
|
|
}
|
|
|
|
default:
|
|
// See if it was an endorsed actor cheat.
|
|
if filename, ok := balance.CheatActors[strings.ToLower(c.Raw)]; ok {
|
|
d.Flash("Set default player character to %s.", filename)
|
|
balance.PlayerCharacterDoodad = filename
|
|
setPlayerCharacter = true
|
|
} else {
|
|
// Not a cheat code.
|
|
return false
|
|
}
|
|
}
|
|
|
|
// If we're setting the player character and in Play Mode, do it.
|
|
if setPlayerCharacter && isPlay {
|
|
playScene.SetCheated()
|
|
playScene.SetPlayerCharacter(balance.PlayerCharacterDoodad)
|
|
}
|
|
|
|
return true
|
|
}
|