Skip to content

Instantly share code, notes, and snippets.

@TrueBrain
Last active January 6, 2021 14:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TrueBrain/fe3c80e7dc9313b7ac7941540e5dee22 to your computer and use it in GitHub Desktop.
Save TrueBrain/fe3c80e7dc9313b7ac7941540e5dee22 to your computer and use it in GitHub Desktop.
GameScript identities

This is meant as extension on: https://wiki.openttd.org/en/Development/Design%20Drafts/Scripts/Capability-based%20API

In addition to having capabilities, GS would benefit from being able to instantiate controllers for certain objects.

For example, take a town. Currently either a GS controls all towns or it doesn't. By adding capabilities, as written in the wiki, it can either share all towns with other GSes or keep them all for him self. I would propose a more fine-graned method: instances.

Every GS has a function like: HasInstanceFor(capability). As example: HasInstanceFor(TownGrowth). The GS either returns 0 if it has nothing for this capability, or N with N > 0 for how many different forms it has for this instance. Next, OpenTTD adds up all the Ns, picks a random number in range, and selects that GS + index to handle that town now forths. For example: GetInstanceFor(TownGrowth, 2).

In Squirrel, the GS creates an instance, which has a few mandatory functions defined to handle the TownGrowth capability. This is all in addition to claiming capabilities as written in the wiki document.

Basically, this assigns "AI"s to certain objects of the game.

This could work for several things

  • Towns
  • Cargo
  • Industry (single industry)
  • Industry group (single type)
  • Even vehicles (not sure this is wanted, but one could argue this could do funky stuff like ATCs)

There are things of course that are more global, like subsidies. This would benefit more from a shared capabilties as described in the wiki, although each subsidiary would be assigned to a single GS of course.

The benefit of this approach is that each of the above objects can have their own identity. For example, I can have 10 towns with 10 different growth algorithms spread over 4 different GSes. It would mostly replace any "exclusive" claim on a capability; but it is also not really shared.

Communication from C++ to such instances could be done in an event-based system as we currently do, but instead of delivering the event to the AI or GS, it is delivered to the Squirrel instance of the object. An example: someone hits "Fund Town". For this C++ creates an event which is delivered to the Squirrel instance of the object to handle. In other words, there will be many small event-loops.

This would make GSes more cooperative.

The downside is that this might be more difficult to present in UIs.

@TrueBrain
Copy link
Author

TrueBrain commented Jan 6, 2021

To make a Proof-of-Value, I suggest we take this approach:

  • Implement the above summary

  • Create TownConstruction as capability, which takes over:

    • DoCreateTown in town_cmd.cpp
    • Callback from CmdExpandTown
    • Callback from TownTickHandler

    (in other words, all roads to GrowTown). We can work on having enough API functions to do what needs to be done.

  • Make a C++ based MapGenerator controller, which create a TownConstruction controller to create and grow a town. This controller is completely fake, and possibly even a single function-call in the current map generators, and only serves as proof the system works.

This sounds simple enough to do in a weekend, hence the scoping like this. This would allow other people to see if this is sufficient for them to build their own town growth algorithms, without going overboard.

The next step would be to find a way for them to communicate with each other, and work towards TownGrowth controller.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment