I'm working on a game project, and I need to blindly be able to duplicate a class. Because Pascal cannot do this natively, what I'm doing is writing code for Assign so that I can assign from the original to the new. The usage of this would be for store inventory to a player's inventory in a RPG.
For instance, here's my Assign event for the base TItem class.
Code:
procedure TItem.Assign(From: TItem);
begin
fCopied := True;
fName := From.Name;
fDesc := From.Description;
fIntName := From.InternalName;
fValue := From.Value;
// No idea if the following will work!
fAttr[0] := From.fAttr[0].ClassType.Create;
fAttr[1] := From.fAttr[1].ClassType.Create;
fAttr[0].Assign(From.fAttr[0]);
fAttr[1].Assign(From.fAttr[1]);
end;
fAttr is a defined as: "array[0..1] of IAttribute". This sort of thing would be if you get a smith to harden your sword, you'd gain the attribute and it'd apply its bonus(es) to the item. Only trouble is, as you can see, I'm struggling to figure out if this sort of blind creation will work. Every Attribute, when I get them written, will have a Create call with no parameters and will be assigned to from the attribute derived from.
Ick, this is more complex than I had thought. I'll just post the source (it is all untested!).
What do you all think? Will this work, and if it won't then how can I fix it? I really need some kind of way to make a blind construction system like this.
Code:
// This source is private source code, please don't reuse it in your projects
// without my express written permission.
unit uWeapon;
interface
type
TItem = class;
// An attribute is a bonus to a given item.
IAttribute = interface
procedure ApplyTo(What: TItem);
procedure Assign(From: IAttribute);
end;
IAttributePair = Array[0..1] of IAttribute;
// Placeholder class for a real inventory item class
TItem = class
private
fCopied: Boolean;
fName, fDesc, fIntName: String;
fValue: Single;
fAttr: IAttributePair;
function GetAttr(Index: Boolean): IAttribute;
procedure SetAttr(Index: Boolean; Value: IAttribute);
public
property Name: String read fName write fName default 'Unknown';
property Description: String read fDesc write fDesc;
property InternalName: String read fIntName write fIntName;
property Value: Single read fValue write fValue default 0.00;
// Indexer...
property Attributes[Index: Boolean]: IAttribute read GetAttr write SetAttr;
// Constructor/destructor...
constructor Create;
destructor Destroy;
// Basic functions...
procedure Assign(From: TItem);
end;
implementation
constructor TItem.Create;
begin
fCopied := False;
fName := 'Unknown';
fDesc := 'The mysterious unknown item!';
fIntName := 'Item, Unknown';
fValue := 0.00;
fAttr := [nil, nil];
end;
destructor TItem.Destroy;
begin
if Assigned(fAttr[0]) then
FreeAndNil(fAttr[0]);
if Assigned(fAttr[1]) then
FreeAndNil(fAttr[1]);
inherited Destroy;
end;
procedure TItem.Assign(From: TItem);
begin
fCopied := True;
fName := From.Name;
fDesc := From.Description;
fIntName := From.InternalName;
fValue := From.Value;
// No idea if the following will work!
fAttr[0] := From.fAttr[0].ClassType.Create;
fAttr[1] := From.fAttr[1].ClassType.Create;
fAttr[0].Assign(From.fAttr[0]);
fAttr[1].Assign(From.fAttr[1]);
end;
function TItem.GetAttr(Index: Boolean): IAttribute;
begin
Result := fAttr[Ord(Index)];
end;
procedure TItem.SetAttr(Index: Boolean; Value: IAttribute);
begin
if (Value := nil) and Assigned(fAttr[Ord(Index)]) then
FreeAndNil(fAttr[Ord(Index)])
else
fAttr[Ord(Index)] := Value;
end;
end.
Bookmarks