1 /* Boomshire */
2 
Initialize()3 private func Initialize()
4 {
5 	// Create dynamite below the first lava basin
6 	DrawMaterialQuad("Tunnel",1378,1327-5,1860,1327-5,1860,1330,1387,1330,1);
7 
8 	//Sound("Environment::BirdsLoop",true,100,nil,+1);
9 	Cloud->Place(40);
10 	PlaceObjects(Rock,50,"Earth");
11 	PlaceObjects(Loam,25,"Earth");
12 	PlaceObjects(Nugget,25,"Earth");
13 
14 	AddEffect("PlaneReset",CreateObjectAbove(Airplane,3030,315,0),100,10,nil,nil);
15 	AddEffect("PlaneReset",CreateObjectAbove(Airplane,3160,315,1),100,10,nil,nil);
16 
17 	Doors();
18 
19 	var concierge = CreateObjectAbove(Clonk, 70, 1030, NO_OWNER);
20 	concierge->SetDir(DIR_Left);
21 	concierge->SetAlternativeSkin("Mime");
22 	concierge->SetObjectLayer(concierge);
23 	concierge->SetName("$NameConcierge$");
24 	concierge->SetDialogue("Concierge");
25 	concierge->Sound("Circus", false, nil, nil, +1, 100);
26 	Dialogue->FindByTarget(concierge)->AddAttention();
27 
28 	var cannons = FindObjects(Find_ID(Cannon));
29 	for (var cannon in cannons)
30 	{
31 		cannon->TurnCannon(0);
32 		cannon->SetCannonAngle(45000);
33 		cannon.Touchable = false;
34 	}
35 
36 	// Various tunnels for dynamite to fall through
37 	DrawMaterialQuad("Tunnel-brickback",339,687,350,687,350,761,339,761);
38 	DrawMaterialQuad("Tunnel-brickback",1889,866,1955,866,1955,882,1889,882);
39 	DrawMaterialQuad("Tunnel-brickback",1920,874,1955,874,1930,1000,1920,1000);
40 	DrawMaterialQuad("Tunnel-brickback",1920,1000,1930,1000,1970,1100,1960,1100);
41 	DrawMaterialQuad("Tunnel-brickback",1960,1100,1970,1100,1930,1201,1919,1201);
42 
43 	DrawMaterialQuad("Tunnel-brickback",2549,907,2590,907,2590,920,2549,920);
44 	DrawMaterialQuad("Tunnel-brickback",2549,920,2560,920,2560,1000,2550,1000);
45 	DrawMaterialQuad("Tunnel-brickback",2550,1000,2560,1000,2720,1160,2710,1160);
46 	DrawMaterialQuad("Tunnel-brickback",2710,1160,2720,1160,2710,1190,2700,1190);
47 	DrawMaterialQuad("Tunnel-brickback",2680,1185,2750,1185,2750,1195,2680,1195);
48 	DrawMaterialQuad("Tunnel-brickback",2737,1195,2750,1190,2775,1255,2765,1255);
49 
50 	AddEffect("DynamiteEruption",nil,100,130);
51 }
52 
InitializePlayer(int plr)53 private func InitializePlayer(int plr)
54 {
55 	SetPlayerTeam(plr, 1);
56 }
57 
58 // Gamecall from Race-goal, on respawning.
OnPlayerRespawn(int iPlr,object cp)59 public func OnPlayerRespawn(int iPlr, object cp)
60 {
61 	var clonk = GetCrew(iPlr);
62 	clonk->CreateContents(WindBag);
63 }
64 
FxDynamiteEruptionTimer(object nobject,effect,int timer)65 global func FxDynamiteEruptionTimer(object nobject, effect, int timer)
66 {
67 	if(Random(5))
68 	{
69 		var dyn=CreateObjectAbove(Firestone,2460+Random(20),670);
70 		dyn->SetYDir(-80);
71 		dyn->SetXDir(RandomX(-1,1));
72 		dyn->SetRDir(RandomX(-30,30));
73 	}
74 	else
75 	{
76 		var dyn=CreateObjectAbove(Dynamite,2460+Random(20),670);
77 		dyn->SetYDir(-80);
78 		dyn->SetXDir(RandomX(-1,1));
79 		dyn->SetRDir(RandomX(-30,30));
80 		dyn->Fuse();
81 	}
82 }
83 
FxAutoOpenTimer(object pTarget,effect,int timer)84 global func FxAutoOpenTimer(object pTarget, effect, int timer)
85 {
86 	if (!effect.fired)
87 	{
88 		if (FindObject(Find_ID(Airplane),Find_InRect(2710,310,130,40)))
89 		{
90 			effect.fired = true;
91 			var cannons = FindObjects(Find_ID(Cannon));
92 			for (var cannon in cannons)
93 			{
94 				cannon->CreateContents(Boompack);
95 				cannon->DoFire(cannon->Contents(), nil, -45000);
96 			}
97 		}
98 	}
99 	if(FindObject(Find_ID(Airplane),Find_InRect(0,0,2000,500)))
100 	{
101 		pTarget->OpenDoor();
102 		return FX_Execute_Kill;
103 	}
104 	else return FX_OK;
105 }
106 
FxSparklingAttentionStart(object target,effect fx,temp)107 global func FxSparklingAttentionStart(object target, effect fx, temp)
108 {
109 	if (temp) return;
110 	fx.particles =
111 	{
112 		Size = PV_Linear(2, 0),
113 		Alpha = PV_KeyFrames(0, 0, 0, 300, 255, 1000, 0),
114 		Rotation = PV_Random(0, 360),
115 		R = 255, G = 200, B = 50,
116 		Stretch = PV_Random(10000, 15000),
117 		BlitMode = GFX_BLIT_Additive
118 	};
119 }
120 
FxSparklingAttentionTimer(object target,effect fx,int timer)121 global func FxSparklingAttentionTimer(object target, effect fx, int timer)
122 {
123 	// Sparkle quickly every now-and-then.
124 	var sparkle_cycle = timer % 100;
125 	if (sparkle_cycle < 30)
126 	{
127 		fx.Interval = 1;
128 		if (Random(2)) return FX_OK;
129 	}
130 	else
131 	{
132 		fx.Interval = 100;
133 		return FX_OK;
134 	}
135 	var x = RandomX(-10, 10);
136 	var y = RandomX(-10, 10);
137 	target->CreateParticle("StarSpark", x, y, 0, 0, PV_Random(1, 7), fx.particles, 10);
138 	return FX_OK;
139 }
140 
FxPlaneResetTimer(object target,effect,int time)141 global func FxPlaneResetTimer(object target, effect, int time)
142 {
143 	if(target->GetX() > 3000 || target->Contents())
144 	{
145 		effect.count=0;
146 		return FX_OK;
147 	}
148 	else
149 		effect.count++;
150 
151 	if(effect.count<4) return FX_OK;
152 
153 	var particles =
154 	{
155 		Prototype = Particles_Air(),
156 		Size = PV_Linear(4, 0)
157 	};
158 	DrawParticleLine("Air", target->GetX()+3, target->GetY(), 3030, 315, 1, PV_Random(-2, 2), PV_Random(-2, 2), PV_Random(10, 30), particles);
159 
160 	target->SetPosition(3030,315);
161 	target->SetDir(0);
162 	target->SetR(-90);
163 	target->~RollPlane();
164 }
165 
Doors()166 private func Doors()
167 {
168 	var door=CreateObjectAbove(StoneDoor, 135, 60, NO_OWNER);
169 	door->CloseDoor();
170 	AddEffect("AutoOpen",door,1,15);
171 
172 	var gate = CreateObjectAbove(StoneDoor, 865, 1195, NO_OWNER);
173 	var wheel = CreateObjectAbove(SpinWheel, 1045, 1165, NO_OWNER);
174 	wheel->SetSwitchTarget(gate);
175 	gate->CloseDoor();
176 	AddEffect("SparklingAttention",wheel,100,100);
177 
178 	var gate = CreateObjectAbove(StoneDoor, 1155, 1026, NO_OWNER);
179 	var wheel = CreateObjectAbove(SpinWheel, 1906, 778, NO_OWNER);
180 	wheel->SetArrowWheel();
181 	var straw = CreateObjectAbove(DoorTarget,1850,820,NO_OWNER);
182 	straw->SetGate(gate);
183 	straw->SetAction("Float");
184 	gate->CloseDoor();
185 	AddEffect("SparklingAttention",wheel,100,100);
186 
187 	var gate = CreateObjectAbove(StoneDoor, 1875, 761, NO_OWNER);
188 	var wheel = CreateObjectAbove(SpinWheel, 1752, 1148, NO_OWNER);
189 	wheel->SetSwitchTarget(gate);
190 	gate->CloseDoor();
191 	AddEffect("SparklingAttention",wheel,100,100);
192 
193 	var gate = CreateObjectAbove(StoneDoor, 1875, 864, NO_OWNER);
194 	var wheel = CreateObjectAbove(SpinWheel, 1116, 1038, NO_OWNER);
195 	wheel->SetSwitchTarget(gate);
196 	gate->CloseDoor();
197 	AddEffect("SparklingAttention",wheel,100,100);
198 
199 	var gate = CreateObjectAbove(StoneDoor, 3115, 685, NO_OWNER);
200 	var wheel = CreateObjectAbove(SpinWheel, 3140, 588, NO_OWNER);
201 	wheel->SetSwitchTarget(gate);
202 	gate->CloseDoor();
203 	AddEffect("SparklingAttention",wheel,100,100);
204 
205 	var gate = CreateObjectAbove(StoneDoor, 585, 915, NO_OWNER);
206 	var wheel = CreateObjectAbove(SpinWheel, 853, 681, NO_OWNER);
207 	wheel->SetSwitchTarget(gate);
208 	gate->CloseDoor();
209 	AddEffect("SparklingAttention",wheel,100,100);
210 
211 	var gate = CreateObjectAbove(StoneDoor, 345, 740, NO_OWNER);
212 	var wheel = CreateObjectAbove(SpinWheel, 60, 644, NO_OWNER);
213 	wheel->SetSwitchTarget(gate);
214 	gate->CloseDoor();
215 	AddEffect("SparklingAttention",wheel,100,100);
216 
217 	var gate = CreateObjectAbove(StoneDoor, 1935, 558, NO_OWNER);
218 	var wheel = CreateObjectAbove(SpinWheel, 1900, 565, NO_OWNER);
219 	wheel->SetSwitchTarget(gate);
220 	gate->CloseDoor();
221 	AddEffect("SparklingAttention",wheel,100,100);
222 
223 	var gate = CreateObjectAbove(StoneDoor, 2965, 316, NO_OWNER);
224 	var wheel = CreateObjectAbove(SpinWheel, 3260, 328, NO_OWNER);
225 	wheel->SetSwitchTarget(gate);
226 	gate->CloseDoor();
227 
228 	var gate = CreateObjectAbove(StoneDoor, 3285, 1150, NO_OWNER);
229 	var wheel = CreateObjectAbove(SpinWheel, 3220, 1200, NO_OWNER);
230 	wheel->SetSwitchTarget(gate);
231 	gate->CloseDoor();
232 }
233 
234 static g_num_chests;
235 static const MAX_CHESTS = 14;
236 
OnChestOpened(object collector)237 public func OnChestOpened(object collector)
238 {
239 	++g_num_chests;
240 	var sAchievement = "";
241 	if (g_num_chests == 4)
242 	{
243 		sAchievement = "|$Achieve4$";
244 		GainScenarioAchievement("Chests", 1);
245 	}
246 	else if (g_num_chests==MAX_CHESTS/2)
247 	{
248 		sAchievement = "|$Achieve7$";
249 		GainScenarioAchievement("Chests", 2);
250 	}
251 	else if (g_num_chests==MAX_CHESTS)
252 	{
253 		sAchievement = "|$Achieve14$";
254 		GainScenarioAchievement("Chests", 3);
255 	}
256 	UpdateLeagueScores();
257 	Dialogue->MessageBoxAll(Format("$MsgChestOpened$%s", g_num_chests, MAX_CHESTS, sAchievement), collector, true);
258 	return true;
259 }
260 
OnGoalsFulfilled()261 public func OnGoalsFulfilled()
262 {
263 	GainScenarioAchievement("Done");
264 	UpdateLeagueScores();
265 }
266 
OnGameOver()267 public func OnGameOver()
268 {
269 	UpdateLeagueScores();
270 }
271 
UpdateLeagueScores()272 private func UpdateLeagueScores()
273 {
274 	// +50 for finishing and +5 for every chest
275 	var goal_finished = (g_goal && g_goal->IsFulfilled());
276 	return SetLeagueProgressScore(g_num_chests, g_num_chests * 5 + goal_finished * 50);
277 }
278