forked from Mirrors/openclonk
Experimental maze parkour scenario. Collect a ruby and return it to the start to win.
Crashes sometimes during map generation. Couldn't reproduce this in a debug build yet :(scancodes-fix
parent
c17c971b40
commit
f244efbc86
|
@ -0,0 +1,5 @@
|
|||
[DefCore]
|
||||
id=Goal_RubyHunt
|
||||
Version=5,2,0,1
|
||||
Category=C4D_StaticBack|C4D_Goal
|
||||
Picture=0,0,128,128
|
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
|
@ -0,0 +1,85 @@
|
|||
/*--
|
||||
Ruby hunt
|
||||
Author: Sven2
|
||||
|
||||
Mine one ruby and return to start
|
||||
--*/
|
||||
|
||||
|
||||
#include Library_Goal
|
||||
|
||||
local goal_rect, has_winner;
|
||||
|
||||
protected func Initialize()
|
||||
{
|
||||
return inherited(...);
|
||||
}
|
||||
|
||||
func SetGoalRect(r)
|
||||
{
|
||||
goal_rect = r;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*-- Goal interface --*/
|
||||
|
||||
// The goal is fulfilled if a ruby is in the goal rectangle
|
||||
public func IsFulfilled()
|
||||
{
|
||||
var winner=NO_OWNER, winners, winner_teams;
|
||||
if (has_winner) return true;
|
||||
for (var ruby in FindObjects(Find_InRect(goal_rect.x, goal_rect.y, goal_rect.w, goal_rect.h), Find_ID(Ruby)))
|
||||
{
|
||||
if (ruby->Contained()) winner = ruby->Contained()->GetOwner();
|
||||
if (winner==NO_OWNER) winner = ruby->GetController();
|
||||
if (winner==NO_OWNER) continue;
|
||||
if (!winners) winners = [winner]; else winners[GetLength(winners)] = winner;
|
||||
var team = GetPlayerTeam(winner);
|
||||
if (team) if (!winner_teams) winner_teams = [team]; else winner_teams[GetLength(winner_teams)] = team;
|
||||
}
|
||||
if (!winners) return false;
|
||||
has_winner = true;
|
||||
var iplr=GetPlayerCount();
|
||||
while (iplr--)
|
||||
{
|
||||
var plr = GetPlayerByIndex(iplr);
|
||||
if (GetIndexOf(winners, plr) >= 0) continue;
|
||||
if (winner_teams) if (GetIndexOf(winner_teams, GetPlayerTeam(plr)) >= 0) continue;
|
||||
EliminatePlayer(plr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Shows or hides a message window with information.
|
||||
public func Activate(int plr)
|
||||
{
|
||||
// If goal message open -> hide it.
|
||||
if (GetEffect("GoalMessage", this))
|
||||
{
|
||||
CustomMessage("", nil, plr, nil, nil, nil, nil, nil, MSG_HCenter);
|
||||
RemoveEffect("GoalMessage", this);
|
||||
return;
|
||||
}
|
||||
// Otherwise open a new message.
|
||||
AddEffect("GoalMessage", this, 100, 0, this);
|
||||
var message;
|
||||
if (IsFulfilled())
|
||||
message = "@$MsgGoalFulfilled$";
|
||||
else
|
||||
message = "@$MsgGoalUnfulfilled$";
|
||||
|
||||
CustomMessage(message, nil, plr, 0, 16 + 64, 0xffffff, GUI_MenuDeco, this, MSG_HCenter);
|
||||
return;
|
||||
}
|
||||
|
||||
protected func FxGoalMessageStart() {}
|
||||
|
||||
public func GetShortDescription(int plr)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
/*-- Proplist --*/
|
||||
|
||||
local Name = "$Name$";
|
|
@ -0,0 +1,4 @@
|
|||
Name=Rubinsuche
|
||||
#Goal window
|
||||
MsgGoalFulfilled=Ein Rubin wurde abgeliefert.
|
||||
MsgGoalUnfulfilled=Noch kein Rubin am Start.
|
|
@ -0,0 +1,5 @@
|
|||
Name=Sell gems
|
||||
|
||||
#Goal window
|
||||
MsgGoalFulfilled=A ruby has been delivered.
|
||||
MsgGoalUnfulfilled=Mine a ruby and deliver it to the starting platform.
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,79 @@
|
|||
/*--
|
||||
Cool Cavern
|
||||
Author: Maikel
|
||||
|
||||
Cavern with lots of snow, ice, rock and dirt.
|
||||
--*/
|
||||
|
||||
|
||||
// Randomly placed material specks according to rndchecker.
|
||||
overlay MatRC {
|
||||
algo=rndchecker; a=8;
|
||||
zoomX=-50; zoomY=-50;
|
||||
turbulence=100; loosebounds=1;
|
||||
};
|
||||
|
||||
// Fills an overlay with earth and materials.
|
||||
overlay MatFill {
|
||||
overlay { mat=Earth; tex=earth_dry; loosebounds=1; };
|
||||
MatRC { mat=Ore; tex=ore; a=20; };
|
||||
MatRC { mat=Snow; tex=snow1; a=20; };
|
||||
MatRC { mat=Granite; tex=granite; a=20; };
|
||||
MatRC { mat=Rock; tex=rock; a=20; };
|
||||
MatRC { mat=Ore; tex=ore; a=20; };
|
||||
MatRC { mat=Ice; tex=ice3; a=20; };
|
||||
MatRC { mat=Snow; tex=snow1; a=20; };
|
||||
MatRC { mat=Ice; tex=ice3; };
|
||||
MatRC { mat=Rock; tex=rock; };
|
||||
MatRC { mat=Tunnel; tex=tunnel; };
|
||||
MatRC { mat=Earth; tex=earth_dry; };
|
||||
MatRC { mat=Earth; tex=earth_rough; };
|
||||
overlay {
|
||||
algo=lines; a=3; b=16;
|
||||
rotate=45;
|
||||
turbulence=100;
|
||||
mat=Tunnel; tex=tunnel;
|
||||
};
|
||||
overlay {
|
||||
algo=lines; a=3; b=16;
|
||||
rotate=-45;
|
||||
turbulence=100;
|
||||
mat=Tunnel; tex=tunnel;
|
||||
};
|
||||
};
|
||||
|
||||
// Randomly placed material specks according to bozo.
|
||||
overlay MatBozo {
|
||||
algo=bozo; a=5;
|
||||
turbulence=1000; loosebounds=1;
|
||||
};
|
||||
|
||||
// Fills an overlay with ice, tunnel, rock and granite.
|
||||
overlay BorderFill {
|
||||
overlay { mat=Rock; tex=rock; loosebounds=1;
|
||||
MatBozo { mat=Tunnel; tex=tunnel; };
|
||||
MatBozo { mat=Rock; tex=rock_cracked; a=6; };
|
||||
MatBozo { mat=Granite; tex=granite; a=14; };
|
||||
MatBozo { mat=Ice; tex=ice3; a=8; };
|
||||
MatBozo { mat=Tunnel; tex=tunnel; };
|
||||
};
|
||||
};
|
||||
|
||||
// A lengthy vertical cavern surrounded by ice, dirt and rock.
|
||||
map Cavern {
|
||||
overlay {
|
||||
// Cut cavern out of the landscape.
|
||||
x=40; wdt=20; y=-6; hgt=100;
|
||||
turbulence=100; lambda=4;
|
||||
loosebounds=1;
|
||||
} ^ overlay {
|
||||
// Fill remaining area with MatFill.
|
||||
MatFill;
|
||||
// And create a border around this area.
|
||||
overlay {
|
||||
algo=border; a=4; b=4;
|
||||
// Fill border with BorderFill.
|
||||
BorderFill;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,261 @@
|
|||
/*--
|
||||
Dynamic maze
|
||||
|
||||
Author: Sven2
|
||||
--*/
|
||||
|
||||
#include Library_Map
|
||||
|
||||
static g_caves;
|
||||
|
||||
local caves, n_caves, start_cave, end_cave;
|
||||
|
||||
func FindCaves(int n)
|
||||
{ //n=6;
|
||||
var mask = CreateLayer();
|
||||
mask->Draw("Rock");
|
||||
caves = [];
|
||||
var min_cave_dist = 12, border = 5;
|
||||
while (n--)
|
||||
{
|
||||
var cave = {};
|
||||
if (!mask->FindPosition(cave, "Rock", [border,border,this.Wdt-border*2,this.Hgt-border*2])) continue;
|
||||
mask->Draw("Tunnel", {Algo=MAPALGO_Ellipsis, X=cave.X, Y=cave.Y, Wdt=min_cave_dist, Hgt=min_cave_dist});
|
||||
cave.links = [];
|
||||
cave.dirs = 0;
|
||||
cave.rand = Random(65536);
|
||||
cave.depth = -1;
|
||||
caves[n_caves++] = cave;
|
||||
}
|
||||
/* caves[0].X = 10; caves[0].Y = 10;
|
||||
caves[1].X = 30; caves[1].Y = 10;
|
||||
caves[2].X = 10; caves[2].Y = 30;
|
||||
caves[3].X = 30; caves[3].Y = 70;
|
||||
caves[4].X = 50; caves[4].Y = 10;
|
||||
caves[5].X = 50; caves[5].Y = 30;*/
|
||||
return n_caves;
|
||||
}
|
||||
|
||||
func GetCaveLinkDir(c1, c2)
|
||||
{
|
||||
// Returns if c2 is left (1), right (2), atop (4) or below (8) c1. Returns only one direction.
|
||||
var dx=c2.X-c1.X, dy=c2.Y-c1.Y, adx=Abs(dx), ady=Abs(dy);
|
||||
//Log("%d,%d to %d,%d dx=%d dy=%d", c1.X, c1.Y, c2.X, c2.Y, dx, dy);
|
||||
return (dx<-ady) | (dx>ady)<<1 | (dy<=-adx)<<2 | (dy>=adx)<<3;
|
||||
}
|
||||
|
||||
func IsLineOverlap(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4)
|
||||
{
|
||||
// Check if line from x1,y1 to x2,y2 crosses the line from x3,y3 to x4,y4
|
||||
var d1x=x2-x1, d1y=y2-y1, d2x=x4-x3, d2y=y4-y3, d3x=x3-x1, d3y=y3-y1;
|
||||
var a = d1y*d3x-d1x*d3y;
|
||||
var b = d2y*d3x-d2x*d3y;
|
||||
var c = d2y*d1x-d2x*d1y;
|
||||
if (!c) return !a && Inside(x3, x1,x2) && Inside(y3, y1,y2); // lines are parallel
|
||||
return a*c>=0 && !(a*a/(c*c+1)) && b*c>=0 && !(b*b/(c*c+1));
|
||||
}
|
||||
|
||||
func FindCaveConnections()
|
||||
{
|
||||
var i, j, cave, cave2, caves2, dir, dir2, n, check_link, all_links = [];
|
||||
// Connect all caves to neighbours
|
||||
for (i=0; i<n_caves; ++i)
|
||||
{
|
||||
cave = caves[i];
|
||||
caves2 = caves[i+1:n_caves];
|
||||
for (cave2 in caves2) cave2.d = Distance(cave.X, cave.Y, cave2.X, cave2.Y);
|
||||
SortArrayByProperty(caves2, "d");
|
||||
for (cave2 in caves2)
|
||||
{
|
||||
// Make sure there's a max of one connection per direction (up/left/right/down)
|
||||
dir = GetCaveLinkDir(cave, cave2);
|
||||
//Log("Cave %d to %d direction %d.", GetIndexOf(caves, cave), GetIndexOf(caves, cave2), dir);
|
||||
if (cave.dirs & dir) continue;
|
||||
dir2 = dir >> 1& 5|10 &dir << 1;
|
||||
//Log("dir %d opposite to %d.", dir2, dir);
|
||||
if (cave2.dirs & dir2) continue;
|
||||
// Make sure the connectors don't cross each other
|
||||
// Note that connectors may still overlap the edges of caves, effectively connecting them
|
||||
// But since nothing really "breaks" on this occasion, just stick with the simple check for now.
|
||||
var has_overlap = false;
|
||||
for (check_link in all_links)
|
||||
if (check_link[0] !== cave && check_link[1] !== cave)
|
||||
if (check_link[0] !== cave2 && check_link[1] !== cave2)
|
||||
if (IsLineOverlap(cave.X, cave.Y, cave2.X, cave2.Y, check_link[0].X, check_link[0].Y, check_link[1].X, check_link[1].Y))
|
||||
{ has_overlap=true; break; }
|
||||
if (has_overlap) continue;
|
||||
// Connect these caves
|
||||
cave.links[GetLength(cave.links)] = cave2;
|
||||
cave2.links[GetLength(cave2.links)] = cave;
|
||||
cave.dirs |= dir;
|
||||
cave2.dirs |= dir2;
|
||||
// Register and count connections
|
||||
all_links[n++] = [cave, cave2];
|
||||
// All directions connected?
|
||||
if (cave.dirs == 0xf) break;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
func FindStart()
|
||||
{
|
||||
SortArrayByProperty(caves, "X");
|
||||
start_cave = caves[0];
|
||||
return start_cave;
|
||||
}
|
||||
|
||||
func MakeMaze()
|
||||
{
|
||||
// Make maze by removing unnecesseriy links
|
||||
start_cave.path = [];
|
||||
var open = [start_cave], n_open = 1;
|
||||
while (n_open)
|
||||
{
|
||||
var i_cave = n_open-1-Random(1+Random(n_open)); // Prefer depth-first generation so stray paths are deeper
|
||||
var cave = open[i_cave];
|
||||
open[i_cave] = open[--n_open]; // SetLength(open, n_open) not nessessery because length is stored in n_open
|
||||
var path_length = GetLength(cave.path);
|
||||
var path_to_cave = cave.path[:];
|
||||
path_to_cave[path_length] = cave;
|
||||
cave.depth = path_length;
|
||||
for (var cave2 in cave.links[:]) // force a copy because cave.links is modified in the loop
|
||||
{
|
||||
if (path_length && cave2 === path_to_cave[path_length-1]) continue;
|
||||
// Only first path survives
|
||||
if (cave2.path)
|
||||
{
|
||||
// Remove circular path
|
||||
RemoveCaveLinks(cave, cave2);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remember path to this cave
|
||||
cave2.path = path_to_cave;
|
||||
open[n_open++] = cave2;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Sort from start to goal
|
||||
SortArrayByProperty(caves, "depth");
|
||||
// Close one connection 2/3rds of the way to the goal
|
||||
var main_path = caves[n_caves-1].path;
|
||||
var main_path_length = GetLength(main_path);
|
||||
if (main_path_length > 5) RemoveCaveLinks(main_path[main_path_length*2/3], main_path[main_path_length*2/3+1]);
|
||||
// Kill unreachable caves
|
||||
var i;
|
||||
for (i=0; i<n_caves; ++i) if (caves[i].depth>=0) break;
|
||||
caves = caves[i:n_caves];
|
||||
n_caves -= i;
|
||||
end_cave = caves[n_caves-1];
|
||||
return true;
|
||||
}
|
||||
|
||||
func RemoveCaveLinks(c1, c2)
|
||||
{
|
||||
var i = GetIndexOf(c1.links, c2), n = GetLength(c1.links) - 1;
|
||||
if (i>=0)
|
||||
{
|
||||
c1.links[i] = c1.links[n];
|
||||
SetLength(c1.links, n);
|
||||
c1.dirs &= ~GetCaveLinkDir(c1,c2);
|
||||
}
|
||||
i = GetIndexOf(c2.links, c1); n = GetLength(c2.links) - 1;
|
||||
if (i>=0)
|
||||
{
|
||||
c2.links[i] = c2.links[n];
|
||||
SetLength(c2.links, n);
|
||||
c2.dirs &= ~GetCaveLinkDir(c2,c1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
func DrawVariations(string mat, int ratio, int sx, int sy)
|
||||
{
|
||||
var rand_algo = {Algo=MAPALGO_RndChecker, Ratio=ratio, Wdt=sx, Hgt=sy};
|
||||
var turb_algo = {Algo=MAPALGO_Turbulence, Amplitude=12, Scale=8, Op=rand_algo};
|
||||
return Draw(mat, turb_algo);
|
||||
}
|
||||
|
||||
func DrawBackground()
|
||||
{
|
||||
Draw("Rock");
|
||||
DrawVariations("Rock-rock_cracked", 50, 5,15);
|
||||
DrawVariations("Ore", 10, 8,8);
|
||||
DrawVariations("Sulphur", 8, 12,3);
|
||||
DrawVariations("Coal", 8, 8,3);
|
||||
DrawVariations("Gold", 5, 4,4);
|
||||
DrawVariations("Granite", 14, 15,5);
|
||||
DrawVariations("Granite", 14, 5,15);
|
||||
return true;
|
||||
}
|
||||
|
||||
func DrawCaves()
|
||||
{
|
||||
for (var cave in caves)
|
||||
{
|
||||
Draw("Tunnel", {Algo=MAPALGO_Ellipsis, X=cave.X, Y=cave.Y, Wdt=4, Hgt=4});
|
||||
//var src = cave.path;
|
||||
//if (src && GetLength(src)) src = Format("%d,%d", src[GetLength(src)-1].X, src[GetLength(src)-1].Y);
|
||||
//Log("Cave at %d,%d src %v", cave.X, cave.Y, src);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
func DrawTunnels()
|
||||
{
|
||||
for (var cave in caves)
|
||||
{
|
||||
for (var cave2 in cave.links)
|
||||
{
|
||||
if (cave2.done) continue;
|
||||
Draw("Tunnel", {Algo=MAPALGO_Polygon, X=[cave.X, cave2.X], Y=[cave.Y, cave2.Y], Wdt=2, Open=1, Empty=1 });
|
||||
}
|
||||
cave.done = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
func DrawStart()
|
||||
{
|
||||
Draw("Tunnel", nil, [0, start_cave.Y - 4, start_cave.X, 4]);
|
||||
Draw("Brick", nil, [0, start_cave.Y, start_cave.X-2, 1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
func DrawEnd()
|
||||
{
|
||||
Draw("Ruby", {Algo=MAPALGO_Ellipsis, X=end_cave.X, Y=end_cave.Y, Wdt=4, Hgt=4});
|
||||
return true;
|
||||
}
|
||||
|
||||
protected func InitializeMap(map)
|
||||
{
|
||||
map->Resize(300,300);
|
||||
|
||||
FindCaves(200);
|
||||
FindCaveConnections();
|
||||
FindStart();
|
||||
MakeMaze();
|
||||
|
||||
DrawBackground();
|
||||
DrawTunnels();
|
||||
DrawCaves();
|
||||
DrawStart();
|
||||
DrawEnd();
|
||||
|
||||
// Caves to global var: Need to clean up circular prop list references because they cause crashes
|
||||
var cave;
|
||||
for (cave in end_cave.path)
|
||||
{
|
||||
cave.is_main_path = true;
|
||||
}
|
||||
for (cave in caves)
|
||||
{
|
||||
cave.n_links = GetLength(cave.links);
|
||||
cave.links = cave.path = nil;
|
||||
}
|
||||
g_caves = caves;
|
||||
return true;
|
||||
}
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 114 KiB |
|
@ -0,0 +1,13 @@
|
|||
[Material]
|
||||
Name=Ruby
|
||||
Shape=Rough
|
||||
Density=70
|
||||
Friction=15
|
||||
BlastFree=1
|
||||
Blast2Object=Ruby
|
||||
Blast2ObjectRatio=100
|
||||
MaxAirSpeed=100
|
||||
MaxSlide=1
|
||||
Corrode=60
|
||||
Placement=21
|
||||
TextureOverlay=Ruby
|
|
@ -0,0 +1,46 @@
|
|||
OverloadMaterials
|
||||
OverloadTextures
|
||||
|
||||
10=Tunnel-tunnel
|
||||
12=Tunnel-brickback
|
||||
|
||||
13=BrickSoft-brick1
|
||||
|
||||
19=DuroLava-lava_red
|
||||
20=Water-water1-water2-water3-water1-water3-water2
|
||||
22=Acid-acid
|
||||
23=Lava-lava_red
|
||||
25=Water-water
|
||||
|
||||
28=Earth-earth
|
||||
29=Earth-earth_dry
|
||||
30=Earth-earth_rough
|
||||
31=Earth-earth_topsoil
|
||||
32=Earth-earth_midsoil
|
||||
33=Ashes-ashes
|
||||
|
||||
36=Ore-ore
|
||||
|
||||
40=Granite-granite
|
||||
42=Granite-rock
|
||||
|
||||
45=Gold-gold
|
||||
|
||||
50=Rock-rock
|
||||
51=Rock-rock_cracked
|
||||
|
||||
53=Sulphur-sulphur
|
||||
|
||||
54=Coal-coal
|
||||
|
||||
55=Sand-sand_rough
|
||||
56=Sand-sand_smooth
|
||||
|
||||
60=Ruby-Ruby
|
||||
|
||||
65=Ice-ice2
|
||||
67=Ice-ice3
|
||||
|
||||
70=Snow-snow1
|
||||
|
||||
73=Brick-brick1
|
|
@ -0,0 +1,40 @@
|
|||
[Head]
|
||||
Icon=34
|
||||
Title=Maze
|
||||
Version=5,2,0,1
|
||||
Difficulty=20
|
||||
|
||||
[Definitions]
|
||||
Definition1=Objects.ocd
|
||||
Definition2=Experimental.ocd\Gems.ocd
|
||||
|
||||
[Game]
|
||||
Goals=Goal_RubyHunt=1;
|
||||
|
||||
[Player1]
|
||||
Crew=Clonk=1
|
||||
|
||||
[Player2]
|
||||
Crew=Clonk=1
|
||||
|
||||
[Player3]
|
||||
Crew=Clonk=1
|
||||
|
||||
[Player4]
|
||||
Crew=Clonk=1
|
||||
|
||||
[Landscape]
|
||||
Sky=Clouds2
|
||||
MapWidth=100
|
||||
MapHeight=100
|
||||
MapZoom=10
|
||||
TopOpen=0
|
||||
BottomOpen=0
|
||||
SkyScrollMode=2
|
||||
|
||||
[Weather]
|
||||
Climate=0,0,0,100
|
||||
StartSeason=0,0,0,100
|
||||
YearSpeed=0,0,0,100
|
||||
Wind=1,100,-100,100
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
/*--
|
||||
Maze
|
||||
Author: Sven2
|
||||
|
||||
Dynamic maze
|
||||
--*/
|
||||
|
||||
static g_caves;
|
||||
local goal_cave;
|
||||
|
||||
func InitializePlayer(int plr)
|
||||
{
|
||||
// Harsh zoom range
|
||||
for (var flag in [PLRZOOM_LimitMax, PLRZOOM_Direct])
|
||||
SetPlayerZoomByViewRange(plr,300,200,flag);
|
||||
//SetPlayerZoomByViewRange(plr,LandscapeWidth(),LandscapeHeight(),flag);
|
||||
SetPlayerViewLock(plr, true);
|
||||
// Position and materials
|
||||
LaunchPlayer(plr);
|
||||
return true;
|
||||
}
|
||||
|
||||
func LaunchPlayer(int plr)
|
||||
{
|
||||
// Position and materials
|
||||
var starting_cave = g_caves[0];
|
||||
var i, crew, obj;
|
||||
for (i=0; crew=GetCrew(plr,i); ++i)
|
||||
{
|
||||
crew->SetPosition(starting_cave.X/2, starting_cave.Y-18);
|
||||
for (var tool in [Pickaxe, GrappleBow])
|
||||
if (obj = FindObject(Find_ID(tool), Find_Owner(plr), Find_NoContainer()))
|
||||
obj->Enter(crew);
|
||||
else
|
||||
crew->CreateContents(tool);
|
||||
crew->CreateContents(Loam,2);
|
||||
crew->CreateContents(Dynamite,2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
func RelaunchPlayer(int plr)
|
||||
{
|
||||
var clonk = CreateObject(Clonk,0,0,plr);
|
||||
if (!clonk) return false;
|
||||
clonk->MakeCrewMember(plr);
|
||||
SetCursor(plr, clonk);
|
||||
return LaunchPlayer(plr);
|
||||
}
|
||||
|
||||
func CreateBonus(int x, int y, int value)
|
||||
{
|
||||
var obj;
|
||||
if (Random(value) > 50)
|
||||
{
|
||||
obj = CreateObject(Signpost, x,y);
|
||||
if (obj)
|
||||
{
|
||||
if (Random(value) > 5)
|
||||
{
|
||||
var dx = goal_cave.X - x, dy = goal_cave.Y - y;
|
||||
if (Abs(dx) > Abs(dy))
|
||||
if (dx>0) obj->SetText("$MsgGoalRight$"); else obj->SetText("$MsgGoalLeft$");
|
||||
else
|
||||
if (dy>0) obj->SetText("$MsgGoalBelow$"); else obj->SetText("$MsgGoalAbove$");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
obj = CreateObject(Chest, x,y);
|
||||
if (obj)
|
||||
{
|
||||
if (Random(value) > 90) obj->CreateContents(Shovel);
|
||||
if (Random(value) > 90) obj->CreateContents(JarOfWinds);
|
||||
if (Random(value) > 90) obj->CreateContents(TeleGlove);
|
||||
if (Random(value) > 90) obj->CreateContents(Sword);
|
||||
if (Random(value) > 5) obj->CreateContents(Loam, 1+Random(2));
|
||||
if (Random(value) > 5) obj->CreateContents(Dynamite, 1+Random(2));
|
||||
if (Random(value) > 25) obj->CreateContents(DynamiteBox, 1+Random(2));
|
||||
if (Random(value) > 10) obj->CreateContents(Bread, 1+Random(2));
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
protected func Initialize()
|
||||
{
|
||||
var zoom = 10, cave, n_caves = GetLength(g_caves);
|
||||
for (cave in g_caves) { cave.X *= zoom; cave.Y *= zoom; }
|
||||
// Goal
|
||||
var starting_cave = g_caves[0];
|
||||
var goal = FindObject(Find_ID(Goal_RubyHunt));
|
||||
if (!goal) goal = CreateObject(Goal_RubyHunt);
|
||||
goal->SetGoalRect(Rectangle(0, starting_cave.Y-25, starting_cave.X-20, 25));
|
||||
goal_cave = g_caves[n_caves-1];
|
||||
// Place extra elements in caves (except at start/end)
|
||||
for (cave in g_caves)
|
||||
{
|
||||
if (cave == g_caves[0] || cave == g_caves[n_caves-1]) continue;
|
||||
var x=cave.X, y=cave.Y;
|
||||
while (!GBackSolid(x,y)) ++y;
|
||||
if (cave.n_links <= 1)
|
||||
{
|
||||
// This is a dead end.
|
||||
if (cave.dirs == 8)
|
||||
{
|
||||
// Facing downwards. Hard to reach, but cannot place a chest here :(
|
||||
CreateObject(Trunk, cave.X, cave.Y)->SetR(160+Random(41));
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateBonus(x, y, 100);
|
||||
}
|
||||
}
|
||||
else if (!(cave.dirs & 8))
|
||||
{
|
||||
// Connecting cave without bottom
|
||||
CreateBonus(x, y, 25 + 25 * !cave.is_main_path);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
[DefCore]
|
||||
id=Signpost
|
||||
Version=5,2,0,1
|
||||
Category=C4D_StaticBack
|
||||
Width=32
|
||||
Height=32
|
||||
Offset=-16,-16
|
||||
Vertices=1
|
||||
VertexX=4
|
||||
VertexY=15
|
||||
VertexCNAT=8
|
||||
VertexFriction=100
|
||||
Components=Wood=1;
|
||||
Construction=1
|
||||
Value=5
|
||||
Mass=5
|
||||
Rotate=1
|
Binary file not shown.
After Width: | Height: | Size: 83 KiB |
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
Signpost
|
||||
Author: Sven2
|
||||
|
||||
Storage for text.
|
||||
*/
|
||||
|
||||
local text;
|
||||
|
||||
func SetText(string t) { text=t; }
|
||||
|
||||
public func IsInteractable() { return GetCon() >= 100; }
|
||||
|
||||
public func GetInteractionMetaInfo(object clonk)
|
||||
{
|
||||
return { Description = "$MsgRead$", IconName = nil, IconID = nil };
|
||||
}
|
||||
|
||||
// Read on interaction
|
||||
public func Interact(object clonk)
|
||||
{
|
||||
var message = Format("%s ", text ?? "$MsgUnreadable$");
|
||||
CustomMessage(message, nil, clonk->GetController(), 150,150, nil, GUI_MenuDeco, Signpost);
|
||||
return true;
|
||||
}
|
||||
|
||||
local Name = "$Name$";
|
|
@ -0,0 +1,3 @@
|
|||
Name=Schild
|
||||
MsgRead=Lesen
|
||||
MsgUnreadable=Unlesbar.
|
|
@ -0,0 +1,3 @@
|
|||
Name=Signpost
|
||||
MsgRead=Read
|
||||
MsgUnreadable=Unreadable.
|
|
@ -0,0 +1,4 @@
|
|||
MsgGoalAbove=Das Ziel ist oberhalb von hier.
|
||||
MsgGoalBelow=Das Ziel ist unterhalb von hier.
|
||||
MsgGoalLeft=Das Ziel ist links von hier.
|
||||
MsgGoalRight=Das Ziel ist rechts von hier.
|
|
@ -0,0 +1,4 @@
|
|||
MsgGoalAbove=The goal is above this post.
|
||||
MsgGoalBelow=The goal is below this post.
|
||||
MsgGoalLeft=The goal is left of this post.
|
||||
MsgGoalRight=The goal is right of this post.
|
|
@ -0,0 +1,16 @@
|
|||
/*--
|
||||
Override screenshot functionality
|
||||
--*/
|
||||
|
||||
global func PlayerControl(int plr, int ctrl)
|
||||
{
|
||||
if (ctrl == CON_TryScreenshot)
|
||||
{
|
||||
CustomMessage(Format("$MsgCheater$", GetTaggedPlayerName(plr)));
|
||||
Sound("Error", true);
|
||||
var crew = GetCursor(plr);
|
||||
if (crew) crew->Punch(crew, 50);
|
||||
return true;
|
||||
}
|
||||
return _inherited(plr, ctrl, ...);
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
[ControlDefs]
|
||||
|
||||
[ControlDef]
|
||||
Identifier=TryScreenshot
|
||||
|
||||
[ControlSets]
|
||||
|
||||
[ControlSet]
|
||||
Name=*
|
||||
|
||||
[Assignment]
|
||||
Key=Ctrl+F9
|
||||
Priority=999
|
||||
Control=TryScreenshot
|
|
@ -0,0 +1 @@
|
|||
MsgCheater=%s wollte cheaten!
|
|
@ -0,0 +1 @@
|
|||
MsgCheater=%s tried to cheat!
|
|
@ -0,0 +1,2 @@
|
|||
DE:Labyrinth
|
||||
US:Maze
|
Loading…
Reference in New Issue