Changeset 407


Ignore:
Timestamp:
Jan 8, 2025, 10:18:12 AM (37 hours ago)
Author:
chronos
Message:
  • Fixed: Cell cities were not correctly stored the saved game.
  • Fixed: ItemList references were loaded by item index instead of item id.
Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Building.pas

    r344 r407  
    3939  public
    4040    Kind: TBuildingKind;
     41    Game: TObject; // TGame
     42    class function GetFields: TItemFields; override;
     43    procedure GetValue(Index: Integer; out Value); override;
     44    procedure SetValue(Index: Integer; var Value); override;
     45    function GetReferenceList(Index: Integer): TBaseItemList; override;
    4146    procedure Assign(Source: TItem); override;
    4247    property MapCell: TObject read FMapCell write SetMapCell; // TMapCell;
     
    4752  TBuildings = class(TItemList<TBuilding>)
    4853    Game: TObject; // TGame;
     54    function CreateItem(Name: string = ''): TBuilding; override;
     55    procedure Assign(Source: TItemList<TBuilding>); override;
    4956  end;
    5057
     
    6471
    6572uses
    66   Map;
     73  Map, Game;
    6774
    6875{ TBuilding }
     
    8087end;
    8188
     89class function TBuilding.GetFields: TItemFields;
     90var
     91  Field: TItemField;
     92begin
     93  Result := inherited;
     94  Field := Result.AddField(2, 'Kind', SBuildingKind, dtReference);
     95end;
     96
     97procedure TBuilding.GetValue(Index: Integer; out Value);
     98begin
     99  if Index = 1 then string(Value) := Name
     100  else if Index = 2 then TBuildingKind(Value) := Kind
     101  else inherited;
     102end;
     103
     104procedure TBuilding.SetValue(Index: Integer; var Value);
     105begin
     106  if Index = 1 then Name := string(Value)
     107  else if Index = 2 then Kind := TBuildingKind(Value)
     108  else inherited;
     109end;
     110
     111function TBuilding.GetReferenceList(Index: Integer): TBaseItemList;
     112begin
     113  if Index = 2 then Result := TGame(Game).GameSystem.BuildingKinds.BaseItemList
     114  else Result := nil;
     115end;
     116
    82117procedure TBuilding.Assign(Source: TItem);
    83118begin
    84119  inherited;
    85120  Kind := TBuilding(Source).Kind;
     121end;
     122
     123{ TBuildings }
     124
     125function TBuildings.CreateItem(Name: string): TBuilding;
     126begin
     127  Result := inherited;
     128  Result.Game := Game;
     129end;
     130
     131procedure TBuildings.Assign(Source: TItemList<TBuilding>);
     132var
     133  I: Integer;
     134begin
     135  inherited;
     136  for I := 0 to Count - 1 do
     137    Items[I].Game := Game;
    86138end;
    87139
  • trunk/Core.pas

    r406 r407  
    284284  if not Assigned(Game.CurrentPlayer) then
    285285    Game.CurrentPlayer := Game.Players.GetFirstHuman;
    286   if Assigned(Game.CurrentPlayer) then begin
     286  if Assigned(Game.CurrentPlayer) and (Game.CurrentPlayer.Mode = pmHuman) then begin
    287287    FormMain.FormClient.Client := TClientGUI(LocalClients.SearchPlayer(Game.CurrentPlayer));
    288288  end else begin
  • trunk/Game.pas

    r399 r407  
    5858    procedure InitDefaultPlayers;
    5959    procedure WinObjectiveMapPrepare;
     60    procedure BuildCity(Cell: TCell);
    6061  public
    6162    GameSystem: TGameSystem;
     
    342343  with Cell do begin
    343344    if (Terrain = ttNormal) and CityEnabled and (Random < CityPercentage / 100) then begin
    344       Building := Buildings.AddItem('City');
    345       Building.Kind := GameSystem.BuildingKinds.FindBySpecialType(stCity);
     345      BuildCity(Cell);
    346346    end;
    347347  end;
     
    369369          StartCell := Map.Cells[Map.Cells.Count - 1 - Map.Cells.IndexOf(Players[0].StartCell)];
    370370
    371         if CityEnabled then begin
    372           StartCell.Building := Buildings.AddItem('City');
    373           StartCell.Building.Kind := GameSystem.BuildingKinds.FindBySpecialType(stCity);
    374         end;
     371        if CityEnabled then BuildCity(StartCell);
    375372        StartCell.Player := Player;
    376373        if GameSystem.UnitKinds.Count > 0 then begin
     
    497494end;
    498495
     496procedure TGame.BuildCity(Cell: TCell);
     497var
     498  CityBuildingKind: TBuildingKind;
     499begin
     500  CityBuildingKind := GameSystem.BuildingKinds.FindBySpecialType(stCity);
     501  if not Assigned(CityBuildingKind) then begin
     502    CityBuildingKind := GameSystem.BuildingKinds.AddItem('City');
     503    CityBuildingKind.SpecialType := stCity;
     504  end;
     505  if not Assigned(Cell.Building) then begin
     506    Cell.Building := Buildings.AddItem('City');
     507    Cell.Building.Kind := CityBuildingKind;
     508    Cell.Building.Game := Self;
     509  end;
     510end;
     511
    499512procedure TGame.Assign(Source: TGame);
    500513begin
     
    502515  DevelMode := Source.DevelMode;
    503516  Players.Assign(Source.Players);
     517  Buildings.Assign(Source.Buildings);
    504518  MapType := Source.MapType;
    505519  Map.Assign(Source.Map);
     
    647661        Units.LoadFromNode(NewNode);
    648662
     663      NewNode := FindNode('Buildings');
     664      if Assigned(NewNode) then
     665        Buildings.LoadFromNode(NewNode);
     666
    649667      Map.Cells.FixRefId;
    650668      Units.FixRefId;
     
    697715      Units.RecalculateItemsId;
    698716      Players.RecalculateItemsId;
     717      Buildings.RecalculateItemsId;
    699718
    700719      NewNode := OwnerDocument.CreateElement('GameSystem');
     
    713732      AppendChild(NewNode);
    714733      Units.SaveToNode(NewNode);
     734
     735      NewNode := OwnerDocument.CreateElement('Buildings');
     736      AppendChild(NewNode);
     737      Buildings.SaveToNode(NewNode);
    715738    end;
    716739    if ExtractFileDir(FileName) <> '' then
     
    955978  Map.Clear;
    956979  Units.Clear;
     980  Buildings.Clear;
    957981end;
    958982
  • trunk/Map.pas

    r398 r407  
    4848    Extra: TExtraType;
    4949    OneUnitId: Integer; // Temporary value
     50    BuildingId: Integer; // Temporary value
    5051    function Compare(Cell: TCell): Boolean;
    5152    procedure ConnectTo(Cell: TCell);
     
    10641065  end else Player := nil;
    10651066
     1067  if BuildingId <> 0 then begin
     1068    Building := TGame(Map.Game).Buildings.FindById(BuildingId);
     1069    if not Assigned(Building) then
     1070      raise Exception.Create('Referenced building id ' + IntToStr(BuildingId) + ' not found.');
     1071  end else Building := nil;
     1072
    10661073  if OneUnitId <> 0 then begin
    10671074    OneUnit := TGame(Map.Game).Units.FindById(OneUnitId);
     
    10951102  PosPx.Y := ReadInteger(Node, 'PosY', 0);
    10961103  PlayerId := ReadInteger(Node, 'Player', 0);
     1104  BuildingId := ReadInteger(Node, 'Building', 0);
    10971105
    10981106  Node3 := Node.FindNode('Neighbours');
     
    11351143    WriteInteger(Node, 'Player', TPlayer(Player).Id)
    11361144    else WriteInteger(Node, 'Player', 0);
     1145  if Assigned(Building) then
     1146    WriteInteger(Node, 'Building', Building.Id)
     1147    else WriteInteger(Node, 'Building', 0);
    11371148  NewNode := Node.OwnerDocument.CreateElement('Neighbours');
    11381149  Node.AppendChild(NewNode);
  • trunk/Packages/Common/ItemList.pas

    r399 r407  
    8383  public
    8484  type
    85     TAddEvent = function (constref AValue: TItem): SizeInt of object;
     85    TAddEvent = function(constref AValue: TItem): SizeInt of object;
    8686    TGetCountEvent = function: SizeInt of object;
    8787    TSetItemEvent = procedure(Index: SizeInt; AValue: TItem) of object;
    88     TGetNameEvent = procedure (out Name: string) of object;
     88    TGetNameEvent = procedure(out Name: string) of object;
    8989    TGetItemEvent = function(Index: SizeInt): TItem of object;
    9090    TGetItemFieldsEvent = function: TItemFields of object;
    9191    TRemoveEvent = function(constref AValue: TItem): SizeInt of object;
    92     TGetNextAvailableNameEvent = procedure (Name: string; out NewName: string) of object;
     92    TGetNextAvailableNameEvent = procedure(Name: string; out NewName: string) of object;
    9393    TCreateItemEvent = function(Name: string = ''): TItem of object;
     94    TFindByIdEvent = function(Id: Integer): TItem of object;
    9495  private
    9596    FOnAdd: TAddEvent;
    9697    FOnCreateItem: TCreateItemEvent;
     98    FOnFindById: TFindByIdEvent;
    9799    FOnGetCount: TGetCountEvent;
    98100    FOnGetItem: TGetItemEvent;
     
    112114    function GetNextAvailableName(Name: string): string;
    113115    function GetItemFields: TItemFields;
     116    function FindById(Id: Integer): TItem;
    114117    property Count: SizeInt read GetCount;
    115118    property Items[Index: SizeInt]: TItem read GetItem write SetItem; default;
     
    125128    property OnCreateItem: TCreateItemEvent read FOnCreateItem
    126129      write FOnCreateItem;
     130    property OnFindById: TFindByIdEvent read FOnFindById
     131      write FOnFindById;
    127132  end;
    128133
     
    141146    function BaseGetItemFields: TItemFields;
    142147    function BaseCreateItem(Name: string = ''): TItem;
     148    function BaseFindById(Id: Integer): TItem;
    143149    procedure BaseGetNextAvailableName(Name: string; out NewName: string);
    144150  public
     
    245251end;
    246252
     253function TItemList<T>.BaseFindById(Id: Integer): TItem;
     254begin
     255  Result := FindById(Id);
     256end;
     257
    247258procedure TItemList<T>.LoadFromNode(Node: TDOMNode);
    248259var
     
    286297  FBaseItemList.OnGetNextAvailableName := BaseGetNextAvailableName;
    287298  FBaseItemList.OnGetName := BaseGetName;
     299  FBaseItemList.OnFindById := BaseFindById;
    288300  NewId := 1;
    289301end;
     
    483495  ReadId: Integer;
    484496  ReferenceList: TBaseItemList;
     497  RefItem: TItem;
    485498begin
    486499  if Field.DataType = dtString then begin
     
    503516    ReferenceList := GetReferenceList(Field.Index);
    504517    if (ReadId > 0) and Assigned(ReferenceList) then
    505       SetValueReference(Field.Index, TItem(ReferenceList[ReadId]));
     518      RefItem := ReferenceList.FindById(ReadId);
     519      if Assigned(RefItem) then
     520        SetValueReference(Field.Index, RefItem)
     521        else raise Exception.Create('Reference id ' + IntToStr(ReadId) + ' not found.');
    506522  end else
    507523    raise Exception.Create(Format(SUnsupportedDataType, [DataTypeStr[Field.DataType]]));
     
    817833end;
    818834
     835function TBaseItemList.FindById(Id: Integer): TItem;
     836begin
     837  if Assigned(FOnFindById) then Result := FOnFindById(Id)
     838    else raise Exception.Create('Undefined FindById handler');
     839end;
     840
    819841end.
    820842
Note: See TracChangeset for help on using the changeset viewer.