(ns advent.screens.rooms.inside-jail (:require [clojure.core.async :refer [chan]] [advent.screens.rooms :as rooms] [advent.screens.rooms.common :as common] [advent.saves :as saves] [advent.steam :as steam] [advent.actions :as actions] [advent.screens.items :as items] [advent.utils :as utils] [advent.pathfind] [clojure.zip :as zip] [play-clj.core :refer :all] [play-clj.ui :refer :all] [play-clj.utils :refer :all] [play-clj.g2d :refer :all])) (defn remove-lock [entities] (-> entities (utils/remove-interaction :lock) (assoc-in [:room :collision] (get-in entities [:room :collision-free])))) (defn open-lock [entities] (actions/walk-to entities :ego [174 80] :face :right) (actions/play-animation entities :ego :reach) (actions/talk entities :ego "Yes, that's it!") (actions/play-sound entities "inside-jail/open-door.ogg" 0.5 false) (actions/walk-straight-to entities :moveable-bars [65 77]) (actions/update-entities entities #(remove-lock %)) (actions/update-state entities #(assoc % :opened-bars? true))) (defn chest-full? [entities] (seq (get-in @entities [:state :chest-contents]))) (defn touch-chest [entities] (cond (not (chest-full? entities)) (do (actions/walk-to entities :ego [192 66] :face :right) (actions/play-animation entities :ego :reach-start :stop? false) (actions/play-animation entities :chest-top :open) (actions/play-animation entities :ego :reach-stop) (actions/do-dialogue entities :ego "It's empty now.") (actions/play-animation entities :ego :reach-start :stop? false) (actions/play-animation entities :chest-top :close) (actions/play-animation entities :ego :reach-stop)) (get-in @entities [:state :opened-bars?]) (do (actions/walk-to entities :ego [192 66] :face :right) (actions/play-animation entities :ego :reach-start :stop? false) (actions/play-animation entities :chest-top :open) (actions/play-animation entities :ego :reach-stop) (actions/do-dialogue entities :ego "Hey!" :ego "All my possessions are in here!") (actions/update-state entities #(-> % (assoc :inventory (concat (:inventory %) (:chest-contents %))) (assoc :chest-contents []))) (when (not (actions/has-obtained? entities :rope)) (actions/give entities :rope) (actions/do-dialogue entities :ego "Looks like there's some rope in here too.")) (actions/play-animation entities :ego :reach-start :stop? false) (actions/play-animation entities :chest-top :close) (actions/play-animation entities :ego :reach-stop) ) :else (do (actions/walk-to entities :ego [179 81] :face :right) (actions/play-animation entities :ego :reach) (actions/do-dialogue entities :ego "I can't reach it!") (when (not (get-in @entities [:state :warden-sleeping?])) (actions/do-dialogue entities :warden "Quit yer yappin'!" :warden "You're not escaping while I'm on watch, so just give it up."))))) (defn do-warden-dialogue [entities] (actions/do-dialogue entities :ego "Hey, who are you? Why am I in this cell?" :warden "You're under arrest for theft of property." :ego "Under arrest? Theft of property?" :ego "I didn't steal the Sword of Blergh, I fulfilled the prophecy." :warden "Slow down there, chap." :warden "You're not under arrest for theft of the sword." :warden "You're under arrest for stealing the Duke of Remington's ladder." :ego "But I'm the good guy!\nThe game is named after me!" :warden "Sorry, chap. The law's the law." ) (actions/present-choices entities {:choices ["But I'm just a kid." {:run #(actions/respond entities % :warden "The Duke of Remington is a very stern fellow." :warden "He doesn't bend the rules, even for young thieves.") :choices actions/previous-choices} "Took, son of Luke, son of Puke lent me that ladder!" {:run #(actions/respond entities % :warden "It wasn't his to give." :warden "In fact, he's off to the gallows come dawn." :ego "Oh boy.") :choices actions/previous-choices} "But I was going to teach Bloodclot a lesson!" {:run #(actions/respond entities % :warden "Sure you were. If he even exists." :ego "He does! He's going to come destroy the town first thing in the morning!" :warden "Uh huh." :warden "As if I haven't heard the \"bad guy is coming to destroy the town\" 1000 times already." :warden "You could try coming up with something creative, chap." :ego "Creative?" :warden "Yeah, like, 'My mother is in the hospital.'" :warden "Or, 'I have a highly contagious case of the lizard-pox.'") :choices actions/previous-choices} "But the whole town will die if I don't do something!" {:run #(actions/respond entities % :warden "The whole town will have a thief on the loose if I don't keep you here." :warden "We don't want that either, do we?" :ego "This is life and death we're talking about here!" :warden "And this is my job. A chap's got to do his job, am I right?" :warden "You've got to steal, and I've got to lock you up." :warden "It's how it works.") :choices actions/previous-choices} "Nevermind." {:run #(do (actions/respond entities % :warden "This conversation has got me very tired." :warden "Be a good chap and let me rest.") (actions/play-animation entities :warden :fall-asleep :stop? false) (actions/begin-animation entities :warden :sleep) (actions/update-state entities (fn [s] (assoc s :warden-sleeping? true))))}]})) (defn get-key [ entities] (actions/walk-to entities :ego [71 82] :face :left) (actions/play-animation entities :ego :squat) (let [had-key-before? (actions/has-obtained? entities :key)] (if had-key-before? (do (actions/do-dialogue entities :ego "He's got the key clutched in his hand!") (actions/play-animation entities :ego :squat) (actions/give entities :key)) (do (actions/do-dialogue entities :ego "He's got something clutched in his hand!") (actions/play-animation entities :ego :squat) (actions/do-dialogue entities :ego "What's this?" :ego "Hello hello!" :ego "It's the key!") (actions/give entities :key) (actions/do-dialogue entities :ego "Come on! It's that easy to escape?" :ego "We're not going to at least do that dog and bone scenario?" :ego "I get to just take the key and leave?" :ego "Seems like a pretty sorry excuse for a puzzle."))))) (defn tie-up-warden [entities message] (if (get-in @entities [:state :opened-bars?]) (do (actions/play-animation entities :ego :idea) (actions/do-dialogue entities :ego "I know!" :ego message) (actions/walk-to entities :ego [91 61] :face :left) (actions/play-animation entities :ego :reach) (actions/do-dialogue entities :warden "Hey! What do you think you're doing?" :warden "Back in the slammer you go.") (common/go-to-jail entities)) (actions/talk entities :ego "What am I supposed to do while in this cell?"))) (defn search-hay [entities] (actions/walk-to entities :ego [144 86] :face :right) (let [hay-searches (get-in @entities [:state :hay-searches] 0)] (condp = hay-searches 0 (do (actions/talk entities :ego "Maybe there's a needle or something in here.") (actions/play-animation entities :ego :squat) (actions/talk entities :ego "No. Nothing at all!")) 1 (do (actions/talk entities :ego "Maybe I missed something. I'll check again.") (actions/play-animation entities :ego :squat) (actions/talk entities :ego "Nope. Still nothing.")) 2 (do (actions/talk entities :ego "There's got to be something in here!") (actions/play-animation entities :ego :squat) (actions/talk entities :ego "Nope. Still nothing.")) (do (actions/talk entities :ego "One more try.") (actions/play-animation entities :ego :squat) (actions/play-animation entities :ego :sigh) (actions/do-dialogue entities :ego "You know, in some games, you have to try multiple times." :ego "But I have a feeling each time you click on this hay, I'm going to find nothing." :ego "Maybe you should give it a rest."))) (actions/update-state entities #(assoc % :hay-searches (inc hay-searches))))) (defn leave [entities] (if (get-in @entities [:state :opened-bars?]) (do (actions/walk-to entities :ego [279 57]) (if (chest-full? entities) (actions/talk entities :ego "I probably shouldn't leave without my belongings.") (do (actions/transition-background entities :outside-jail [50 46] :face :right) (if (get-in @entities [:state :dropped-ball?]) (do (actions/do-dialogue entities :ego "Yes! I made it!" :ego "But what now?" :ego "I have till sunrise before Bloodclot comes and destroys the town." :ego "Maybe Gandarf can help me!") (steam/set-achievement "EX_CON") (utils/save-chapter @entities :chapter-4) ) (do (actions/do-dialogue entities :ego "Yes! I made it!" :guard "Hmm?" :guard "Halt! Thou art under arrest!" :guard "Thou wilst be putteth back into thy cell.") (actions/play-animation entities :ego :sigh) (common/go-to-jail entities) (actions/do-dialogue entities :ego "Dang! I was so close to freedom, I could taste it!")))))) (actions/talk entities :ego "Do you really think I can walk down those steps while I'm locked up?"))) (defn make [screen] (let [warden-sheet (texture! (utils/get-texture "inside-jail/warden.png") :split 43 58) warden-talk (animation 0.2 (for [i [1 0 1 0 1 0 1 0 0 0 2 0]] (aget warden-sheet 0 i))) warden-stand (animation 0.1 (for [i (flatten [(repeat 30 0) 2 (repeat 20 0) 2])] (aget warden-sheet 0 i))) warden-fall-asleep (animation 0.1 (for [i (flatten [(repeat 5 0) 2 2 (repeat 10 0) 2 2 2 (repeat 10 0) 2 2 2])] (aget warden-sheet 0 i))) warden-sleep (animation 0.25 (for [i (flatten [ 3 4 3 4 3 4 3 4 3 4 5 5 2 2 2 2 2 2])] (aget warden-sheet 0 i))) candle (utils/make-anim "inside-jail/candle.png" [20 25] 0.1 (range 4)) candle-aura (utils/make-anim "inside-house/candle-aura.png" [27 27] 0.2 [0 1 2 3 2 1]) crowbar (utils/make-anim "inside-jail/crowbar.png" [16 33] 0.15 (flatten [(repeat 120 0) [1 2 3 3 2 1]]))] (rooms/make :music :inside-antique :name "In jail" :sounds { :squeek (utils/load-sound "inside-jail/squeak.ogg") :crowbar-sound (utils/load-sound "ego/crowbar.ogg") } :interactions { :lock {:box [172 102 190 124] :script (actions/get-script entities (actions/walk-to entities :ego [174 80] :face :right) (actions/play-animation entities :ego :reach) (actions/talk entities :ego "There's no helping it. It's locked.")) :scripts {:key (actions/get-script entities (open-lock entities))}} :window {:box [98 110 118 140] :script (actions/get-script entities (actions/walk-to entities :ego [102 88] :face :right) (actions/do-dialogue entities :ego "What a peaceful night." :ego "Oh my sweet Georgia McGorgeous. How will I ever save you now?") (when-not (get-in @entities [:state :daydreamed-georgia-night]) (actions/update-state entities #(assoc % :daydreamed-georgia-night true)) (actions/georgia-say entities "You gotta find a way out of there, Tick!") (actions/do-dialogue entities :ego "She's right." :ego "I have to escape."))) :scripts {:crowbar (actions/get-script entities (if (get-in @entities [:state :bent-bars?]) (actions/do-dialogue entities :ego "They're bent as far as they can go.") (do (actions/walk-to entities :ego [102 88] :face :right) (actions/play-animation entities :ego :reach) (actions/play-sound entities :crowbar-sound 0.5) (actions/remove-entity entities :closed-window) (actions/update-state entities #(assoc % :bent-bars? true)) (actions/do-dialogue entities :ego "Now we're getting somewhere.")))) :ball-n-chain (actions/get-script entities (if (get-in @entities [:state :bent-bars?]) (do (actions/walk-to entities :ego [102 88] :face :right) (actions/play-animation entities :ego :reach) (actions/play-sound entities (get-in @entities [:room :entities :ego :drop-sound]) 0.2) (actions/update-state entities #(assoc % :dropped-ball? true)) (actions/do-dialogue entities :ego "Geronimo!!") (actions/play-sound entities "inside-jail/guard-crash.ogg" 0.6 false) (actions/do-dialogue entities :guard "*oof*!") (actions/camera-shake entities 6) (actions/begin-animation entities :warden :stand) (Thread/sleep 300) (actions/do-dialogue entities :warden "Charlie, is that you chap?" :warden "What're you doing digging through my trash can?") (Thread/sleep 300) (actions/play-animation entities :warden :fall-asleep :stop? false) (actions/begin-animation entities :warden :sleep) (actions/remove-item entities :ball-n-chain) (actions/talk entities :ego "Phew! That was close!")) (actions/do-dialogue entities :ego "I don't know what to do with that."))) :sword (actions/get-script entities (actions/talk entities :ego "I wouldn't want to accidentally break the Sword of Blergh.")) :rope (actions/get-script entities (cond (get-in @entities [:state :dropped-ball?]) (do (actions/walk-to entities :ego [102 88] :face :right) (actions/do-dialogue entities :ego "Here goes.") (actions/play-animation entities :ego :reach) (actions/do-dialogue entities :ego "Wait a second." :ego "That guard is out cold." :ego "Why risk breaking my neck now?")) (get-in @entities [:state :bent-bars?]) (do (actions/walk-to entities :ego [102 88] :face :right) (actions/do-dialogue entities :ego "Here goes.") (actions/play-animation entities :ego :reach) (actions/do-dialogue entities :ego "Uh oh. There's a guard right beneath the window." :ego "I had better not, or else I'd get caught.")) :else (actions/do-dialogue entities :ego "Good thinking." :ego "But I can't fit out that window." :ego "And the bars are made of steel!"))) :key (actions/get-script entities (actions/walk-to entities :ego [102 88] :face :right) (actions/do-dialogue entities :ego "Here goes." :ego "Wait..." :ego "The door locks without a key." :ego "If I get caught, I won't be able to get out."))}} :hay {:box [130 86 177 102] :script (actions/get-script entities (search-hay entities)) :scripts {:default (actions/get-script entities (actions/talk entities :ego "Finding it again will be like finding a needle in a haystack!")) :key (actions/get-script entities (actions/do-dialogue entities :ego "I'm trying to escape." :ego "Not help the next bloke who gets trapped here."))}} :chest {:box [194 62 228 99] :script (actions/get-script entities (touch-chest entities)) :scripts {:key (actions/get-script entities (if (get-in @entities [:state :opened-bars?]) (do (actions/walk-to entities :ego [192 66] :face :right) (actions/play-animation entities :ego :reach) (actions/do-dialogue entities :ego "The key doesn't unlock the chest." :ego "Good thing it's not locked!")) (actions/talk entities :ego "Not while I'm in this cell.")))}} :door {:box [257 62 301 152] :cursor :down :script (actions/get-script entities (leave entities))} } :layers [(assoc (utils/get-texture "inside-jail/background.png") :x 0 :y 0 :baseline 0 :night-profile :none) (assoc (utils/get-texture "inside-jail/bars.png") :x 0 :y 0 :baseline 165 :night-profile :none) (assoc (utils/get-texture "inside-jail/glow.png") :x 0 :y 0 :baseline 240 :additive? true :opacity 0.35 :night-profile :none) (assoc (utils/get-texture "inside-jail/fg.png") :x 0 :y 5 :baseline 241 :parallax 1.5 :night-profile :none)] :hotspots [{:box [121 40 258 44] :fn (fn [screen entities] (let [is-walking? (#{(get-in entities [:room :entities :ego :left :walk]) (get-in entities [:room :entities :ego :right :walk])} (get-in entities [:room :entities :ego :anim]))] (if is-walking? (let [entities (-> entities (update-in [:fg-actions] #(assoc % :channel (chan) :current nil :started? false :script-running? false)) (update-in [:room :entities :ego] #(actions/start-animation screen % :stand)))] ((actions/get-script entities (actions/stop-walking entities :ego) (actions/play-sound entities :squeek 0.15) (actions/do-dialogue entities :ego "Oops!" :warden "Hey! What are you doing?" :warden "Trying to escape, are ye, chap?") (common/go-to-jail entities)) entities) entities) entities)))}] :entities {:warden (assoc (utils/get-texture "inside-jail/warden.png" ) :x 40 :y 60 :baseline 166 :stand warden-stand :talk warden-talk :sleep warden-sleep :fall-asleep warden-fall-asleep :anim warden-stand :anim-start 0 :night-profile :none :inhale (utils/load-sound "inside-jail/inhale.ogg") :exhale (utils/load-sound "inside-jail/exhale.ogg") :talk-color (color 0.9 0.3 0.9 1.0) :anim-sound-frames {warden-stand {31 [:blink 0.15] 51 [:blink 0.15]} warden-talk {10 [:blink 0.15]} warden-fall-asleep {7 [:blink 0.15] 18 [:blink 0.15]} warden-sleep {0 [:inhale 0.1] 10 [:exhale 0.1]}} :script (actions/get-script entities (cond (actions/has-item? entities :key) (actions/talk entities :ego "Shh! It's best not to wake him now.") (get-in @entities [:state :warden-fast-asleep?]) (get-key entities) (get-in @entities [:state :warden-sleeping?]) (do (actions/walk-to entities :ego [103 82]) (actions/do-dialogue entities :ego "Yoo-hoo! Mr. Warden?" :ego "I guess he's really fast asleep!") (actions/update-state entities #(assoc % :warden-fast-asleep? true))) :else (do (actions/walk-to entities :ego [103 82]) (do-warden-dialogue entities)))) :scripts {:sword (actions/get-script entities (actions/do-dialogue entities :ego "That's pretty gruesome." :ego "I can't kill him just for doing his job.")) :rope (actions/get-script entities (tie-up-warden entities "I'll tie him up.")) :ball-n-chain (actions/get-script entities (tie-up-warden entities "I'll lock him up."))}) :chest-top (assoc (utils/get-texture "inside-jail/chest-top.png") :x 193 :y (- 240 165) :baseline 166 :origin-x 0 :origin-y 0 :night-profile :none :open (animation 0.8 [(utils/get-texture "inside-jail/chest-top-open.png")]) :close (animation 0.8 [(utils/get-texture "inside-jail/chest-top.png")])) :ball-n-chain (assoc (utils/get-texture "inside-jail/ball-n-chain.png") :x 80 :y 80 :baseline 160 :night-profile :none :script (actions/get-script entities (actions/walk-to entities :ego [103 83] :face :left) (actions/play-animation entities :ego :squat) (actions/remove-entity entities :ball-n-chain) (actions/give entities :ball-n-chain))) :moveable-bars (assoc (utils/get-texture "inside-jail/moveable-bars.png") :night-profile :none :x 132 :y 77 :baseline 163) :candle (assoc (animation->texture screen candle) :x 207 :y 118 :baseline 2 :anim candle :anim-start 0 :night-profile :none) :candle-aura (assoc (animation->texture screen candle-aura) :x 215 :y 130 :baseline 2 :additive? true :origin-x 13 :origin-y 13 :opacity 0.5 :anim candle-aura :anim-start 0 :night-profile :none :script (actions/get-script entities (actions/talk entities :ego "Just a candle.")) :scripts {:default (actions/get-script entities (actions/talk entities :ego "I might catch the place on fire."))}) :candle-smoke (doto (assoc (particle-effect "particles/candle") :x 215 :y 130 :baseline 200) (particle-effect! :set-position 215 130)) :crowbar (assoc (animation->texture screen crowbar) :anim crowbar :anim-start 0 :x 300 :y 60 :baseline 175 :night-profile :none :script (actions/get-script entities (if (get-in @entities [:state :opened-bars?]) (do (actions/walk-to entities :ego [295 55] :face :right) (actions/play-animation entities :ego :reach) (actions/remove-entity entities :crowbar ) (actions/give entities :crowbar) (actions/talk entities :ego "It's a crowbar.")) (actions/talk entities :ego "I can't reach it.")))) :closed-window (assoc (utils/get-texture "inside-jail/window.png") :night-profile :none :x 99 :y 111 :baseline 128) :guard { :object nil :width 100 :height 100 :x 70 :y 55 :talk-color (color 0.2 0.6 1.0 1.0)}} :collision "inside-jail/collision-locked.png" :collision-free (advent.pathfind/map-from-resource "inside-jail/collision-free.png") :scale-fn (utils/scaler-fn-with-baseline 0 0.50 1.5) :start-pos [130 85] :apply-state (fn [_ entities] (utils/fast-forward-particle (get-in entities [:room :entities :candle-smoke])) (as-> entities entities (if (actions/has-obtained? entities :ball-n-chain) (update-in entities [:room :entities] #(dissoc % :ball-n-chain)) entities) (if (actions/has-obtained? entities :crowbar) (update-in entities [:room :entities] #(dissoc % :crowbar)) entities) (if (get-in entities [:state :warden-sleeping?]) (update-in entities [:room :entities :warden] #(actions/start-animation % :sleep)) entities) (if (get-in entities [:state :opened-bars?]) (update-in (remove-lock entities) [:room :entities :moveable-bars] #(assoc % :x 65 :y 77)) entities) (if (get-in entities [:state :bent-bars?]) (update-in entities [:room :entities] #(dissoc % :closed-window)) entities))))))