1;; Sets a quest to be complete, with notification if it is in progress 2;; Note that if you set the quest to be complete before you assign it, 3;; then the assignment notification will say that it has been immediately 4;; completed, avoiding spamming the player with multiple notifications 5 6(define (quest-complete quest) 7 (if (and (quest-assigned? quest) use-quest-pane) 8 (kern-log-msg "^c+mQuest completed:^c-\n^c+m" (qst-title quest) "^c-") 9 ) 10 (qst-complete! quest) 11 ) 12 13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 14;; internal utility methods 15 16(define (quest-data-add-child parent quest) 17 (let ((childlist (quest-data-getvalue parent 'qchildren))) 18 (if (not (in-list? quest childlist)) 19 (quest-data-update parent 'qchildren 20 (cons 21 quest 22 childlist 23 ) 24 )) 25 )) 26 27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 28;; quest assignment callbacks for use in quest definition 29 30;; causes a notification on assignment 31(define (quest-assign-notify quest target) 32 (let ((notifytext (if (qst-complete? quest) 33 "^c+mQuest completed:^c-\n^c+m" 34 "^c+mNew quest:^c-\n^c+m" 35 ))) 36 (if use-quest-pane 37 (kern-log-msg notifytext (qst-title quest) "^c-") 38 ) 39 #t 40 )) 41 42;; ensures parent/subquest relation once quest is assigned 43(define (quest-assign-subquest quest target) 44 (let ((parent (quest-tbl-get quest 'qparent))) 45 (if (not (null? parent)) 46 (quest-data-add-child parent (qst-tag quest)) 47 ) 48 #t 49 )) 50 51;; allows quest to proceed without any other action 52(define (quest-assign-silent quest target) 53 #t 54 ) 55 56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 57;; quest display callbacks for use in quest definition 58 59;; doesnt actually do anything 60(define (quest-status-from-payload quest) 61 "In progress" 62 ) 63 64;; doesnt actually do anything 65(define (quest-status-inprogress quest) 66 "In progress" 67 ) 68 69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 70;; Interacting with the Quest Data Table 71;; 72;; The quest data table is a global storage location for fixed, plot 73;; based quests that are created once and then activated at the 74;; appropriate time 75;; 76;; Anything procedurally generated on the fly would need 77;; to interface directly with the quest-sys module. 78;; 79 80;; retrieves a quest from the quest data table 81(define (quest-data-get tag) 82 (println "quest-data-get:" tag) 83 (let* ((questdata (tbl-get (gob (kern-get-player)) 'questdata)) 84 ) 85 (tbl-get questdata tag) 86 ) 87 ) 88 89;; retrieves a value from a quest payload tbl, given the key for the quest 90;; and for the value 91(define (quest-data-getvalue quest tag) 92 (let* ((qpayload (car (qst-payload (quest-data-get quest))))) 93 (tbl-get qpayload tag) 94 ) 95 ) 96 97;; assigns a quest from the quest data table, while ensuring it is not 98;; given out repeatedly 99(define (quest-data-assign-once tag) 100 (let ((questentry (quest-data-get tag))) 101 (if (not (quest-assigned? questentry)) 102 (quest-assign questentry) 103 ) 104 )) 105 106;; checks if a quest from the quest data table has been assigned 107(define (quest-data-assigned? tag) 108 (quest-assigned? (quest-data-get tag)) 109 ) 110 111;; assuming quest in the QDT uses a tbl for payload, updates a key/value pair 112(define (quest-data-update tag key value) 113 (let* ((qpayload (car (qst-payload (quest-data-get tag)))) 114 (updatehook (tbl-get qpayload 'on-update)) 115 ) 116 (if (not (equal? (tbl-get qpayload key) value)) 117 (begin 118 (tbl-set! qpayload key value) 119 (if (not (null? updatehook)) 120 ((eval updatehook)) 121 ) 122 (qst-bump! (quest-data-get tag)) 123 )) 124 )) 125 126;; updates as per quest-data-update, but additionally triggers a passed in function 127(define (quest-data-update-with tag key value callback) 128 (println "quest-data-update-with") 129 (let* ( 130 (quest (quest-data-get tag)) 131 (qpayload (car (qst-payload quest))) 132 ) 133 (println "quest:" quest) 134 (println "qpayload:" qpayload) 135 (if (is-tbl? qpayload) 136 (let ( 137 (updatehook (tbl-get qpayload 'on-update)) 138 ) 139 (println "updatehook" updatehook) 140 (if (not (equal? (tbl-get qpayload key) value)) 141 (begin 142 (tbl-set! qpayload key value) 143 (callback quest) 144 (if (not (null? updatehook)) 145 ((eval updatehook)) 146 ) 147 (qst-bump! (quest-data-get tag)) 148 ) 149 ) 150 ) 151 ) 152 ) 153 ) 154 155;; sets the description for a quest in the QDT 156(define (quest-data-descr! tag descr) 157 (qst-set-descr! (quest-data-get tag) descr) 158 ) 159 160;; sets the icon for a quest in the QDT 161(define (quest-data-icon! tag icon) 162 (qst-set-icon! (quest-data-get tag) icon) 163 ) 164 165;; sets a quest in the QDT to be complete, giving a notification if appropriate 166;; see the notes for quest-complete, above 167(define (quest-data-complete tag) 168 (quest-complete (quest-data-get tag)) 169 ) 170 171;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 172;; callbacks for quest-data-update-with 173 174;; if appropriate, notifies the player about a change in quest state 175;; can be chained to further functions 176(define (quest-notify subfunction) 177 (println "quest-notify") 178 (lambda (quest) 179 (if (and (quest-assigned? quest) use-quest-pane) 180 (kern-log-msg "^c+mQuest updated:^c-\n^c+m" (qst-title quest) "^c-") 181 ) 182 (if (not (null? subfunction)) 183 (subfunction quest)) 184 )) 185 186;; grants the player a given amount of experience, using or adding to the bonus xp 187;; as appropriate 188(define (grant-xp-fn amount) 189 (lambda (quest) 190 (let* ((qpayload (car (qst-payload quest))) 191 (bonusxp (tbl-get qpayload 'bonus-xp)) 192 (bonusxp (if (null? bonusxp) 193 0 bonusxp)) 194 (totalxp (+ bonusxp amount)) 195 ) 196 (if (quest-assigned? quest) 197 (begin 198 (kern-char-add-experience (car (kern-party-get-members (kern-get-player))) totalxp) 199 (tbl-set! qpayload 'bonus-xp 0) 200 ) 201 (tbl-set! qpayload 'bonus-xp totalxp) 202 ) 203 ) 204 )) 205 206;; shares amongst the players party a given amount of experience, 207;; using or adding to the bonus xp as appropriate 208(define (grant-party-xp-fn amount) 209 (lambda (quest) 210 (let* ((qpayload (car (qst-payload quest))) 211 (bonusxp (tbl-get qpayload 'bonus-xp)) 212 (bonusxp (if (null? bonusxp) 213 0 bonusxp)) 214 (totalxp (+ bonusxp amount)) 215 (party (kern-party-get-members (kern-get-player))) 216 (xp-each (ceiling (/ totalxp (length party)))) 217 ) 218 (if (quest-assigned? quest) 219 (begin 220 (map (lambda (kchar) (kern-char-add-experience kchar xp-each)) party) 221 (tbl-set! qpayload 'bonus-xp 0) 222 ) 223 (tbl-set! qpayload 'bonus-xp totalxp) 224 ) 225 ) 226 )) 227 228;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 229;; Reconcile active and pregenned quests at game load to simplify 230;; ingame tracking 231;; 232;; internal methods- will run automatically 233 234(kern-add-hook 'new_game_start_hook 'reconcile-quests) 235(kern-add-hook 'new_game_start_hook 'refresh-quests) 236 237(define (reconcile-quests kplayer) 238 (let ((questlist 239 (tbl-get (gob 240 (kern-get-player)) 'quests)) 241 (questdata 242 (tbl-get (gob 243 (kern-get-player)) 'questdata)) 244 ) 245 (map 246 (lambda (quest) 247 (let ((tag (qst-tag quest))) 248 (if (and (not (null? tag)) 249 (not (null? (tbl-get questdata tag)))) 250 (tbl-set! questdata tag quest)) 251 )) 252 questlist) 253 )) 254 255(define (refresh-quests) 256 (load "quests-data.scm") 257 ) 258 259 260;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 261;; utilities 262 263;; links a quest and subquest after they are already in-play 264(define (quest-data-convert-subquest quest parent) 265 (quest-data-update quest 'qparent parent) 266 (quest-data-add-child parent quest) 267 )