File: Script.c

package info (click to toggle)
openclonk 8.1-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 169,500 kB
  • sloc: cpp: 180,478; ansic: 108,988; xml: 31,371; python: 1,223; php: 767; makefile: 139; sh: 101; javascript: 34
file content (288 lines) | stat: -rw-r--r-- 6,325 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
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
/**
	Dynamite box
	Contains five dynamite sticks which can be placed and detonated from a distance.
	
	@author: Newton
*/

#include Library_HasExtraSlot

static const DYNA_MaxLength = 500;
static const DYNA_MaxCount  = 5;

/*-- Initialization --*/

public func Initialize(...)
{
	CreateContents(Dynamite, DYNA_MaxCount);
	// Hide it TODO: Remove if the mesh isn't shown if there is a picture set
	this.PictureTransformation = Trans_Scale();
	UpdatePicture();
	return _inherited(...);
}

public func Hit()
{
	Sound("Hits::Materials::Wood::DullWoodHit?");
}


/*-- Dynamite stick contents --*/

public func RejectCollect(id def, object obj, ...)
{
	if (obj->GetID() != Dynamite)
		return true;
	// Max five dynamite sticks. However, longer sets of sticks can be constructed by putting more of them in while some are out on the wire
	if (GetDynamiteCount() >= DYNA_MaxCount)
		return true;

	return _inherited(def, obj, ...);
}

public func Ejection(...)
{
	if (GetDynamiteCount() == 0)
	{
		ChangeToIgniter();
	}
	else
	{
		UpdatePicture();
	}
	return _inherited(...);
}

public func ContentsDestruction(...)
{
	Ejection();
	return _inherited(...);
}

public func Collection2(...)
{
	if (GetID() == Igniter)
	{
		ChangeToBox();
	}
	UpdatePicture();
	return _inherited(...);
}

public func GetDynamiteCount()
{
	// Get number of contained dynamite sticks
	return ContentsCount(Dynamite);
}

public func SetDynamiteCount(int new_count)
{
	// Adjust dynamite counts to given amount
	var dyna;
	var change = new_count - GetDynamiteCount();
	if (change > 0) while (change--) CreateContents(Dynamite);
	if (change < 0) while (change++) if ((dyna = FindObject(Find_ID(Dynamite), Find_Container(this)))) dyna->RemoveObject();
}

// Empty this box and turn it into an igniter
public func ChangeToIgniter()
{
	if (GetID() == Igniter) return;
	UpdatePicture();
	ChangeDef(Igniter);
	SetGraphics("Picture", Igniter, 1, GFXOV_MODE_Picture);
	// Update carrier
	var container = Contained();
	if (container)
	{
		var pos = container->~GetItemPos(this);
		container->~UpdateAttach();
		container->~OnSlotFull(pos);
	}
	return true;
}

// Change back into a box
public func ChangeToBox()
{
	if (GetID() == DynamiteBox) return;
	ChangeDef(DynamiteBox);
	UpdatePicture();
	// Update carrier
	if (Contained())
	{
		var pos = Contained()->~GetItemPos(this);
		Contained()->~UpdateAttach();
		Contained()->~OnSlotFull(pos);
	}
	
	return true;
}

// Do not stack empty dynamite boxes with full ones.
public func CanBeStackedWith(object other, ...)
{
	if (GetID() != other->GetID()) return false;
	if (this->GetDynamiteCount() != other->GetDynamiteCount()) return false;
	return inherited(other, ...);
}

// Drop connected or fusing boxes
public func IsDroppedOnDeath(object clonk)
{
	return GetEffect("Fuse", this) || GetLength(FindFuses());
}


/*-- Ignition --*/

public func ActivateFuse()
{
	// Activate all fuses.
	for (var obj in FindFuses())
		obj->~StartFusing(this);
}

public func DoExplode()
{
	// Activate all fuses.
	ActivateFuse();
	// Explode, calc the radius out of the area of a explosion of a single dynamite times the amount of dynamite
	// This results to 18, 25, 31, 36, and 40
	Explode(Sqrt(18**2*GetDynamiteCount()));
}

public func FxFuseTimer(object target, effect, int timer)
{
	CreateParticle("Fire", 0, 0, PV_Random(-10, 10), PV_Random(-20, 10), PV_Random(10, 40), Particles_Glimmer(), 6);
	if (timer > 90)
		DoExplode();
	return FX_OK;
}

public func Incineration(int caused_by)
{
	ActivateFuse();
	if (!GetEffect("Fuse", this)) AddEffect("Fuse", this, 100, 1, this);
	Sound("Fire::Fuse");
	SetController(caused_by);
}

public func Damage(int change, int type, int by_player)
{
	Incinerate(nil, by_player);
}

private func OnFuseFinished(object fuse)
{
	SetController(fuse->GetController());
	DoExplode();
}

public func OnCannonShot(object cannon)
{
	Incinerate(nil, cannon->GetController());
}

public func IsExplosive() { return true; }

/*-- Usage --*/

public func ControlUse(object clonk, int x, int y)
{
	var dynamite = Contents();

	if (!dynamite || dynamite->GetID() != Dynamite)
		return false;

	if (!dynamite->ControlPlace(clonk, x, y, 1))
		return true;

	// Connect with a fuse: Move last wire to dynamite
	var wire = FindFuses()[0];
	if(wire)
		wire->Connect(wire->GetConnectedItem(this), dynamite);
	// Create new wire from box to dynamite
	Fuse->Create(dynamite, this);
	Sound("Objects::Connect");

	return true;
}

private func FindFuses()
{
	// return all fuses connected to this item
	return FindObjects(Find_Category(C4D_StaticBack), Find_Func("IsFuse"), Find_ActionTargets(this));
}


/*-- Production --*/

public func IsTool() { return true; }
public func IsChemicalProduct() { return true; }

/*-- Display --*/

public func GetCarryMode(object clonk, bool idle)
{
	if (idle) return CARRY_Back;
	if (clonk->~IsWalking() || clonk->~IsJumping()) return CARRY_BothHands;
	return CARRY_Back;
}

public func GetCarryTransform(object clonk, bool idle, bool nohand, bool second_on_back)
{
	if (idle)
	{
		if (!second_on_back)
			return Trans_Mul(Trans_Translate(0,3000, 00), Trans_Rotate(-45,0,1));
		else
			return Trans_Mul(Trans_Translate(-5000,3000), Trans_Rotate(-45,0,1));
	}
	if (nohand)
		return Trans_Mul(Trans_Translate(0,-3000, -2200), Trans_Rotate(-45,0,1));
}

public func GetCarryPhase()
{
	return 450;
}

func UpdatePicture()
{
	SetGraphics(Format("%d", 6 - GetDynamiteCount()), DynamiteBox, 1, GFXOV_MODE_Picture);
	// Update inventory if contained in a crew member.
	if (Contained())
		Contained()->~OnInventoryChange();
}

// Saving: Save custom dynamite stick count
public func SaveScenarioObject(proplist props)
{
	if (!_inherited(props, ...)) return false;
	var dyna_count = this->GetDynamiteCount();
	if (dyna_count != DYNA_MaxCount)
	{
		props->AddCall("Dynamite", this, "SetDynamiteCount", dyna_count);
	}
	return true;
}


func Definition(def)
{
	SetProperty("PictureTransformation", Trans_Mul(Trans_Rotate(150, 1, 0, 0), Trans_Rotate(140, 0, 1, 0)), def);
}

/*-- Properties --*/

public func IsDynamiteBox() { return true; }

local Name = "$Name$";
local Description = "$Description$";
local Collectible = true;
local BlastIncinerate = 1;
local ContactIncinerate = 2;
local NoBurnDecay = true;
local Components = {Wood = 1, Coal = 2, Firestone = 2};
local MaxContentsCount = 5;