Community

SCI Programming => SCI Syntax Help => Topic started by: Doan Sephim on February 20, 2022, 02:25:28 PM

Title: [SOLVED] SCI0 - Globalizing my local death sheet Script
Post by: Doan Sephim on February 20, 2022, 02:25:28 PM
Last year, inspired by Charles "retry/restore/quit" thread (https://sciprogramming.com/community/index.php?topic=1946.15), I put together a death window to show the various deaths the player has suffered in the game to the current point. I had to do a lot of things differently, such as saving variables to an external file so that restoring doesn't remove them, to make this possible.

I've put together a bare bones script in a random room's script to test getting it up and running, but now I need to make it global so that the sheet can be accessed anytime (preferably in the menubar). Here's where the problem presents itself - while migrating the code to the main script, I can get everything up and running except the ability to remove the window. I think the problem may rest with my use of the Display command, but I'm not 100% certain.

My question is should I try to make a new script for this (and how), or does it belong in an existing script (Window, User), or is the Main script a fine place for and there are just some bugs? And finally, should I not be using "display" at all and keep it all a "Print" command? If that's the case, how do I argue how to print some things and not others in a Print? Perhaps FormatPrint first?

Here is how it presented in the Roomscript:
Code: [Select]
;;; Sierra Script 1.0 - (do not remove this comment)
; Broken Bridge Forest
(script# 210)
(include sci.sh)
(include game.sh)
(use controls)
(use cycle)
(use feature)
(use game)
(use inv)
(use main)
(use obj)
(use window)
(use menubar)

(public
rm210 0
)

(local
deathWindowOpen = 0 ; Used as a switch to determine when you can close the deathWindow
deathWindow ; Used to open the display window
i = 0 ; Used in the "for"
textDown = 7 ; Used to place statements progressively lower than earlier statements
textRight = 20 ; Used to move statements right, once y-axis full - NOT YET IMPLEMENTED
[str 30] ; String for pulling text resources
)

(instance rm210 of Rm
(properties
picture scriptNumber
north 0
east 211
south 0
west 215
)

(method (init)
(super init:)
(self
setScript: RoomScript
)
(switch gPreviousRoomNumber
(else
(gEgo init: posn: 32 96)
)
)
(SetUpEgo)

)
)

(instance RoomScript of Script
(properties)

(method (changeState mainState)
(= state mainState)

)

(method (handleEvent pEvent)
(super handleEvent: pEvent)

; removes the window AND dsiplay text! I'm not sure why it disposes the display though.
(if (== deathWindowOpen 1)
(DisposeWindow deathWindow)
(= deathWindowOpen 0)
(= textDown 7)
)
(if (== (pEvent type?) evMOUSEBUTTON)
)
(if(Said 'show/death')
(= deathWindowOpen 1)
(= deathWindow (NewWindow
0
0
190
318
{Death Count}
nwNORMAL
15 ; priority
7
15
))
; For loop to run through the gDeath array and print a statement of death for each that is true
(for ( (= i 0)) (< i 9)  ( (++ i)) (if (> [gDeaths i] 0)
(switch i
(0
(Display
(Format @str {You have died %u times:} [gDeaths 0])
dsCOORD 10 textDown
)
(= textDown (+ textDown 12))
)
(1
(deathCountIterator)
)
(2
(deathCountIterator)
)
(3
(deathCountIterator)
)
(4
(deathCountIterator)
)
(5
(deathCountIterator)
)
(6
(deathCountIterator)
)
(7
(deathCountIterator)
)
)
)
)
)
)
)

(procedure (deathCountIterator)
(Display
(Format @str 650 i)
dsCOORD 20 textDown
dsFONT 4
)
(= textDown (+ textDown 9))
)
Attached is how the window looks in the roomscript, and the termination command works just fine (but doesn't work well at all in the Main)
Title: Re: SCI0 - Globalizing my local death sheet Script
Post by: Kawa on February 20, 2022, 02:59:18 PM
1. Something like a death screen doesn't need to be a Room per se, but you certainly don't want it as part of Main there's no reason to keep a large script that may not be needed for a long time in memory.

2. Display or Print... why not a third option? Print is just a convenience function that populates a Dialog, after all, so why not use a Dialog but not Print? That'll take care of both dismissing the window and having a complicated layout inside of it.
Title: Re: SCI0 - Globalizing my local death sheet Script
Post by: Doan Sephim on February 20, 2022, 03:06:38 PM
1. Something like a death screen doesn't need to be a Room per se, but you certainly don't want it as part of Main there's no reason to keep a large script that may not be needed for a long time in memory.

2. Display or Print... why not a third option? Print is just a convenience function that populates a Dialog, after all, so why not use a Dialog but not Print? That'll take care of both dismissing the window and having a complicated layout inside of it.
1. Any suggestions on a good place to put it? I'm not great when it comes to reading/editing the template and I've never been successful in creating my own script (that wasn't a region or regular roomscript)

2. Sounds like a good idea re: Dialog. Do you know where I can look to find the basics for it? I'm not very familiar with it.
Title: Re: SCI0 - Globalizing my local death sheet Script
Post by: Kawa on February 20, 2022, 04:52:30 PM
Just pick a number that isn't taken by a script yet, I guess? As for how to do a custom Dialog, I'd say study the Print function.



The Print function uses temporary variables to hold a Dialog instance, one DText, one icon, one DEdit, and up to six DButtons, plus a bunch of things to track all that. It first instantiates a new Dialog ((= hDialog (Dialog new:))) and DText, then figures out what text to put in there (is it a Text tuple or a script pointer?), and finally adds the DText to the Dialog ((hDialog add: hDText)). It then goes through all the other arguments, if any, adding icons, setting titles, adding and tracking buttons, and moving things around. Finally, it opens the Dialog, calls Dialog::doit to get the user's response, and disposes it again ((hDialog open: nwNORMAL -1 doit: dispose:), to simplify).

Therefore, here's what I'd do, off the top of my head:
Code: [Select]
(procedure (DeathReport &tmp hDialog hText [str 512] theY)
(= hDialog (Dialog new:))

(Format @str {You have died %u times:} [gDeaths 0])
(= hText (DText new:))
(hText
text: @str
moveTo: 4 4
font: 0
setSize:
)
(hDialog add: hText)
(= theY (+ 4 (hText nsBottom?)))

;;; The iteration starts here
; Put something new in str
(= hText (DText new:))
(hText
text: @str
moveTo: 4 theY
font: 4
setSize:
)
(hDialog add: hText)
(= theY (+ 4 (hText nsBottom?)))
;;; Repeat that part until you're done.

(hDialog
text: {Death Count}
setSize:
center:
open: nwTITLE -1
doit: ; This should block until you click the dialog. Or a button, which we didn't add.
dispose:
)
)

You might wonder if it's safe to reuse hText like that. Well, SCI10's PrintD does it, and that does in fact allow more arbitrary layouts than SCI0's Print. (https://helmet.kafuka.org/logopending/2020/08/11/print-printd-and-the-other-print/)
Title: Re: SCI0 - Globalizing my local death sheet Script
Post by: Doan Sephim on February 20, 2022, 08:33:55 PM
Thanks Kawa. I'm trying to use the procedure you posted to get started with, but it's coming up with the "oops" error, so I'm not sure where things aren't working. It compiled just fine...

If I'm reading your code and comment correctly, it looks like the important thing I need to add a particular number of lines to a single window is DText (and as you mentioned reusing the hText) for DText.

I will keep playing around with this to see if I can start with something simple and build my understanding from there.

Edit: I seem to have localized the area leading to the crash:
Something in this part seems to cause the crash. With this removed, the procedure runs its course while displaying nothing
Code: [Select]
(hDialog
text: {Death Count}
setSize:
center:
open: nwTITLE -1
doit: ; This should block until you click the dialog. Or a button, which we didn't add.
dispose:
)
Title: Re: SCI0 - Globalizing my local death sheet Script
Post by: Kawa on February 21, 2022, 08:18:32 AM
I did write that off the top of my head without testing. Try doit: 0?
Title: Re: SCI0 - Globalizing my local death sheet Script
Post by: Doan Sephim on February 21, 2022, 08:51:21 AM
I did write that off the top of my head without testing. Try doit: 0?
Wow! I definitely don't have that kind of competence to write code in my head.

doit: 0 still yields error.

When I have time, I'll keep looking
Title: Re: SCI0 - Globalizing my local death sheet Script
Post by: Kawa on February 21, 2022, 09:00:23 AM
If I had competence, it would've worked 😺
Title: Re: SCI0 - Globalizing my local death sheet Script
Post by: Doan Sephim on February 21, 2022, 10:14:24 AM
Does anyone how QfG1 did something similar with its inventory screen? That could be a good place for me to look if we have the script
Title: Re: SCI0 - Globalizing my local death sheet Script
Post by: doomlazer on February 21, 2022, 01:32:17 PM
This?
https://github.com/EricOakford/SCI-Decompilation-Archive/blob/master/qfg1ega/src/InvSheet.sc

You'd need to convert the display's p_at, p_mode, etc. back to using dsCOORD, dsALIGN, etc.
http://scicompanion.com/Documentation/Kernels/Display.html

Looks like the InvSheet is activated from the handleEvent method of the menuBar script in QFG1:
https://github.com/EricOakford/SCI-Decompilation-Archive/blob/master/qfg1ega/src/Menu.sc

Code: [Select]
((ScriptID INVSHEET 0) init: doit:)
Title: Re: SCI0 - Globalizing my local death sheet Script
Post by: Doan Sephim on February 21, 2022, 02:43:42 PM
Thanks for the links! This looks fruitful, albeit a bit above my knowledge level, but I'm able to at least make out what's going on. Converting it and structuring for my own use...we'll see  ;)
Thanks again for the links

If I were to make my own script, I would clearly use "Main" and "System", but I don't know what to do about "Invent" or if I'd need to include other scripts from the template
Title: Re: SCI0 - Globalizing my local death sheet Script
Post by: doomlazer on February 21, 2022, 03:01:32 PM
Keep in mind I'm wrong at least half the time, but (use inv) might be the SCI0 template equivalent of (use Invent). Maybe try commenting out ;(use Invent) and see if it compiles without it. That would at least help identify what it needs from Invent.

You will probably need to change (include game.sh) to (include sci.sh). That should make the dsCOORD, etc. compile.
Title: Re: SCI0 - Globalizing my local death sheet Script
Post by: Doan Sephim on February 21, 2022, 03:05:54 PM
Keep in mind I'm wrong at least half the time, but (use inv) might be the SCI0 template equivalent of (use Invent). Maybe try commenting out ;(use Invent) and see if it compiles without it. That would at least help identify what it needs from Invent.

You will probably need to change (include game.sh) to (include sci.sh). That should make the dsCOORD, etc. compile.
That's funny, I just had that issue :D At the moment I have the following:

Code: [Select]
(include sci.sh)
(include game.sh)
(use Main)
(use User)
(use SysWindow)
and that fixed the dsWHATEVER problem you anticipated I was having XD It took me longer than I am comfortable sharing before I realized it was probably my includes causing the issue.
Title: Re: SCI0 - Globalizing my local death sheet Script
Post by: doomlazer on February 21, 2022, 03:13:28 PM
My fault, I should have mentioned sci.sh in the first place when changing back to dsCOORD.
Title: Re: SCI0 - Globalizing my local death sheet Script
Post by: Doan Sephim on February 21, 2022, 03:32:31 PM
Okay, rewriting the whole script and editing it piece by piece isn't going to work for me with all the different syntax and especially different classes that I can't access on my end. I'm just going to try and focus on the part that I'm having the most difficulty with, and that is the process of iterating through a series of variables and displaying something on those that are true. This seems to be the relevant code:
Code: [Select]
(method (init &tmp i temp1 y fgColour totalWeight [str 40])
(super init:)
(= theWindow
(NewWindow nsTop nsLeft nsBottom nsRight {} 0 -1 vBLUE vWHITE)
)
(Display 206 1 p_at 10 8 p_mode teJustLeft p_font 300 p_color vBLUE)
;You Are Carrying:
(= totalWeight (WtCarried))
(= i 1)
(= y 24)
(while (<= i 41)
(if (and (> [invNum i] 0) (> i 2))
(if (<= y 160)
(DisplayInventoryItem i 10 y)
)
(= y (+ y 9))
)
(++ i)
)
(cond
((== y 24)
(Display 206 2 p_at 40 (+ y 5) p_mode teJustLeft p_font 300 p_color vBLUE)
;Nothing
)
((>= y 174)
(Display 206 3 p_at 40 172 p_mode teJustLeft p_font 300 p_color vBLUE)
;. . . and more
)
)
this while loop is actually very similar to how I had tried to do this with my for loop. It'll make a new window than display things accordingly, which I think is the same thing I tried...so I guess I'll just have to figure out what the major differences are. This is so much headache for something that seems so simple and easy.
Title: Re: SCI0 - Globalizing my local death sheet Script
Post by: doomlazer on February 21, 2022, 04:28:59 PM
If I'm understanding the current issue correctly, your iterator is displaying all possible deaths listed in 650.txt, not just the ones that have happened to the player?
Title: Re: SCI0 - Globalizing my local death sheet Script
Post by: Doan Sephim on February 21, 2022, 04:41:37 PM
No, the iteration is working properly. It's only showing the ones that have their conditions met.

The thing I'm having problems with is writing the code to properly display them in a window, and then closing that window. I build the code in a random roomscript and it works, but I'm not able to make it its own script (so that I can trigger it from say, the menubar)
Title: Re: SCI0 - Globalizing my local death sheet Script
Post by: doomlazer on February 21, 2022, 05:40:19 PM
I tested this in the SCI0 template and it "works"

Code: [Select]
;;; Sierra Script 1.0 - (do not remove this comment)
(script# 777)
(include sci.sh)
(use Main)
(use SysWindow)
(use Obj)

(public
theInvSheet 0
)



(class InvSheet of Obj
(properties
nsTop 10
nsLeft 10
nsBottom 40
nsRight 160
theWindow 0
)

(method (init &tmp i temp1 y [str 40])
(super init:)
(= theWindow
(NewWindow nsTop nsLeft nsBottom nsRight {} 0 -1 clBLUE clWHITE)
)

;your iterate over deaths code here
(Display
(Format @str {You have died test times:} )
dsCOORD 10 10
)
                ;end iterate code
)

(method (doit &tmp newEvent newEventType)
(= newEventType 0)
(while (not newEventType)
(GlobalToLocal (= newEvent (Event new:)))
(= newEventType (newEvent type?))
(newEvent dispose:)
)
(self dispose:)
)

(method (dispose)
(DisposeWindow theWindow)
(super dispose:)
(DisposeScript 206)
)
)

;;;(procedure (deathCountIterator)
;;; (Display
;;; (Format @str 650 i)
;;; dsCOORD 20 textDown
;;; dsFONT 4
;;; )
;;; (= textDown (+ textDown 9))
;;;)

(instance theInvSheet of InvSheet
(properties)
)


call the window with:
Code: [Select]
((ScriptID 777 0) init: doit:)

Title: Re: SCI0 - Globalizing my local death sheet Script
Post by: Doan Sephim on February 21, 2022, 09:03:23 PM
Great! That worked perfectly once I incorporated my iteration code.

I think the thing I was really missing out on was what class to make it. I think I was confused when I tried to follow the QfG1 script's direction when I also made it of the object class, but Companion didn't like that because I didn't realize in the template game the class is Obj (and the capital O matters!)

Thanks for helping me troubleshoot this. It feels really good to have this squared away.
Title: Re: [SOLVED] SCI0 - Globalizing my local death sheet Script
Post by: doomlazer on February 21, 2022, 10:10:35 PM
That decompile archive is a valuable reference, once you get used to a few minor differences from the template game. You can basically just look up how the Sierra devs solved these problems.