Files
gitea-docker/desktop/src-common/advent/screens/rooms/inside_antique.clj
2017-06-01 08:05:02 -07:00

495 lines
43 KiB
Clojure

(ns advent.screens.rooms.inside-antique
(:require [advent.screens.rooms :as rooms]
[advent.actions :as actions]
[advent.screens.items :as items]
[advent.utils :as utils]
[advent.tween :as tween]
[advent.zone :as zone]
[clojure.zip :as zip]
[play-clj.core :refer :all]
[play-clj.ui :refer :all]
[play-clj.utils :refer :all]
[play-clj.g2d :refer :all]))
(println "loading " *ns*)
(def boy-names
["Steve" "Bob" "Bud" "Clement" "Terrence" "Flapjack" "Ticklemonster" "Peter" "Greg" "Dave" "Stu" "Calsbad" "Fatso" "Tanner" "Klug"
"Griswold" "Leonardo" "Donatello" "Raphael" "Michelangelo" "Francis" "Ebeneezer" "Pierre" "Finn" "Slade" "Gilbert" "Graham"
"Ralphie" "Arthur" "Barney" "Harry" "Gus" "Mortimer" "Walt"])
(defn do-antique-dialogue [entities]
(if (< (get-in @entities [:room :entities :ego :x])
(get-in @entities [:room :entities :shopkeep :x]))
(actions/do-stop entities :ego :face :right)
(actions/do-stop entities :ego :face :left))
(actions/do-dialogue entities
:shopkeep "Oh, hello there."
:shopkeep "Can I help you?")
(let [son-choices ["How long has he been gone?"
{:run #(do (actions/respond entities %
:shopkeep "5..."
:shopkeep "... maybe 6 years."
:ego "6 YEARS?!"
:shopkeep "There must have been some delay."
:shopkeep "He should be back any minute."
:ego "... Are you sure he's coming back?"
:shopkeep "Of course he is!")
(actions/play-animation entities :shopkeep :sigh)
(actions/do-dialogue entities :shopkeep "Until then, I just have this grandfather clock to keep me company."))
:choices actions/previous-choices}
"So you're just waiting in the dark?"
{:run #(do (actions/respond entities %
:shopkeep "Somebody's got to guard all of this stuff."
:shopkeep "Plus, my son will be back any minute now with those candles.")
(actions/play-animation entities :shopkeep :sigh))
:choices actions/previous-choices}
"Something else."
{:choices actions/something-else}]]
(actions/present-choices entities
{:choices [(when-not (get-in @entities [:state :opened-blinds?])
"I can barely see anything!")
{:run #(actions/respond entities %
:shopkeep "Sorry about that, sonny."
:shopkeep "My son will be back any minute with some candles.")
:choices son-choices}
(when (get-in @entities [:state :opened-blinds?])
"I let some light in. Will you open up shop?")
{:run #(actions/respond entities %
:shopkeep "It's still too dark in here."
:shopkeep "Don't worry."
:shopkeep "My son will be back any minute with those candles.")
:choices son-choices}
"What do you have for sale here?"
{:run #(actions/respond entities %
:shopkeep "We're not open for business right now."
:shopkeep "Can't you see the lights are out?"
:shopkeep "We'll be open again when my son comes back with some candles.")
:choices [(when-not (get-in @entities [:state :opened-blinds?])
"Why don't you just open the curtains?")
{:run #(actions/respond entities %
:shopkeep "That window doesn't let much light in anyhow."
:shopkeep "Plus, my son should be back any minute now.")
:choices son-choices}
"Is there anything here you will sell?"
{:run #(actions/respond entities %
:shopkeep "No, not until my son returns.")
:choices son-choices}
(if (get-in @entities [:state :opened-blinds?])
"Since I got some light in here, will you open up shop?"
"If I get some light in here, will you open up shop?")
{:run #(actions/respond entities %
:shopkeep "No."
:shopkeep "I need my son to help around the shop anyways."
:shopkeep "And there's a lot to fix up before we're ready to open shop again.")
:choices son-choices}
"Something else."
{:choices actions/something-else}]}
(when (= 3 (get-in @entities [:state :mints-eaten]))
"Do you still need those lava mints?")
{:run #(actions/respond entities %
:shopkeep "Of course!"
:shopkeep "How am I going to keep all my customers happy?"
:ego "But you don't have any customers."
:shopkeep "No matter."
:shopkeep "Tell Gandarf I need some more."
:shopkeep "Pronto!")
:choices actions/previous-choices}
(when (not= 3 (get-in @entities [:state :mints-eaten]))
"Are those lava mints on the desk?")
{:run #(actions/respond entities %
:shopkeep "They're the finest lava mints in all of Remington."
:shopkeep "Hand-brewed and delivered by none other than Gandarf himself!"
:shopkeep "They're free for customers."
:shopkeep "We're not open for business, but I'll let you have one or two.")
:choices actions/previous-choices}
(when (and (get-in @entities [:state :wants-toy])
(not (get-in @entities [:state :allowed-to-keep-teddy?])))
"Listen, I really need that teddy bear you have.")
{:run #(actions/respond entities %
:shopkeep "Why?"
:shopkeep "It's my son's favorite toy!"
:shopkeep "Why should I give it to you?")
:choices ["Because it's the choicest toy I've ever seen!"
{:run #(actions/respond entities %
:shopkeep "I'm sorry, it's not for sale.")
:choices actions/something-else}
"Your son said I could have it."
{:run #(do (actions/respond entities %
:shopkeep "REALLY? You've met him?"
:ego "... erm. Yes!"
:shopkeep "If you really did meet him, you'll have to prove it."
:shopkeep "What is my son's name?"))
:choice-fn (fn make-choices []
(let [names (shuffle boy-names)]
(into
(vec (interleave
(take 3 (map #(str "Is it... " % "?")
names))
(repeat {:run #(do (actions/respond entities % :shopkeep "No. That's not it.")
(actions/play-animation entities :shopkeep :sigh)
(actions/do-dialogue entities :ego "Oh. I must be thinking of another long lost son."))
:choices #(-> %
zip/left
(zip/edit (fn [_] (str "Is it... " (rand-nth names) "?")))
zip/up
)})))
[(when ((get-in @entities [:state :clues]) :name)
"Herb.")
{:run #(do (actions/respond entities %
:shopkeep "Yes, that's it!"
:shopkeep "You must have really met my son!"
:shopkeep "Of course you can keep the teddy bear.")
(actions/update-state entities (fn [s] (assoc s :allowed-to-keep-teddy? true))))}
"It must have slipped my mind."
{:run #(do (actions/respond entities %
:shopkeep "I was afraid you might say that."))
:choices #(-> % zip/up zip/up zip/up)}])))}]}
"Nevermind." {:run (fn [m]
(if (= 3 (get-in @entities [:state :mints-eaten]))
(actions/respond entities m :shopkeep "Make sure to tell Gandarf to bring more lava mints.")
(actions/respond entities m :shopkeep "Feel free to look around."))
) }]})))
(defn return-portrait [ entities]
(actions/walk-to entities :ego [143 58] :face :left)
(actions/play-animation entities :ego :reach)
(actions/add-entity entities :portrait (get-in @entities [:room :portrait]))
(actions/remove-item entities :portrait)
(actions/remove-entity entities :return-portrait)
(actions/remove-entity entities :return-portrait-2))
(defn get-portrait [entities]
(actions/walk-to entities :ego [140 58] :face :left)
(actions/play-animation entities :ego :reach)
(actions/remove-entity entities :portrait)
(actions/give entities :portrait)
(actions/talk entities :ego "It's a portrait. There's something on the back but it's too dim to read.")
(actions/add-entity entities :return-portrait-2 (get-in @entities [:room :return-portrait-2]))
(actions/add-entity entities :return-portrait (get-in @entities [:room :return-portrait])))
(defn return-teddy [entities]
(actions/walk-to entities :ego [242 49] :face :right)
(actions/play-animation entities :ego :reach)
(actions/add-entity entities :teddy (get-in @entities [:room :teddy]))
(actions/remove-item entities :teddy)
(actions/remove-entity entities :return-teddy))
(defn has-to-return-teddy? [entities]
(and (actions/has-item? entities :teddy)
(not (get-in @entities [:state :allowed-to-keep-teddy?]))))
(defn choose-correct-blind-state [e]
(if (get-in e [:state :opened-blinds?])
(-> e
(assoc-in [:room :entities :closed-blinds :opacity] 0.0)
(assoc-in [:room :entities :open-blinds :opacity] 1.0)
(assoc-in [:room :entities :darken :opacity] 0.0)
(assoc-in [:room :entities :glow :opacity] 0.25))
(-> e
(assoc-in [:room :entities :closed-blinds :opacity] 1.0)
(assoc-in [:room :entities :open-blinds :opacity] 0.0)
(assoc-in [:room :entities :darken :opacity] 0.4)
(assoc-in [:room :entities :glow :opacity] 0.0))))
(defn make [screen atlas global-atlas]
(let [shopkeep-sheet (texture! (utils/atlas->texture atlas "shopkeep-talk") :split 18 21)
shopkeep-stand (animation 0.1 (for [i (flatten [(repeat 30 0) 1 (repeat 50 0) 1 0 1 0])]
(aget shopkeep-sheet 0 i)))
shopkeep-talk (animation 0.15 (for [i [0 2 0 2 0 3 1 0]]
(aget shopkeep-sheet 0 i)))
shopkeep-sigh (utils/make-anim atlas "antique-sigh" [24 21] 0.12 (flatten [ (range 9) 0 0 ]))
beard (utils/make-anim atlas "beard" [28 54] 0.5 [0 1 0 2])
teddy (assoc (utils/atlas->texture atlas "teddy")
:x 255
:y 95
:baseline 160
:label "Choicest teddy bear"
:cursor :hand
:script (actions/get-script entities
(actions/walk-to entities :ego [242 49] :face :right)
(actions/play-animation entities :ego :reach)
(actions/add-entity entities :return-teddy (get-in @entities [:room :return-teddy]))
(actions/give entities :teddy)
(actions/remove-entity entities :teddy)
(when (not (get-in @entities [:state :allowed-to-keep-teddy?]))
(actions/do-dialogue entities
:ego "Aww, a cute teddy bear!"
:shopkeep "Don't get any fast ideas."
:shopkeep "That teddy bear does not leave my store."
:shopkeep "My son would be stricken with grief to find it missing."))))]
(rooms/make :music :inside-antique
:name "Antique shop"
:sounds {:fire-1 (utils/load-sound "inside-antique/fire-1.ogg")
:fire-2 (utils/load-sound "inside-antique/fire-2.ogg")
:fire-3 (utils/load-sound "inside-antique/fire-3.ogg")
}
:return-portrait (rooms/make-entity :return-portrait {:box [103 70 206 116]
:label "Desk"
:baseline 0
:cursor :look
:script (actions/get-script entities (actions/talk entities :ego "It's the shopkeep's desk."))
:scripts {:portrait (actions/get-script entities
(return-portrait entities))
:teddy (actions/get-script entities
(return-teddy entities))}})
:return-portrait-2 (rooms/make-entity :return-portrait-2
{:box [103 116 131 131]
:label "Desk"
:baseline 0
:cursor :look
:script (actions/get-script entities (if (actions/has-item? entities :portrait)
(actions/talk entities :ego "The shopkeep's portrait used to sit there.")
(get-portrait entities)
))
:scripts {:portrait (actions/get-script entities
(return-portrait entities))
:teddy (actions/get-script entities
(return-teddy entities))}})
:return-teddy (rooms/make-entity :return-teddy {:box [227 90 301 105]
:baseline 0
:cursor :look
:label "Shelf"
:script (actions/get-script entities
(actions/talk entities :ego "It's a shelf."))
:scripts {:teddy (actions/get-script entities
(return-teddy entities))
:portrait (actions/get-script entities
(return-portrait entities))}})
:interactions
{:right {:box [250 0 320 75]
:cursor :right
:only-script (actions/get-script entities
(when (or (actions/has-item? entities :portrait)
(has-to-return-teddy? entities))
(actions/walk-to entities :ego [235 15])
(actions/talk entities :shopkeep "Excuse me, sonny. Please return my belongings before you leave.")
(when (actions/has-item? entities :portrait)
(return-portrait entities))
(when (has-to-return-teddy? entities)
(return-teddy entities)))
(actions/walk-to entities :ego [235 15] :stop? false :skip-type :end)
(actions/walk-straight-to entities :ego [320 -5])
(actions/transition-background entities :inside-castle [182 90])
(actions/walk-to entities :ego [187 75]))}
:window {:box [195 121 256 190]
:label "Window"
:cursor :hand
:script (actions/get-script entities
(actions/walk-to entities :ego [207 68] :face :right)
(actions/play-animation entities :ego :reach)
(actions/update-state entities (fn [s] (assoc s :opened-blinds? (not (:opened-blinds? s)))))
(actions/update-entities entities (fn [screen e]
(if (get-in e [:state :opened-blinds?])
(-> e
(assoc-in [:room :entities :closed-blinds :opacity] 0.0)
(assoc-in [:room :entities :open-blinds :opacity] 1.0)
(assoc-in [:tweens :fade-darken-out]
(tween/tween :fade-darken-out screen [:room :entities :darken :opacity] 0.4 0.0 0.75 :ease tween/ease-out-quadratic))
(assoc-in [:tweens :fade-glow-in]
(tween/tween :fade-glow-in screen [:room :entities :glow :opacity] 0.0 0.3 0.75 :ease tween/ease-out-quadratic)))
(-> e
(assoc-in [:room :entities :closed-blinds :opacity] 1.0)
(assoc-in [:room :entities :open-blinds :opacity] 0.0)
(assoc-in [:tweens :fade-darken-in]
(tween/tween :fade-darken-in screen [:room :entities :darken :opacity] 0.0 0.4 0.75 :ease tween/ease-out-quadratic))
(assoc-in [:tweens :fade-glow-out]
(tween/tween :fade-glow-out screen [:room :entities :glow :opacity] 0.3 0.0 0.75 :ease tween/ease-out-quadratic)))))
:use-screen? true))
:scripts {:portrait (actions/get-script entities
(if (get-in @entities [:state :opened-blinds?])
(do (actions/walk-to entities :ego [142 49] :face :left)
(actions/play-animation entities :ego :hold-up-to-window)
(actions/talk entities :ego "The portrait says \"Herb\" on the back.")
(actions/update-state entities (fn [state] (update-in state [:clues] #(conj % :name)) )))
(do (actions/walk-to entities :ego [142 49] :face :left)
(actions/play-animation entities :ego :hold-up-to-window)
(actions/talk entities :ego "It's just too dim."))))}}
:grandfather-clock {:box [55 70 103 185]
:label "Grandfather clock"
:cursor :look
:script (actions/get-script entities
(actions/do-dialogue entities :ego "Cool grandfather clock!"
:shopkeep "It's quite the exquisite piece, isn't it?"))}
:shelf {:box [0 60 52 199]
:cursor :look
:label "Trinkets"
:script (actions/get-script entities
(actions/walk-to entities :ego [48 58])
(actions/talk entities :ego "All of these trinkets seem too bulky to fit in my pack."))}
:flowers {:box [178 115 188 143]
:label "Flowers"
:cursor :look
:script (actions/get-script entities
(actions/talk entities :ego "I've never been a fan of flowers."))}
:lian {:box [264 103 317 198]
:cursor :look
:label "Tapestry"
:script (actions/get-script entities
(actions/walk-to entities :ego [220 35] :face :right)
(actions/do-dialogue entities
:ego "It's a tapestry of Rupert the Lion!"
:ego "He's the town of Remington's mascot."))}
}
:layers [(assoc (utils/atlas->texture atlas "background") :x 0 :y 0 :baseline 0)
(assoc (utils/atlas->texture atlas "desk") :x 0 :y 0 :baseline 113)
(assoc (utils/atlas->texture atlas "fg") :x 0 :y 0 :baseline 320 :parallax 1.5)
]
:entities {:shopkeep (actions/start-animation screen (assoc (animation->texture screen shopkeep-stand) :x 148 :y 122 :baseline 112
:label "Shopkeeper"
:cursor :talk
:stand shopkeep-stand
:scale-x 1.6
:scale-y 1.6
:talk-color (color 0.2 1.0 0.2 1.0)
:talk shopkeep-talk
:sigh shopkeep-sigh
:sigh-sound (utils/load-sound "inside-antique/shopkeep-sigh.ogg")
:anim-merges {shopkeep-sigh {:origin-x 9}
:default {:origin-x 9}}
:anim-sound-frames {shopkeep-stand {31 [:blink 0.5 1.5]
81 [:blink 0.5 1.5]
83 [:blink 0.5 1.5]}
shopkeep-talk {6 [:blink 0.5 1.5]}
shopkeep-sigh {1 [:sigh-sound 1.0]}}
:script (actions/get-script entities (do-antique-dialogue entities))
:scripts #(condp = %
:teddy (actions/get-script entities
(if (get-in @entities [:state :allowed-to-keep-teddy?])
(actions/talk entities :shopkeep "Please give the teddy bear to Herb when you see him.")
(actions/talk entities :shopkeep "That belonged to my long lost son.")))
:portrait (actions/get-script entities
(if (get-in @entities [:state :allowed-to-keep-teddy?])
(actions/talk entities :shopkeep "That's a portrait of my little Herb. "
:shopkeep "Please put it back before you leave." )
(actions/do-dialogue entities
:shopkeep "Put that back!"
:shopkeep "It's been six years since I last saw my son."
:shopkeep "I won't let you keep my only portrait of him.")))
(actions/get-script entities
(actions/talk entities :shopkeep "No thanks, sonny."))))
:stand)
:glow (assoc (utils/atlas->texture atlas "glow") :x 0 :y 0 :baseline 240 :additive? true :opacity 0.3)
:closed-blinds (assoc (utils/atlas->texture atlas "closed-blinds") :x 0 :y 0 :baseline 1 :opacity 1.0)
:open-blinds (assoc (utils/atlas->texture atlas "open-blinds") :x 0 :y 0 :baseline 1 :opacity 0.0)
:darken (assoc (utils/atlas->texture atlas "darken") :x 0 :y 0 :baseline 321 :opacity 0.4 )
:beard (assoc (animation->texture screen beard)
:anim beard
:anim-start 0
:x 69
:y 86
:baseline 120)
:smoke-particle (doto (assoc (particle-effect "particles/smoke-particle") :x 162 :y 104
:baseline 240)
(particle-effect! :set-position 162 103))
:fire-particle (doto (assoc (particle-effect "particles/fire-particle") :x 162 :y 104
:baseline 240)
(particle-effect! :set-position 162 104))
:bowl (assoc (utils/atlas->texture atlas "bowl")
:images [(utils/atlas->texture atlas "bowl-0")
(utils/atlas->texture atlas "bowl-1")
(utils/atlas->texture atlas "bowl-2")
(utils/atlas->texture atlas "bowl-3")]
:x 165
:y 110
:baseline 125
:label "Mint bowl"
:cursor :hand
:script (actions/get-script entities
(if (= 3 (get-in @entities [:state :mints-eaten]))
(do (actions/walk-to entities :ego [159 58] :face :right)
#_(actions/update-state entities (fn [s] (assoc s :mints-eaten 0)))
(actions/do-dialogue entities
:ego "She's all out."
:shopkeep "That's right, I'm all out."
:shopkeep "Go tell Gandarf that I need some more brewed up."
:shopkeep "Pronto!"))
(do (actions/walk-to entities :ego [159 58] :face :right)
(if (= 0 (get-in @entities [:state :mints-eaten]))
(actions/talk entities :ego "I'll just try one of these mints.")
(actions/talk entities :ego "I'll just try another one of these mints."))
(actions/play-animation entities :ego :reach)
(actions/update-state entities (fn [s] (assoc s :mints-eaten (inc (s :mints-eaten)))))
(actions/update-entities entities
(fn [entities]
(update-in entities
[:room :entities :bowl]
(fn [b]
(merge b
(get-in b [:images (- 3
(get-in entities [:state :mints-eaten] 0))])
)))))
(actions/play-sound entities (keyword (str "fire-" (get-in @entities [:state :mints-eaten]))) 0.8)
(cond
(= 2 (get-in @entities [:state :mints-eaten]))
(do (particle-effect! (get-in @entities [:room :entities :smoke-particle]) :reset)
(particle-effect! (get-in @entities [:room :entities :smoke-particle]) :start))
(= 3 (get-in @entities [:state :mints-eaten]))
(do (particle-effect! (get-in @entities [:room :entities :fire-particle]) :reset)
(particle-effect! (get-in @entities [:room :entities :fire-particle]) :start)))
(actions/play-animation entities :ego [:fire (get-in @entities [:state :mints-eaten])])
(actions/talk entities :ego "WOWZA! Those are hot.")
(when (= 3 (get-in @entities [:state :mints-eaten]))
(actions/do-dialogue entities :shopkeep "Oh drat! You ate the last mint."
:shopkeep "It seems like I'm always running out."
:shopkeep "Now be a good lad and tell Gandarf that I need some more brewed up."
:shopkeep "Pronto!"))))))
:teddy teddy}
:portrait (rooms/make-entity :portrait
(assoc (utils/atlas->texture atlas "portrait")
:x 112
:y 114
:baseline 120
:cursor :hand
:label "Portrait"
:script (actions/get-script entities
(get-portrait entities))))
:teddy (rooms/make-entity :teddy teddy)
:collision "inside-antique/collision.png"
:apply-state (fn [_ entities]
(let [mints-eaten (get-in entities [:state :mints-eaten] 0)]
(as-> entities entities
(if (or (actions/has-item? entities :teddy)
(actions/has-obtained? entities :balloon))
(update-in entities [:room :entities] #(dissoc % :teddy))
entities)
(if (actions/has-item? entities :portrait)
(update-in entities [:room :entities] assoc
:return-portrait (get-in entities [:room :return-portrait])
:return-portrait-2 (get-in entities [:room :return-portrait-2]))
entities)
(if (actions/has-item? entities :teddy)
(update-in entities [:room :entities] assoc
:return-teddy (get-in entities [:room :return-teddy]))
entities)
(update-in entities
[:room :entities :bowl]
(fn [b]
(merge b (get-in b [:images (- 3 mints-eaten)]))))
(if (actions/has-item? entities :portrait )
entities
(assoc-in entities [:room :entities :portrait] (get-in entities [:room :portrait])))
(choose-correct-blind-state entities)
)))
:scale-fn (utils/scaler-fn-with-baseline 110 0.10 1.75)
:start-pos [222 3])))