1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
/*--
Moss
Authors: Mimmo, Clonkonaut
--*/
#include Library_Flammable
static const MOSS_MAXWETNESS = 30; // Moisture the moss can achieve. Dries out within 36*MOSS_MAXWETNESS frames
static const MOSS_MAXDIST = 50; // Used for various distance checks
local wetness;
local graphic;
local lastpos;
func Initialize()
{
graphic = Random(3);
if (graphic)
SetGraphics(Format("%d",graphic));
wetness = MOSS_MAXWETNESS;
lastpos = CreateArray();
AddEffect("MossMoisture",this,100,36,this);
}
public func ControlUse(object clonk, int x, int y, bool box)
{
if(!clonk->~IsWalking()) return true;
// Search for ground
x = 0; y = 0;
if (GBackSemiSolid(x,y)) return true;
if (GetMaterial(x,y) != Material("Tunnel")) return true;
var i = 0;
while (!GBackSolid(x,y) && i < 15) { ++y; ++i; }
if (!GBackSolid(x,y)) return true;
if (GetMaterialVal("Soil", "Material", GetMaterial(x,y)) == 1)
{
// Plant!
clonk->DoKneel();
CreateObjectAbove(Lichen, x, y, clonk->GetOwner());
RemoveObject();
}
else
clonk->Message("$NoSuitableGround$");
return true;
}
/*-- Reproduction --*/
private func FxMossMoistureTimer(target, effect, time)
{
if (GetMaterial() == Material("Water"))
{
DoWetness(MOSS_MAXWETNESS);
}
else if (!Contained() && !GBackSolid() && !GBackLiquid())
if (wetness)
{
DoWetness(-1);
// Fire nearby -> dry faster
if (FindObject(Find_Distance(100), Find_OCF(OCF_OnFire))) DoWetness(-1);
if ([GetX(),GetY()]==lastpos)
{
if (FindNearWater())
TryToLichen();
}
else
lastpos = [GetX(), GetY()];
}
}
private func DoWetness(int change)
{
var was_wet = wetness > 0;
wetness = BoundBy(wetness + change, 0, MOSS_MAXWETNESS);
var is_wet = wetness > 0;
if (was_wet && !is_wet)
{
this.Name = Format("$Dry$ %s", this.Name);
if (graphic)
SetGraphics(Format("%dDry",graphic));
else
SetGraphics("Dry");
}
else if (!was_wet && is_wet)
{
this.Name = this.Prototype.Name;
if (graphic)
SetGraphics(Format("%d",graphic));
else
SetGraphics();
}
}
public func CanBeStackedWith(object other)
{
if ((this.wetness > 0) != (other.wetness > 0)) return false;
return _inherited(other, ...);
}
protected func TryToLichen()
{
if (GetMaterial() != Material("Tunnel")) return false;
var y = 0;
while (!GBackSolid(0,y) && y < 10) y++;
if (!GBackSolid(0,y)) return false;
if (!GetMaterialVal("Soil", "Material", GetMaterial(0,y))) return false;
if (FindObject(Find_ID(Lichen), Find_Distance(MOSS_MAXDIST))) return false;
CreateObjectAbove(Lichen, 0, y, NO_OWNER);
RemoveObject();
return true;
}
// Moss only grows (on itself) if close to water
private func FindNearWater()
{
// Take a random hit within the target area
var y = RandomX(-MOSS_MAXDIST, MOSS_MAXDIST);
for (var i = 0; i < MOSS_MAXDIST; i+=2)
{
if (GetMaterial(i, y) == Material("Water")) return true;
if (GetMaterial(-i,y) == Material("Water")) return true;
}
return false;
}
/*-- Status --*/
public func IsFuel() { return !wetness; }
public func GetFuelAmount(int requested_amount) { return 100; } // disregard the parameter, because only a complete chunk should be removed
local Collectible = 1;
local Name = "$Name$";
local Description = "$Description$";
local Placement = 3;
local BlastIncinerate = 1;
local ContactIncinerate = 1;
local Plane = 470;
|