Crash landing intro/dialogues/outro improved for storyline integration.

issue1247
Sven Eberhardt 2014-08-26 16:06:53 +02:00
parent faa9667b66
commit addac19062
12 changed files with 357 additions and 73 deletions

View File

@ -8,6 +8,9 @@
#include Library_Goal #include Library_Goal
local is_fulfilled = false;
local is_outro_stated = false;
protected func Initialize() protected func Initialize()
{ {
return inherited(...); return inherited(...);
@ -15,6 +18,9 @@ protected func Initialize()
public func IsFulfilled() public func IsFulfilled()
{ {
// already done?
if (is_fulfilled || is_outro_stated) return is_fulfilled;
// not done yet. do fulfillment check
var cabin = FindObject(Find_ID(WoodenCabin)); var cabin = FindObject(Find_ID(WoodenCabin));
if (!cabin) if (!cabin)
return false; return false;
@ -22,9 +28,14 @@ public func IsFulfilled()
if (!plane) if (!plane)
return false; return false;
// Plane has to be brought to the wooden cabin. // Plane has to be brought to the wooden cabin.
if (ObjectDistance(plane, cabin) < 80) if (ObjectDistance(plane, cabin) < 200)
return true; {
return false; is_outro_stated = true;
StartSequence("Outro", 0, this, plane);
// wait for end of outro for fulfillment
return false;
}
return false;
} }
public func GetDescription(int plr) public func GetDescription(int plr)
@ -51,5 +62,11 @@ public func GetShortDescription(int plr)
return "{{Plane}}"; // TODO return "{{Plane}}"; // TODO
} }
public func SetFulfilled()
{
is_fulfilled = true;
return true;
}
/*-- Proplist --*/ /*-- Proplist --*/
local Name = "$Name$"; local Name = "$Name$";

View File

@ -35,6 +35,11 @@ MapWidth=200,0,64,10000
MapHeight=175,0,40,10000 MapHeight=175,0,40,10000
NewStyleLandscape=2 NewStyleLandscape=2
NoScan=1 NoScan=1
AutoScanSideOpen=0
LeftOpen=450
RightOpen=0
TopOpen=1
BottomOpen=0
[Weather] [Weather]
Climate=0,10,0,100 Climate=0,10,0,100

View File

@ -5,7 +5,7 @@
@authors Sven2, Maikel, ck @authors Sven2, Maikel, ck
*/ */
static g_is_initialized; static g_is_initialized, g_has_bought_plans, npc_pyrit;
func DoInit(int first_player) func DoInit(int first_player)
{ {
@ -68,6 +68,9 @@ func InitializePlayer(int plr)
crew->SetPosition(x , y); crew->SetPosition(x , y);
} }
} }
// Extra plans from merchant to newly joined players
if (g_has_bought_plans) GiveExtraPlans(plr);
// Give clonks initial tools // Give clonks initial tools
for(var index = 0; crew = GetCrew(plr, index); ++index) for(var index = 0; crew = GetCrew(plr, index); ++index)
@ -83,3 +86,18 @@ func InitializePlayer(int plr)
return true; return true;
} }
func OnGameOver()
{
GainMissionAccess("S2Crash");
return true;
}
func GiveExtraPlans(int plr)
{
SetPlrKnowledge(plr, Pump);
SetPlrKnowledge(plr, Pipe);
SetPlrKnowledge(plr, Catapult);
SetPlrKnowledge(plr, Cannon);
return true;
}

View File

@ -2,49 +2,119 @@
#appendto Dialogue #appendto Dialogue
static g_has_bought_plans;
private func Dlg_Merchant_1(object clonk) func Dlg_Merchant_1(object clonk)
{ {
MessageBox("$MsgSellPlans$", clonk); MessageBox("$Merchant1$", clonk);
return; return true;
} }
private func Dlg_Merchant_2(object clonk) func Dlg_Merchant_2(object clonk)
{ {
var options = [["$MerchantQPlane$", "Dlg_Merchant_Plane"]];
var i = GetLength(options);
if (g_has_bought_plans)
{
options[i++] = ["$MerchantQPump$", "Dlg_Merchant_Pump"];
options[i++] = ["$MerchantQCatapult$", "Dlg_Merchant_Catapult"];
}
else
{
options[i++] = ["$MerchantQLake$", "Dlg_Merchant_Lake"];
}
options[i++] = ["$MerchantQDone$", "StopDialogue()"];
MessageBox("", clonk, clonk, false, nil, options);
SetDialogueProgress(1);
return true;
}
func Dlg_Merchant_Lake(object clonk)
{
if (g_has_bought_plans) return StopDialogue(); // in case multiple players initiate the dialogue at the same time
MessageBox("$MerchantSellPlans$", clonk);
SetDialogueProgress(10);
return true;
}
func Dlg_Merchant_10(object clonk)
{
if (g_has_bought_plans) return StopDialogue(); // in case multiple players initiate the dialogue at the same time
var plr = clonk->GetOwner(); var plr = clonk->GetOwner();
var wealth = GetWealth(plr); var wealth = GetWealth(plr);
if (wealth >= 150) if (wealth >= 150)
{ {
MessageBox("$AnsBuyPlans$", clonk, clonk); MessageBox("$MerchantBuyPlans$", clonk, clonk);
} }
else else
{ {
MessageBox("$AnsNoMoney$", clonk, clonk); MessageBox("$MerchantNoMoney$", clonk, clonk);
SetDialogueProgress(0); SetDialogueProgress(2);
SetDialogueStatus(DLG_Status_Stop);
} }
return; return true;
} }
private func Dlg_Merchant_3(object clonk) func Dlg_Merchant_11(object clonk)
{ {
MessageBox("$MsgGivePlans$", clonk); // prevent race conditions
DoWealth(clonk->GetOwner(), -150); if (g_has_bought_plans) return StopDialogue();
for (var i = 0; i < GetPlayerCount(); i++) var plr = clonk->GetOwner();
var wealth = GetWealth(plr);
if (wealth < 150)
{ {
var plr = GetPlayerByIndex(i); MessageBox("$MerchantNoMoney$", clonk, clonk);
SetPlrKnowledge(plr, Pump); SetDialogueProgress(2);
SetPlrKnowledge(plr, Pipe); }
SetPlrKnowledge(plr, Catapult); // do transaction.
SetPlrKnowledge(plr, Cannon); MessageBox("$MerchantGivePlans$", clonk);
} DoWealth(clonk->GetOwner(), -150);
SetDialogueStatus(DLG_Status_Stop); for (var i = 0; i < GetPlayerCount(); i++) GameCall("GiveExtraPlans", GetPlayerByIndex(i));
return; g_has_bought_plans = true;
SetDialogueProgress(2);
return true;
} }
private func Dlg_Merchant_4(object clonk) func Dlg_Merchant_Plane(object clonk)
{ {
MessageBox("$MsgLeaveVillage$", clonk); MessageBox("$MerchantAPlane1$", clonk);
SetDialogueStatus(DLG_Status_Stop); SetDialogueProgress(20);
return; return true;
}
func Dlg_Merchant_20(object clonk)
{
MessageBox("$MerchantAPlane2$", clonk);
SetDialogueProgress(2);
return true;
}
func Dlg_Merchant_Pump(object clonk)
{
MessageBox("$MerchantAPump1$", clonk);
SetDialogueProgress(30);
return true;
}
func Dlg_Merchant_30(object clonk)
{
MessageBox("$MerchantAPump2$", clonk);
SetDialogueProgress(2);
return true;
}
func Dlg_Merchant_Catapult(object clonk)
{
MessageBox("$MerchantACatapult1$", clonk);
SetDialogueProgress(40);
return true;
}
func Dlg_Merchant_40(object clonk)
{
MessageBox("$MerchantACatapult2$", clonk, clonk);
SetDialogueProgress(2);
return true;
} }

View File

@ -3,17 +3,28 @@
#appendto Dialogue #appendto Dialogue
private func Dlg_Pilot_1(object clonk) func Dlg_Pilot_1(object clonk)
{ {
MessageBox("$MsgCrashedPlane$", clonk); MessageBox("$MsgCrashedPlane$", clonk);
return; return true;
} }
private func Dlg_Pilot_2(object clonk) func Dlg_Pilot_2(object clonk)
{ {
MessageBox("$AnsCrashedPlane$", clonk, clonk); var options = [["$PyritQPlane$", "Dlg_Pilot_Plane"], ["$PyritQLake$", "Dlg_Pilot_Lake"], ["$PyritQDone$", "StopDialogue()"]];
MessageBox("$AnsCrashedPlane$", clonk, clonk, nil, false, options);
SetDialogueProgress(1); SetDialogueProgress(1);
SetDialogueStatus(DLG_Status_Stop); return true;
return;
} }
func Dlg_Pilot_Plane(object clonk, q)
{
MessageBox("$PyritAPlane$", clonk);
return StopDialogue();
}
func Dlg_Pilot_Lake(object clonk, q)
{
MessageBox("$PyritALake$", clonk);
return StopDialogue();
}

View File

@ -5,7 +5,7 @@
func Intro_Init() func Intro_Init()
{ {
this.plane = CreateObject(Plane, 0, 400); this.plane = CreateObject(Plane, 0, 400);
this.pilot = CreateObject(Clonk, 100, 100, NO_OWNER); this.pilot = npc_pyrit = CreateObject(Clonk, 100, 100, NO_OWNER);
this.pilot->MakeInvincible(); this.pilot->MakeInvincible();
this.pilot->MakeNonFlammable(); this.pilot->MakeNonFlammable();
this.pilot->SetSkin(2); this.pilot->SetSkin(2);
@ -24,7 +24,6 @@ func Intro_Init()
func Intro_Start(object hero) func Intro_Start(object hero)
{ {
if (!this.plane) Intro_Init();
this.hero = hero; this.hero = hero;
this.plane->StartInstantFlight(90, 15); this.plane->StartInstantFlight(90, 15);
@ -36,7 +35,6 @@ func Intro_Start(object hero)
func Intro_JoinPlayer(int plr) func Intro_JoinPlayer(int plr)
{ {
if (!this.plane) Intro_Init();
if (this.intro_closed) return false; // too late for join - just join in village if (this.intro_closed) return false; // too late for join - just join in village
var crew; var crew;
for(var index = 0; crew = GetCrew(plr, index); ++index) for(var index = 0; crew = GetCrew(plr, index); ++index)
@ -152,40 +150,99 @@ func Intro_16()
{ {
var x = this.plane->GetX(); var x = this.plane->GetX();
var y = this.plane->GetY(); var y = this.plane->GetY();
this.pilot->Exit(); this.pilot->Exit();
Intro_CreateBoompack(RandomX(x-5,x+5), RandomX(y-5,y+5), 160)->Launch(290 + Random(26), this.pilot); Intro_CreateBoompack(RandomX(x-5,x+5), RandomX(y-5,y+5), 160)->Launch(290 + Random(26), this.pilot);
while(this.dialogue->Contents()) while(this.dialogue->Contents())
Intro_CreateBoompack(RandomX(x-5,x+5), RandomX(y-5,y+5), 160)->Launch(290 + Random(26), this.dialogue->Contents()); Intro_CreateBoompack(RandomX(x-5,x+5), RandomX(y-5,y+5), 160)->Launch(290 + Random(26), this.dialogue->Contents());
return ScheduleNext(100);
SetViewTarget(nil);
for (var i=0; i<GetPlayerCount(C4PT_User); ++i)
{
var plr = GetPlayerByIndex(i, C4PT_User);
SetPlrView(plr, GetCrew(plr));
}
return ScheduleNext(40);
} }
func Intro_17() func Intro_17()
{ {
ScheduleCall(nil, this.Intro_PilotDlg, 330, 1, this.pilot); this.pilot->SetCommand("MoveTo", nil, 120, 860);
for (var i=0; i<GetPlayerCount(C4PT_User); ++i)
{
var plr = GetPlayerByIndex(i, C4PT_User);
var crew = GetCrew(plr);
if (crew)
{
crew->SetCommand("MoveTo", nil, 135+Random(25), 860);
}
}
this.timer=0;
return ScheduleNext(100);
}
func Intro_18()
{
// wait until pilot has arrived in village
if (!Inside(this.pilot->GetX(), 100,140))
{
++this.timer;
if (this.timer < 12) return ScheduleSame(18);
// Pilot didn't arrive on time. Just put him there.
this.pilot->SetPosition(120,860);
}
this.pilot->SetCommand("None");
this.pilot->SetComDir(COMD_Stop);
this.pilot->SetXDir();
return ScheduleNext(30);
}
func Intro_19()
{
// Begin dialogue in village
this.pilot->SetDir(DIR_Right);
MessageBoxAll("$MsgIntro6$", this.pilot, true); // that was close
return ScheduleNext(150);
}
func Intro_20()
{
this.hero->SetDir(DIR_Left);
MessageBoxAll("$MsgIntro7$", this.hero, true); // what now?
return ScheduleNext(150);
}
func Intro_21()
{
MessageBoxAll("$MsgIntro8$", this.pilot, true); // plane crashed into mountain on other side
return ScheduleNext(250);
}
func Intro_22()
{
MessageBoxAll("$MsgIntro9$", this.pilot, true); // u go there n save it
return ScheduleNext(220);
}
func Intro_23()
{
MessageBoxAll("$MsgIntro10$", this.hero, true); // ok
return ScheduleNext(40);
}
func Intro_24()
{
return Stop(); return Stop();
} }
func Intro_Stop() func Intro_Stop()
{ {
// if players got stuck somewhere, unstick them
for (var i=0; i<GetPlayerCount(C4PT_User); ++i)
{
var plr = GetPlayerByIndex(i, C4PT_User);
var crew = GetCrew(plr);
if (crew && !Inside(crew->GetX(),125,170))
{
crew->SetPosition(135+Random(25), 860);
}
crew->Extinguish();
crew->DoEnergy(100);
}
this.dialogue->SetInteraction(true);
this.dialogue->AddAttention();
SetPlayerZoomByViewRange(NO_OWNER, 400,300, PLRZOOM_Set); SetPlayerZoomByViewRange(NO_OWNER, 400,300, PLRZOOM_Set);
return true; return true;
} }
func Intro_PilotDlg(object pilot)
{
pilot->SetCommand("MoveTo", nil, 120, 860);
var dialogue = Dialogue->FindByTarget(pilot);
dialogue->SetInteraction(true);
dialogue->AddAttention();
return true;
}

View File

@ -0,0 +1,45 @@
/* Outro sequence */
#appendto Sequence
func Outro_Start(object goal, object plane)
{
this.goal = goal;
this.plane = plane;
this.hero = plane->FindObject(Find_Not(Find_Owner(NO_OWNER)), Find_ID(Clonk), plane->Sort_Distance());
SetViewTarget(this.plane);
MessageBoxAll("$Outro1$", this.hero, true);
return ScheduleNext(150);
}
func Outro_1()
{
MessageBoxAll("$Outro2$", npc_pyrit, true);
return ScheduleNext(220);
}
func Outro_2()
{
MessageBoxAll("$Outro3$", this.hero, true);
return ScheduleNext(180);
}
func Outro_3()
{
MessageBoxAll("$Outro4$", npc_pyrit, true);
return ScheduleNext(150);
}
func Outro_4()
{
return Stop();
}
func Outro_Stop()
{
this.goal->SetFulfilled();
return true;
}

View File

@ -4,15 +4,41 @@ MsgIntro2=Schau, der sch
MsgIntro3=Komm schon, Baby... MsgIntro3=Komm schon, Baby...
MsgIntro4=Oh oh... MsgIntro4=Oh oh...
MsgIntro5=Schnell! Der Schleudersitz! MsgIntro5=Schnell! Der Schleudersitz!
MsgIntro6=Puh, das war knapp.
MsgIntro7=Was können wir nun tun?
MsgIntro8=Ich glaube ich habe gesehen, wie das Flugzeug auf der anderen Seite des Vulkans im Schnee gelandet ist.
MsgIntro9=Schnee ist weich. Wenn du dorthin gelangst, kannst du das Flugzeug vielleicht retten.
MsgIntro10=Ich werde es versuchen.
# NPC Pilot # NPC Pilot
NamePilot=Pilot
MsgCrashedPlane=Und, habt ihr das Flugzeug schon gefunden? MsgCrashedPlane=Und, habt ihr das Flugzeug schon gefunden?
AnsCrashedPlane=Nein, wir suchen noch. AnsCrashedPlane=Nein, wir suchen noch.
PyritQPlane=Wo ist das Flugzeug?
PyritAPlane=Ich glaube ich habe gesehen, wie das Flugzeug auf der anderen Seite des Vulkans im Schnee gelandet ist.
PyritQLake=Wie überquere ich den See?
PyritALake=Du braucht vermutlich ein paar fortgeschrittene Werkzeuge. Vielleicht geben uns die Dorfbewohner etwas.
PyritQDone=Nichts weiter.
# NPC Merchant # NPC Merchant
MsgSellPlans=Ich habe hier ein paar interessante Baupläne! Für 150 Clunker würde ich sie dir überlassen. Merchant1=Seid gegrüßt, Fremde aus dem Himmel. Wie kann ich euch helfen?
AnsNoMoney=Da muss ich noch etwas Gold abbauen. Ich komme später wieder. MerchantQPlane=Hast du unser Flugzeug gesehen?
AnsBuyPlans=Das ist ein guter Deal; hier sind deine Clunker. MerchantAPlane1=Der seltame Vogel? Er trudelte über den Vulkan und landere auf der anderen Seite im Schnee.
MsgGivePlans=Danke! Hier hast du Pläne fuer {{Pump}}, {{Pipe}}, {{Catapult}} und {{Cannon}}. Aber Vorsicht: Die Pumpe ist aus Holz und sollte nicht zum Pumpen von Lava verwendet werden! MerchantAPlane2=Dorthin zu gelangen wird nicht einfach sein.
MsgLeaveVillage=Bitte verlasse unser verschlafenes Dorf! MerchantQLake=Kannst du uns helfen, den See zu überqueren?
MerchantSellPlans=Ich habe hier ein paar interessante Baupläne! Für 150 Clunker würde ich sie dir überlassen.
MerchantNoMoney=Da muss ich noch etwas Gold abbauen. Ich komme später wieder.
MerchantBuyPlans=Das ist ein guter Deal; hier sind deine Clunker.
MerchantGivePlans=Danke! Hier hast du Pläne fuer {{Pump}}, {{Pipe}}, {{Catapult}} und {{Cannon}}.
MerchantQPump=Wie benutze ich die Pumpe?
MerchantAPump1=Baue zwei Leitungen und benutze sie, während du vor der Pumpe stehst. Die erste Leitung wird das Zuflussrohr und die zweite Leitung das Abflussrohr.
MerchantAPump2=Wirf dann einfach das andere Ende des zuflussrohrs ins Wasser und platziere das Abflussrohr dort, wo die Flüssigkeit hingepumpt werden soll.
MerchantQCatapult=Wozu brauche ich ein Katapult?
MerchantACatapult1=Ein Katapult hat viele Anwendungen. Man kann Dinge wie Leitungsenden durch die Gegend werfen. Und wenn du mutig bist, kannst du selbst ins Katapult steigen und dich über den Lavasee schleudern.
MerchantACatapult2=Das...klingt gefährlich. Das gefällt mir!
MerchantQDone=Tschüss.
# Outro
Outro1=Es ist vollbracht! Das Flugzeug ist zurück.
Outro2=Gut gemacht. Dann lasst uns die Reise fortsetzen. Wir haben noch einen weiten Weg vor uns.
Outro3=Aber diesmal fliegen wir etwas höher, ok?
Outro4=Mal sehen, was ich tun kann.

View File

@ -4,15 +4,42 @@ MsgIntro2=Have a look at that lava lake!
MsgIntro3=Come on old girl, hang in there... MsgIntro3=Come on old girl, hang in there...
MsgIntro4=Uh oh... MsgIntro4=Uh oh...
MsgIntro5=Quick! The ejection seats! MsgIntro5=Quick! The ejection seats!
MsgIntro6=Phew, that was close.
MsgIntro7=What can we do now?
MsgIntro8=I think I saw the plane crash into the snow on the hill on the other side of the volcano.
MsgIntro9=The snow is soft. Maybe if you get there, you can still salvage the plane.
MsgIntro10=I will try my best
# NPC Pilot # NPC Pilot
NamePilot=Pilot
MsgCrashedPlane=So, have you found the plane yet? MsgCrashedPlane=So, have you found the plane yet?
AnsCrashedPlane=No, we're still searching. AnsCrashedPlane=No, we're still searching.
PyritQPlane=Where is the plane?
PyritAPlane=I think I saw it crash into the snow on the hill on the other side of the volcano.
PyritQLake=How can I cross the lake
PyritALake=You probably need some advanced tools. Maybe the villagers can give us something.
PyritQDone=Nevermind.
# NPC Merchant # NPC Merchant
MsgSellPlans=I know some interesting construction plans, which I can share with you for 150 clunkers. Merchant1=Greetings, strangers from the sky. How can I help you?
AnsNoMoney=Then I'll have to mine for gold, I'll be back later. MerchantQPlane=Have you seen our plane?
AnsBuyPlans=That's a good deal, here you go. MerchantAPlane1=The strange bird? It flew over the turublent volcano and landed on the other side in the snow.
MsgGivePlans=Thanks, here are the plans for {{Pump}}, {{Pipe}}, {{Catapult}} and {{Cannon}}. But be careful with the pump; it's made of wood and cannot be used to pump lava! MerchantAPlane2=Getting there might not be that easy.
MsgLeaveVillage=Please leave this quiet village. MerchantQLake=Can you help us cross the lake?
MerchantSellPlans=I know some interesting construction plans, which may help you in this situation. I can share them with you for 150 clunkers.
MerchantNoMoney=Then I'll have to mine for gold, I'll be back later.
MerchantBuyPlans=That's a good deal, here you go.
MerchantGivePlans=Thanks, here are the plans for {{Pump}}, {{Pipe}}, {{Catapult}} and {{Cannon}}.
MerchantQPump=How do I use the pump?
MerchantAPump1=Just use two pipes as you're standing in front of the pump. The first pipe becomes the source pipe from which is pumped and the second pipe is the drain.
MerchantAPump2=Then just throw the source pipe into liquid and the drain pipe to where you want to pump!
MerchantQCatapult=Why do I need the catapult?
MerchantACatapult1=A catapult has many uses. You can fling things like pipe ends. If you're daring, you could even try to catapult yourself over the lava lake!
MerchantACatapult2=That...sounds scary. I like it!
MerchantQDone=Goodbye.
# Outro
Outro1=It's done! The plane is back.
Outro2=Good job. Let's continue our voyage then. We still have a long way ahead of us.
Outro3=But next time we fly a bit higher, ok?
Outro4=I'll see what I can do.
# plane flies up vertically

View File

@ -27,6 +27,8 @@ func Initialize()
{ {
MakeRuinsOnDamage(); // see System.ocg/Ruins.c MakeRuinsOnDamage(); // see System.ocg/Ruins.c
PlaceGrass(40); PlaceGrass(40);
SetNextMission("Mission.ocf/Crash.ocs");
return true;
} }
func DoInit(int first_player) func DoInit(int first_player)

View File

@ -318,6 +318,8 @@ private func MessageBox(string message, object clonk, object talker, int for_pla
// Text+Command given // Text+Command given
option_text = option[0]; option_text = option[0];
option_command = option[1]; option_command = option[1];
// if only a command is given, the standard parameter is just the clonk
if (!WildcardMatch(option_command, "*(*")) option_command = Format("%s(Object(%d))", option_command, clonk->ObjectNumber());
} }
else else
{ {

View File

@ -18,6 +18,10 @@ func Start(string name, int progress, ...)
SetPosition(0,0); // force global coordinates SetPosition(0,0); // force global coordinates
this.seq_name = name; this.seq_name = name;
this.seq_progress = progress; this.seq_progress = progress;
// call init function of this scene - difference to start function is that it is called before any player joins
var fn_init = Format("~%s_Init", seq_name);
if (!Call(fn_init, ...))
GameCall(fn_init, this, ...);
// Disable crew of all players // Disable crew of all players
for (var i=0; i<GetPlayerCount(C4PT_User); ++i) for (var i=0; i<GetPlayerCount(C4PT_User); ++i)
{ {
@ -181,10 +185,10 @@ private func MessageBox(string message, object clonk, object talker, int for_pla
/* Global helper functions */ /* Global helper functions */
global func StartSequence(string name, int progress, object view_target) global func StartSequence(string name, int progress, ...)
{ {
var seq = CreateObject(Sequence, 0,0, NO_OWNER); var seq = CreateObject(Sequence, 0,0, NO_OWNER);
seq->Start(name, progress, view_target); seq->Start(name, progress, ...);
return seq; return seq;
} }