Files
gitea-docker/desktop/src-common/advent/screens/rooms/inside_castle.clj
2015-02-23 17:25:21 -08:00

407 lines
34 KiB
Clojure

(ns advent.screens.rooms.inside-castle
(:require [advent.screens.rooms :as rooms]
[advent.actions :as actions]
[advent.screens.items :as items]
[advent.utils :as utils]
[advent.tween :as tween]
[clojure.zip :as zip]
[clojure.set :as set]
[clojure.string :as str]
[play-clj.core :refer :all]
[play-clj.ui :refer :all]
[play-clj.utils :refer :all]
[play-clj.g2d :refer :all]))
(defn bloodclot-appear [entities]
(actions/run-action entities
(begin [this screen entities]
(particle-effect! (get-in entities [:room :entities :appear]) :reset)
(particle-effect! (get-in entities [:room :entities :appear]) :start)
(sound! (sound "inside-house/disappear.ogg") :play)
(-> entities
(assoc-in [:tweens :bloodclot-head-appear]
(tween/tween :bloodclot-head-appear screen [:room :entities :bloodclot-head :opacity] 0.0 1.0 1.0 :ease tween/ease-in-quadratic))
(assoc-in [:tweens :bloodclot-appear]
(tween/tween :bloodclot-appear screen [:room :entities :bloodclot :opacity] 0.0 1.0 1.0 :ease tween/ease-in-quadratic))))
(continue [this screen entities]
entities)
(done? [this screen entities]
(= 1.0 (get-in entities [:room :entities :bloodclot :opacity])))
(terminate [this screen entities]
entities)
(can-skip? [this screen entities]
false)))
(defn nice-trophy-dialogue [entities]
{:run #(actions/respond entities %
:game-player "Thanks. I'm the reigning champ in the annual Town of Remington Junior Smarty Pants Derby."
:game-player "I earned it with my wisdom and sharp intellect."
:game-player "Oh, I'm guessing you want it? Maybe to prove your wisdom and pull the Sword of Blergh?"
:game-player "Perhaps to become a knight and impress a young lady?")
:choices ["Yes."
{:run #(actions/respond entities %
:game-player "My trophy is hard-won. You won't pry it from my fingers easily."
:game-player "But I'm preparing for next year's Junior Smarty Pants Derby, and I need some help."
:game-player "If you can help me, it will secure my success for next year, and so you can have this trophy."
:game-player "Deal?")
:choices ["What is the Junior Smarty Pants Derby?"
{:run #(actions/respond entities %
:game-player "The annual Town of Remington Junior Smarty Pants Derby is a contest of wits."
:game-player "It's sort of like a game of riddles, mixed with a scavenger hunt."
:game-player "You must find the answer to the riddle to win."
:game-player "There are a few puzzles that even I, Brian O'Brainy, stumped."
:game-player "If you can help me, I'll let you have my trophy.")
:choices actions/previous-choices}
"Deal."
{:run #(do (actions/update-state entities (fn [state] (assoc state :current-riddle :wool)))
(actions/respond entities %
:game-player "Very well. I am studying for next year's derby, and there are a few puzzles that have me stumped."
:game-player "If you can bring me the answers to three riddles, I'll give you my trophy."
:game-player "Here's the first riddle:"
:game-player "'White as snow, but not as cold,\nKeeps you warm, or so I'm told.'"
:ego "Okay. So I'll be back soon."))}
"No thanks."
{:run #(actions/respond entities % :game-player "Fine by me.")}]}
"No."
{:run #(actions/respond entities % :game-player "Fine by me.")}]})
(defn walk-to-player [entities]
(actions/walk-to entities :ego [210 73] :face :right))
(defn do-game-player-dialogue [entities]
(walk-to-player entities)
(actions/do-dialogue entities :ego "You there!" :game-player "... Yes?")
(actions/present-choices entities
{:choices ["Do you know anything about the sword in the stone up there?"
{:run #(actions/respond entities %
:game-player "It's the Sword of Blergh. There's a prophecy that says that whoever pulls it will be a great knight!"
:game-player "'The Sword of Blergh, with magic sting,\nshall yield to no earthly king.'"
:game-player "'Worthy in wisdom, courage, and might,\nonly then with sword he'll fight.'"
:game-player "I've often dreamed of pulling the sword myself.")
:choices ["Why don't you?"
{:run #(do (actions/respond entities %
:game-player "I, of course, have the wisdom to do such a deed."
:game-player "But I'm not much of a hero."
:game-player "I don't have the might or courage required to pull the sword and fulfill the prophecy. "
:game-player "The knights of Remington have muscles the size of tree trunks."
:game-player "But me...")
(sound! (sound "inside-castle/flex.ogg") :play)
(actions/play-animation entities :game-player :flex)
(actions/do-dialogue entities :game-player "I'd never be able to prove my strength."))
:choices actions/previous-choices}
"Something else."
{:choices actions/something-else}]}
(when (= nil (get-in @entities [:state :current-riddle]))
"Nice trophy.")
(nice-trophy-dialogue entities)
(when (= :wool (get-in @entities [:state :current-riddle]))
"What was that riddle again?")
{:run #(actions/respond entities %
:game-player "'White as snow, but not as cold,\nKeeps you warm, or so I'm told.'")
:choices actions/previous-choices}
(when (= :balloon (get-in @entities [:state :current-riddle]))
"What was that riddle again?")
{:run #(actions/respond entities %
:game-player "'Filled with air, light as a feather,\nIf you want to keep it, best have a tether.'")
:choices actions/previous-choices}
(when (= :frog-legs (get-in @entities [:state :current-riddle]))
"What was that riddle again?")
{:run #(actions/respond entities %
:game-player "'Hippity-hop, I'd jump so high,\nWithout these springs, can't harm a fly.'")
:choices actions/previous-choices}
"Nevermind."
{:run #(actions/respond entities % :game-player "See you around.")}]}))
(defn walk-to-blergh [entities]
(actions/walk-to entities :ego [85 145] :face :right)
(actions/transition-background entities :space [0 65] :transition-music? false)
(actions/walk-straight-to entities :ego [160 45] :face :right)
(bloodclot-appear entities)
(actions/transition-music entities nil :duration 0.15))
(defn pull-sword [entities]
(actions/play-animation entities :ego :reach)
(actions/transition-music entities :pull-sword)
(actions/add-entity entities :blackout (get-in @entities [:room :blackout]))
(actions/add-entity entities :pull-sword (get-in @entities [:room :pull-sword]))
(actions/play-animation entities :pull-sword :pull-sword)
(actions/give entities :sword)
(actions/remove-entity entities :sword)
(actions/remove-entity entities :pull-sword)
(actions/remove-entity entities :blackout)
(actions/transition-music entities nil)
(actions/do-dialogue entities :ego "That was weird."
:ego "I have to go show my friends!")
(walk-to-blergh entities)
(actions/add-entity entities :blergh (get-in @entities [:room :blergh]))
(actions/talk entities :ego "Who are you?!" :anim :scared-talk)
(actions/begin-animation entities :ego :scared)
(actions/do-dialogue entities
:bloodclot-head "I am Bloodclot, the Scottish goblin!"
:bloodclot-head "I've spent last 100 years training for this day."
:bloodclot-head "The day when I must best the worthiest of knights in battle."
:bloodclot-head "But I had never expected my foe to be so..."
:bloodclot-head "... appetizing."
:bloodclot-head "You're no hero. You're just a morsel."
:bloodclot-head "Come here, and I promise I will spare you much pain.")
(actions/talk entities :ego "Wait a second. I'm just a kid." :anim :scared-talk)
(actions/walk-straight-to entities :ego [115 45] :override-dir :right)
(actions/talk entities :ego "I'm just trying to impress Georgia McGorgeous." :anim :scared-talk)
(actions/walk-straight-to entities :ego [75 45] :override-dir :right)
(actions/talk entities :ego "I just... accidentally pulled the sword!":anim :scared-talk)
(actions/walk-straight-to entities :ego [35 45] :override-dir :right)
(actions/talk entities :ego "I wouldn't taste very good anyhow!" :anim :scared-talk)
(actions/begin-animation entities :ego :scared)
(actions/do-dialogue entities
:bloodclot-head "'Fight he must for one more test,\nHe will die if not the best.'"
:bloodclot-head "Ring any bells?"
:bloodclot-head "Face it kiddo, you're no match for me, or my appetite."
:bloodclot-head "And Georgia McGorgeous would never go for such a cowardly knight anyhow."
:bloodclot-head "Let the feast begin."))
(defn try-to-pull-sword [entities missing-items obtained-items]
(let [item->proof {:trophy "wisdom" :medal "strength" :kiss "courage"}]
(actions/play-animation entities :ego :reach)
(actions/do-dialogue entities
:ego "I can't pull it out!"
:ego "It looks like there's an inscription here.")
(actions/play-animation entities :ego :squat)
(actions/do-dialogue entities
:ego "'The Sword of Blergh with magic sting,\nShall yield to no earthly king.'"
:ego "Worthy in wisdom, courage, and might,\nOnly then with sword he'll fight. ")
(if (= 3 (count missing-items))
(actions/do-dialogue entities
:ego "I have to prove myself worthy in wisdom, courage, and might!"
:ego "Then I can become a knight and impress Georgia McGorgeous!")
(actions/do-dialogue entities :ego (str "I've proven myself in "
(str/join " and " (map item->proof obtained-items))
", but still have to prove myself in "
(str/join " and " (map item->proof missing-items))
".")))))
(defn add-monocle-if-necessary [entities]
(if (and (not (actions/has-obtained? entities :monocle))
(get-in entities [:state :talked-to-owl?]))
(update-in entities [:room :entities] #(assoc % :monocle (get-in entities [:room :monocle])))
entities))
(defn make-night [entities]
(-> entities
(update-in [:room :entities] #(dissoc % :game-player))
add-monocle-if-necessary))
(defn make [screen]
(let [game-player-talk-sheet (texture! (texture "inside-castle/game-player-talk.png") :split 40 44)
game-player-talk (animation 0.15 (for [i [0 2 0 2 0 2 0 3 0 2 0 1 0 0 0 0 2 0 2 0 3 0 1 0 1 0 0 1 0 2 0 3 0]]
(aget game-player-talk-sheet 0 i)))
game-player-stand (animation 0.15 (for [i [0 0 0 0 0 0 0 0 0 0 0 1]]
(aget game-player-talk-sheet 0 i)))
game-player-flex (animation 0.075 (for [i [0 0 4 4 5 5 5 5 5 5 5 6 7 8 7 9 7 8 7 9 7 8 7 9 7 8 7 9 7 8 7 9 7 8 7 9 7 8 7 9 7 8 7 9 7 8 7 9 7 8 7 9 7 8 7 6 5 5 5 5 5 5 5 5 5 5 4 4 0 0 0 0]]
(aget game-player-talk-sheet 0 i)))
trophy (utils/make-anim "inside-castle/trophy.png" [16 16] 0.1 (flatten [(repeat 50 0) 1 2 3 3 3 3 2 1]))
pull-sword-anim (utils/make-anim "inside-castle/pull-sword.png" [95 190] 0.10 (flatten [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 3 2 3 2 3 3 2 3 2 2 3 3 2 3 2 3 2 3 2 3 2 3 2 2 3 3 3 2 3 2 3 3 2 3 2 3 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ]))
monocle (utils/make-anim "inside-castle/monocle.png" [7 7] 0.05 (flatten [(repeat 70 0) 1 2 3 3 3 2 1]))]
(rooms/make :music {:day :town-1 :night :night :sunrise :night}
:interactions
{:right-door {:box [286 140 306 160]
:cursor :right
:script (actions/get-script entities
(actions/walk-to entities :ego [284 145])
(actions/transition-background entities :outside-castle [82 180])
(actions/walk-to entities :ego [129 148]))}
:up-door {:box [50 150 70 170]
:script (actions/get-script entities
(actions/walk-to entities :ego [65 155])
(if (= :night (get-in @entities [:state :time]))
(actions/talk entities :ego "It's locked.")
(do (actions/transition-background entities :inside-cafeteria [319 55])
(actions/walk-to entities :ego [300 55]))))
:cursor :up}
:antique-door {:box [154 90 189 150]
:cursor :up
:script (actions/get-script entities
(actions/walk-to entities :ego [182 90] :face :left)
(sound! (sound "door.ogg") :play)
(actions/play-animation entities :ego :reach)
(if (= :night (get-in @entities [:state :time]))
(actions/talk entities :ego "It's locked.")
(do (actions/transition-background entities :inside-antique [325 -30])
(actions/walk-straight-to entities :ego [235 15] :face :left)
(if (get-in @entities [:state :allowed-to-keep-teddy?])
(actions/do-dialogue entities :shopkeep "Hello there, sonny."
:shopkeep "Have you seen Herb lately?"
:ego "Erm... No, not recently."
:shopkeep "Oh. Send him my love if you do see him.")
(actions/talk entities :shopkeep "Hello there, sonny.")))))}
:sword {:box [0 130 39 165]
:script (actions/get-script entities
(if (actions/has-item? entities :sword)
(actions/talk entities :ego "I already have the Sword of Blergh!")
(do (actions/talk entities :ego "That's the coolest sword I've ever seen!!")
(actions/walk-to entities :ego [37 134] :face :left)
(actions/talk entities :ego "If I pull it out I can become a great knight!")
(let [missing-items (set/difference #{:trophy :medal :kiss} (get-in @entities [:state :obtained-items]))
obtained-items (set/intersection #{:trophy :medal :kiss} (get-in @entities [:state :obtained-items]))]
(if (= #{} missing-items)
(pull-sword entities)
(try-to-pull-sword entities missing-items obtained-items))))))}
:sign {:box [125 140 165 155]
:script (actions/get-script entities
(actions/talk entities :ego "Ye Ol' Antique Shoppe."))}
:background-houses {:box [84 145 126 180]
:script (actions/get-script entities
(actions/walk-to entities :ego [79 145] :face :right)
(actions/transition-background entities :outside-jail [159 -20])
(actions/walk-straight-to entities :ego [159 20]))
:cursor :right}
:mid-house {:box [217 125 250 180]
:script (actions/get-script entities
(actions/do-dialogue entities
:ego "That's Billy Billigan's house."
:ego "He's probably still angry from when I put his dog in the dryer."))}
:frankie-house {:box [251 140 266 160]
:script (actions/get-script entities
(actions/do-dialogue entities
:ego "That's Frankie Rockfist's house."
:ego "The last time I saw him, he socked me one, right in the kisser."))}
:georgia-house {:box [271 150 286 170]
:script (actions/get-script entities
(actions/do-dialogue entities
:ego "That's Georgia McGorgeous' house."
:ego "One day, when I'm a knight, I'll ask her to be my girlfriend."))}}
:layers {:day [(assoc (texture "inside-castle/background.png") :x 0 :y 0 :baseline 0)
(assoc (texture "inside-castle/pedestal-overlay.png") :x 0 :y 0 :baseline 135)]
:night [(assoc (texture "inside-castle/background-dark.png") :x 0 :y 0 :baseline 0)
(assoc (texture "inside-castle/pedestal-overlay-dark.png") :x 0 :y 0 :baseline 135)]
:sunrise [(assoc (texture "inside-castle/background-sunrise.png") :x 0 :y 0 :baseline 0)]}
:blackout (assoc (texture "black.png")
:x 0 :y 0
:width 320
:height 240 :opacity 0.8
:baseline 239)
:pull-sword (assoc (animation->texture screen pull-sword-anim)
:x 10
:y 40
:baseline 240
:pull-sword pull-sword-anim)
:entities {:bird-1 (utils/make-bird screen (as-> [[185 235]
[220 225] [210 230] [250 235]] p
(concat p (reverse p))))
:bird-2 (utils/make-bird screen (as-> [[220 225] [195 235] [210 230] [250 225]] p
(concat p (reverse p))))
:sword (assoc (texture "inside-castle/sword.png")
:x 16
:y 145
:baseline 95)
:trophy (assoc (animation->texture screen trophy)
:x 253 :y 69 :baseline 191
:anim trophy
:anim-start 0
:script (actions/get-script entities
(walk-to-player entities)
(if (= nil (get-in @entities [:state :current-riddle]))
(let [{:keys [run choices]} (nice-trophy-dialogue entities)]
(run "Nice trophy.")
(actions/present-choices entities {:choices choices}))
(actions/do-dialogue entities :ego "Can't you give me your trophy of wisdom?"
:game-player "If you want my trophy, you'll have to help me with my riddles."))))
:game-player (assoc (texture "inside-castle/gameplayer.png") :x 266 :y 49 :baseline 191
`:talk-color (color 1.0 0.3 0.2 1.0)
:script (actions/get-script entities (do-game-player-dialogue entities))
:scripts #(condp = %
:wool (actions/get-script entities
(walk-to-player entities)
(if (= :wool (get-in @entities [:state :current-riddle]))
(do (actions/update-state entities (fn [s] (assoc s :current-riddle :balloon)))
(actions/remove-item entities :wool)
(actions/do-dialogue entities
:game-player "That's right! Now for your second riddle:"
:game-player "'Filled with air, light as a feather,\nIf you want to keep it, best have a tether.'"
:ego "Okay. Be back soon."))
(actions/do-dialogue entities :ego "What about this?" :game-player "No, that's not the solution. Keep looking.")))
:balloon (actions/get-script entities
(walk-to-player entities)
(if (= :balloon (get-in @entities [:state :current-riddle]))
(do (actions/update-state entities (fn [s] (assoc s :current-riddle :frog-legs)))
(actions/remove-item entities :balloon)
(actions/do-dialogue entities
:game-player "That's right! Now for your third riddle:"
:game-player "'Hippity-hop, I'd jump so high,\nWithout these springs, can't harm a fly.'"
:ego "Okay. Be back soon."))
(actions/do-dialogue entities :ego "What about this?" :game-player "No, that's not the solution. Keep looking.")))
:frog-legs (actions/get-script entities
(walk-to-player entities)
(if (= :frog-legs (get-in @entities [:state :current-riddle]))
(do (actions/update-state entities (fn [s] (assoc s :current-riddle :done)))
(actions/remove-item entities :frog-legs)
(actions/do-dialogue entities
:game-player "Wow! That's right!"
:game-player "You, sir, have proven yourself worthy of my trophy."
:game-player "Even I, Brian O'Brainy, am impressed with your wisdom."
:game-player "Take it, and go in wisdom.")
(actions/give entities :trophy)
(actions/remove-entity entities :trophy)
(actions/talk entities :ego "Thanks!"))
(actions/do-dialogue entities :ego "What about this?" :game-player "No, that's not the solution. Keep looking.")))
:trophy (actions/get-script entities
(walk-to-player entities)
(actions/talk entities :game-player "You can keep the trophy. You've earned it."))
(actions/get-script entities
(walk-to-player entities)
(condp = (get-in @entities [:state :current-riddle])
:done (actions/do-dialogue entities :game-player "I've gotten all the help I need with riddles today.")
nil (actions/do-dialogue entities :game-player "Why are you offering me this?")
(actions/do-dialogue entities :ego "What about this?" :game-player "No, that's not the solution. Keep looking."))))
:anim game-player-stand
:anim-start 0
:stand game-player-stand
:anim-sound-frames {game-player-stand {11 [:blink 0.3] }}
:flex game-player-flex
:talk game-player-talk)}
:monocle (rooms/make-entity :monocle (assoc (animation->texture screen monocle)
:x 209 :y 160 :baseline 240
:anim monocle
:anim-start 0
:script (actions/get-script entities
(actions/walk-to entities :ego [213 87] :face :left)
(actions/talk entities :ego "There's something up there on the roof!"))
:scripts {:spear (actions/get-script entities
(actions/walk-to entities :ego [213 87] :face :left)
(actions/talk entities :ego "Maybe I can reach it with this.")
(actions/play-animation entities :ego :spear)
(actions/talk entities :ego "Got it!")
(actions/remove-entity entities :monocle)
(actions/give entities :monocle)
(actions/talk entities :ego "It looks like a monocle."))}))
:collision "inside-castle/collision.png"
:scale-fn (utils/scaler-fn-from-image "inside-castle/scale.png" 0.25 1.00)
:apply-state (fn [entities]
(as-> entities entities
(if (actions/has-obtained? entities :trophy)
(update-in entities [:room :entities] #(dissoc % :trophy))
entities)
(if (actions/has-item? entities :sword)
(update-in entities [:room :entities] #(dissoc % :sword))
entities)
(if (= :night (get-in entities [:state :time]))
(make-night entities)
entities)))
:start-pos [245 90])))