Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Give GS control over buy and build action of the user #5697

Closed
DorpsGek opened this issue Aug 5, 2013 · 8 comments
Closed

Give GS control over buy and build action of the user #5697

DorpsGek opened this issue Aug 5, 2013 · 8 comments
Labels
component: AI/Game script (squirrel) This issue is related to Squirrel (Scripting language) flyspray This issue is imported from FlySpray (https://bugs.openttd.org/)

Comments

@DorpsGek
Copy link
Member

DorpsGek commented Aug 5, 2013

idioty opened the ticket and wrote:

I want an overwrite function, like Save() or Load(version, table), but
like these:
CanPurshase(companyid, purchaseinfo) or CanBuild(companyid, buildinfo), and return true or false, before the game show the object (and before take the mony).

Example:
In my script companies can't purchase more than five truck. If a company complete any goal, become "truck" reward, and the compnay can purchase more two truck.

Reported version: trunk
Operating system: All


This issue was imported from FlySpray: https://bugs.openttd.org/task/5697
@DorpsGek
Copy link
Member Author

Zuu wrote:

If this is implemented using direct callbacks from OpenTTD, this has the consequence that you can probably not call DoCommands in CanPurshase to display an error message when something is denied. Your GS could have a message queue to which CanPurshase can push an error. Then back in the main-loop, you can detect a queue > 0 and display all queued errors and possible send an error to AIs.

Another consequence is that you will only have X number of oopcodes to provide an answer. If you overshot this, OpenTTD will need to crash your GS to avoid that a GS could hang OpenTTD.

It may be possible to implement it such that the GS may return True, False or a GSText with a custom error message for human players. Showing this error message only to the client that tried to execute the action is possible non-trivial. That said it is probably easier on the OpenTTD side than on GS side to make sure the error message is only shown for a specific client in the company. The returned GSText will however be of little use for AIs. So another option is to provide a few built-in error enums so that AIs can call GetLastError and get a bit more clue than just "script denied action".


This comment was imported from FlySpray: https://bugs.openttd.org/task/5697#comment12518

@DorpsGek
Copy link
Member Author

idioty wrote:

So, if my script denied the purchase, then send back a GSText, but if company can purchase the thing, my script send back null? Yes, this is more useful. :)


This comment was imported from FlySpray: https://bugs.openttd.org/task/5697#comment12523

@DorpsGek
Copy link
Member Author

idioty wrote:

I thought about the issue.
If the return type would be an class or table or enum with "GSText with a custom error message for human players" and "built-in error enums so that AIs can call GetLastError "?
But built-in errors must be contain an option: these type of vehicle (or station, etc...) can not purchase any more, or must contain a number, the AI know how much can buy these.
example: -2: can not purchase any more, -1: AI can buy any of number, 0: yet can not buy, and above the number of AI can purchase.

I hope you understand...


This comment was imported from FlySpray: https://bugs.openttd.org/task/5697#comment12606

@DorpsGek
Copy link
Member Author

Zuu wrote:

An alternative solution that looks more appealing to me is (I will give pros/minus at the end):

/*
* Set the default number of allowed vehicles of the given
* engine id that a company is allowed to buy.
* This value is automatically applied to new engines when
* they become available.
* @param value The vehicle limit. Set to 0 to disable engines by default. Set to NO_LIMIT if you don't want any limit.
*/
GSEngine.SetDefaultAllowedVehicleCount(value)

/*
* Set the number of allowed vehicles of the given engine id
* that a company is allowed to buy.
* @param company_id The company that the limit should be set for or COMPANY_INVALID to update all companies.
* @param engine_id Which engine to update the vehicle limit.
* @param value The new vehicle count limit. Set to 0 to disable the engine completely. Set to NO_LIMIT if you don't want any limit.
*/
GSEngine.SetAllowedVehicleCount(company_id, engine_id, value)

Benefits (compared to a callback):
+ When a limit is changed we can invalidate all affected buy vehicle windows so that we can give visual information to players which engines they can build.
+ When a vehicle with limit 0 is changed to > 0, we can show the new vehicle news automatically without the GS needing to do anything.
+ It is cheap to check the limit of a vehicle to provide visual information to players about the limits
+ We avoid any problems related to a GS providing different information when you open the Buy window and when you click to buy a vehicle. (if the GS change its mind between these two points we get informed and can update the window)

Drawback:
- Concepts where the total limit is not per engine type or when the total is not per company are harder to enforce with this API design. The GS will not have the chance against a player to react on a vehicle being bought and reduce the other limits before a fast player buy a second engine.


This comment was imported from FlySpray: https://bugs.openttd.org/task/5697#comment12614

@DorpsGek
Copy link
Member Author

idioty wrote:

I like this: GSEngine.SetAllowedVehicleCount(company_id, engine_id, value)
But
"The GS will not have the chance against a player to react on a vehicle being bought and reduce the other limits before a fast player buy a second engine."
for this reason, I think this is the right solution: if these method implemented in script:
CanPurshase(companyid, purchaseinfo) or CanBuild(companyid, buildinfo)


This comment was imported from FlySpray: https://bugs.openttd.org/task/5697#comment12617

@DorpsGek
Copy link
Member Author

Zuu wrote:

True, but you will then lose all benefits with having a API where the GS declare the limits to OpenTTD. I would like to have a more constructive and open discussion where it is possible to see benefits and drawbacks of each solutions. Both for GS and for OpenTTD.

A drawback with the callback is that it will be easier for a GS to mess up with multiple execution points in the code. What if the main "thread" did half-update the data used by the callback? Yes, it is possible to write the code as to reduce this problem but not all novice GS authors will be aware of it.

A drawback with callbacks is that they can do random things that are hard for other parts of the OpenTTD eco system to cope with. As a script author you should be aware of the different interesting things that NewGRF callbacks can cause. (eg. a vehicle with different properties than told by [AI|GS]Engine etc. etc.)

Another drawback with callbacks is multiplayer. Codewise it means that a human client need to ask the server over the network for which engines that it can buy when populating a vehicle purchase list. The purchase list must then have a non-populated state. These things makes this path tricky to implement on the OpenTTD side as well.


This comment was imported from FlySpray: https://bugs.openttd.org/task/5697#comment12618

@DorpsGek
Copy link
Member Author

idioty wrote:

You're right, I did not thik about these problems.
It will remain: GSEngine.SetAllowedVehicleCount(company_id, engine_id, value)
I thought also about this problem: "The GS will not have the chance against a player to react on a vehicle being bought and reduce the other limits before a fast player buy a second engine."
Only problem is if the player can choose between two or more engine, and it can buy only one engine.
A possible solution:
exp: GSEngine.SetChooseVehicles(company_id, engine_list)
and the OpenTTD game know: the company can purchase only one of these type of engine, and if the company bought, the company can't purchase other engine from the list (or the OpenTTD reset the previous state).


This comment was imported from FlySpray: https://bugs.openttd.org/task/5697#comment12619

@DorpsGek
Copy link
Member Author

andythenorth closed the ticket.

Reason for closing: Won't implement

The OP's request isn't implementable as requested, GS is too slow / deliberately limited to handle player actions on an event bubbling basis. Zuu has suggested alternatives, but likely doesn't need this issue open to develop those further (if at all). Closing as part of Flyspray clean up. Thanks :)


This comment was imported from FlySpray: https://bugs.openttd.org/task/5697

@DorpsGek DorpsGek added flyspray This issue is imported from FlySpray (https://bugs.openttd.org/) Goal/Game script labels Apr 7, 2018
@frosch123 frosch123 added the component: AI/Game script (squirrel) This issue is related to Squirrel (Scripting language) label Apr 14, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: AI/Game script (squirrel) This issue is related to Squirrel (Scripting language) flyspray This issue is imported from FlySpray (https://bugs.openttd.org/)
Projects
None yet
Development

No branches or pull requests

2 participants