[Help Needed] New syntax for DSF

Post ideas & suggestions you have pertaining to the game here.
Post Reply
User avatar
alterecco
Fleet Officer
Fleet Officer
Posts: 1658
Joined: Wed Jan 14, 2009 3:08 am
Location: Previously enslaved by the Iocrym

I have been giving some thought to a rewrite of DSF (Dock Screen Framework) lately, and after Georges post on the nature of Transcendence, I decided to grab the bull by the horns. If I can say that we need easier dock screens, then I should to something about it too. I have brainstormed a lot and started from scratch, but before I get too far into this, I would like some feedback from fellow modders. Please read the Overview section in the document linked below.

Also, George, if you are reading this, and have the time, I would really appreciate your point of view. Is it worth it or a silly approach? Are there planned changes to the engine rendering this useless? Any other thoughts?

Document | Sources

Thanks in advance
Last edited by alterecco on Thu Jul 22, 2010 1:43 am, edited 1 time in total.
User avatar
Arisaya
Fleet Admiral
Fleet Admiral
Posts: 5535
Joined: Tue Feb 05, 2008 1:10 am
Location: At the VSS Shipyards in the frontier, designing new ships.

IMO, it's a simpler, easier-to-get-going sort of DS system because it's concise and clean, allowing people to see exactly what is where. Now, to understand or do complex things, it can end up looking more intimidating because the entire framework is all script (thus people will try to decipher what is going on, making things look more difficult than they really are), but its really about the same difficulty, or easier, depending on what it is you are trying to do. (same difficulty: integrating world-scripts into the DS; easier difficulty: integrating DS-scripts into the DS)
(shpOrder gPlayership 'barrelRoll)

<New tutorials, modding resources, and official extension stuff coming to this space soon!>
george moromisato
Developer
Developer
Posts: 2998
Joined: Thu Jul 24, 2003 9:53 pm
Contact:

Wow, this is really interesting and well thought-out!

I have a bunch of thoughts, but nothing coherent, so let me just list them out:

1. First, I completely support your goals. You are right when you say that creating dock screens needs to be easier.

2. I don't have any current plans to change the dock screen mechanism, but that is only because I think radical changes are needed and I don't have any good ideas.

3. One thing I suggest is that before you start spending a lot of time implementing, you should write out a couple of real screen in the syntax that you hope to implement. That will help you (and us) understand the advantages and disadvantages.

4. Also, since you have spent a lot of time thinking about this, you might be the best person to tell me how to improve the built-in dock screen system. If you could re-design the current dock screen system, how would you do it?

5. Regardless of #4, if there are game engine changes that might make your current design easier, let me know. For example, would it help to be able to store variables on the screen itself? [Something like, (scrSetData gScreen "myData" 'someValue)]

6. BTW, one enhancement that I am likely to add for 1.1 is a better way to nest screens. Right now, when a screen navigates to another screen, it has to set a global variable (gPrevScreen) to know what screen to return to. I want to change this so that the engine keeps track of a screen stack. You should just be able to call a screen (scrShowScreen gScreen "...") and then the target screen should be able to exit (scrExit gScreen) and it will automatically go back to the calling screen.

7. Another thought I had was that maybe it would be possible to optimize particular dialog patterns. Take the implementation of Raisu station, for example. It is basically a state machine: when the player docks, we check our current state and go to a different pane depending on the state. Maybe there could be a way to design the structures/functions to optimize for this usage pattern. I don't have concrete anything concrete, but I'll think about it.

I don't know if any of the above helps you, but I fully support your goals, so let me know what I can do to help.
User avatar
alterecco
Fleet Officer
Fleet Officer
Posts: 1658
Joined: Wed Jan 14, 2009 3:08 am
Location: Previously enslaved by the Iocrym

Thanks a lot for the reply George. Your support is really appreciated in this.

I will have to mull over some of your points much more, and will return to some
of them in later threads. Right now I thought it would make sense to give a
little background on DSF and how it works. It might make it easier to discuss
implementation and improvements to the DS xml.

DSF works by creating a tscript data structure that is then used by a custom
xml dock screen. If we cut one down, here is what it looks like

Code: Select all

<DockScreen UNID="..." name="=(dsf/current-name)">
  <OnInit>(-dsf/run-on-init)</OnInit>
  <Panes>
    <Default>
      <Initialize>(-dsf/run-initialize)</Initialize>
      <Actions>
        <Action name="Default Action" default="1">
          (-dsf/run-action 0)
        </Action>
        <Action name="Action1">(-dsf/run-action 1)</Action>
        <Action name="Cancel Action" cancel="1">
          (-dsf/run-action 2)
        </Action>
      </Actions>
    </Default>
    <Counter showCounter="true">
      ... lather, rinse, repeat
As you can see, this is a standard dock screen, that uses function calls
everywhere it can. Without the "=(...)" syntax in the name attribute DSF would
not be possible at all :). The types of panes available are limited to the ones
hardcoded in the xml definition. By default I have a normal pane, a textinput
and a counter pane. This has worked well so far (in the old DSF).

When defining a screen in DSF, we are just building a data structure in the
background that the function calls in the xml use to create the screen. A small
example of the calls and the resulting datastructure

Code: Select all

(dsf/screen 'Standard "My Screen")
(dsf/description "My description")
(dsf/action 0 "My action" 'M '(dbgLog "called my action"))

;; the above creates the following datastructure
(('type "Standard")
 ('unid 0x........)
 ('name "My Screen")
 ('description "My description")
 ('actions
  (0 ('name "My action")
     ('key "M")
     ('expression '(dbgLog "called my action")))))
Now, when dsf/show-screen is called, we look for the unid of the screen
to show, do some error checking, store the current screen in history and any
other bookkeeping we can imagine, and then move the new data structure in as
the current data structure. We then call scrShowScreen with the unid and pane
defined in the data structure.

Most of the meat of DSF happens, not in dsf/run-on-init, but in
dsf/run-initialize. Here actions are hidden and shown, labels and keys are set,
pane description is inserted and much more (the old pane initialize is 150
lines long). It is possible to do a lot of things in this function.

Last, but not least, stuff happens when you select and action. This action
looks up it's appropriate expression and runs it. We can do practically
anything we want to inside an action, including defining an entire screen and
showing it!

So, that was a short tour of the internals of DSF. This is more or less how the
old DSF was built, albeit without a nice api on top (you just wrote the
data structure by hand). I think the addition of a clear api will make the
entry level much lower for modders new to dock screens.

Comments to some of your points

3) I will definitely be doing this. Expect a post on this topic soon!

4) I have no concrete concept of what could be done to redesign dock screen
from the ground up. Perhaps we will come up with some good ideas in a this
thread?

5) There are several things, but I can not name them of the top of my head. As
you can imagine, the more things it is possible to control via script, the
better for something like DSF. Specific examples would be setting the default
and cancel actions via script (scrActionDefault screen action true/nil),
changing the pane type via script (scrShowCounter screen true/nil) and
similar. The more things that have to be hardcoded in xml, the more workarounds
DSF has to provide. I am sure I can come up with more during the development.

6) Having nested screens sounds very interesting. I added history management
for the old DSF and will re-implement it in the rewrite. I am not sure how much
use DSF will have of nested screens, as history does not depend on what screen
(unid) was shown, but what data was show on it. Typically in DSF the same
screen is used over and over again, but the data is changed between
redisplays. Therefore history in DSF is maintained by storing the data
structure on a stack. In any case, I definitely think it is a good idea to get
rid of gPrevScreen :)

7) I completely agree with this. This was one of the reasons DSF was created in
the first place. I wanted to abstract away most of the repetitive stuff going
on in screens. I never ended up doing much work on what could be considered
"adventure screens" (dialouge screens, choice screens), since most of the work
on DSF went into supporting G.O.D mod (custom pickers galore).

Disclaimer

Another of the original goals of DSF was to avoid having to write xml. I wanted
to avoid having to much around with unid's and so on as far as possible. An it
is possible. The old G.O.D mod mentioned above is ~3000 lines of dock screens
in pure script. Call me a fanatic :D

I mention this because it is a bias I have, and I am not sure that it should
dominate the development of vanilla screens too much. I might be able to
imagine a scenario where the main part of dock screens is still defined in xml,
with some well thought out functions present to support complex or repetitive
tasks, but I shudder a bit to think of it :D

OK, enough for now (sorry for writing a small essay).

Thanks for the feedback
User avatar
Atarlost
Fleet Admiral
Fleet Admiral
Posts: 2391
Joined: Tue Aug 26, 2008 12:02 am

There are basically two kinds of dockscreens: Those that represent station services, and those that represent conversations. The latter really need to be compact because dealing with large conversations is very difficult with screen definitions interspersed with the content.

I personally favor doing away with dialog trees entirely apart from special cases of yes/no questions. Make conversation flat file like in Ultima 4-6 where a keyword selects the response.

Conversation data then might be stored in a switch statement, comparing text box input to determine how the NPC responds. In some cases the responses would be calls to different dockscreens for things like transactions.

Code: Select all

(switch 
     (eq text "trigger1")
          "response1"
     (eq text "trigger2")
          "response2"
     "default response"
)
A tree conversation structure as is popular in modern CRPGs is much trickier, forces someone on a second playthrough to do a runaround to get to the conversation trigger they want, and is generally annoying. I think such a structure is justified only in cases like the Huari Temple dream sequence.
User avatar
alterecco
Fleet Officer
Fleet Officer
Posts: 1658
Joined: Wed Jan 14, 2009 3:08 am
Location: Previously enslaved by the Iocrym

@Atarlost. I agree that converstion screens would be interesting, and I like your idea of using the text field to trigger them. We would just need an improved text field to really do this.

Once the framework has come a bit further I think I will return to your post and see what patterns we can extract into DSF. Keep the thoughts coming! :)

Examples

So, I sat down and started converting some vanilla screens to an imaginary DSF syntax. Turned out to be fun. I have written a good deal about it in the documentation. Please take a gander, and bring back your point of view. Is it too complex, too illegible? What could be done better?

Examples
User avatar
alterecco
Fleet Officer
Fleet Officer
Posts: 1658
Joined: Wed Jan 14, 2009 3:08 am
Location: Previously enslaved by the Iocrym

George. What is the reason for the existence of gScreen. Was it for a feature that never got implemented, or do you have some devious plan for the future? I will be wrapping a lot of the scr* builtins, and not allowing for passing in a gScreen. Should I require that as an argument?
george moromisato
Developer
Developer
Posts: 2998
Joined: Thu Jul 24, 2003 9:53 pm
Contact:

alterecco wrote:George. What is the reason for the existence of gScreen. Was it for a feature that never got implemented, or do you have some devious plan for the future? I will be wrapping a lot of the scr* builtins, and not allowing for passing in a gScreen. Should I require that as an argument?
Today, only one screen (the current screen) is ever in existence at one time, so you shouldn't need to pass gScreen around.

Originally I thought there might be a need to have multiple concurrent screens, but it is unlikely to happen.
User avatar
alterecco
Fleet Officer
Fleet Officer
Posts: 1658
Joined: Wed Jan 14, 2009 3:08 am
Location: Previously enslaved by the Iocrym

OK, great... no problem then when wrapping them.

Thanks for the quick reply
User avatar
alterecco
Fleet Officer
Fleet Officer
Posts: 1658
Joined: Wed Jan 14, 2009 3:08 am
Location: Previously enslaved by the Iocrym

OK, after more musing I sat down and cleaned up the document.

I have attempted to define a clear api, and will write up some examples using it tomorrow.

ATM i have only one really simple example

I would love to hear anyones thoughts/suggestions.

Please consume here
Post Reply