You can derive descendants of CastleCreatures
and
CastleItems
classes,
to customize the behavior of creatures and items. There are a lot of methods
to override and behaviors to customize. For example,
you can make something interesting happen when you use an item
(like heal the player), or when creature creature state changes
(e.g. creatures explodes into other creatures when dying). See
examples/fps_game/fps_game.lpr
for an example that customizes what happens when using a
medkit item.
You can start your customizations from full-features classes, like
TWalkAttackCreatureResource
and
TWalkAttackCreature
.
Or you can take the basic
TCreatureResource
and
TCreature
,
and extend them to your liking.
This is a good moment to browse the classes inside
CastleCreatures
and
CastleItems
unit,
if you haven't already. Some of the important creature/item classes:
TCreatureResource
working with
TCreature
TWalkAttackCreatureResource
working with
TWalkAttackCreature
TMissileCreatureResource
working with
TMissileCreature
TStillCreatureResource
working with
TStillCreature
TItemResource
working with
TInventoryItem
TItemWeaponResource
working with
TItemWeapon
A "resource" is an information shared by all creatures/items of given type.
For example you can have two instances of TCreatureResource
: Werewolf
and Knight
. (Actually, they would probably be instances of
TWalkAttackCreatureResource
,
as TCreatureResource
is abstract.) Using them you can create and place
on your your level millions of actual werewolves and knights
(instances of TWalkAttackCreature
).
Every werewolf on the level will have potentially different life (fully healed
vs almost dead) and state (attacking, walking, dying and such), but all werewolves will share the same
resource, so e.g. all werewolves will use the same dying animation
(TWalkAttackCreatureResource.DieAnimation
) and dying sound
(TCreatureResource.SoundDie
).
A similar example for items: you can have two instances of class TItemResource
:
Sword
and LifePotion
. (Actually, TItemWeaponResource
, which is a descendant
of TItemResource
, sounds like a better candidate for the Sword
.)
Using them, you can create millions of actual swords and life potions,
and place them of your level (as well as in inventories of creatures/players).
Every life potion (TInventoryItem
instance)
may keep some individual information (for example, how much of the potion
is already used/drunk), but all life potions will share the same
TItemResource
instance, so e.g. they all will be displayed using the same model
on 3D level (TItemResource.BaseAnimation
) and the same image in 2D inventory
(TItemResource.Image
).
Everything is designed to give you a lot of properties to set (most
of them are also settable by resource.xml
files) and a
lot of methods to override. All creatures and items descend from
common classes in CastleTransform
unit,
so see also there for various things that you can override and use.
You can code new creatures/items behaviors by deriving new classes
from our existing classes in
CastleCreatures
and
CastleItems
and
CastleTransform
units.
This is the most flexible way to customize everything about a creature/item.
You usually override two classes to define a new creature/item:
The resource class (descendant of T3DResource
,
like TCreatureResource
or TItemResource
). The resource class defines
the shared information for the whole creature/item kind.
For example, you can image a
TWerewolfResource
that is derived from TWalkAttackCreatureResource
and adds the ability to make a howling sound from time to time.
TWerewolfResource
would introduce a property like HowlingSoundName
to be able to define sound for it.
Or imagine a TPotionResource
that is derived from TItemResource
and add a properties saying which player attribute (health, mana, stamina)
is regenerated and how much.
The resource class can be registered, like
uses ..., CastleResources; ... RegisterResourceClass(TWerewolfResource, 'Werewolf'); RegisterResourceClass(TPotionResource, 'Potion');
which allows this class to be referenced inside resource.xml
files
using the type attribute, like type="Werewolf"
.
Many resource.xml files may use the same type="xxx"
,
they only must have a different name="xxx"
.
Every resource.xml
file that uses type="Werewolf"
will make
a new instance of the TWerewolfResource
class to be created at the Resources.LoadFromFiles
call.
This way you can imagine creating a couple of resource.xml
files
that define a couple of resource instances:
<resource name="WerewolfRookie" type="Werewolf" default_max_life="10.0" sound_howling="werewolf_rookie_howling"> <model>...</model> </resource>
<resource name="WerewolfBoss" type="Werewolf" default_max_life="1000000.0" sound_howling="werewolf_boss_howling"> <model>...</model> </resource>
<resource name="SmallLifePotion" type="Potion" regenerate_stat="Life" regenerate_amount="10.0"> <model>...</model> </resource>
<resource name="LargeLifePotion" type="Potion" regenerate_stat="Life" regenerate_amount="50.0"> <model>...</model> </resource>
<resource name="ManaPotion" type="Potion" regenerate_stat="Mana" regenerate_amount="10.0"> <model>...</model> </resource>
As you can see in the above examples, you can use the same
resource class in many ways. Practically speaking, you only need to create
a new resource class (like TWerewolfResource
) when you really need
to introduce a new behavior that needs to be implemented using ObjectPascal.
Otherwise, if what you want can be achieved by tweaking the value
of a property of an existing class, then you don't need new resource class,
you only need to create new resource.xml
file that refers to the same
class but sets different value for given property.
After calling Resources.LoadFromFiles
, the
Resources
list will be filled
with instances of appropriate classes. You can find them by name,
e.g.
var WerewolfRookie: TWerewolfResource; ... WerewolfRookie := Resources.FindName('WerewolfRookie') as TWerewolfResource;
Defining a new property in a resource class usually means
defining a normal ObjectPascal property and overriding
T3DResource.LoadFromFile
to load the value of this property. See existing units
like CastleCreatures
and CastleItems
for a lot of examples.
The second class will be used to represent a single occurrence
of this creature/item in the 3D world. This has a reference
to the appropriate resource (for shared information)
and can have it's own properties, specific to this current instance.
For example, creatures have their current Life
.
You can imagine that a potion instance could have a property saying e.g. how much of it was drunk (if you want to allow player to drink only parts of the potions).
The resource class indicates the related non-resource class by the
TCreatureResource.CreatureClass
or
TItemResource.ItemClass
method (although it's not necessary,
but usually you want to define non-resource class together with
resource class to implement the behavior you need).
These are used by
TCreatureResource.CreateCreature
and TItemResource.CreateItem
methods,
which you can use to create creature/item occurrence by code:
type TWerewolfResource = class(TWalkAttackCreatureResource) public function CreatureClass: TCreatureClass; override; ... end; TWerewolf = class(TWalkAttackCreature) ... end; function TWerewolfResource.CreatureClass: TCreatureClass; begin Result := TWerewolf; end; ... { and if you want to create werewolves programmatically (not just by placing "placeholders" on level 3D model) then do this: } for I := 1 to 100 do WerewolfRookie.CreateCreature(Level, Vector3(1, 2, 3) { position } Vector3(1, 0, 0) { direction });
There are many possible classes to override. Overriding
the more specialized (finished) classes, like TWalkAttackCreature*
,
is nice to merely tweak some detail.
Overriding the more basic classes, like TCreature*
, is good if you're
prepared to implement something (like creature AI) completely from scratch
on your own.
Overriding the really basic classes from CastleTransform
unit (and optionally
also CastleResources
, if you want your 3D object to be associated with
a resource) is for advanced usage, when you want to define a 3D
object within your game that doesn't really fit our creatures/items
definitions. CastleTransform
contains a lot of classes to make it easy
to create your own, dynamic 3D objects.
Copyright Michalis Kamburelis and Castle Game Engine Contributors.
This webpage is also open-source and we welcome pull requests to improve it.
We use cookies for analytics. See our privacy policy.