This is an attempt at building a hook for DockScreens.
What this will provide, is a way for a 3'rd party mod, to tell the dockscreen that is wants to be available (so you can show another screen)
It requires that the XML for the DockScreen be overwritten (really simple change though), so there is that one issue.
As a proof of concept, i have implemented this on the ships interior dockscreen. (This is the one you refuel from)
I have added a new action (External Interfaces), which holds the meat of this mod.
Instead of selecting which dockscreen you want to see by calling an action, you are presented with a custompicker interface (think a list of items you can navigate).
This list consists of actions that invoke a dockscreen. We can provide a title, description, icon and of course the doockscreen to navigate to.
- So, what does this provide.
Well...
Ever wanted an item to have multiple unrelated dockscreens.
Have a usable item run an effect on <Invoke> but still have a dockscreen for configuration.
Have a dockscreen without having an item or station.
The list goes on... (i dont know what the limits are right now)
Basically it provides dynamic dockscreens.
As i said, it does require overriding some vanilla XML, and that is the thing I'm least satisfied with.
But in weighing the benefits against the disadvantages, I just can't help myself.
The dockscreen that I have overridden is the one that is always present to the user. The override is very simple, so migrating to future versions is simple.
What I am proposing is something of a convention among modders for providing dockscreens to the user.
Don't override that XML once again. Use this hook, and if it isn't already implemented for your base dockscreen, implement it, share it, and use it.
That way we can end up all being able to add custom actions to StartonEridani in our mods, without making our mod incompatible with others (there are plenty of other ways of doing this)
- So, what now?
Since this is a proof of concept here is some code.
You can put these into a vanilla game, and it should work (please let me know if i doesn't).
Access your ship's dockscreen and hit 'e' for ExternalInterface and bask in the glory of a test interface.
So... this works, but it is not finished. As stated i would like to see this turn into a framework, but for that to happen, we need to agree on the usability and possibilities of it.
There are a lot of things that could be done differently, from naming conventions, to extra hooks (wan't to update the pane description when user selects your action?)
Please let me know your thoughts
ShipInteriorHook.xml
Code: Select all
<?xml version="1.0" ?>
<!DOCTYPE TranscendenceExtension
[
<!ENTITY sih_modShipInteriorHook "0xDCBA0030">
<!ENTITY sih_dsExternalInterface "0xDCBA0031">
]>
<TranscendenceExtension UNID="&sih_modShipInteriorHook;" version="0.99c">
<DockScreen UNID="&sih_dsExternalInterface;"
name= "External Interfaces"
type= "customPicker"
backgroundID= "&rsItemListScreen;"
>
<List>
(block (displayList)
(if (isError ExternalInterfaceList)
(setq ExternalInterfaceList (list))
)
(setq displayList (list))
(enum ExternalInterfaceList fn
(lnkAppend displayList ((eval fn)))
)
(lnkRemoveNil displayList)
)
</List>
<Panes>
<Default desc="Select and external interface to use.">
<Actions>
<Action name="Select" key="S" default="1">
(block Nil
(setq scr (item (scrGetListEntry gScreen) 3))
(scrShowScreen gScreen scr)
)
</Action>
<Action name="Back" key="B" cancel="1">
<Navigate screen="&dsShipInterior;"/>
</Action>
</Actions>
</Default>
</Panes>
</DockScreen>
<!-- Taken straight from Vanilla XML -->
<!-- Only added an action to access External Interfaces -->
<!-- Player ship's interior -->
<DockScreen UNID="&dsShipInterior;"
name= "Ship's Interior"
backgroundID= "&rsShipInterior;"
>
<Panes>
<Default
desc= "You are inside the main compartment of your ship. A hatch in front of you opens into the cargo hold. To the side there is a small ladder that leads to the reactor and the ship's engines.">
<Actions>
<Action name="Ship configuration" key="S">
(scrShowScreen gScreen "&dsShipConfig;")
</Action>
<Action name="View cargo hold" key="V" >
(block Nil
(setq gDest Nil)
(scrShowScreen gScreen "&dsCargoHold;")
)
</Action>
<Action name="Refuel engines" key="R" >
<Navigate screen="&dsManualRefuel;"/>
</Action>
<Action name="External Interface" key="E">
<Navigate screen="&sih_dsExternalInterface;"/>
</Action>
<Action name="Back to cockpit" cancel="1" key="B">
<Exit/>
</Action>
</Actions>
</Default>
</Panes>
</DockScreen>
</TranscendenceExtension>
Code: Select all
<?xml version="1.0" ?>
<!DOCTYPE TranscendenceExtension
[
<!ENTITY tst_modExternalInterfaceTest "0xDCBA0032">
<!ENTITY tst_dsExternalInterfaceTest "0xDCBA0033">
]>
<TranscendenceExtension UNID="&tst_modExternalInterfaceTest;" version="0.99c">
<DockScreen UNID="&tst_dsExternalInterfaceTest;"
name= "External Interface"
backgroundDI= "&rsShipInterior;"
>
<Panes>
<Default
desc= "I should be available through the external interfaces list in your ship interior screen.">
<Actions>
<Action name="Do Something" key="D">
(scrSetDesc gScreen "Yes... that's right, you can do anything here")
</Action>
<Action name="Back" key="B" cancel="1">
<Navigate screen="&dsShipInterior;"/>
</Action>
</Actions>
</Default>
</Panes>
</DockScreen>
<Globals>
(block Nil
;; this is the only required part of using the ShipInteriorHook
;; let me walk you through it
;; ShipInteriorHook must be a list of functions, that when called, provide information about the DockScreen to show
;; The format of the list is:
;; ("Title" ImageDesc "A Long Description of this screen" "&tst_dsExternalInterfaceTest;")
;;
;; If the function returns Nil instead, it won't be shown
;;
;; Here we will make it really simple, but you can have it's logic be as complicated as you want
(setq tst_ExternalInterfaceFunc (lambda Nil
(list "External Interface Test" Nil "This is a long winded description of what is available here" "&tst_dsExternalInterfaceTest;")
))
;; If the ExternalInterfaceList is not defined anywhere, calling it will result in an error.
;; By testing for this, we can determine if we must define it ourselves, or append to the existing one
(if (isError ExternalInterfaceList)
;; we got an error, define it ourselves
(setq ExternalInterfaceList (list "tst_ExternalInterfaceFunc"))
;; it already exists, append to it
(lnkAppend ExternalInterfaceList "tst_ExternalInterfaceFunc")
)
)
</Globals>
</TranscendenceExtension>
Have fun!