whoward69
DLL Minion
Scratching an itch!
So Hambril's mention of his dislike for loops within loops when checking units in his Follow and Cover mod got me to wondering if worker units could somehow be self-aware of their own movement and then use that knowledge to get the combat unit to follow them.
The results of scratching that itch are attached. The code is functional but incomplete (there is no UI to assign Escorts to Workers, or any persistance code for save/load of the game). But rather than ditch it (I'm not going to develop this further) I'll make it available to anybody that's interested.
So Hambril's mention of his dislike for loops within loops when checking units in his Follow and Cover mod got me to wondering if worker units could somehow be self-aware of their own movement and then use that knowledge to get the combat unit to follow them.
The results of scratching that itch are attached. The code is functional but incomplete (there is no UI to assign Escorts to Workers, or any persistance code for save/load of the game). But rather than ditch it (I'm not going to develop this further) I'll make it available to anybody that's interested.
Spoiler :
Code:
--
-- Workers, Escorts and Blockers
--
-- Workers do work, travel to their next assignment and do more work. They may have an assigned Escort.
-- Escorts are assigned to a Worker, move as they move, fortify when they are working. They may be being blocked.
-- Blockers are units that are stopping Escorts from entering a tile.
--
-- While we will keep with the terms "Worker" and "Escort" they are really just "Leader" and "Follower".
-- We could just as easily have a Settler follow a Warrior as a Warrior escort a Settler, and units may have multiple roles at the same time.
-- This makes more sense if you set a Great Admiral to follow a Destroyer which itself is following an embarked Settler,
-- or consider that an escort being blocked may itself be blocking another escort.
--
--
-- So what's going on ...
--
-- Firstly we have three primary classes - Worker, Escort and Blocker - inheriting from an (abstract) MoveAwareUnit base class.
-- Each of these wraps a Civ5 Unit object. An individual Civ5 Unit may be all, any or none of these three classes.
--
-- Secondly we have three class managers - WorkerManager, EscortManager and BlockerManager - again inheriting from an (abstract) MoveAwareUnitManager class
-- The managers are responsible for "wrapping-up" the Civ5 Unit into the required class, in such a way that there is only ever one copy of the wrapped Unit.
-- In other words, if you call WorkerManger:Get() multiple times for the same Civ5 Unit (pWorker) you always get the same wrapper object.
--
--
-- So what do the primary classes do ...
--
-- worker = WorkerManager:Get(pWorker) pretty much does nothing useful on its own.
-- worker:AddEscort(pEscort) assigns the Civ5 Unit pEscort to guard pWorker.
-- Adding an escort makes the worker self-aware of it's movement, as the worker moves it tells its escort to move to the same plot.
-- The escort will attempt to move to the worker's plot, which it will either be able to do, or will be blocked by another unit.
-- If the escort is blocked, it wraps each blocking unit as a Blocker and adds itself to the list of unit(s) being blocked.
-- Blockers are also self-aware of their movement, so when they move away from the tile, they inform the escort(s) they are blocking that the tile is vacant.
--
-- The interesting methods are AddEscort() on Worker and MovedTo()/MoveTo() on all three classes
--
--
-- A note on GameEvents.UnitSetXY ...
--
-- The initial design added a movement listener for every MoveAwareUnit, which in an efficient system would be the nicely encapsulated way.
-- However, Civ 5 events are far from efficient, and receiving every movement step for every Civ 5 Unit into every MoveAwareUnit is grossly inefficient.
-- There is also the issue of apparently not being able to remove anonymous functions as event listeners (see http://forums.civfanatics.com/showthread.php?t=493645)
--
-- The new Civ 5 limitations aware design registers one GameEvents.UnitSetXY listener (in the MoveAwareUnitManager class)
-- that then distributes movement events directly to the associated MoveAwareUnit
-- Having a factory/manager understands it objects inner workings is NOT good OO design, but hey,
-- sometimes we have to make the "best" design decision and not the "correct" one!
--