add tutorial 1

shapetextures
Maikel de Vries 2015-09-13 13:34:00 +02:00
parent ace8ad48d6
commit 80d5525ed9
12 changed files with 877 additions and 0 deletions

View File

@ -0,0 +1,29 @@
{\rtf1\ansi\deff0\adeflang1025
{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}{\f1\froman\fprq2\fcharset2 Symbol;}{\f2\fswiss\fprq2\fcharset0 Arial;}{\f3\froman\fprq2\fcharset1 Times New Roman;}{\f4\froman\fprq2\fcharset1 Arial;}{\f5\froman\fprq0\fcharset1 Arial;}{\f6\fnil\fprq2\fcharset0 Microsoft YaHei;}{\f7\fnil\fprq2\fcharset0 Mangal;}{\f8\fnil\fprq0\fcharset1 Mangal;}}
{\colortbl;\red0\green0\blue0;\red128\green128\blue128;}
{\stylesheet{\s0\snext0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af9\langfe2052\dbch\af7\afs24\alang1081\loch\f0\fs24\lang1043 Normal;}
{\s15\sbasedon0\snext16\sb240\sa120\keepn\dbch\af6\dbch\af7\afs28\loch\f2\fs28 Heading;}
{\s16\sbasedon0\snext16\sb0\sa120 Text body;}
{\s17\sbasedon16\snext17\sb0\sa120\dbch\af8 List;}
{\s18\sbasedon0\snext18\sb120\sa120\noline\i\dbch\af8\afs24\ai\fs24 Caption;}
{\s19\sbasedon0\snext19\noline\dbch\af8 Index;}
}{\info{\creatim\yr0\mo0\dy0\hr0\min0}{\revtim\yr0\mo0\dy0\hr0\min0}{\printim\yr0\mo0\dy0\hr0\min0}{\comment LibreOffice}{\vern3600}}\deftab720
\viewscale100
{\*\pgdsctbl
{\pgdsc0\pgdscuse195\pgwsxn12240\pghsxn15840\marglsxn1800\margrsxn1800\margtsxn1440\margbsxn1440\pgdscnxt0 Default;}}
\formshade{\*\pgdscno0}\paperh15840\paperw12240\margl1800\margr1800\margt1440\margb1440\sectd\sbknone\sectunlocked1\pgndec\pgwsxn12240\pghsxn15840\marglsxn1800\margrsxn1800\margtsxn1440\margbsxn1440\ftnbj\ftnstart1\ftnrstcont\ftnnar\aenddoc\aftnrstcont\aftnstart1\aftnnrlc
\pgndec\pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af9\langfe2052\dbch\af7\afs24\alang1081\loch\f0\fs24\lang1043{\b\rtlch \ltrch\loch\fs20\lang1033\loch\f5
Wanderender Wipf}
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af9\langfe2052\dbch\af7\afs24\alang1081\loch\f0\fs24\lang1043\b\rtlch \ltrch\loch\fs20\lang1033\loch\f5
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af9\langfe2052\dbch\af7\afs24\alang1081\loch\f0\fs24\lang1043{\b0\rtlch \ltrch\loch\fs16\lang1033\loch\f5
Dein bester Freund, ein noch junger und neckischer Wipf, ist mal wieder davon gerannt. Fange ihn bevor er sich verletzt.}
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af9\langfe2052\dbch\af7\afs24\alang1081\loch\f0\fs24\lang1043\rtlch \ltrch\loch
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af9\langfe2052\dbch\af7\afs24\alang1081\loch\f0\fs24\lang1043{\b0\rtlch \ltrch\loch\fs16\lang1033\loch\f5
Ziel: Finde und fange dein kleiner Freund.}
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af9\langfe2052\dbch\af7\afs24\alang1081\loch\f0\fs24\lang1043\rtlch \ltrch\loch
\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af9\langfe2052\dbch\af7\afs24\alang1081\loch\f0\fs24\lang1043{\b0\rtlch \ltrch\loch\fs16\lang1033\loch\f5
Lernrunde erkl\u228\'e4rt: Bewegung, klettern und schwimmen.}
\par }

View File

@ -0,0 +1,33 @@
{\rtf1\ansi\deff0\adeflang1025
{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}{\f1\froman\fprq2\fcharset2 Symbol;}{\f2\fswiss\fprq2\fcharset0 Arial;}{\f3\froman\fprq0\fcharset1 Arial;}{\f4\froman\fprq0\fcharset1 Times New Roman;}{\f5\fswiss\fprq0\fcharset1 Arial;}{\f6\fnil\fprq2\fcharset0 Microsoft YaHei;}{\f7\fnil\fprq2\fcharset0 Arial;}{\f8\fnil\fprq0\fcharset1 Mangal;}}
{\colortbl;\red0\green0\blue0;\red128\green128\blue128;}
{\stylesheet{\s0\snext0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f4\fs24\lang1043 Normal;}
{\s15\sbasedon0\snext16\ql\nowidctlpar\sb240\sa120\keepn\ltrpar\cf0\kerning1\dbch\af6\langfe2052\dbch\af8\afs28\alang1081\loch\f5\fs28\lang1043 Heading;}
{\s16\sbasedon0\snext16\ql\nowidctlpar\sb0\sa120\ltrpar\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f4\fs24\lang1043 Text body;}
{\s17\sbasedon16\snext17\ql\nowidctlpar\sb0\sa120\ltrpar\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f4\fs24\lang1043 List;}
{\s18\sbasedon0\snext18\ql\nowidctlpar\sb120\sa120\noline\ltrpar\cf0\i\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\ai\loch\f4\fs24\lang1043 Caption;}
{\s19\sbasedon0\snext19\ql\nowidctlpar\noline\ltrpar\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f4\fs24\lang1043 Index;}
}{\info{\creatim\yr0\mo0\dy0\hr0\min0}{\revtim\yr0\mo0\dy0\hr0\min0}{\printim\yr0\mo0\dy0\hr0\min0}{\comment LibreOffice}{\vern3600}}\deftab720
\viewscale100
{\*\pgdsctbl
{\pgdsc0\pgdscuse195\pgwsxn12240\pghsxn15840\marglsxn1800\margrsxn1800\margtsxn1440\margbsxn1440\pgdscnxt0 Default;}}
\formshade{\*\pgdscno0}\paperh15840\paperw12240\margl1800\margr1800\margt1440\margb1440\sectd\sbknone\sectunlocked1\pgndec\pgwsxn12240\pghsxn15840\marglsxn1800\margrsxn1800\margtsxn1440\margbsxn1440\ftnbj\ftnstart1\ftnrstcont\ftnnar\aenddoc\aftnrstcont\aftnstart1\aftnnrlc
\pgndec\pard\plain \s0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f4\fs24\lang1043\ql\nowidctlpar{\cf1\b\kerning1\langfe2052\dbch\af8\afs24\alang1081\rtlch \ltrch\loch\fs20\lang1033\loch\f3
Wandering Wipf}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f4\fs24\lang1043\ql\nowidctlpar\cf1\b\kerning1\langfe2052\dbch\af8\afs24\alang1081\rtlch \ltrch\loch\fs20\lang1033\loch\f3
\par \pard\plain \s0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f4\fs24\lang1043\ql\nowidctlpar{\cf1\b0\kerning1\langfe2052\dbch\af8\afs24\alang1081\rtlch \ltrch\loch\fs16\lang1033\loch\f3
Your best friend, a still young and playful Wipf, has r}{\cf1\b0\kerning1\langfe2052\dbch\af8\afs24\alang1081\rtlch \ltrch\loch\fs16\lang1033\loch\f3
a}{\cf1\b0\kerning1\langfe2052\dbch\af8\afs24\alang1081\rtlch \ltrch\loch\fs16\lang1033\loch\f3
n away. Catch him before he hurts himself.}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f4\fs24\lang1043\ql\nowidctlpar\cf1\kerning1\langfe2052\dbch\af8\afs24\alang1081\rtlch \ltrch\loch\fs24\lang1043
\par \pard\plain \s0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f4\fs24\lang1043\ql\nowidctlpar{\cf1\b0\kerning1\langfe2052\dbch\af8\afs24\alang1081\rtlch \ltrch\loch\fs16\lang1033\loch\f3
Goal: Find and catch your little friend.}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f4\fs24\lang1043\ql\nowidctlpar\cf1\kerning1\langfe2052\dbch\af8\afs24\alang1081\rtlch \ltrch\loch\fs24\lang1043
\par \pard\plain \s0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f4\fs24\lang1043\ql\nowidctlpar{\cf1\b0\kerning1\langfe2052\dbch\af8\afs24\alang1081\rtlch \ltrch\loch\fs16\lang1033\loch\f3
Tutorial explains: Movement, climbing and swimming.}
\par \pard\plain \s0\ql\nowidctlpar\ltrpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f4\fs24\lang1043\ql\nowidctlpar\rtlch \ltrch\loch
\par }

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -0,0 +1,22 @@
[Head]
Icon=2
Title=Tutorial01
Version=6,0
MaxPlayer=1
Difficulty=1
[Definitions]
Definition1=Objects.ocd
[Player1]
Crew=Clonk=1
[Landscape]
Sky=Clouds1
SkyScrollMode=2
[Weather]
Climate=0,0,0,100
StartSeason=0,0,0,100
YearSpeed=0,0,0,100
Wind=1,100,-100,100

View File

@ -0,0 +1,520 @@
/**
Tutorial 01: Wandering Wipf
Author: Maikel
First introduction to the world of OpenClonk: explains basic movement controls.
Following controls and concepts are explained:
* Clonk HUD
* Walking and jumping with WASD
* Scaling, wall jump and hangling
* Swimming, diving and breath
* Liquids: water
*/
static guide; // guide object
protected func Initialize()
{
// Tutorial goal.
var goal = CreateObject(Goal_Tutorial);
goal.Name = "$MsgGoalName$";
goal.Description = "$MsgGoalDescription$";
CreateObject(Rule_NoPowerNeed);
// Place objects in different sections.
InitStartLake();
InitCaveEntrance();
InitHangleSection();
InitCaveCenter();
InitGoldMine();
InitCaveExit();
InitVegetation();
InitAnimals();
// Environment.
var time = CreateObject(Environment_Time);
time->SetTime(18*60 + 30);
time->SetCycleSpeed(0);
// Dialogue options -> repeat round.
SetNextMission("Tutorials.ocf\\Tutorial01.ocs", "$MsgRepeatRound$", "$MsgRepeatRoundDesc$");
return;
}
// Gamecall from goals, set next mission.
protected func OnGoalsFulfilled()
{
// Achievement: Tutorial completed.
GainScenarioAchievement("TutorialCompleted", 3);
// Dialogue options -> next round.
SetNextMission("Tutorials.ocf\\Tutorial02.ocs", "$MsgNextTutorial$", "$MsgNextTutorialDesc$");
// Normal scenario ending by goal library.
return false;
}
// Lake and start position.
private func InitStartLake()
{
// Seaweed, fishes and shells in the lakes.
Seaweed->Place(5, Rectangle(0, 600, 50, 100));
Seaweed->Place(5, Rectangle(120, 600, 120, 120));
Seaweed->Place(5, Rectangle(220, 400, 140, 50));
// A shipwreck on the beach.
// A few coconut trees.
CreateObjectAbove(Tree_Coconut, 52, 620);
CreateObjectAbove(Tree_Coconut, 79, 620);
CreateObjectAbove(Tree_Coconut, 105, 620);
// Ropebridge over the lake.
var post1 = CreateObjectAbove(Ropebridge_Post, 144, 616);
var post2 = CreateObjectAbove(Ropebridge_Post, 232, 616);
post2->SetObjDrawTransform(-1000, 0, 0, 0, 1000);
post2.Double->SetObjDrawTransform(-1000, 0, 0, 0, 1000);
CreateObjectAbove(Ropebridge, 186, 616)->MakeBridge(post1, post2);
// Small sink hole for the water to flow through, cover by a trunk.
DrawMaterialQuad("Tunnel", 231, 631, 231, 633, 251, 615, 249, 615, DMQ_Sub);
var trunk = CreateObjectAbove(Trunk, 241, 644);
trunk->SetR(45); trunk.Plane = 510; trunk->DoCon(-42);
trunk.MeshTransformation = [-1000, 0, -17, 0, 0, 1000, 0, 0, 17, 0, -1000, 0];
return;
}
// Cave entrance with waterfall.
private func InitCaveEntrance()
{
// Waterfall from a leaking trunk.
var trunk = CreateObjectAbove(Trunk, 324, 465);
trunk->SetR(150); trunk.Plane = 510;
trunk.MeshTransformation = [-70, 0, 998, 0, 0, 1000, 0, 0, -998, 0, -70, 0];
var waterfall;
waterfall = CreateWaterfall(325, 448, 2, "Water");
waterfall->SetDirection(2, 0, 3, 6);
waterfall = CreateWaterfall(338, 450, 8, "Water");
waterfall->SetDirection(1, 0, 4, 8);
CreateLiquidDrain(160, 648, 10);
CreateLiquidDrain(184, 648, 10);
CreateLiquidDrain(208, 648, 10);
// Some vegetation below the waterfall.
Fern->Place(2 + Random(2), Rectangle(300, 600, 60, 40));
Mushroom->Place(4 + Random(2), Rectangle(300, 600, 60, 40));
// Make the wipf hole a bit wider.
DrawMaterialQuad("Tunnel", 360, 600, 410, 600, 410, 589, 360, 589, DMQ_Sub);
// Vegetation in wall jump hole.
var rock = CreateObjectAbove(BigRock, 313, 525);
rock.MeshTransformation = [-314, -543, 671, 0, 0, 1085, 878, 0, -974, 222, -275, 0];
rock.Plane = 510;
// Torches to show the path.
var torch = CreateObjectAbove(Torch, 288, 608);
torch->AttachToWall(true);
var torch = CreateObjectAbove(Torch, 388, 488);
torch->AttachToWall(true);
return;
}
// Hangle section with large mushrooms and gap to cross.
private func InitHangleSection()
{
// Some large mushrooms.
var mushroom = CreateConstruction(LargeCaveMushroom, 489, 557, NO_OWNER, 100, false, false);
mushroom.MeshTransformation = Trans_Scale(500, 500, 500); mushroom->SetR(240);
mushroom = CreateConstruction(LargeCaveMushroom, 517, 606, NO_OWNER, 100, false, false);
mushroom.MeshTransformation = Trans_Scale(550, 550, 550);
mushroom = CreateConstruction(LargeCaveMushroom, 597, 670, NO_OWNER, 100, false, false);
mushroom.MeshTransformation = Trans_Scale(600, 600, 600);
mushroom = CreateConstruction(LargeCaveMushroom, 642, 686, NO_OWNER, 100, false, false);
mushroom.MeshTransformation = Trans_Scale(700, 700, 700);
// Some ferns and mushrooms.
Fern->Place(5 + Random(3), Rectangle(480, 560, 220, 140));
Mushroom->Place(9 + Random(4), Rectangle(480, 560, 220, 140));
// Make the diagonal wipf hole a bit wider.
DrawMaterialQuad("Tunnel", 690, 671, 754, 607, 769, 607, 690, 686, DMQ_Sub);
// Wipf hole covered by trunk.
var trunk = CreateObjectAbove(Trunk, 822, 621);
trunk.MeshTransformation = [821, 0, 795, 0, 0, 1145, 0, 0, -795, 0, 821, 0];
trunk.Plane = 510; trunk->SetR(90);
DrawMaterialQuad("Tunnel", 796, 591, 836, 591, 836, 602, 796, 602, DMQ_Sub);
return;
}
// The cave center has two lakes with seaweed.
private func InitCaveCenter()
{
// Seaweed in the two lakes.
Seaweed->Place(5, Rectangle(540, 480, 140, 100));
Seaweed->Place(12, Rectangle(520, 330, 380, 100));
// Some vegetation between the two bodies of water.
var ferns = Fern->Place(5 + Random(2), Rectangle(420, 370, 110, 90));
for (var fern in ferns)
fern->SetR(40 + Random(10));
var mushrooms = Mushroom->Place(7 + Random(3), Rectangle(420, 370, 110, 90));
for (var mushroom in mushrooms)
mushroom->SetR(40 + Random(10));
return;
}
// Gold mine with dynamite and lorry.
private func InitGoldMine()
{
// Foundry with a lorry and some metal.
CreateObjectAbove(Foundry, 980, 486);
CreateObjectAbove(Metal, 950, 474);
// Pickaxe + ore near ore field.
CreateObjectAbove(Lorry, 824, 460);
CreateObjectAbove(Pickaxe, 808, 446)->SetR(RandomX(300, 330));
CreateObjectAbove(Ore, 818, 460);
CreateObjectAbove(Ore, 839, 460);
// Shovel + coal chunks near coal field.
CreateObjectAbove(Shovel, 966, 534)->SetR(RandomX(90, 135));
CreateObjectAbove(Coal, 959, 532);
CreateObjectAbove(Coal, 936, 532);
// Dynamite box to blast through mine.
var dyn1 = CreateObjectAbove(Dynamite, 959, 585, NO_OWNER); dyn1->SetR(-135);
var dyn2 = CreateObjectAbove(Dynamite, 974, 597, NO_OWNER); dyn2->SetR(-105);
var dyn3 = CreateObjectAbove(Dynamite, 970, 618, NO_OWNER); dyn3->SetR(-60);
var dyn4 = CreateObjectAbove(Dynamite, 955, 633, NO_OWNER); dyn4->SetR(-30);
var dyn5 = CreateObjectAbove(Dynamite, 941, 637, NO_OWNER); dyn5->SetR(-15);
CreateObjectAbove(Fuse, 959, 585, NO_OWNER)->Connect(dyn1, dyn2);
CreateObjectAbove(Fuse, 974, 597, NO_OWNER)->Connect(dyn2, dyn3);
CreateObjectAbove(Fuse, 970, 618, NO_OWNER)->Connect(dyn3, dyn4);
CreateObjectAbove(Fuse, 955, 633, NO_OWNER)->Connect(dyn4, dyn5);
var igniter = CreateObjectAbove(Igniter, 909, 637, NO_OWNER);
CreateObjectAbove(Fuse, 941, 637, NO_OWNER)->Connect(dyn5, igniter);
igniter->SetGraphics("0", Fuse, 1, GFXOV_MODE_Picture);
return;
}
// Cave exit: Elevator, cabin and flag.
private func InitCaveExit()
{
// A small settlement.
var elevator = CreateObjectAbove(Elevator, 872, 328);
elevator->CreateShaft(248);
CreateObjectAbove(WoodenCabin, 968, 328);
// Some vegetation / rocks on top of the cave.
SproutBerryBush->Place(1 + Random(2), Rectangle(420, 200, 160, 70));
SproutBerryBush->Place(1, Rectangle(640, 80, 100, 70));
Flower->Place(10, Rectangle(420, 200, 160, 70));
var bigrock = CreateObjectAbove(BigRock, 218, 395);
bigrock.MeshTransformation = [-103, 561, -337, 0, 0, 730, 1216, 0, 555, 74, -44, 0];
return;
}
// Vegetation throughout the scenario.
private func InitVegetation()
{
PlaceGrass(85);
PlaceObjects(Firestone, 25 + Random(5), "Earth");
PlaceObjects(Loam, 15 + Random(5), "Earth");
Branch->Place(32, nil, {underground = true});
Branch->Place(10, nil, {underground = false});
return;
}
private func InitAnimals()
{
// The wipf as your friend, controlled by AI.
CreateObjectAbove(Wipf, 76, 616);
// Some butterflies as atmosphere.
for (var i = 0; i < 25; i++)
PlaceAnimal(Butterfly);
// Some fish in the big lake.
Fish->Place(5, Rectangle(500, 300, 300, 150));
return;
}
/*-- Player Handling --*/
protected func InitializePlayer(int plr)
{
// Position player's clonk.
var clonk = GetCrew(plr, 0);
clonk->SetPosition(60, 606);
var effect = AddEffect("ClonkRestore", clonk, 100, 10);
effect.to_x = 60;
effect.to_y = 606;
// Player controls disabled at the start.
DisablePlrControls(plr);
// Add an effect to the clonk to track the goal.
var track_goal = AddEffect("TrackGoal", clonk, 100, 2);
track_goal.plr = plr;
// Standard player zoom for tutorials, player is not allowed to zoom in/out.
SetPlayerViewLock(plr, true);
SetPlayerZoomByViewRange(plr, 400, nil, PLRZOOM_Direct | PLRZOOM_LimitMin | PLRZOOM_LimitMax);
// Determine player movement keys.
var left = GetPlayerControlAssignment(plr, CON_Left, true, true);
var right = GetPlayerControlAssignment(plr, CON_Right, true, true);
var up = GetPlayerControlAssignment(plr, CON_Up, true, true);
var down = GetPlayerControlAssignment(plr, CON_Down, true, true);
var jump = GetPlayerControlAssignment(plr, CON_Jump, true, true);
var control_keys = Format("[%s] [%s] [%s] [%s]", up, left, down, right);
// Create tutorial guide, add messages, show first.
guide = CreateObjectAbove(TutorialGuide, 0, 0, plr);
guide->AddGuideMessage(Format("$MsgTutorialWelcome$", control_keys));
guide->AddGuideMessage("$MsgTutorialHUD$");
guide->AddGuideMessage(Format("$MsgTutorialFollowFriend$", left, right, jump));
guide->ShowGuideMessage(0);
AddEffect("TutorialScale", nil, 100, 2);
return;
}
/*-- Intro, Tutorial Goal & Outro --*/
private func OnFinishedTutorialIntro(int plr)
{
// enable crew
EnablePlrControls(plr);
// start the wipf
FindObject(Find_ID(Wipf))->StartMoving();
}
global func FxTrackGoalTimer(object target, proplist effect, int time)
{
if (Inside(target->GetX(), 980, 996) && Inside(target->GetY(), 314, 324))
{
if (FindObject(Find_ID(Wipf), Find_Distance(15, target->GetX(), target->GetY())))
{
var outro = AddEffect("GoalOutro", target, 100, 5);
outro.plr = effect.plr;
return FX_Execute_Kill;
}
}
return FX_OK;
}
global func FxGoalOutroStart(object target, proplist effect, int temp)
{
if (temp)
return;
// Show guide message congratulating.
guide->AddGuideMessage("$MsgTutorialCompleted$");
guide->ShowGuideMessage(8);
// Halt clonk and disable player controls.
DisablePlrControls(effect.plr);
target->SetComDir(COMD_Stop);
// Find wipf and enter it into the clonk.
var wipf = FindObject(Find_ID(Wipf), Find_Distance(15, target->GetX(), target->GetY()));
if (wipf)
wipf->Enter(target);
// Let the clonk pick up the wipf as an outro.
effect.mesh = target->AttachMesh(Wipf, "pos_tool1", "Bone.006");
effect.anim = target->PlayAnimation("CarryArmsPickup", 10, Anim_Linear(0,0,target->GetAnimationLength("CarryArmsPickup"), 60, ANIM_Remove), Anim_Const(1000));
return FX_OK;
}
global func FxGoalOutroTimer(object target, proplist effect, int time)
{
if (time >= 60)
{
var goal = FindObject(Find_ID(Goal_Tutorial));
goal->Fulfill();
return FX_Execute_Kill;
}
return FX_OK;
}
global func FxGoalOutroStop(object target, proplist effect, int reason, bool temp)
{
if (temp)
return;
// Enable player controls again.
EnablePlrControls(effect.plr);
target->DetachMesh(effect.mesh);
target->StopAnimation(effect.anim);
}
/*-- Guide Messages --*/
// Finds when the Clonk has done 'X', and changes the message.
global func FxTutorialScaleTimer(object target, proplist effect, int timer)
{
var clonk = FindObject(Find_ID(Clonk), Find_InRect(264, 568, 80, 48));
if (clonk)
{
var plr = clonk->GetOwner();
while (GetEffect("TutorialIntro*"))
RemoveEffect("TutorialIntro*");
var up = GetPlayerControlAssignment(plr, CON_Up, true, true);
var down = GetPlayerControlAssignment(plr, CON_Down, true, true);
guide->AddGuideMessage(Format("$MsgTutorialScaleWall$", up, down));
guide->ShowGuideMessage(3);
AddEffect("TutorialHangle", nil, 100, 2);
return FX_Execute_Kill;
}
return FX_OK;
}
global func FxTutorialHangleTimer(object target, proplist effect, int timer)
{
var clonk = FindObject(Find_ID(Clonk), Find_InRect(480, 560, 80, 48));
if (clonk)
{
var plr = clonk->GetOwner();
var down = GetPlayerControlAssignment(plr, CON_Down, true, true);
guide->AddGuideMessage(Format("$MsgTutorialHangle$", down));
guide->ShowGuideMessage(4);
AddEffect("TutorialJump", nil, 100, 2);
return FX_Execute_Kill;
}
return FX_OK;
}
global func FxTutorialJumpTimer(object target, proplist effect, int timer)
{
if (FindObject(Find_ID(Clonk), Find_InRect(744, 568, 56, 40)))
{
guide->AddGuideMessage("$MsgTutorialJump$");
guide->ShowGuideMessage(5);
AddEffect("TutorialSwimming", nil, 100, 2);
return FX_Execute_Kill;
}
return FX_OK;
}
global func FxTutorialSwimmingTimer(object target, proplist effect, int timer)
{
var clonk = FindObject(Find_ID(Clonk), Find_InRect(672, 440, 80, 72));
if (clonk)
{
var plr = clonk->GetOwner();
var left = GetPlayerControlAssignment(plr, CON_Left, true, true);
var right = GetPlayerControlAssignment(plr, CON_Right, true, true);
var up = GetPlayerControlAssignment(plr, CON_Up, true, true);
var down = GetPlayerControlAssignment(plr, CON_Down, true, true);
var control_keys = Format("[%s] [%s] [%s] [%s]", up, left, down, right);
guide->AddGuideMessage(Format("$MsgTutorialSwimming$", control_keys));
guide->ShowGuideMessage(6);
AddEffect("TutorialDiving", nil, 100, 2);
return FX_Execute_Kill;
}
return FX_OK;
}
global func FxTutorialDivingTimer(object target, proplist effect, int timer)
{
if (FindObject(Find_ID(Clonk), Find_InRect(472, 280, 48, 64)))
{
guide->AddGuideMessage("$MsgTutorialDiving$");
guide->ShowGuideMessage(7);
return FX_Execute_Kill;
}
return FX_OK;
}
protected func OnGuideMessageShown(int plr, int index)
{
// Show the player his clonk and the guide.
if (index == 0)
{
TutArrowShowTarget(GetCrew(GetPlayerByIndex()), 225, 24);
}
// Show the player HUD.
if (index == 1)
{
TutArrowShowGUITarget(FindObject(Find_ID(GUI_Controller_CrewBar)), 0);
TutArrowShowGUITarget(FindObject(Find_ID(GUI_Controller_Goal)), 0);
}
// Show the clonks friend: the wipf.
if (index == 2)
{
OnFinishedTutorialIntro(plr);
TutArrowShowTarget(FindObject(Find_ID(Wipf)));
}
// Show wall to climb.
if (index == 3)
TutArrowShowPos(366, 570, 45);
// Show ceiling on which to hangle.
if (index == 4)
TutArrowShowPos(592, 564, 45);
// Show wall to jump to.
if (index == 5)
{
TutArrowShowPos(780, 560, 0);
TutArrowShowPos(756, 544, 315);
}
// Show sea to swim in.
if (index == 6)
TutArrowShowPos(652, 478, 225);
// Show breath indicator.
if (index == 7)
TutArrowShowGUITarget(FindObject(Find_ID(GUI_Controller_CrewBar)), 0);
return;
}
protected func OnGuideMessageRemoved(int plr, int index)
{
TutArrowClear();
return;
}
/*-- Clonk restoring --*/
global func FxClonkRestoreTimer(object target, proplist effect, int time)
{
// Respawn clonk to new location if reached certain position.
if (FindObject(Find_OCF(OCF_CrewMember), Find_InRect(656, 432, 40, 48)))
{
effect.to_x = 680;
effect.to_y = 470;
}
if (FindObject(Find_OCF(OCF_CrewMember), Find_InRect(488, 280, 32, 48)))
{
effect.to_x = 500;
effect.to_y = 318;
}
return FX_OK;
}
// Relaunches the clonk, from death or removal.
global func FxClonkRestoreStop(object target, effect, int reason, bool temporary)
{
if (reason == 3 || reason == 4)
{
var restorer = CreateObjectAbove(ObjectRestorer, 0, 0, NO_OWNER);
var x = BoundBy(target->GetX(), 0, LandscapeWidth());
var y = BoundBy(target->GetY(), 0, LandscapeHeight());
restorer->SetPosition(x, y);
var to_x = effect.to_x;
var to_y = effect.to_y;
// Respawn new clonk.
var plr = target->GetOwner();
var clonk = CreateObjectAbove(Clonk, 0, 0, plr);
clonk->GrabObjectInfo(target);
SetCursor(plr, clonk);
clonk->DoEnergy(100000);
restorer->SetRestoreObject(clonk, nil, to_x, to_y, 0, "ClonkRestore");
}
return FX_OK;
}

View File

@ -0,0 +1,20 @@
# Goal Description
MsgGoalName=Catch your Wipf
MsgGoalDescription=Follow your little friend and catch him as soon as possible.
# Dialogue options
MsgNextTutorial=&Next tutorial
MsgNextTutorialDesc=Start the next tutorial scenario.
MsgRepeatRound=&Repeat this round
MsgRepeatRoundDesc=Restart this scenario.
# Tutorial messages
MsgTutorialWelcome=Welcome to OpenClonk! This is your clonk and it is controlled with the %s keys. Click on the next button to read the next hint and click on my icon at any time to view the current hint.
MsgTutorialHUD=In the upper left part of the screen each of your clonks is shown, in the upper right part you can see the current goal and the amount of clunkers you own.
MsgTutorialFollowFriend=Follow your animal friend across the bridge and past the obstacles ahead while the clonk's movement is explained. Try moving the clonk around a bit by pressing [%s] or [%s] for walking left or right and [%s] for jumping.
MsgTutorialScaleWall=Here you will need to climb the wall to advance. To climb, walk towards the wall until your clonk grabs on. Once you have grabbed on, you may scale up or down the wall by holding [%s] or [%s].
MsgTutorialHangle=Clonks are incredibly versatile and nimble, once a clonk touches a ceiling it automatically holds on to it. Jump to this ceiling, hangle to the other side and let go by pressing [%s].
MsgTutorialJump=Your friend squeezed himself through this trunk, you are too big. So jump upwards and move towards the wall on the left to climb to the next plateau.
MsgTutorialSwimming=Another obstacle: Water! Clonks are able to swim, using the directional keys %s. Cross this body of water to find your fluffy friend.
MsgTutorialDiving=Sometimes it is necessary to dive into the water. Clonks have limited breath which is indicated in the HUD, so you need to resurface regularly.
MsgTutorialCompleted=Well done! You have found your little furry friend, let's proceed to the next tutorial.

View File

@ -0,0 +1,20 @@
# Goal description
MsgGoalName=Catch your Wipf
MsgGoalDescription=Follow your little friend and catch him as soon as possible.
# Dialogue options
MsgNextTutorial=&Next tutorial
MsgNextTutorialDesc=Start the next tutorial scenario.
MsgRepeatRound=&Repeat this round
MsgRepeatRoundDesc=Restart this scenario.
# Tutorial messages
MsgTutorialWelcome=Welcome to OpenClonk! This is your clonk and it is controlled with the %s keys. Click on the next button to read the next hint and click on my icon at any time to view the current hint.
MsgTutorialHUD=In the upper left part of the screen each of your clonks is shown, in the upper right part you can see the current goal and the amount of clunkers you own.
MsgTutorialFollowFriend=Follow your animal friend across the bridge and past the obstacles ahead while the clonk's movement is explained. Try moving the clonk around a bit by pressing [%s] or [%s] for walking left or right and [%s] for jumping.
MsgTutorialScaleWall=Here you will need to climb the wall to advance. To climb, walk towards the wall until your clonk grabs on. Once you have grabbed on, you may scale up or down the wall by holding [%s] or [%s].
MsgTutorialHangle=Clonks are incredibly versatile and nimble, once a clonk touches a ceiling it automatically holds on to it. Jump to this ceiling, hangle to the other side and let go by pressing [%s].
MsgTutorialJump=Your friend squeezed himself through this trunk, you are too big. So jump upwards and move towards the wall on the left to climb to the next plateau.
MsgTutorialSwimming=Another obstacle: Water! Clonks are able to swim, using the directional keys %s. Cross this body of water to find your fluffy friend.
MsgTutorialDiving=Sometimes it is necessary to dive into the water. Clonks have limited breath which is indicated in the HUD, so you need to resurface regularly.
MsgTutorialCompleted=Well done! You have found your little furry friend, let's proceed to the next tutorial.

View File

@ -0,0 +1,132 @@
// Triggers colored wipf rainbow on a succesful jump roll and wall jump performed by the player.
#appendto Clonk
public func DoRoll()
{
// Only perform events on first roll.
if (GetEffect("IntDoneRoll", this))
return _inherited(...);
else
AddEffect("IntDoneRoll", this, 100);
// Add some stars effect to the clonk indicating the easteregg.
CreateParticle("StarSpark", PV_Random(-3, 3), PV_Random(-14, -10), PV_Random(-5, 5), PV_Random(-8, 0), 25, Particles_Magic(), 20);
if (GetEffect("IntDoneWallJump", this))
DoEasterEgg();
return _inherited(...);
}
protected func FxIntDoneRollStart(object target, proplist effect, int temporary)
{
// Just a an effect which should always stay and hence accept always.
return FX_OK;
}
public func StartJump()
{
// Only do something if it is a wal jump, not an ordinary one.
if (!GetEffect("WallKick",this))
return _inherited(...);
// Only perform events on first wall jump.
if (GetEffect("IntDoneWallJump", this))
return _inherited(...);
else
AddEffect("IntDoneWallJump", this, 100);
// Add some stars effect to the clonk indicating the easteregg.
CreateParticle("StarSpark", PV_Random(-3, 3), PV_Random(-14, -10), PV_Random(-5, 5), PV_Random(-8, 0), 25, Particles_Magic(), 20);
if (GetEffect("IntDoneRoll", this))
DoEasterEgg();
return _inherited(...);
}
protected func FxIntDoneWallJumpStart(object target, proplist effect, int temporary)
{
// Just a an effect which should always stay and hence accept always.
return FX_OK;
}
// Award achievement if a gold bar has been collected.
public func Collection(object collected)
{
if (collected->GetID() == GoldBar)
{
// Only perform events on first wall jump.
if (GetEffect("IntAwardedAchievement", this))
return _inherited(...);
AddEffect("IntAwardedAchievement", this, 100);
// Add some stars effect to the clonk indicating the easteregg.
CreateParticle("StarSpark", PV_Random(-3, 3), PV_Random(-14, -10), PV_Random(-5, 5), PV_Random(-8, 0), 25, Particles_Magic(), 20);
// Achievement: easter egg found.
GainScenarioAchievement("TutorialEasterEgg");
}
return _inherited(collected, ...);
}
protected func FxIntAwardedAchievementStart(object target, proplist effect, int temporary)
{
// Just a an effect which should always stay and hence accept always.
return FX_OK;
}
// Creates the easteregg.
public func DoEasterEgg()
{
// Create the wipf rainbow at the cave exit.
CreateRainbow();
// Create a chest with gold at the other end of the rainbow.
var chest = CreateObjectAbove(Chest, AbsX(576), AbsY(260));
chest->CreateContents(GoldBar, 10);
return;
}
// Creates a rainbow consisting of small colored wipfs.
public func CreateRainbow()
{
// Rainbow properties
var cx = 772, cy = 400; // rainbow center
var r = 244; // rainbow radius
var colors = [[255, 0, 0], [255, 127, 0], [255, 255, 0], [0, 255, 0], [0, 0, 255], [75, 0, 130], [143, 0, 255]];
// Loop over the number for particles in the rainbow and create it.
var arc_start = 120;
var arc_length = 1360;
var nparticle = 150;
// Dummy object for attaching the particles and make them background.
var dummy = CreateObject(Dummy);
dummy.Visibility = VIS_Owner;
dummy.Plane = -600;
dummy->SetCategory(C4D_StaticBack | C4D_Background | C4D_Parallax);
dummy.Parallaxity = [20, 20];
// Loop over the arc and the colors and create the particles.
for (var angle = arc_start; angle < arc_start + arc_length; angle += (arc_length / nparticle))
{
for (var i = 0; i < GetLength(colors); i++)
{
var x = dummy->AbsX(cx + Cos(angle, r - 2 * i, 10));
var y = dummy->AbsY(cy - Sin(angle, r - 2 * i, 10));
var wipf =
{
Size = 7,
Rotation = 90 - angle / 10,
R = colors[i][0],
G = colors[i][1],
B = colors[i][2],
Alpha = 128, //PV_Step(1, 0, 1, 255),
Attach = ATTACH_Back,
};
dummy->CreateParticle("Sphere", x, y, 0, 0, 0, wipf, 1);
}
}
return;
}

View File

@ -0,0 +1,99 @@
// Artificial intelligence for the wipf and also the elevator.
#appendto Wipf
protected func Initialize()
{
_inherited(...);
RemoveEffect("Activity", this);
AddEffect("TutorialWipf", this, 1, 5, this);
return;
}
protected func FxTutorialWipfStart(object target, proplist effect, int temp)
{
if (temp)
return;
effect.Sequence = "Introduction";
effect.StartMoving = false;
return FX_OK;
}
public func StartMoving()
{
var effect = GetEffect("TutorialWipf", this, 0);
effect.StartMoving = true;
}
protected func FxTutorialWipfTimer(object target, proplist effect, int time)
{
// Wait for the introduction to finish and then move through the first hole.
if (effect.Sequence == "Introduction")
{
if (effect.StartMoving)
{
SetCommand("MoveTo", nil, 344, 612);
effect.Sequence = "WaitInFrontOfHole";
FindObject(Find_ID(ElevatorCase))->SetMoveDirection(COMD_Down, true, false);
}
}
// Wait in front of the the first hole.
if (effect.Sequence == "WaitInFrontOfHole")
{
if (FindObject(Find_OCF(OCF_CrewMember), Find_InRect(AbsX(256), AbsY(576), 80, 40)))
{
SetCommand("MoveTo", nil, 548, 604);
effect.Sequence = "MoveThroughHole";
}
}
// Wait after the first hole until the clonk arrives and move through the second.
if (effect.Sequence == "MoveThroughHole")
{
if (FindObject(Find_OCF(OCF_CrewMember), Find_InRect(AbsX(424), AbsY(464), 64, 64)))
{
SetCommand("MoveTo", nil, 780, 604);
AddCommand("MoveTo", nil, 676, 684);
effect.Sequence = "MoveAcross";
}
}
// Wait after the second hole until the clonk arrives and move through the third.
if (effect.Sequence == "MoveAcross")
{
if (FindObject(Find_OCF(OCF_CrewMember), Find_InRect(AbsX(664), AbsY(560), 80, 48)))
{
SetCommand("MoveTo", nil, 890, 636);
effect.Sequence = "MoveToLift";
}
}
// Move to the elevator.
if (effect.Sequence == "MoveToLift")
{
if (Inside(GetX(), 885, 895) && Inside(GetY(), 632, 640) && !GetCommand())
{
SetCommand("None");
SetPosition(891, 634);
effect.Sequence = "WaitOnLift";
Schedule(FindObject(Find_ID(ElevatorCase)), "SetMoveDirection(COMD_Up, true, false)", 15);
Schedule(FindObject(Find_ID(ElevatorCase)), "SetMoveDirection(COMD_Down, true, false)", 17);
Schedule(FindObject(Find_ID(ElevatorCase)), "SetMoveDirection(COMD_Up, true, false)", 20);
}
}
// Wait on the moving lift.
if (effect.Sequence == "WaitOnLift")
{
if (Inside(GetX(), 885, 895) && Inside(GetY(), 320, 328))
{
SetCommand("MoveTo", nil, 992, 324);
effect.Sequence = "MoveToCabin";
}
}
// Move to the cabin.
if (effect.Sequence == "MoveToCabin")
{
}
return 1;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1,2 @@
DE:Wanderender Wipf
US:Wandering Wipf