(ns advent.screens.rooms.dream (:require [clojure.core.async :as a] [advent.screens.rooms :as rooms] [advent.screens.rooms.common :as common] [advent.actions :as actions] [advent.screens.items :as items] [advent.tween :as tween] [advent.utils :as utils] [clojure.zip :as zip] [clojure.set :as set] [clojure.string :as str] [play-clj.core :refer :all] [play-clj.math :refer :all] [play-clj.ui :refer :all] [play-clj.utils :refer :all] [play-clj.g2d :refer :all])) (def walk-chan (a/chan)) (defn set-opacity [entities opacity tool-opacity] (-> entities (assoc-in [:room :layers 0 :opacity] opacity) (assoc-in [:room :layers 1 :opacity] opacity) (assoc-in [:room :layers 2 :opacity] opacity) (assoc-in [:room :layers 3 :opacity] opacity) (assoc-in [:room :layers 4 :opacity] opacity) (assoc-in [:room :layers 5 :opacity] opacity) (assoc-in [:room :layers 6 :opacity] opacity) (assoc-in [:room :entities :sword :opacity] tool-opacity) (assoc-in [:room :entities :case :opacity] tool-opacity) (assoc-in [:room :entities :broom :opacity] tool-opacity) (assoc-in [:room :entities :shovel :opacity] tool-opacity) (assoc-in [:room :entities :fairy-godfather :opacity] opacity) (assoc-in [:room :entities :sign :opacity] opacity) (assoc-in [:room :entities :plaque-1 :opacity] tool-opacity) (assoc-in [:room :entities :plaque-2 :opacity] tool-opacity) (assoc-in [:room :entities :plaque-3 :opacity] tool-opacity))) (defn fade-in [entities] (actions/run-action entities (begin [this screen entities] (-> entities (assoc-in [:tweens :fade-in] (tween/tween :fade-in screen [:room :layers 0 :opacity] 0.0 1.0 0.5 :ease tween/ease-in-out-quintic)))) (continue [this screen entities] (set-opacity entities (get-in entities [:room :layers 0 :opacity] ) 0.0)) (done? [this screen entities] (= 1.0 (get-in entities [:room :layers 0 :opacity]))) (terminate [this screen entities] entities) (skip-type [this screen entities] :none))) (defn fade-in-tools [entities] (actions/run-action entities (begin [this screen entities] (-> entities (assoc-in [:tweens :fade-in] (tween/tween :fade-in screen [:room :entities :sword :opacity] 0.0 1.0 0.5 :ease tween/ease-in-out-quintic)))) (continue [this screen entities] (set-opacity entities 1.0 (get-in entities [:room :entities :sword :opacity]))) (done? [this screen entities] (= 1.0 (get-in entities [:room :entities :sword :opacity]))) (terminate [this screen entities] entities) (skip-type [this screen entities] :none))) (defn face-fairy [entities] (if (< (get-in @entities [:room :entities :fairy-godfather :x]) (get-in @entities [:room :entities :ego :x])) (actions/do-stop entities :ego :face :left) (actions/do-stop entities :ego :face :right))) (defn read-sword-plaque [entities] (actions/walk-to entities :ego [168 76] :face :left) (if-not (get-in @entities [:state :plaques-read :sword]) (do (actions/talk entities :ego "There's a plaque here.") (actions/play-animation entities :ego :squat) (actions/do-dialogue entities :ego "'A noble choice to be a knight,\nBe a hero, do what's right.'" :ego "'There's no need to shove,\nTo find your true love,'" :ego "'Because maidens love guys with might.'" :ego "Awesome!" :ego "If I become a knight, maybe Georgia McGorgeous will love me!") (actions/in-love entities)) (actions/talk entities :ego "I can't get through that glass!")) (actions/stop-walking entities :ego :face :right) (when-not (get-in @entities [:room :entities :fairy-godfather :distracted?]) (face-fairy entities) (actions/do-dialogue entities :fairy-godfather "Tick, I told you that you can't be a knight." :fairy-godfather "I think you'd be much better suited for a more menial job." :ego "Hey! Why can't I be a knight? It's my destiny!" :ego "And plus, it's the only way to get Georgia McGorgeous to love me!" :ego "And this plaque here says that maidens love knights." :fairy-godfather "As long as you're under my watch, Tick, I forbid it!" :fairy-godfather "And you're just not cut out for it!")) (actions/update-state entities #(update-in % [:plaques-read] conj :sword))) (defn read-broom-plaque [entities] (actions/walk-to entities :ego [267 70] :face :right) (actions/talk entities :ego "There's a plaque here.") (actions/play-animation entities :ego :squat) (actions/do-dialogue entities :ego "'Grab the broom, and sweep that dirt!\nSweep, and mop till your arms hurt.'" :ego "'You'll smell like a hog,\nwith stench like a fog,'" :ego "'So with you, no girl will flirt.'") (actions/play-animation entities :ego :sigh) (when-not (get-in @entities [:room :entities :fairy-godfather :distracted?]) (face-fairy entities) (actions/talk entities :ego "So can I at least slay ghouls with this broom?") (actions/stop-walking entities :ego :face :left) (actions/do-dialogue entities :fairy-godfather "Not quite, young Tick." :fairy-godfather "This weapon is used to fight a more persistent foe." :fairy-godfather "Dust and grime!" :fairy-godfather "Take the broom, and cast it into the pit of fate." :fairy-godfather "Then you can fulfill your fate as a janitor.")) (actions/update-state entities #(update-in % [:plaques-read] conj :broom))) (defn read-shovel-plaque [entities] (actions/walk-to entities :ego [61 72] :face :left) (actions/talk entities :ego "There's a plaque here.") (actions/play-animation entities :ego :squat) (actions/do-dialogue entities :ego "'Choose the shovel, dig some holes,\ntis the boringest of roles,'" :ego "'You can work by night,\nBut suffer a plight:'" :ego "'Gals dislike guys who bury souls.'") (actions/play-animation entities :ego :sigh) (when-not (get-in @entities [:room :entities :fairy-godfather :distracted?]) (face-fairy entities) (actions/do-dialogue entities :fairy-godfather "Don't be dismayed, young Tick." :fairy-godfather "Remember, these destinies can't be mistaken." :ego "But it sounds so dull!")) (actions/update-state entities #(update-in % [:plaques-read] conj :shovel))) (defn do-intro [entities] (Thread/sleep 2000) (actions/talk entities :ego "What's going on?") (actions/walk-straight-to entities :ego [160 60]) (actions/do-dialogue entities :ego "Who turned out the lights?") (actions/walk-straight-to entities :ego [120 50]) (Thread/sleep 900) (actions/talk entities :ego "Am I...") (Thread/sleep 500) (actions/talk entities :ego "... dead?") (Thread/sleep 900) (actions/talk entities :ego "... But I'm too young to die!" :anim :frustrated-talk :stop? false) (Thread/sleep 200) (actions/talk entities :ego "I promise I'll be a better boy!" :anim :frustrated-talk :stop? false) (Thread/sleep 200) (actions/talk entities :ego "I'll never steal another one of Gandarf's potions!" :anim :frustrated-talk :stop? false) (Thread/sleep 200) (actions/talk entities :ego "I swear!" :anim :frustrated-talk :stop? false) (actions/talk entities :fairy-godfather "... Tick ...") (Thread/sleep 500) (actions/walk-straight-to entities :ego [140 55] :face :right) (Thread/sleep 500) (actions/do-dialogue entities :ego "Huh?") (actions/talk entities :fairy-godfather "... Tiiiiccckk ...") (Thread/sleep 500) (actions/present-choices entities {:choices ["Who is that?" {:run #(actions/talk entities :ego %)} "What do you want from me?" {:run #(actions/talk entities :ego %)} "Show yourself!" {:run #(actions/talk entities :ego %)}]}) (actions/talk entities :fairy-godfather "Taaaaaaaaaaaaaaaaaa-") (sound! (sound "dream/appear.ogg") :play (utils/current-sound-volume)) (particle-effect! (get-in @entities [:room :entities :magic]) :reset) (particle-effect! (get-in @entities [:room :entities :magic]) :start) (fade-in entities) (actions/transition-music entities :dream :duration 0.25 ) (actions/talk entities :fairy-godfather "-daaaaaaaaaaaaa!") (Thread/sleep 1500) (actions/talk entities :ego "Oh no! The grim reaper!" :anim :frustrated-talk) (actions/do-dialogue entities :fairy-godfather "Relax, Tick. You're dreaming!" :ego "I am?" :ego "Then who are you?" :fairy-godfather "Why, I'm your fairy godfather of course!" :fairy-godfather "I've brought you here, to the pit of destiny." :fairy-godfather "Today you will choose your trade!" :fairy-godfather "Let us see what your fate could bring!" :fairy-godfather "Behold!") (particle-effect! (get-in @entities [:room :entities :magic]) :reset) (particle-effect! (get-in @entities [:room :entities :magic]) :start) (sound! (sound "dream/appear.ogg") :play (utils/current-sound-volume)) (fade-in-tools entities) (Thread/sleep 2500) (actions/do-dialogue entities :fairy-godfather "These, young Tick, represent the potential destinies for your life." :fairy-godfather "They have been selected since the dawn of time." :fairy-godfather "These destinies are never mistaken.") (actions/present-choices entities {:choices ["So I'm destined to be a shovel?" {:run #(actions/talk entities :ego %)} "So I'm destined to be a broom?" {:run #(actions/talk entities :ego %)} "So I'm destined to be a sword?" {:run #(actions/talk entities :ego %)}]}) (actions/update-entities entities #(update-in % [:room :entities :fairy-godfather] dissoc :path)) (actions/walk-straight-to entities :fairy-godfather [87 120] :speed 1.75 :update-baseline? false) (actions/update-entities entities (fn [e] (update-in e [:room :entities :fairy-godfather] assoc :path (catmull-rom-spline (map #(apply vector-2* %) [[87 120] [87 124]]) true)))) (actions/do-dialogue entities :fairy-godfather "This shovel represents the job of grave-digger." :fairy-godfather "A simple job, for a simple fellow." :ego "Hey! " :ego "I'm not simple.") (actions/update-entities entities #(update-in % [:room :entities :fairy-godfather] dissoc :path)) (actions/walk-straight-to entities :fairy-godfather [260 120] :speed 1.75 :update-baseline? false) (actions/update-entities entities (fn [e] (update-in e [:room :entities :fairy-godfather] assoc :path (catmull-rom-spline (map #(apply vector-2* %) [[260 120] [260 124]]) true)))) (actions/do-dialogue entities :fairy-godfather "Next, we have the broom, representing the humble job of a janitor." :ego "I'm not going to be a janitor!" :ego "What about that sword?" :fairy-godfather "Hmm? Sword?") (actions/update-entities entities #(update-in % [:room :entities :fairy-godfather] dissoc :path)) (actions/walk-straight-to entities :fairy-godfather [192 120] :speed 1.75 :update-baseline? false) (actions/update-entities entities (fn [e] (update-in e [:room :entities :fairy-godfather] assoc :path (catmull-rom-spline (map #(apply vector-2* %) [[192 118] [192 124]]) true)))) (actions/do-dialogue entities :fairy-godfather "Sword...?" :fairy-godfather "Uh, oh. There must be some mistake." :fairy-godfather "Ahem." :fairy-godfather "You must choose between being a janitor and grave-digger." :ego "But I want that sword, and be a knight!" :ego "And you said that these destinies are never mistaken!" :fairy-godfather "Nevermind that." :fairy-godfather "Choose the broom or shovel, and cast it into the pit of fate." :ego "But..." :fairy-godfather "No buts.") (actions/update-state entities #(assoc % :seen-intro? true))) (defn swing [entities] (actions/run-action entities (begin [this screen entities] (update-in entities [:room :entities :ego] #(actions/start-animation screen % :swing-shovel) )) (continue [this screen entities] (if (and (= (get-in entities [:room :entities :ego :current-frame-index]) 3) (not= (get-in entities [:room :entities :ego :previous-frame-index]) 3)) (do (particle-effect! (get-in entities [:room :entities :explode]) :reset) (particle-effect! (get-in entities [:room :entities :explode]) :start) (update-in entities [:room :entities] dissoc :case)) entities)) (done? [this screen entities] (animation! (actions/find-animation (get-in entities [:room :entities :ego]) :swing-shovel) :is-animation-finished (- (:total-time screen) (get-in entities [:room :entities :ego :anim-start])))) (terminate [this screen entities] (actions/stop screen entities :ego)) (skip-type [this screen entities] :none))) (defn return-from-island [screen entities] (when (and (not (get-in entities [:actions :script-running?])) (get-in entities [:state :active?]) (get-in entities [:room :entities :fairy-godfather :distracted?])) ((actions/get-script entities (actions/update-entities entities (fn [e] (update-in e [:room :entities :fairy-godfather] dissoc :distracted?))) (actions/walk-straight-to entities :fairy-godfather [240 120] :speed 3.0 :update-baseline? false :face :left) (actions/update-entities entities (fn [e] (update-in e [:room :entities :fairy-godfather] assoc :path (catmull-rom-spline (map #(apply vector-2* %) [[240 120] [240 124]]) true)))) (actions/do-dialogue entities :fairy-godfather "Hey! I didn't see anything over there!" :ego "Oh, yes, it must have flown off.")) entities)) nil) (defn distract [entities message subject] (actions/respond entities message :fairy-godfather (str "A " subject "!? Where?") :ego "Err..." :ego "Umm..." ) (actions/play-animation entities :ego :idea) (actions/do-dialogue entities :ego "On that island over there!" :ego (str "Yes, that's it! There's a " subject " on that island!") :fairy-godfather "Let me go check it out.") (actions/update-entities entities (fn [e] (update-in e [:room :entities :fairy-godfather] dissoc :path))) (actions/update-entities entities (fn [e] (update-in e [:room :entities :fairy-godfather] assoc :distracted? true))) (actions/walk-straight-to entities :fairy-godfather [211 210] :face :left)) (defn talk-to-fairy [entities] (do (face-fairy entities) (actions/do-dialogue entities :fairy-godfather "Young Tick, you must choose your destiny!") (actions/present-choices entities {:choices ["What if I don't like any of these choices?" {:run #(do (actions/respond entities % :fairy-godfather "Who wouldn't want to be a grave digger or janitor?" :fairy-godfather "That's the problem with kids these days." :fairy-godfather "Always complaining about what they can't have." :fairy-godfather "You need an attitude adjustment, mister.")) :choices actions/previous-choices} "Look out!" {:run #(do (actions/respond entities % :fairy-godfather "What is it?" :ego "Err... Um..." :ego "I saw a, um...")) :choices ["... a dragon!" {:run #(distract entities % "dragon")} "... a ghost!" {:run #(distract entities % "ghost")} "... a fairy godfather-eating plant!" {:run #(distract entities % "fairy godfather-eating plant")}] } "Nevermind." {:run #(actions/respond entities % :fairy-godfather "Don't worry, Tick.")}]}))) (defn describe-shovel [entities] (actions/do-dialogue entities :fairy-godfather "Grave-digging is just the thing for you, Tick." :fairy-godfather "Just think about it." :fairy-godfather "You'll have your own little shack at the cemetery..." :fairy-godfather "... where you can stay at not see another person for months on end ..." :fairy-godfather "well, another alive person anyways.")) (defn describe-broom [entities] (actions/do-dialogue entities :fairy-godfather "Janitoring is just the thing for you, Tick." :fairy-godfather "Just think about it." :fairy-godfather "Imagine the sweet smell of victory once you've mopped up some spilled milk." :fairy-godfather "Or the smell of soap in the bathroom, where you'll spend a lot of your time.")) (defn make [screen] (let [fairy-godfather-anim (utils/make-anim "dream/fairy-godfather.png" [63 77] 0.15 [0 1 2 3 2 1 0 1 4 3 2 1]) fairy-godfather-talk-anim (utils/make-anim "dream/fairy-godfather.png" [63 77] 0.15 [5 6 7 8 7 6])] (rooms/make :music :dream :interactions {:pit {:box [54 0 219 36] :script (actions/get-script entities (actions/walk-to entities :ego [154 41]) (actions/talk entities :ego "Wow! That's a long way down.")) :scripts {:shovel (actions/get-script entities (actions/walk-to entities :ego [154 41]) (actions/talk entities :ego "I guess I'm doomed to be a grave-digger.") (actions/play-animation entities :ego :sigh) (actions/play-animation entities :ego :reach-start :stop? false) (describe-shovel entities) (actions/play-animation entities :ego :reach-stop :stop? true) (actions/do-dialogue entities :ego "I can't bring myself to do it." :ego "It seems like misery!" :ego "Plus, how can I ever win the heart of my true love, Georgia McGorgeous?")) :broom (actions/get-script entities (actions/walk-to entities :ego [154 41]) (actions/talk entities :ego "I guess I'm doomed to be a janitor.") (actions/play-animation entities :ego :sigh) (actions/play-animation entities :ego :reach-start :stop? false) (describe-broom entities) (actions/play-animation entities :ego :reach-stop :stop? true) (actions/do-dialogue entities :ego "I can't bring myself to do it." :ego "It seems like misery!" :ego "Plus, how can I ever win the heart of my true love, Georgia McGorgeous?"))}}} :timers {:return [15.0 15.0 return-from-island]} :layers [(assoc (texture "dream/clouds1.png") :x -10 :y 0 :baseline -1 :parallax 0.2 :scale-x 1.1 :scale-y 1.1) (assoc (texture "dream/island.png") :x 180 :y 180 :baseline 0 :parallax 0.3 :scale-x 1.1 :scale-y 1.1) (assoc (texture "dream/cliff.png") :x 50 :y 133 :baseline 1 :parallax 0.6 :scale-x 1.2 :scale-y 1.2) (assoc (texture "dream/background.png") :x 0 :y 0 :baseline 2) (assoc (texture "dream/corner-l.png") :x -10 :y -10 :baseline 240 :parallax 2.0 ) (assoc (texture "dream/corner-r.png") :x (- 320 80) :y -20 :baseline 240 :parallax 3.2) (assoc (texture "dream/pedestals.png") :x 0 :y 0 :baseline 139)] :wind-sound {:sound (sound "dream/wind.ogg") :id nil} :entities {:magic (assoc (particle-effect "dream/magic") :x 160 :y 80 :baseline 240) :clouds (assoc (particle-effect "dream/cloudy2") :x 160 :y 120 :baseline 241) :case (assoc (texture "dream/case.png") :x 144 :y 122 :baseline 139 :script (actions/get-script entities (read-sword-plaque entities)) :scripts {:shovel (actions/get-script entities (if (get-in @entities [:room :entities :fairy-godfather :distracted?]) (do (actions/walk-to entities :ego [148 76] :face :right) (swing entities) (actions/play-animation entities :ego :reach-start :stop? false) (actions/remove-entity entities :sword) (actions/play-animation entities :ego :reach-stop) (actions/give entities :dream-sword) (actions/do-dialogue entities :ego "Yes! Now, before he gets back!") (actions/pause-camera entities) (actions/walk-straight-to entities :ego [173 51] :anim :jump :update-baseline? false :speed 2.0) (actions/walk-straight-to entities :ego [200 -80] :anim :stand :update-baseline? false :speed 3.0) (actions/remove-item entities :dream-sword) (actions/remove-item entities :broom) (actions/remove-item entities :shovel) (actions/transition-background entities :inside-castle [92 150] :time 8.0) (actions/resume-camera entities) (actions/walk-straight-to entities :ego [79 145] :stop? false) (actions/walk-to entities :ego [159 74]) (actions/do-dialogue entities :ego "Man! What a dream!" :ego "If I only really could be a knight." :ego "Then I'd be able to win Georgia McGorgeous' heart.") (actions/in-love entities)) (do (actions/walk-to entities :ego [148 76] :face :right) (actions/do-dialogue entities :fairy-godfather "What are you doing?" :ego "Erm... Nothing.")))) :broom (actions/get-script entities (if (get-in @entities [:room :entities :fairy-godfather :distracted?]) (actions/talk entities :ego "I don't think this is hard enough to break the case.") (do (actions/walk-to entities :ego [148 76] :face :right) (actions/do-dialogue entities :fairy-godfather "What are you doing?" :ego "Erm... Nothing."))))}) :sword (assoc (texture "dream/sword.png") :x 144 :y 122 :baseline 139) :explode (assoc (particle-effect "dream/explode") :x 150 :y 138 :baseline 240) :broom (assoc (texture "dream/broom.png") :x 286 :y 122 :path (catmull-rom-spline (map #(apply vector-2* %) [[286 122] [286 128]]) true) :update-fn (partial utils/update-path-location 0.30) :baseline 240 :script (actions/get-script entities (if ((get-in @entities [:state :plaques-read]) :broom) (do (actions/walk-to entities :ego [267 70] :face :right) (actions/play-animation entities :ego :sigh) (actions/play-animation entities :ego :reach) (actions/remove-entity entities :broom) (actions/give entities :broom)) (read-broom-plaque entities)))) :shovel (assoc (texture "dream/shovel.png") :x 33 :y 122 :path (catmull-rom-spline (map #(apply vector-2* %) [[22 122] [22 128]]) true) :update-fn (partial utils/update-path-location 0.33) :baseline 240 :script (actions/get-script entities (if ((get-in @entities [:state :plaques-read]) :shovel) (do (actions/walk-to entities :ego [61 72] :face :left) (actions/play-animation entities :ego :sigh) (actions/play-animation entities :ego :reach) (actions/remove-entity entities :shovel) (actions/give entities :shovel)) (read-shovel-plaque entities)))) :sign (assoc (texture "dream/sign.png") :x 229 :y 33 :baseline 207) :plaque-1 (assoc (texture "dream/plaque1.png") :x 39 :y 99 :baseline 139 :script (actions/get-script entities (read-shovel-plaque entities))) :plaque-2 (assoc (texture "dream/plaque2.png") :x 147 :y 104 :baseline 139 :script (actions/get-script entities (read-sword-plaque entities))) :plaque-3 (assoc (texture "dream/plaque3.png") :x 283 :y 98 :baseline 139 :script (actions/get-script entities (read-broom-plaque entities))) :outside-particles (common/make-outside-particles) :fairy-godfather (assoc (animation->texture screen fairy-godfather-anim) :x 200 :y 130 :baseline 240 :origin-x 31 :origin-y 0 :test true :anim fairy-godfather-anim :anim-start 0 :path (catmull-rom-spline (map #(apply vector-2* %) [[200 130] [200 134]]) true) :scaled true :left {:walk fairy-godfather-anim :talk fairy-godfather-talk-anim :stand fairy-godfather-anim} :right {:walk (utils/flip fairy-godfather-anim) :stand (utils/flip fairy-godfather-anim) :talk (utils/flip fairy-godfather-talk-anim)} :facing :left :update-fn (fn [s es e] (if (:path e) (utils/update-path-location 0.2 s es e) e)) :script (actions/get-script entities (if (get-in @entities [:room :entities :fairy-godfather :distracted?]) (actions/do-dialogue entities :ego "He wouldn't be able to hear me from there.") (talk-to-fairy entities))) :scripts {:shovel (actions/get-script entities (describe-shovel entities) (actions/play-animation entities :ego :sigh)) :broom (actions/get-script entities (describe-broom entities) (actions/play-animation entities :ego :sigh))})} :collision "dream/collision.png" :scale-fn (utils/scaler-fn-from-image "dream/scale.png" 0.1 1.3) :stop-fn (fn [_ entities] (when-let [wind-sound-id (get-in entities [:room :wind-sound :id])] (sound! (get-in entities [:room :wind-sound :sound]) :stop wind-sound-id)) entities) :apply-state (fn [_ entities] (utils/fast-forward-particle (get-in entities [:room :entities :outside-particles])) (as-> entities entities (if (get-in entities [:state :seen-intro?]) (set-opacity entities 1.0 1.0) (set-opacity entities 0.0 0.0)) (if (actions/has-item? entities :broom) (update-in entities [:room :entities] dissoc :broom) entities) (if (actions/has-item? entities :shovel) (update-in entities [:room :entities] dissoc :shovel) entities) (assoc-in entities [:room :wind-sound :id] (sound! (get-in entities [:room :wind-sound :sound]) :loop 0.2)))) :start-pos [140 55])))