/
timer.cljc
71 lines (65 loc) · 3.2 KB
/
timer.cljc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
(ns cark.behavior-tree.node-defs.timer
"The :timer node stays :running until a certain duration (in milliseconds) has elapsed.
parameters:
- :timer : an optional keyword or keyword returning context function. The name of this timer.
- :duration : an integer or integer returning context function. The numebr of milliseconds this node stays :running before succeeding.
This node has two modes of operation.
- named timer :
when the :timer parameter is set, the :timer node will start counting time based on the last completed timer with the same name (or now if none were found)
- free timer :
The duration starts counting when the :timer node passes from :fresh to :running
Although they're not always necessary, named timers are the most precise as their combined durations do not depend on the tick invokation times."
(:require [cark.behavior-tree.context :as ctx]
[cark.behavior-tree.db :as db]
[cark.behavior-tree.tree :as tree]
[cark.behavior-tree.type :as type]
[cark.behavior-tree.base-nodes :as bn]
[clojure.spec.alpha :as s]))
(defn log [val]
(tap> val)
val)
(s/def ::duration (s/or :function fn?
:integer int?))
(s/def ::timer (s/or :keyword keyword?
:function ifn?))
(defn compile-node [tree id tag params _]
(let [[type value] (:duration params)
get-duration (case type
:integer (constantly value)
:function value)
[type value] (:timer params)
get-name (case type
:function value
:keyword (constantly value)
nil nil)]
[(if get-name
(fn named-timer-tick [ctx arg]
(case (db/get-node-status ctx id)
:fresh (recur (-> (db/set-node-data ctx id (+ (or (db/get-timer-start-time ctx (get-name ctx))
(db/get-time ctx))
(get-duration ctx)))
(db/set-node-status id :running))
arg)
:running (let [end (db/get-node-data ctx id)
now (db/get-time ctx)]
(if (<= end now)
(-> (db/set-node-status ctx id :success)
(db/set-timer-start-time (get-name ctx) end)
(db/set-node-data id nil))
ctx))))
(fn timer-tick [ctx arg]
(case (db/get-node-status ctx id)
:fresh (recur (-> (db/set-node-data ctx id (+ (db/get-time ctx) (get-duration ctx)))
(db/set-node-status id :running))
arg)
:running (if (<= (db/get-node-data ctx id) (db/get-time ctx))
(-> (db/set-node-status ctx id :success)
(db/set-node-data id nil))
ctx))))
tree]))
(defn register []
(type/register
(bn/leaf
{::type/tag :timer
::type/params-spec (s/keys :req-un [::duration] :opt-un [::timer])
::type/compile-func compile-node})))