add new parkour aerobatics (sky race) (#1550)

objectmenu
Maikel de Vries 2016-01-23 14:43:46 +01:00
parent 4b68d82380
commit 7d46ab9f26
16 changed files with 832 additions and 0 deletions

View File

@ -0,0 +1,10 @@
Aerobatik
High up in the skies a challenge awaits! Move from island to island by jumping, blasting yourself, flying, catapulting, constructing bridges, or your imagination. The first one to arrive on the final sky island wins this round.
Ziel: Wettrennen
Tipps:
- You can get items at the spawn points, the item reappears when it has been used.
- More powerful tools can be produced at the inventor's lab if you find the resources.
- The use of the wind bag is limited, the number of available wind bursts is shown in the HUD.

View File

@ -0,0 +1,10 @@
Aerobatics
High up in the skies a challenge awaits! Move from island to island by jumping, blasting yourself, flying, catapulting, constructing bridges, or your imagination. The first one to arrive on the final sky island wins this round.
Goal: Race
Hints:
- You can get items at the spawn points, the item reappears when it has been used.
- More powerful tools can be produced at the inventor's lab if you find the resources.
- The use of the wind bag is limited, the number of available wind bursts is shown in the HUD.

View File

@ -0,0 +1,3 @@
[DefCore]
id=ItemSpawn
Category=C4D_StaticBack | C4D_Environment

View File

@ -0,0 +1,125 @@
/**
Item Spawn
If the clonk moves through the spawn it automatically get the item.
@author Maikel
*/
public func Create(id def, int x, int y)
{
if (this != ItemSpawn)
return;
var spawn = CreateObject(ItemSpawn, x, y);
AddEffect("ProcessSpawn", spawn, 100, 1, spawn, nil, def);
return spawn;
}
public func InitializePlayer(int plr)
{
var spawn_effect = GetEffect("ProcessSpawn", this);
if (spawn_effect)
EffectCall(this, spawn_effect, "AddPlayer", plr);
return;
}
public func RemovePlayer(int plr)
{
var spawn_effect = GetEffect("ProcessSpawn", this);
if (spawn_effect)
EffectCall(this, spawn_effect, "RemovePlayer", plr);
return;
}
/*-- Spawn Effect --*/
public func FxProcessSpawnStart(object target, proplist effect, int temp, id def)
{
if (temp)
return FX_OK;
effect.spawn_id = def;
effect.spawn_list = [];
effect.graphic_list = [];
for (var plr in GetPlayers())
{
var plrid = GetPlayerID();
effect.graphic_list[plrid] = CreateObject(Dummy, 0, 0, plr);
effect.graphic_list[plrid].Visibility = VIS_Owner;
effect.graphic_list[plrid]->SetGraphics(nil, effect.spawn_id, GFX_Overlay, GFXOV_MODE_Base);
}
return FX_OK;
}
public func FxProcessSpawnAddPlayer(object target, proplist effect, int add_plr)
{
var plrid = GetPlayerID(add_plr);
effect.graphic_list[plrid] = CreateObject(Dummy, 0, 0, add_plr);
effect.graphic_list[plrid].Visibility = VIS_Owner;
effect.graphic_list[plrid]->SetGraphics(nil, effect.spawn_id, GFX_Overlay, GFXOV_MODE_Base);
return FX_OK;
}
public func FxProcessSpawnRemovePlayer(object target, proplist effect, int remove_plr)
{
var plrid = GetPlayerID(remove_plr);
if (effect.graphic_list[plrid])
effect.graphic_list[plrid]->RemoveObject();
if (effect.spawn_list[plrid])
effect.spawn_list[plrid].item = nil;
return FX_OK;
}
public func FxProcessSpawnTimer(object target, proplist effect, int time)
{
// Produce some particles for the spawn ring.
if (time % 30 == 0)
{
var spawn_particle =
{
Size = PV_Linear(24, 36),
Alpha = PV_Linear(0, 255),
R = PV_Random(200, 255),
G = PV_Random(200, 255),
B = PV_Random(200, 255)
};
CreateParticle("MagicRing", 0, 0, 0, 0, 60, spawn_particle, 1);
}
// Update item availability for all active players.
if (time % 10 == 0)
{
for (var plr in GetPlayers())
{
var plrid = GetPlayerID();
if (effect.spawn_list[plrid] && !effect.spawn_list[plrid].item && effect.graphic_list[plrid].Visibility == VIS_None)
effect.graphic_list[plrid].Visibility = VIS_Owner;
}
}
// Check for crew members near the item spawn and give the item.
for (var crew in FindObjects(Find_OCF(OCF_CrewMember), Find_Distance(20)))
{
var plrid = GetPlayerID(crew->GetOwner());
if (effect.spawn_list[plrid] == nil)
effect.spawn_list[plrid] = {};
if (!effect.spawn_list[plrid].item)
{
if (crew->ContentsCount() < crew.MaxContentsCount)
{
var spawned = crew->CreateContents(effect.spawn_id);
effect.spawn_list[plrid].item = spawned;
effect.graphic_list[plrid].Visibility = VIS_None;
}
}
}
return FX_OK;
}
public func FxProcessSpawnStop(object target, proplist effect, int reason, bool temp)
{
if (temp)
return FX_OK;
return FX_OK;
}

View File

@ -0,0 +1,148 @@
/**
Aerobatics
A map with lots of small sky islands forming a parkour sequence.
@author Maikel
*/
#include Library_Map
static checkpoint_locations;
static inventorslab_location;
// Called be the engine: draw the complete map here.
public func InitializeMap(proplist map)
{
// Initialize a list for checkpoint locations.
checkpoint_locations = [];
// Determine the number of checkpoints.
var nr_checkpoints = BoundBy(SCENPAR_NrCheckPoints, 6, 20);
// Set the map size: depends on game mode and number of checkpoints.
var map_wdt = 140 + nr_checkpoints * 6;
var map_hgt = map_wdt / 2;
if (SCENPAR_GameMode == 2)
map_wdt *= 2;
map->Resize(map_wdt, map_hgt);
// Draw the start platform
DrawStartFinishIsland(map, map.Wdt / 5, map.Hgt / 2 - 2);
PushBack(checkpoint_locations, [map.Wdt / 5, map.Hgt / 2 - 2]);
// Find the checkpoint locations: substract the finish from the number of checkpoints.
var checkpoint_islands = FindCheckPointLocations(map, nr_checkpoints - 1);
// Store the locations in the list and draw the islands.
for (var index = 0; index < GetLength(checkpoint_islands); index++)
{
var cp_island = checkpoint_islands[index];
PushBack(checkpoint_locations, [cp_island.X, cp_island.Y]);
DrawCheckpointIsland(map, cp_island.X, cp_island.Y, index >= GetLength(checkpoint_islands) - 1 - Random(2));
}
// Draw the finish platform.
DrawStartFinishIsland(map, 4 * map.Wdt / 5, map.Hgt / 2 - 2);
PushBack(checkpoint_locations, [4 * map.Wdt / 5, map.Hgt / 2 - 2]);
// Draw a platform for the inventor's lab.
DrawStartFinishIsland(map, map.Wdt / 2, map.Hgt / 2 - 2);
inventorslab_location = [map.Wdt / 2, map.Hgt / 2 - 2];
// Draw other smaller islands.
DrawSmallIslands(map, checkpoint_locations);
// Return true to tell the engine a map has been successfully created.
return true;
}
public func DrawStartFinishIsland(proplist map, int x, int y)
{
var island = {Algo = MAPALGO_Rect, X = x - 7, Y = y, Wdt = 15, Hgt = 8};
island = {Algo = MAPALGO_Or, Op = [island, {Algo = MAPALGO_Turbulence, Amplitude = 6, Scale = 6, Op = island}]};
island = {Algo = MAPALGO_And, Op = [island, {Algo = MAPALGO_Not, Op = {Algo = MAPALGO_Rect, X = x - 6, Y = y - 5, Wdt = 13, Hgt = 5}}]};
island = {Algo = MAPALGO_And, Op = [island, {Algo = MAPALGO_Not, Op = {Algo = MAPALGO_Rect, X = x - 9, Y = y - 5, Wdt = 17, Hgt = 4}}]};
Draw("Earth", island);
DrawMaterial("Firestone", island, 2, 10);
DrawMaterial("Rock", island, 2, 25);
var brick = {Algo = MAPALGO_Rect, X = x - 5, Y = y, Wdt = 11, Hgt = 4};
Draw("Brick", brick);
return;
}
public func FindCheckPointLocations(proplist map, int nr_checkpoints)
{
// Prepare a mask out of the map.
var mask = map->CreateLayer();
mask->Draw("Rock");
// Remove the start, finish and middle island from the mask.
mask->Draw("Tunnel", {Algo = MAPALGO_Ellipsis, X = map.Wdt / 5, Y = map.Hgt / 2, Wdt = 38, Hgt = 38});
mask->Draw("Tunnel", {Algo = MAPALGO_Ellipsis, X = 4 * map.Wdt / 5, Y = map.Hgt / 2, Wdt = 38, Hgt = 38});
mask->Draw("Tunnel", {Algo = MAPALGO_Ellipsis, X = map.Wdt / 2, Y = map.Hgt / 2, Wdt = 38, Hgt = 38});
// Remove the middle area between start and finish from the mask.
mask->Draw("Tunnel", {Algo = MAPALGO_Rect, X = map.Wdt / 5, Y = map.Hgt / 2 - 16, Wdt = 3 * map.Wdt / 5, Hgt = 16});
// Array for the checkpoint islands.
var checkpoint_islands = [];
// Add checkpoint islands at random locations around the map.
var border = 10;
var cp_dist = 28;
for (var i = 0; i < nr_checkpoints; i++)
{
var cp_island = {};
if (!mask->FindPosition(cp_island, "Rock", [border, border, map.Wdt - border * 2, map.Hgt - border * 2]))
{
Log("WARNING: Map script could not find a suitable checkpoint location, there will be one checkpoint less in this round.");
continue;
}
mask->Draw("Tunnel", {Algo = MAPALGO_Ellipsis, X = cp_island.X, Y = cp_island.Y, Wdt = cp_dist, Hgt = cp_dist});
PushBack(checkpoint_islands, cp_island);
}
return checkpoint_islands;
}
public func DrawCheckpointIsland(proplist map, int x, int y, bool enclosed)
{
var island = {Algo = MAPALGO_Rect, X = x - 4, Y = y, Wdt = 9, Hgt = 6};
island = {Algo = MAPALGO_Or, Op = [island, {Algo = MAPALGO_Turbulence, Seed = Random(65536), Amplitude = 8, Scale = 8, Op = island}]};
island = {Algo = MAPALGO_And, Op = [island, {Algo = MAPALGO_Not, Op = {Algo = MAPALGO_Rect, X = x - 4, Y = y - 5, Wdt = 9, Hgt = 5}}]};
Draw("Earth", island);
DrawMaterial("Firestone", island, 2, 10);
DrawMaterial("Rock", island, 2, 25);
var brick = {Algo = MAPALGO_Rect, X = x - 2, Y = y, Wdt = 5, Hgt = 2};
Draw("Brick", brick);
// Trap the checkpoint in rock / granite if it must be enclosed.
if (enclosed)
{
var border = {Algo = MAPALGO_Ellipsis, X = x, Y = y - 3, Wdt = 7, Hgt = 7};
border = {Algo = MAPALGO_Border, Op = border, Wdt = 2};
border = {Algo = MAPALGO_And, Op = [border, {Algo = MAPALGO_Not, Op = island}]};
Draw("Granite", border);
DrawMaterial("Rock", border, 2, 20);
}
return;
}
public func DrawSmallIslands(proplist map, array checkpoints)
{
// Prepare a mask out of the checkpoint positions.
var mask = {Algo = MAPALGO_Rect, X = 0, Y = 0, Wdt = 0, Hgt = 0};
var island_border = 16;
var map_border = 6;
// Remove checkpoints and middle area from mask.
for (var cp in checkpoints)
mask = {Algo = MAPALGO_Or, Op = [mask, {Algo = MAPALGO_Ellipsis, X = cp[0], Y = cp[1], Wdt = island_border, Hgt = island_border}]};
mask = {Algo = MAPALGO_Or, Op = [mask, {Algo = MAPALGO_Rect, X = map.Wdt / 5, Y = map.Hgt / 2 - 16, Wdt = 3 * map.Wdt / 5, Hgt = 16}]};
mask = {Algo = MAPALGO_Not, Op = mask};
mask = {Algo = MAPALGO_And, Op = [mask, {Algo = MAPALGO_Rect, X = map_border, Y = map_border, Wdt = map.Wdt - 2 * map_border, Hgt = map.Hgt - 2 * map_border}]};
var islands = {Algo = MAPALGO_RndChecker, Seed = Random(65536), Ratio = 4, Wdt = 4, Hgt = 3};
islands = {Algo = MAPALGO_And, Op = [islands, mask]};
islands = {Algo = MAPALGO_Or, Op = [islands, {Algo = MAPALGO_Turbulence, Seed = Random(65536), Amplitude = 6, Scale = 6, Op = islands}]};
Draw("Earth", islands);
DrawMaterial("Firestone", islands, 2, 10);
DrawMaterial("Rock", islands, 2, 25);
DrawMaterial("Ore", islands, 2, 5);
DrawMaterial("Granite", islands, 2, 5);
return;
}

View File

@ -0,0 +1,47 @@
[ParameterDef]
Name=$ScenParNrCheckPoint$
Description=$ScenParNrCheckPointDesc$
ID=NrCheckPoints
Default=8
[Options]
[Option]
Name=6
Value=6
[Option]
Name=8
Value=8
[Option]
Name=10
Value=10
[Option]
Name=12
Value=12
[Option]
Name=16
Value=16
[Option]
Name=20
Value=20
[ParameterDef]
Name=$ScenParGameMode$
Description=$ScenParGameModeDesc$
ID=GameMode
Default=1
[Options]
[Option]
Name=$ScenParGameModeZigZag$
Value=1
#[Option]
#Name=$ScenParGameModeHorizontal$
#Value=2

View File

@ -0,0 +1,26 @@
[Head]
Icon=28
Title=Aerobatics
Version=7,0
Difficulty=80
[Definitions]
Definition1=Objects.ocd
Definition2=Decoration.ocd
[Player1]
Crew=Clonk=1
[Player2]
Crew=Clonk=1
[Player3]
Crew=Clonk=1
[Player4]
Crew=Clonk=1
[Landscape]
BottomOpen=1
Sky=Clouds2
SkyScrollMode=2

View File

@ -0,0 +1,288 @@
/**
Aerobatics
Several small sky islands form a chaotic parkour with lots of usable and respawning items.
TODO:
horizontal mode with large map
reset player cp completion to killer (idea)
@author Maikel
*/
static checkpoint_locations;
static inventorslab_location;
protected func Initialize()
{
// Create the parkour goal.
var goal = CreateObject(Goal_Parkour);
goal->TransferContentsOnRelaunch(true);
// Iterate over checkpoint list and create the checkpoints.
// Also add items spawns close to the checkpoints.
var map_zoom = GetScenarioVal("MapZoom", "Landscape");
for (var index = 0; index < GetLength(checkpoint_locations); index++)
{
var cp = checkpoint_locations[index];
var x = map_zoom * cp[0] + map_zoom / 2;
var y = map_zoom * cp[1] + map_zoom / 2 - 20;
if (index == 0)
{
goal->SetStartpoint(x, y);
ItemSpawn->Create(Dynamite, x - 30, y);
ItemSpawn->Create(Loam, x + 30, y);
continue;
}
if (index == GetLength(checkpoint_locations) - 1)
{
goal->SetFinishpoint(x, y);
ItemSpawn->Create(Balloon, x + 30, y);
continue;
}
var mode = PARKOUR_CP_Check | PARKOUR_CP_Ordered | PARKOUR_CP_Respawn | PARKOUR_CP_Bonus;
goal->AddCheckpoint(x - 10, y, mode);
var spawn_items = [Dynamite, Loam, DynamiteBox, IronBomb, Javelin];
ItemSpawn->Create(spawn_items[Random(Min(index, GetLength(spawn_items)))], x + 20, y);
}
// Rules.
CreateObject(Rule_NoPowerNeed);
// Initialize parts of the scenario.
var amount = BoundBy(SCENPAR_NrCheckPoints, 6, 20);
InitMaterials(amount);
InitEnvironment(amount);
InitVegetation(amount);
InitAnimals(amount);
// Start the intro sequence.
StartSequence("Intro", 0);
return;
}
private func InitMaterials(int amount)
{
PlaceObjects(Dynamite, 4 * amount, "Earth");
PlaceObjects(Loam, 4 * amount, "Earth");
PlaceObjects(Metal, 2 * amount, "Earth");
// Place chests on several of the sky islands.
for (var count = 0; count < amount / 2; count++)
{
var pos = FindIslandLocation();
if (!pos)
continue;
var chest = CreateObjectAbove(Chest, pos.x, pos.y);
chest->CreateContents(Dynamite, 4);
chest->CreateContents(Club);
chest->CreateContents(Musket)->CreateContents(LeadShot);
chest->CreateContents(Bow)->CreateContents(Arrow);
chest->CreateContents(Bread, 2);
chest->CreateContents(IronBomb);
chest->CreateContents(Cloth);
chest->CreateContents(Pickaxe);
if (!Random(2))
chest->CreateContents(GrenadeLauncher)->CreateContents(IronBomb);
if (!Random(2))
chest->CreateContents(Boompack);
if (!Random(2))
chest->CreateContents(WallKit);
if (!Random(2))
chest->CreateContents(TeleGlove);
}
// Place some catapults.
for (var count = 0; count < amount / 4; count++)
{
var pos = FindIslandLocation();
if (pos)
CreateObjectAbove(Catapult, pos.x, pos.y);
}
// Place some cannons.
for (var count = 0; count < amount / 4; count++)
{
var pos = FindIslandLocation();
if (pos)
{
var cannon = CreateObjectAbove(Cannon, pos.x, pos.y);
cannon->CreateContents(PowderKeg, 1);
}
}
// Place some ropeladders.
for (var count = 0; count < 2; count++)
{
var pos = FindLocation(Loc_Sky(), Loc_Wall(CNAT_Top));
if (!pos)
continue;
CreateObject(Ropeladder, pos.x, pos.y)->Unroll(-1, COMD_Up);
}
// An inventor's lab on its island.
var map_zoom = GetScenarioVal("MapZoom", "Landscape");
var lab = CreateObjectAbove(InventorsLab, inventorslab_location[0] * map_zoom, inventorslab_location[1] * map_zoom);
lab->MakeInvincible();
return;
}
private func FindIslandLocation()
{
var pos;
for (var tries = 0; tries < 100; tries++)
{
pos = FindLocation(Loc_Sky(), Loc_Wall(CNAT_Bottom));
if (!pos)
continue;
if (FindObject(Find_Category(C4D_Vehicle), Find_Distance(30, pos.x, pos.y)))
continue;
break;
}
return pos;
}
private func InitEnvironment(int amount)
{
for (var count = 0; count < amount / 2; count++)
{
var pos = FindLocation(Loc_Sky(), Loc_Space(40), Loc_InRect(100, 100, LandscapeWidth() - 200, LandscapeHeight() - 200));
if (!pos)
return;
AddEffect("WindStream", nil, 100, 1, nil, nil, RandomX(-10, 10), pos.x, pos.y);
}
return;
}
private func InitVegetation(int amount)
{
Grass->Place(100);
Branch->Place(3 * amount);
Mushroom->Place(amount);
Fern->Place(amount);
Flower->Place(3 * amount / 2);
Tree_Deciduous->Place(amount);
Tree_Coniferous2->Place(amount / 4);
Tree_Coniferous3->Place(amount / 4);
Cotton->Place(amount / 2);
return;
}
private func InitAnimals(int amount)
{
Butterfly->Place(amount);
Mosquito->Place(amount / 2);
Zaphive->Place(amount / 4);
return;
}
/*-- Player Control --*/
protected func InitializePlayer(int plr)
{
// Make the player enemy to all other players.
Goal_Melee->MakeHostileToAll(plr, GetPlayerTeam(plr));
// Set large zoom ranges for the player.
SetPlayerZoomByViewRange(plr, 1200, nil, PLRZOOM_LimitMax);
// Give the player knowledge for items in the inventor's lab.
SetPlrKnowledge(plr, WindBag);
SetPlrKnowledge(plr, WallKit);
return;
}
public func OnPlayerRespawn(int plr, object cp)
{
var crew = GetCrew(plr);
if (!crew)
return;
// Ensure at least a shovel, loam and dynamite on respawn when items not present and there is space in inventory.
if (!FindObject(Find_ID(Shovel), Find_Container(crew)) && crew->ContentsCount() < crew.MaxContentsCount)
crew->CreateContents(Shovel);
if (!FindObject(Find_ID(Loam), Find_Container(crew)) && crew->ContentsCount() < crew.MaxContentsCount)
crew->CreateContents(Loam);
if (!FindObject(Find_ID(Dynamite), Find_Container(crew)) && crew->ContentsCount() < crew.MaxContentsCount)
crew->CreateContents(Dynamite);
// Give the crew more HP, so that it can survive more flint jumps.
crew.MaxEnergy = 80000;
crew->DoEnergy(crew.MaxEnergy / 1000);
return;
}
// Give the player a bonus when he reaches a new checkpoint for the first time and is behind the leader.
public func GivePlrBonus(int plr, object cp)
{
var crew = GetCrew(plr);
if (!crew)
return;
var goal = cp->GetCPController();
if (!goal)
return;
var cp_behind = goal->GetLeaderClearedCheckpoints() - goal->GetPlayerClearedCheckpoints(plr);
if (cp_behind <= 2)
return;
var windbag = FindObject(Find_ID(WindBag), Find_Container(crew));
if (windbag)
{
windbag->SetUsageCount(windbag->GetUsageCount() + cp_behind);
}
else
{
if (crew->ContentsCount() < crew.MaxContentsCount)
windbag = crew->CreateContents(WindBag);
else
windbag = CreateObjectAbove(WindBag, cp->GetX(), cp->GetY() + cp->GetBottom(), plr);
windbag->SetUsageCount(2 * cp_behind);
}
return;
}
/*-- Wind Streams --*/
global func FxWindStreamStart(object target, effect, int temp, angle, x, y)
{
if (temp)
return FX_OK;
effect.xdir = Sin(angle, 32);
effect.ydir = -Cos(angle, 32);
effect.x = x + Sin(angle, 43);
effect.y = y - Cos(angle, 43);
effect.particles =
{
Prototype = Particles_Air(),
Size = PV_Random(2, 5)
};
return FX_OK;
}
global func FxWindStreamTimer(object target, proplist effect, int time)
{
var xdir = effect.xdir;
var ydir = effect.ydir;
var x = effect.x;
var y = effect.y;
if(time<36)
{
var r=Random(360);
var d=Random(40);
CreateParticle("Air", Sin(r,d)+x,-Cos(r,d)+y, xdir/3, ydir/3, PV_Random(10, 30), effect.particles, 1);
return FX_OK;
}
CreateParticle("Air", PV_Random(x - 20, x + 20), PV_Random(y - 20, y + 20), xdir/2, ydir/2, PV_Random(10, 30), effect.particles, 5);
for(var obj in FindObjects(Find_Distance(40,x,y), Find_Not(Find_Category(C4D_Structure)), Find_Layer()))
{
if(PathFree(x,y,obj->GetX(),obj->GetY()))
{
if(xdir<0)
{if(obj->GetXDir() > xdir) obj->SetXDir(obj->GetXDir(100) + (xdir*3)/2,100); }
else
{if(obj->GetXDir() < xdir) obj->SetXDir(obj->GetXDir(100) + (xdir*3)/2,100); }
if(ydir<0)
{if(obj->GetYDir() > ydir) obj->SetYDir(obj->GetYDir(100) + (ydir*3)/2,100); }
else
{if(obj->GetYDir() < ydir) obj->SetYDir(obj->GetYDir(100) + (ydir*3)/2,100); }
}
}
return FX_OK;
}

View File

@ -0,0 +1,9 @@
# Scenario option: number of checkpoints
ScenParNrCheckPoint=Number of checkpoints
ScenParNrCheckPointDesc=Choose the number of checkpoints for this round, the map size and round duration will increase with this number.
# Scenario option: mode
ScenParGameMode=Mode
ScenParGameModeDesc=Game mode: whether the checkpoints are ordered (horizontal) or the players must go back and forth (zig zag).
ScenParGameModeZigZag=Zig Zag
ScenParGameModeHorizontal=Horizontal

View File

@ -0,0 +1,9 @@
# Scenario option: number of checkpoints
ScenParNrCheckPoint=Number of checkpoints
ScenParNrCheckPointDesc=Choose the number of checkpoints for this round, the map size and round duration will increase with this number.
# Scenario option: mode
ScenParGameMode=Mode
ScenParGameModeDesc=Game mode: whether the checkpoints are ordered (horizontal) or the players must go back and forth (zig zag).
ScenParGameModeZigZag=Zig Zag
ScenParGameModeHorizontal=Horizontal

View File

@ -0,0 +1,91 @@
// Intro sequence for Aerobatics: Host tells you about the game.
#appendto Sequence
public func Intro_Start()
{
this.airship = CreateObjectAbove(Airship, LandscapeWidth() / 4 + 40, LandscapeHeight() / 2 - 40);
this.host = CreateObjectAbove(Clonk, LandscapeWidth() / 4 + 40, LandscapeHeight() / 2 - 50);
this.host->SetAlternativeSkin("Mime");
this.host->SetName("Mr. Aerobat");
this.host->SetDir(DIR_Left);
this.airship->SetObjectLayer(this.host);
this.host->SetObjectLayer(this.host);
return ScheduleNext(4);
}
public func Intro_JoinPlayer(int plr)
{
SetPlayerZoomByViewRange(plr, 300, nil, PLRZOOM_Set);
var crew = GetCrew(plr);
crew->SetPosition(crew->GetX() + RandomX(-10, 10), crew->GetY());
return;
}
public func Intro_1()
{
// Display intro message for all players.
MessageBoxAll("$MsgLetAerobaticsBegin$", this.host, true);
return ScheduleNext(12);
}
public func Intro_2()
{
AddEffect("IntroControlAirship", nil, 100, 5, nil, this->GetID(), this.airship, this.host);
return ScheduleNext(12);
}
public func Intro_3()
{
// Add a countdown for this attempt.
GUI_Clock->CreateCountdown(10);
return ScheduleNext(10 * 36);
}
public func Intro_4()
{
return Stop();
}
public func Intro_Stop()
{
// Reset player zoom.
SetPlayerZoomByViewRange(NO_OWNER, 600, nil, PLRZOOM_Set);
return true;
}
public func FxIntroControlAirshipStart(object target, proplist effect, int temp, object airship, object host)
{
if (temp)
return FX_OK;
effect.airship = airship;
effect.host = host;
effect.host->SetCommand("Grab", effect.airship);
effect.airship->ControlRight(effect.host);
effect.state = 1;
return FX_OK;
}
public func FxIntroControlAirshipTimer(object target, proplist effect, int time)
{
if (effect.state == 1 && effect.host->GetX() > 4 * LandscapeWidth() / 5 - 30)
{
effect.airship->ControlStop(effect.host);
effect.airship->ControlDown(effect.host);
effect.state = 2;
}
if (effect.state == 2 && effect.airship->GetContact(-1, CNAT_Bottom))
{
effect.airship->ControlStop(effect.host);
return FX_Execute_Kill;
}
return FX_OK;
}
public func FxIntroControlAirshipStop(object target, proplist effect, int reason, bool temp)
{
if (temp)
return FX_OK;
effect.host->SetCommand("UnGrab");
return FX_OK;
}

View File

@ -0,0 +1,5 @@
# Intro sequence messages
MsgLetAerobaticsBegin=Dear contestants, in this challenge you will need to take some risks to win. Dig, climb, jump or blast yourself from island to island and be the first to meet me at the finish. Let the aerobatics begin!
# Wind bag description
MsgWindBagUsageCount=In this round you can only use the wind bag a limited number of times.

View File

@ -0,0 +1,5 @@
# Intro sequence messages
MsgLetAerobaticsBegin=Dear contestants, in this challenge you will need to take some risks to win. Dig, climb, jump or blast yourself from island to island and be the first to meet me at the finish. Let the aerobatics begin!
# Wind bag description
MsgWindBagUsageCount=In this round you can only use the wind bag a limited number of times.

View File

@ -0,0 +1,5 @@
// Make wall kit producible in the inventor's lab.
#appendto WallKit
public func IsInventorProduct() { return true; }

View File

@ -0,0 +1,49 @@
// Restrict amount of usages with the windbag.
#appendto WindBag
local usage_count;
protected func Initialize()
{
this.Description = Format("%s %s", this.Description, "$MsgWindBagUsageCount$");
SetUsageCount(10);
return _inherited(...);
}
public func SetUsageCount(int count)
{
usage_count = BoundBy(count, 1, 99);
if (Contained())
Contained()->~OnInventoryChange();
return;
}
public func GetUsageCount() { return usage_count; }
private func BlastWind(object clonk, int x, int y)
{
usage_count--;
clonk->~OnInventoryChange();
return _inherited(clonk, x, y, ...);
}
public func FxIntBurstWindStop(object target, proplist effect, int reason, bool temp)
{
var result = _inherited(target, effect, reason, temp, ...);
if (!temp)
{
if (usage_count <= 0)
RemoveObject();
}
return result;
}
// Display the remaining amount of usages.
public func GetInventoryIconOverlay()
{
return {Left = "40%", Bottom = "50%",
tens = {Right = "60%", Symbol = Icon_Number, GraphicsName = Format("%d", usage_count / 10)},
ones = {Left = "40%", Symbol = Icon_Number, GraphicsName = Format("%d", usage_count % 10)},
};
}

View File

@ -0,0 +1,2 @@
DE:Aerobatik
US:Aerobatics