combat.lisp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. ;;; Combat systems implemented here
  2. (defvar *combat-menu-options-display* "
  3. Actions:
  4. 1 | Attack | a
  5. 2 | Regen. Shields | r
  6. 3 | Overcharge Gun | o
  7. 4 | Attempt to flee | f
  8. ")
  9. ;; Combat options:
  10. ;; Attack (with specific weapon)
  11. ;; Regen shields
  12. ;; - (add value to rep-shield-val at cost of overcharing
  13. ;; - (overcharing can cause warp field to go into low-power)
  14. ;; - (overcharging can cause hull damage)
  15. ;; Overcharge gun at cost of overcharing reactor
  16. ;; Attempt to flee into the warp
  17. ;; - (requires full power / overcharged reactor)
  18. ;; - (can also cause reactor to go low power, which removes ability to regen/overcharge)
  19. ;; TODO - Combat always pops off first enemy from the enemy-ships list
  20. (defun combat-loop (sector)
  21. "The main loop responsbile for resolving combat situations"
  22. (let ((combat-state T))
  23. (loop
  24. while combat-state
  25. do (progn
  26. (format T *combat-menu-options-display*)
  27. (let ((top-level-selection (prompt-read "Enter a selection: ")))
  28. (case (read-from-string top-level-selection)
  29. (1 (progn ;; There is a way to collapse this progn into a single
  30. ;; function call, but it's arguably a lot less readable
  31. (let* ((weapon (weapon-select-menu (player-ship-obj sector)))
  32. (attack-result (player-ship-attack
  33. (player-ship-obj sector)
  34. (first (enemy-ships sector))
  35. weapon)))
  36. (if attack-result
  37. (progn
  38. (setf (enemy-ships sector) (delete attack-result (enemy-ships sector)))
  39. (format T "Your opponent has been vanquished!~%")
  40. (top-level-game-menu))))
  41. (enemy-turn sector)))))))))
  42. (defun enemy-turn (sector)
  43. "Perform AI actions based on AI-type associated with enemy ship"
  44. (case (ai-type (first (enemy-ships sector)))
  45. (aggressive (progn
  46. ;; This AI will just stupidly attack until it's out of ammo
  47. ;; If it runs out of ammo, it will try and flee
  48. ))
  49. (fearful ())
  50. (unpredicatable ())))
  51. ;; Select weapon
  52. ;; Determine if hit (% chance?)
  53. ;; If hit resolve shield
  54. ;; -- IF Shields down (ie shield damage causes target shield value to be 0)
  55. ;; -- Apply hull damage
  56. ;; ELSE
  57. ;; -- Decrement shield value per value of shield dmg
  58. (defun weapon-select-menu (player-ship-obj)
  59. (let ((weapon-list (loop for weapon in (weapons player-ship-obj)
  60. for i from 0
  61. collect (list i
  62. (name weapon)
  63. (shield-dmg weapon)
  64. (hull-dmg weapon)
  65. (ammo-cost weapon)))))
  66. (format T "~%Available Ammo: ~A~%~%" (ammo (inventory player-ship-obj)))
  67. (format T "Available Weapons: ~%")
  68. (format-table T weapon-list :column-label '("Number" "Name" "Shield Damage" "Hull Damage" "Ammo Cost"))
  69. (let ((selection (prompt-read "Select a weapon to via the number column: ")))
  70. (format t "Selection was number: ~A and weapon name: ~A~%~%"
  71. selection
  72. (second (nth (parse-integer selection) weapon-list)))
  73. (return-from weapon-select-menu (nth (parse-integer selection) (weapons player-ship-obj))))))
  74. (defun calculate-shield-damage (attacker-obj target-obj attacker-weapon)
  75. "Given a target and a weapon, return a value that the
  76. targets shield value should now be set as"
  77. (let ((new-shield-value (- (rep-shield-val target-obj) (shield-dmg attacker-weapon))))
  78. (setf (ammo (inventory attacker-obj)) (- (ammo (inventory attacker-obj)) (ammo-cost attacker-weapon)))
  79. (if (>= 0 new-shield-value)
  80. (return-from calculate-shield-damage 0)
  81. (return-from calculate-shield-damage new-shield-value))))
  82. (defun calculate-hull-damage (attacker-obj target-obj attacker-weapon)
  83. "Given a target and a weapon, return a value that the
  84. targets hull value should now be set as"
  85. (let ((new-hull-value (- (armor-val target-obj) (hull-dmg attacker-weapon))))
  86. (setf (ammo (inventory attacker-obj)) (- (ammo (inventory attacker-obj)) (ammo-cost attacker-weapon)))
  87. (if (>= 0 new-hull-value)
  88. (return-from calculate-hull-damage 0)
  89. (return-from calculate-hull-damage new-hull-value))))
  90. (defun player-ship-attack (player-ship-obj target-obj attacker-weapon)
  91. "Given a target and the attackers chosen weapon resolve the combat by
  92. calculating shield/hull damage and resolving resources. If the target
  93. is reduced to 0 hull points, return the target-obj and end combat"
  94. (if (> (ammo-cost attacker-weapon) (ammo (inventory player-ship-obj)))
  95. (progn
  96. (format T "You don't have enough ammo to fire your ~A gun!~%" (name attacker-weapon))
  97. (return-from player-ship-attack NIL)))
  98. (let ((calculated-shield-damage (calculate-shield-damage player-ship-obj target-obj attacker-weapon))
  99. (calculated-hull-damage (calculate-hull-damage player-ship-obj target-obj attacker-weapon)))
  100. (setf (rep-shield-val target-obj) calculated-shield-damage) ;; Resolve shield hit
  101. (if (> (rep-shield-val target-obj) 0)
  102. (format T "You hit their repulsor shields for ~A !~%" (shield-dmg attacker-weapon)))
  103. (if (= 0 calculated-shield-damage)
  104. (progn
  105. (format T "Their shields are down!~%")
  106. (setf (armor-val target-obj) calculated-hull-damage)
  107. (format T "You hit their hull for ~A !~%" (hull-dmg attacker-weapon))))
  108. (if (= 0 calculated-hull-damage)
  109. (progn
  110. (format T "Their hulls been breached! You've won the exchange!~%")
  111. (return-from player-ship-attack target-obj))
  112. NIL)))
  113. (defun display-weapons (player-ship-obj)
  114. "Given player ship, display weapons and associated attributes"
  115. (let* ((weapons (weapons player-ship-obj))
  116. (weapon-list (loop for weapon in weapons
  117. collect (list (name weapon)
  118. (shield-dmg weapon)
  119. (hull-dmg weapon)
  120. (ammo-cost weapon)))))
  121. (format T "~%WEAPON DETAILS~%")
  122. (format-table T weapon-list :column-label '("Name" "Shield Damage" "Hull Damage" "Ammo Cost"))))