;;-*-Lisp-*-
(in-package goal)

;; name: citizen-enemy.gc
;; name in dgo: citizen-enemy
;; dgos: CWI

;; DECOMP BEGINS

(deftype citizen-enemy (citizen)
  ((next-update-target  time-frame)
   (minimap             connection-minimap)
   )
  (:methods
    (traffic-danger-init! (_type_) none)
    (citizen-enemy-method-202 (_type_) none)
    )
  )


(defmethod common-post ((this citizen-enemy))
  "Does a lot of various things relating to interacting with the target
- tracks when the enemy was last drawn
- looks at the target and handles attacking
@TODO Not extremely well understood yet"
  (let ((a1-0 (new 'stack-no-clear 'overlaps-others-params)))
    (set! (-> a1-0 options) (overlaps-others-options))
    (set! (-> a1-0 collide-with-filter) (-> this enemy-info overlaps-others-collide-with-filter))
    (set! (-> a1-0 tlist) *touching-list*)
    (find-overlapping-shapes (-> this root) a1-0)
    )
  (when (and (not (focus-test? this disable dead ignore inactive))
             (< (-> this next-update-target) (current-time))
             (not (logtest? (enemy-flag lock-focus) (-> this enemy-flags)))
             (-> this next-state)
             (= (-> this next-state name) 'active)
             )
    (citizen-enemy-method-202 this)
    (set! (-> this next-update-target) (+ (current-time) (seconds 0.2)))
    (traffic-danger-init! this)
    )
  ((method-of-type citizen common-post) this)
  (none)
  )

;; WARN: Return type mismatch object vs symbol.
(defmethod enemy-method-76 ((this citizen-enemy) (arg0 process) (arg1 event-message-block))
  (the-as
    symbol
    (cond
      ((and (-> this next-state) (let ((v1-3 (-> this next-state name)))
                                   (or (= v1-3 'knocked) (= v1-3 'jump))
                                   )
            )
       ((method-of-type citizen enemy-method-76) this arg0 arg1)
       )
      (else
        (when (!= (-> arg0 type) target)
          (let* ((s3-0 (-> arg1 param 0))
                 (s2-0 arg0)
                 (v1-6 (if (type? s2-0 process-focusable)
                           s2-0
                           )
                       )
                 )
            (cond
              ((and (focus-test? this dangerous)
                    (logtest? (process-mask guard civilian) (-> arg0 mask))
                    (and v1-6
                         (not (logtest? (-> (the-as process-focusable v1-6) focus-status) (focus-status disable dead ignore grabbed)))
                         )
                    ((method-of-type touching-shapes-entry prims-touching-action?)
                     (the-as touching-shapes-entry s3-0)
                     (-> this root)
                     (collide-action deadly)
                     (collide-action)
                     )
                    )
               (let ((a3-2 (if ((method-of-type touching-shapes-entry prims-touching-action?)
                                (the-as touching-shapes-entry s3-0)
                                (-> this root)
                                (collide-action persistent-attack)
                                (collide-action)
                                )
                               (-> this persistent-attack-id)
                               (-> this attack-id)
                               )
                           )
                     )
                 (enemy-method-104 this arg0 (the-as touching-shapes-entry s3-0) a3-2)
                 )
               )
              (else
                (send-event arg0 'touch (-> arg1 param 0))
                )
              )
            )
          )
        )
      )
    )
  )

(defmethod general-event-handler ((this citizen-enemy) (arg0 process) (arg1 int) (arg2 symbol) (arg3 event-message-block))
  "Handles various events for the enemy
@TODO - unsure if there is a pattern for the events and this should have a more specific name"
  (case arg2
    (('event-death)
     #f
     )
    (('effect-control)
     (case (-> arg3 param 0)
       (('death-default)
        (cond
          ((> (-> this hit-points) 0)
           #t
           )
          (else
            (let ((v1-4 (-> this root root-prim)))
              (set! (-> v1-4 prim-core collide-as) (collide-spec))
              (set! (-> v1-4 prim-core collide-with) (collide-spec))
              )
            0
            #f
            )
          )
        )
       (else
         #f
         )
       )
     )
    (('end-task)
     (let ((v0-0 (the-as object (logclear (-> this flags) (citizen-flag persistent)))))
       (set! (-> this flags) (the-as citizen-flag v0-0))
       v0-0
       )
     )
    (else
      ((method-of-type citizen general-event-handler) this arg0 arg1 arg2 arg3)
      )
    )
  )

(defmethod traffic-danger-init! ((this citizen-enemy))
  (let ((a1-0 (new 'stack-no-clear 'traffic-danger-info)))
    (set! (-> a1-0 sphere quad) (-> this root trans quad))
    (set! (-> a1-0 sphere r) 40960.0)
    (set! (-> a1-0 velocity quad) (-> this root transv quad))
    (set! (-> a1-0 notify-radius) 122880.0)
    (set! (-> a1-0 danger-level) 1.0)
    (set! (-> a1-0 decay-rate) 0.0)
    (set! (-> a1-0 flags) (traffic-danger-flags tdf0))
    (set! (-> a1-0 danger-type) (traffic-danger-type tdt7))
    (set! (-> a1-0 handle) (process->handle this))
    (add-danger (-> this controller traffic) a1-0)
    )
  0
  (none)
  )

(defmethod citizen-enemy-method-202 ((this citizen-enemy))
  (let ((s5-0 (new 'stack-no-clear 'vector)))
    (set! (-> s5-0 quad) (-> this root trans quad))
    (set! (-> s5-0 w) 122880.0)
    (let ((s4-0 (the-as process-drawable #f)))
      (let ((f30-0 122880.0))
        (let ((s3-0 (new 'stack-no-clear 'array 'collide-shape 64)))
          (countdown (s2-0 (fill-actor-list-for-sphere *actor-hash* (the-as sphere s5-0) s3-0 64))
            (let* ((s1-0 (-> s3-0 s2-0))
                   (a0-6 (if (type? s1-0 collide-shape)
                             s1-0
                             )
                         )
                   )
              (when a0-6
                (let* ((s0-0 (-> a0-6 process))
                       (s1-1 (if (type? s0-0 process-focusable)
                                 s0-0
                                 )
                             )
                       )
                  (when (and s1-1
                             (!= this s1-1)
                             (not (focus-test? (the-as process-focusable s1-1) inactive))
                             (not (focus-test? (the-as process-focusable s1-1) disable))
                             (not (logtest? (process-mask enemy) (-> s1-1 mask)))
                             (not (logtest? (process-mask crate) (-> s1-1 mask)))
                             (not (logtest? (process-mask vehicle) (-> s1-1 mask)))
                             s1-1
                             (not (logtest? (-> (the-as process-focusable s1-1) focus-status) (focus-status disable dead ignore grabbed)))
                             )
                    (let ((f0-1 (vector-vector-xz-distance (-> this root trans) (-> s1-1 root trans))))
                      (when (or (not s4-0) (< f0-1 f30-0))
                        (set! s4-0 s1-1)
                        (set! f30-0 f0-1)
                        )
                      )
                    )
                  )
                )
              )
            )
          )
        (if (and *target* (< (vector-vector-distance (target-pos 0) s5-0) f30-0))
            (set! s4-0 *target*)
            )
        )
      (when s4-0
        (try-update-focus (-> this focus) (the-as process-focusable s4-0) this)
        (go-hostile this)
        )
      )
    )
  0
  (none)
  )

(defstate active (citizen-enemy)
  :virtual #t
  :code (behavior ()
    (ja-channel-push! 1 (seconds 0.075))
    (let ((f30-0 (rnd-float-range self 0.8 1.2)))
      (until #f
        (ja-no-eval :group! (-> self draw art-group data (-> self enemy-info walk-anim))
                    :num! (seek! max f30-0)
                    :frame-num 0.0
                    )
        (until (ja-done? 0)
          (suspend)
          (ja :num! (seek! max f30-0))
          )
        )
      )
    #f
    )
  )

(defstate inactive (citizen-enemy)
  :virtual #t
  :enter (behavior ()
    (when (-> self minimap)
      (logior! (-> self minimap flags) (minimap-flag fade-out))
      (set! (-> self minimap) #f)
      )
    (let ((t9-0 (-> (method-of-type citizen inactive) enter)))
      (if t9-0
          (t9-0)
          )
      )
    )
  )

(defmethod citizen-init! ((this citizen-enemy))
  "Initialize [[citizen]] defaults."
  (let ((t9-0 (method-of-type citizen citizen-init!)))
    (t9-0 this)
    )
  (if (-> this skel effect)
      (logior! (-> this skel effect flags) (effect-control-flag ecf0))
      )
  (logior! (-> this mask) (process-mask enemy))
  (reset-to-collide-spec (-> this focus) (collide-spec jak civilian player-list bot-targetable jak-vehicle))
  (let ((v1-12 (-> this nav)))
    (set! (-> v1-12 sphere-mask) (the-as uint #x800e8))
    )
  0
  (set! (-> this anim-shuffle) (-> this enemy-info walk-anim))
  (set! (-> this anim-walk) (-> this enemy-info walk-anim))
  (set! (-> this speed-walk) (-> this enemy-info walk-travel-speed))
  (set! (-> this dist-walk-anim) (-> this enemy-info walk-travel-speed))
  (set! (-> this anim-run) (-> this enemy-info run-anim))
  (set! (-> this dist-run-anim) (-> this enemy-info run-travel-speed))
  (set! (-> this speed-run) (-> this enemy-info walk-travel-speed))
  (set! (-> this fated-time) 0)
  (logior! (-> this enemy-flags) (enemy-flag vulnerable vulnerable-backup))
  (logior! (-> this focus-status) (focus-status dangerous))
  (logior! (-> this enemy-flags) (enemy-flag dangerous-backup))
  (logior! (-> this enemy-flags) (enemy-flag trackable trackable-backup))
  (logclear! (-> this focus-status) (focus-status dead))
  (logior! (-> this mask) (process-mask collectable))
  (logior! (-> this enemy-flags) (enemy-flag attackable-backup))
  (if (not (-> this minimap))
      (set! (-> this minimap) (add-icon! *minimap* this (the-as uint 70) (the-as int #f) (the-as vector #t) 0))
      )
  (ja-channel-set! 0)
  0
  (none)
  )

(defmethod kill-prefer-falling ((this citizen-enemy))
  "If available in `enemy-info`, [[go]] to the [[die-falling]] state, if not, [[die]]"
  ((method-of-type nav-enemy kill-prefer-falling) this)
  )

(defmethod go-hostile ((this citizen-enemy))
  (if (not (and (-> this next-state) (= (-> this next-state name) 'hostile)))
      (go (method-of-object this hostile))
      )
  )

(defmethod go-stare ((this citizen-enemy))
  (go (method-of-object this active))
  )
