project. Please read the
before using.
//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\//
// Algae/Plant Script by Never Rust //
//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\//
string VersionInfo = "Algae Script v0.94";
vector BirthSize = <0.3, 0.3, 0.3>;
vector MaxSize = <1, 1, 1>; // Maximum size. only will pay attention to Z
vector FertileSize = <1, 1, 0.6>; // Size that produces seeds. only will pay attention to Z
integer Age = 0; // current age (1 age = GrowthTimer seconds old)
integer OldAge = 80; // age to start dying
integer MaxAge = 100; // age to die
float GrowthTimer = 5; // # of seconds between growth checks
float SeedTimer = 12; // # of seconds to sleep after seed-shooting (make a multiple of Growthtimer)
float MaxGrowthStep = 0.05; // max size increase per growth spurt
integer SeedNumber = 1; // the number of seeds to birth at a time
integer MaxSeedNumber = 6; // the max # of seeds per lifetime
integer CurrentSeedNumber = 0; // currently how many seeds have been born
integer MyGeneration; // generation of plant
integer MaxGeneration = 7; // max # of generations to prevent
float MaxDepth = 100; // depth / MaxDepth = % of sunlight to absorb
vector MyPos;
string MyProperName = "Algae";
float NonSurvivalRange = 1; // can't survive within this range of another of it's type
//string daytolive = "2006-05-17"; //The one day that this will be alive for
//################## functions ######################//
talk (string m) {
llWhisper(0, "/me "+ m);
}
TellAboutSelf() {
talk("is generation "+ (string)MyGeneration + ", Age " + (string)Age + " ("+VersionInfo+")");
}
reset() {
llVolumeDetect(TRUE);
llSetText("", <0,0,0>, 0);
llSetAlpha(0.95, ALL_SIDES);
llSetAlpha(0.0, 0);
Age = 0;
CurrentSeedNumber = 0;
ResetAtGround();
MyPos = llGetPos();
}
CheckNearbySurvival() {
llSensor("Algae", NULL_KEY, PASSIVE | SCRIPTED, NonSurvivalRange, TWO_PI);
}
ResetAtGround() {
vector OgPos = llGetPos();
float ground = llGround(ZERO_VECTOR);
vector size = llGetScale();
float zz = ground - (OgPos.z - (size.z / 2.0));
llSetPos(<OgPos.x, OgPos.y, OgPos.z + zz>);
}
float WaterDepth() {
vector MyPos = llGetPos();
float depth = llWater(ZERO_VECTOR) - MyPos.z;
return depth;
}
float Sunlight() { // return 0 to 1: 0=no sunlight, 1=sun & no clouds
vector sun = llGetSunDirection();
float clouds = llCloud(ZERO_VECTOR);
float sunlight = 0;
if (sun.z < 0) sunlight = 0;
else sunlight = 1 - clouds;
return sunlight;
}
float SunDepthFactor() {
float depthfactor = 1 - (WaterDepth() / MaxDepth);
if (depthfactor < 0) depthfactor = 0;
//talk("depth: "+ (string)depth + " depthfactor: "+ (string)depthfactor);
return depthfactor;
}
Grow(float GrowthFraction) {
vector size = llGetScale();
float GrowthFactor = 1 + (MaxGrowthStep * GrowthFraction);
if (CanGrow(size * GrowthFactor)) {
//talk("is growing. (GrowthFactor: " + (string)GrowthFactor+ ")");
ResizeAll(GrowthFactor);
}
}
integer CanGrow(vector newsize) {
// if we haven't reached max size and we're not in old age and we're not doing to grow out of the water
if (MaxSize.z > newsize.z && Age < OldAge && (newsize.z / 2.0) < WaterDepth())
return TRUE;
else return FALSE;
}
Reproduce() {
vector size = llGetScale();
if (CanReproduce(size)) {
//talk("is reproducing (budding).");
CurrentSeedNumber += SeedNumber;
integer i;
for (i = 0; i < SeedNumber; i++) {
float distx = RandBetween(0, 3 * size.x) * RandNegative();
float disty = RandBetween(0, 3 * size.x) * RandNegative();
vector RezPos = <MyPos.x + distx, MyPos.y + disty, llGround(<distx, disty, 0>)>;
//talk("is at "+ (string)MyPos + " and birthing at: "+ (string)RezPos);
float RezDegree = llFrand(360);
rotation RezRot = llEuler2Rot( <0, 0, RezDegree * DEG_TO_RAD> );
llRezObject(llKey2Name(llGetKey()), RezPos, ZERO_VECTOR, RezRot, MyGeneration + 1);
}
llSleep(SeedTimer);
}
}
integer CanReproduce(vector size) {
// if we've reached fertile size and won't produce more than the max # of seeds, then make some seeds
if (size.z >= FertileSize.z && (CurrentSeedNumber + SeedNumber) <= MaxSeedNumber && MyGeneration < MaxGeneration)
return TRUE;
else return FALSE;
}
float RandBetween(float min, float max)
{
return llFrand(max - min) + min;
}
integer RandNegative() { // returns 1 or -1 randomly
return ( -1 + (llFloor(llFrand(2.0)) * 2) );
}
GetOlder() {
if (IsAboveWater()) { // Age quickly if above water
Age += 10;
} else Age += 1; // otherwise age normally
if (MyGeneration > 0 && Age > OldAge && llGetObjectName() != "Dying "+MyProperName) {
llSetAlpha(0.5, ALL_SIDES);
llSetAlpha(0.0, 0);
llSetObjectName("Dying "+ MyProperName);
}
if (MyGeneration > 0 && Age > MaxAge) llDie();
}
integer IsAboveWater() {
vector size = llGetScale();
if ((MyPos.z + size.z / 2) > llWater(ZERO_VECTOR)) return TRUE;
else return FALSE;
}
ResizeAll(float scale) {
llMessageLinked(LINK_SET, -1, (string)scale, NULL_KEY);
}
//************** default ******************************//
default
{
state_entry()
{
llSetAlpha(0.0, 0);
//talk("is born.");
llSetTimerEvent(GrowthTimer);
reset();
}
touch_start(integer total_number)
{
TellAboutSelf();
if (MyGeneration == 0) {
CurrentSeedNumber = 0;
talk(" is resetting seed number.");
}
//talk(" randomneg:" + (string)RandNegative());
//ProduceSeeds();
}
on_rez(integer start_param)
{
MyGeneration = start_param;
if (MyGeneration > 0) llSetScale(BirthSize);
//talk("is born. Generation "+ (string)MyGeneration + " ("+ VersionInfo + ")");
llSleep(1);
reset();
CheckNearbySurvival();
}
object_rez(key child)
{
// Give copy of child to child
llGiveInventory(child, llKey2Name(llGetKey()));
}
timer()
{
float sun = Sunlight() * SunDepthFactor();
//llSetText("Sunlight: "+ (string)sun, <1.0, 1.0, 0.0>, 0.9);
if (sun > 0) {
Grow(sun);
}
Reproduce();
GetOlder();
//if ( llGetDate() != daytolive ) llDie(); //failsafe
}
collision_start(integer num_detected) {
if (llDetectedType(0) & AGENT) {
llSay(0, llDetectedName(0) + " is disturbing the plantlife!");
Age += 10;
} else {
llSay(0, llDetectedName(0) + " collided with me! Type:" + (string)llDetectedType(0));
llEmail((string)llDetectedKey(0) + "@lsl.secondlife.com", "food", "20");
if (Age < OldAge) Age = OldAge - 1;
else Age = MaxAge;
}
}
sensor(integer num_detected)
{
if (num_detected > 0) Age = OldAge - 1;
}
link_message(integer sender_num, integer num, string str, key id)
{
if (num == -1) {
float scale = (float)str; // size factor
list primparams = [PRIM_SIZE, llGetScale() * scale]; //resize
llSetPrimitiveParams(primparams);
ResetAtGround();
}
}
}