/*--
	Moss
	Authors: Mimmo, Clonkonaut
--*/

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();
		CreateObject(Lichen, x, y, clonk->GetOwner());
		RemoveObject();
	}
	else
		clonk->Message("$NoSuitableGround$");

	return true;
}

/*-- Reproduction --*/

private func FxMossMoistureTimer(target, effect, time)
{
	if (GetMaterial() == Material("Water"))
	{
		
		if (wetness < MOSS_MAXWETNESS)
		{	
			wetness = MOSS_MAXWETNESS;
			if(graphic)
				SetGraphics(Format("%d",graphic));
			else
				SetGraphics();
		}
	}
	else if (!Contained() && !GBackSolid() && !GBackLiquid())
		if (wetness)
		{
			wetness--;
			// Fire nearby -> dry faster
			if (FindObject(Find_Distance(100), Find_OCF(OCF_OnFire))) wetness--;
			if (wetness <= 0)
			{
				wetness = 0;
				if (graphic)
					SetGraphics(Format("%dDry",graphic));
				else
					SetGraphics("Dry");
			}
			if ([GetX(),GetY()]==lastpos)
			{
				if (FindNearWater())
					TryToLichen();
			}
			else
				lastpos = [GetX(), GetY()];
		}		 
}

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;

	CreateObject(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() { return 100; }

local Collectible = 1;
local Name = "$Name$";
local Description = "$Description$";
local UsageHelp = "$UsageHelp$";
local Placement = 3;
local BlastIncinerate = 1;
local ContactIncinerate = 1;