systems.fnl 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. ;TODO find home for these game fns
  2. (fn things-at [v col]
  3. ;list of all entities at a world pos
  4. ;naive, replace with bucket hash at some point
  5. (var found [])
  6. (each [_ e (ipairs col)]
  7. (if (and e.pos (point= e.pos v))
  8. (add found e))) found)
  9. (fn entities-at [v] (things-at v entities))
  10. (fn items-at [v] (things-at v items))
  11. (fn triggers-at [v] (things-at v triggers))
  12. (fn trigger-at [v] (let [xs (triggers-at v)]
  13. (if (not (empty? xs)) (first xs))))
  14. (fn blood [v n c]
  15. (let [pv (->view (vadd (vmul v 8) (point 4 4)))]
  16. (for [i 1 n]
  17. (var c {
  18. :type :circ
  19. :pos (vadd pv (rand-point 4))
  20. :r 1 :c (or c 6)})
  21. (add fx c)
  22. (wait (rand 5) (fn []
  23. (tween c :r (rand 4) 6 {:f (fn [c]
  24. (tween c :r 0 6 {:f (fn [c] (remove fx c))}))}))))))
  25. (fn text-fx [v s c]
  26. (let [pv (->view (vadd (vmul v 8) (point 4 4)))]
  27. (var c {
  28. :type :text
  29. :value s
  30. :pos pv
  31. :c c})
  32. (add fx c)
  33. (tween pv :y (- pv.y 8) 20 {:f
  34. (fn [o] (remove fx c))})))
  35. (fn attack-fx [a b] ;animate the attack sprite towards the target
  36. (let [dif (vsub b a)
  37. s (if
  38. (point= dif (point -1 0)) 241
  39. (point= dif (point 1 0)) 242
  40. (point= dif (point 0 -1)) 243
  41. (point= dif (point 0 1)) 244 241)
  42. a (->view (vmul a 8))
  43. b (->view (vmul b 8))]
  44. (var c {
  45. :type :sprite
  46. :value s
  47. :pos a})
  48. (add fx c)
  49. (tween c :pos b 10 {:l vlerp :f
  50. (fn [o] (remove fx c)) })))
  51. (fn kill-player [s]
  52. (set DEATHMSG s)
  53. (set LOOP :death)
  54. (set depth 0)
  55. (song! 2)
  56. (music 2 0 0 false)
  57. (set creditsv (point 120 74))
  58. (wait 200 (fn []
  59. (tween creditsv :y -500 3000))))
  60. (fn kill [e]
  61. (blood e.pos 8)
  62. ;TODO but what if PLAYER is ME?
  63. (remove entities e)
  64. (if
  65. (= e.name :ohno)
  66. (kill-player true)
  67. e.player
  68. (kill-player false)
  69. (do
  70. (wait 1 (fn [] (table.insert msgs 1 (.. "you kill the " e.name)))))))
  71. (fn attack [e target]
  72. (attack-fx e.pos target.pos)
  73. (if (calc-hit e target)
  74. (let [amount (calc-damage e target)]
  75. (update target :hp
  76. (fn [n] (- n amount)))
  77. (blood target.pos 2)
  78. (text-fx target.pos (.. amount) 6)
  79. (sound! :hit))
  80. (do
  81. (sound! :miss)))
  82. (when (< target.hp 0)
  83. (set e.exp (+ e.exp (exp-value target)))
  84. (kill target)))
  85. (fn hat-swap [e target]
  86. (let [th (. (or target.equip.head {}) :name) ph (. (or e.equip.head {}) :name)]
  87. (if (and e.equip.head (not th))
  88. (when true
  89. (wait 1 (fn [] (table.insert msgs 1 (.. "thanks, " target.equip.head.msg))))
  90. (var tmp target.equip.head)
  91. (set target.equip.head e.equip.head)
  92. (set e.equip.head tmp))
  93. (wait 1 (fn [] (table.insert msgs 1 (if target.equip.head target.equip.head.msg "hello!")))))))
  94. (fn bump [e col]
  95. ; should not all happen at once (attacks)
  96. ; also check for hit dice etc.
  97. (let [target (rand-nth col)]
  98. (if
  99. (and (or e.player (and e.monster target.player)) (not (or e.passive target.passive)))
  100. (attack e target))
  101. (if
  102. (and e.player target.townie)
  103. (hat-swap e target))))
  104. (fn walk [e dir]
  105. (let [target (vadd e.pos dir)]
  106. (when (~= 0 (gget world target))
  107. (let [found (entities-at target)]
  108. (if (not (empty? found))
  109. (bump e found)
  110. (do
  111. (tset e :pos (vadd (. e :pos) dir))
  112. (tset e :offset (vmul dir -8))
  113. (tween e :offset (point 0 0) 10 {:l vlerp :e (powf 2)})))))))
  114. (fn pickup [e]
  115. (let [found (first (things-at e.pos items))]
  116. (when found
  117. (if found.amount
  118. (do (set player.gold (+ player.gold found.amount))
  119. (remove items found))
  120. (when (and (< (# e.inventory) e.inventory-limit))
  121. (remove items found)
  122. (add e.inventory found))))))
  123. (var A 1)
  124. (var B 3)
  125. (when (chance 50)
  126. (set A 3)
  127. (set B 1))
  128. (var dung-song A)
  129. (fn flip-song [] (wait 6000
  130. (fn [_]
  131. (trace "FLIP 1")
  132. (set dung-song A)
  133. (wait 6000
  134. (fn [_]
  135. (trace "FLIP 3")
  136. (set dung-song B)
  137. (flip-song))))))
  138. (flip-song)
  139. (var _button_dirty false)
  140. (fn action [e]
  141. ;find an appropriate action for situation
  142. (let [t (trigger-at e.pos)
  143. i (items-at e.pos)]
  144. (when (not _button_dirty)
  145. (if (not (empty? i))
  146. (pickup e)
  147. (and t t.stairs)
  148. (do
  149. (cache-level)
  150. (set depth (+ depth t.dir))
  151. (if (not (load-cache depth))
  152. (change-level t.dir))
  153. (clear-cache)
  154. (if (= depth 0) (song! 0)
  155. (song! dung-song)))
  156. :pass))))
  157. (fn recall [e]
  158. (if (= depth 0)
  159. (do (cache-level)
  160. (set depth DEEPEST)
  161. (load-cache DEEPEST)
  162. (song! dung-song))
  163. (do
  164. (cache-level)
  165. (set depth 0)
  166. (load-cache 0)
  167. (song! 0) )))
  168. (fn drop [e o]
  169. (tset o :pos (copy e.pos))
  170. (add items o)
  171. (remove e.inventory o))
  172. (fn wear [e o]
  173. (if
  174. o.wear ;TODO should check if wear key is in equip
  175. (if true ;(has-key? e.equip o.wear)
  176. (let [old (. e.equip o.wear)]
  177. (remove e.inventory o) ;could not even be there
  178. (if old (add e.inventory old)) ;TODO check inventory limit?
  179. (tset e.equip o.wear o)))
  180. o.weapon
  181. (let [old e.weapon]
  182. (if old (add e.inventory old))
  183. (remove e.inventory o)
  184. (set e.weapon o)) ))
  185. (fn unwear [e o]
  186. (each [k v (pairs e.equip)]
  187. (when (= v o)
  188. (tset e.equip k false)
  189. (add e.inventory o))))
  190. (fn draw-fx []
  191. (each [_ m (ipairs fx)]
  192. (if (= m.type :circ)
  193. (circ m.pos.x m.pos.y m.r m.c)
  194. (= m.type :sprite)
  195. (spr m.value m.pos.x m.pos.y (or m.mask 0))
  196. (= m.type :text)
  197. (do
  198. (print m.value (+ m.pos.x 1) (+ m.pos.y 1) 0)
  199. (print m.value (- m.pos.x 1) (- m.pos.y 1) 0)
  200. (print m.value m.pos.x m.pos.y m.c)) )))
  201. (fn path-towards [a b]
  202. (vfn (vnorm (vsub b a))
  203. (fn [n] (if (< n 0) -1 (> n 0) 1 0))))
  204. ; systems
  205. (local sprites (system [:pos :sprite] (fn [e]
  206. (let [v (if e.offset
  207. (->view (vadd (vmul e.pos 8) e.offset))
  208. (->view (vmul e.pos 8)))]
  209. (if e.nomask
  210. (spr e.sprite v.x v.y)
  211. e.mask
  212. (spr e.sprite v.x v.y e.mask)
  213. (spr e.sprite v.x v.y 0))
  214. (if (and e.equip e.equip.feet)
  215. (spr e.equip.feet.sprite v.x (+ v.y 1) 0))
  216. (if (and e.equip e.equip.head)
  217. (spr e.equip.head.sprite v.x (- v.y 5) 0))
  218. (if (and e.equip e.equip.body)
  219. (spr e.equip.body.sprite v.x (+ v.y 2) 0))
  220. (if e.weapon
  221. (spr e.weapon.sprite (+ v.x 4) (- v.y 2) 0))))))
  222. (local stat-updates (system [:exp :level] (fn [e]
  223. (when (> e.exp (exp-next e.level))
  224. (set e.exp (math.max 0 (- e.exp (exp-next e.level))))
  225. (set e.level (inc e.level))
  226. (set e.maxhp (+ e.maxhp (+ 3 (roll [1 5]))))
  227. (set e.hp e.maxhp)
  228. (sound! :levelup))
  229. )))
  230. (local brains (system [:ai] (fn [e]
  231. (if
  232. (= e.ai :hunt)
  233. (let [dir (path-towards e.pos player.pos)]
  234. (walk e dir))
  235. (= e.ai :wander)
  236. (let [dir (rand-nth cardinals)]
  237. (walk e dir))
  238. (= e.ai :slow-wander)
  239. (let [dir (rand-nth cardinals)]
  240. (if (= 0 (math.random 0 5)) (walk e dir)))
  241. (= e.ai :confused)
  242. (let [a (rand-nth cardinals)
  243. b (path-towards e.pos player.pos)]
  244. (walk e (rand-nth [a b])))
  245. (= e.ai :breed)
  246. (let [dir (rand-nth cardinals)]
  247. (if (chance 20)
  248. (when (> e.breed 0)
  249. (update e :breed dec)
  250. (add entities (copy e))
  251. (walk e dir))))))))