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 (209 lines) | stat: -rw-r--r-- 6,236 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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/*-- 
	Resource Extraction
	Author: Maikel, Marky
	
	Player must extract the resources of the specified type, the
	tolerance of this goal is 5% currently, if no percentage of
	exploitation is specified.
	
	Additionally, the scenario designer can specify a percentage
	of material to be exploited, between 5% and 95%.
		
	TODO: Expand to liquids and digable materials.
--*/


#include Library_Goal

local resource_list; // List of materials to be mined.
local tolerance_list; // List of ignorable amounts of available objects.

protected func Initialize()
{
	resource_list = [];
	tolerance_list = [];
	return inherited(...);
}

/*-- Resources --*/

public func SetResource(string resource, int percent)
{
	var list_end = GetLength(resource_list);
	resource_list[list_end] = resource;
	
	// Assume that all objects, with 5% tolerance, have to be exploited if no percentage is specified 
	percent = BoundBy(percent ?? 95, 5, 95);

	var material = Material(resource);
	var exploitable_units = GetMaterialCount(material);
	var exploitable_objects = ExploitableObjectCount(exploitable_units, material);
	
	var target_objects = percent * exploitable_objects / 100;

	// Calculate 100 / 20 = 5% of the exploitable objects as tolerance
	tolerance_list[list_end] = Max(1, exploitable_objects - target_objects);
	return;
}

/*-- Scenario saving --*/

public func SaveResource(string resource, int tolerance_count)
{
	var list_end = GetLength(resource_list);
	resource_list[list_end] = resource;
	tolerance_list[list_end] = tolerance_count;
	return;
}

public func SaveScenarioObject(props)
{
	if (!inherited(props, ...)) return false;
	for (var i = 0; i < GetLength(resource_list); i++)
		props->AddCall("Goal", this, "SaveResource", Format("%v", resource_list[i]), tolerance_list[i]);
	return true;
}


/*-- Goal interface --*/

// The goal is fulfilled if all specified resource have been mined.
public func IsFulfilled()
{
	for (var i = 0; i < GetLength(resource_list); i++)
	{
		var material = Material(resource_list[i]);
		var exploitable_units = GetMaterialCount(material);
		var tolerance_units = ObjectCount2MaterialCount(tolerance_list[i], material);

		// Still solid material to be mined.
		if (exploitable_units == -1 || exploitable_units > tolerance_units)
			return false; 
		// Still objects of material to be collected.
		if (AvailableObjectCount(material) > 0)
			return false; 
	}
	// Goal fulfilled.
	return true;
}

// Shows or hides a message window with information.
public func GetDescription(int plr)
{
	var message;
	if (IsFulfilled())
	{
		message = "$MsgGoalFulfilled$";		
	}
	else
	{
		message = "$MsgGoalExtraction$";
		for (var i = 0; i < GetLength(resource_list); i++)
		{
			// Current data
			var material = Material(resource_list[i]);
			var exploitable_units = GetMaterialCount(material);
			var tolerance_units = ObjectCount2MaterialCount(tolerance_list[i], material);
			// Put the message together
			var icon = GetBlastID(material);
			var available_object_count = AvailableObjectCount(material);
			var exploitable_object_count = Max(0, ExploitableObjectCount(exploitable_units - tolerance_units, material));
			var add_msg = Format("$MsgGoalResource$", icon, exploitable_object_count, available_object_count);
			message = Format("%s%s", message, add_msg);
		}
	}
	return message;
}

// Shows or hides a message window with information.
public func Activate(int plr)
{
	// If goal message open -> hide it.
	if (GetEffect("GoalMessage", this))
	{
		CustomMessage("", nil, plr, nil, nil, nil, nil, nil, MSG_HCenter);
		RemoveEffect("GoalMessage", this);
		return;
	}
	// Otherwise open a new message.
	AddEffect("GoalMessage", this, 100, 0, this);
	var message;
	if (IsFulfilled())
	{
		message = "@$MsgGoalFulfilled$";		
	}
	else
	{
		message = "@$MsgGoalExtraction$";
		for (var i = 0; i < GetLength(resource_list); i++)
		{
			// Current data
			var material = Material(resource_list[i]);
			var exploitable_units = GetMaterialCount(material) * 10 / 11; // subtract some that gets lost on blasting
			var tolerance_units = ObjectCount2MaterialCount(tolerance_list[i], material);
			// Put the message together
			var icon = GetBlastID(material);
			var available_object_count = AvailableObjectCount(material);
			var exploitable_object_count = Max(0, ExploitableObjectCount(exploitable_units - tolerance_units));
			var add_msg = Format("$MsgGoalResource$", icon, exploitable_object_count, available_object_count);
			message = Format("%s%s", message, add_msg);
		}
	}
	CustomMessage(message, nil, plr, 0, 16 + 64, 0xffffff, GUI_MenuDeco, this, MSG_HCenter);
	return;
}

protected func FxGoalMessageStart() {}

public func GetShortDescription(int plr)
{
	// Show resource image with total resource count.
	var msg = "";
	for (var i = 0; i < GetLength(resource_list); i++)
	{
		// Current data
		var material = Material(resource_list[i]);
		var exploitable_units = GetMaterialCount(material);
		var tolerance_units = ObjectCount2MaterialCount(tolerance_list[i], material);
		// Put the message together
		var icon = GetBlastID(material);
		var available_object_count = AvailableObjectCount(material);
		var exploitable_object_count = Max(0, ExploitableObjectCount(exploitable_units - tolerance_units, material));
		msg = Format("%s{{%i}}: %d ", msg, icon, exploitable_object_count + available_object_count);
	}	
	return msg;
}

func GetBlastRatio(int material)
{
	return GetMaterialVal("Blast2ObjectRatio", "Material", material);
}

func GetBlastID(int material)
{
	return GetMaterialVal("Blast2Object", "Material", material);
}

/** Get number of objects that are lying around freely. */
func AvailableObjectCount(int material)
{
	return ObjectCount(Find_ID(GetBlastID(material)));
}

/** Gets the number of objects that can be exploited from a material, based on material count. */
func ExploitableObjectCount(int material_count, int material)
{
	return material_count / GetBlastRatio(material);
}

/** Converts a number of objects to the amount of material
    that would have to be exploited in order to receive that
    amount of objects. */
func ObjectCount2MaterialCount(int count, int material)
{
	return (2 * count + 1) * GetBlastRatio(material) / 2;
}

/*-- Proplist --*/

local Name = "$Name$";