openclonk/planet/Worlds.ocf/Chine.ocs/Script.c

254 lines
7.1 KiB
C
Raw Normal View History

2014-09-21 16:37:48 +00:00
/**
2014-09-22 17:20:15 +00:00
Chine
A chine with a large waterfall and lots of vegetation.
2014-09-21 16:37:48 +00:00
@author Maikel
*/
2014-09-26 20:08:19 +00:00
// Whether the intro has been initialized.
static intro_init;
2014-09-21 16:37:48 +00:00
protected func Initialize()
{
2015-12-26 22:15:38 +00:00
// Show wealth in HUD.
GUI_Controller->ShowWealth();
2014-09-21 16:37:48 +00:00
// Rules: team account and buying at flagpole.
CreateObject(Rule_TeamAccount);
CreateObject(Rule_BuyAtFlagpole);
2014-09-22 17:20:15 +00:00
// Goal: transport the cannon to the top of the chine.
var cannon = CreateObjectAbove(Cannon, 96 + RandomX(-12, 12), LandscapeHeight() - 92);
var keg = cannon->CreateContents(PowderKeg);
// Infinite ammo for this cannon.
keg->SetPowderCount(nil);
var cannon_goal = CreateObject(Goal_Script);
2014-09-22 17:20:15 +00:00
cannon_goal.Name = "$GoalName$";
cannon_goal.Description = "$GoalDesc$";
cannon_goal.Picture = Chine_GoalIcon;
2014-09-22 17:20:15 +00:00
// Add an effect to check whether the goal is fulfilled.
AddEffect("GoalCheck", nil, 100, 2, nil);
2014-09-21 16:37:48 +00:00
// Initialize different parts of the scenario.
2014-09-28 08:56:32 +00:00
InitEnvironment(SCENPAR_MapSize, SCENPAR_Difficulty);
InitVegetation(SCENPAR_MapSize, SCENPAR_Difficulty);
InitAnimals(SCENPAR_Difficulty);
InitMaterial(4 - SCENPAR_Difficulty);
2014-09-21 16:37:48 +00:00
return;
}
2014-09-26 17:32:43 +00:00
protected func OnGoalsFulfilled()
{
// Give the remaining players their achievement.
GainScenarioAchievement("Done", BoundBy(SCENPAR_Difficulty, 1, 3));
return false;
}
2014-09-21 16:37:48 +00:00
/*-- Player Initialization --*/
protected func InitializePlayer(int plr)
{
2014-09-22 17:20:15 +00:00
// Harsh zoom range.
2014-09-28 08:56:32 +00:00
SetPlayerZoomByViewRange(plr, LandscapeWidth(), nil, PLRZOOM_Direct | PLRZOOM_LimitMax);
2014-09-22 17:20:15 +00:00
SetPlayerViewLock(plr, true);
2014-09-21 16:37:48 +00:00
// Move clonks to location and give them a shovel.
var index = 0, crew;
while (crew = GetCrew(plr, index))
{
2014-09-22 17:20:15 +00:00
crew->SetPosition(96 + RandomX(-12, 12), LandscapeHeight() - 92);
var u = 0;
while(crew->Stuck())
{
crew->SetPosition(crew->GetX(), crew->GetY()-1);
++u;
if (u > 50) // This is bad, the clonk will most likely die
break;
}
2014-09-21 16:37:48 +00:00
// First clonk can construct, others can chop.
if (index == 0)
{
crew->CreateContents(Shovel);
crew->CreateContents(Pickaxe);
}
else
{
crew->CreateContents(Axe);
crew->CreateContents(Hammer);
}
index++;
}
// Give the player basic knowledge.
GivePlayerBasicKnowledge(plr);
GivePlayerSpecificKnowledge(plr, [InventorsLab, Ropeladder, MetalBarrel, PowderKeg, GrappleBow]);
// Give the player the elementary base materials and some tools.
GivePlayerElementaryBaseMaterial(plr);
GivePlayerToolsBaseMaterial(plr);
// Additional explosives: dynamite boxes.
GivePlayerSpecificBaseMaterial(plr, [[DynamiteBox, 4, 2]]);
2014-09-26 20:08:19 +00:00
// Ensure mimimum player wealth.
var add_wealth = Max(0, 75 - 25 * SCENPAR_Difficulty - GetWealth(plr));
DoWealth(plr, add_wealth);
2014-09-26 20:08:19 +00:00
// Initialize the intro sequence if not yet started.
if (!intro_init)
{
StartSequence("Intro", 0);
intro_init = true;
}
2014-09-21 16:37:48 +00:00
return;
}
2014-09-22 17:20:15 +00:00
/*-- Goal Check --*/
global func FxGoalCheckTimer(object target, proplist effect)
{
var cannon = FindObject(Find_ID(Cannon));
if (!cannon)
{
2014-09-26 17:32:43 +00:00
// Start elimination sequence due to lost cannon.
// TODO: determine clonk which was responsible and let him take the blame in the sequence.
StartSequence("Failure", 0);
2014-09-22 17:20:15 +00:00
return -1;
}
if (cannon->GetY() < 100)
{
var goal = FindObject(Find_ID(Goal_Script));
if (goal)
goal->Fulfill();
return -1;
}
return 1;
}
2014-09-21 16:37:48 +00:00
/*-- Scenario Initialization --*/
2014-09-28 08:56:32 +00:00
private func InitEnvironment(int map_size, int difficulty)
2014-09-21 16:37:48 +00:00
{
// Adjust the sky a bit.
SetSkyParallax(0, 20, 20);
2014-09-22 17:20:15 +00:00
SetSkyAdjust(RGBa(225, 255, 205, 191), RGB(63, 200, 0));
2014-09-21 16:37:48 +00:00
2014-09-28 08:56:32 +00:00
// Waterfalls dominate the landscape, they are place at the top left of the chine.
var waterfall_x = 0;
while (!GBackSky(waterfall_x, 0) && waterfall_x < LandscapeWidth() / 2)
waterfall_x++;
2014-09-26 20:08:19 +00:00
for (var i = 0; i < 16 + 4 * difficulty; i++)
2014-09-21 16:37:48 +00:00
{
2014-09-28 08:56:32 +00:00
var fall = CreateWaterfall(waterfall_x + 2, 0, RandomX(3, 4), "Water");
2018-03-13 19:37:46 +00:00
fall->SetDirection(RandomX(14, 16), 12, 4, 4);
2014-09-22 17:20:15 +00:00
fall->SetSoundLocation(LandscapeWidth() / 2, Random(LandscapeHeight()));
}
var trunk = CreateObjectAbove(Trunk, waterfall_x + 2, 20);
2014-09-28 08:56:32 +00:00
trunk->SetR(-30); trunk.Plane = 550;
trunk->MakeInvincible();
2014-09-28 08:56:32 +00:00
2014-09-22 17:20:15 +00:00
// Cast some additional PXS at the start at random locations.
2014-09-28 08:56:32 +00:00
for (var i = 0; i < 20000 + 10000 * map_size; i++)
2014-09-22 17:20:15 +00:00
InsertMaterial(Material("Water"), Random(LandscapeWidth()), Random(5 * LandscapeHeight() / 6), RandomX(-5, 5), RandomX(3, 6));
// Some natural disasters.
Earthquake->SetChance(2 + 2 * difficulty);
2014-10-03 12:37:27 +00:00
if (difficulty >= 2)
Rockfall->SetChance(20);
if (difficulty >= 3)
{
2014-10-03 12:37:27 +00:00
Rockfall->SetChance(80);
Rockfall->SetExplosiveness(15);
}
Rockfall->SetSpawnDistance(250);
Rockfall->SetArea(Shape->Rectangle(128, 0, 128, LandscapeHeight() - 300));
2014-09-21 16:37:48 +00:00
return;
}
2014-09-28 08:56:32 +00:00
private func InitVegetation(int map_size, int difficulty)
2014-09-21 16:37:48 +00:00
{
2014-09-22 17:20:15 +00:00
// Define parts of the map for even distribution.
var top = Shape->Rectangle(0, 0, LandscapeWidth(), LandscapeHeight() / 3);
var middle = Shape->Rectangle(0, LandscapeHeight() / 3, LandscapeWidth(), LandscapeHeight() / 3);
var bottom = Shape->Rectangle(0, 2 * LandscapeHeight() / 3, LandscapeWidth(), LandscapeHeight() / 3);
2014-09-22 17:20:15 +00:00
// Place gras wherever possible.
2014-09-21 16:37:48 +00:00
PlaceGrass(100);
2014-09-22 17:20:15 +00:00
// Place some cocont trees and cave mushrooms for wood.
for (var i = 0; i < 16 + Random(6); i++)
2014-09-22 17:20:15 +00:00
{
PlaceVegetation(Tree_Coconut, top.x, top.y, top.wdt, top.hgt, 1000 * (61 + Random(40)));
PlaceVegetation(Tree_Coconut, middle.x, middle.y, middle.wdt, middle.hgt, 1000 * (61 + Random(40)));
PlaceVegetation(Tree_Coconut, bottom.x, bottom.y, bottom.wdt, bottom.hgt, 1000 * (61 + Random(40)));
2014-09-22 17:20:15 +00:00
}
LargeCaveMushroom->Place(6, middle, { terraform = false });
LargeCaveMushroom->Place(6, bottom, { terraform = false });
2014-09-22 17:20:15 +00:00
// Place some bushes, ferns and mushrooms.
SproutBerryBush->Place(2, top);
SproutBerryBush->Place(2, middle);
SproutBerryBush->Place(2, bottom);
Fern->Place(20, top);
Fern->Place(20, middle);
Fern->Place(20, bottom);
2015-03-25 19:04:39 +00:00
Mushroom->Place(10, top);
Mushroom->Place(10, middle);
Mushroom->Place(10, bottom);
2014-09-22 17:20:15 +00:00
2015-01-06 23:04:30 +00:00
// Some branches and trunks.
Branch->Place(30 + 12 * map_size + Random(16));
Trunk->Place(6 + 2 * map_size + Random(5));
2014-09-21 16:37:48 +00:00
// Some objects in the earth.
2014-09-22 17:20:15 +00:00
PlaceObjects(Rock, 25 + 10 * map_size + Random(10),"Earth");
PlaceObjects(Firestone, 25 + 10 * map_size + Random(10), "Earth");
PlaceObjects(Loam, (6 + 2 * map_size) * (4 - difficulty) + Random(5), "Earth");
if (difficulty == 1)
PlaceObjects(Loam, 12, "Earth");
2014-09-21 16:37:48 +00:00
return;
}
2014-09-28 08:56:32 +00:00
private func InitAnimals(int difficulty)
2014-09-21 16:37:48 +00:00
{
2014-09-28 08:56:32 +00:00
// Place some fish or piranhas on the basin.
var fish = Fish;
if (difficulty >= 3)
fish = Piranha;
fish->Place(4);
2014-09-21 16:37:48 +00:00
return;
}
private func InitMaterial(int amount)
{
// No extra materials for little materials.
if (amount <= 1)
return;
// For medium amount of materials provide a lorry with resources.
if (amount >= 2)
{
var lorry = CreateObjectAbove(Lorry, 72 + RandomX(-12, 12), LandscapeHeight() - 92);
2014-09-21 16:37:48 +00:00
lorry->CreateContents(Wood, 6);
lorry->CreateContents(Metal, 4);
lorry->CreateContents(Rock, 4);
lorry->CreateContents(Dynamite, 4);
lorry->CreateContents(Loam, 4);
// For large amount of materials provide some buildings as well.
if (amount >= 3)
{
lorry->CreateContents(Wood, 6);
lorry->CreateContents(Metal, 4);
lorry->CreateContents(Rock, 4);
lorry->CreateContents(DynamiteBox, 4);
lorry->CreateContents(Ropeladder, 4);
}
}
return;
}