##// END OF EJS Templates
Fix a bug with kill-var and calling service locations
naryl -
r66:84186fb0 default
parent child Browse files
Show More
@@ -1,522 +1,523 b''
1 1
2 2 (in-package txt2web.api)
3 3
4 4 ;;; API deals with DOM manipulation and some bookkeeping for the
5 5 ;;; intrinsics, namely variables
6 6 ;;; API is an implementation detail and has no QSP documentation. It
7 7 ;;; doesn't call intrinsics
8 8
9 9 ;;; Utils
10 10
11 11 (defun make-act-html (title img)
12 12 (+ "<a class='qsp-act' href='" (href-call call-act title) "' onmouseover='" (inline-call select-act title) "'>"
13 13 (if img (+ "<img src='" img "'>") "")
14 14 title
15 15 "</a>"))
16 16
17 17 (defun make-menu-item-html (num title img loc)
18 18 (+ "<a href='" (href-call finish-menu loc) "'>"
19 19 (if img (+ "<img src='" img "'>") "")
20 20 title
21 21 "</a>"))
22 22
23 23 (defun make-obj (title img selected)
24 24 (+ "<li onclick='" (inline-call select-obj title img) "'>"
25 25 "<a class='qsp-obj" (if selected " qsp-obj-selected" "") "'>"
26 26 (if img (+ "<img src='" img "'>") "")
27 27 title
28 28 "</a>"))
29 29
30 30 (defun make-menu-delimiter ()
31 31 "<hr>")
32 32
33 33 (defun copy-obj (obj)
34 34 (chain *j-s-o-n (parse (chain *j-s-o-n (stringify obj)))))
35 35
36 36 (defun report-error (text)
37 37 (alert text))
38 38
39 39 (defun start-sleeping ()
40 40 (chain (by-id "qsp") class-list (add "disable")))
41 41
42 42 (defun finish-sleeping ()
43 43 (chain (by-id "qsp") class-list (remove "disable")))
44 44
45 45 (defun sleep (msec)
46 46 (with-sleep (resume)
47 47 (set-timeout resume msec)))
48 48
49 49 (defun init-dom ()
50 50 ;; Save/load buttons
51 51 (let ((btn (by-id "qsp-btn-save")))
52 52 (setf (@ btn onclick) savegame)
53 53 (setf (@ btn href) "#"))
54 54 (let ((btn (by-id "qsp-btn-open")))
55 55 (setf (@ btn onclick) opengame)
56 56 (setf (@ btn href) "#"))
57 57 ;; Close image on click
58 58 (setf (@ (by-id "qsp-image-container") onclick)
59 59 show-image)
60 60 ;; Enter in input field
61 61 (setf (@ (get-frame :input) onkeyup)
62 62 on-input-key)
63 63 ;; Close the dropdown on any click
64 64 (setf (@ window onclick)
65 65 (lambda (event)
66 66 (setf (@ window mouse)
67 67 (list (@ event page-x)
68 68 (@ event page-y)))
69 69 (finish-menu nil))))
70 70
71 71 (defun init-globals (game-name)
72 72 (chain *object (assign *globals (getprop *default-globals game-name))))
73 73
74 74 (defun call-serv-loc (var-name &rest args)
75 75 (let ((loc-name (get-global var-name 0)))
76 76 (when loc-name
77 (let ((loc (getprop *locs loc-name)))
77 (let ((loc (getprop *locs (chain loc-name (to-upper-case)))))
78 78 (when loc
79 79 (call-loc loc-name args))))))
80 80
81 81 (defun filename-game (filename)
82 82 (let ((game-name (chain filename (match "(.*/)?([^.]+)(\\.[a-zA-Z]+)?") 2))))
83 83 (getprop *games game-name))
84 84
85 85 (defun run-game (name)
86 86 (let ((game (filename-game name)))
87 87 (setf *main-game name)
88 88 ;; Replace locations with the new game's
89 89 (setf *locs game)
90 90 (funcall (getprop game
91 91 (chain *object (keys game) 0))
92 92 (list))))
93 93
94 94 ;;; Misc
95 95
96 96 (defun newline (key)
97 97 (append-id (key-to-id key) "<br>" t))
98 98
99 99 (defun clear-id (id)
100 100 (setf (inner-html (by-id id)) ""))
101 101
102 102 (defun escape-html (text)
103 103 (chain text
104 104 (replace (regex "/&/g") "&amp;")
105 105 (replace (regex "/</g") "&lt;")
106 106 (replace (regex "/>/g") "&gt;")
107 107 (replace (regex "/\"/g") "&quot;")
108 108 (replace (regex "/'/g") "&apos;")))
109 109
110 110 (defun prepare-contents (s &optional force-html)
111 111 (setf s (chain s (to-string)))
112 112 (if (or force-html (get-global "USEHTML" 0))
113 113 s
114 114 (escape-html s)))
115 115
116 116 (defun get-id (id &optional force-html)
117 117 (inner-html (by-id id)))
118 118
119 119 (defun set-id (id contents &optional force-html)
120 120 (setf (inner-html (by-id id)) (prepare-contents contents force-html)))
121 121
122 122 (defun append-id (id contents &optional force-html)
123 123 (when contents
124 124 (incf (inner-html (by-id id)) (prepare-contents contents force-html))))
125 125
126 126 (defun on-input-key (ev)
127 127 (when (= 13 (@ ev key-code))
128 128 (chain ev (prevent-default))
129 129 (call-serv-loc "$USERCOM")))
130 130
131 131 ;;; Function calls
132 132
133 133 (defun init-args (args)
134 134 (dotimes (i 10)
135 135 (set-global "ARGS" i 0)
136 136 (set-global "$ARGS" i "")
137 137 (when (and args (< i (length args)))
138 138 (let ((arg (elt args i)))
139 139 (if (numberp arg)
140 140 (set-global "ARGS" i arg)
141 141 (set-global "$ARGS" i arg))))))
142 142
143 143 (defun get-result ()
144 144 (or (get-global "$RESULT" 0)
145 145 (get-global "RESULT" 0)))
146 146
147 147 (defun call-loc (name args)
148 148 (setf name (chain name (to-upper-case)))
149 149 (with-frame
150 150 (with-call-args args t
151 151 (funcall (getprop *locs name)))))
152 152
153 153 (defun call-act (title)
154 154 (with-frame
155 155 (funcall (getprop *acts title :act)))
156 156 (void))
157 157
158 158 ;;; Text windows
159 159
160 160 (defun key-to-id (key)
161 161 (case key
162 162 (:all "qsp")
163 163 (:main "qsp-main")
164 164 (:stat "qsp-stat")
165 165 (:objs "qsp-objs")
166 166 (:acts "qsp-acts")
167 167 (:input "qsp-input")
168 168 (:image "qsp-image")
169 169 (:dropdown "qsp-dropdown")
170 170 (t (report-error "Internal error!"))))
171 171
172 172 (defun get-frame (key)
173 173 (by-id (key-to-id key)))
174 174
175 175 (defun add-text (key text)
176 176 (append-id (key-to-id key) text))
177 177
178 178 (defun get-text (key)
179 179 (get-id (key-to-id key)))
180 180
181 181 (defun clear-text (key)
182 182 (clear-id (key-to-id key)))
183 183
184 184 (defun enable-frame (key enable)
185 185 (let ((obj (get-frame key)))
186 186 (setf (@ obj style display) (if enable "block" "none"))
187 187 (void)))
188 188
189 189 ;;; Actions
190 190
191 191 (defun add-act (title img act)
192 192 (setf (getprop *acts title)
193 193 (create :title title :img img :act act :selected nil))
194 194 (update-acts))
195 195
196 196 (defun del-act (title)
197 197 (delete (getprop *acts title))
198 198 (update-acts))
199 199
200 200 (defun clear-act ()
201 201 (setf *acts (create))
202 202 (update-acts))
203 203
204 204 (defun update-acts ()
205 205 (clear-id "qsp-acts")
206 206 (let ((elt (by-id "qsp-acts")))
207 207 (for-in (title *acts)
208 208 (let ((obj (getprop *acts title)))
209 209 (incf (inner-html elt) (make-act-html title (getprop obj :img)))))))
210 210
211 211 (defun select-act (title)
212 212 (loop :for (k v) :of *acts
213 213 :do (setf (getprop v :selected) nil))
214 214 (setf (getprop *acts title :selected) t)
215 215 (call-serv-loc "$ONACTSEL"))
216 216
217 217 ;;; Variables
218 218
219 219 (defun new-var (slot &rest indexes)
220 220 (let ((v (list)))
221 221 (dolist (index indexes)
222 222 (setf (elt v index) (if (eq #\$ (elt slot 0)) "" 0)))
223 223 (setf (@ v :indexes) (create))
224 224 v))
225 225
226 226 (defun set-str-element (slot index value)
227 227 (if (has index (getprop slot :indexes))
228 (setf (elt (getprop slot)
229 (getprop slot :indexes index))
228 (setf (elt slot (getprop slot :indexes index))
230 229 value)
231 230 (progn
232 231 (chain slot (push value))
233 (setf (elt slot index)
234 (length slot))))
232 (setf (getprop slot :indexes index)
233 (1- (length slot)))))
235 234 (void))
236 235
237 236 (defun set-any-element (slot index value)
238 237 (cond ((null index)
239 238 (chain (elt slot) (push value)))
240 239 ((numberp index)
241 240 (setf (elt slot index) value))
242 241 ((stringp index)
243 242 (set-str-element slot index value))
244 243 (t (report-error "INTERNAL ERROR")))
245 244 (void))
246 245
247 246 (defun set-serv-var (name index value)
248 247 (let ((slot (getprop *globals name)))
249 248 (set-any-element slot index value))
250 249 (funcall (getprop serv-vars name :body) value index)
251 250 (void))
252 251
253 252 (defun get-element (slot index)
254 253 (if (numberp index)
255 254 (elt slot index)
256 255 (elt slot (getprop slot :indexes index))))
257 256
258 257 (defun set-global (name index value)
259 258 (set-any-element (getprop *globals name) index value))
260 259
261 260 (defun get-global (name index)
262 261 (get-element (getprop *globals name) index))
263 262
264 263 (defun kill-var (&optional name index)
265 264 (cond (name
266 265 (setf name (chain name (to-upper-case)))
267 (if (and index (not (= 0 index)))
268 (chain (getprop *globals name) (kill index))
269 (delete (getprop *globals name))))
266 (cond ((and index (not (= 0 index)))
267 (chain (getprop *globals name) (kill index)))
268 (t
269 (setf (getprop *globals name) (list))
270 (setf (getprop *globals name "indexes") (create)))))
270 271 (t
271 272 (setf *globals (create))
272 273 (init-globals *main-game)))
273 274 (void))
274 275
275 276 (defun array-size (name)
276 277 (@ (var-ref name) :values length))
277 278
278 279 ;;; Locals
279 280
280 281 (defun push-local-frame ()
281 282 (chain *locals (push (create)))
282 283 (void))
283 284
284 285 (defun pop-local-frame ()
285 286 (chain *locals (pop))
286 287 (void))
287 288
288 289 (defun current-local-frame ()
289 290 (elt *locals (1- (length *locals))))
290 291
291 292 ;;; Objects
292 293
293 294 (defun select-obj (title img)
294 295 (loop :for (k v) :of *objs
295 296 :do (setf (getprop v :selected) nil))
296 297 (setf (getprop *objs title :selected) t)
297 298 (call-serv-loc "$ONOBJSEL" title img))
298 299
299 300 (defun update-objs ()
300 301 (let ((elt (by-id "qsp-objs")))
301 302 (setf (inner-html elt) "<ul>")
302 303 (loop :for (name obj) :of *objs
303 304 :do (incf (inner-html elt)
304 305 (make-obj name (@ obj :img) (@ obj :selected))))
305 306 (incf (inner-html elt) "</ul>")))
306 307
307 308 ;;; Menu
308 309
309 310 (defun open-menu (menu-data)
310 311 (let ((elt (get-frame :dropdown))
311 312 (i 0))
312 313 (loop :for item :in menu-data
313 314 :do (incf i)
314 315 :do (incf (inner-html elt)
315 316 (if (eq item :delimiter)
316 317 (make-menu-delimiter i)
317 318 (make-menu-item-html i
318 319 (@ item :text)
319 320 (@ item :icon)
320 321 (@ item :loc)))))
321 322 (let ((mouse (@ window mouse)))
322 323 (setf (@ elt style left) (+ (elt mouse 0) "px"))
323 324 (setf (@ elt style top) (+ (elt mouse 1) "px"))
324 325 ;; Make sure it's inside the viewport
325 326 (when (> (@ document body inner-width)
326 327 (+ (elt mouse 0) (@ elt inner-width)))
327 328 (incf (@ elt style left) (@ elt inner-width)))
328 329 (when (> (@ document body inner-height)
329 330 (+ (elt mouse 0) (@ elt inner-height)))
330 331 (incf (@ elt style top) (@ elt inner-height))))
331 332 (setf (@ elt style display) "block")))
332 333
333 334 (defun finish-menu (loc)
334 335 (when *menu-resume
335 336 (let ((elt (get-frame :dropdown)))
336 337 (setf (inner-html elt) "")
337 338 (setf (@ elt style display) "none")
338 339 (funcall *menu-resume)
339 340 (setf *menu-resume nil))
340 341 (when loc
341 342 (call-loc loc)))
342 343 (void))
343 344
344 345 (defun menu (menu-data)
345 346 (with-sleep (resume)
346 347 (open-menu menu-data)
347 348 (setf *menu-resume resume))
348 349 (void))
349 350
350 351 ;;; Content
351 352
352 353 (defun clean-audio ()
353 354 (loop :for k :in (chain *object (keys *playing))
354 355 :for v := (getprop *playing k)
355 356 :do (when (@ v ended)
356 357 (delete (@ *playing k)))))
357 358
358 359 (defun show-image (path)
359 360 (let ((img (get-frame :image)))
360 361 (cond (path
361 362 (setf (@ img src) path)
362 363 (setf (@ img style display) "flex"))
363 364 (t
364 365 (setf (@ img src) "")
365 366 (setf (@ img style display) "hidden")))))
366 367
367 368 (defun rgb-string (rgb)
368 369 (let ((red (ps::>> rgb 16))
369 370 (green (logand (ps::>> rgb 8) 255))
370 371 (blue (logand rgb 255)))
371 372 (flet ((rgb-to-hex (comp)
372 373 (let ((hex (chain (*number comp) (to-string 16))))
373 374 (if (< (length hex) 2)
374 375 (+ "0" hex)
375 376 hex))))
376 377 (+ "#" (rgb-to-hex red) (rgb-to-hex green) (rgb-to-hex blue)))))
377 378
378 379 (defun store-obj (key obj)
379 380 (store-str key (btoa (encode-u-r-i-component (chain *j-s-o-n (stringify obj)))))
380 381 (void))
381 382 (defun store-str (key str)
382 383 (chain local-storage (set-item (+ "qsp_" key) str))
383 384 (void))
384 385
385 386 (defun load-obj (key)
386 387 (chain *j-s-o-n (parse (encode-u-r-i-component (atob (load-str key))))))
387 388 (defun load-str (key)
388 389 (chain local-storage (get-item (+ "qsp_" key))))
389 390
390 391 ;;; Saves
391 392
392 393 (defun slot-savegame (slot comment)
393 394 (let ((saves (load-obj "saves")))
394 395 (setf (@ saves slot) comment)
395 396 (store-obj saves))
396 397 (store-str slot (state-to-base64))
397 398 (void))
398 399
399 400 (defun slot-loadgame (slot)
400 401 (base64-to-state (load-str slot))
401 402 (void))
402 403
403 404 (defun slot-deletegame (slot)
404 405 (let ((saves (load-obj "saves")))
405 406 (setf (@ saves slot) undefined)
406 407 (store-obj saves))
407 408 (store-str slot undefined)
408 409 (void))
409 410
410 411 (defun slot-listgames ()
411 412 (load-obj "saves"))
412 413
413 414 (defun opengame ()
414 415 (let ((element (chain document (create-element :input))))
415 416 (chain element (set-attribute :type :file))
416 417 (chain element (set-attribute :id :qsp-opengame))
417 418 (chain element (set-attribute :tabindex -1))
418 419 (chain element (set-attribute "aria-hidden" t))
419 420 (setf (@ element style display) :block)
420 421 (setf (@ element style visibility) :hidden)
421 422 (setf (@ element style position) :fixed)
422 423 (setf (@ element onchange)
423 424 (lambda (event)
424 425 (let* ((file (@ event target files 0))
425 426 (reader (new (*file-reader))))
426 427 (setf (@ reader onload)
427 428 (lambda (ev)
428 429 (block nil
429 430 (let ((target (@ ev current-target)))
430 431 (unless (@ target result)
431 432 (return))
432 433 (base64-to-state (@ target result))
433 434 (unstash-state)))))
434 435 (chain reader (read-as-text file)))))
435 436 (chain document body (append-child element))
436 437 (chain element (click))
437 438 (chain document body (remove-child element))))
438 439
439 440 (defun savegame ()
440 441 (let ((element (chain document (create-element :a))))
441 442 (chain element (set-attribute :href (+ "data:text/plain;charset=utf-8," (state-to-base64))))
442 443 (chain element (set-attribute :download "savegame.sav"))
443 444 (setf (@ element style display) :none)
444 445 (chain document body (append-child element))
445 446 (chain element (click))
446 447 (chain document body (remove-child element))))
447 448
448 449 (defun stash-state (args)
449 450 (call-serv-loc "$ONGSAVE")
450 451 (setf *state-stash
451 452 (chain *j-s-o-n (stringify
452 453 (create :vars *globals
453 454 :objs *objs
454 455 :loc-args args
455 456 :msecs (- (chain *date (now)) *started-at)
456 457 :timer-interval *timer-interval
457 458 :main-html (inner-html
458 459 (get-frame :main))
459 460 :stat-html (inner-html
460 461 (get-frame :stat))
461 462 :next-location *current-location))))
462 463 (void))
463 464
464 465 (defun unstash-state ()
465 466 (let ((data (chain *j-s-o-n (parse *state-stash))))
466 467 (clear-act)
467 468 (setf *globals (@ data :vars))
468 469 (loop :for k :in (chain *object (keys *globals))
469 470 :do (chain *object (set-prototype-of (getprop *globals k)
470 471 (@ *var prototype))))
471 472 (setf *started-at (- (chain *date (now)) (@ data :msecs)))
472 473 (setf *objs (@ data :objs))
473 474 (setf *current-location (@ data :next-location))
474 475 (setf (inner-html (get-frame :main))
475 476 (@ data :main-html))
476 477 (setf (inner-html (get-frame :stat))
477 478 (@ data :stat-html))
478 479 (update-objs)
479 480 (set-timer (@ data :timer-interval))
480 481 (call-serv-loc "$ONGLOAD")
481 482 (call-loc *current-location (@ data :loc-args))
482 483 (void)))
483 484
484 485 (defun state-to-base64 ()
485 486 (btoa (encode-u-r-i-component *state-stash)))
486 487
487 488 (defun base64-to-state (data)
488 489 (setf *state-stash (decode-u-r-i-component (atob data))))
489 490
490 491 ;;; Timers
491 492
492 493 (defun set-timer (interval)
493 494 (setf *timer-interval interval)
494 495 (clear-interval *timer-obj)
495 496 (setf *timer-obj
496 497 (set-interval
497 498 (lambda ()
498 499 (call-serv-loc "$COUNTER"))
499 500 interval)))
500 501
501 502 ;;; Special variables
502 503
503 504 (defvar serv-vars (create))
504 505
505 506 (define-serv-var $backimage (path)
506 507 (setf (@ (get-frame :main) style background-image) path))
507 508
508 509 (define-serv-var bcolor (color)
509 510 (setf (@ (get-frame :all) style background-color) (rgb-string color)))
510 511
511 512 (define-serv-var fcolor (color)
512 513 (setf (@ (get-frame :all) style color) (rgb-string color)))
513 514
514 515 (define-serv-var lcolor (color)
515 516 (setf (@ (get-frame :style) inner-text)
516 517 (+ "a { color: " (rgb-string color) ";}")))
517 518
518 519 (define-serv-var fsize (size)
519 520 (setf (@ (get-frame :all) style font-size) size))
520 521
521 522 (define-serv-var $fname (font-name)
522 523 (setf (@ (get-frame :all) style font-family) (+ font-name ",serif")))
@@ -1,317 +1,315 b''
1 1
2 2 (in-package txt2web.lib)
3 3
4 4 ;;;; Functions and procedures defined by the QSP language.
5 5 ;;;; They can call api and deal with locations and other data directly.
6 6 ;;;; Except vars. Use VAR and SET or GET-VAR and SET-VAR api calls.
7 7
8 8 ;;; 1loc
9 9
10 10 (defun goto (target args)
11 11 (api:clear-text :main)
12 12 (funcall xgoto target args)
13 13 (void))
14 14
15 15 (defun xgoto (target args)
16 16 (setf args (or args (list)))
17 17 (api:clear-act)
18 18 (setf *current-location (chain target (to-upper-case)))
19 19 (api:stash-state args)
20 20 (api:call-loc *current-location args)
21 21 (api:call-serv-loc "$ONNEWLOC")
22 22 (void))
23 23
24 24 ;;; 2var
25 25
26 26 ;;; 3expr
27 27
28 28 (defun obj (name)
29 29 (has name *objs))
30 30
31 31 (defun loc (name)
32 32 (has name *locs))
33 33
34 34 ;;; 4code
35 35
36 36 (defun rand (a &optional (b 1))
37 37 (let ((min (min a b))
38 38 (max (max a b)))
39 39 (+ min (chain *math (random (- max min))))))
40 40
41 41 ;;; 5arrays
42 42
43 43 (defun copyarr (to from start count)
44 44 (multiple-value-bind (to-name to-slot)
45 45 (api:var-real-name to)
46 46 (multiple-value-bind (from-name from-slot)
47 47 (api:var-real-name from)
48 48 (loop :for i :from start :to (min (api:array-size from-name)
49 49 (+ start count))
50 50 :do (api:set-var to-name (+ start i) to-slot
51 51 (api:get-var from-name (+ start i) from-slot))))))
52 52
53 53 (defun arrpos (name value &optional (start 0))
54 54 (multiple-value-bind (real-name slot)
55 55 (api:var-real-name name)
56 56 (loop :for i :from start :to (api:array-size name)
57 57 :do (when (eq (api:get-var real-name i slot) value)
58 58 (return-from arrpos i))))
59 59 -1)
60 60
61 61 (defun arrcomp (name pattern &optional (start 0))
62 62 (multiple-value-bind (real-name slot)
63 63 (api:var-real-name name)
64 64 (loop :for i :from start :to (api:array-size name)
65 65 :do (when (funcall (getprop (api:get-var real-name i slot)
66 66 'match)
67 67 pattern)
68 68 (return-from arrcomp i))))
69 69 -1)
70 70
71 71 ;;; 6str
72 72
73 73 (defun instr (s subs &optional (start 1))
74 74 (+ start (chain s (substring (- start 1)) (search subs))))
75 75
76 76 (defun isnum (s)
77 77 (if (is-na-n s)
78 78 0
79 79 -1))
80 80
81 81 (defun strcomp (s pattern)
82 82 (if (chain s (match pattern))
83 83 -1
84 84 0))
85 85
86 86 (defun strfind (s pattern group)
87 87 (let* ((re (new (*reg-exp pattern)))
88 88 (match (chain re (exec s))))
89 89 (chain match (group group))))
90 90
91 91 (defun strpos (s pattern &optional (group 0))
92 92 (let* ((re (new (*reg-exp pattern)))
93 93 (match (chain re (exec s)))
94 94 (found (chain match (group group))))
95 95 (if found
96 96 (chain s (search found))
97 97 0)))
98 98
99 99 ;;; 7if
100 100
101 101 ;; Has to be a function because it always evaluates all three of its
102 102 ;; arguments
103 103 (defun iif (cond-expr then-expr else-expr)
104 104 (if cond-expr then-expr else-expr))
105 105
106 106 ;;; 8sub
107 107
108 108 (defun gosub (target &rest args)
109 109 (api:call-loc target args)
110 110 (void))
111 111
112 112 (defun func (target &rest args)
113 113 (api:call-loc target args))
114 114
115 115 ;;; 9loops
116 116
117 117 ;;; 10dynamic
118 118
119 119 ;;; 11main
120 120
121 121 (defun main-p (s)
122 122 (api:add-text :main s)
123 123 (void))
124 124
125 125 (defun main-pl (s)
126 126 (api:add-text :main s)
127 127 (api:newline :main)
128 128 (void))
129 129
130 130 (defun main-nl (s)
131 131 (api:newline :main)
132 132 (api:add-text :main s)
133 133 (void))
134 134
135 (defun maintxt (s)
136 (api:get-text :main)
137 (void))
135 (defun maintxt ()
136 (api:get-text :main))
138 137
139 (defun desc (s)
138 (defun desc ()
140 139 "")
141 140
142 141 (defun main-clear ()
143 142 (api:clear-text :main)
144 143 (void))
145 144
146 145 ;;; 12stat
147 146
148 147 (defun stat-p (s)
149 148 (api:add-text :stat s)
150 149 (void))
151 150
152 151 (defun stat-pl (s)
153 152 (api:add-text :stat s)
154 153 (api:newline :stat)
155 154 (void))
156 155
157 156 (defun stat-nl (s)
158 157 (api:newline :stat)
159 158 (api:add-text :stat s)
160 159 (void))
161 160
162 (defun stattxt (s)
163 (api:get-text :stat)
164 (void))
161 (defun stattxt ()
162 (api:get-text :stat))
165 163
166 164 (defun stat-clear ()
167 165 (api:clear-text :stat)
168 166 (void))
169 167
170 168 (defun cls ()
171 169 (stat-clear)
172 170 (main-clear)
173 171 (cla)
174 172 (cmdclear)
175 173 (void))
176 174
177 175 ;;; 13diag
178 176
179 177 ;;; 14act
180 178
181 179 (defun selact ()
182 180 (loop :for (k v) :of *acts
183 181 :do (when (@ v :selected)
184 182 (return-from selact (@ v :name)))))
185 183
186 184 (defun curacts ()
187 185 (let ((acts (api-call copy-obj *acts)))
188 186 (lambda ()
189 187 (setf *acts acts)
190 188 (void))))
191 189
192 190 ;;; 15objs
193 191
194 192 (defun addobj (name img)
195 193 (setf img (or img ""))
196 194 (setf (getprop *objs name)
197 195 (create :name name :img img :selected nil))
198 196 (api:update-objs)
199 197 (api-call call-serv-loc "$ONOBJADD" name img)
200 198 (void))
201 199
202 200 (defun delobj (name)
203 201 (delete (getprop *objs name))
204 202 (api:update-objs)
205 203 (api-call call-serv-loc "$ONOBJDEL" name)
206 204 (void))
207 205
208 206 (defun killobj (&optional (num nil))
209 207 (if (eq undefined num)
210 208 (setf *objs (create))
211 209 (delobj (elt (chain *object (keys *objs)) num)))
212 210 (api:update-objs)
213 211 (void))
214 212
215 213 (defun selobj ()
216 214 (loop :for (k v) :of *objs
217 215 :do (when (@ v :selected)
218 216 (return-from selobj (@ v :name)))))
219 217
220 218 (defun unsel ()
221 219 (loop :for (k v) :of *objs
222 220 :do (setf (@ v :selected) nil)))
223 221
224 222 ;;; 16menu
225 223
226 224 (defun menu (menu-name)
227 225 (let ((menu-data (list)))
228 226 (loop :for item-obj :in (@ (api:get-array (api:var-real-name menu-name)) values)
229 227 :for item := (@ item-obj :str)
230 228 :do (cond ((string= item "")
231 229 (break))
232 230 ((string= item "-:-")
233 231 (chain menu-data (push :delimiter)))
234 232 (t
235 233 (let* ((tokens (chain item (split ":"))))
236 234 (when (= (length tokens) 2)
237 235 (chain tokens (push "")))
238 236 (let* ((text (chain tokens (splice 0 (- (length tokens) 2)) (join ":")))
239 237 (loc (getprop tokens (- (length tokens) 2)))
240 238 (icon (getprop tokens (- (length tokens) 1))))
241 239 (chain menu-data
242 240 (push (create :text text
243 241 :loc loc
244 242 :icon icon))))))))
245 243 (api:menu menu-data)
246 244 (void)))
247 245
248 246 ;;; 17sound
249 247
250 248 (defun play (filename &optional (volume 100))
251 249 (let ((audio (new (*audio filename))))
252 250 (setf (getprop *playing filename) audio)
253 251 (setf (@ audio volume) (* volume 0.01))
254 252 (chain audio (play))))
255 253
256 254 (defun close (filename)
257 255 (funcall (getprop *playing filename) stop)
258 256 (delete (getprop *playing filename))
259 257 (void))
260 258
261 259 (defun closeall ()
262 260 (loop :for k :in (chain *object (keys *playing))
263 261 :for v := (getprop *playing k)
264 262 :do (funcall v stop))
265 263 (setf *playing (create)))
266 264
267 265 ;;; 18img
268 266
269 267 (defun refint ()
270 268 ;; "Force interface update" Uh... what exactly do we do here?
271 269 ;(api:report-error "REFINT is not supported")
272 270 )
273 271
274 272 ;;; 19input
275 273
276 274 (defun usertxt ()
277 275 (let ((input (by-id "qsp-input")))
278 276 (@ input value)))
279 277
280 278 (defun cmdclear ()
281 279 (let ((input (by-id "qsp-input")))
282 280 (setf (@ input value) "")))
283 281
284 282 (defun input (text)
285 283 (chain window (prompt text)))
286 284
287 285 ;;; 20time
288 286
289 287 (defun msecscount ()
290 288 (- (chain *date (now)) *started-at))
291 289
292 290 ;;; 21local
293 291
294 292 ;;; 22for
295 293
296 294 ;;; misc
297 295
298 296 (defun rgb (red green blue)
299 297 (+ (<< red 16)
300 298 (<< green 8)
301 299 blue))
302 300
303 301 (defun openqst (name)
304 302 (api-call run-game name))
305 303
306 304 (defun addqst (name)
307 305 (let ((game (api-call filename-game name)))
308 306 ;; Add the game's locations
309 307 (chain *object (assign *locs
310 308 (getprop *games name)))))
311 309
312 310 (defun killqst ()
313 311 ;; Delete all locations not from the current main game
314 312 (loop :for (k v) :in *games
315 313 :do (unless (string= k *main-game)
316 314 (delete (getprop *locs k)))))
317 315
General Comments 0
You need to be logged in to leave comments. Login now