Skills and Commands...A skill is a 'low level' action, a works by progressing from 0.0 to 1.0
as it is updated [this is currently in Unit::update(), the contents of
which may be subject to re-factoring soon...]
A Command is 'high level' action, a sequence of low level skills.
Example...
Moving:
The move skill performs a 'single' move, from one map cell to an adjacent cell. Unit::update() calculates how much to progress the skill by based on the unit type's speed, whether its a diagonal move, & up or down hill. [Other skills are far less interesting, usually just using a 'speed' setting]
When the progress hits 1.0, Unit::update() return true.
In UnitUpdater::updateUnit() [this code is bound for World::update()], if Unit::update() returns true (the skill cycle is complete), the command is updated.
In the move command, this simply pops the next position off the path and sets it as it's next position, then starts the move skill again.
Obviously it's a bit more complicated than that, the path might be blocked, but the move command isn't much of an issue anyway...
The build command is an issue, or rather, was
The whole update() method as lifted from the UnitUpdater::updateBuild(), is essentially an if/else statement, and that one if/else comes in at about 175 lines of code! Just figuring out what is happening where is a nightmare, the if and else are 144 lines apart...
// What it does do (somewhat abstracted) is this:
If the unit is not executing the build skill
Find the nearest cell we can commence building from
Find a path to that cell
If the pathfinder says we're 'on the way'
set our current skill to move and return
Else If the pathfinder says 'path is blocked'
Cancel the current command (which sets the skill to stop) and return
// Else fallthrough... we have arrived...
If we still have room to build
do a whole bunch of stuff ( apply costs for building, play start sound, etc )
inform the PathFinder of new obstactle in field
Else
If another worker beat us here and the building is under way
set skill to build, configure to build existing unit
Else
If there are units in the way
If they all have a move skill return // we'll 'wait' not cancel
cancel command
Else
// We are executing the build skill
If the unit type of the unit we're building does not match this command
// this is just a sanity check, it should never actually happen...
Bail Out (set current skill to stop)
If the unit we're building is now built
// this is for when another worker finsishes the built earlier in this update
finish command, set skill to stop
'Repair' the building
If it is now built
finish command, set skill to stop
inform the ScriptManager that a new unit has been created
do some more stuff (play built sound, networking... etc)
// Else we'll see you again next time around!
// We'll perform another skill cycle of 'build' and when that
// finishes, this command will be updated again.
I think we could use some abstraction here...
What I now want the build command update to look like is:
cacheUnit ( unit );
if ( unit->getCurrSkill()->getClass() != scBuild )
{
if ( moveToBuildingSite () )
startBuilding ();
}
else
continueBuilding ();
moveToBuildingSite() will execute the move skills to get use where we need to be, and comprises the first part of the 'top level' if clause from the old code.
When moveToBuildingSite() returns true, we'll be in position, so we startBuilding(), which was other part of the original if clause.
continueBuilding() is the former else clause.
Simple!
This is now done for the build command, just committed the code...
But it needs to be done to the others, probably harvest and repair
are the most in need...