Are custom commands explained in the wiki anywhere?
EDIT: This is the closest I've come to an example: https://springrts.com/wiki/SetMoveTypeDataExample
I didn't find any manual/reference for this, just random callins.
wiki info on custom commands?
Moderator: Moderators
Re: Wiki: issues + quick questions/answers
Looks like not, there was some good stuff on the Q&A about this, but that is gone of course 

- Silentwings
- Posts: 3720
- Joined: 25 Oct 2008, 00:23
Re: Wiki: issues + quick questions/answers
I think that this https://github.com/SpringCabal/Corrupti ... h_life.lua (which we just made for LD) would make a good simple example of how to make a custom command & could be easily made into a wiki article.
Re: Wiki: issues + quick questions/answers
Is that actually correct though? I've coded the logic of this one to happen in the AllowCommand callin, but it seems odd to me that the effect should be there too -> I just assumed AllowCommand is a "OK, you can do this command, add it to the queue", where the UnitCommand callin would actually execute it.Silentwings wrote:I think that this https://github.com/SpringCabal/Corrupti ... h_life.lua (which we just made for LD) would make a good simple example of how to make a custom command & could be easily made into a wiki article.
Maybe it depends on the type of the command. I assume most state-change (e.g. fire/move state) commands would be executed immediately in the AllowCommand and others (attack, patrol, build, cast spell) would be executed somewhere else.
Also how does one control the following:
- range (if unit, area or a position is a target)
- cooldown
- ^ how these two can be dynamically changed (by putting the command on/off cooldown or extending/shortening range, if possible)
- facing (whether or not a unit needs to face the target)
- extensibility with lups or ceg (which while it might seem out of scope to define here, users should still know where to add it)
Imo, the above is what a wiki article needs, and I'm not offering to make it right now due to lack of experience.
- Silentwings
- Posts: 3720
- Joined: 25 Oct 2008, 00:23
Re: Wiki: issues + quick questions/answers
In some ways it would be better to action the command in UnitCommand, since then UnitCommand can also be used elsewhere to see that the command happened. But in this case we want to the command to be actioned instantly (at least, that's what I thought you wanted) and only one other place needs to be told what happened, so I decided it was simpler to block the command in AllowCommand (so as it doesn't go into the queue, but also doesn't go through UnitCommand) and instead broadcast its effect (i.e. the corruption level) in a TeamRulesParam. Updated link with comment to say that: https://github.com/SpringCabal/Corrupti ... h_life.lua
In general handling queueing for custom commands is not easy, because iirc there is no callin that tells you when a unit has finished doing a command. I've even seen custom commands which implemented their own queue in lua, in parallel to the normal command queue. I'm not sure what is best to put in a simple example there.
Not entirely sure what you mean by cooldown, but there are callouts to handle all the other things you mention. I don't think it's worth trying to guess what a user implementing a custom command would want it to actually do, since there are so many different things one could want, and it's better just to rely on them finding the necessary stuff for whatever they want to action elsewhere in the wiki.
In general handling queueing for custom commands is not easy, because iirc there is no callin that tells you when a unit has finished doing a command. I've even seen custom commands which implemented their own queue in lua, in parallel to the normal command queue. I'm not sure what is best to put in a simple example there.
Not entirely sure what you mean by cooldown, but there are callouts to handle all the other things you mention. I don't think it's worth trying to guess what a user implementing a custom command would want it to actually do, since there are so many different things one could want, and it's better just to rely on them finding the necessary stuff for whatever they want to action elsewhere in the wiki.
Re: Wiki: issues + quick questions/answers
There is UnitCmdDone()iirc there is no callin that tells you when a unit has finished doing a command.
https://springrts.com/wiki/SetMoveTypeDataExample is a state-change command, so AllowCommand seems okay.I've coded the logic of this one to happen in the AllowCommand callin, but it seems odd to me that the effect should be there too -> I just assumed AllowCommand is a "OK, you can do this command, add it to the queue", where the UnitCommand callin would actually execute it.
Maybe it depends on the type of the command. I assume most state-change (e.g. fire/move state) commands would be executed immediately in the AllowCommand and others (attack, patrol, build, cast spell) would be executed somewhere else.
On other hand the life-leech gadget seems more like an action similiar to attack, that should not be immediately.
Player can select a target etc, unit probally has to move into range before it can execute the attack, the action should be queue-able and so on.
Imo best handled with CommandFallBack() ,it is documentated in wiki.
Any way is to put the all actual logic (setting unit health/states, moving in range, spawning effects, animations,..) of an action that takes a while to complete into GameFrame() and CommandFallBack() merely returns "finished=true" once the action is complete.
It comes down to question: "How can a command be blocked based on a condition?"Also how does one control the following:
- range (if unit, area or a position is a target)
- cooldown
- facing (whether or not a unit needs to face the target)
The life-leech gadget already does some check:
Code: Select all
if not Spring.ValidUnitID(targetUnitID) or Spring.GetUnitIsDead(targetUnitID) then return false end
Limiting by range or cooldown works no different, so just add more conditions in similiar way
Code: Select all
if (distance (unit, target) > 400) then ...
if getUnitMana (unit) < 20 then ...
In above conditions replace the numbers constants with values read from UnitRulesParam(unitID) or some table or whatever.- ^ how these two can be dynamically changed (by putting the command on/off cooldown or extending/shortening range, if possible)
Code: Select all
if (distance (unit, target) > spGetUnitRulesParam(unitID, "lifeLeechRange"))then ...
"Extensibility" seems like bit strange word: Such things become clear when writing a gadget.extensibility with lups or ceg
If the gadget makes a unit lose/gain health with SetUnitHealth() then author naturally understands where to call SpawnCEG("blood-splatter") to make the blood-splatter-effect (or whatever) appear at good moment.
Re: Wiki: issues + quick questions/answers
Yeah, this was my intuition as well.8611 wrote:https://springrts.com/wiki/SetMoveTypeDataExample is a state-change command, so AllowCommand seems okay.
On other hand the life-leech gadget seems more like an action similiar to attack, that should not be immediately.
Player can select a target etc, unit probally has to move into range before it can execute the attack, the action should be queue-able and so on.
I thought so too, but something wasn't working when I tried it. Maybe because I didn't have the AllowCommand, or maybe I just had a bug elsewhere. I'll try again when I have time.8611 wrote: Imo best handled with CommandFallBack() ,it is documentated in wiki.
Aha, OK, I think I understand this now.8611 wrote: Any way is to put the all actual logic (setting unit health/states, moving in range, spawning effects, animations,..) of an action that takes a while to complete into GameFrame() and CommandFallBack() merely returns "finished=true" once the action is complete.
This is maybe because I misunderstood something, but I guess I also wanted to communicate to the Lua widget about the range of the command, the required facing and the cooldown. For the range and the facing, this is so it would be displayed in the UI (the range) and so the unit would get into range/proper facing when this command is given.8611 wrote:It comes down to question: "How can a command be blocked based on a condition?"Also how does one control the following:
- range (if unit, area or a position is a target)
- cooldown
- facing (whether or not a unit needs to face the target)
The life-leech gadget already does some check:So the action is already limited to target only not-dead units.Code: Select all
if not Spring.ValidUnitID(targetUnitID) or Spring.GetUnitIsDead(targetUnitID) then return false end
Limiting by range or cooldown works no different, so just add more conditions in similiar wayCode: Select all
if (distance (unit, target) > 400) then ... if getUnitMana (unit) < 20 then ...
The question about the cooldown is basically on how to communicate to the widgets (UI) that the command was successfully done (if it's a state-changing command). State-changing commands would be immediately executed in AllowCommand and would return false, which basically means that they were denied, and it's not clear if they were denied because some condition wasn't met, or if they were actually executed.
Basically, regardless if they failed because of
Code: Select all
if (distance (unit, target) > 400) then ...
if getUnitMana (unit) < 20 then ...
false will be returned.
Maybe instead AllowCommand should still return true and be executed in the CommandFallBack immediately?
This might be a better option for the above problem maybe? Is this how gadgets tell widgets that state-changing command was executed?8611 wrote: In above conditions replace the numbers constants with values read from UnitRulesParam(unitID) or some table or whatever.To change button descriptions or disabling buttons: EditUnitCmdDesc()Code: Select all
if (distance (unit, target) > spGetUnitRulesParam(unitID, "lifeLeechRange"))then ...
You're probably right, this is out of scope.8611 wrote:"Extensibility" seems like bit strange word: Such things become clear when writing a gadget.
If the gadget makes a unit lose/gain health with SetUnitHealth() then author naturally understands where to call SpawnCEG("blood-splatter") to make the blood-splatter-effect (or whatever) appear at good moment.