diff --git a/desktop/src-common/advent/actions.clj b/desktop/src-common/advent/actions.clj index 9af62260..1182399f 100644 --- a/desktop/src-common/advent/actions.clj +++ b/desktop/src-common/advent/actions.clj @@ -47,10 +47,13 @@ (seq (set/intersection (set (get-in entities [:state :inventory])) (set items))) (seq (set/intersection (set (get-in @entities [:state :inventory])) (set items))))) +(def ^{:dynamic true} *fg-bg-key* :fg-actions) + + (defmacro run-action [entities & forms] `(let [c# (chan)] (do - (put! (get-in (deref ~entities) [:actions :channel]) + (put! (get-in (deref ~entities) [*fg-bg-key* :channel]) (reify IAction (get-channel [_] c#) ~@forms)) @@ -62,36 +65,55 @@ (reset! ~entities result#)))))) (defn change-script-state [entities state] - (run-action entities - (begin [this screen entities] - (update-in entities [:actions] assoc :script-running? state :last-skip-type (if state :end nil))) + (let [fg-bg-key *fg-bg-key*] + (run-action entities + (begin [this screen entities] + (update-in entities [fg-bg-key] assoc :script-running? state :last-skip-type (if state :end nil))) - (continue [this screen entities] entities) + (continue [this screen entities] entities) - (done? [this screen entities] - true) + (done? [this screen entities] + true) - (terminate [this screen entities] - entities) - (skip-type [this screen entities] - :none-but-arrow))) + (terminate [this screen entities] + entities) + (skip-type [this screen entities] + :none-but-arrow)))) + +(defmacro get-bg-script [entities & forms] + `(fn [starting-entities#] + (put! (get-in starting-entities# [:bg-actions :script-chan]) + (fn [starting-entities#] + (let [~entities (atom starting-entities#)] + (thread (binding [*fg-bg-key* :bg-actions] + ~@forms + (change-script-state ~entities false) + ))))))) (defmacro get-script [entities & forms] `(fn [starting-entities#] - (put! (get-in starting-entities# [:actions :script-chan]) + (put! (get-in starting-entities# [:fg-actions :script-chan]) (fn [starting-entities#] (let [~entities (atom starting-entities#)] - (thread (do + (thread (binding [*fg-bg-key* :fg-actions] ~@forms (change-script-state ~entities false) (utils/save @~entities "autosave" "Autosave")))))))) +(defn force-end [entities current-action key] + (do (put! (get-channel current-action) :end) + (screen! dialogue/talking-screen :stop-talk :id key) + (-> entities + (assoc-in [key :script-running?] false) + (assoc-in [key :current] nil) + (assoc-in [key :started?] false)))) + (defmacro get-unsaved-script [entities & forms] `(fn [starting-entities#] - (put! (get-in starting-entities# [:actions :script-chan]) + (put! (get-in starting-entities# [:fg-actions :script-chan]) (fn [starting-entities#] (let [~entities (atom starting-entities#)] - (thread (do + (thread (binding [*fg-bg-key* :fg-actions] ~@forms (change-script-state ~entities false)))))))) @@ -183,6 +205,19 @@ (skip-type [this screen entities] :skip))) +(defn do-force-end [entities key] + (run-action entities + (begin [this screen entities] + (if (get-in entities [key :script-running?]) + (force-end entities (get-in entities [key :current]) key) + entities)) + (continue [this screen entities] entities) + (done? [this screen entities] true) + (terminate [this screen entities] + entities) + (skip-type [this screen entities] + :none))) + (defn walk-straight-to [entities target-id [final-x final-y] & {:keys [update-baseline? face speed anim override-dir stop?]}] @@ -352,7 +387,8 @@ (defn talk [entities target-id text & {:keys [stop? animate? anim wait color] :or {wait true}}] (let [initial-time (atom nil) stop? (if (nil? stop?) true stop?) - animate? (if (nil? animate?) true animate?)] + animate? (if (nil? animate?) true animate?) + fg-or-bg *fg-bg-key*] (run-action entities (begin [this screen entities] (let [_ (swap! initial-time #(or % (:total-time screen))) @@ -369,6 +405,7 @@ scale (get-in entities [:room :entities target-id :scale-y] 1) height (* scale height)] (screen! dialogue/talking-screen :on-talk :text text + :id fg-or-bg :scene-viewport (:viewport screen) :x target-x :y (+ target-y height) :color (or color (get-in entities [:room :entities target-id :talk-color])) @@ -391,7 +428,7 @@ (terminate [this screen entities] (if wait (do - (screen! dialogue/talking-screen :stop-talk :target-id target-id) + (screen! dialogue/talking-screen :stop-talk :id fg-or-bg) (if stop? (stop screen entities target-id) entities)) @@ -648,12 +685,16 @@ (assoc-in [:state :next-time] nil)) entities) :ego - :face face)] + :face face) + entities (if (get-in entities [:bg-actions :script-running?]) + (force-end entities (get-in entities [:bg-actions :current]) :bg-actions) + entities)] (if-let [stop-fn (get-in entities [:room :stop-fn])] (stop-fn screen entities) entities))) (skip-type [this screen entities] :none)) + (screen! dialogue/talking-screen :stop-talk :id :bg-actions) (run-action entities (begin [this screen entities] (utils/stop-all-sounds! entities) diff --git a/desktop/src-common/advent/screens/dialogue.clj b/desktop/src-common/advent/screens/dialogue.clj index 3ddfd394..12a1bfe3 100644 --- a/desktop/src-common/advent/screens/dialogue.clj +++ b/desktop/src-common/advent/screens/dialogue.clj @@ -50,7 +50,7 @@ entities) :on-talk - (fn [{:keys [create-talk target-id color text x y scale scene-viewport] :as screen} [entities]] + (fn [{:keys [create-talk target-id color text x y scale scene-viewport id] :as screen} [entities]] (let [font (bitmap-font "ego/font.fnt" ) p (NinePatchEntity. (skin! (skin "ui/ui.json") :get-patch "ui-bg")) _ (nine-patch! p :set-padding 25 25 5 15) @@ -71,25 +71,28 @@ :source-x source-x :source-y source-y ) x (- x (/ (label! talk :get-width) 2)) - talk (assoc talk :x x :y y) + talk (assoc talk :x x :y y :id id) talk (ensure-on-screen talk)] - (assoc entities :dialogue talk))) + (assoc entities id talk))) :on-update-camera - (fn [{:keys [scene-viewport scene-camera viewport] :as screen} [ {:keys [dialogue] :as entities}]] - (when dialogue - (let [[x y] (scene-world->talk-world scene-viewport [(:source-x dialogue) - (:source-y dialogue)])] - (-> entities - (assoc-in [:dialogue :x] (- x (/ (label! dialogue :get-width) 2))) - (assoc-in [:dialogue :y] y) - (update-in [:dialogue] ensure-on-screen) - )))) + (fn [{:keys [scene-viewport scene-camera viewport] :as screen} [ entities]] + (reduce-kv (fn [entities id e] + (if (:id e) + (let [[x y] (scene-world->talk-world scene-viewport [(:source-x e) + (:source-y e)])] + (-> entities + (assoc-in [id :x] (- x (/ (label! e :get-width) 2))) + (assoc-in [id :y] y) + (update-in [id] ensure-on-screen))) + entities)) + entities + entities)) :stop-talk - (fn [{:keys [target-id] } [entities]] - (dissoc entities :dialogue)) + (fn [{:keys [id] } [entities]] + (dissoc entities (or id :fg-actions))) :on-resize (fn [{:keys [viewport width height]} entities] diff --git a/desktop/src-common/advent/screens/rooms/castle_gate.clj b/desktop/src-common/advent/screens/rooms/castle_gate.clj index 18963d0c..6e123f40 100644 --- a/desktop/src-common/advent/screens/rooms/castle_gate.clj +++ b/desktop/src-common/advent/screens/rooms/castle_gate.clj @@ -97,7 +97,7 @@ (update-in entities [:tweens] dissoc :coin-y))) (actions/walk-straight-to entities :coin-flip [212 90] :update-baseline? false :speed 3.0) - (screen! dialogue/talking-screen :stop-talk :target-id :ego) + (screen! dialogue/talking-screen :stop-talk) (actions/do-stop entities :ego) (actions/walk-straight-to entities :coin-flip [210 105] :update-baseline? false :speed 1.0) diff --git a/desktop/src-common/advent/screens/rooms/dream.clj b/desktop/src-common/advent/screens/rooms/dream.clj index c0430905..99098573 100644 --- a/desktop/src-common/advent/screens/rooms/dream.clj +++ b/desktop/src-common/advent/screens/rooms/dream.clj @@ -281,7 +281,7 @@ (defn return-from-island [screen entities] - (when (and (not (get-in entities [:actions :script-running?])) + (when (and (not (get-in entities [:fg-actions :script-running?])) (get-in entities [:state :active?]) (get-in entities [:room :entities :fairy-godfather :distracted?])) (if (> (get-in entities [:room :entities :fairy-godfather :distracted-time] 0) 15) diff --git a/desktop/src-common/advent/screens/rooms/held.clj b/desktop/src-common/advent/screens/rooms/held.clj index c93bc8f4..4663b427 100644 --- a/desktop/src-common/advent/screens/rooms/held.clj +++ b/desktop/src-common/advent/screens/rooms/held.clj @@ -37,7 +37,7 @@ (actions/update-entities entities (fn [e] (assoc-in e [:room :bloodclot-timer] 0))))}]})) (defn add-second [screen entities] - (when (and (not (get-in entities [:actions :script-running?])) + (when (and (not (get-in entities [:fg-actions :script-running?])) (get-in entities [:state :active?])) (if (> (get-in entities [:room :bloodclot-timer] 0) 7) (do diff --git a/desktop/src-common/advent/screens/rooms/inside_castle.clj b/desktop/src-common/advent/screens/rooms/inside_castle.clj index 6d60b1a5..319c33c5 100644 --- a/desktop/src-common/advent/screens/rooms/inside_castle.clj +++ b/desktop/src-common/advent/screens/rooms/inside_castle.clj @@ -15,10 +15,11 @@ [play-clj.g2d :refer :all])) (defn brian [screen entities] - (when (and (not (get-in entities [:actions :script-running?])) + (when (and (not (get-in entities [:fg-actions :script-running?])) + (not (get-in entities [:bg-actions :script-running?])) (get-in entities [:state :active?]) (get-in entities [:room :entities :game-player])) - ((actions/get-script entities + ((actions/get-bg-script entities ((rand-nth [#(actions/do-dialogue entities :game-player "2 to the power of pi." :game-player "No, that's not right.") #(actions/do-dialogue entities :game-player "Eureka!" @@ -114,7 +115,8 @@ {:run #(actions/respond entities % :game-player "Fine by me.")}]}) (defn walk-to-player [entities] - (actions/walk-to entities :ego [209 74] :face :right)) + (actions/walk-to entities :ego [209 74] :face :right) + (actions/do-force-end entities :bg-actions)) (defn brian-pause-from-work [entities] (actions/play-animation entities :game-player :pause-from-work :stop? false) @@ -250,6 +252,7 @@ (actions/transition-music entities nil :duration 0.15)) (defn pull-sword [entities] + (actions/do-force-end entities :bg-actions) (actions/play-animation entities :ego :reach-start :stop? false) (actions/pause-camera entities) (actions/transition-music entities :pull-sword @@ -362,7 +365,7 @@ ] (rooms/make :music {:day :town-1 :night :night :sunrise :night} :name "Inside castle" - :timers {:brian [10.0 20.0 brian]} + :timers {:brian [10.0 2.0 brian]} :interactions {:right-door {:box [286 140 306 160] :cursor :right diff --git a/desktop/src-common/advent/screens/rooms/inside_jail.clj b/desktop/src-common/advent/screens/rooms/inside_jail.clj index 5a55af65..3330cc8d 100644 --- a/desktop/src-common/advent/screens/rooms/inside_jail.clj +++ b/desktop/src-common/advent/screens/rooms/inside_jail.clj @@ -334,7 +334,7 @@ (get-in entities [:room :entities :ego :right :walk])} (get-in entities [:room :entities :ego :anim]))] (if is-walking? (let [entities (-> entities - (update-in [:actions] #(assoc % :channel (chan) :current nil :started? false :script-running? false)) + (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) diff --git a/desktop/src-common/advent/screens/rooms/space.clj b/desktop/src-common/advent/screens/rooms/space.clj index 915d368a..36b989c9 100644 --- a/desktop/src-common/advent/screens/rooms/space.clj +++ b/desktop/src-common/advent/screens/rooms/space.clj @@ -17,7 +17,7 @@ [play-clj.g2d :refer :all])) (defn taunt [screen entities] - (when (and (not (get-in entities [:actions :script-running?])) + (when (and (not (get-in entities [:fg-actions :script-running?])) (get-in entities [:state :active?]) (not (get-in entities [:state :blergh-dead?])) (not (actions/has-item? entities :magic-slingshot))) @@ -30,7 +30,7 @@ nil) (defn shock [screen entities] - (when (and (not (get-in entities [:actions :script-running?])) + (when (and (not (get-in entities [:fg-actions :script-running?])) (get-in entities [:state :active?]) (not (get-in entities [:state :blergh-dead?])) (actions/has-item? entities :magic-slingshot)) diff --git a/desktop/src-common/advent/screens/scene.clj b/desktop/src-common/advent/screens/scene.clj index 89eb7e0c..97640ff9 100644 --- a/desktop/src-common/advent/screens/scene.clj +++ b/desktop/src-common/advent/screens/scene.clj @@ -180,7 +180,7 @@ void main () (defn click-inventory [screen entities] - (when (not (get-in entities [:actions :script-running?])) + (when (not (get-in entities [:fg-actions :script-running?])) (if (= (get-in entities [:cursor :current] ) :main) (do (screen! inventory-screen :show-screen :items (map (entities :all-items) (get-in entities [:state :inventory]))) @@ -189,23 +189,22 @@ void main () (assoc-in [:cursor :override] nil))) (assoc-in entities [:cursor :current] :main)))) + + (defn skip-action [screen entities] - (let [current-action (get-in entities [:actions :current])] + (let [current-action (get-in entities [:fg-actions :current])] (cond (= :skip (actions/skip-type current-action screen entities)) (let [terminated-entities (actions/terminate current-action screen entities)] (do (put! (actions/get-channel current-action) terminated-entities) (-> terminated-entities - (assoc-in [:actions :current] nil) - (assoc-in [:actions :started?] false)))) + (assoc-in [:fg-actions :current] nil) + (assoc-in [:fg-actions :started?] false)))) (= :end (actions/skip-type current-action screen entities)) (let [terminated-entities (actions/terminate current-action screen entities)] (println "trying to end") - (do (put! (actions/get-channel current-action) :end) - (-> terminated-entities - (assoc-in [:actions :script-running?] false) - (assoc-in [:actions :current] nil) - (assoc-in [:actions :started?] false)))) + (actions/force-end terminated-entities current-action :fg-actions) + ) :else entities))) @@ -229,7 +228,7 @@ void main () _ (println "clicked " x y) interaction (get-interaction entities x y) interacting-entity (get-interacting-entity entities x y) - current-action (get-in entities [:actions :current]) + current-action (get-in entities [:fg-actions :current]) ;; TODO - hacky way of resetting queue @@ -239,7 +238,8 @@ void main () (skip-action screen entities) entities)] - (when (and (not (get-in entities [:actions :script-running?])) + + (when (and (not (get-in entities [:fg-actions :script-running?])) (= (get-in entities [:cursor :down-target]) (or (:id interacting-entity) (:id interaction) nil))) ((or (when interacting-entity @@ -768,32 +768,40 @@ void main () (merge (animation->texture screen (:stand (:right ego))) ego) :stand))) -(defn start-script-if-necessary [screen {{:keys [script-running? script-chan]} :actions :as entities}] - (if script-running? - entities - (let [[next-script] (alts!! [script-chan] :default nil)] - (if next-script - (do - (next-script entities) - (println "starting script") - - (assoc-in entities [:actions :script-running?] true)) - entities)))) +(defn start-script-if-necessary [screen entities key] + (let [{{:keys [script-running? script-chan]} key} entities] + (if script-running? + entities + (let [[next-script] (alts!! [script-chan] :default nil)] + (if next-script + (do + (next-script entities) + (println "starting script") + + (assoc-in entities [key :script-running?] true)) + entities))))) -(defn update-from-script [screen {{:keys [current started? channel script-chan]} :actions :as entities}] - (if current - (let [entities (if started? entities (actions/begin current screen entities)) - entities (actions/continue current screen entities)] - (if (actions/done? current screen entities) - (let [terminated (actions/terminate current screen entities)] - (put! (actions/get-channel current) terminated) - (recur screen (assoc terminated - :actions {:channel channel :script-chan (get-in entities [:actions :script-chan]) :current nil :started? false :script-running? (get-in entities [:actions :script-running?]) :last-skip-type (get-in entities [:actions :last-skip-type])}))) - (assoc-in entities [:actions :started?] true))) - (let [[current _] (alts!! [channel] :default nil)] - (assoc entities :actions {:script-chan (get-in entities [:actions :script-chan]) :channel channel :current current :started? false :script-running? (get-in entities [:actions :script-running?]) :last-skip-type (if current - (actions/skip-type current screen entities) - (get-in entities [:actions :last-skip-type]))})))) +(defn update-from-script [screen entities key] + (let [{{:keys [current started? channel script-chan script-running?]} key} entities] + + (if current + (let [entities (if started? entities (actions/begin current screen entities)) + entities (actions/continue current screen entities)] + (if (actions/done? current screen entities) + (let [terminated (actions/terminate current screen entities)] + (put! (actions/get-channel current) terminated) + (recur screen + (update-in terminated [key] assoc :current nil :started? false) + key)) + (assoc-in entities [key :started?] true))) + (let [[current _] (alts!! [channel] :default nil)] + + (-> entities + (assoc-in [key :started?] false) + (assoc-in [key :last-skip-type] (if current + (actions/skip-type current screen entities) + (get-in entities [key :last-skip-type]))) + (assoc-in [key :current] current)))))) (defn update-from-hotspots [screen entities] @@ -1104,12 +1112,18 @@ void main () :origin-y 0 :x -20 :y -20) - :actions {:object nil + :fg-actions {:object nil :channel (chan) :current nil :script-running? false :started? false - :script-chan (chan (dropping-buffer 1))} + :script-chan (chan (dropping-buffer 1))} + :bg-actions {:object nil + :channel (chan) + :current nil + :script-running? false + :started? false + :script-chan (chan (dropping-buffer 1))} :volume {:object nil :value 0.0} :music-override {:object nil @@ -1171,8 +1185,10 @@ void main () (let [entities (fade-in-first-time-if-necessary screen entities) entities (utils/apply-tweens screen entities (:tweens entities)) entities (update-cursor screen entities) - entities (start-script-if-necessary screen entities) - entities (update-from-script screen entities) + entities (start-script-if-necessary screen entities :fg-actions) + entities (update-from-script screen entities :fg-actions) + entities (start-script-if-necessary screen entities :bg-actions) + entities (update-from-script screen entities :bg-actions) entities (update-from-room screen entities) entities (update-from-hotspots screen entities) entities (assoc-in entities [:room :entities :ego :last-frame] (get-in entities [:room :entities :ego :object])) @@ -1292,7 +1308,7 @@ void main () :on-show-inventory (fn [screen [entities]] (click-inventory screen entities)) :on-save (fn [screen [entities]] - (when-not (get-in entities [:actions :script-running?]) + (when-not (get-in entities [:fg-actions :script-running?]) (let [date (.format (java.text.SimpleDateFormat. "MM/dd/YY") (java.util.Date.)) save-name (str (-> entities :room :name) " - " date)] (utils/save entities @@ -1363,7 +1379,7 @@ void main () ) (defn hud-interactable? [] (let [[scene-entities] (-> scene :entities deref)] - (and (not (get-in scene-entities [:actions :script-running?])) + (and (not (get-in scene-entities [:fg-actions :script-running?])) (get-in scene-entities [:state :active?]) (= 0.0 (get-in scene-entities [:fade :opacity]))))) diff --git a/desktop/src-common/advent/utils.clj b/desktop/src-common/advent/utils.clj index 2ef9357b..1b3c6fdc 100644 --- a/desktop/src-common/advent/utils.clj +++ b/desktop/src-common/advent/utils.clj @@ -348,10 +348,10 @@ (< y1 y (+ y1 height)))) (defn is-unstoppable-script-running [screen entities] - (let [current-action (get-in entities [:actions :current]) - is-script-running (get-in entities [:actions :script-running?])] + (let [current-action (get-in entities [:fg-actions :current]) + is-script-running (get-in entities [:fg-actions :script-running?])] (and is-script-running - (= :none (get-in entities [:actions :last-skip-type]))))) + (= :none (get-in entities [:fg-actions :last-skip-type]))))) (defn update-override [{:keys [^FitViewport viewport] :as screen} entities] (let [raw-pos (get-in entities [:cursor :last-pos])