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	)