-
Notifications
You must be signed in to change notification settings - Fork 161
Linked and Group Movement How it works
Link Units
Both linked and group movement are focused on the unit receiving the move order. For linked units, upon clicking the link button/hotkey, the selected unit receives a LinkUnits() call. The unit is set as the IsLinkedLeader, while other eligible units sharing the same plot, let's call followers for simplicity, are set to IsLinked. The LinkedLeader unit stores the UnitIDs of the followers while the follower units only store the ID of their leader to save memory. Important to note that the linked units will have their current and maximum movements to set to that of the unit with slowest values. Note that there are no checks for promotions, simply because it would be very performance intensive. In movement, units receive a Move Mission, and complete that mission by moving one plot at a time in CvUnit::move(). A check has been added to CvUnit::move() for IsLinkedLeader, and the linked units move only if all linked units can move into the ordered plot, this ensures the linked units follow the same path. The follower units do not get a move order, instead they get MoveLinkedUnit() through WorldView.lua, which forwards the order to the leader. When units are unlinked, UnlinkUnits() is called. The function is mostly there for the lua call, and it calls SetIsLinkedLeader(false), where actual unlinking happens. The UI part is messy. I didn't add these functions through a Mission as the UI expects, because that was more expensive&time-consuming. As a workaround, a LinkUnits button is added with associated Update and OnClicked functions in UnitPanel.lua. Hotkey (L) is received through the CustomHotkeyUp function.
Group Movement
Group movement moves all eligible adjacent units together with the selected unit. While it moves a whole lot more, it's actually simpler than linked movement. Pretty much everything is done in CvUnit::DoGroupMovement(), called by WorldView.lua. A ring iterator constructs a vector of all eligible units - combat units of the same domain, and embarked units considered sea in this. Then we have two loops, first loop normalizes the current & max movement points, as seen in the LinkUnits. The second loop issues move orders to each unit while trying to keep their relative positions to the leader. Units on the same plot as the leader are linked at the beginning, as the iterator doesn't check the starting plot. Example: Unit A is on plot (5,6), Unit B on (6,6), and A gets a group move order to (6,7). The code gets the difference in position between A and B (-1,0), and gives B a move order to the plot with same relative position to the destination plot, which would be (7,7). This is not a foolproof method, units keep somewhat together because movement points are normalized, but there aren't any plot-by-plot checks like linked order. I'll probably add one ring approximation flag for safety, needs a bit more testing. The group is automatically disbanded when units complete their move missions, so there is no need to store UnitIDs etc. UI is also simpler than linking units. We hijack the unused INTERFACEMODE_MOVE_TO_ALL interface, probably a leftover from Civ4 times. Hotkey/button activates the interface, and clicking issues a DoGroupMovement instead of a normal move order.