diff --git a/src/clj/game/core/actions.clj b/src/clj/game/core/actions.clj index 108762f14c..c109b57ada 100644 --- a/src/clj/game/core/actions.clj +++ b/src/clj/game/core/actions.clj @@ -257,13 +257,14 @@ (defn select "Attempt to select the given card to satisfy the current select prompt. Calls resolve-select if the max number of cards has been selected." - [state side {:keys [card]}] + [state side {:keys [card shift-key-held]}] (let [target (get-card state card) prompt (first (get-in @state [side :selected])) ability (:ability prompt) card-req (:req prompt) card-condition (:card prompt) cid (:not-self prompt)] + (swap! state assoc-in [side :shift-key-select] shift-key-held) (when (and (not= (:cid target) cid) (cond card-condition (card-condition target) diff --git a/src/clj/game/core/pick_counters.clj b/src/clj/game/core/pick_counters.clj index 3be66768b9..c5347afa8e 100644 --- a/src/clj/game/core/pick_counters.clj +++ b/src/clj/game/core/pick_counters.clj @@ -130,7 +130,8 @@ ([provider-func outereid] (pick-credit-providing-cards provider-func outereid nil 0 (hash-map))) ([provider-func outereid target-count] (pick-credit-providing-cards provider-func outereid target-count 0 (hash-map))) ([provider-func outereid target-count stealth-target] (pick-credit-providing-cards provider-func outereid target-count stealth-target (hash-map))) - ([provider-func outereid target-count stealth-target selected-cards] + ([provider-func outereid target-count stealth-target selected-cards] (pick-credit-providing-cards provider-func outereid target-count stealth-target selected-cards nil)) + ([provider-func outereid target-count stealth-target selected-cards pre-chosen] (let [counter-count (reduce + 0 (map #(:number (second %) 0) selected-cards)) selected-stealth (filter #(has-subtype? (:card (second %)) "Stealth") selected-cards) stealth-count (reduce + 0 (map #(:number (second %) 0) selected-stealth)) @@ -138,6 +139,9 @@ (filter #(has-subtype? % "Stealth") (provider-func)) (provider-func)) provider-cards (filter #(not (get-in (card-def %) [:interactions :pay-credits :cost-reduction])) provider-cards) + ;; note - this allows holding the shift key while clicking a card to keep picking that card while possible + ;; ie: taking 5cr from miss bones with one click, instead of waiting for 5 server round-trips + should-auto-repeat? (fn [state side] (get-in @state [side :shift-key-select] nil)) pay-rest (req (if (and (<= (- target-count counter-count) (get-in @state [side :credit])) (<= stealth-target stealth-count)) @@ -171,29 +175,49 @@ (zero? (count provider-cards))) ; no more additional credit sources found {:async true :effect pay-rest} - {:async true - :prompt (str "Choose a credit providing card (" - counter-count (when (and target-count (pos? target-count)) - (str " of " target-count)) - " [Credits]" - (if (pos? stealth-target) - (str ", " (min stealth-count stealth-target) " of " stealth-target " stealth") - "") - ")") - :choices {:card #(in-coll? (map :cid provider-cards) (:cid %))} - :effect (req (let [pay-credits-type (-> target card-def :interactions :pay-credits :type) - pay-function (if (= :custom pay-credits-type) - (-> target card-def :interactions :pay-credits :custom) - (take-counters-of-type pay-credits-type)) - custom-ability ^:ignore-async-check {:async true - :effect pay-function} - neweid (make-eid state outereid) - providing-card target] - (wait-for (resolve-ability state side neweid custom-ability providing-card [card]) - (continue-ability state side - (pick-credit-providing-cards - provider-func eid target-count stealth-target - (update selected-cards (:cid providing-card) - #(assoc % :card providing-card :number (+ (:number % 0) async-result)))) - card targets)))) - :cancel-effect pay-rest})))) + (if (and pre-chosen (in-coll? (map :cid provider-cards) (:cid pre-chosen))) + {:async true + :effect (req (let [target pre-chosen + pay-credits-type (-> target card-def :interactions :pay-credits :type) + pay-function (if (= :custom pay-credits-type) + (-> target card-def :interactions :pay-credits :custom) + (take-counters-of-type pay-credits-type)) + custom-ability ^:ignore-async-check {:async true + :effect pay-function} + neweid (make-eid state outereid) + providing-card target] + (wait-for (resolve-ability state side neweid custom-ability providing-card [card]) + (continue-ability state side + (pick-credit-providing-cards + provider-func eid target-count stealth-target + (update selected-cards (:cid providing-card) + #(assoc % :card providing-card :number (+ (:number % 0) async-result))) + target) + card targets))))} + {:async true + :prompt (str "Choose a credit providing card (" + counter-count (when (and target-count (pos? target-count)) + (str " of " target-count)) + " [Credits]" + (if (pos? stealth-target) + (str ", " (min stealth-count stealth-target) " of " stealth-target " stealth") + "") + ")") + :choices {:card #(in-coll? (map :cid provider-cards) (:cid %))} + :effect (req (let [pay-credits-type (-> target card-def :interactions :pay-credits :type) + pay-function (if (= :custom pay-credits-type) + (-> target card-def :interactions :pay-credits :custom) + (take-counters-of-type pay-credits-type)) + custom-ability ^:ignore-async-check {:async true + :effect pay-function} + neweid (make-eid state outereid) + providing-card target] + (wait-for (resolve-ability state side neweid custom-ability providing-card [card]) + (continue-ability state side + (pick-credit-providing-cards + provider-func eid target-count stealth-target + (update selected-cards (:cid providing-card) + #(assoc % :card providing-card :number (+ (:number % 0) async-result))) + (when (should-auto-repeat? state side) target)) + card targets)))) + :cancel-effect pay-rest}))))) diff --git a/src/cljs/nr/gameboard/board.cljs b/src/cljs/nr/gameboard/board.cljs index 6c44b26fe6..2f392b3448 100644 --- a/src/cljs/nr/gameboard/board.cljs +++ b/src/cljs/nr/gameboard/board.cljs @@ -170,13 +170,13 @@ (:poison card) (:highlight-in-discard card)))) -(defn handle-card-click [{:keys [type zone] :as card}] +(defn handle-card-click [{:keys [type zone] :as card} shift-key-held] (let [side (:side @game-state)] (when (not-spectator?) (cond ;; Selecting card (= (get-in @game-state [side :prompt-state :prompt-type]) "select") - (send-command "select" {:card (card-for-click card)}) + (send-command "select" {:card (card-for-click card) :shift-key-held shift-key-held}) ;; Card is an identity of player's side (and (= (:type card) "Identity") @@ -189,7 +189,7 @@ (not (any-prompt-open? side)) (= "hand" (first zone)) (playable? card)) - (send-command "play" {:card (card-for-click card)}) + (send-command "play" {:card (card-for-click card) :shift-key-held shift-key-held}) ;; Corp clicking on a corp card (and (= side :corp) @@ -202,7 +202,8 @@ (if (= (:cid card) (:source @card-menu)) (do (send-command "generate-install-list" nil) (close-card-menu)) - (do (send-command "generate-install-list" {:card (card-for-click card)}) + (do (send-command "generate-install-list" {:card (card-for-click card) + :shift-key-held shift-key-held}) (open-card-menu (:cid card))))) :else @@ -722,13 +723,13 @@ (put-game-card-in-channel card zoom-channel)) :on-mouse-leave #(put! zoom-channel false) :on-click #(when (not disable-click) - (handle-card-click card)) + (handle-card-click card (.-shiftKey %))) :on-key-down #(when (and (= "Enter" (.-key %)) (not disable-click)) - (handle-card-click card)) + (handle-card-click card (.-shiftKey %))) :on-key-up #(when (and (= " " (.-key %)) (not disable-click)) - (handle-card-click card))} + (handle-card-click card (.-shiftKey %)))} (if (or (not code) flipped facedown) (let [facedown-but-known (or (not (or (not code) flipped facedown)) (spectator-view-hidden?)