Moves trigger progress tracks
Also a number of bug fixes and minor cosmetic changes ... of course.
This commit is contained in:
parent
b5239362d5
commit
9c8b030633
9 changed files with 226 additions and 126 deletions
182
README.org
182
README.org
|
@ -313,16 +313,16 @@ We assume you have created an org-file, and the /template/ will just append some
|
||||||
(setq name (rpgdm-tables-choose "name/ironlander")))
|
(setq name (rpgdm-tables-choose "name/ironlander")))
|
||||||
|
|
||||||
(let ((frmt (seq-random-elt '("* The Adventures of %s"
|
(let ((frmt (seq-random-elt '("* The Adventures of %s"
|
||||||
"* The Journeys of %s"
|
"* The Journeys of %s"
|
||||||
"* %s, an Epic Saga"
|
"* %s, an Epic Saga"
|
||||||
"* The Epic of %s"
|
"* The Epic of %s"
|
||||||
"* Travels of %s"))))
|
"* Travels of %s"))))
|
||||||
(goto-char (point-max))
|
(goto-char (point-max))
|
||||||
(insert "# Local Variables:
|
;; (insert "# Local Variables: # eval: (progn (require 'rpgdm-ironsworn) (rpgdm-mode)) # End: ")
|
||||||
# eval: (progn (require 'rpgdm-ironsworn) (rpgdm-mode))
|
(insert (format frmt name))
|
||||||
# End:
|
(insert "
|
||||||
")
|
|
||||||
(insert (format frmt name))))
|
")))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
**** Character Assets
|
**** Character Assets
|
||||||
We store the assets in a collection of org files in the [[file:assets/][assets]] directory. We'd like the user to choose an asset, so we convert a filename into something nicer to read based on extracting the /description/ from the /filename/, for instance, =:
|
We store the assets in a collection of org files in the [[file:assets/][assets]] directory. We'd like the user to choose an asset, so we convert a filename into something nicer to read based on extracting the /description/ from the /filename/, for instance, =:
|
||||||
|
@ -375,7 +375,7 @@ We can use a function that interactively queries the user for an asset and retur
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(defun rpgdm-ironsworn--pick-character-asset ()
|
(defun rpgdm-ironsworn--pick-character-asset ()
|
||||||
"Completing read for an Ironsworn asset."
|
"Completing read for an Ironsworn asset."
|
||||||
(let ((choice (completing-read "Which asset? " (rpgdm-ironsworn-character-assets))))
|
(let ((choice (completing-read "Which asset: " (rpgdm-ironsworn-character-assets))))
|
||||||
(thread-first choice
|
(thread-first choice
|
||||||
(assoc rpgdm-ironsworn-character-assets 'equal)
|
(assoc rpgdm-ironsworn-character-assets 'equal)
|
||||||
(cdr))))
|
(cdr))))
|
||||||
|
@ -387,12 +387,24 @@ Let the user choose an asset and insert it into the file at the current point. W
|
||||||
(defun rpgdm-ironsworn-insert-character-asset (asset)
|
(defun rpgdm-ironsworn-insert-character-asset (asset)
|
||||||
"Choose and insert the contents of an ASSET in the current buffer."
|
"Choose and insert the contents of an ASSET in the current buffer."
|
||||||
(interactive (list (rpgdm-ironsworn--pick-character-asset)))
|
(interactive (list (rpgdm-ironsworn--pick-character-asset)))
|
||||||
|
(when rpgdm-ironsworn-new-character (goto-char (point-max)))
|
||||||
(let ((file (if (consp asset) (cdr asset) asset)))
|
(let ((file (if (consp asset) (cdr asset) asset)))
|
||||||
(insert-file-contents file nil)
|
(ignore-errors
|
||||||
|
(insert-file-contents file nil))))
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
(when (called-interactively-p)
|
Hrm. Perhaps we just want to /look/ at an asset before inserting it, similar to how we show moves, we could open the asset in another buffer window.
|
||||||
(when (y-or-n-p "Insert another asset? ")
|
|
||||||
(call-interactively 'rpgdm-ironsworn-insert-character-asset)))))
|
#+BEGIN_SRC emacs-lisp
|
||||||
|
(defun rpgdm-ironsworn-show-character-asset (asset)
|
||||||
|
"Choose and insert the contents of an ASSET in the current buffer."
|
||||||
|
(interactive (list (rpgdm-ironsworn--pick-character-asset)))
|
||||||
|
(let ((asset-file (if (consp asset) (cdr asset) asset))
|
||||||
|
(orig-buf (window-buffer)))
|
||||||
|
(ignore-errors
|
||||||
|
(find-file-other-window asset-file)
|
||||||
|
(goto-char (point-min))
|
||||||
|
(pop-to-buffer orig-buf))))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
When you start a character, you choose three assets, but what if we choose them randomly from our asset list? Could be fun, however, I don't want duplicates, or two companions, or ... well, I may come up with more rules, but I codify those rules into a function that returns a list, if it is good, or =nil= otherwise:
|
When you start a character, you choose three assets, but what if we choose them randomly from our asset list? Could be fun, however, I don't want duplicates, or two companions, or ... well, I may come up with more rules, but I codify those rules into a function that returns a list, if it is good, or =nil= otherwise:
|
||||||
|
@ -479,15 +491,23 @@ Now we have a function that inserts the contents of three randomly chosen assets
|
||||||
Whew. We finally can have a function that queries the user about a new character and whether we should insert them randomly or let the user choose.... or do nothing at all.
|
Whew. We finally can have a function that queries the user about a new character and whether we should insert them randomly or let the user choose.... or do nothing at all.
|
||||||
|
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
|
(defun rpgdm-ironsworn-insert-character-assets ()
|
||||||
|
(ignore-errors
|
||||||
|
(call-interactively 'rpgdm-ironsworn-insert-character-asset))
|
||||||
|
(when (y-or-n-p "Insert another asset? ")
|
||||||
|
(rpgdm-ironsworn-insert-character-assets)))
|
||||||
|
|
||||||
(defun rpgdm-ironsworn--new-character-assets ()
|
(defun rpgdm-ironsworn--new-character-assets ()
|
||||||
"Insert the contents of three character assets from the assets directory."
|
"Insert the contents of three character assets from the assets directory."
|
||||||
(goto-char (point-max))
|
(goto-char (point-max))
|
||||||
(insert "\n** Assets\n")
|
(insert "\n** Assets\n")
|
||||||
(if (y-or-n-p "Would you like three random assets? ")
|
(if (y-or-n-p "Would you like three random assets? ")
|
||||||
(rpgdm-ironsworn-random-character-assets 3)
|
(rpgdm-ironsworn-random-character-assets 3)
|
||||||
(if (y-or-n-p "Would you like to choose your assets? ")
|
(if (y-or-n-p "Would you like to choose your assets? ")
|
||||||
(call-interactively 'rpgdm-ironsworn-insert-character-asset))))
|
(rpgdm-ironsworn-insert-character-assets))))
|
||||||
|
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
**** Character Stats
|
**** Character Stats
|
||||||
This function will query the user for all of the stats and other properties that we will need to store before we can play the game.
|
This function will query the user for all of the stats and other properties that we will need to store before we can play the game.
|
||||||
|
|
||||||
|
@ -505,13 +525,12 @@ This function will query the user for all of the stats and other properties that
|
||||||
(rpgdm-ironsworn-store-character-state stat 5))
|
(rpgdm-ironsworn-store-character-state stat 5))
|
||||||
(rpgdm-ironsworn-store-character-state 'momentum 2)
|
(rpgdm-ironsworn-store-character-state 'momentum 2)
|
||||||
|
|
||||||
(rpgdm-ironsworn-progress-create (read-string "What title should we give this new character's Epic vow? ") 1)
|
(rpgdm-ironsworn-progress-create (read-string "What title should we give this new character's Epic vow: ") 1)
|
||||||
(rpgdm-ironsworn-progress-create "Bonds" 1)
|
(rpgdm-ironsworn-progress-create "Bonds" 1)
|
||||||
(rpgdm-ironsworn-progress-mark "Bonds")
|
(rpgdm-ironsworn-progress-mark "Bonds")
|
||||||
(search-forward ":END:")
|
(next-line)
|
||||||
(end-of-line)
|
|
||||||
(insert "\n** Bonds\n")
|
(insert "\n** Bonds\n")
|
||||||
(insert (format " - Your home settlement of %s\n" (rpgdm-tables-choose "settlement/name"))))
|
(insert (format " - My home settlement of %s\n" (rpgdm-tables-choose "settlement/name"))))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
**** New Character Interface
|
**** New Character Interface
|
||||||
Do we choose the stats first, or the assets? Do we ask, or have two separate functions?
|
Do we choose the stats first, or the assets? Do we ask, or have two separate functions?
|
||||||
|
@ -521,6 +540,7 @@ Perhaps the clearest approach is to do both, create two process functions, and t
|
||||||
(defun rpgdm-ironsworn--new-character-stats-first (&optional name)
|
(defun rpgdm-ironsworn--new-character-stats-first (&optional name)
|
||||||
"Insert a new character template for character, NAME.
|
"Insert a new character template for character, NAME.
|
||||||
The character stats are first queried, and then assets inserted."
|
The character stats are first queried, and then assets inserted."
|
||||||
|
(goto-char (point-max))
|
||||||
(rpgdm-ironsworn--new-character-stats)
|
(rpgdm-ironsworn--new-character-stats)
|
||||||
(rpgdm-ironsworn--new-character-assets))
|
(rpgdm-ironsworn--new-character-assets))
|
||||||
|
|
||||||
|
@ -529,9 +549,10 @@ Perhaps the clearest approach is to do both, create two process functions, and t
|
||||||
The assets are inserted first, and then character stats are queried."
|
The assets are inserted first, and then character stats are queried."
|
||||||
;; Saving and restoring point, means the properties should be in the
|
;; Saving and restoring point, means the properties should be in the
|
||||||
;; correct, top-level position.
|
;; correct, top-level position.
|
||||||
(save-excursion
|
(let ((p (point)))
|
||||||
(rpgdm-ironsworn--new-character-assets))
|
(rpgdm-ironsworn--new-character-assets)
|
||||||
(rpgdm-ironsworn--new-character-stats))
|
(goto-char p)
|
||||||
|
(rpgdm-ironsworn--new-character-stats)))
|
||||||
|
|
||||||
(defun rpgdm-ironsworn-new-character (name order)
|
(defun rpgdm-ironsworn-new-character (name order)
|
||||||
"Interactively query the user for a new character's attribute.
|
"Interactively query the user for a new character's attribute.
|
||||||
|
@ -543,13 +564,19 @@ Perhaps the clearest approach is to do both, create two process functions, and t
|
||||||
(read-string "What is the new character's name? ")
|
(read-string "What is the new character's name? ")
|
||||||
(completing-read "What order should we build this? " '("Statistics first" "Assets first"))))
|
(completing-read "What order should we build this? " '("Statistics first" "Assets first"))))
|
||||||
|
|
||||||
|
(setq rpgdm-ironsworn-new-character t)
|
||||||
(rpgdm-ironsworn--new-character-template name)
|
(rpgdm-ironsworn--new-character-template name)
|
||||||
(if (equal order "Assets first")
|
(if (equal order "Assets first")
|
||||||
(rpgdm-ironsworn--new-character-assets-first)
|
(rpgdm-ironsworn--new-character-assets-first)
|
||||||
(rpgdm-ironsworn--new-character-stats-first))
|
(rpgdm-ironsworn--new-character-stats-first))
|
||||||
|
(setq rpgdm-ironsworn-new-character nil)
|
||||||
(message "Alright, the template is complete. Edit away!" name))
|
(message "Alright, the template is complete. Edit away!" name))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
|
The asset-insertion and other functions above act slightly differently during the initial character creating process, so we keep track of that with this variable:
|
||||||
|
#+BEGIN_SRC emacs-lisp
|
||||||
|
(defvar rpgdm-ironsworn-new-character nil "Are we in the process of creating a new character?")
|
||||||
|
#+END_SRC
|
||||||
*** Showing a Character Stats
|
*** Showing a Character Stats
|
||||||
Sure, you could open up the appropriate drawer to see a character's stats, but we could do better? An updated org table? A separate buffer? For the moment, I am just going to display it in the mini-buffer whenever I want to see it.
|
Sure, you could open up the appropriate drawer to see a character's stats, but we could do better? An updated org table? A separate buffer? For the moment, I am just going to display it in the mini-buffer whenever I want to see it.
|
||||||
|
|
||||||
|
@ -722,7 +749,7 @@ The =rpgdm-ironsworn-adjust-stat= function takes one of the four stats, like =
|
||||||
(:decrease (- curr numb))
|
(:decrease (- curr numb))
|
||||||
(:absolute numb)
|
(:absolute numb)
|
||||||
(t default))))
|
(t default))))
|
||||||
(message "Combining curr %d with %d with %s operator" curr numb oper)
|
;; (message "Combining curr %d with %d with %s operator" curr numb oper)
|
||||||
(rpgdm-ironsworn-store-character-state stat new)))
|
(rpgdm-ironsworn-store-character-state stat new)))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
|
@ -1106,6 +1133,8 @@ Now, let's do the Move interface. We need to load the documentation, and retriev
|
||||||
The =rpgdm-ironsworn--make-move= call does something based on the properties stored in the file:
|
The =rpgdm-ironsworn--make-move= call does something based on the properties stored in the file:
|
||||||
|
|
||||||
- If nil, do nothing
|
- If nil, do nothing
|
||||||
|
- If one or more stats, separated by a =|=, do each stat in series, e.g. =track|heart=
|
||||||
|
- If single stat that is =track=, call =rpgdm-ironsworn-progress-create=
|
||||||
- If single stat that is =progress=, call =rpgdm-ironsworn-progress-roll=
|
- If single stat that is =progress=, call =rpgdm-ironsworn-progress-roll=
|
||||||
- If single stat, call =rpgdm-ironsworn-roll-stat= with that stat as a symbol, e.g. ='wits=
|
- If single stat, call =rpgdm-ironsworn-roll-stat= with that stat as a symbol, e.g. ='wits=
|
||||||
- If first entry is =>=, call =rpgdm-ironsworn-roll-stat= with the largest of the listed character's stats
|
- If first entry is =>=, call =rpgdm-ironsworn-roll-stat= with the largest of the listed character's stats
|
||||||
|
@ -1116,19 +1145,29 @@ Seems like a job for =cond=:
|
||||||
|
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(defun rpgdm-ironsworn--make-move (move-props)
|
(defun rpgdm-ironsworn--make-move (move-props)
|
||||||
"Query user for rolls based on the MOVE-PROPS."
|
"Query user for rolls based on one or series of MOVE-PROPS."
|
||||||
(let* ((props (s-split " " (or move-props "")))
|
(if (string-match (rx (group (1+ alpha)) "|" (group (1+ any))) move-props)
|
||||||
(count (seq-length props))
|
(let ((first (match-string 1 move-props))
|
||||||
(stats (seq-filter (lambda (s) (string-match (rx (one-or-more alpha)) s)) props))
|
(rest (match-string 2 move-props)))
|
||||||
(first (first props)))
|
(rpgdm-ironsworn--make-single-move first)
|
||||||
(cond
|
(rpgdm-ironsworn--make-move rest))
|
||||||
((seq-empty-p stats) nil)
|
(rpgdm-ironsworn--make-single-move move-props)))
|
||||||
((equal first "progress") (call-interactively 'rpgdm-ironsworn-progress-roll))
|
|
||||||
((= count 1) (rpgdm-ironsworn-roll-with first))
|
(defun rpgdm-ironsworn--make-single-move (move-props)
|
||||||
((equal first ">") (rpgdm-ironsworn-roll-best stats))
|
"Query user for rolls based on one MOVE-PROPS."
|
||||||
(t (rpgdm-ironsworn-roll-stat
|
(let* ((props (s-split " " (or move-props "")))
|
||||||
(completing-read "Stat Choice: " stats)
|
(count (seq-length props))
|
||||||
(read-string "Modifier: "))))))
|
(stats (seq-filter (lambda (s) (string-match (rx (one-or-more alpha)) s)) props))
|
||||||
|
(first (first props)))
|
||||||
|
(cond
|
||||||
|
((seq-empty-p stats) nil)
|
||||||
|
((equal first "track") (call-interactively 'rpgdm-ironsworn-progress-create))
|
||||||
|
((equal first "progress") (call-interactively 'rpgdm-ironsworn-progress-roll))
|
||||||
|
((= count 1) (rpgdm-ironsworn-roll-with first))
|
||||||
|
((equal first ">") (rpgdm-ironsworn-roll-best stats))
|
||||||
|
(t (rpgdm-ironsworn-roll-stat
|
||||||
|
(completing-read "Stat Choice: " stats)
|
||||||
|
(read-string "Modifier: "))))))
|
||||||
|
|
||||||
(defun rpgdm-ironsworn-roll-with (stat)
|
(defun rpgdm-ironsworn-roll-with (stat)
|
||||||
"Roll against a character STAT, as a string, and prompt for modifier.
|
"Roll against a character STAT, as a string, and prompt for modifier.
|
||||||
|
@ -1228,7 +1267,7 @@ Adding a progress to a character amounts to an arbitrary name, and the number of
|
||||||
(title (org-get-heading))
|
(title (org-get-heading))
|
||||||
(option '(("At the same level as a sibling?" same-level)
|
(option '(("At the same level as a sibling?" same-level)
|
||||||
("As a subheading to this?" subheading)
|
("As a subheading to this?" subheading)
|
||||||
("No new heading. Re-use this." no))))
|
("No new heading. Re-use this?" no))))
|
||||||
|
|
||||||
(when (called-interactively-p)
|
(when (called-interactively-p)
|
||||||
(cl-case (completing-read-value "Create a new heading? " option)
|
(cl-case (completing-read-value "Create a new heading? " option)
|
||||||
|
@ -1517,7 +1556,7 @@ With these properties in place, we can now do a much better job with the [[file:
|
||||||
(interactive (list (completing-read "Stat Choice: "
|
(interactive (list (completing-read "Stat Choice: "
|
||||||
'("wits" "shadow" "edge"))))
|
'("wits" "shadow" "edge"))))
|
||||||
(let ((table-name (format "delve/weak-hit/%s" stat)))
|
(let ((table-name (format "delve/weak-hit/%s" stat)))
|
||||||
(message "Rolling on %s" table-name)
|
;; (message "Rolling on %s" table-name)
|
||||||
(rpgdm-tables-choose table-name)))
|
(rpgdm-tables-choose table-name)))
|
||||||
|
|
||||||
(defun rpgdm-ironsworn-delve-the-depths-weak-edge ()
|
(defun rpgdm-ironsworn-delve-the-depths-weak-edge ()
|
||||||
|
@ -1546,14 +1585,19 @@ With the theme and domain properties in place, we can now do a much better job w
|
||||||
properties in the current org file, and rolls on the appropriate
|
properties in the current org file, and rolls on the appropriate
|
||||||
chart."
|
chart."
|
||||||
(let* ((theme (rpgdm-ironsworn-character-stat 'site-theme))
|
(let* ((theme (rpgdm-ironsworn-character-stat 'site-theme))
|
||||||
(domain (rpgdm-ironsworn-character-stat 'site-domain))
|
(domain (rpgdm-ironsworn-character-stat 'site-domain))
|
||||||
(danger (rpgdm-tables-choose "danger")))
|
(danger (rpgdm-tables-choose "danger")))
|
||||||
(cond
|
(cond
|
||||||
((equal danger "Check the theme card.")
|
((equal danger "Check the theme card.")
|
||||||
(rpgdm-tables-choose (format "danger/theme/%s" theme)))
|
(rpgdm-tables-choose (format "danger/theme/%s" theme)))
|
||||||
|
|
||||||
((equal danger "Check the domain card.")
|
((equal danger "Check the domain card.")
|
||||||
(rpgdm-tables-choose (format "danger/domain/%s" theme)))
|
(rpgdm-tables-choose (format "danger/domain/%s" domain)))
|
||||||
|
|
||||||
|
((s-starts-with? "Roll twice" danger)
|
||||||
|
(format "%s <AND> %s"
|
||||||
|
(rpgdm-ironsworn--reveal-a-danger)
|
||||||
|
(rpgdm-ironsworn--reveal-a-danger)))
|
||||||
|
|
||||||
(t danger))))
|
(t danger))))
|
||||||
|
|
||||||
|
@ -1791,8 +1835,9 @@ Can a Hydra call a hydra? Let's more all the special oracle and progress functio
|
||||||
("A" rpgdm-ironsworn-insert-character-asset "insert new asset")
|
("A" rpgdm-ironsworn-insert-character-asset "insert new asset")
|
||||||
("a" rpgdm-ironsworn-asset-stat-adjust "adjust asset stat")
|
("a" rpgdm-ironsworn-asset-stat-adjust "adjust asset stat")
|
||||||
("n" rpgdm-ironsworn-asset-stat-create "new asset stat")
|
("n" rpgdm-ironsworn-asset-stat-create "new asset stat")
|
||||||
("s" rpgdm-ironsworn-asset-stat-show "show")
|
("s" rpgdm-ironsworn-asset-stat-show "show asset stat")
|
||||||
("r" rpgdm-ironsworn-asset-stat-roll "roll asset as modifier"))
|
("r" rpgdm-ironsworn-asset-stat-roll "roll asset as modifier")
|
||||||
|
("v" rpgdm-ironsworn-show-character-asset "view asset"))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
I'd like to repurpose the RPGDM Hydra to be more specific to Ironsworn, so this has both the instructions on how to use it and the key-to-function mapping. A pattern I would like to follow is that a uppercase letters indicate altering something.
|
I'd like to repurpose the RPGDM Hydra to be more specific to Ironsworn, so this has both the instructions on how to use it and the key-to-function mapping. A pattern I would like to follow is that a uppercase letters indicate altering something.
|
||||||
|
@ -1811,7 +1856,7 @@ I would also like pairings where lowercase ~p~ rolls against Supply, but a ~P~ c
|
||||||
But we roll some of these more than others, especially since "moves" does most of the work.
|
But we roll some of these more than others, especially since "moves" does most of the work.
|
||||||
|
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(defhydra hydra-rpgdm (:color blue :hint nil)
|
(defhydra hydra-rpgdm (:color pink :hint nil)
|
||||||
"
|
"
|
||||||
^Dice^ 0=d100 1=d10 6=d6 ^Roll/Adjust^ ^Oracles/Tables^ ^Moving/Editing^ ^Messages^
|
^Dice^ 0=d100 1=d10 6=d6 ^Roll/Adjust^ ^Oracles/Tables^ ^Moving/Editing^ ^Messages^
|
||||||
------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
@ -1839,9 +1884,9 @@ But we roll some of these more than others, especially since "moves" does most o
|
||||||
|
|
||||||
("O" rpgdm-tables-load) ("c" rpgdm-tables-choose) ("C" rpgdm-tables-choose :color pink)
|
("O" rpgdm-tables-load) ("c" rpgdm-tables-choose) ("C" rpgdm-tables-choose :color pink)
|
||||||
|
|
||||||
("d" hydra-rpgdm-delve/body)
|
("d" hydra-rpgdm-delve/body :color blue)
|
||||||
("p" hydra-rpgdm-progress/body)
|
("p" hydra-rpgdm-progress/body :color blue)
|
||||||
("a" hydra-rpgdm-assets/body)
|
("a" hydra-rpgdm-assets/body :color blue)
|
||||||
|
|
||||||
("o" ace-link) ("N" org-narrow-to-subtree) ("W" widen)
|
("o" ace-link) ("N" org-narrow-to-subtree) ("W" widen)
|
||||||
("K" scroll-down :color pink) ("J" scroll-up :color pink)
|
("K" scroll-down :color pink) ("J" scroll-up :color pink)
|
||||||
|
@ -1857,6 +1902,7 @@ But we roll some of these more than others, especially since "moves" does most o
|
||||||
("0" rpgdm-roll-d100 :color pink)
|
("0" rpgdm-roll-d100 :color pink)
|
||||||
("1" rpgdm-roll-d10 :color pink)
|
("1" rpgdm-roll-d10 :color pink)
|
||||||
("6" rpgdm-roll-d6 :color pink)
|
("6" rpgdm-roll-d6 :color pink)
|
||||||
|
("RET" evil-open-below :color blue)
|
||||||
("q" nil "quit") ("<f6>" nil))
|
("q" nil "quit") ("<f6>" nil))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
** Org Interface
|
** Org Interface
|
||||||
|
@ -1868,10 +1914,13 @@ Couple of patterns:
|
||||||
- We set progress, on the other hand, only once in the file, and update it
|
- We set progress, on the other hand, only once in the file, and update it
|
||||||
- Choosing progress to mark will only be available by walking "up" the tree, as we view progress in sibling trees as /completed/.
|
- Choosing progress to mark will only be available by walking "up" the tree, as we view progress in sibling trees as /completed/.
|
||||||
*** Store Character State
|
*** Store Character State
|
||||||
We set all of these values in the current tree using [[help:org-set-property][org-set-property]], as =rpgdm-ironsworn-store-character-state= will function as a wrapper around it:
|
|
||||||
|
I may make a distinction between different types of character stats, as some, like the “Iron” attribute is a stat a character always has, and doesn’t change. Others, like “health” changes, but never really goes away. Still others, my be temporary, and only needing to be accessible for /part/ of an document and would go away when we create a new heading at the same level.
|
||||||
|
|
||||||
|
To make a temporary stat, we set its values in the current document tree using [[help:org-set-property][org-set-property]], and the function =rpgdm-ironsworn-store-character-temp-state= its function.
|
||||||
|
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(defun rpgdm-ironsworn-store-character-state (stat value)
|
(defun rpgdm-ironsworn-store-character-temp-state (stat value)
|
||||||
"Store the VALUE of a character's STAT in the current org tree property.
|
"Store the VALUE of a character's STAT in the current org tree property.
|
||||||
Note that STAT should be a symbol, like `supply' and VALUE should be a
|
Note that STAT should be a symbol, like `supply' and VALUE should be a
|
||||||
number, but doesn't have to be."
|
number, but doesn't have to be."
|
||||||
|
@ -1879,11 +1928,14 @@ We set all of these values in the current tree using [[help:org-set-property][or
|
||||||
(when (numberp value)
|
(when (numberp value)
|
||||||
(setq value (number-to-string value)))
|
(setq value (number-to-string value)))
|
||||||
(org-set-property prop value)))
|
(org-set-property prop value)))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
Oh, but what if we want to store a value for a /default stat/? This needs to go to the top-level header first:
|
But since most character stats do not simply /go away/ but are constantly in flux, and these need to be stored at the top-most level of the org file, so the function, =rpgdm-ironsworn-store-character-state=, walks up the heading tree until it reaches the top.
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
(defun rpgdm-ironsworn-store-default-character-state (stat value)
|
(defun rpgdm-ironsworn-store-character-state (stat value)
|
||||||
"Store the VALUE of a character's STAT in the top-level org tree property.
|
"Store the VALUE of a character's STAT in the top-level org tree property.
|
||||||
Note that STAT should be a symbol, like `supply' and VALUE should be a
|
Note that STAT should be a symbol, like `supply' and VALUE should be a
|
||||||
number, but doesn't have to be."
|
number, but doesn't have to be."
|
||||||
|
@ -1891,7 +1943,14 @@ Oh, but what if we want to store a value for a /default stat/? This needs to go
|
||||||
(org-up-heading)
|
(org-up-heading)
|
||||||
(while (> (org-heading-level) 1)
|
(while (> (org-heading-level) 1)
|
||||||
(org-up-heading))
|
(org-up-heading))
|
||||||
(rpgdm-ironsworn-store-character-state stat value)))
|
(rpgdm-ironsworn-store-character-temp-state stat value)))
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
Attributes (stats that never change) are actually stored just like any other stat (at least, at the moment), so this “default” function name is an alias for the normal process of storing state:
|
||||||
|
#+BEGIN_SRC emacs-lisp
|
||||||
|
(defalias 'rpgdm-ironsworn-store-default-character-state
|
||||||
|
'rpgdm-ironsworn-store-character-state)
|
||||||
|
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
*** Property Key Conversions and Predicates
|
*** Property Key Conversions and Predicates
|
||||||
Loading state means looking at properties, and we distinguish Ironsworn-specific with a few functions:
|
Loading state means looking at properties, and we distinguish Ironsworn-specific with a few functions:
|
||||||
|
@ -1964,7 +2023,7 @@ Since [[help:org-up-element][org-up-element]]’s behavior has changed, and [[he
|
||||||
(defun org-up-heading ()
|
(defun org-up-heading ()
|
||||||
"Move the point to next parent heading, unless already at the top-level."
|
"Move the point to next parent heading, unless already at the top-level."
|
||||||
(if (= 0 (org-heading-level))
|
(if (= 0 (org-heading-level))
|
||||||
(outline-up-heading 0)
|
(org-previous-visible-heading 1)
|
||||||
(outline-up-heading 1)))
|
(outline-up-heading 1)))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
|
@ -1991,7 +2050,6 @@ Enough chit-chat, let's write this function. While we are at it, let's convert t
|
||||||
(when (rpgdm-ironsworn--property-p k)
|
(when (rpgdm-ironsworn--property-p k)
|
||||||
(let ((key (key-convert k))
|
(let ((key (key-convert k))
|
||||||
(val (value-convert v)))
|
(val (value-convert v)))
|
||||||
(message "Found %s : %s" key val)
|
|
||||||
(unless (gethash key results)
|
(unless (gethash key results)
|
||||||
(puthash key val results)))))
|
(puthash key val results)))))
|
||||||
|
|
||||||
|
@ -2014,7 +2072,6 @@ Enough chit-chat, let's write this function. While we are at it, let's convert t
|
||||||
(second)
|
(second)
|
||||||
(plist-get :raw-value))
|
(plist-get :raw-value))
|
||||||
results)
|
results)
|
||||||
(message "Hash: %s" results)
|
|
||||||
(rpgdm-ironsworn--current-character-state results)
|
(rpgdm-ironsworn--current-character-state results)
|
||||||
results)))
|
results)))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
@ -2043,8 +2100,9 @@ Org can return the value, but breaking it up requires a regular expression:
|
||||||
(list (match-string 1 value)
|
(list (match-string 1 value)
|
||||||
(string-to-number (match-string 2 value))
|
(string-to-number (match-string 2 value))
|
||||||
(string-to-number (match-string 3 value))))))
|
(string-to-number (match-string 3 value))))))
|
||||||
#+END_SRC
|
|
||||||
|
|
||||||
|
#+END_SRC
|
||||||
|
(rx (syntax character-quote))
|
||||||
Using the =rpgdm-ironsworn-current-character-state= function to return /all properties/ in the org file, we can filter our all the progress tracks, and then return a list of the parsed values:
|
Using the =rpgdm-ironsworn-current-character-state= function to return /all properties/ in the org file, we can filter our all the progress tracks, and then return a list of the parsed values:
|
||||||
|
|
||||||
#+BEGIN_SRC emacs-lisp
|
#+BEGIN_SRC emacs-lisp
|
||||||
|
|
31
moves/adventure/begin-a-journey.org
Normal file
31
moves/adventure/begin-a-journey.org
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
** Begin a Journey
|
||||||
|
|
||||||
|
When you travel across hazardous or unfamiliar lands, first set the rank of your journey.
|
||||||
|
|
||||||
|
- Troublesome journey :: 3 progress per waypoint.
|
||||||
|
- Dangerous journey :: 2 progress per waypoint.
|
||||||
|
- Formidable journey :: 1 progress per waypoint.
|
||||||
|
- Extreme journey :: 2 ticks per waypoint.
|
||||||
|
- Epic journey :: 1 tick per waypoint.
|
||||||
|
|
||||||
|
Then, for each segment of your journey, make the [[file:undertake-a-journey.org][Undertake a Journey]] move.
|
||||||
|
|
||||||
|
*** Details
|
||||||
|
:PROPERTIES:
|
||||||
|
:move-stats: track
|
||||||
|
:VISIBILITY: folded
|
||||||
|
:END:
|
||||||
|
|
||||||
|
This is Ironsworn’s travel move. When you set off toward a destination, make this move.
|
||||||
|
|
||||||
|
First, give your journey a rank. Decide how far—and how hazardous—it is based on the established fiction. If you’re unsure, [[file:../fate/ask-the-oracle.org][Ask the Oracle]]. Most of your journeys should be troublesome or dangerous. Formidable or extreme journeys might require weeks within your narrative, with appropriate stops, side quests, and adventures along the way. An epic journey is one of months, or even years. It is the journey of a lifetime.
|
||||||
|
|
||||||
|
If the journey is mundane—a relatively short distance through safe territory, —don’t make this move. Just narrate the trip and jump to what happens or what you do when you arrive.
|
||||||
|
**** Along for the Ride?
|
||||||
|
If you are part of a caravan or party of NPCs, and aren’t an active participant in the planning or execution of the journey, you won’t make this move or track progress. The journey will be resolved in the fiction. You can [[file:../fate/ask-the-oracle.org][Ask the Oracle]] to determine what happens en route or when you arrive.
|
||||||
|
**** Allies and Journeys
|
||||||
|
If you are traveling with allies, one of you makes the *Undertake a Journey* roll for each segment, and you share a progress track. The responsibility for leading the journey can switch from segment to segment as you like.
|
||||||
|
|
||||||
|
Your fellow travelers can assist by making the [[file:../relationship/aid-your-ally.org][Aid Your Ally]] move. Perhaps they are scouting ahead or sustaining you with a lively song. They can also Resupply to represent foraging or hunting for supplies en route. Everyone should offer narrative color for what they do and see on the journey, even if they are not making moves.
|
||||||
|
|
||||||
|
Only the character making the move takes the momentum bonus on a *strong hit*. But, because your supply track is shared, each of you mark -1 supply when the acting character makes that choice on a *strong hit* or when they suffer a *weak hit*.
|
|
@ -1,14 +1,6 @@
|
||||||
** Undertake a Journey
|
** Undertake a Journey
|
||||||
|
|
||||||
When you travel across hazardous or unfamiliar lands, first set the rank of your journey.
|
For each segment of your journey, roll +wits. If you are just setting off from a community with which you share a bond (see the [[file:begin-a-journey.org][Begin a Journey]] move), add +1 to your initial roll.
|
||||||
|
|
||||||
- Troublesome journey :: 3 progress per waypoint.
|
|
||||||
- Dangerous journey :: 2 progress per waypoint.
|
|
||||||
- Formidable journey :: 1 progress per waypoint.
|
|
||||||
- Extreme journey :: 2 ticks per waypoint.
|
|
||||||
- Epic journey :: 1 tick per waypoint.
|
|
||||||
|
|
||||||
Then, for each segment of your journey, roll +wits. If you are setting off from a community with which you share a bond, add +1 to your initial roll.
|
|
||||||
|
|
||||||
On a *strong hit*, you reach a waypoint. If the waypoint is unknown to you, envision it or roll the [[elisp:(rpgdm-tables-choose "locations")][locations]] or [[elisp:(rpgdm-tables-choose "location-descriptors")][descriptors]] tables (or [[elisp:(kill-new (format "- %s %s" (rpgdm-tables-choose "location-descriptors") (rpgdm-tables-choose "locations")))][both]]), or even the site-specific [[elisp:(rpgdm-tables-choose "site-name-detail")][detail]] or [[elisp:(rpgdm-tables-choose "site-name-description")][description]]s, to help describe the waypoint. Then, choose one:
|
On a *strong hit*, you reach a waypoint. If the waypoint is unknown to you, envision it or roll the [[elisp:(rpgdm-tables-choose "locations")][locations]] or [[elisp:(rpgdm-tables-choose "location-descriptors")][descriptors]] tables (or [[elisp:(kill-new (format "- %s %s" (rpgdm-tables-choose "location-descriptors") (rpgdm-tables-choose "locations")))][both]]), or even the site-specific [[elisp:(rpgdm-tables-choose "site-name-detail")][detail]] or [[elisp:(rpgdm-tables-choose "site-name-description")][description]]s, to help describe the waypoint. Then, choose one:
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ On a *miss*, combat begins with you at a disadvantage. [[file:../fate/pay-the-pr
|
||||||
|
|
||||||
*** Details
|
*** Details
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:move-stats: heart shadow wits
|
:move-stats: track|heart shadow wits
|
||||||
:VISIBILITY: folded
|
:VISIBILITY: folded
|
||||||
:END:
|
:END:
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ Then, [[file:delve-the-depths.org][Delve the Depths]] to explore this place.
|
||||||
|
|
||||||
*** Details
|
*** Details
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
|
:move-stats: track
|
||||||
:VISIBILITY: folded
|
:VISIBILITY: folded
|
||||||
:END:
|
:END:
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ On a *miss*, you face a significant obstacle before you can begin your quest. En
|
||||||
|
|
||||||
*** Details
|
*** Details
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:move-stats: heart
|
:move-stats: track|heart
|
||||||
:VISIBILITY: folded
|
:VISIBILITY: folded
|
||||||
:END:
|
:END:
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ On a *miss*, also suffer -1 momentum. If you are at 0 health, you must mark woun
|
||||||
|
|
||||||
*** Details
|
*** Details
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:move-stats: > heart iron
|
:move-stats: > health iron
|
||||||
:VISIBILITY: folded
|
:VISIBILITY: folded
|
||||||
:END:
|
:END:
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
;;
|
;;
|
||||||
;;; Commentary:
|
;;; Commentary:
|
||||||
;;
|
;;
|
||||||
;; This file is conspicuously absent from commentary or even
|
;; This file is conspicuously absent of commentary or even
|
||||||
;; comments. This is because this file is created from tangling
|
;; comments. This is because we create this file by tangling
|
||||||
;; the README.org file in this directory.
|
;; the README.org file in this directory.
|
||||||
;;
|
;;
|
||||||
;;; Code:
|
;;; Code:
|
||||||
|
@ -96,16 +96,16 @@ a random name is generated for the purposes of the template."
|
||||||
(setq name (rpgdm-tables-choose "name/ironlander")))
|
(setq name (rpgdm-tables-choose "name/ironlander")))
|
||||||
|
|
||||||
(let ((frmt (seq-random-elt '("* The Adventures of %s"
|
(let ((frmt (seq-random-elt '("* The Adventures of %s"
|
||||||
"* The Journeys of %s"
|
"* The Journeys of %s"
|
||||||
"* %s, an Epic Saga"
|
"* %s, an Epic Saga"
|
||||||
"* The Epic of %s"
|
"* The Epic of %s"
|
||||||
"* Travels of %s"))))
|
"* Travels of %s"))))
|
||||||
(goto-char (point-max))
|
(goto-char (point-max))
|
||||||
(insert "# Local Variables:
|
;; (insert "# Local Variables: # eval: (progn (require 'rpgdm-ironsworn) (rpgdm-mode)) # End: ")
|
||||||
# eval: (progn (require 'rpgdm-ironsworn) (rpgdm-mode))
|
(insert (format frmt name))
|
||||||
# End:
|
(insert "
|
||||||
")
|
|
||||||
(insert (format frmt name))))
|
")))
|
||||||
|
|
||||||
(defun rpgdm-ironsworn--character-asset-label (filename)
|
(defun rpgdm-ironsworn--character-asset-label (filename)
|
||||||
"Given a FILENAME of an Ironsworn asset, return an Asset label."
|
"Given a FILENAME of an Ironsworn asset, return an Asset label."
|
||||||
|
@ -142,7 +142,7 @@ the `assets' directory, otherwise, we return a cached version."
|
||||||
|
|
||||||
(defun rpgdm-ironsworn--pick-character-asset ()
|
(defun rpgdm-ironsworn--pick-character-asset ()
|
||||||
"Completing read for an Ironsworn asset."
|
"Completing read for an Ironsworn asset."
|
||||||
(let ((choice (completing-read "Which asset? " (rpgdm-ironsworn-character-assets))))
|
(let ((choice (completing-read "Which asset: " (rpgdm-ironsworn-character-assets))))
|
||||||
(thread-first choice
|
(thread-first choice
|
||||||
(assoc rpgdm-ironsworn-character-assets 'equal)
|
(assoc rpgdm-ironsworn-character-assets 'equal)
|
||||||
(cdr))))
|
(cdr))))
|
||||||
|
@ -150,6 +150,7 @@ the `assets' directory, otherwise, we return a cached version."
|
||||||
(defun rpgdm-ironsworn-insert-character-asset (asset)
|
(defun rpgdm-ironsworn-insert-character-asset (asset)
|
||||||
"Choose and insert the contents of an ASSET in the current buffer."
|
"Choose and insert the contents of an ASSET in the current buffer."
|
||||||
(interactive (list (rpgdm-ironsworn--pick-character-asset)))
|
(interactive (list (rpgdm-ironsworn--pick-character-asset)))
|
||||||
|
(when rpgdm-ironsworn-new-character (goto-char (point-max)))
|
||||||
(let ((file (if (consp asset) (cdr asset) asset)))
|
(let ((file (if (consp asset) (cdr asset) asset)))
|
||||||
(insert-file-contents file nil)
|
(insert-file-contents file nil)
|
||||||
|
|
||||||
|
@ -221,17 +222,16 @@ Note: The stats are added as properties using the
|
||||||
(rpgdm-ironsworn-store-character-state stat 5))
|
(rpgdm-ironsworn-store-character-state stat 5))
|
||||||
(rpgdm-ironsworn-store-character-state 'momentum 2)
|
(rpgdm-ironsworn-store-character-state 'momentum 2)
|
||||||
|
|
||||||
(rpgdm-ironsworn-progress-create (read-string "What title should we give this new character's Epic vow? ") 1)
|
(rpgdm-ironsworn-progress-create (read-string "What title should we give this new character's Epic vow: ") 1)
|
||||||
(rpgdm-ironsworn-progress-create "Bonds" 1)
|
(rpgdm-ironsworn-progress-create "Bonds" 1)
|
||||||
(rpgdm-ironsworn-progress-mark "Bonds")
|
(rpgdm-ironsworn-progress-mark "Bonds")
|
||||||
(search-forward ":END:")
|
|
||||||
(end-of-line)
|
|
||||||
(insert "\n** Bonds\n")
|
(insert "\n** Bonds\n")
|
||||||
(insert (format " - Your home settlement of %s\n" (rpgdm-tables-choose "settlement/name"))))
|
(insert (format " - Your home settlement of %s\n" (rpgdm-tables-choose "settlement/name"))))
|
||||||
|
|
||||||
(defun rpgdm-ironsworn--new-character-stats-first (&optional name)
|
(defun rpgdm-ironsworn--new-character-stats-first (&optional name)
|
||||||
"Insert a new character template for character, NAME.
|
"Insert a new character template for character, NAME.
|
||||||
The character stats are first queried, and then assets inserted."
|
The character stats are first queried, and then assets inserted."
|
||||||
|
(goto-char (point-max))
|
||||||
(rpgdm-ironsworn--new-character-stats)
|
(rpgdm-ironsworn--new-character-stats)
|
||||||
(rpgdm-ironsworn--new-character-assets))
|
(rpgdm-ironsworn--new-character-assets))
|
||||||
|
|
||||||
|
@ -240,9 +240,10 @@ The character stats are first queried, and then assets inserted."
|
||||||
The assets are inserted first, and then character stats are queried."
|
The assets are inserted first, and then character stats are queried."
|
||||||
;; Saving and restoring point, means the properties should be in the
|
;; Saving and restoring point, means the properties should be in the
|
||||||
;; correct, top-level position.
|
;; correct, top-level position.
|
||||||
(save-excursion
|
(let ((p (point)))
|
||||||
(rpgdm-ironsworn--new-character-assets))
|
(rpgdm-ironsworn--new-character-assets)
|
||||||
(rpgdm-ironsworn--new-character-stats))
|
(goto-char p)
|
||||||
|
(rpgdm-ironsworn--new-character-stats)))
|
||||||
|
|
||||||
(defun rpgdm-ironsworn-new-character (name order)
|
(defun rpgdm-ironsworn-new-character (name order)
|
||||||
"Interactively query the user for a new character's attribute.
|
"Interactively query the user for a new character's attribute.
|
||||||
|
@ -254,12 +255,16 @@ which should be using the `org-mode' major mode."
|
||||||
(read-string "What is the new character's name? ")
|
(read-string "What is the new character's name? ")
|
||||||
(completing-read "What order should we build this? " '("Statistics first" "Assets first"))))
|
(completing-read "What order should we build this? " '("Statistics first" "Assets first"))))
|
||||||
|
|
||||||
|
(setq rpgdm-ironsworn-new-character t)
|
||||||
(rpgdm-ironsworn--new-character-template name)
|
(rpgdm-ironsworn--new-character-template name)
|
||||||
(if (equal order "Assets first")
|
(if (equal order "Assets first")
|
||||||
(rpgdm-ironsworn--new-character-assets-first)
|
(rpgdm-ironsworn--new-character-assets-first)
|
||||||
(rpgdm-ironsworn--new-character-stats-first))
|
(rpgdm-ironsworn--new-character-stats-first))
|
||||||
|
(setq rpgdm-ironsworn-new-character nil)
|
||||||
(message "Alright, the template is complete. Edit away!" name))
|
(message "Alright, the template is complete. Edit away!" name))
|
||||||
|
|
||||||
|
(defvar rpgdm-ironsworn-new-character nil "Are we in the process of creating a new character?")
|
||||||
|
|
||||||
(defun rpgdm-ironsworn--display-stat (stat character)
|
(defun rpgdm-ironsworn--display-stat (stat character)
|
||||||
"Colorized the STAT from a CHARACTER hash containing it.
|
"Colorized the STAT from a CHARACTER hash containing it.
|
||||||
See `rpgdm-ironsworn-character-display'."
|
See `rpgdm-ironsworn-character-display'."
|
||||||
|
@ -350,7 +355,7 @@ If the STAT isn't found, returns DEFAULT."
|
||||||
(:decrease (- curr numb))
|
(:decrease (- curr numb))
|
||||||
(:absolute numb)
|
(:absolute numb)
|
||||||
(t default))))
|
(t default))))
|
||||||
(message "Combining curr %d with %d with %s operator" curr numb oper)
|
;; (message "Combining curr %d with %d with %s operator" curr numb oper)
|
||||||
(rpgdm-ironsworn-store-character-state stat new)))
|
(rpgdm-ironsworn-store-character-state stat new)))
|
||||||
|
|
||||||
(defun rpgdm-ironsworn-adjust-health ()
|
(defun rpgdm-ironsworn-adjust-health ()
|
||||||
|
@ -574,19 +579,29 @@ on the properties in the file."
|
||||||
(rpgdm-ironsworn--store-move title (rpgdm-ironsworn--make-move props))))
|
(rpgdm-ironsworn--store-move title (rpgdm-ironsworn--make-move props))))
|
||||||
|
|
||||||
(defun rpgdm-ironsworn--make-move (move-props)
|
(defun rpgdm-ironsworn--make-move (move-props)
|
||||||
"Query user for rolls based on the MOVE-PROPS."
|
"Query user for rolls based on one or series of MOVE-PROPS."
|
||||||
(let* ((props (s-split " " (or move-props "")))
|
(if (string-match (rx (group (1+ alpha)) "|" (group (1+ any))) move-props)
|
||||||
(count (seq-length props))
|
(let ((first (match-string 1 move-props))
|
||||||
(stats (seq-filter (lambda (s) (string-match (rx (one-or-more alpha)) s)) props))
|
(rest (match-string 2 move-props)))
|
||||||
(first (first props)))
|
(rpgdm-ironsworn--make-single-move first)
|
||||||
(cond
|
(rpgdm-ironsworn--make-move rest))
|
||||||
((seq-empty-p stats) nil)
|
(rpgdm-ironsworn--make-single-move move-props)))
|
||||||
((equal first "progress") (call-interactively 'rpgdm-ironsworn-progress-roll))
|
|
||||||
((= count 1) (rpgdm-ironsworn-roll-with first))
|
(defun rpgdm-ironsworn--make-single-move (move-props)
|
||||||
((equal first ">") (rpgdm-ironsworn-roll-best stats))
|
"Query user for rolls based on one MOVE-PROPS."
|
||||||
(t (rpgdm-ironsworn-roll-stat
|
(let* ((props (s-split " " (or move-props "")))
|
||||||
(completing-read "Stat Choice: " stats)
|
(count (seq-length props))
|
||||||
(read-string "Modifier: "))))))
|
(stats (seq-filter (lambda (s) (string-match (rx (one-or-more alpha)) s)) props))
|
||||||
|
(first (first props)))
|
||||||
|
(cond
|
||||||
|
((seq-empty-p stats) nil)
|
||||||
|
((equal first "track") (call-interactively 'rpgdm-ironsworn-progress-create))
|
||||||
|
((equal first "progress") (call-interactively 'rpgdm-ironsworn-progress-roll))
|
||||||
|
((= count 1) (rpgdm-ironsworn-roll-with first))
|
||||||
|
((equal first ">") (rpgdm-ironsworn-roll-best stats))
|
||||||
|
(t (rpgdm-ironsworn-roll-stat
|
||||||
|
(completing-read "Stat Choice: " stats)
|
||||||
|
(read-string "Modifier: "))))))
|
||||||
|
|
||||||
(defun rpgdm-ironsworn-roll-with (stat)
|
(defun rpgdm-ironsworn-roll-with (stat)
|
||||||
"Roll against a character STAT, as a string, and prompt for modifier.
|
"Roll against a character STAT, as a string, and prompt for modifier.
|
||||||
|
@ -655,7 +670,7 @@ NAME should be a short title, not a description."
|
||||||
(title (org-get-heading))
|
(title (org-get-heading))
|
||||||
(option '(("At the same level as a sibling?" same-level)
|
(option '(("At the same level as a sibling?" same-level)
|
||||||
("As a subheading to this?" subheading)
|
("As a subheading to this?" subheading)
|
||||||
("No new heading. Re-use this." no))))
|
("No new heading. Re-use this?" no))))
|
||||||
|
|
||||||
(when (called-interactively-p)
|
(when (called-interactively-p)
|
||||||
(cl-case (completing-read-value "Create a new heading? " option)
|
(cl-case (completing-read-value "Create a new heading? " option)
|
||||||
|
@ -846,7 +861,7 @@ The STAT should be the symbol, 'wits, 'shadow, or 'edge."
|
||||||
(interactive (list (completing-read "Stat Choice: "
|
(interactive (list (completing-read "Stat Choice: "
|
||||||
'("wits" "shadow" "edge"))))
|
'("wits" "shadow" "edge"))))
|
||||||
(let ((table-name (format "delve/weak-hit/%s" stat)))
|
(let ((table-name (format "delve/weak-hit/%s" stat)))
|
||||||
(message "Rolling on %s" table-name)
|
;; (message "Rolling on %s" table-name)
|
||||||
(rpgdm-tables-choose table-name)))
|
(rpgdm-tables-choose table-name)))
|
||||||
|
|
||||||
(defun rpgdm-ironsworn-delve-the-depths-weak-edge ()
|
(defun rpgdm-ironsworn-delve-the-depths-weak-edge ()
|
||||||
|
@ -871,14 +886,19 @@ or domain tables, this reads the `site-theme' and `site-domain'
|
||||||
properties in the current org file, and rolls on the appropriate
|
properties in the current org file, and rolls on the appropriate
|
||||||
chart."
|
chart."
|
||||||
(let* ((theme (rpgdm-ironsworn-character-stat 'site-theme))
|
(let* ((theme (rpgdm-ironsworn-character-stat 'site-theme))
|
||||||
(domain (rpgdm-ironsworn-character-stat 'site-domain))
|
(domain (rpgdm-ironsworn-character-stat 'site-domain))
|
||||||
(danger (rpgdm-tables-choose "danger")))
|
(danger (rpgdm-tables-choose "danger")))
|
||||||
(cond
|
(cond
|
||||||
((equal danger "Check the theme card.")
|
((equal danger "Check the theme card.")
|
||||||
(rpgdm-tables-choose (format "danger/theme/%s" theme)))
|
(rpgdm-tables-choose (format "danger/theme/%s" theme)))
|
||||||
|
|
||||||
((equal danger "Check the domain card.")
|
((equal danger "Check the domain card.")
|
||||||
(rpgdm-tables-choose (format "danger/domain/%s" theme)))
|
(rpgdm-tables-choose (format "danger/domain/%s" domain)))
|
||||||
|
|
||||||
|
((s-starts-with? "Roll twice" danger)
|
||||||
|
(format "%s <AND> %s"
|
||||||
|
(rpgdm-ironsworn--reveal-a-danger)
|
||||||
|
(rpgdm-ironsworn--reveal-a-danger)))
|
||||||
|
|
||||||
(t danger))))
|
(t danger))))
|
||||||
|
|
||||||
|
@ -1156,7 +1176,7 @@ Return 0 if not at a heading, or above first headline."
|
||||||
(defun org-up-heading ()
|
(defun org-up-heading ()
|
||||||
"Move the point to next parent heading, unless already at the top-level."
|
"Move the point to next parent heading, unless already at the top-level."
|
||||||
(if (= 0 (org-heading-level))
|
(if (= 0 (org-heading-level))
|
||||||
(outline-up-heading 0)
|
(org-previous-visible-heading 1)
|
||||||
(outline-up-heading 1)))
|
(outline-up-heading 1)))
|
||||||
|
|
||||||
(defun rpgdm-ironsworn--current-character-state (results)
|
(defun rpgdm-ironsworn--current-character-state (results)
|
||||||
|
@ -1179,7 +1199,6 @@ precendence over similar settings in higher headers."
|
||||||
(when (rpgdm-ironsworn--property-p k)
|
(when (rpgdm-ironsworn--property-p k)
|
||||||
(let ((key (key-convert k))
|
(let ((key (key-convert k))
|
||||||
(val (value-convert v)))
|
(val (value-convert v)))
|
||||||
(message "Found %s : %s" key val)
|
|
||||||
(unless (gethash key results)
|
(unless (gethash key results)
|
||||||
(puthash key val results)))))
|
(puthash key val results)))))
|
||||||
|
|
||||||
|
@ -1202,7 +1221,6 @@ lower levels of the tree headings take precedence."
|
||||||
(second)
|
(second)
|
||||||
(plist-get :raw-value))
|
(plist-get :raw-value))
|
||||||
results)
|
results)
|
||||||
(message "Hash: %s" results)
|
|
||||||
(rpgdm-ironsworn--current-character-state results)
|
(rpgdm-ironsworn--current-character-state results)
|
||||||
results)))
|
results)))
|
||||||
|
|
||||||
|
|
|
@ -5,15 +5,15 @@
|
||||||
#+TAGS: rpg table ironsworn
|
#+TAGS: rpg table ironsworn
|
||||||
|
|
||||||
Roll on Table: d100
|
Roll on Table: d100
|
||||||
| 1-30 | Check the theme card. |
|
| 1-30 | Check the theme card. |
|
||||||
| 31-45 | Check the domain card. |
|
| 31-45 | Check the domain card. |
|
||||||
| 46-57 | You encounter a hostile denizen. |
|
| 46-57 | You encounter a hostile denizen. |
|
||||||
| 58-68 | You face an environmental or architectural hazard. |
|
| 58-68 | You face an environmental or architectural hazard. |
|
||||||
| 69-76 | A discovery undermines or complicates your quest. |
|
| 69-76 | A discovery undermines or complicates your quest. |
|
||||||
| 77-79 | You confront a harrowing situation or sensation. |
|
| 77-79 | You confront a harrowing situation or sensation. |
|
||||||
| 80-82 | You face the consequences of an earlier choice or approach. |
|
| 80-82 | You face the consequences of an earlier choice or approach. |
|
||||||
| 83-85 | Your way is blocked or trapped. |
|
| 83-85 | Your way is blocked or trapped. |
|
||||||
| 86-88 | A resource is diminished, broken, or lost. |
|
| 86-88 | A resource is diminished, broken, or lost. |
|
||||||
| 89-91 | You face a perplexing mystery or tough choice. |
|
| 89-91 | You face a perplexing mystery or tough choice. |
|
||||||
| 92-94 | You lose your way or are delayed. |
|
| 92-94 | You lose your way or are delayed. |
|
||||||
| 95-00 | Roll twice more on this table. Both results occur. |
|
| 95-100 | Roll twice more on this table. Both results occur. |
|
||||||
|
|
Loading…
Reference in a new issue