source: trunk/Units.pas

Last change on this file was 399, checked in by chronos, 2 weeks ago
  • Fixed: Wrong players and units id recalculation during game save causing bad references.
  • Modified: Set new created players as computer.
File size: 5.8 KB
Line 
1unit Units;
2
3interface
4
5uses
6 Classes, SysUtils, Generics.Collections, Geometry, DOM, XML, ItemList, UnitKind;
7
8type
9 TUnit = class
10 private
11 FId: Integer;
12 FMapCell: TObject; // TCell
13 FPlayer: TObject; // TPlayer
14 procedure SetId(AValue: Integer);
15 procedure SetMapCell(AValue: TObject);
16 procedure SetPlayer(AValue: TObject);
17 public
18 Game: TObject; // TGame
19 Kind: TUnitKind;
20 KindId: Integer; // Temporary
21 Power: Integer;
22 Moves: Integer;
23 Position: TPoint;
24 PlayerId: Integer; // Temporary
25 procedure FixRefId;
26 function GetPowerAttack: Integer;
27 function GetPowerDefense: Integer;
28 procedure LoadFromNode(Node: TDOMNode);
29 procedure SaveToNode(Node: TDOMNode);
30 procedure Assign(Source: TUnit);
31 constructor Create;
32 destructor Destroy; override;
33 property Player: TObject read FPlayer write SetPlayer; // TPlayer
34 property MapCell: TObject read FMapCell write SetMapCell; // TMapCell;
35 property Id: Integer read FId write SetId;
36 end;
37
38 { TUnits }
39
40 TUnits = class(TObjectList<TUnit>)
41 NewId: Integer;
42 Game: TObject; //TGame;
43 procedure RecalculateItemsId;
44 procedure FixRefId;
45 function FindById(Id: Integer): TUnit;
46 function GetNewId: Integer;
47 procedure LoadFromNode(Node: TDOMNode);
48 procedure SaveToNode(Node: TDOMNode);
49 function AddNew(Kind: TUnitKind; Power: Integer): TUnit;
50 constructor Create(FreeObjects: Boolean = True);
51 procedure Assign(Source: TUnits);
52 end;
53
54
55implementation
56
57uses
58 Player, Map, Game;
59
60{ TUnits }
61
62procedure TUnits.RecalculateItemsId;
63var
64 I: Integer;
65begin
66 for I := 0 to Count - 1 do
67 Items[I].Id := I + 1;
68 NewId := Count + 1;
69end;
70
71procedure TUnits.FixRefId;
72var
73 I: Integer;
74begin
75 for I := 0 to Count - 1 do
76 Items[I].FixRefId;
77end;
78
79function TUnits.FindById(Id: Integer): TUnit;
80var
81 I: Integer;
82begin
83 I := 0;
84 while (I < Count) and (Items[I].Id <> Id) do Inc(I);
85 if I < Count then Result := Items[I]
86 else Result := nil;
87end;
88
89function TUnits.GetNewId: Integer;
90begin
91 Result := NewId;
92 Inc(NewId);
93end;
94
95procedure TUnits.LoadFromNode(Node: TDOMNode);
96var
97 Node2: TDOMNode;
98 NewItem: TUnit;
99begin
100 Count := 0;
101 Node2 := Node.FirstChild;
102 while Assigned(Node2) and (Node2.NodeName = 'Unit') do begin
103 NewItem := TUnit.Create;
104 NewItem.Game := Game;
105 NewItem.LoadFromNode(Node2);
106 Add(NewItem);
107 Node2 := Node2.NextSibling;
108 end;
109end;
110
111procedure TUnits.SaveToNode(Node: TDOMNode);
112var
113 I: Integer;
114 NewNode2: TDOMNode;
115begin
116 for I := 0 to Count - 1 do
117 with Items[I] do begin
118 NewNode2 := Node.OwnerDocument.CreateElement('Unit');
119 Node.AppendChild(NewNode2);
120 SaveToNode(NewNode2);
121 end;
122end;
123
124function TUnits.AddNew(Kind: TUnitKind; Power: Integer): TUnit;
125begin
126 Result := TUnit.Create;
127 Result.Id := GetNewId;
128 Result.Kind := Kind;
129 Result.Power := Power;
130 Result.Game := Game;
131 Add(Result);
132end;
133
134constructor TUnits.Create(FreeObjects: Boolean);
135begin
136 inherited;
137 NewId := 1;
138end;
139
140procedure TUnits.Assign(Source: TUnits);
141var
142 I: Integer;
143begin
144 while Count > Source.Count do
145 Delete(Count - 1);
146 while Count < Source.Count do
147 Add(TUnit.Create);
148 for I := 0 to Count - 1 do begin
149 Items[I].Assign(Source[I]);
150 Items[I].Game := Game;
151 end;
152 NewId := Source.NewId;
153end;
154
155{ TUnit }
156
157procedure TUnit.SetId(AValue: Integer);
158begin
159 if FId = AValue then Exit;
160 FId := AValue;
161end;
162
163procedure TUnit.SetMapCell(AValue: TObject);
164var
165 OldValue: TCell;
166begin
167 if FMapCell = AValue then Exit;
168 OldValue := TCell(FMapCell);
169 FMapCell := nil;
170 if Assigned(OldValue) then OldValue.OneUnit := nil;
171 FMapCell := AValue;
172 if Assigned(FMapCell) then TCell(FMapCell).OneUnit := Self;
173end;
174
175procedure TUnit.SetPlayer(AValue: TObject);
176var
177 OldValue: TPlayer;
178begin
179 if FPlayer = AValue then Exit;
180 OldValue := TPlayer(FPlayer);
181 FPlayer := nil;
182 if Assigned(OldValue) then TPlayer(OldValue).Units.Remove(Self);
183 FPlayer := AValue;
184 if Assigned(FPlayer) then TPlayer(FPlayer).Units.Add(Self);
185end;
186
187procedure TUnit.FixRefId;
188begin
189 if PlayerId <> 0 then begin
190 Player := TGame(Game).Players.FindById(PlayerId);
191 if not Assigned(Player) then
192 raise Exception.Create('Referenced player id ' + IntToStr(PlayerId) + ' not found.');
193 end else Player := nil;
194
195 if KindId <> 0 then begin
196 Kind := TGame(Game).GameSystem.UnitKinds.FindById(KindId);
197 if not Assigned(Kind) then
198 raise Exception.Create('Referenced unit kind id ' + IntToStr(KindId) + ' not found.');
199 end else Kind := nil;
200end;
201
202function TUnit.GetPowerAttack: Integer;
203begin
204 Result := Power * Kind.PowerAttack;
205end;
206
207function TUnit.GetPowerDefense: Integer;
208begin
209 Result := Power * Kind.PowerDefense;
210end;
211
212procedure TUnit.LoadFromNode(Node: TDOMNode);
213begin
214 Id := ReadInteger(Node, 'Id', 0);
215 Power := ReadInteger(Node, 'Power', 0);
216 Moves := ReadInteger(Node, 'Moves', 0);
217 KindId := ReadInteger(Node, 'Kind', 0);
218 PlayerId := ReadInteger(Node, 'Player', 0);
219end;
220
221procedure TUnit.SaveToNode(Node: TDOMNode);
222begin
223 WriteInteger(Node, 'Id', Id);
224 WriteInteger(Node, 'Power', Power);
225 WriteInteger(Node, 'Moves', Moves);
226 if Assigned(Kind) then WriteInteger(Node, 'Kind', Kind.Id)
227 else WriteInteger(Node, 'Kind', 0);
228 if Assigned(Player) then WriteInteger(Node, 'Player', TPlayer(Player).Id)
229 else WriteInteger(Node, 'Player', 0);
230end;
231
232procedure TUnit.Assign(Source: TUnit);
233begin
234 Kind := Source.Kind;
235 Moves := Source.Moves;
236 Power := Source.Power;
237 Id := Source.Id;
238end;
239
240constructor TUnit.Create;
241begin
242 Player := nil;
243end;
244
245destructor TUnit.Destroy;
246begin
247 MapCell := nil;
248 Player := nil;
249 inherited;
250end;
251
252end.
253
Note: See TracBrowser for help on using the repository browser.