1 /* Intro sequence */
2 
3 #appendto Sequence
4 
Intro_Init()5 func Intro_Init()
6 {
7 	this.plane = CreateObjectAbove(Airplane, 0, 800);
8 	this.plane->SetColor(0xa04000);
9 	this.plane.HitPoints = 9999999;
10 	this.plane.intro_seq = this;
11 
12 	this.pilot = npc_pyrit = CreateObjectAbove(Clonk, 100, 100, NO_OWNER);
13 	this.pilot->MakeInvincible();
14 	this.pilot->Enter(this.plane);
15 	this.pilot->SetAction("Walk");
16 
17 	this.pilot->SetName("Pyrit");
18 	this.pilot->SetColor(0xff0000);
19 	this.pilot->SetAlternativeSkin("MaleBrownHair");
20 	this.pilot->SetDir(DIR_Left);
21 	this.pilot->SetObjectLayer(this.pilot);
22 	this.pilot->AttachMesh(Hat, "skeleton_head", "main", Trans_Translate(5500, 0, 0));
23 
24 	this.dialogue = this.pilot->SetDialogue("Pyrit");
25 	this.dialogue->SetInteraction(false);
26 
27 	this.plane->PlaneMount(this.pilot);
28 	this.plane->FaceRight();
29 	this.plane.PlaneDeath = this.Intro_PlaneDeath;
30 }
31 
Intro_Start(object hero)32 func Intro_Start(object hero)
33 {
34 	this.hero = hero;
35 	this.plane->StartInstantFlight(90, 40);
36 
37 	SetViewTarget(this.pilot);
38 	SetPlayerZoomByViewRange(NO_OWNER, 200,100, PLRZOOM_Set); // zoom out from plane
39 
40 	return ScheduleNext(50);
41 }
42 
Intro_JoinPlayer(int plr)43 func Intro_JoinPlayer(int plr)
44 {
45 	if (this.intro_closed) return false; // too late for join - just join in village
46 	var crew;
47 	for(var index = 0; crew = GetCrew(plr, index); ++index)
48 	{
49 		crew->Enter(this.dialogue);
50 	}
51 	return true;
52 }
53 
Intro_1()54 func Intro_1()
55 {
56 	SetPlayerZoomByViewRange(NO_OWNER, 800,600, PLRZOOM_Set); // zoom out from plane
57 	MessageBoxAll("$MsgIntro1$", this.pilot, true); // we've reached the castle
58 	return ScheduleNext(10);
59 }
60 
Intro_2()61 func Intro_2()
62 {
63 	if (this.plane->GetX() < 400) return ScheduleSame(3);
64 	this.plane_r = 90;
65 	return ScheduleNext(1);
66 }
67 
Intro_3()68 func Intro_3()
69 {
70 	this.plane->StartInstantFlight(--this.plane_r, 40);
71 	if (this.plane_r>45) return ScheduleSame(2);
72 	return ScheduleNext(10);
73 }
74 
Intro_4()75 func Intro_4()
76 {
77 	MessageBoxAll("$MsgIntro2$", g_cannoneer, true); // alert! intruders!
78 	g_cannoneer->SetCommand("Grab", g_cannon);
79 	return ScheduleNext(5);
80 }
81 
Intro_5()82 func Intro_5()
83 {
84 	// Wait until placed diagonally above cannon
85 	var dx = this.plane->GetX() - g_cannon->GetX();
86 	var dy = this.plane->GetY() - g_cannon->GetY();
87 	var r = Angle(0,0,dx+30,dy,g_cannon.angPrec); // aim a bit ahead
88 	if (dx < dy)
89 	{
90 		r = g_cannon->ConvertAngle(r);
91 		g_cannon->SetCannonAngle(r);
92 		return ScheduleSame(3);
93 	}
94 	// Boooom!
95 	this.projectile = g_cannon->CreateContents(IronBomb);
96 	g_cannon->DoFire(this.projectile, g_cannoneer, r);
97 	return ScheduleNext(5);
98 }
99 
100 // Don't explode. Plane death handled in sequence.
Intro_PlaneDeath()101 func Intro_PlaneDeath() { return true; }
102 
Intro_6()103 func Intro_6()
104 {
105 	// Wait for hit
106 	if (this.projectile->GetX() > this.plane->GetX()) return ScheduleSame(1);
107 	// Booom!
108 	this.intro_closed = true;
109 	this.projectile->DoExplode();
110 	this.plane->SetMeshMaterial("CrashedAirplane");
111 	this.plane->CancelFlight();
112 	this.plane->RemovePlaneControl();
113 	this.plane->SetRDir(-10);
114 	// Calc fling direction to land near flagpole
115 	var tx = 135 - this.plane->GetX();
116 	var ty = 1200 - this.plane->GetY();
117 	var xdir = -50;
118 	var t = tx * 10 / xdir;
119 	var g = GetGravity();
120 	var ydir = 10*ty/t - g*t/20;
121 	this.plane->SetXDir(xdir);
122 	this.plane->SetYDir(ydir);
123 	return ScheduleNext(30);
124 }
125 
Intro_7()126 func Intro_7()
127 {
128 	MessageBoxAll("$MsgIntro3$", npc_pyrit, true); // aargh
129 	this.plane_Hit = this.plane.Hit;
130 	this.plane.Hit = this.Intro_PlaneHit;
131 	g_cannoneer->SetCommand("Ungrab");
132 	return true; // next schedule on plane hit
133 }
134 
Intro_8()135 func Intro_8()
136 {
137 	MessageBoxAll("$MsgIntro4$", GetHero(), true); // seems like we need to find another way in
138 	ScheduleNext(40);
139 }
140 
Intro_9()141 func Intro_9()
142 {
143 	npc_pyrit->SetDir(DIR_Right);
144 	return Stop();
145 }
146 
Intro_Stop()147 func Intro_Stop()
148 {
149 	//this.dialogue->SetInteraction(true); - no dialogue yet
150 	//this.dialogue->AddAttention();
151 	AI->AddAI(g_cannoneer);
152 	AI->SetHome(g_cannoneer);
153 	AI->SetGuardRange(g_cannoneer, g_cannoneer->GetX()-100, g_cannoneer->GetY()-100, 300, 110);
154 	g_cannoneer->CreateContents(Sword);
155 	AI->BindInventory(g_cannoneer);
156 	g_cannoneer->DoEnergy(10000);
157 	g_cannoneer->AddEnergyBar();
158 	g_cannoneer.SpecialDeathMessage = "$DeathOfBrutus$";
159 	SetPlayerZoomByViewRange(NO_OWNER, 400,300, PLRZOOM_Set);
160 	return true;
161 }
162 
Intro_PlaneHit()163 func Intro_PlaneHit()
164 {
165 	// Plane hit ground! Continue sequence.
166 	Sound("Objects::Plane::PlaneCrash", true);
167 	var particles = Particles_Smoke(true);
168 	particles.Size = PV_Linear(PV_Random(20, 60), PV_Random(50, 100));
169 	CreateParticle("Smoke", PV_Random(-30,30), PV_Random(-30,30), PV_Random(-60, 60), PV_Random(-20,0), PV_Random(200, 500), particles, 20);
170 	particles.Size = PV_Linear(PV_Random(50, 80), PV_Random(100, 200));
171 	CreateParticle("Smoke", PV_Random(-30,30), PV_Random(-30,30), PV_Random(-20, 20), PV_Random(-20,0), PV_Random(100, 200), particles, 20);
172 	for (var iplr=0,plr; iplr<GetPlayerCount(C4PT_User); ++iplr)
173 	{
174 		plr = GetPlayerByIndex(iplr, C4PT_User);
175 		var icrew=0,crew;
176 		while (crew=GetCrew(plr, icrew++))
177 		{
178 			crew->Exit(0,-5, 0, Random(3)-1, Random(5)-6);
179 			crew->SetAction("Tumble");
180 		}
181 	}
182 	npc_pyrit->Exit(0,-5, 0, -1, -2);
183 	npc_pyrit->SetAction("Tumble");
184 	this.Hit = this.intro_seq.plane_Hit;
185 	this.MeshTransformation=Trans_Mul(Trans_Rotate(10,0,2,1), Airplane.MeshTransformation);
186 	this.intro_seq->ScheduleNext(50);
187 	SetObjectLayer(this); // plane is broken
188 	return true;
189 }
190