(ns advent.screens.rooms.cat-tree (:require [advent.screens.rooms :as rooms] [advent.actions :as actions] [advent.saves :as saves] [advent.screens.items :as items] [advent.screens.rooms.common :as common] [advent.utils :as utils] [advent.steam :as steam] [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 get-down [entities & break] (actions/walk-straight-to entities :ego [151 50] :update-baseline? false :face :left) (if break (do (actions/play-animation entities :ladder :destroy-ladder :stop? false) (actions/remove-entity entities :blank) (actions/remove-entity entities :ladder) (actions/play-animation entities :ego :sigh)) (do (actions/play-animation entities :ego :reach) (actions/remove-entity entities :blank) (actions/remove-entity entities :ladder) (actions/give entities :ladder)))) (defn do-saved-grandma-dialogue [entities] (actions/walk-to entities :ego [165 45] :face :left) (actions/do-dialogue entities :grandma "Oh, it's my handsome hero again!" :grandma "Back for another kiss?" :ego "Umm, erm...") (actions/play-animation entities :ego :get-sick :stop? false) (actions/walk-straight-to entities :ego [205 10]) (actions/talk entities :ego "No way.")) (defn do-puke [entities] (particle-effect! (get-in @entities [:room :entities :puke]) :reset) (particle-effect! (get-in @entities [:room :entities :puke]) :start) (actions/play-animation entities :owl :puke)) (defn is-standing-on-ladder [entities] (and (not (actions/has-item? entities :kiss)) (not (actions/has-item? entities :ladder)) (actions/has-obtained? entities :ladder))) (defn do-grandma-dialogue-with-cat [entities] (actions/walk-to entities :ego [165 45] :face :left) (actions/do-dialogue entities :grandma "Oh, good, a strapping young lad!" :grandma "Are you here to help this damsel in distress?") (actions/play-animation entities :grandma :cry) (actions/present-choices entities {:choices ["Damsel in distress?" {:run #(actions/respond entities % :grandma "Yes! I'm a damsel, and I'm in distress!" :ego "Don't you have to be young to be a damsel?" :grandma "I'm 113 years young! I'm practically a baby!") :choices ["What's your distress?" {:run #(do (actions/respond entities % :grandma "It's my Smuffle Wuffles!" :grandma "We were on a pleasant walk through the woods." :grandma "Then we got in an argument, and so he ran up into that tree!") (actions/play-animation entities :grandma :cry) (actions/do-dialogue entities :ego "An argument? With a cat?" :grandma "Yes, of course! We were arguing about politics!")) :choices ["So you want me to get your cat down?" {:run #(actions/respond entities % :grandma "Yes! I need a courageous hero to rescue Smuffle Wuffles for me." :grandma "And this damsel in distress will reward you handsomely for your bravery.") :choices actions/previous-choices} "Cat's can't talk. How could he argue about politics?" {:run #(actions/respond entities % :grandma "Smuffle Wuffles is not your ordinary cat." :grandma "He's got an exceptionally high intellect for a cat." :ego "So other people can hear him?" :grandma "Well, not exactly." :grandma "No one else gives him the time of day, so he only speaks when we're alone." :ego "Why would such an intelligent cat be named Smuffle Wuffles?" :grandma "You'd have to take that up with his parents, Mr. and Mrs. Cuddly Wuddly.") :choices actions/previous-choices} "Something else." {:choices actions/something-else}]} "113 years old isn't young, lady." {:run #(actions/respond entities % :grandma "Oh sure it is!" :grandma "I do the same things every young damsel does." :grandma "Sit in my rocking chair, knit, take photos of the grandkids..." :ego "... Right.") :choices actions/previous-choices} "Something else." {:choices actions/something-else}]} "What are you doing way out here?" {:run #(do (actions/respond entities % :grandma "Me and my cat, Smuffle Wuffles were on a nice, leisurely stroll." :grandma "Then he ran up that tree!" :grandma "So I've been camped out here for the last two days.") (actions/play-animation entities :grandma :cry)) :choices actions/previous-choices} "Do you know how I can pull the Sword of Blergh, and become a knight?" {:run #(actions/respond entities % :grandma "Young man, I was here when that sword was put in the stone 100 years ago!" :grandma "Of course I know how it can be pulled!" :grandma "One must prove themselves worthy in wisdom, courage, and might." :grandma "How about proving your courage by helping me rescue Smuffle Wuffles?") :choices actions/previous-choices} "Later." {:run #(do (actions/respond entities % :grandma "Please come back soon and help me rescue Smuffle Wuffles!") (actions/play-animation entities :grandma :cry))}]})) (defn do-grandma-dialogue [entities] (if (actions/has-obtained? entities :kiss) (do-saved-grandma-dialogue entities) (do-grandma-dialogue-with-cat entities))) (defn remove-rock-if-necessary [entities] (if (actions/has-obtained? entities :note-1) entities (utils/remove-interaction entities :rock))) (defn make-night [entities] (-> entities (update-in [:room :entities] #(dissoc % :grandma)) (utils/remove-interaction :ladder-area-1) (utils/remove-interaction :ladder-area-2) (utils/remove-interaction :ladder-area-3) (utils/remove-interaction :grandma) (update-in [:room :entities] #(assoc % :owl (get-in entities [:room :owl]))) remove-rock-if-necessary)) (defn get-choices [entities] ["Can you help me in my quest?" {:run #(do (actions/respond entities % :owl "Of course I can help you in your quest." :owl "Quests are my specialty!" :owl "I know just what you need." :owl "But I'm also in some trouble of my own.") (actions/update-state entities (fn [s] (assoc s :knows-owl-trouble? true)))) :choice-fn (partial get-choices entities) } "Catch any mice tonight?" {:run #(do (actions/respond entities % :owl "Nothing at all." :owl "I keep trying to catch them but...") (do-puke entities) (actions/do-dialogue entities :owl "Excuse me.") (actions/update-state entities (fn [s] (assoc s :knows-owl-trouble? true)))) :choice-fn (partial get-choices entities)} (when (get-in @entities [:state :knows-owl-trouble?]) "Is something wrong?") {:run #(do (actions/respond entities % :owl "Yes, in fact there is." :owl "You see, we owls have very strong vision." :owl "I was born with a birth defect, and only one of my eyes is sharp enough for hunting." :owl "As for the other, alas, I need a monocle, or it's useless." :owl "And now I've dropped that very monocle somewhere in this valley!" :owl "What's worse, without it, I have severe nausea.") (do-puke entities) (actions/do-dialogue entities :owl "Excuse me." :owl "I don't suppose you could help me find it?" :ego "I'll let you know if I find it.") (actions/update-state entities (fn [s] (assoc s :wants-monocle? true))))} "Nevermind." {:run #(do (actions/respond entities % :owl "Goodnight to you."))}] ) (defn present-owl-choices [entities] (actions/present-choices entities {:choices (get-choices entities)})) (defn talk-to-owl [entities] (actions/walk-to entities :ego [141 54] :face :right) (cond (actions/has-obtained? entities :feather) (do (actions/do-dialogue entities :ego "Hello again." :owl "Oh! Hello again! Thank you again for all your help." :owl "My nausea has nearly worn off.") (do-puke entities)) (get-in @entities [:state :wants-monocle?]) (do (actions/do-dialogue entities :ego "Hello again." :owl "Have you found my glass monocle!?" :owl "I'll have no relief of this nausea until you do.") (do-puke entities)) (get-in @entities [:state :talked-to-owl?]) (do (actions/do-dialogue entities :ego "Hello again." :owl "Hello.") (present-owl-choices entities)) :else (do (actions/do-dialogue entities :ego "Hello there, little owl." :owl "Who you calling little?" :ego "Wow! You can talk?" :owl "Of course I can!" :ego "But none of the other animals so far in this game have talked!" :owl "Have you ever thought that maybe you're not that enjoyable to talk to?" :ego "I guess not." :owl "Naw, I'm just pulling your leg." :owl "I'm an owl, and owls are wise." :owl "Therefore we express our wisdom by way of speech.") (present-owl-choices entities))) (actions/update-state entities #(assoc % :talked-to-owl? true))) (defn give-monocle [entities] (actions/walk-to entities :ego [141 54] :face :right) (actions/talk entities :ego "Is this your monocle?") (do-puke entities) (actions/remove-item entities :monocle) (actions/do-dialogue entities :owl "It is!" :owl "Thank you!" :owl "And now, I will help you on your quest." :owl "This is for you.") (actions/give entities :feather) (actions/do-dialogue entities :ego "What's this for?" :owl "I'm sure you can find a use for it." :owl "And without pockets, I don't have much else I can give you." :ego "Thanks, I guess.")) (defn make-ladder-area [box] {:box box :script (actions/get-script entities (actions/walk-to entities :ego [144 58] ) (actions/talk entities :ego "Maybe I can climb it!") (actions/walk-straight-to entities :ego [144 72] :face :right) (actions/play-animation entities :ego :climb) (actions/walk-straight-to entities :ego [144 58]) (actions/talk entities :ego "Nope.")) :scripts {:ladder (actions/get-script entities (actions/talk entities :ego "I'll just set this up.") (actions/walk-to entities :ego [151 50] :face :left) (actions/play-animation entities :ego :reach) (actions/remove-item entities :ladder) (actions/add-entity entities :ladder (get-in @entities [:room :ladder])) (actions/walk-straight-to entities :ego [140 85] :face :right :update-baseline? false) (actions/add-entity entities :blank (get-in @entities [:room :blank])))}}) (defn make [screen] (let [cat-stand-sheet (texture! (utils/get-texture "cat-tree/cat-stand.png") :split 22 10) cat-stand (animation 0.15 (for [i (flatten [(repeat 10 0) 1 1 (repeat 10 0) 2 3 4 3 0 0 2 3 4 3 (repeat 10 0) 1 1 (repeat 10 0) 5 5 6 6 7 (repeat 10 [7 8]) 6 5 0])] (aget cat-stand-sheet 0 i))) cat-walk (animation 0.2 [(utils/get-texture "cat-tree/pounce.png")]) destroy-ladder (utils/make-anim "cat-tree/destroy-ladder.png" [29 38] 0.1 (range 18)) ladder-entity (assoc (utils/get-texture "inside-cafeteria/ladder.png") :x 130 :y 60 :baseline 162 :origin-x 0 :destroy-ladder destroy-ladder :ladder-break-sound (utils/load-sound "cat-tree/ladder-break.ogg") :anim-sound-frames {destroy-ladder {4 [:ladder-break-sound 0.6]}}) grandma-stand (utils/make-anim "cat-tree/grandma.png" [25 36] 0.2 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1]) grandma-squat-1 (utils/make-anim "cat-tree/grandma.png" [25 36] 0.2 [3 4 5 5 5 5 5]) grandma-squat-2 (utils/make-anim "cat-tree/grandma.png" [25 36] 0.2 [5 5 4 3]) grandma-talk (utils/make-anim "cat-tree/grandma.png" [25 36] 0.2 [0 2 0 2 0 2 0 2 0 2 0 1 0 2 0 0]) grandma-kiss (utils/make-anim "cat-tree/grandma.png" [25 36] 0.2 [0 8 9 10 9 10 9 10 9 8 0]) grandma-cry (utils/make-anim-seq "cat-tree/grandma-cry" [58 40] 0.15 (flatten [(range 20) 0 0 0 0 0 0 0 0 0])) owl-stand (utils/make-anim "cat-tree/owl.png" [21 30] 0.2 [0 0 0 0 0 0 0 2]) owl-talk (utils/make-anim "cat-tree/owl.png" [21 30] 0.2 [1 0 1 0 1 0 0 0 2 0]) owl-puke (utils/make-anim "cat-tree/owl.png" [21 30] 0.10 [0 0 2 2 3 2 2 3 3 2 3 3 3 4 5 6 7 4 4 3 3 2 2 2 2 2]) puke (particle-effect "particles/puke")] (rooms/make :music {:day :town-2 :night :night} :name "Tree" :sounds {:cat (utils/load-sound "cat-tree/cat.ogg") :kiss (utils/load-sound "cat-tree/kiss.ogg")} :ladder ladder-entity :blank (rooms/make-entity :blank {:object nil :x 0 :y 0 :width 320 :height 240 :baseline 240 :script (actions/get-script entities (when (get-in @entities [:room :entities :ladder]) (actions/talk entities :ego "I'll get down.") (get-down entities)))}) :interactions {:down-dir {:box [150 0 270 20] :script (actions/get-script entities (if (get-in @entities [:room :entities :ladder]) (do (actions/talk entities :ego "I'll get down.") (get-down entities))) (actions/walk-to entities :ego [200 10] :skip-type :end :stop? false) (actions/walk-straight-to entities :ego [223 -51]) (actions/transition-background entities :outside-house [137 204]) (actions/walk-to entities :ego [158 110] :skip-type :end)) :cursor :down} :ladder-area-1 (make-ladder-area [123 100 167 199]) :ladder-area-2 (make-ladder-area [87 151 227 212]) :ladder-area-3 (make-ladder-area [133 69 205 92]) :rock {:box [62 83 101 103] :script (actions/get-script entities (when (and (actions/has-obtained? entities :note-1) (not (actions/has-obtained? entities :walkie-talkies))) (actions/walk-to entities :ego [85 99]) (actions/play-animation entities :ego :squat) (actions/do-dialogue entities :ego "Hey! A little lever." :ego "I think this is Gandarf's secret stash of helpful stuff.") (actions/play-animation entities :ego :squat) (actions/give entities :alarm-clock) (actions/do-dialogue entities :ego "What is this?") (actions/play-animation entities :ego :squat) (actions/give entities :camera) (actions/do-dialogue entities :ego "These are all really strange devices.") (actions/play-animation entities :ego :squat) (actions/give entities :walkie-talkies) (actions/talk entities :ego "Tin cans connected with string?") (actions/do-dialogue entities :ego "I wonder what all of these magic devices do.")))} :grass {:box [26 105 60 160] :script (actions/get-script entities (if (not (actions/has-obtained? entities :grass)) (do (actions/walk-to entities :ego [60 100] :face :left) (actions/play-animation entities :ego :reach) (actions/give entities :grass) (actions/do-dialogue entities :ego "Grass." :ego "It's a high protein variety.")) (actions/talk entities :ego "I don't really need any more grass.")))} :grandma {:box [109 33 132 98] :script (actions/get-script entities (do-grandma-dialogue entities)) :scripts #(condp = % :kiss (actions/get-script entities (do-saved-grandma-dialogue entities)) (actions/get-script entities (actions/walk-to entities :ego [165 45] :face :left) (actions/do-dialogue entities :grandma "No thank you, handsome."))) }} :layers {:day [(assoc (utils/get-texture "cat-tree/background.png") :x 0 :y 0 :baseline 0) (assoc (utils/get-texture "cat-tree/tree-and-rock.png") :x 0 :y 0 :baseline 161) (assoc (utils/get-texture "cat-tree/brush-l.png") :x -5 :y -5 :parallax 1.3 :baseline 240) (assoc (utils/get-texture "cat-tree/tree-r.png") :x 270 :y 0 :scale-x 1.1 :scale-y 1.1 :parallax 1.5 :baseline 240)] :night [(assoc (utils/get-texture "cat-tree/background.png") :x 0 :y 0 :baseline 0) (assoc (utils/get-texture "cat-tree/tree-and-rock.png") :x 0 :y 0 :baseline 161) (assoc (utils/get-texture "cat-tree/brush-l.png") :x -5 :y -5 :parallax 1.3 :baseline 240) (assoc (utils/get-texture "cat-tree/tree-r.png") :x 270 :y 0 :scale-x 1.1 :scale-y 1.1 :parallax 1.5 :baseline 240)]} :entities { :outside-particles (common/make-outside-particles) :cat (actions/start-animation screen (assoc (animation->texture screen cat-stand) :x 184 :y 173 :baseline 1000 :walk cat-walk :stand cat-stand :script (actions/get-script entities (actions/talk entities :ego "Here kitty, kitty, kitty.") (actions/talk entities :ego "Kitty's so bored, he doesn't even notice me.")) :scripts {:cat-toy (actions/get-script entities (actions/play-animation entities :ego :cat-toy) (if (get-in @entities [:room :entities :ladder]) (do (actions/talk entities :ego "I think he's going for it!") (actions/play-animation entities :ego :cat-toy-first-half :stop? false) (actions/play-sound entities :cat 0.5) (actions/walk-straight-to entities :cat [138 40] :update-baseline? false :speed 3) (actions/play-animation entities :ego :cat-toy-last-half) (actions/play-animation entities :grandma :squat-1 :stop? false) (actions/remove-entity entities :cat) (actions/play-animation entities :grandma :squat-2) (actions/do-dialogue entities :grandma "Thank you for rescuing my furry friend, young man!") (get-down entities true) (actions/walk-straight-to entities :ego [165 45] :face :left) (actions/do-dialogue entities :ego "It's no big deal." :grandma "You won't go unrewarded!" :grandma "Come here, young man.") (actions/walk-straight-to entities :ego [133 35]) (actions/talk entities :grandma "For your impressive display of courage and bravery, I give you this. ") (actions/play-sound entities :kiss 0.7) (actions/play-animation entities :grandma :kiss) (actions/play-animation entities :ego :get-sick :stop? false) (actions/walk-straight-to entities :ego [165 45]) (actions/do-dialogue entities :ego "Ugh! Gross!" :ego "What's this?") (actions/give entities :kiss) (actions/do-dialogue entities :ego "A kiss for an inventory item?" :ego "Sounds like the game designer was running out of good ideas.") (steam/set-achievement "KITTY_KISS")) (actions/talk entities :ego "I can't get his attention from way down here."))) :stick (actions/get-script entities (if (get-in @entities [:room :entities :ladder]) (do (actions/play-animation entities :ego :poke) (actions/do-dialogue entities :ego "He's still too far for me to poke him." :ego "Maybe I can encourage him to come down on his own.")) (do (actions/walk-to entities :ego [210 58] :face :right) (actions/play-animation entities :ego :poke) (actions/talk entities :ego "I can't poke him from way down here.")))) :wool (actions/get-script entities (actions/talk entities :ego "I don't think the cat would notice the wool from all the way up there.")) :default (actions/get-script entities (actions/talk entities :ego "Kitty seems disinterested in it."))}) cat-stand) :grandma (let [gma (assoc (animation->texture screen grandma-stand) :x 130 :y 37 :baseline 200 :anim grandma-stand :anim-start 0 :talk grandma-talk :kiss grandma-kiss :cry grandma-cry :stand grandma-stand :squat-1 grandma-squat-1 :squat-2 grandma-squat-2 :cry-sound (utils/load-sound "cat-tree/cry.ogg") :anim-sound-frames {grandma-stand {15 [:blink 0.2 1.6]} grandma-talk {11 [:blink 0.2 1.6]} grandma-cry {1 [:cry-sound 0.5]}} :talk-color (color 1.0 0.4 0.9 1.0) :origin-x 13 :origin-y 0 :scale-x 1.45 :scale-y 1.45)] (assoc gma :anim-merges {(:cry gma) {:origin-x 35 :origin-y 4} :default {:origin-x 13 :origin-y 0}})) :puke (assoc puke :x 194 :y 188 :baseline 241)} :owl (rooms/make-entity :owl (assoc (animation->texture screen owl-stand) :x 187 :y 172 :baseline 241 :stand owl-stand :talk owl-talk :puke owl-puke :talk-color (color 0.5 0.5 1.0 1.0) :anim owl-stand :anim-start 0 :night-profile :none :puke-sound (utils/load-sound "cat-tree/owl-puke.ogg") :script (actions/get-script entities (talk-to-owl entities)) :anim-sound-frames {owl-puke {9 [:puke-sound (constantly 0.6)]}} :scripts #(condp = % :monocle (actions/get-script entities (give-monocle entities)) (actions/get-script entities (if (get-in @entities [:state :knows-owl-trouble?]) (do (actions/do-dialogue entities :ego "Is this your monocle?") (if (actions/has-obtained? entities :feather) (actions/talk entities :owl "You already gave me my monocle, silly boy!") (actions/talk entities :owl "No, it's round and made of glass.")) (do-puke entities)) (actions/talk entities :ego "Why would an owl want that?")))))) :collision "cat-tree/collision.png" :scale-fn (utils/scaler-fn-with-baseline 110 0.10 1.20) :apply-state (fn [_ entities] (utils/fast-forward-particle (get-in entities [:room :entities :outside-particles])) (as-> entities entities (if (actions/has-item? entities :kiss) (update-in entities [:room :entities] #(dissoc % :cat)) entities) (if (is-standing-on-ladder entities) (do (-> entities (update-in [:room :entities] assoc :blank (get-in entities [:room :blank]) :ladder (get-in entities [:room :ladder])) (update-in [:room :entities :ego ] assoc :x 140 :y 85 :facing :right :baseline (- 240 25)))) entities) (if (= :night (get-in entities [:state :time])) (make-night entities) (utils/remove-interaction entities :rock) ))) :start-pos [200 10])))