openclonk/planet/Objects.ocd/Libraries.ocd/Animal.ocd/Script.c

155 lines
4.6 KiB
C

/**
Animal Library
Handles reproduction and growth for animals. If included the Construction()
call must return _inherited(...) for this library to work.
@author Maikel
*/
// This object is an animal.
public func IsAnimal() { return true; }
protected func Construction(...)
{
// Add a reproduction timer.
AddReproductionEffect();
// Add a growth effect.
StartGrowth(GrowthSpeed());
_inherited(...);
}
private func AddReproductionEffect()
{
if (!GetEffect("IntReproduction", this))
return AddEffect("IntReproduction", this, 100, 72, this);
}
private func RemoveReproductionEffect()
{
return RemoveEffect("IntReproduction", this);
}
/*-- Growth --*/
// Speed of the growth of an animal.
private func GrowthSpeed() { return 5; }
/*-- Reproduction --*/
local animal_reproduction_area_size = 800;
local animal_reproduction_rate = 67;
local animal_max_count = 10;
// Population control is handled through these variables.
// The area, in which new animals of this kind can appear.
public func ReproductionAreaSize() { return animal_reproduction_area_size; }
public func SetReproductionAreaSize(int v) { animal_reproduction_area_size = v; return true; }
// The chance that reproduction takes place in one timer interval. From 0 to 10000.
// The higher this value the more likely it is to reproduce. Special: If it is zero, reproduction is off.
public func ReproductionRate() { return animal_reproduction_rate; }
public func SetReproductionRate(int v)
{
animal_reproduction_rate = v;
if (v) AddReproductionEffect(); else RemoveReproductionEffect();
return true;
}
// The maximal animal count in the area.
public func MaxAnimalCount() { return animal_max_count; }
public func SetMaxAnimalCount(int v) { animal_max_count = v; return true; }
// Special reproduction method (e.g. with egg).
private func SpecialReproduction()
{
// You can have a special kind of reproduction implemented here.
// If you do so return true in this function.
return false;
}
// Standard conditions for reproduction.
private func ReproductionCondition()
{
return GetAlive() && GetCon() >= 100;
}
// Special conditions which needs to be fulfilled (e.g. a fish should have the swim action).
private func SpecialReproductionCondition()
{
// You can implement a special condition for reproduction here.
// Return false if this condition is not satisfied.
return true;
}
// Count animals in the reproduction area.
private func CountAnimalsInArea()
{
var reprod_size = ReproductionAreaSize();
var reprod_size_half = reprod_size / 2;
return ObjectCount(Find_ID(GetID()), Find_InRect(-reprod_size_half, -reprod_size_half, reprod_size , reprod_size), Find_OCF(OCF_Alive));
}
public func FxIntReproductionTimer(object target, proplist effect, int time)
{
// Already dead or not full grown? Don't do anything.
if (!ReproductionCondition())
return FX_OK;
// Apply the reproduction rate.
if (Random(10000) >= ReproductionRate())
return FX_OK;
// Special conditions not fulfilled? Don't do anything either.
if (!SpecialReproductionCondition())
return FX_OK;
// Check whether there are already enough animals of this kind.
if (CountAnimalsInArea() >= MaxAnimalCount())
return FX_OK;
// Reproduction: first try special reproduction, otherwise normal.
if (!SpecialReproduction())
{
// Normal reproduction.
var child = CreateConstruction(GetID(), 0, 0, NO_OWNER, 40);
child->~Birth(this);
}
return FX_OK;
}
// Callback in the animal on its birth.
public func Birth(object parent)
{
SetAction("Walk");
if (Random(2))
SetComDir(COMD_Left);
else
SetComDir(COMD_Right);
return;
}
/*-- Collection --*/
protected func RejectEntrance(object container)
{
// From one container to another is not blocked by this library.
if (Contained())
return _inherited(container, ...);
// Neither are dead animals.
if (!GetAlive())
return _inherited(container, ...);
// For all other cases the entrance is blocked.
return true;
}
/* Editor */
public func Definition(def, ...)
{
if (!def.EditorProps) def.EditorProps = {};
def.EditorProps.animal_reproduction_area_size = { Name="$ReproductionAreaSize$", EditorHelp="$ReproductionAreaSizeHelp$", Type="int", Min=0, AsyncGet="ReproductionAreaSize", Set="SetReproductionAreaSize", Save="Reproduction" };
def.EditorProps.animal_reproduction_rate = { Name="$ReproductionRate$", EditorHelp="$ReproductionRateHelp$", Type="int", Min=0, Max=10000, AsyncGet="ReproductionRate", Set="SetReproductionRate", Save="Reproduction" };
def.EditorProps.animal_max_count = { Name="$MaxCount$", EditorHelp="$MaxCountHelp$", Type="int", Min=1, AsyncGet="MaxAnimalCount", Set="SetMaxAnimalCount", Save="Reproduction" };
return _inherited(def, ...);
}