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 (156 lines) | stat: -rw-r--r-- 4,334 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
144
145
146
147
148
149
150
151
152
153
154
155
156
/**
	Earthquake
	Trembles the earth.
	
	@author Maikel	
*/


/*-- Disaster Control --*/

public func SetChance(int chance)
{
	if (this != Earthquake)
		return;
	var effect = GetEffect("IntEarthquakeControl");
	if (!effect)
		effect = AddEffect("IntEarthquakeControl", nil, 100, 20, nil, Earthquake);
	effect.chance = chance;
	return;
}

public func GetChance()
{
	if (this != Earthquake)
		return;
	var effect = GetEffect("IntEarthquakeControl");
	if (effect)
		return effect.chance;
	return;
}

protected func FxIntEarthquakeControlTimer(object target, proplist effect, int time)
{
	if (Random(100) < effect.chance && !Random(10))
		LaunchEarthquake(Random(LandscapeWidth()), Random(LandscapeHeight()), Random(40) + 35);
	return FX_OK;
}

// Scenario saving
func FxIntEarthquakeControlSaveScen(obj, fx, props)
{
	props->Add("Earthquake", "Earthquake->SetChance(%d)", fx.chance);
	return true;
}

// Launches an earthquake with epicenter (x,y) in global coordinates.
global func LaunchEarthquake(int x, int y, int strength)
{
	// Earthquake should start in solid.
	if (!GBackSemiSolid(x - GetX(), y - GetY()))
		return false;
	// Minimum strength is 15, maximum strength is 100.
	strength = BoundBy(strength, 15, 100);
	// The earthquake is handled by a global effect.
	var effect = AddEffect("IntEarthquake", nil, 100, 1, nil, Earthquake);
	effect.x = x; // Epicentre x coordinate.
	effect.y = y; // Epicentre y coordinate.
	effect.strength = strength / 3; // Earthquake strength.
	effect.length = 3 * strength / 2; // Earthquake length.
	return true;
}

/*-- Earthquake --*/

protected func FxIntEarthquakeStart(object target, effect)
{
	// Start sound at quake local coordinates.
	// < Maikel> Global until someone implements non-object local sounds
	Sound("Environment::Disasters::Earthquake", true, 100, nil, 1);
	return FX_OK;
}

protected func FxIntEarthquakeStop(object target, effect)
{
	// Stop sound.
	Sound("Environment::Disasters::Earthquake", true, 100, nil, -1);
	Sound("Environment::Disasters::EarthquakeEnd",true);
	return FX_OK;
}

protected func FxIntEarthquakeTimer(object target, effect, int time)
{
	// Time is up?
	if (time > effect.length)
		return FX_Execute_Kill;
	// Some randomness.
	if (Random(3))
		return FX_OK;
	// Get strength.
	var str = effect.strength;
	// Get quake coordinates.
	var x = effect.x;
	var y = effect.y;
	var l = 4 * str;
	// Shake viewport.
	if (!Random(10))
		ShakeViewport(str, x, y);
	// Shake ground & objects.
	ShakeFree(x, y, Random(str / 2) + str / 5 + 5);
	for (var obj in FindObjects(Find_NoContainer(), Find_OCF(OCF_Alive), Find_InRect(x - l, y - l, l, l)))
	{
		if (Random(3)) continue;
		if (!obj->GetAction()) continue;
		var act = obj.ActMap[obj->GetAction()];
		if (act.Attach || (act.Procedure
		    && act.Procedure != DFA_FLIGHT
		    && act.Procedure != DFA_LIFT
		    && act.Procedure != DFA_FLOAT
		    && act.Procedure != DFA_ATTACH
		    && act.Procedure != DFA_CONNECT))
			//if (!MatVehicle(obj->Shape.AttachMat))
			obj->Fling(Random(3)-1);
	}
	// Move the quake around a little.
	var dx, dy, cnt = 0;
	do
	{	// Try ten times to find a nearby in material location.
		dx = Random(str * 4 + 1) - str * 2;
		dy = Random(str * 4 + 1) - str * 2;
		cnt++;
	} while (!GBackSemiSolid(x + dx, y + dy) && cnt < 10);
	// No continuation.
	if (cnt >= 10)
		return FX_Execute_Kill;
	// Set new position.
	effect.x += dx;
	effect.y += dy;
	// Done.
	return FX_OK;
}

/*-- Proplist --*/

local Name = "$Name$";


/* Editor */

public func Definition(def, ...)
{
	UserAction->AddEvaluator("Action", "Disasters", "$LaunchEarthquake$", "$LaunchEarthquakeHelp$", "launch_earthquake", [def, def.EvalAct_LaunchEarthquake], { Strength={Function="int_constant", Value=50} }, { Type="proplist", Display="{{Position}}, {{Strength}}", EditorProps = {
		Position = new UserAction.Evaluator.Position { EditorHelp="$PositionHelp$" },
		Strength = new UserAction.Evaluator.Integer { Name="$Strength$", EditorHelp="$StrengthHelp$" },
		} } );
}

private func EvalAct_LaunchEarthquake(proplist props, proplist context)
{
	// Earthquake through user action
	var position = UserAction->EvaluatePosition(props.Position, context);
	var strength = UserAction->EvaluateValue("Integer", props.Strength, context);
	if (strength > 0)
	{
		LaunchEarthquake(position[0], position[1], strength);
	}
}