Files
kam-mobile/vendor/kam_remake/src/units/KM_UnitWorkPlan.pas
T
admin_d 7063d1b1c9
Sync changed files to Google Drive / sync (push) Successful in 1h45m13s
sync: restore source from Google Drive
2026-09-12 16:50:30 +05:00

691 lines
28 KiB
ObjectPascal

unit KM_UnitWorkPlan;
{$I KaM_Remake.inc}
interface
uses
KM_Defaults, KM_CommonClasses, KM_Points, KM_TerrainTypes, KM_Units,
KM_ResTypes;
const
MAX_WORKPLAN = 24;
type
TKMWorkPlanAllowedEvent = function(aProduct: TKMWareType): Boolean of object;
TKMUnitWorkPlan = class
private
fHome: TKMHouseType;
fIssued: Boolean;
function ChooseTree(const aLoc, aAvoid: TKMPoint; aRadius: Integer; aPlantAct: TKMPlantAct; aUnit: TKMUnit;
out Tree: TKMPointDir; out PlantAct: TKMPlantAct): Boolean;
procedure Clear;
procedure WalkStyle(const aLoc2: TKMPointDir; aTo, aWork: TKMUnitActionType; aCycles, aDelay: Byte; aFrom: TKMUnitActionType; aScript: TKMGatheringScript);
procedure SubActAdd(aAct: TKMHouseActionType; aCycles: Single);
procedure ResourcePlan(Res1: TKMWareType; Qty1: Byte; Res2: TKMWareType; Qty2: Byte; Prod1: TKMWareType; Prod2: TKMWareType = wtNone);
public
HasToWalk: Boolean;
Loc: TKMPoint;
ActionWalkTo: TKMUnitActionType;
ActionWorkType: TKMUnitActionType;
WorkCyc: Integer;
WorkDir: TKMDirection;
GatheringScript: TKMGatheringScript;
AfterWorkDelay: Integer;
ActionWalkFrom: TKMUnitActionType;
Resource1: TKMWareType; Count1: Byte;
Resource2: TKMWareType; Count2: Byte;
ActCount: Byte;
HouseAct: array [0..MAX_WORKPLAN - 1] of record
Act: TKMHouseActionType;
TimeToWork: Word;
end;
Product1: TKMWareType; ProdCount1: Byte;
Product2: TKMWareType; ProdCount2: Byte;
AfterWorkIdle: Integer;
ResourceDepleted: Boolean;
public
procedure FindPlan(aUnit: TKMUnit; aHome: TKMHouseType; aProduct: TKMWareType;
aLoc: TKMPoint; aPlantAct: TKMPlantAct);
function FindDifferentResource(aUnit: TKMUnit; aLoc: TKMPoint; const aAvoidLoc: TKMPoint): Boolean;
property IsIssued: Boolean read fIssued;
procedure Save(SaveStream: TKMemoryStream);
procedure Load(LoadStream: TKMemoryStream);
end;
implementation
uses
SysUtils,
KM_ResUnits, KM_Houses, KM_HouseWoodcutters,
KM_ResHouses,
KM_Terrain,
KM_Resource, KM_CommonUtils;
{Houses are only a place on map, they should not issue or perform tasks (except Training)
Everything should be issued by units
Where to go, which walking style, what to do on location, for how long
How to go back in case success, incase bad luck
What to take from supply, how much, take2, much2
What to do, Work/Cycles, What resource to add to Output, how much
E.g. CoalMine: Miner arrives at home and Idles for 5sec, then takes a work task (depending on ResOut count)
Since Loc is 0,0 he immidietely skips to Phase X where he switches house to Work1 (and self busy for same framecount)
Then Work2 and Work3 same way. Then adds resource to out and everything to Idle for 5sec.
E.g. Farmer arrives at home and Idles for 5sec, then takes a work task (depending on ResOut count, HouseType and Need to sow corn)
...... then switches house to Work1 (and self busy for same framecount)
Then Work2 and Work3 same way. Then adds resource to out and everything to Idle for 5sec.}
procedure TKMUnitWorkPlan.Clear;
begin
fIssued := False;
HasToWalk := False;
Loc := KMPOINT_ZERO;
ActionWalkTo := uaWalk;
ActionWorkType := uaWork;
WorkCyc := 0;
WorkDir := dirNA;
GatheringScript := gsNone;
AfterWorkDelay := 0;
ActionWalkFrom := uaWalk;
Resource1 := wtNone;
Count1 := 0;
Resource2 := wtNone;
Count2 := 0;
ActCount := 0;
Product1 := wtNone;
ProdCount1 := 0;
Product2 := wtNone;
ProdCount2 := 0;
AfterWorkIdle := 0;
ResourceDepleted := False;
end;
procedure TKMUnitWorkPlan.WalkStyle(const aLoc2: TKMPointDir; aTo, aWork: TKMUnitActionType; aCycles,aDelay: Byte; aFrom: TKMUnitActionType; aScript: TKMGatheringScript);
begin
Loc := aLoc2.Loc;
HasToWalk := True;
ActionWalkTo := aTo;
ActionWorkType := aWork;
WorkCyc := aCycles;
AfterWorkDelay := aDelay;
GatheringScript := aScript;
ActionWalkFrom := aFrom;
WorkDir := aLoc2.Dir;
end;
procedure TKMUnitWorkPlan.SubActAdd(aAct: TKMHouseActionType; aCycles: Single);
begin
HouseAct[ActCount].Act := aAct;
HouseAct[ActCount].TimeToWork := Round(gRes.Houses[fHome].Anim[aAct].Count * aCycles);
Inc(ActCount);
end;
procedure TKMUnitWorkPlan.ResourcePlan(Res1: TKMWareType; Qty1: Byte; Res2: TKMWareType; Qty2: Byte; Prod1: TKMWareType; Prod2: TKMWareType = wtNone);
begin
Resource1 := Res1; Count1 := Qty1;
Resource2 := Res2; Count2 := Qty2;
Product1 := Prod1; ProdCount1 := gRes.Houses[fHome].ResProductionX;
if Prod2=wtNone then exit;
Product2 := Prod2; ProdCount2 := gRes.Houses[fHome].ResProductionX;
end;
function TKMUnitWorkPlan.FindDifferentResource(aUnit: TKMUnit; aLoc: TKMPoint; const aAvoidLoc: TKMPoint): Boolean;
var
NewLoc: TKMPointDir;
PlantAct: TKMPlantAct;
Found: boolean;
HW: TKMHouseWoodcutters;
begin
if (GatheringScript = gsWoodCutterCut) or (GatheringScript = gsWoodCutterPlant) then
begin
HW := TKMHouseWoodcutters(aUnit.Home);
HW.ValidateFlagPoint; //Validate Cutting point. It will be set to a valid one if needed.
if HW.IsFlagPointSet then
aLoc := HW.FlagPoint;
end;
with gTerrain do
case GatheringScript of
gsStoneCutter: Found := FindStone(aLoc, gRes.Units[aUnit.UnitType].MiningRange, aAvoidLoc, False, NewLoc);
gsFarmerSow: Found := FindCornField(aLoc, gRes.Units[aUnit.UnitType].MiningRange, aAvoidLoc, taPlant, PlantAct, NewLoc);
gsFarmerCorn: begin
Found := FindCornField(aLoc, gRes.Units[aUnit.UnitType].MiningRange, aAvoidLoc, taAny, PlantAct, NewLoc);
if PlantAct = taPlant then
begin
GatheringScript := gsFarmerSow; //Switch to sowing corn rather than cutting
ActionWalkFrom := uaWalkTool; //Carry our scythe back (without the corn) as the player saw us take it out
ActionWorkType := uaWork1;
WorkCyc := 10;
Product1 := wtNone; //Don't produce corn
ProdCount1 := 0;
end;
end;
gsFarmerWine: begin
Found := FindWineField(aLoc, gRes.Units[aUnit.UnitType].MiningRange, aAvoidLoc, NewLoc);
NewLoc.Dir := dirN; //The animation for picking grapes is only defined for facing north
end;
gsFisherCatch: Found := FindFishWater(aLoc, gRes.Units[aUnit.UnitType].MiningRange, aAvoidLoc, False, NewLoc);
gsWoodCutterCut: Found := ChooseTree(aLoc, KMGetVertexTile(aAvoidLoc, WorkDir), gRes.Units[aUnit.UnitType].MiningRange, taCut, aUnit, NewLoc, PlantAct);
gsWoodCutterPlant: Found := ChooseTree(aLoc, aAvoidLoc, gRes.Units[aUnit.UnitType].MiningRange, taPlant, aUnit, NewLoc, PlantAct);
else
Found := False; //Can find a new resource for an unknown gathering script, so return with False
end;
if Found then
begin
Loc := NewLoc.Loc;
WorkDir := NewLoc.Dir;
Result := True;
end
else
Result := False;
end;
function TKMUnitWorkPlan.ChooseTree(const aLoc, aAvoid: TKMPoint; aRadius: Integer; aPlantAct: TKMPlantAct; aUnit: TKMUnit; out Tree: TKMPointDir; out PlantAct: TKMPlantAct): Boolean;
var
I: Integer;
T: TKMPoint;
treeList: TKMPointDirCenteredList;
bestToPlant, secondBestToPlant: TKMPointCenteredList;
begin
treeList := TKMPointDirCenteredList.Create(aLoc);
bestToPlant := TKMPointCenteredList.Create(aLoc);
secondBestToPlant := TKMPointCenteredList.Create(aLoc);
gTerrain.FindTree(aLoc, aRadius, aAvoid, aPlantAct, treeList, bestToPlant, secondBestToPlant);
//Convert taAny to either a Tree or a Spot
if (aPlantAct in [taCut, taAny])
and ((treeList.Count > 8) //Always chop the tree if there are many
or (bestToPlant.Count + secondBestToPlant.Count = 0)
or ((treeList.Count > 0) and (KaMRandom({$IFDEF DBG_RNG_SPY}'TKMUnitWorkPlan.ChooseTree'{$ENDIF}) < treeList.Count / (treeList.Count + (bestToPlant.Count + secondBestToPlant.Count)/15)))
) then
begin
PlantAct := taCut;
Result := treeList.GetWeightedRandom(Tree);
end
else
begin
PlantAct := taPlant;
//First try stumps list
for I := bestToPlant.Count - 1 downto 0 do
if not TKMUnitCitizen(aUnit).CanWorkAt(bestToPlant[I], gsWoodCutterPlant) then
bestToPlant.Delete(I);
Result := bestToPlant.GetWeightedRandom(T);
//Trees must always be planted facing north as that is the direction the animation uses
if Result then
Tree := KMPointDir(T, dirN)
else
begin
//Try empty places list
for I := secondBestToPlant.Count - 1 downto 0 do
if not TKMUnitCitizen(aUnit).CanWorkAt(secondBestToPlant[I], gsWoodCutterPlant) then
secondBestToPlant.Delete(I);
Result := secondBestToPlant.GetWeightedRandom(T);
//Trees must always be planted facing north as that is the direction the animation uses
if Result then
Tree := KMPointDir(T, dirN);
end;
end;
treeList.Free;
bestToPlant.Free;
secondBestToPlant.Free;
end;
procedure TKMUnitWorkPlan.FindPlan(aUnit: TKMUnit; aHome: TKMHouseType; aProduct: TKMWareType; aLoc: TKMPoint; aPlantAct: TKMPlantAct);
var
I: Integer;
tmp: TKMPointDir;
plantAct: TKMPlantAct;
HW: TKMHouseWoodcutters;
begin
Clear;
fHome := aHome;
AfterWorkIdle := gRes.Houses[aHome].WorkerRest * 10;
//Now we need to fill only specific properties
case aUnit.UnitType of
utWoodcutter: if aHome = htWoodcutters then
begin
HW := TKMHouseWoodcutters(aUnit.Home);
HW.ValidateFlagPoint; //Validate Cutting point. It will be set to a valid one if needed.
if HW.IsFlagPointSet then
aLoc := HW.FlagPoint;
fIssued := ChooseTree(aLoc, KMPOINT_ZERO, gRes.Units[aUnit.UnitType].MiningRange, aPlantAct, aUnit, tmp, plantAct);
if fIssued then
begin
case plantAct of
taCut: begin //Cutting uses DirNW,DirSW,DirSE,DirNE (1,3,5,7) of uaWork
ResourcePlan(wtNone,0,wtNone,0,wtTrunk);
WalkStyle(tmp, uaWalkBooty,uaWork,15,20,uaWalkTool2,gsWoodCutterCut);
end;
taPlant: begin //Planting uses DirN (0) of uaWork
WalkStyle(tmp, uaWalkTool,uaWork,12,0,uaWalk,gsWoodCutterPlant);
end;
else fIssued := False;
end;
end
else
case plantAct of
taCut: if not gTerrain.CanFindTree(aLoc, gRes.Units[aUnit.UnitType].MiningRange) then
ResourceDepleted := True; //No more trees to cut
taPlant: if HW.WoodcutterMode = wmPlant then
ResourceDepleted := True; //No place for trees to plant
end;
end;
utMiner: if aHome = htCoalMine then
begin
fIssued := gTerrain.FindOre(aLoc, wtCoal, tmp.Loc);
if fIssued then
begin
Loc := tmp.Loc;
ResourcePlan(wtNone,0,wtNone,0,wtCoal);
GatheringScript := gsCoalMiner;
SubActAdd(haWork1,1);
SubActAdd(haWork2,23);
SubActAdd(haWork5,1);
end else
ResourceDepleted := True;
end else
if aHome = htIronMine then
begin
fIssued := gTerrain.FindOre(aLoc, wtIronOre, tmp.Loc);
if fIssued then
begin
Loc := tmp.Loc;
ResourcePlan(wtNone,0,wtNone,0,wtIronOre);
GatheringScript := gsIronMiner;
SubActAdd(haWork1,1);
SubActAdd(haWork2,24);
SubActAdd(haWork5,1);
end else
ResourceDepleted := True;
end else
if aHome = htGoldMine then
begin
fIssued := gTerrain.FindOre(aLoc, wtGoldOre, tmp.Loc);
if fIssued then
begin
Loc := tmp.Loc;
ResourcePlan(wtNone,0,wtNone,0,wtGoldOre);
GatheringScript := gsGoldMiner;
SubActAdd(haWork1,1);
SubActAdd(haWork2,24);
SubActAdd(haWork5,1);
end else
ResourceDepleted := True;
end;
utAnimalBreeder: if aHome = htSwine then
begin
ResourcePlan(wtCorn,1,wtNone,0,wtPig,wtSkin);
GatheringScript := gsSwineBreeder;
for I := 0 to 3 do
begin
SubActAdd(haWork2,1);
SubActAdd(haWork3,1);
end;
SubActAdd(haWork2,1);
fIssued := True;
end else
if aHome = htStables then
begin
ResourcePlan(wtCorn,1,wtNone,0,wtHorse);
GatheringScript := gsHorseBreeder;
SubActAdd(haWork1,1);
SubActAdd(haWork2,1);
SubActAdd(haWork3,1);
SubActAdd(haWork4,1);
SubActAdd(haWork5,1);
fIssued := True;
end;
utFarmer: if aHome = htFarm then
begin
fIssued := gTerrain.FindCornField(aLoc, gRes.Units[aUnit.UnitType].MiningRange, KMPOINT_ZERO, aPlantAct, plantAct, tmp);
if fIssued then
case plantAct of
taCut: begin
ResourcePlan(wtNone,0,wtNone,0,wtCorn);
WalkStyle(tmp, uaWalkTool,uaWork,6,0,uaWalkBooty,gsFarmerCorn);
end;
taPlant: WalkStyle(tmp, uaWalk,uaWork1,10,0,uaWalk,gsFarmerSow);
else fIssued := False;
end;
end else
if aHome = htVineyard then
begin
fIssued := gTerrain.FindWineField(aLoc, gRes.Units[aUnit.UnitType].MiningRange, KMPOINT_ZERO, tmp);
if fIssued then
begin
ResourcePlan(wtNone,0,wtNone,0,wtWine);
WalkStyle(KMPointDir(tmp.Loc,dirN), uaWalkTool2,uaWork2,5,0,uaWalkBooty2,gsFarmerWine); //The animation for picking grapes is only defined for facing north
SubActAdd(haWork1,1);
SubActAdd(haWork2,11);
SubActAdd(haWork5,1);
end;
end;
utCarpenter: if aHome = htSawmill then
begin
ResourcePlan(wtTrunk,1,wtNone,0,wtTimber);
SubActAdd(haWork1,1);
SubActAdd(haWork2,25);
SubActAdd(haWork5,1);
fIssued := True;
end else
if (aHome = htArmorWorkshop) and (aProduct = wtLeatherArmor) then
begin
ResourcePlan(wtLeather,1,wtNone,0,wtLeatherArmor);
for I := 0 to 3 do
begin
SubActAdd(haWork2,1);
SubActAdd(haWork3,1);
SubActAdd(haWork4,1);
end;
SubActAdd(haWork2,0.25);
fIssued := True;
end else
if (aHome = htArmorWorkshop) and (aProduct = wtWoodenShield) then
begin
ResourcePlan(wtTimber,1,wtNone,0,wtWoodenShield);
for I := 0 to 3 do
begin
SubActAdd(haWork2,1);
SubActAdd(haWork3,1);
SubActAdd(haWork4,1);
end;
SubActAdd(haWork2,0.25);
fIssued := True;
end else
if (aHome = htWeaponWorkshop) and (aProduct = wtAxe) then
begin
ResourcePlan(wtTimber,2,wtNone,0,wtAxe);
SubActAdd(haWork1,1);
for I := 0 to 2 do
begin
SubActAdd(haWork2,1);
SubActAdd(haWork3,1);
SubActAdd(haWork4,1);
end;
SubActAdd(haWork5,1);
fIssued := True;
end else
if (aHome = htWeaponWorkshop) and (aProduct = wtLance) then
begin
ResourcePlan(wtTimber,2,wtNone,0,wtLance);
SubActAdd(haWork1,1);
for I := 0 to 2 do
begin
SubActAdd(haWork2,1);
SubActAdd(haWork3,1);
SubActAdd(haWork4,1);
end;
SubActAdd(haWork5,1);
fIssued := True;
end else
if (aHome = htWeaponWorkshop) and (aProduct = wtBow) then
begin
ResourcePlan(wtTimber,2,wtNone,0,wtBow);
SubActAdd(haWork1,1);
for I := 0 to 2 do
begin
SubActAdd(haWork2,1);
SubActAdd(haWork3,1);
SubActAdd(haWork4,1);
end;
SubActAdd(haWork5,1);
fIssued := True;
end;
utBaker: if aHome = htMill then
begin
ResourcePlan(wtCorn,1,wtNone,0,wtFlour);
SubActAdd(haWork2,47);
fIssued := True;
end else
if aHome = htBakery then
begin
ResourcePlan(wtFlour,1,wtNone,0,wtBread);
for I := 0 to 6 do
begin
SubActAdd(haWork2,1);
SubActAdd(haWork3,1);
end;
fIssued := True;
end;
utButcher: if aHome = htTannery then
begin
ResourcePlan(wtSkin,1,wtNone,0,wtLeather);
SubActAdd(haWork1,1);
SubActAdd(haWork2,29);
fIssued := True;
end else
if aHome = htButchers then
begin
ResourcePlan(wtPig,1,wtNone,0,wtSausage);
SubActAdd(haWork1,1);
for I := 0 to 5 do
begin
SubActAdd(haWork2,1);
SubActAdd(haWork4,1);
SubActAdd(haWork3,1);
end;
fIssued := True;
end;
utFisher: if aHome = htFishermans then
begin
fIssued := gTerrain.FindFishWater(aLoc, gRes.Units[aUnit.UnitType].MiningRange, KMPOINT_ZERO, False, tmp);
if fIssued then
begin
ResourcePlan(wtNone,0,wtNone,0,wtFish);
WalkStyle(tmp,uaWalk,uaWork2,10,0,uaWalkTool,gsFisherCatch);
end else
//We must check again this time ignoring working units since they don't indicate the resource is depleted
ResourceDepleted := not gTerrain.FindFishWater(aLoc, gRes.Units[aUnit.UnitType].MiningRange, KMPOINT_ZERO, True, tmp);
end;
utStonemason: if aHome = htQuarry then
begin
fIssued := gTerrain.FindStone(aLoc, gRes.Units[aUnit.UnitType].MiningRange, KMPOINT_ZERO, False, tmp);
if fIssued then
begin
ResourcePlan(wtNone,0,wtNone,0,wtStone);
WalkStyle(tmp, uaWalk,uaWork,8,0,uaWalkTool,gsStoneCutter);
SubActAdd(haWork1,1);
SubActAdd(haWork2,9);
SubActAdd(haWork5,1);
end else
//We must check again this time ignoring working units since they don't indicate the resource is depleted
ResourceDepleted := not gTerrain.FindStone(aLoc, gRes.Units[aUnit.UnitType].MiningRange, KMPOINT_ZERO, True, tmp);
end;
utSmith: if (aHome = htArmorSmithy) and (aProduct = wtIronShield) then
begin
ResourcePlan(wtIron,1,wtCoal,1,wtIronShield);
for I := 0 to 3 do
begin
SubActAdd(haWork2,1);
SubActAdd(haWork3,1);
SubActAdd(haWork4,1);
end;
SubActAdd(haWork2,1);
SubActAdd(haWork5,1);
fIssued := True;
end else
if (aHome = htArmorSmithy) and (aProduct = wtIronArmor) then
begin
ResourcePlan(wtIron,1,wtCoal,1,wtIronArmor);
for I := 0 to 3 do
begin
SubActAdd(haWork2,1);
SubActAdd(haWork3,1);
SubActAdd(haWork4,1);
end;
SubActAdd(haWork2,1);
SubActAdd(haWork5,1);
fIssued := True;
end else
if (aHome = htWeaponSmithy) and (aProduct = wtSword) then
begin
ResourcePlan(wtIron,1,wtCoal,1,wtSword);
SubActAdd(haWork1,1);
for I := 0 to 2 do
begin
SubActAdd(haWork2,1);
SubActAdd(haWork3,1);
SubActAdd(haWork4,1);
end;
SubActAdd(haWork5,1);
fIssued := True;
end else
if (aHome = htWeaponSmithy) and (aProduct = wtPike) then
begin
ResourcePlan(wtIron,1,wtCoal,1,wtPike);
SubActAdd(haWork1,1);
for I := 0 to 2 do
begin
SubActAdd(haWork2,1);
SubActAdd(haWork3,1);
SubActAdd(haWork4,1);
end;
SubActAdd(haWork5,1);
fIssued := True;
end else
if (aHome = htWeaponSmithy) and (aProduct = wtCrossbow) then
begin
ResourcePlan(wtIron,1,wtCoal,1,wtCrossbow);
SubActAdd(haWork1,1);
for I := 0 to 2 do
begin
SubActAdd(haWork2,1);
SubActAdd(haWork3,1);
SubActAdd(haWork4,1);
end;
SubActAdd(haWork5,1);
fIssued := True;
end;
utMetallurgist: if aHome = htIronSmithy then
begin
ResourcePlan(wtIronOre,1,wtCoal,1,wtIron);
for I := 0 to 3 do
begin
SubActAdd(haWork2,1);
SubActAdd(haWork3,1);
end;
SubActAdd(haWork2,1);
SubActAdd(haWork3,0.25);
fIssued := True;
end else
if aHome = htMetallurgists then
begin
ResourcePlan(wtGoldOre,1,wtCoal,1,wtGold);
for I := 0 to 3 do
begin
SubActAdd(haWork2,1);
SubActAdd(haWork3,1);
SubActAdd(haWork4,1);
end;
SubActAdd(haWork2,1);
SubActAdd(haWork3,0.1);
fIssued := True;
end;
else
raise Exception.Create('No work plan for ' +
gRes.Units[aUnit.UnitType].GUIName + ' in ' +
gRes.Houses[aHome].HouseName);
end;
end;
procedure TKMUnitWorkPlan.Load(LoadStream: TKMemoryStream);
var
I: Integer;
begin
LoadStream.CheckMarker('WorkPlan');
LoadStream.Read(fHome, SizeOf(fHome));
LoadStream.Read(fIssued);
//public
LoadStream.Read(HasToWalk);
LoadStream.Read(Loc);
LoadStream.Read(ActionWalkTo, SizeOf(ActionWalkTo));
LoadStream.Read(ActionWorkType, SizeOf(ActionWorkType));
LoadStream.Read(WorkCyc);
LoadStream.Read(WorkDir);
LoadStream.Read(GatheringScript, SizeOf(GatheringScript));
LoadStream.Read(AfterWorkDelay);
LoadStream.Read(ActionWalkFrom, SizeOf(ActionWalkFrom));
LoadStream.Read(Resource1, SizeOf(Resource1));
LoadStream.Read(Count1);
LoadStream.Read(Resource2, SizeOf(Resource2));
LoadStream.Read(Count2);
LoadStream.Read(ActCount);
for I := 0 to ActCount - 1 do //Write only assigned
begin
LoadStream.Read(HouseAct[I].Act, SizeOf(HouseAct[I].Act));
LoadStream.Read(HouseAct[I].TimeToWork);
end;
LoadStream.Read(Product1, SizeOf(Product1));
LoadStream.Read(ProdCount1);
LoadStream.Read(Product2, SizeOf(Product2));
LoadStream.Read(ProdCount2);
LoadStream.Read(AfterWorkIdle);
LoadStream.Read(ResourceDepleted);
end;
procedure TKMUnitWorkPlan.Save(SaveStream: TKMemoryStream);
var
I: Integer;
begin
SaveStream.PlaceMarker('WorkPlan');
SaveStream.Write(fHome, SizeOf(fHome));
SaveStream.Write(fIssued);
//public
SaveStream.Write(HasToWalk);
SaveStream.Write(Loc);
SaveStream.Write(ActionWalkTo, SizeOf(ActionWalkTo));
SaveStream.Write(ActionWorkType, SizeOf(ActionWorkType));
SaveStream.Write(WorkCyc);
SaveStream.Write(WorkDir);
SaveStream.Write(GatheringScript, SizeOf(GatheringScript));
SaveStream.Write(AfterWorkDelay);
SaveStream.Write(ActionWalkFrom, SizeOf(ActionWalkFrom));
SaveStream.Write(Resource1, SizeOf(Resource1));
SaveStream.Write(Count1);
SaveStream.Write(Resource2, SizeOf(Resource2));
SaveStream.Write(Count2);
SaveStream.Write(ActCount);
for I := 0 to ActCount - 1 do //Write only assigned
begin
SaveStream.Write(HouseAct[I].Act, SizeOf(HouseAct[I].Act));
SaveStream.Write(HouseAct[I].TimeToWork);
end;
SaveStream.Write(Product1, SizeOf(Product1));
SaveStream.Write(ProdCount1);
SaveStream.Write(Product2, SizeOf(Product2));
SaveStream.Write(ProdCount2);
SaveStream.Write(AfterWorkIdle);
SaveStream.Write(ResourceDepleted);
end;
end.