openclonk/planet/Objects.ocd/Animals.ocd/Piranha.ocd/Script.c

129 lines
3.8 KiB
C

/*
Fish
Author: Zapper
*/
#include Fish
// Default additional scaling for the mesh.
local BaseScale = +200;
// Damage per bite.
local BiteStrength = 10;
local hunger;
func Construction()
{
hunger = 0;
AddTimer("MoreHunger", 80);
// Set base transform (can be overwritten by e.g. Place()).
SetYZScale(1000);
_inherited(...);
}
func MoreHunger()
{
++hunger;
if (hunger > 100) hunger = 100;
}
func InitFuzzyRules()
{
brain = FuzzyLogic->Init();
// ACTION SETS
brain->AddSet("swim", "sharp_left", [[-2 * SwimMaxAngle, 1], [-SwimMaxAngle, 0], [SwimMaxAngle, 0]]);
brain->AddSet("swim", "left", [[-SwimMaxAngle, 1], [-SwimMaxAngle/2, 0], [SwimMaxAngle, 0]]);
brain->AddSet("swim", "straight", [[-5, 0], [0, 1], [5, 0]]);
brain->AddSet("swim", "right", [[-SwimMaxAngle, 0], [SwimMaxAngle/2, 0], [SwimMaxAngle, 1]]);
brain->AddSet("swim", "sharp_right", [[-SwimMaxAngle, 0], [SwimMaxAngle, 0], [2 * SwimMaxAngle, 1]]);
brain->AddSet("speed", "slow", [[0, 1], [SwimMaxSpeed/2, 0], [SwimMaxSpeed, 0]]);
brain->AddSet("speed", "fast", [[0, 0], [SwimMaxSpeed/2, 0], [SwimMaxSpeed, 1]]);
// RULE SETS
var directional_sets = ["food"];
for (var set in directional_sets)
{
brain->AddSet(set, "left", [[-VisionMaxAngle, 1], [0, 0], [VisionMaxAngle, 0]]);
brain->AddSet(set, "straight", [[-5, 0], [0, 1], [5, 0]]);
brain->AddSet(set, "right", [[-VisionMaxAngle, 0], [0, 0], [VisionMaxAngle, 1]]);
}
var proximity_sets = ["food_range"];
var middle = VisionMaxRange / 2;
for (var set in proximity_sets)
{
brain->AddSet(set, "far", [[middle, 0], [VisionMaxRange, 1], [VisionMaxRange, 1]]);
brain->AddSet(set, "medium", [[0, 0], [middle, 1], [VisionMaxRange, 0]]);
brain->AddSet(set, "close", [[0, 1], [0, 1], [middle, 0]]);
}
brain->AddSet("left_wall", "close", [[0, 1], [0, 1], [wall_vision_range/2, 0]]);
brain->AddSet("right_wall", "close", [[0, 1], [0, 1], [wall_vision_range/2, 0]]);
brain->AddSet("wall_range", "close", [[0, 1], [0, 1], [wall_vision_range, 0]]);
brain->AddSet("hunger", "low", [[0, 1], [0, 1], [75, 0]]);
brain->AddSet("hunger", "high", [[25, 0], [100, 1], [100, 1]]);
// RULES
brain->AddRule(brain->And("hunger=high", "food=right"), "swim=right");
brain->AddRule(brain->And("hunger=high", "food=left"), "swim=left");
brain->AddRule("hunger=high", "speed=fast");
brain->AddRule(brain->Or("wall_range=close", "hunger=low"), "speed=slow");
brain->AddRule(brain->And("left_wall=close", brain->Not("right_wall=close")), "swim=sharp_right");
brain->AddRule("right_wall=close", "swim=sharp_left");
}
func UpdateVision()
{
brain->Fuzzify("hunger", hunger);
UpdateVisionFor("food", "food_range", FindObjects(Find_Distance(VisionMaxRange), Find_OCF(OCF_Alive), Find_Func("IsPrey"), Find_NoContainer(), Sort_Distance()), true);
UpdateWallVision();
}
func DoEat(object obj)
{
BiteEffect();
var len = GetAnimationLength("Bite");
PlayAnimation("Bite", 5, Anim_Linear(0, 0, len, 36, ANIM_Remove), Anim_Const(1000)); // temp overrides Swim animation in same slot
if (obj->GetAlive())
obj->DoEnergy(-BiteStrength);
hunger -= 20;
if (hunger < 0) hunger = 0;
DoEnergy(BiteStrength);
}
private func BiteEffect()
{
Sound("Animals::Fish::Munch*");
}
// Make this piranha a little larger than the mesh.
func SetYZScale(int new_scale)
{
base_transform = Trans_Scale(1000 + BaseScale, new_scale + BaseScale, new_scale + BaseScale);
return true;
}
local Name = "$Name$";
local Description = "$Description$";
local MaxEnergy = 50000;
local Placement = 1;
local NoBurnDecay = true;
local BreatheWater = 1;
local BorderBound = C4D_Border_Sides | C4D_Border_Top | C4D_Border_Bottom;
local ContactCalls = true;
func IsPrey() { return false; }
func IsPredator() { return true; }
func Definition(proplist def)
{
def.PictureTransformation = Trans_Mul(Trans_Translate(2000, 0, 0), Trans_Scale(1500), Trans_Rotate(20, 1, 0, 0), Trans_Rotate(70, 0, 1, 0));
}