Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Charles

Pages: [1] 2 3 ... 7
1
SCI Syntax Help / Re: [SOLVED] SCI0 - Autosave
« on: January 05, 2021, 09:10:08 AM »
QfG3 had autosave, too... although they only used it like 2 or 3 times, if I recall right.

2
SCI Community How To's & Tutorials / Re: Retry/Restore/Quit Death Dialog
« on: December 10, 2020, 10:58:14 PM »
That reminds me, the use statements in the DeathScript are referencing my custom file names. I prefaced system scripts with an underscore for easier file sorting, so those are completely non-standard.
Interface is script 255, Inventory and System are in the 900s. I don’t recall exactly which right now, on my phone. I’ll have to sort that out and update the post to make it more compatible with the Template Game.

I know Phil mentioned making the use statements redundant was on his TODO list at one point. Kawa, is that implemented in your latest SCICompanion build?

3
SCI Community How To's & Tutorials / Re: Retry/Restore/Quit Death Dialog
« on: December 10, 2020, 05:39:41 PM »
Ah yeah, I agree. ProgramControl and PlayerControl look analogous to HandsOff and HandsOn.

If you’re not comfortable changing all your variable names (which I get), try at least importing some of the headers from the template game in, so you’ll have access to the newer defines.

4
SCI Development Tools / SCI01 interp decompiling
« on: December 10, 2020, 04:58:52 PM »
So I was procrastinating on another project and idly wondering what it would take to decompile the SCI01 interpreter and re-incorporate text parser code into SCI11.

This is a nearly 30 year old program.. surely there must be decent decompilation software out there now, right?  I found one called Reko Decompiler that looked promising.  I opened it up, but it reported the file was compressed with LZEXE.  I noticed that Eric already knew that, and has already decompressed it in the SCI01 template.  But when I opened it up again in Reko, I found it was still partially compressed a second time with EXEPACKER.

So after hunting far and wide, I finally found a dead link to a DOS program that can unpack EXEPACKER files. A trip to the WayBackMachine found a working link, and in DOSBOX I was able to uncompress it yet again.

Now, Reko was able to process the thing. And here's where I've reached my level of incompetence. There were a small handful of errors decompressing, but there looks to be actual code -- that is bereft of any ral variable names -- so it might as well be gibberish to me.  Anyway, I've gone as far as I probably can with it, but I thought it was interesting that the EXE was compressed in two different ways, and wanted to share. I've also attached the hard to find unpack.exe, if somebody else wanted to give it a go.

5
SCI Community How To's & Tutorials / Re: Retry/Restore/Quit Death Dialog
« on: December 10, 2020, 03:10:36 PM »
I'd like to help reconcile my variable names to your variable names. Is your code based off Eric's SCI0 template?  (If you're basing it off of old SCI Studio script and naming conventions, I'm pretty clueless there).

I'm not sure HandsOff translates to ProgramControl.  In Eric's Template HandsOff and HandsOn are global functions defined in main.sc:
Code: [Select]
(procedure (HandsOn)
;Enable ego control
(= isHandsOff FALSE)
(User canControl: TRUE canInput: TRUE)
(theGame setCursor: normalCursor (HaveMouse))
)

(procedure (HandsOff)
;Disable ego control
(= isHandsOff TRUE)
(User canControl: FALSE canInput: FALSE)
(theGame setCursor: waitCursor TRUE)
(ego setMotion: 0)
)

The normalCursor variable is the same as global20, from main.sc (so starting at 0, count down to variable number 20); theGame is global01; sounds is global08; quit is global04;

deathMusic is a variable unique to QFG1GA. You may not have it in yours. You'll have to comment out that line in that case.

Edited to add:
'music' is a reference to an instance of Sound near the bottom on main.sc, in mine:
Code: [Select]
(instance music of Sound
(properties
number 26
priority 10
)
)
I think you probably have similar. Eric's Template stores that instance in a variable called theMusic. It appears QFG1EGA only calls it directly.

6
SCI Community How To's & Tutorials / Re: Retry/Restore/Quit Death Dialog
« on: December 09, 2020, 10:07:08 PM »
Thank you for posting that. A large part of my inspiration was my vague memory of that feature in LSL6.  I believe there's also one whereby you get electrocuted by the electric fence... although I seemed to recall after you did that once, they just removed the death the next time, and said something like "Not doing that again."... no sense telling the same joke twice, I guess.

I never bothered to look into how they did it, before proceeding with my own take. Looks fairly similar to how I implemented, but a bit cleaner... I think I kinda like that they passed a script reference to EgoDead, and let it cue: to the next state.

I've wanted to do this since about the time AGD was working on their KQ1VGA remake. I even suggested it to them, citing LSL6, after I had unexpectedly died by clicking on a large boulder from the wrong side. They passed... I think they said it didn't stay true to the original Sierra vibe they were going for. What was that, nearly 20 years ago?  Gads.

7
The Games and other Sierra Adventure stuff / Re: What are we working on?
« on: December 09, 2020, 03:27:34 PM »
Would it be rude of me to implement just the death counter and type in my game similar to what you are doing here? I think it's a really cool idea.

I absolutely welcome it. I'm happy it's been as well received as it has. I'm not sure if you could implement just the death counter without the Retry option, but I wrote up a couple page tutorial on how I did what I did http://sciprogramming.com/community/index.php?topic=1946.0.

8
SCI Community How To's & Tutorials / Re: Retry/Restore/Quit Death Dialog
« on: December 09, 2020, 03:23:46 PM »
And lastly, the fun part: displaying the Deaths in game!

A couple caveat to this, I think this code can be improved a bunch. It has a limitation that it will only show 60 deaths.  I want to use a paged view, but I couldn't get that working. So if somebody else wants to do that, I'd love to see it. As a consequence of that limitation, whatever the most recent death is will always be shown 1st in red. Then all the rest will show, up to 60.

Another limitation is that I don't save every new death since this screen was last viewed... only the most recent death.  I'm kinda assuming that most players will check the death log right away, but I'm very biased about that because that's just what i did (it being a new and exciting feature and all).

This is basically a modification of QFG1EGA's Inventory Sheet.  That's where the majority of the code came from, I just modified it to fit these purposes.  I used room 650. The real secret to this though is text.651.  This is a hand-written brief account of each death, starting at 0.  text 651 0 equals death DIE_START (or 450 from our initial enum).  It makes it a pain to reorder any deaths. And this order is the order they're ultimately displayed on screen.

Code: [Select]
;;; Sierra Script 1.0 - (do not remove this comment)
(script# 650)
(include system.sh) (include sci2.sh) (include game.sh)
(use Main)
(use _Inventory)
(use _System)
(use _Interface)

(public
theDeathSheet 0
)

(define SMALL_LINE_HEIGHT 9)

(procedure (DisplayDeathText death x y &tmp invQty [str 40])
(Display
651 (- death DIE_START)
p_at (+ x 5) y
p_mode teJustLeft
p_font smallFont
p_color (if (== death prevDeathNum) vLRED else vLBLUE)
)
;display name of death
)

(procedure (DisplayDeathHeader &tmp [str 40])
;Displays a different header depending on how many deaths we've had
;
(cond
((== deathCount 0)
(Display
650 0
p_at 10 8
p_mode teJustLeft
p_font 300
p_color vBLUE
)
;You haven't died at all. Don't be afraid to explore and try new things.
)
((== deathCount 1)
(Display
650 1
p_at 10 8
p_mode teJustLeft
p_font 300
p_color vBLUE
)
;You have died once.
)
((== deathCount deathCountUnique)
(Display
(Format @str 650 2 deathCount)
p_at 10 8
p_mode teJustLeft
p_font 300
p_color vBLUE
)
;You have died %u times.
)
(else
(Display
(Format @str 650 3 deathCount deathCountUnique)
p_at 10 8
p_mode teJustLeft
p_font 300
p_color vBLUE
)
;You have died %u times, in %u unique ways
)
)
)

(procedure (DisplayDeathPage pageStart offset &tmp i x y nextDeathStart)
(= i pageStart)
(= x 10)
(= y (+ 24 (* offset SMALL_LINE_HEIGHT)))
(= nextDeathStart 0)
(while (<= i DIE_END) ;there are currently 60 deaths. So that's how many we will show.
;if this is a true death, and it doesn't match the most recent death
(if (and (Btst i) (not (== i prevDeathNum)) )
(if (<= y 160)
;display the death text
(DisplayDeathText i x y)
else
;otherwise, make note of where to start the next page, and end this page.
(= nextDeathStart i)
(= i DIE_END)
)
;increment to the next line. If the next line is too far down, shift to the next column
(= y (+ y SMALL_LINE_HEIGHT))
(if (and (> y 160) (== x 10))
(= y 24)
(= x 170)
)
)
(++ i)
)
(return nextDeathStart)
)

(class DeathSheet of Object
(properties
nsTop 0
nsLeft 0
nsBottom southEdge
nsRight MAXRIGHT
theWindow NULL
state 0
register 0
more FALSE
startAt 0
)

(method (init &tmp i x y pageStart [str 40])
(super init:)
(self clearWindow:)
(self drawContents:)
)

(method (drawContents &tmp pageStart offset)
;decide what header to show
(DisplayDeathHeader)

;if there's a new death, we'll show that at the top row
(= offset 0)
(if prevDeathNum
(DisplayDeathText prevDeathNum 10 24)
(= offset 1)
)

;now we show the individual deaths.
(= pageStart (DisplayDeathPage (+ DIE_START startAt) offset))

(if (> pageStart DIE_START)
(= startAt pageStart)
(= more TRUE)
(Display 206 3 p_at 200 172 p_mode teJustRight p_font 300 p_color vBLUE p_width 100)
;(and more . . .)
else
(= more FALSE)
)
;now show the second page, then third page, etc. until we're done.

;clear any "Previous Death" flags.
(= prevDeathNum 0)
)

(method (clearWindow &tmp newWindow)
(= newWindow
(NewWindow nsTop nsLeft nsBottom nsRight {} nwNORMAL nwON_TOP vBLUE vWHITE)
)
(if theWindow
(DisposeWindow theWindow)
)
(= theWindow newWindow)
)

(method (doit &tmp newEvent evtType)
(= evtType nullEvt)
(while (not evtType)
(GlobalToLocal (= newEvent (Event new:)))
(cond
((not more)
(= evtType (newEvent type?))
)
((and (== keyDown (newEvent type?)) (== KEY_ESC (newEvent message?)) )
;there's more to see, but the user has clicked ESC
(= evtType (newEvent type?))
)
((not (== nullEvt (newEvent type?)))
;do anything else
(= evtType (newEvent type?))
;CI: TODO: Show a second page.
;(Print {Skip to next page})
;(self clearWindow:)
)
)

;(= evtType (newEvent type?))
(newEvent dispose:)
)
(self dispose:)
)

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

(instance theDeathSheet of DeathSheet
(properties)
)

Then some brief modifications to the Menu script, to get it to show as an option. In a few places. 
I've given easy names to reference them. Sierra measures them in hex, so $500 is 0x500 = 1280. And that's the 5th drop down menu.

You have to manually line these enums with the AddMenu below, if you want to reference the menu items by name.
Code: [Select]
(enum
$500 infoM
invI
charI
divider501I
timeI
askI
lookI
divider502I
deathsI
)
I decided on CTRL-H for the DeatH List. I had also changed the Time/Day to line up with QFG2.
Note each entry is seperated by a : and --! represents a line. ^ is CTRL.
Code: [Select]
(AddMenu
{ Information_}
{Inventory`^i:Char Sheet`^s:--!:Time/Day`^d:Ask about`^a:Look at`^l:--!:Deaths List`^h}
)

since the DeathScreen is pretty much a copy of the Inventory Screen, I copied the same requirements before loading it. It won't load in the Brigand Dining Hall (I guess before it uses a lot of memory?) nor if there's less than 2000 bytes(?) of memory free.
Code: [Select]
(method (handleEvent event &tmp [i 3] newVol [str 300] temp304)
(switch (super handleEvent: event)
(deathsI
;(Print {Not yet implemented.} #title {Deaths List})
(cond
((or (not (HaveMem 2000)) (== curRoomNum 95)) ;brigand dining hall (presumably, this room requires a lot of memory)
(HighPrint MENU 5)
;Sorry, there's not enough room to see that here.
)
((not isEgoLocked)
((ScriptID 650 0) init: doit:)
)
)
)
)
)


NOTE: Using pretty much the exact same design, it should actually be pretty easy to also implement a Points Screen, to see exactly where you're gotten the points you're at.

9
SCI Community How To's & Tutorials / Re: Retry/Restore/Quit Death Dialog
« on: December 09, 2020, 03:06:53 PM »
To implement the Retry in game scripts, you have to make a slight mental change to how you think of EgoDeath dialogs.

In classic Sierra games, once the EgoDead function has been called nothing else in the script matters. The current game state is effectively destroyed. The only way to go from there is reload the game state (Restore), restart the game state from scratch (Restart), or just closing the game state altogether. As a consequence, there was no clean-up to worry about in those game scripts.

With Retry now as a viable option, you must assume that the current game state is still active. The current game state is only destroyed if the user explicitly restores or quits.  Immediately after the call to EgoDead in your game script, you must reset the scene.

For simple dialog-only deaths, that's easy... nothing has moved, you can just pick up and carry on.

For more complex deaths where there is some animation or scripting happening before the actual death, you must manually reset the positioning and visible state of all actors and views and close (or NULL) any open scripts.  In some cases this also means changing how some items are displayed. I came across some AddToPic commands for some views, that could no longer be a constant part of the scene where Retry was a possibility.

There are some instances where you'll want to move Ego to a previous screen during a Retry. In that case, set another flag to let that room know you're entering it because of a Retry. If there are more than 1 retries that take you to that room, use a few flags.  I found an unused flag in QFG1, and called it DIE_RETRY_INPROGRESS.  For the Target Range (when spying on Bruno, I also added in ENTERROOM_WEST and ENTERROOM_EAST to know which side of the room to replace them.)

The good news though, is these can be tackled one at a time without breaking your game's ability to compile. Because the EgoDead is backwards compatible with existing EgoDead script calls.

Now as for the actual syntax, a classic EgoDead call looks like this:
Code: [Select]
(EgoDead
0 28
#title {The surgeon general warns . . ._}
#icon (GetEgoViewNumber vEgoDeathScenes) 0 0
)
Specify the view, then the title, icon, etc.
With the new EgoDead function there are 2 new ways to call it.  If you want a Retry death, without recording that  death happened, use the DIE_NOFLAG command as your first parameter, then continue the rest as normal.
Code: [Select]
(EgoDead
DIE_NOFLAG
0 28
#title {The surgeon general warns . . ._}
#icon (GetEgoViewNumber vEgoDeathScenes) 0 0
)

But, if you want to really take advantage of the Retry, but incrementing the Death counter, you pass the special define DIE_RETRY and the flag number:
Code: [Select]
(EgoDead
DIE_RETRY DIE_PICKNOSE
0 28
#title {The surgeon general warns . . ._}
#icon (GetEgoViewNumber vEgoDeathScenes) 0 0
)

There is one more special flag, and this is mostly for debugging purposes.  When I was working through updating each death one by one, it helped to do a quick Text Search and find all that I had left to do.  For that, you can update each EgoDead reference to use the special DIE_RESTART flag.  This still produces a Restore/Restart/Quit dialog, but it allows you to do a global search on EgoDead DIE_RESTART and find all remaining instances.
Code: [Select]
(EgoDead DIE_RESTART
0 28
#title {The surgeon general warns . . ._}
#icon (GetEgoViewNumber vEgoDeathScenes) 0 0
)

10
SCI Community How To's & Tutorials / Retry/Restore/Quit Death Dialog
« on: December 09, 2020, 02:45:32 PM »
As I detailed in the "What are we working on?" thread earlier, I've modded QFG1EGA to implement a "Retry" feature when the Hero dies.

I was absolutely floored by the positive encouragement I've received in the community, so I wanted to share how I implemented it, so others could also implement in their games (or mod existing Sierra games).

My goal with "Retry" was to remove a potential point of frustration for new (and old) players being punished for exploring the game and trying things. However, I didn't want to eliminate the deaths entirely, because they are a fundamental part of the Sierra experience, and are part of each Sierra game's unique charm.

My particular solution was to replace game-ending deaths with an additional achievement system, which not only keeps track of which deaths the user encountered but also displays them (like QFG1EGA's inventory screen).

I chose a "minimally invasive" approach, whereby I only reverted the specific events that caused the death (and any items directly branched off from that death, if the death wasn't instant), leaving the rest of the users experiences intact.

I had to modify/add five things to make this happen:
  • game.sh (modified)
  • main.sc (modified)
  • menu.sc (modified)
  • DeathSheet.sc (added)
  • any script that calls the EgoDead function

To keep track of each unique death, I created an Enum. Because this can grow fairly large (QFG1EGA had 79 Unique Deaths), I decided to create a new file and reference it in game.sh, rather than putting everything into game.sh itself.
Code: [Select]
;These are death flags. They're used to track which ways the user has died. 
;They will be shown at the end of the game.

; unique deaths
(define DIE_RESTART -2) ;show Restore, Restart, Quit; (same as not specifying anything at all) instead of Retry, Restore, Quit)
(define DIE_RETRY -1) ;show a Retry, Restore, Quit
(define DIE_NOFLAG -1) ; a retry is shown, but nothing is flagged.
;explicitly define the starting number, ending number and death count, which will be used in the DeathSheet script.
(define DIE_START 450)
(define DIE_COUNT 79)
(define DIE_END 528)
;there are roughly 100 deaths, so we'll reserve flags 450-550 for them (with room for 50 more in expansion up to flag 600)
(enum 450
DIE_NOSTAMINA
DIE_PICKNOSE
DIE_ARRESTED
DIE_NIGHTGAUNT
)

Next up is modifying the EgoDeath function in main.sc.  Keeping track of the different deaths is done with the eventFlags variable, and Btst, Bclr, Bset. I don't know if every Sierra game includes them or not, so if they're not present, you'll need to add them. the eventFlags variable must be an array. Each byte of the array can hold 16 bits (or 16 individual flags).  QFG1EGA allocated 50 bytes (800 flags), and didn't use nearly all of them, so I was able to just use them without allocating any more space.
Code: [Select]
(procedure (Bset bit)
(= [eventFlags (/ bit 16)]
(|
[eventFlags (/ bit 16)]
(>> $8000 (mod bit 16))
)
)
)

(procedure (Bclr bit)
(= [eventFlags (/ bit 16)]
(&
[eventFlags (/ bit 16)]
(~ (>> $8000 (mod bit 16)))
)
)
)

(procedure (Btst bit)
(return
(&
[eventFlags (/ bit 16)]
(>> $8000 (mod bit 16))
)
)
)

Then the EgoDeath function. In QFG1EGA it's the first global function in main.sc, so I assume that's constant across all Sierra games.
Code: [Select]
(enum 1
RESTORE
RESTART
QUIT
RETRY
)

(procedure (EgoDead what how &tmp printRet)
;stops all sounds, plays the death music, and gives the player a choice:
; Restore, Restart, Quit or
; Retry, Restore, Quit
;
; 'what' decides what we're doing: Restart or Retry.
; if 'what' == DIE_RETRY (-1), it's a Retry death;
; if 'what' == DIE_RESTART (-2), it's a Restart death (explicitly defined).
; any other values are assumed to be the original EgoDead function, for a Restart death (implicitly defined),
; and should be fully passed to the Print procedure.
;
; 'how' is this specific death's flag, to be set in the eventFlags variable, via the Bset function
;
; (CI: NOTE: This procedure is a recreation, based on Eric Oaklands's SCI01 template)
; https://github.com/EricOakford/SCI01-Template/blob/master/src/Main.sc
; it has been modified to more closely match the original asm, which is commented out but intact above,
; then has been further modified to support a Retry mode.

(HandsOff)
(Wait 100)

(theGame setCursor: normalCursor TRUE)
(sounds eachElementDo: #stop)

(if (!= deathMusic NULL)
(music number: deathMusic priority: 15 init: play:)
)

;if we're specifying a way the player died, then we'll set the flag for that death method.
(if (and (== what DIE_RETRY) (!= how DIE_NOFLAG))
(++ deathCount)
(= prevDeathNum how) ;we're going to flag out *every* time the hero dies.
(if (not (Btst how))
(Bset how)
(++ deathCountUnique)
)
)

(repeat
(= printRet
(cond
;1st priority: the new Retry dialog
((== what DIE_RETRY)
(Print &rest
#width 250
#button { Retry_} RETRY
#button {Restore} RESTORE
#button { Quit_} QUIT
)
)
;2nd priority: an explicit DIE_RESTART flag with no second parameter
((== what DIE_RESTART)
(Print how &rest
#width 250
#button {Restore} RESTORE
#button { Restart_} RESTART
#button { Quit_} QUIT
)
)
;finally, any original script EgoDeath scripts
((>= what 0)
(Print what how &rest
#width 250
#button {Restore} RESTORE
#button { Restart_} RESTART
#button { Quit_} QUIT
)
)
)
)
(switch printRet
(RESTORE ;restore
(theGame restore:)
)
(RESTART ;restart
(theGame restart:)
)
(QUIT ;quit
(= quit TRUE)
(break)
)
(RETRY ;retry
(if (!= deathMusic NULL)
(music stop:)
)
(HandsOn)
(break)
)
)
)
)

If you wanted, you could stop here and compile your game without changing anything else. All existing calls to EgoDead will continue to function as they always have, bringing up the RESTORE/RESTART/QUIT dialog.

I'll describe the DeathSheet and actually implementing the new EgoDead function in game script in the next post.

EDIT: I forgot, I also added a couple of global variables to main.sc.  There were several unused variables in QFG1EGA, so I was able to just rename one of them, without adding any more.
Code: [Select]
deathCount ;added by CI: the total number of times Ego has died (shown on the Death List)
deathCountUnique ;added by CI: the number of unique ways Ego has died (shown on the Death List)
prevDeathNum ;added by CI: Used to highlight the most recent death in the Death List.

11
The Games and other Sierra Adventure stuff / Re: What are we working on?
« on: December 07, 2020, 11:45:40 AM »
Wouldn't you also need to store all status, inventory items, etc. right before ego enters the situation that kills him for the retry? Wouldn't that require modification at each danger point?
That's exactly the sort of challenge I faced at the outset. Most of the time, if you die it's because of something you immediately did wrong. Like step on the wrong trap in the Brigand Fortress, or fall down a hole in the Graveyard, etc. Those are easy. Just back track to right before you did that one thing -- reposition ego, reset any views, undo any flags.

But my earlier example of destroying the spitting plants... you might do that early on in the game, and then forget about it... you could have done dozens of tasks and played through a handful of game days between destroying those plants and actually meeting the Dryad face to face. Others may approach the solution differently, but I decided on a minimally invasive approach to the Retry. In other words, I only change the one specific thing that caused you to die (and anything directly related to it).  Anything else you may have done after killing the plants still happened... time doesn't reverse, your stats aren't reversed, the only thing that changed is that Retry brings you back in the spitting plant room and the plants are alive (and the seed is out of your inventory and back with the plants). Now you can Retry to get the seed the proper way.

Similar thing if you died in battle, or because your stats were too low.  I don't reverse any skill improvements you made. With the premise that this is a game and above all, should be fun... if you died because your character wasn't good enough, it would be incredibly frustrating to be put back right where you were, with skills still too poor.  You're just going to need to grind again anyway...  There are dozens of places where the hero can lose HP (and thus potentially die). I took different approaches in different contexts... in some, I revert the HP to before whatever caused them to die... in others, I just restore them to a token 50% HP or such.

And if people are concerned about "cheating" or getting a freebie or having an unfair advantage because they clicked Retry, well, it's not free... it's marked off in their Death List.  That's why I not just mark the unique deaths, but the total number of deaths.  You're still free to Save/Restore if you want the extra challenge. That's entirely on you.

I also don't remember, but does the Mandrake plant grow back if you take it in the daytime?

Even if it does grow back, I think if you try to take it the day you get the Baba Yaga quest it won't be there for you at midnight, resulting in an unwinnable state. Probably just having it spawn at midnight would solve this problem.

Also, I love the death achievement log! I'm not sure how you are achieving that, but I would love to add something like that to my current project...but I guess it includes a huge overhaul of the entire save/restore system. Still, I really love it!

The Mandrake is similar to killing the plants.  It isn't a walking dead state, like not getting the seed on time.  True, the mandrake doesn't respawn.  But if you agree to get Baba Yaga her mandrake (and if you don't agree, you die) then you have 3 days to do so. If you don't do it in that time, you die.  So I respawn the mandrake on that Retry.  It may not be the most intuitive, and I may still tweak it, but I wanted to stay as true as possible to the original intent of the game... it's completely subjective... I'm just some schlub editorializing someone else's work. Obviously if you implemented this in your own project, it's entirely your choice to decide how to handle it.

Speaking of, I don't think it's as daunting a task as you imagine to retro fit it.  Yes, I had to edit almost every script (and especially every script that had a death), but I wrote my modified EgoDead function so that I could fix things up piecemeal. I'll try and post the code later today in another thread, but basically, you can update the EgoDead function and change nothing else, and the game will properly recompile and all the existing Restore/Restart/Quit dialogs will remain unchanged.  Then you can go through one by one, and update the existing Deaths at your leisure.

12
AGI Development Tools / Re: WinAGI Version 2.1.2 Is Available
« on: December 07, 2020, 11:24:48 AM »
Or VB.Net.  I used to be a big VB6 guy back in the day but I switched to VB.Net 10 years ago (more?) and now I physically shudder whenever I need to touch legacy VB6 programs at work.  C# and VB.Net compile to the exact same thing 99.999% of the time anyway; I just personally find the VB syntax easier to use than the C# syntax.

13
The Games and other Sierra Adventure stuff / Re: What are we working on?
« on: December 07, 2020, 12:04:03 AM »
However, what about dead-ends? I guess you'll have to restore, and lose any unsaved death achievements?
Are there any dead-ends in QfG1?

Yeah, the dead-ends are still a problem. I think they’re only related to the dispel potion though. If you don’t take the seed in the first place, or you waste your potion once it’s made. I think the best fix there is to not limit the times you can get the ingredients. Maybe with the Dryad (or whoever else) grumbling about the hero needing it again.

Speaking of achievements, there’s no reason one couldn’t also implement a Points List screen that lists off everything you’ve done to score points (or conversely, what’s left to score). Heck, I bet it could even be tied into the Gog or Steam Achievements API somehow. That’d be neat.

If there’s any interest, I might write a tutorial post on how to convert other existing games to use Retry/Restore/Quit. I coded it in such a way, it can be a drop-in replacement to the stock EgoDead function in Main. Then you can update each Restore/Restart/Quit one at a time without breaking any other part of the game.

14
The Games and other Sierra Adventure stuff / Re: What are we working on?
« on: December 05, 2020, 11:56:22 PM »
For the last couple of years, on and off, I've been working on a fairly extensive mod to QFG1EGA. I'm touching on just about every room and every script, but in a slightly different way than the two excellent QFG3 and QFG1VGA fan-updates.  It's a fairly ambitious mod for me, and I'm probably another few years away from completion at least.

There's 3 major areas of the game I'm changing (I think and hope for the better).
1) This is the hardest to explain, and probably the most controversial. Replace every Restore/Restart/Quit dialog with Retry/Restore/Quit.
2) Add a new player avatar choice. Female.
3) Add a Goblin Maze and Town Shed interior, along with a new puzzle and new characters involving them.

In order of completion, #1 I've fully finished; #2 I've finished all the coding and have only (only) to draw 700 some-odd brand new character animations; and #3 I've only just begun. I've unlocked the town shed door, and programmed it opening/closing and ego can walk through it to a crudely drawn white room.  #'s 2 and 3 will take me a very long time, because art is my weakest area of expertise (seconded only by music ;)). 

I've actually fully programmed #2 so that up to 3 or 4 different avatars are supported. I had to rearrange the number of several of the views, and in some cases split them up into ego and stationary. To test it, I duplicated each existing ego view and inverted the colours. It's slightly bizarre to watch this inverted-color aberration wander through a regular Spielberg.

I wasn't even planning on #2,3 originally --- I wanted to do #1 as a proof of concept (the result of which I'm very proud) and figured since I finished that, I'd try and learn view and pic editing/creating.

So let me explain a bit about #1.  I think we're all familiar with the major difference between the Sierra games and the LucasArt ones... Sierra games strongly encourage (require?) you to save early/save often, while LucasArts games generally have no dead-ends. I always liked the character deaths... they were humorous, and helped give the world and characters a sense of consequence -- however as a player (especially one well past his youth, with limited time in any given day to actually play games) I find it incredibly annoying and discouraging to be penalized for exploring the world and trying new things. I mean I think Corey Cole summed it up pretty good way back when he first gave QFG2VGA a go. As he described it, he got killed by an unexpected brigand inside the City of Shapier; Realizing he hadn't saved his game he didn't bother restarting or redoing the lost 30 minutes or more he put into the game, he just turned it off and never went back.

To use a QFG1 example, it's one thing to try drinking the Dragon's breath. You've (possibly) been warned about it by the Sherrif... it looks very ominous when the bartender pours it... arguably, that's sufficient forewarning that maybe you should save your game before drinking it; and if you didn't, oh well, that's on you.  But picking your nose, early in the game?  There's absolutely no reason (especially in the EGA version, when you're not clicking the lock pick on yourself) to think that telling the hero to go "pick his nose" will cause him to kill himself. It's not fair to require your player to save the game before every single action, and to penalize them if they don't.  But it is a funny message.

So, that was my personal challenge. Keep the humour of the deaths, but remove the penalty. Could it be done in the original engine... And of course, the answer is yes. I think I came up with a novel solution. I turned it from a penalty into an additional in-game challenge.  Now, not only can you instantly reverse any fatal mistakes you make, but the game keeps track of each death and will show you a list, stating how many times you died. It changes deaths (and thus exploration) from something to be avoided into something actively encouraged.  Can you beat the game scoring every single death?

Yeah, so that's how I've been spending some of my free time.  I'm really happy with the results.

15
SCI Development Tools / Re: Batch export vector draw commands one by one
« on: October 11, 2020, 11:09:21 PM »
That sounds incredibly tedious. Maybe a hundred or more drawing “frames” and cropping et al.

If you’re doing a bunch of them, wouldn’t it be relatively easy to hack something into SCICompanion to auto increment the playback slider and save a BMP at each step?

You could even get fancy and skip BMP output on commands that don’t draw anything (like enable/disable control/visual, or palette changes). Then you’d have a series of BMP files you could drop into some other 3rd party program to create the gif.

Pages: [1] 2 3 ... 7

SMF 2.0.14 | SMF © 2017, Simple Machines
Simple Audio Video Embedder

Page created in 0.124 seconds with 22 queries.