File: Script.c

package info (click to toggle)
openclonk 8.1-4
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 169,520 kB
  • sloc: cpp: 180,479; ansic: 108,988; xml: 31,371; python: 1,223; php: 767; makefile: 145; sh: 101; javascript: 34
file content (143 lines) | stat: -rw-r--r-- 3,328 bytes parent folder | download | duplicates (5)
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;