flora-search-aurora/dialogue.lisp
2023-06-19 08:47:45 -05:00

130 lines
4.7 KiB
Common Lisp
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;;;; Copyright © 2023, Jaidyn Ann <jadedctrl@posteo.at>
;;;;
;;;; This program is free software: you can redistribute it and/or
;;;; modify it under the terms of the GNU General Public License as
;;;; published by the Free Software Foundation, either version 3 of
;;;; the License, or (at your option) any later version.
;;;;
;;;; This program is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;;; GNU General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU General Public License
;;;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;;; FLORA-SEARCH-AURORA.OVERWORLD
;;;; All game-functions and data relating to the “overworld” (that is,
;;;; the primary gameplay, the RPG-ish-ish bits).
(defpackage :flora-search-aurora.dialogue
(:nicknames :fsa.d :dialogue)
(:use :cl
:flora-search-aurora.overworld :flora-search-aurora.ui :flora-search-aurora.input)
(:export #:dialogue-state #:say))
(in-package :flora-search-aurora.dialogue)
;;; ———————————————————————————————————
;;; Dialogue-generation DSL (sorta)
;;; ———————————————————————————————————
(defun dialogue (&rest dialogue-tree)
(reduce (lambda (a b) (append a b))
dialogue-tree))
(defun say (speaker text)
(list
(list :speaker speaker :text text :face 'talking-face)
(car (face speaker 'normal-face))))
(defun mumble (speaker text)
(list
(list :speaker speaker :text text)))
(defun face (speaker face)
(list
(list :speaker speaker :face face)))
;;; ———————————————————————————————————
;;; Dialogue logic
;;; ———————————————————————————————————
(defun pressed-enter-p ()
(and (listen)
(eq (getf (normalize-char-plist (read-char-plist)) :char)
#\return)))
(defun appropriate-face (map speaker face)
(let ((talking-face (getf-entity-data map speaker :talking-face))
(normal-face (getf-entity-data map speaker :normal-face)))
(cond ((and (eq face 'talking-face)
talking-face)
talking-face)
((and (eq face 'normal-face)
normal-face)
normal-face)
((stringp face)
face))))
(defun dialogue-state-update (dialogue-list map)
"The logic/input-processing helper function for DIALOGUE-STATE."
(let* ((speaker (intern (string-upcase (getf (car dialogue-list) :speaker))))
(new-face (appropriate-face map speaker
(getf (car dialogue-list) :face))))
;; Replace the face, when appropriate.
(when new-face
(setf (getf-entity-data map speaker :face) new-face)))
;; Progress the dialogue as appropriate.
(let ((text (getf (car dialogue-list) :text)))
(cond ((or (pressed-enter-p)
(not text))
(if (cdr dialogue-list)
(list :dialogue (cdr dialogue-list) :map map)
(values nil
(list :map map))))
((cdr dialogue-list)
(list :dialogue dialogue-list :map map))
('t
(values nil
(list :map map))))))
;;; ———————————————————————————————————
;;; Dialogue drawing
;;; ———————————————————————————————————
(defun dialogue-state-draw (matrix dialogue-list)
"Draw the dialogue where appropriate.
Helper function for DIALOGUE-STATE."
(let ((text (getf (car dialogue-list) :text)))
(when text
(render-line matrix text 0 0))))
;;; ———————————————————————————————————
;;; Dialogue loop
;;; ———————————————————————————————————
(defun dialogue-state (matrix &key dialogue map)
"Render a bit of dialogue to the screen, using :FLORA-SEARCH-AURORA.OVERWORLD
entities as the speakers. Dialogue should be in the format:
((:text \"Hello, papa!\"
:speaker \"son\" ;; The entitys ID (if applicable)
:face \"owo\") ;; If you want their face to change
(:face \"=w=\" :speaker 'son) ;; change their face back when done talking
(:text \"Hello, you little gremlin! <3\"
:speaker \"papa\"
...))
A state-function for use with STATE-LOOP."
(sleep .02)
(dialogue-state-draw matrix dialogue)
(dialogue-state-update dialogue map))