Compare commits

...

40 Commits

Author SHA1 Message Date
Nicolas Hake 92ed1537a0 Fix off-by-one error in FoW renderer (#1678)
The FoW renderer would try drawing to texture coordinates one pixel
too high (i.e. if the texture was 256 pixels high, it would draw to
pixels with 1 <= y <= 256 instead of 0..255).
2016-02-15 13:52:03 +01:00
Nicolas Hake 1a82b164b4 Link to terminfo or one of its compat libraries in add'n to readline
Unmodified readline relies on, but doesn't link to, a termcap library.
Several Linux distributions patch this, but others don't; to avoid build
failures, we'll just link to a library that provides termcap symbols
even though we don't use them ourselves. Fixes Github #15.
2016-02-15 13:50:56 +01:00
Maikel de Vries 4b01f51337 only structures should have Exclusive=1
Otherwise these objects would block new constructions
2016-02-14 13:37:24 +01:00
Maikel de Vries 488ec4d318 shovel: symmetrize dig angle limits 2016-02-14 13:36:39 +01:00
Maikel de Vries 46b977e506 block construction sites based on Exclusive and not on planes (#1534)
This makes more sense, exclusive object block all other construction sites, irrespective of their planes.
2016-02-14 13:36:10 +01:00
Maikel de Vries 8d63ddfdef fix additional preview overlay after combining with other structure
This caused an overlay warning in the previewer object when constructing an elevetor and combining it with another elevator and detaching it again.
2016-02-14 13:35:56 +01:00
Maikel de Vries c0382ceb7f correctly place/preview basement for elevator (#1534) 2016-02-14 13:35:45 +01:00
Sven Eberhardt bb46dede7a Fix overflow when calling DoEnergy with large values #1646 2016-02-14 13:32:39 +01:00
Sven Eberhardt b4919fb1ec Fight for Gidl: Fix script error on statue death #1610 2016-02-14 13:31:56 +01:00
Maikel de Vries 6978bbe646 fix script errors for wrong parameter types in tele glove 2016-02-14 13:30:23 +01:00
Sven Eberhardt 675740c8dd Add missing sound for snapping line #1644
Sound original from CosmicEmbers (http://freesound.org/people/CosmicEmbers/sounds/161650/); cropped and pitch adjusted.
2016-02-14 13:29:21 +01:00
David Dormagen 8aec2eadd2 pickaxe: removed debug message
introduced in https://git.openclonk.org/openclonk.git/commitdiff/796aa7d7c62c5348417d584c9637da61297736d4
2016-02-14 13:27:39 +01:00
Sven Eberhardt a52a4335fc Maze: Fix error sound when trying to cheat 2016-02-14 13:26:58 +01:00
Sven Eberhardt c097c6eb35 Fix shovel shoveling in the wrong direction sometimes #1626 2016-02-14 13:26:35 +01:00
Sven Eberhardt d8f9ab5232 Fix pickaxe picking in the wrong direction sometimes #1626 2016-02-14 13:26:27 +01:00
Maikel de Vries 60c5fb99a2 add power information to interaction menu for flagpole (#1579) 2016-02-14 13:24:25 +01:00
Maikel de Vries 79146dac9b power library: methods to for storage information and balance updates 2016-02-14 13:24:15 +01:00
David Dormagen 4c8d4ef18d producers: show progress of current product (#1549)
This is solved via another entry in the production menu (below the products), which is updated by an effect, that is being told the menu ID/target by the interaction menu through a callback.
This setup allows for very intrusive changes to the interaction menu with only few lines of code!
2016-02-14 13:24:04 +01:00
Maikel de Vries b49f89d31c move mime skin/portrait from boomshire to decoration folder
This makes it available for multiple rounds.
2016-02-14 13:19:26 +01:00
Maikel de Vries e9e06263a8 fix shape of basement construction preview and site (#1586) 2016-02-14 13:18:36 +01:00
Maikel de Vries 2e2450ee77 update license of Sky.jpg in Clonkomotive to cc-by 3.0 2016-02-14 13:18:16 +01:00
Clonkonaut e486712934 Clonkomotive: German translation (#1632).
I also took the liberty of renaming "HeavyCrumb" to "Boulder". I have never heard the word 'crumb' used in this context.
2016-02-14 13:16:55 +01:00
Clonkonaut 47820691d0 Elevator construction preview shows placement of the case (#1534).
Structures can use the definition call ConstructionPreview(Previewer Object, Overlay, Direction) to add any overlay to the previewer. It will be coloured accordingly.
2016-02-14 13:08:19 +01:00
David Dormagen 684b0d0682 contents menu: fixed possible "use after deletion" error 2016-02-14 13:03:26 +01:00
David Dormagen 546ae30928 cannon: fix possible nil pointer access
In boomshire, the cannons are automatically filled with boompacks (and then fired). That means that there is no Clonk to be passed.
2016-02-14 13:03:05 +01:00
Nicolas Hake f35b3f3342 Fix NULL deref when deserializing CustomNode AnimationNodes (GH #13) 2016-02-14 13:02:36 +01:00
Sven Eberhardt 0301f610fc Use sched_yield instead of pthread_yield in png save wait loop [cfkoch] 2016-01-18 11:29:47 +01:00
Günther Brammer aa7e2e91db CMake: Fix building mape on systems with more than one GTK+ CPP flag 2016-01-18 11:28:56 +01:00
Sven Eberhardt 1bba764219 Extinguish transferred contents on respawn 2016-01-18 11:02:00 +01:00
Sven Eberhardt 21390f4c29 Crash landing: Fix post-intro plane placement so it cannot slide into the lava #1615 2016-01-18 11:00:55 +01:00
Sven Eberhardt ba82f5c3ac Raid: Fix goal descroptions and buckets in Mave's foundry. 2016-01-18 11:00:22 +01:00
Sven Eberhardt b0ae8fae84 DarkCastle: Minor objects+text fixes 2016-01-18 11:00:07 +01:00
Sven Eberhardt 193dd6adf4 Hot Ice: Spawn and map improvements in "small islands" mode #1623 2016-01-18 10:56:50 +01:00
Tobias Zwick 0cf9473280 correct Philipp Kern's name in the credit screen 2016-01-18 10:54:52 +01:00
Philipp Kern 2f264b1825 Correct the spelling of my name in Credits.txt 2016-01-18 10:54:38 +01:00
Maikel de Vries 75ab7e0f00 tutorials: hide guide message while in a dialogue (#1593) 2016-01-18 10:48:25 +01:00
Maikel de Vries 6d95c83196 fix dialogue stopping and waiting time (#1597)
First stop the dialogue properly and then wait for 30 frames to start a new one.
2016-01-18 10:48:25 +01:00
Maikel de Vries 6655fdf8c7 tutorial 3: lumberjack directs to other villagers when needed (#1596) 2016-01-18 10:48:25 +01:00
Maikel de Vries dbc21d8431 make sawmill site uncancellable in tutorial 3 (#1617) 2016-01-18 10:48:25 +01:00
Sven Eberhardt 082373d6e6 Maze: Fix possible spray line to last position or (0,0) landscape corner #1624 2016-01-16 22:35:46 -05:00
75 changed files with 742 additions and 252 deletions

View File

@ -1170,7 +1170,7 @@ endif()
if(GTK3_FOUND AND GTK3_gtksourceview_FOUND)
add_executable(mape ${MAPE_BASE_SOURCES} ${MAPE_SOURCES})
set_property(TARGET mape APPEND PROPERTY COMPILE_FLAGS ${GTK3_COMPILE_DEFINITIONS})
target_compile_options(mape PRIVATE ${GTK3_COMPILE_DEFINITIONS} ${GTK3_gtksourceview_COMPILE_DEFINITIONS})
target_include_directories(mape PRIVATE ${GTK3_INCLUDE_DIRS} ${GTK3_gtksourceview_INCLUDE_DIRS})
target_link_libraries(mape
${GTK3_LIBRARIES}

View File

@ -27,10 +27,10 @@ Martin Strohmeier (K-Pone)
Tobias Zwick (Newton)
<Thanks to our package maintainers>
Benedict Etzel (B_E), Phillip Kern (pkern), Kevin Zheng and more
Benedict Etzel (B_E), Philipp Kern (pkern), Kevin Zheng and more
<Special Thanks to Contributors>
Martin Adam (Win), Florian Graier (Nachtfalter), Mark Haßelbusch (Marky), Merten Ehmig (pluto), Benjamin Herr (Loriel), Armin Schäfer, Pyrit, Philip Holzmann (Batman), Alexander Semeniuk (AlteredARMOR), Andriel, Peewee, Oliver Schneider (ker), Fabian Pietsch, Manuel Rieke (MrBeast), Felix Riese (Fungiform), Carl-Philip Hänsch (Carli), Sebastian Rühl, Gurkenglas and many more:
Luchs, Asmageddon, mizipzor, Tim Blume, Apfelclonk, Sven-Hendrik Haase, Lauri Niskanen (Ape), Daniel Theuke (ST-DDT), Russell, Stan, TomyLobo, Clonkine, Koronis, Johannes Nixdorf (mixi), grgecko, Dominik Bayerl, Misty de Meo, Lorenz Schwittmann, hasufell, Jan Heberer, dylanstrategie, Checkmaty, Faby
Also, big thanks to Matthes Bender and all those who contributed to previous Clonk titles for the passion they put into the game and for agreeing to make Clonk open source.
Also, big thanks to Matthes Bender and all those who contributed to previous Clonk titles for the passion they put into the game and for agreeing to make Clonk open source.

View File

@ -1,6 +1,6 @@
# OpenClonk, http://www.openclonk.org
#
# Copyright (c) 2011-2013, The OpenClonk Team and contributors
# Copyright (c) 2011-2016, The OpenClonk Team and contributors
#
# Distributed under the terms of the ISC license; see accompanying file
# "COPYING" for details.
@ -26,6 +26,13 @@ ENDIF (READLINE_INCLUDE_DIR)
FIND_PATH(READLINE_INCLUDE_DIR readline.h PATH_SUFFIXES readline)
# Unmodified readline depends on symbols from termcap without explicitly
# linking to it. Several distributions patch this to make it link against
# terminfo from ncurses or another termcap library, but some don't. To avoid
# having to run link tests, we'll just look for and use any termcap providing
# library.
FIND_LIBRARY(TERMCAP_LIBRARY NAMES tinfo termcap ncursesw ncurses cursesw curses)
SET(READLINE_NAMES readline libreadline)
FIND_LIBRARY(READLINE_LIBRARY NAMES ${READLINE_NAMES} )
@ -35,10 +42,13 @@ INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(READLINE DEFAULT_MSG READLINE_LIBRARY READLINE_INCLUDE_DIR)
IF(READLINE_FOUND)
SET( READLINE_LIBRARIES ${READLINE_LIBRARY} )
if(TERMCAP_LIBRARY)
set(READLINE_LIBRARIES ${READLINE_LIBRARY} ${TERMCAP_LIBRARY})
else()
set(READLINE_LIBRARIES ${READLINE_LIBRARY})
endif()
ELSE(READLINE_FOUND)
SET( READLINE_LIBRARIES )
ENDIF(READLINE_FOUND)
MARK_AS_ADVANCED( READLINE_LIBRARY READLINE_INCLUDE_DIR )
MARK_AS_ADVANCED( READLINE_LIBRARY TERMINFO_LIBRARY READLINE_INCLUDE_DIR )

View File

@ -128,7 +128,7 @@
<row>
<literal_col>Exclusive</literal_col>
<col>Integer</col>
<col>0 or 1. Determines whether the object blocks objects behind it.</col>
<col>0 or 1. Determines whether the object blocks objects behind it. Exclusive objects also block the placement of a construction site at an overlapping location.</col>
</row>
<row>
<literal_col>Line</literal_col>

View File

@ -9,7 +9,7 @@
<subcat>OCF</subcat>
<version>5.1 OC</version>
<syntax><rtype>int</rtype></syntax>
<desc>Object character flag: the object blocks (covers) objects behind it and prevents other objects from being built in front. This flag is set by <emlink href="definition/defcore.html">DefCore</emlink> entry "Exclusive".</desc>
<desc>Object character flag: the object blocks (covers) objects behind it and prevents construction sites from being built in front of it. This flag is set by <emlink href="definition/defcore.html">DefCore</emlink> entry "Exclusive".</desc>
<remark>For more information and examples regarding these constants see <emlink href="definition/ocf.html">object character flags</emlink>.</remark>
<related>
<funclink>GetOCF</funclink>

View File

@ -1,10 +1,13 @@
/**
/*
Hot Ice
Ice islands above a lava lake
@authors Sven2
*/
static g_player_spawn_positions;
static g_map_width;
// Called be the engine: draw the complete map here.
public func InitializeMap(proplist map)
{
@ -12,35 +15,77 @@ public func InitializeMap(proplist map)
// Map type 1: Only many small islands
var t = SCENPAR_MapType;
var w = map.Wdt, h=map.Hgt;
g_map_width = w;
// Bottom lava lake
map->Draw("^DuroLava", nil, [0,h*4/5,w,h/5]);
// Big island
if (t == 0)
{
var island = { Algo=MAPALGO_Polygon, X=[0,w,w*6/8,w*2/8], Y=[h*4/10,h*4/10,h*7/10,h*7/10] };
island = { Algo=MAPALGO_Turbulence, Op=island, Amplitude=[0, 8] };
map->Draw("^Ice-ice2", island, [w/10,h*13/20,w*8/10,h*3/20]);
}
// Small islands
var n_islands = [12,37][t];
while(n_islands--)
{
var y = h*2/10 + Random(h*(3+t*2)/10);
var x = w*1/10 + Random(w*8/10);
var szx = t*Random(3);
var szy = 1+t*Random(Random(2));
map->Draw("^Ice-ice2", nil, [x-szx,y,1+2*szx,szy]);
}
// Alternate texctures
var icealt_tex = { Algo=MAPALGO_RndChecker, Wdt=2, Hgt=3 };
icealt_tex = { Algo=MAPALGO_Turbulence, Op=icealt_tex };
icealt_tex = { Algo=MAPALGO_And, Op=[Duplicate("Ice"), icealt_tex]};
map->Draw("^Ice-ice3", icealt_tex);
if (t == 0) DrawBigIslandMap(map);
if (t == 1) DrawSmallIslandsMap(map);
// Alternate texctures
var icealt_tex = { Algo=MAPALGO_RndChecker, Wdt=2, Hgt=3 };
icealt_tex = { Algo=MAPALGO_Turbulence, Op=icealt_tex };
icealt_tex = { Algo=MAPALGO_And, Op=[Duplicate("Ice"), icealt_tex]};
map->Draw("^Ice-ice", icealt_tex);
// Return true to tell the engine a map has been successfully created.
return true;
}
func DrawBigIslandMap(proplist map)
{
var w = map.Wdt, h=map.Hgt;
// Draw one big island as the ground and some smaller islands floating above
// Big
var island = { Algo=MAPALGO_Polygon, X=[0,w,w*6/8,w*2/8], Y=[h*4/10,h*4/10,h*7/10,h*7/10] };
island = { Algo=MAPALGO_Turbulence, Op=island, Amplitude=[0, 8] };
map->Draw("^Ice-ice2", island, [w/10,h*13/20,w*8/10,h*3/20]);
// Make sure one row of inner island is drawn because it's used for player spawns
map->Draw("^Ice-ice2", nil, [w*3/10,h*13/20,w*4/10+1,1]);
// Smaller floating
var n_islands = 12;
while(n_islands--)
{
var x = w*1/10 + Random(w*8/10);
var y = h*2/10 + Random(h*3/10);
map->Draw("^Ice-ice2", nil, [x,y,1,1]);
}
// Player spawns simply in middle of big island
var plrcnt = GetStartupPlayerCount();
g_player_spawn_positions = CreateArray(plrcnt);
for (var i = 0; i < plrcnt; ++i)
{
g_player_spawn_positions[i] = [w*3/10 + i*w*4/10/(plrcnt-1), h*13/20-1];
}
return true;
}
func DrawSmallIslandsMap(proplist map)
{
var w = map.Wdt, h=map.Hgt, x, y, szx, szy;
// Islands in center of map
var n_islands = 35;
while(n_islands--)
{
y = h*3/10 + Random(h*5/10 - 3);
var xrange = w * (y)/(h*9/10);
x = w/2 - xrange/2 + Random(xrange);
szx = Random(3);
szy = 1;
if (y > h/2) szy += Random(2); // lower islands sometimes taller
if (Abs(x-w/2) < w/10) szx += Random(3); // central islands sometimes wider
map->Draw("^Ice-ice2", nil, [x-szx,y,1+2*szx,szy]);
}
// Starting islands for player spawns
var spawn_island_count = GetStartupPlayerCount();
g_player_spawn_positions = CreateArray(spawn_island_count);
for (var i = 0; i < spawn_island_count; ++i)
{
var x = w*2/10 + i * (w*6/10) / (spawn_island_count - 1);
var y = Max(1, h/10) + Abs(x-w/2) * 3*h/10/w;
map->Draw("^Ice-ice2", nil, [x,y,1,1]);
g_player_spawn_positions[i] = [x, y-1];
}
return true;
}

View File

@ -5,9 +5,10 @@ func Initialize()
// Materials: Chests
var i,pos;
var ls_wdt = LandscapeWidth(), ls_hgt = LandscapeHeight();
var top_area_hgt = ls_hgt*[50,80][SCENPAR_MapType]/100;
var chest_area_y = ls_hgt*[0,30][SCENPAR_MapType]/100;
var chest_area_hgt = ls_hgt/2;
for (i=0; i<6; ++i)
if (pos=FindLocation(Loc_InRect(0,0,ls_wdt,top_area_hgt-100), Loc_Wall(CNAT_Bottom))) // Loc_Wall adds us 100 pixels...
if (pos=FindLocation(Loc_InRect(0,chest_area_y,ls_wdt,chest_area_hgt-100), Loc_Wall(CNAT_Bottom))) // Loc_Wall adds us 100 pixels...
{
var chest = CreateObjectAbove(Chest,pos.x,pos.y);
if (chest)
@ -24,27 +25,40 @@ func Initialize()
}
// Materials: Firestones
for (i=0; i<30; ++i)
if (pos=FindLocation(Loc_InRect(0,0,ls_wdt,top_area_hgt), Loc_Solid()))
if (pos=FindLocation(Loc_InRect(0,chest_area_y,ls_wdt,chest_area_hgt), Loc_Solid()))
if (IsFirestoneSpot(pos.x,pos.y))
CreateObjectAbove(Firestone,pos.x,pos.y-1);
// Some firestones in lower half. For ap type 1, more firestones in lower than upper half.
// Some firestones and bombs in lower half. For ap type 1, more firestones in lower than upper half.
for (i=0; i<30; ++i)
if (pos=FindLocation(Loc_InRect(0,ls_hgt/2,ls_wdt,ls_hgt/3), Loc_Solid()))
if (IsFirestoneSpot(pos.x,pos.y))
CreateObjectAbove(Firestone,pos.x,pos.y-1);
CreateObjectAbove([Firestone,IronBomb][Random(Random(3))],pos.x,pos.y-1);
return true;
}
static g_player_spawn_positions, g_map_width, g_player_spawn_index;
func InitializePlayer(int plr)
{
// everything visible
SetFoW(false, plr);
// player positioning. In lower area for both maps becuase starting high is an an advantage.
// Player positioning.
var ls_wdt = LandscapeWidth(), ls_hgt = LandscapeHeight();
var crew = GetCrew(plr);
var start_pos = FindLocation(Loc_InRect(ls_wdt/5,ls_hgt/2,ls_wdt*3/5,ls_hgt/3), Loc_Wall(CNAT_Bottom), Loc_Func(Scenario.IsStartSpot));
if (!start_pos) start_pos = FindLocation(Loc_InRect(ls_wdt/10,0,ls_wdt*8/10,ls_hgt*4/5), Loc_Wall(CNAT_Bottom), Loc_Func(Scenario.IsStartSpot));
if (!start_pos) start_pos = {x=Random(ls_wdt*6/10)+ls_wdt*2/10, y=ls_hgt*58/100};
var crew = GetCrew(plr), start_pos;
// Position by map type?
if (g_player_spawn_positions && g_player_spawn_index < GetLength(g_player_spawn_positions))
{
start_pos = g_player_spawn_positions[g_player_spawn_index++];
var map_zoom = ls_wdt / g_map_width;
start_pos = {x=start_pos[0]*map_zoom+map_zoom/2, y=start_pos[1]*map_zoom};
}
else
{
// Start positions not defined or exhausted: Spawn in lower area for both maps becuase starting high is an an advantage.
start_pos = FindLocation(Loc_InRect(ls_wdt/5,ls_hgt/2,ls_wdt*3/5,ls_hgt/3), Loc_Wall(CNAT_Bottom), Loc_Func(Scenario.IsStartSpot));
if (!start_pos) start_pos = FindLocation(Loc_InRect(ls_wdt/10,0,ls_wdt*8/10,ls_hgt*4/5), Loc_Wall(CNAT_Bottom), Loc_Func(Scenario.IsStartSpot));
if (!start_pos) start_pos = {x=Random(ls_wdt*6/10)+ls_wdt*2/10, y=ls_hgt*58/100};
}
crew->SetPosition(start_pos.x, start_pos.y-10);
// initial material
crew->CreateContents(Shovel);

View File

@ -11,4 +11,8 @@ GraphicsPortraitMaleBrownHair.png, MaleBrownHair.jpg,
GraphicsPortraitMaleDarkHair.png, MaleDarkHair.jpg,
GraphicsPortraitSage.png, Sage.jpg,
GraphicsPortraitYoungster.png, Youngster.jpg,
GraphicsPortraitYoungsterBlond.png, YoungsterBlond.jpg
GraphicsPortraitYoungsterBlond.png, YoungsterBlond.jpg
The following graphics are created by Clonkonaut and are licensed under CC-BY 3.0 (http://creativecommons.org/licenses/by/3.0/):
GraphicsPortraitMime.png, Mime.png, MimeOverlay.png

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -0,0 +1,39 @@
material Clonk_Mime
{
receive_shadows on
technique
{
pass
{
ambient 1.000000 1.000000 1.000000 1.000000
diffuse 1.000000 1.000000 1.000000 1.000000
specular 0.000000 0.000000 0.000000 1.000000 3.000000
emissive 0.000000 0.000000 0.000000 1.000000
texture_unit Overlay
{
texture MimeOverlay.png
tex_address_mode wrap
filtering trilinear
colour_op_ex modulate src_texture src_player_colour
// take alpha from texture only, ignore player alpha
alpha_op_ex source1 src_texture src_player_colour
}
texture_unit Clonk
{
texture Mime.png
tex_address_mode wrap
filtering trilinear
colour_op_ex blend_current_alpha src_current src_texture
// Don't blend alpha, to make sure we have full intensity at the base/overlay border region
alpha_op_ex add src_current src_texture
}
texture_unit Light
{
// apply lighting
colour_op_ex modulate src_current src_diffuse
alpha_op_ex modulate src_current src_diffuse
}
}
}
}

View File

Before

Width:  |  Height:  |  Size: 546 KiB

After

Width:  |  Height:  |  Size: 546 KiB

View File

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 110 KiB

View File

@ -34,6 +34,7 @@ global func SetAlternativeSkin(string skin_name)
["MaleBlackHair", 0, 0x4040ff],
["MaleBrownHair", 0, 0x2020ff],
["MaleDarkHair", 0, 0x406d99],
["Mime", 2, 0xffffff],
["Sage", 0, 0x813100],
["Youngster", 0, 0xba8e37],
["YoungsterBlond", 0, 0x151366]

View File

@ -284,43 +284,3 @@ material CrashedAirplane
}
}
}
material clonkMime
{
receive_shadows on
technique
{
pass
{
ambient 1.000000 1.000000 1.000000 1.000000
diffuse 1.000000 1.000000 1.000000 1.000000
specular 0.000000 0.000000 0.000000 1.000000 3.000000
emissive 0.000000 0.000000 0.000000 1.000000
texture_unit Overlay
{
texture clonkMimeOverlay.png
tex_address_mode wrap
filtering trilinear
colour_op_ex modulate src_texture src_player_colour
// take alpha from texture only, ignore player alpha
alpha_op_ex source1 src_texture src_player_colour
}
texture_unit Clonk
{
texture clonkMime.png
tex_address_mode wrap
filtering trilinear
colour_op_ex blend_current_alpha src_current src_texture
// Don't blend alpha, to make sure we have full intensity at the base/overlay border region
alpha_op_ex add src_current src_texture
}
texture_unit Light
{
// apply lighting
colour_op_ex modulate src_current src_diffuse
alpha_op_ex modulate src_current src_diffuse
}
}
}
}

View File

@ -386,9 +386,8 @@ func Statue_Death()
while (i--) EliminatePlayer(GetPlayerByIndex(i, C4PT_User));
// Statue down :(
CastObjects(Nugget, 5, 10);
Explode(10);
ScheduleCall(nil, Global.GameOver, 50, 1);
return true;
return Explode(10);
}
/* Developer commands */

Binary file not shown.

Before

Width:  |  Height:  |  Size: 292 KiB

After

Width:  |  Height:  |  Size: 293 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View File

@ -28,10 +28,8 @@ func InitializeObjects()
var Tree_Coniferous2003 = CreateObjectAbove(Tree_Coniferous2, 347, 565);
var Tree_Coniferous2004 = CreateObjectAbove(Tree_Coniferous2, 422, 558);
CreateObjectAbove(Tree_Coniferous2, 1329, 384);
CreateObjectAbove(Tree_Coniferous2, 1364, 364);
CreateObjectAbove(Tree_Coniferous2, 1389, 327);
CreateObjectAbove(Tree_Coniferous2, 1295, 398);
CreateObjectAbove(Tree_Coniferous2, 1404, 390);
CreateObjectAbove(Tree_Coniferous2, 1290, 403);
CreateObject(Fern, 1331, 701);
CreateObject(Fern, 1468, 661);
@ -143,7 +141,7 @@ func InitializeObjects()
CreateObject(Loam, 1360, 781);
CreateObject(Loam, 1519, 721);
CreateObject(Loam, 1348, 718);
CreateObject(Loam, 1379, 349);
CreateObject(Loam, 1358, 388);
CreateObject(Loam, 559, 1120);
CreateObject(Loam, 505, 850);
CreateObject(Loam, 517, 858);

View File

@ -259,8 +259,8 @@ func Intro_Stop()
if (plane)
{
plane->FaceLeft();
plane->SetR(-130);
plane->SetPosition(1387, 238);
plane->SetR(-90);
plane->SetPosition(1387, 345);
}
return true;
}

View File

@ -17,9 +17,6 @@ func InitializeObjects()
var Tree_Coniferous_Burned001 = CreateObject(Tree_Coniferous_Burned, 17, 1097);
Tree_Coniferous_Burned001->SetR(10);
var Tree_Coniferous_Burned002 = CreateObject(Tree_Coniferous_Burned, 43, 1246);
Tree_Coniferous_Burned002->SetCon(75);
Tree_Coniferous_Burned002->SetR(100);
var Tree_Coniferous001 = CreateObject(Tree_Coniferous, 415, 1117);
Tree_Coniferous001->SetR(10);
@ -118,16 +115,6 @@ func InitializeObjects()
var Fern002 = CreateObject(Fern, 276, 1442);
Fern002->SetCon(22);
CreateObjectAbove(Tree_Coniferous, 408, 1167);
var Tree_Coniferous002 = CreateObject(Tree_Coniferous, 408, 1191);
Tree_Coniferous002->SetCon(47);
var Tree_Coniferous003 = CreateObjectAbove(Tree_Coniferous, 217, 1191);
Tree_Coniferous003->SetCon(39);
var Tree_Coniferous004 = CreateObject(Tree_Coniferous, 392, 1148);
Tree_Coniferous004->SetCon(27);
var Tree_Coniferous005 = CreateObject(Tree_Coniferous, 410, 1168);
Tree_Coniferous005->SetCon(3);
g_ruin1 = CreateObject(Ruin_WoodenCabin, 97, 1150);
g_ruin1->SetR(16);
g_ruin1.StaticSaveVar = "g_ruin1";

View File

@ -1,4 +1,4 @@
MsgEncounterCave=An intruder tries to steal out gold. Catch him!
MsgEncounterCave=An intruder tries to steal our gold. Catch him!
MsgEncounterOutpost=Stop, in the name of the king!
MsgEncounterKing=Ah, %s. I have been awaiting you.
MsgEncounterShrooms=What is this in the cave? Fireworks? Maybe we can use them to get into the castle.

View File

@ -352,8 +352,10 @@ func InitializeObjects()
Crate001->CreateContents(Hammer);
ToolsWorkshop001->CreateContents(Hammer, 2);
Foundry002->CreateContents(Bucket, 3);
CreateObjectAbove(Bucket, 435, 1271);
CreateObjectAbove(Bucket, 943, 775);
CreateObjectAbove(Bucket, 944, 775);
CreateObjectAbove(Bucket, 946, 775);
CreateObjectAbove(Crate, 2849, 607);
CreateObjectAbove(Crate, 444, 1271);

View File

@ -114,7 +114,7 @@ Mave7=Wie komme ich über den See?
Mave8=Du könntest meinen Hochofen nutzen, um Lehm zu bauen.
Mave9=Wie funktioniert das mit dem Lehm?
Mave10=Oh, das ist ganz einfach: Fülle einen Eimer{{Bucket}} mit Erde und ein Fass{{Barrel}} mit Wasser, lege beides in den Hochofen und starte die Lehmproduktion.
Mave11=Die Werkzeuge im Hochofen kannst du benutzen.
Mave11=Die Werkzeuge beim Hochofen kannst du benutzen.
Mave12=Wohin führt der Fahrstuhlschacht?
Mave13=Das ist der Fahrstuhl zur Kammer mit unseren Ölreserven. Leider ist der Weg von einem Vulkan geflutet. Hm. Vielleicht könnte man das Wasser aus dem See benutzen, um die Lava abzukühlen.
MaveBye=Tschüss.

View File

@ -114,7 +114,7 @@ Mave7=How do I cross the lake?
Mave8=You could use my foundry to build some loam.
Mave9=How do I build loam?
Mave10=Oh, that is easy: Fill a bucket{{Bucket}} with earth and fill a barrel{{Barrel}} with water. Then put both into the foundry and produce loam.
Mave11=You can find the necessary tools in my foundry.
Mave11=You can find the necessary tools in and in front of my foundry.
Mave12=Where does this elevator shaft lead?
Mave13=This elevator leads to the chamber with our oil reserves. Unfortunately, the path got flooded by the volcano. Maybe water from the lake can be used to extinguish the lava?
MaveBye=Bye.

View File

@ -6,7 +6,6 @@ Width=512
Height=350
Offset=-256,-175
Picture=0,0,220,110
Exclusive=1
Components=Cloud=1
Oversize=1
StretchGrowth=1

View File

@ -904,6 +904,8 @@ private func OnContentsSelection(symbol, extra_data)
for (var obj in to_transfer)
{
if (!obj) continue;
// Our target might have disappeared (e.g. a construction site completing after the first item).
if (!other_target) break;
var handled = false;
// Does the object not want to leave the other container anyway?
@ -924,7 +926,7 @@ private func OnContentsSelection(symbol, extra_data)
// More special handling for Stackable items..
handled = obj->~TryPutInto(other_target);
// Try to normally collect the object otherwise.
if (!handled)
if (!handled && other_target && obj)
handled = other_target->Collect(obj, true);
}
if (handled)

View File

@ -193,8 +193,7 @@ public func StopDialogue()
// clear remembered positions
dlg_last_opt_sel = nil;
// put on wait for a while; then reenable
SetDialogueStatus(DLG_Status_Wait);
ScheduleCall(this, this.SetDialogueStatus, 30, 1, DLG_Status_Stop);
SetDialogueStatus(DLG_Status_Stop);
return true;
}
@ -245,7 +244,8 @@ public func Interact(object clonk)
if (dlg_status == DLG_Status_Stop)
{
clonk->CloseMenu();
dlg_status = DLG_Status_Active;
dlg_status = DLG_Status_Wait;
ScheduleCall(this, this.SetDialogueStatus, 30, 0, DLG_Status_Active);
// Do a call on a closed dialogue as well.
var fn_closed = Format("~Dlg_%s_Closed", dlg_name);
if (!Call(fn_closed, clonk, dlg_target))

View File

@ -52,7 +52,10 @@ func ControlUseStart(object clonk, int ix, int iy)
clonk->SetHandAction(1);
clonk->UpdateAttach();
clonk->PlayAnimation("StrikePickaxe", CLONK_ANIM_SLOT_Arms, Anim_Linear(0, 0, clonk->GetAnimationLength("StrikePickaxe"), Pickaxe_SwingTime, ANIM_Loop), Anim_Const(1000));
AddEffect("IntPickaxe", clonk, 1, 1, this);
var fx = AddEffect("IntPickaxe", clonk, 1, 1, this);
if (!fx) return false;
fx.x = ix;
fx.y = iy;
return true;
}
@ -66,13 +69,12 @@ func ControlUseHolding(object clonk, int new_x, int new_y)
clonk->PauseUse(this);
return true;
}
x = new_x; y = new_y;
var fx = GetEffect("IntPickaxe", clonk);
if (!fx) return clonk->CancelUse();
fx.x = new_x; fx.y = new_y;
return true;
}
local x, y;
func ControlUseStop(object clonk, int ix, int iy)
{
Reset(clonk);
@ -181,11 +183,11 @@ public func FxIntPickaxeTimer(object clonk, proplist effect, int time)
++swingtime;
if(swingtime >= Pickaxe_SwingTime) // Waits three seconds for animation to run (we could have a clonk swing his pick 3 times)
{
DoSwing(clonk,x,y);
DoSwing(clonk,effect.x,effect.y);
swingtime = 0;
}
var angle = Angle(0,0,x,y);
var angle = Angle(0,0,effect.x,effect.y);
var speed = 50;
var iPosition = swingtime*180/Pickaxe_SwingTime;

View File

@ -59,7 +59,7 @@ public func GetConnectedObject(object obj)
private func LineBreak(bool no_msg)
{
Sound("LineBreak");
Sound("Objects::LineSnap");
if (!no_msg)
BreakMessage();

View File

@ -38,6 +38,8 @@ public func ControlUseStart(object clonk, int x, int y)
DigFree(clonk->GetX(), clonk->GetY(), 10);
}
ControlUseHolding(clonk, x, y); // initial coordinate setup
return true;
}
@ -137,10 +139,10 @@ public func FxShovelDigTimer(object clonk, effect, int time)
var iPosition = clonk->GetAnimationPosition(iAnimation)*180/clonk->GetAnimationLength("Dig");
speed = speed*(Cos(iPosition-45, 50)**2)/2500;
// limit angle
DigAngle = BoundBy(DigAngle,65,300);
var dig_xdir = Sin(DigAngle,+speed);
var dig_ydir = Cos(DigAngle,-speed);
// Limit the digging angle: one can dig maximally 30 degrees upwards.
DigAngle = BoundBy(DigAngle, 60, 300);
var dig_xdir = Sin(DigAngle, speed);
var dig_ydir = -Cos(DigAngle, speed);
// Stuck-check: When player wants to go horizontally while standing on the ground but can't, add a vertical redirect
// This helps with Clonks getting "stuck" not moving on certain terrain when dig speed is not sufficient to push him up a slope

View File

@ -227,12 +227,12 @@ global func FxTeleGloveReleasedStart(object target, effect)
return;
}
global func FxTeleGloveWeightStart(object target, int num)
global func FxTeleGloveWeightStart(object target, proplist effect)
{
target->SetMass(target->GetMass()/2);
}
global func FxTeleGloveWeightStop(object target, int num, int reason, bool temp)
global func FxTeleGloveWeightStop(object target, proplist effect, int reason, bool temp)
{
target->SetMass(target->GetDefCoreVal("Mass", "DefCore"));
}

View File

@ -9,9 +9,10 @@ static const CONSTRUCTION_STICK_Left = 1;
static const CONSTRUCTION_STICK_Right = 2;
static const CONSTRUCTION_STICK_Bottom = 4;
local dimension_x, dimension_y, clonk, structure, direction, stick_to, blocked;
local extra_overlay, dimension_x, dimension_y, clonk, structure, direction, stick_to, blocked;
local GFX_StructureOverlay = 1;
local GFX_CombineIconOverlay = 2;
local GFX_PreviewerPictureOverlay = 2;
public func GetFlipDescription() { return "$TxtFlipDesc$"; }
@ -23,14 +24,19 @@ func Initialize()
func Set(id to_construct, object constructing_clonk)
{
SetGraphics(nil, to_construct, GFX_StructureOverlay, GFXOV_MODE_Base);
SetGraphics(nil, to_construct, 3, GFXOV_MODE_Picture, nil, GFX_BLIT_Wireframe);
SetGraphics(nil, to_construct, GFX_PreviewerPictureOverlay, GFXOV_MODE_Picture, nil, GFX_BLIT_Wireframe);
// Buildings may add something to the preview and can do so on GFX_PreviewerPictureOverlay
// This is used by the elevator to preview the case
// The definition should return true
extra_overlay = to_construct->~ConstructionPreview(this, GFX_PreviewerPictureOverlay, direction);
dimension_x = to_construct->GetDefWidth();
dimension_y = to_construct->GetDefHeight();
clonk = constructing_clonk;
structure = to_construct;
direction = DIR_Left;
blocked = true;
// Allow the definition to draw an alternative preview.
to_construct->~AlternativeConstructionPreview(this, direction);
AdjustPreview(structure->~IsBelowSurfaceConstruction());
return;
}
@ -60,7 +66,10 @@ public func AdjustPreview(bool below_surface, bool look_up, bool no_call)
if (blocked && !no_call)
return AdjustPreview(below_surface, !look_up, true);
if (blocked)
{
if (extra_overlay) SetClrModulation(RGBa(255,50,50, 100), GFX_PreviewerPictureOverlay);
return SetClrModulation(RGBa(255,50,50, 100), GFX_StructureOverlay);
}
// Position depends on whether the object should below surface.
if (!below_surface)
SetPosition(GetX(), GetY() + y);
@ -80,12 +89,21 @@ public func AdjustPreview(bool below_surface, bool look_up, bool no_call)
if(!blocked)
{
if (!stick_to)
{
if (extra_overlay) SetClrModulation(RGBa(50,255,50, 100), GFX_PreviewerPictureOverlay);
SetClrModulation(RGBa(50,255,50, 100), GFX_StructureOverlay);
}
else
{
if (extra_overlay) SetClrModulation(RGBa(255,255,50, 200), GFX_PreviewerPictureOverlay);
SetClrModulation(RGBa(255,255,50, 200), GFX_StructureOverlay);
}
}
else
{
if (extra_overlay) SetClrModulation(RGBa(255,50,50, 100), GFX_PreviewerPictureOverlay);
SetClrModulation(RGBa(255,50,50, 100), GFX_StructureOverlay);
}
}
// Positions the preview according to the mouse cursor, calls AdjustPreview afterwards
@ -119,6 +137,14 @@ func Reposition(int x, int y)
x = other->GetX() + other->GetObjWidth()/2 + dimension_x / 2;
if ((stick_dir & CONSTRUCTION_STICK_Bottom))
y = other->GetY() + other->GetObjHeight()/2 + dimension_y / 2;
// Add an additional offset if needed, for example a basement can be place
// only under a part of the structure.
var stick_offset = structure->~ConstructionCombineOffset(other);
if (stick_offset)
{
x += stick_offset[0];
y += stick_offset[1];
}
stick_to = other;
found = true;
}
@ -134,7 +160,7 @@ func Reposition(int x, int y)
stick_to = nil;
SetGraphics(nil, nil, GFX_CombineIconOverlay);
}
else if (stick_to)
else if (stick_to)
{
SetGraphics(nil, ConstructionPreviewer_IconCombine, GFX_CombineIconOverlay, GFXOV_MODE_Base);
var dir = 1;
@ -143,7 +169,10 @@ func Reposition(int x, int y)
dir = 0;
SetObjDrawTransform(1000, 0, dimension_x/2 * 1000 * dir, 0, 1000, 0, GFX_CombineIconOverlay);
}
// Update the extra overlay possibly added to the preview.
extra_overlay = structure->~ConstructionPreview(this, GFX_PreviewerPictureOverlay, direction);
// Update alternative preview in the definition to be placed.
structure->~AlternativeConstructionPreview(this, direction, stick_to);
SetPosition(x, y);
AdjustPreview(structure->~IsBelowSurfaceConstruction());
}
@ -162,6 +191,8 @@ func Flip()
direction = DIR_Left;
SetObjDrawTransform(1000,0,0, 0,1000,0, GFX_StructureOverlay);
}
if (extra_overlay)
structure->~ConstructionPreview(this, GFX_PreviewerPictureOverlay, direction);
}
// UI not saved.

View File

@ -133,13 +133,19 @@ public func Set(id def, int dir, object stick)
definition = def;
direction = dir;
stick_to = stick;
// Set the shape of the construction site.
var w = def->~GetSiteWidth(direction, stick_to) ?? def->GetDefWidth();
var h = def->~GetSiteHeight(direction, stick_to) ?? def->GetDefHeight();
// Height of construction site needs to exceed 12 pixels for the clonk to be able to add materials.
var site_h = Max(12, h);
SetShape(-w/2, -site_h, w, site_h);
// Increase shape for below surface constructions to allow for adding materials.
if (definition->~IsBelowSurfaceConstruction())
SetShape(-w/2, -2 * site_h, w, 2 * site_h);
var xw = (1 - dir * 2) * 1000;
var w, h;
w = def->GetDefWidth();
h = def->GetDefHeight();
// Draw the building with a wired frame and large alpha unless site graphics is overloaded by definition
if (!def->~SetConstructionSiteOverlay(this, direction, stick_to))
if (!definition->~SetConstructionSiteOverlay(this, direction, stick_to))
{
SetGraphics(nil, nil, 0);
SetGraphics(nil, def, 1, GFXOV_MODE_Base);
@ -151,22 +157,14 @@ public func Set(id def, int dir, object stick)
SetClrModulation(RGBa(255, 255, 255, 50), 1);
SetGraphics(nil, def, 2, GFXOV_MODE_Base, nil, GFX_BLIT_Wireframe);
}
SetGraphics("", GetID(), 3, GFXOV_MODE_ExtraGraphics);
SetObjDrawTransform((1 - dir * 2) * 1000, 0, 0, 0, 1000, -h * 500, 1);
SetObjDrawTransform((1 - dir * 2) * 1000, 0, 0, 0, 1000, -h * 500, 2);
}
SetObjDrawTransform(xw,0,0,0,1000, -h*500,1);
SetObjDrawTransform(xw,0,0,0,1000, -h*500,2);
// Height of construction site needs to exceed 12 pixels for the clonk to be able to add materials.
h = Max(12, h);
SetShape(-w/2, -h, w, h);
// Increase shape for below surface constructions to allow for adding materials.
if (definition->~IsBelowSurfaceConstruction())
SetShape(-w/2, -2 * h, w, 2 * h);
SetName(Format(Translate("TxtConstruction"),def->GetName()));
this.visibility = VIS_Owner | VIS_Allies;
SetName(Format(Translate("TxtConstruction"), def->GetName()));
this.visibility = VIS_Owner | VIS_Allies;
ShowMissingComponents();
return;
}
// Scenario saving

View File

@ -128,14 +128,14 @@ public func IsFulfilled() { return true; }
// Overload: return the current description for this goal.
public func GetDescription(int plr)
{
return "WARNING: GetDescription(int plr) not overloaded by goal";
return this.Description ?? "WARNING: GetDescription(int plr) not overloaded by goal";
}
protected func Activate(plr)
{
if (IsFulfilled())
return(MessageWindow("$MsgGoalFulfilled$", plr));
return MessageWindow(GetProperty("Description"), plr);
return MessageWindow(this->GetDescription(plr));
}
// Scenario sacing

View File

@ -0,0 +1,4 @@
[DefCore]
id=Library_PowerDisplay
Version=6,0
Category=C4D_StaticBack

View File

@ -0,0 +1,145 @@
/**
Power Display
Include this library into a structure that should display
the status of the power network in the interaction menu.
@author Maikel
*/
// This object is a power display.
public func IsPowerDisplay() { return true; }
/*-- Interaction Menu --*/
public func HasInteractionMenu() { return true; }
public func GetInteractionMenus(object clonk)
{
var menus = _inherited() ?? [];
// Only add a power menu if the structure is a flagpole (Library_Flag).
if (this->~IsFlagpole())
{
var power_menu =
{
title = "$MsgPowerOverview$",
entries_callback = this.GetPowerDisplayMenuEntries,
callback_hover = "OnPowerDisplayHover",
callback_target = this,
BackgroundColor = RGB(0, 50, 50),
Priority = 20
};
PushBack(menus, power_menu);
}
return menus;
}
public func GetPowerDisplayMenuEntries(object clonk)
{
var menu_entries = [];
// Get the power network for this object.
var power_network = this->GetPowerHelper();
if (!power_network)
return menu_entries;
// Get all the power data.
var power_production_current = power_network->GetActivePowerAvailable(true) / 10;
var power_production_capacity = power_network->GetBarePowerAvailable() / 10;
var power_consumption_current = power_network->GetPowerConsumption(true) / 10;
var power_consumption_need = power_network->GetPowerConsumptionNeed() / 10;
var power_stored = power_network->GetStoredPower();
var power_stored_capacity = power_network->GetStoredPowerCapacity();
// Show power production.
var entry =
{
Bottom = "1.1em",
BackgroundColor = {Std = 0, OnHover = 0x50ff0000},
Priority = 0,
text =
{
Style = GUI_TextVCenter | GUI_TextLeft,
Text = Format("$MsgPowerProduction$ %d {{Icon_Lightbulb}} ($MsgPowerProductionCapacity$ %d {{Icon_Lightbulb}})", power_production_current, power_production_capacity)
}
};
PushBack(menu_entries, {symbol = Icon_Lightbulb, extra_data = "production", custom = entry});
// Show power consumption.
var entry =
{
Bottom = "1.1em",
BackgroundColor = {Std = 0, OnHover = 0x50ff0000},
Priority = 1,
text =
{
Style = GUI_TextVCenter | GUI_TextLeft,
Text = Format("$MsgPowerConsumption$ %d {{Icon_Lightbulb}} ($MsgPowerConsumptionDemand$ %d {{Icon_Lightbulb}})", power_consumption_current, power_consumption_need)
}
};
PushBack(menu_entries, {symbol = Icon_Lightbulb, extra_data = "consumption", custom = entry});
// Show power storage.
var entry =
{
Bottom = "1.1em",
BackgroundColor = {Std = 0, OnHover = 0x50ff0000},
Priority = 2,
text =
{
Style = GUI_TextVCenter | GUI_TextLeft,
Text = Format("$MsgPowerStored$ %s {{Icon_Lightbulb}} ($MsgPowerStoredCapacity$ %s {{Icon_Lightbulb}})", GetStoredPowerString(power_stored), GetStoredPowerString(power_stored_capacity))
}
};
PushBack(menu_entries, {symbol = Icon_Lightbulb, extra_data = "storage", custom = entry});
return menu_entries;
}
// Update the hover info display of the interaction menu.
public func OnPowerDisplayHover(id symbol, string extra_data, desc_menu_target, menu_id)
{
var text = "";
// Get the power network for this object.
var power_network = this->GetPowerHelper();
if (power_network)
{
// Display the info dependent on which items is hovered.
if (extra_data == "production")
{
var power_production_current = power_network->GetActivePowerAvailable(true) / 10;
var power_production_capacity = power_network->GetBarePowerAvailable() / 10;
text = Format("$DescPowerProduction$", power_production_capacity, power_production_current);
}
else if (extra_data == "consumption")
{
var power_consumption_current = power_network->GetPowerConsumption(true) / 10;
var power_consumption_need = power_network->GetPowerConsumptionNeed() / 10;
text = Format("$DescPowerConsumption$", power_consumption_need, power_consumption_current);
}
else if (extra_data == "storage")
{
var power_stored = GetStoredPowerString(power_network->GetStoredPower());
var power_stored_capacity = GetStoredPowerString(power_network->GetStoredPowerCapacity());
text = Format("$DescPowerStored$", power_stored, power_stored_capacity, power_stored);
}
}
GuiUpdateText(text, menu_id, 1, desc_menu_target);
return;
}
private func GetStoredPowerString(int stored_power)
{
// Show power per bulb per minute.
stored_power /= (36 * 60);
var unit = stored_power / 10;
var decimal = stored_power % 10;
return Format("%d.%d", unit, decimal);
}
// Called when the power balance of this network changed.
public func OnPowerBalanceChange(object network)
{
// Update the interaction menus.
UpdateInteractionMenus(this.GetPowerDisplayMenuEntries);
return;
}

View File

@ -0,0 +1,11 @@
MsgPowerOverview=Stromübersicht
MsgPowerProduction=Stromproduktion:
MsgPowerProductionCapacity=gesamte Kapazität
MsgPowerConsumption=Stromverbrauch:
MsgPowerConsumptionDemand=gesamte Nachfrage
MsgPowerStored=Gespeicherter Strom:
MsgPowerStoredCapacity=gesamte Kapazität
DescPowerProduction=All the power producers in this network together have a capacity of producing %d {{Icon_Lightbulb}}, currently %d {{Icon_Lightbulb}} is being produced.
DescPowerConsumption=Currently the consumers in this network demand %d {{Icon_Lightbulb}} in total to operate, %d {{Icon_Lightbulb}} is currently being supplied.
DescPowerStored=Power storages are currently holding %s {{Icon_Lightbulb}} out of their total capacity of %s {{Icon_Lightbulb}}. This is equivalent of powering a consumer using up one {{Icon_Lightbulb}} for %s minutes.

View File

@ -0,0 +1,11 @@
MsgPowerOverview=Power Overview
MsgPowerProduction=Power production:
MsgPowerProductionCapacity=total capacity
MsgPowerConsumption=Power consumption:
MsgPowerConsumptionDemand=total demand
MsgPowerStored=Stored power:
MsgPowerStoredCapacity=total capacity
DescPowerProduction=All the power producers in this network together have a capacity of producing %d {{Icon_Lightbulb}}, currently %d {{Icon_Lightbulb}} is being produced.
DescPowerConsumption=Currently the consumers in this network demand %d {{Icon_Lightbulb}} in total to operate, %d {{Icon_Lightbulb}} is currently being supplied.
DescPowerStored=Power storages are currently holding %s {{Icon_Lightbulb}} out of their total capacity of %s {{Icon_Lightbulb}}. This is equivalent of powering a consumer using up one {{Icon_Lightbulb}} for %s minutes.

View File

@ -440,6 +440,8 @@ public func CheckPowerBalance()
// The producers may be underproducing, however, still producing too much for the
// active consumer need. Deactivate producers to correct for this.
PostRefreshProducers(GetActivePowerAvailable() - GetPowerConsumption());
// Notify other objects depending on the power system the balance has changed.
NotifyOnPowerBalanceChange();
// Debugging logs.
//LogState(Format("balance_end nd_power = %d, av_power = %d", needed_power, GetActivePowerAvailable()));
return;
@ -477,13 +479,13 @@ public func GetBarePowerAvailable()
}
// Returns the total active power available in the network.
public func GetActivePowerAvailable()
public func GetActivePowerAvailable(bool exclude_storages)
{
var total = 0;
for (var index = GetLength(lib_power.active_producers) - 1; index >= 0; index--)
{
var link = lib_power.active_producers[index];
if (!link)
if (!link || (exclude_storages && link.obj->~IsPowerStorage()))
continue;
total += link.prod_amount;
}
@ -491,14 +493,14 @@ public func GetActivePowerAvailable()
}
// Returns the amount of power the currently active power consumers need.
public func GetPowerConsumption()
public func GetPowerConsumption(bool exclude_storages)
{
var total = 0;
for (var index = GetLength(lib_power.active_consumers) - 1; index >= 0; index--)
{
var link = lib_power.active_consumers[index];
// If the link does not exist or has no power need, just continue.
if (!link || !link.obj->HasPowerNeed())
if (!link || !link.obj->HasPowerNeed() || (exclude_storages && link.obj->~IsPowerStorage()))
continue;
total += link.cons_amount;
}
@ -521,6 +523,34 @@ public func GetPowerConsumptionNeed()
return total;
}
// Returns the total stored power of all power storages in the network (in power frames).
public func GetStoredPower()
{
var total = 0;
var all_links = GetAllPowerLinks();
for (var index = GetLength(all_links) - 1; index >= 0; index--)
{
var link = all_links[index];
if (link && link.obj->~IsPowerStorage())
total += link.obj->GetStoredPower();
}
return total;
}
// Returns the total capacity for storing power of all power storages in the network (in power frames).
public func GetStoredPowerCapacity()
{
var total = 0;
var all_links = GetAllPowerLinks();
for (var index = GetLength(all_links) - 1; index >= 0; index--)
{
var link = all_links[index];
if (link && link.obj->~IsPowerStorage())
total += link.obj->GetStorageCapacity();
}
return total;
}
// Activates producers according to priotrity from all producers in the network until needed power is met.
// This function automatically deactivates producers which had a lower priority over newly activated ones.
private func RefreshProducers(int power_need)
@ -731,6 +761,18 @@ private func UpdatePriorities(array link_list, bool for_consumers)
return;
}
// Called when the power balance of this network changes: notify other objects depending on this.
private func NotifyOnPowerBalanceChange()
{
// Notify all power display objects a balance change has occured.
for (var display_obj in FindObjects(Find_Func("IsPowerDisplay")))
{
if (Library_Power->GetPowerNetwork(display_obj) == this)
display_obj->~OnPowerBalanceChange(this);
}
return;
}
/*-- Network State --*/
@ -767,6 +809,29 @@ public func GetConsumerLink(object link)
return;
}
// Returns a list of all the power links in this network.
public func GetAllPowerLinks()
{
// Combine producers and consumers into a list of all links.
var all_producers = Concatenate(lib_power.idle_producers, lib_power.active_producers);
var all_consumers = Concatenate(lib_power.waiting_consumers, lib_power.active_consumers);
var all_links = Concatenate(all_producers, all_consumers);
// Remove duplicate entries with the same link object.
for (var index = GetLength(all_links) - 1; index >= 1; index--)
{
var obj = all_links[index].obj;
for (var test_index = index - 1; test_index >= 0; test_index--)
{
if (obj == all_links[test_index].obj)
{
RemoveArrayIndex(all_links, index);
break;
}
}
}
return all_links;
}
/*-- Logging --*/

View File

@ -112,14 +112,28 @@ public func GetProductionMenuEntries(object clonk)
PushBack(menu_entries, {symbol = product, extra_data = nil, custom = entry});
}
// At the bottom of the menu, we add some helpful information about the additional features.
// Below the symbols, we leave some space for a progress bar to indicate the current product progress.
var entry =
{
Style = GUI_TextBottom,
Bottom = "2em", BackgroundColor = RGBa(0, 0, 0, 100),
Bottom = "1em", BackgroundColor = RGBa(0, 0, 0, 50),
Priority = 999998,
bar =
{
BackgroundColor = RGBa(200, 200, 200, 100),
Right = "0%"
}
};
var updating_effect = AddEffect("IntUpgradeProductProgressBar", this, 1, 2, this);
PushBack(menu_entries, {symbol = nil, extra_data = nil, custom = entry, fx = updating_effect});
// At the bottom of the menu, we add some helpful information about the additional features.
entry =
{
Style = GUI_TextBottom | GUI_FitChildren,
Bottom = "1em", BackgroundColor = RGBa(0, 0, 0, 100),
Priority = 999999,
Text = Format("<c 666666>%s + $Click$: $InfiniteProduction$</c>", GetPlayerControlAssignment(clonk->GetOwner(), CON_ModifierMenu1, true))
};
PushBack(menu_entries, {symbol = nil, extra_data = nil, custom = entry});
return menu_entries;
}
@ -180,6 +194,43 @@ private func GetCostString(int amount, bool available)
return Format("<c ff0000>%dx</c>", amount);
}
public func FxIntUpgradeProductProgressBarOnMenuOpened(object target, effect fx, int main_ID, int entry_ID, proplist menu_target)
{
fx.main_ID = main_ID;
fx.entry_ID = entry_ID;
fx.menu_target = menu_target;
// Force update on first 'Timer' call.
fx.is_showing = true;
EffectCall(target, fx, "Timer");
}
public func FxIntUpgradeProductProgressBarTimer(object target, effect fx, int time)
{
if (fx.menu_target == nil) return FX_OK;
// Find (new?) production effect if not already given.
if (fx.production_effect == nil)
{
fx.production_effect = GetEffect("ProcessProduction", this);
if (fx.production_effect == nil)
{
if (fx.is_showing)
{
fx.is_showing = false;
GuiUpdate({Text = "<c 777777>$Producing$: -</c>", bar = {Right = "0%"}}, fx.main_ID, fx.entry_ID, fx.menu_target);
}
return FX_OK;
}
}
fx.is_showing = true;
var max = ProductionTime(fx.production_effect.Product);
var current = Min(max, fx.production_effect.Duration);
var percent = 1000 * current / max;
var percent_string = Format("%d.%d%%", percent / 10, percent % 10);
GuiUpdate({Text = Format("<c aaaaaa>$Producing$: %s</c>", fx.production_effect.Product->GetName()), bar = {Right = percent_string}}, fx.main_ID, fx.entry_ID, fx.menu_target);
return FX_OK;
}
/*-- Production properties --*/
// This function may be overloaded by the actual producer.

View File

@ -1,4 +1,5 @@
Production=Produktion
Producing=Produziert
QueueRemove=Eins weniger produzieren.
InfiniteProduction=Endlosproduktion
Click=Klick

View File

@ -1,4 +1,5 @@
Production=Production
Producing=Producing
QueueRemove=Produce one less.
InfiniteProduction=Infinite production
Click=Click

View File

@ -122,7 +122,14 @@ private func TransferInventory(object from, object to)
while (i--)
if (contents = from->Contents(i))
if (contents->~IsDroppedOnDeath(from))
{
contents->Exit();
}
else
{
// The new clonk doesn't burn. To be consistent, also extinguish contents
contents->Extinguish();
}
return to->GrabContents(from);
}

View File

@ -19,12 +19,16 @@ protected func Construction()
protected func Initialize()
{
var wdt = BoundBy(GetObjWidth(), 8, 120);
var wdt = GetObjWidth();
if (parent)
wdt = BoundBy(parent->GetObjWidth(), 8, 120);
SetWidth(wdt);
{
wdt = parent->~GetBasementWidth();
if (wdt == nil)
wdt = parent->GetObjWidth();
}
SetWidth(BoundBy(wdt, 8, 120));
// Move objects out of the basement.
MoveOutOfSolidMask();
MoveOutOfSolidMask();
return _inherited(...);
}
@ -54,10 +58,13 @@ public func CombineWith(object stick_to)
return;
}
public func SetParent(object to_parent)
public func SetParent(object to_parent)
{
parent = to_parent;
SetWidth(BoundBy(parent->GetObjWidth(), 8, 120));
var wdt = parent->~GetBasementWidth();
if (wdt == nil)
wdt = parent->GetObjWidth();
SetWidth(BoundBy(wdt, 8, 120));
// Notify the parent.
parent->~SetBasement(this);
return;
@ -71,9 +78,42 @@ public func IsBelowSurfaceConstruction() { return true; }
// Sticking to other structures, at the bottom of that structure.
public func ConstructionCombineWith() { return "IsStructureWithoutBasement"; }
public func ConstructionCombineDirection() { return CONSTRUCTION_STICK_Bottom; }
public func ConstructionCombineOffset(object other)
{
// Some structures like the elevator require the basement to have an offset.
return other->~GetBasementOffset();
}
public func NoConstructionFlip() { return true; }
public func AlternativeConstructionPreview(object previewer, int direction, object combine_with)
{
var wdt = GetSiteWidth(direction, combine_with);
previewer->SetObjDrawTransform(1000 * wdt / 40, 0, 0, 0, 1000, 0, previewer.GFX_StructureOverlay);
return;
}
public func GetSiteWidth(int direction, object combine_with)
{
var wdt = GetDefWidth();
if (combine_with)
{
wdt = combine_with->~GetBasementWidth();
if (wdt == nil)
wdt = combine_with->GetObjWidth();
}
return BoundBy(wdt, 8, 120);
}
public func SetConstructionSiteOverlay(object site, int direction, object combine_with)
{
var wdt = GetSiteWidth(direction, combine_with);
site->SetGraphics(nil, Basement, 1, GFXOV_MODE_Base);
site->SetClrModulation(RGBa(255, 255, 255, 128), 1);
site->SetObjDrawTransform(1000 * wdt / 40, 0, 0, 0, 1000, -4000, 1);
return true;
}
// Don't stick to itself, so it should not be a structure.
public func IsStructure() { return false; }

View File

@ -214,6 +214,16 @@ private func UpdateTurnSpeed()
/* Construction preview */
// Definition call by the construction previewer
public func ConstructionPreview(object previewer, int overlay, int dir)
{
if (GetType(this) != C4V_Def) return;
previewer->SetGraphics(nil, Elevator_Case_Front, overlay, GFXOV_MODE_Base);
previewer->SetObjDrawTransform(1000, 0, -19000 * (dir*2-1), 0, 1000, 17000, overlay);
return true;
}
// Sticking to other elevators
public func ConstructionCombineWith() { return "IsElevator"; }
public func ConstructionCombineDirection() { return CONSTRUCTION_STICK_Left | CONSTRUCTION_STICK_Right; }
@ -241,6 +251,11 @@ public func CombineWith(object other)
partner = other;
}
// Special requirements for the basement of the elevator.
public func GetBasementWidth() { return 36; }
public func GetBasementOffset() { return [11 * (2 * GetDir() - 1), 0]; }
/* Combination */
// Called by a new elevator next to this one

View File

@ -4,6 +4,7 @@
#include Library_Structure
#include Library_Flag
#include Library_Base // Needed for DoBuy...
#include Library_PowerDisplay
local ActMap = {
Fly = {

View File

@ -16,7 +16,6 @@ ColorByOwner=1
Components=Metal=6;Wood=4;
Rotate=1
Entrance=-12,-12,24,24
Exclusive=1
RotatedEntrance=1
VehicleControl=1
NoStabilize=1

View File

@ -249,7 +249,8 @@ protected func DoFire(object iammo, object clonk, int angle)
iammo->SetR(r / angPrec);
iammo->SetRDir(-4 + Random(9));
iammo->LaunchProjectile(r, 17, Fire_Velocity, 0,0, angPrec);
iammo->SetController(clonk->GetController());
if (clonk)
iammo->SetController(clonk->GetController());
iammo->~Fuse();
//Particles

View File

@ -1,7 +0,0 @@
[DefCore]
id=DialogueBoomshire
Version=7,0
Category=C4D_StaticBack
Picture=0,0,64,64
Width=1
Height=1

View File

@ -19,12 +19,9 @@ private func Initialize()
var concierge = CreateObjectAbove(Clonk, 70, 1030, NO_OWNER);
concierge->SetDir(DIR_Left);
concierge->SetSkin(2);
concierge->SetMeshMaterial("clonkMime");
concierge->SetColor(0xffffff);
concierge->SetAlternativeSkin("Mime");
concierge->SetObjectLayer(concierge);
concierge->SetName("$NameConcierge$");
concierge->SetPortrait({ Source = DialogueBoomshire });
concierge->SetDialogue("Concierge");
concierge->Sound("Circus", false, nil, nil, +1, 100);
Dialogue->FindByTarget(concierge)->AddAttention();

View File

@ -23,43 +23,36 @@ func SetPaintCol(int idx)
}
// Impact sound
func Hit()
public func Hit()
{
Sound("Hits::GeneralHit?");
}
// Item activation
func ControlUseStart(object clonk, int x, int y)
public func ControlUseStart(object clonk, int x, int y)
{
if (Distance(0,0,x,y) > max_dist) return true;
x += GetX(); y += GetY();
last_x = x; last_y = y;
last_ldx=last_ldy=0;
var r = Random(90), wdt = 2;
var ldx = Sin(r, wdt), ldy = Cos(r, wdt);
DrawMaterialQuad(paint_col, x-ldx,y-ldy, x-ldy,y+ldx, x+ldx,y+ldy, x+ldy,y-ldx, DMQ_Bridge);
SetAction("Spraying");
return true;
return ControlUseHolding(clonk, x, y);
}
func HoldingEnabled() { return true; }
public func HoldingEnabled() { return true; }
func ControlUseHolding(object clonk, int new_x, int new_y)
{
new_x += GetX(); new_y += GetY();
if (new_x==last_x && new_y == last_y) return true;
if (Distance(GetX(),GetY(),new_x,new_y) > max_dist)
public func ControlUseHolding(object clonk, int new_x, int new_y)
{
// Out of reach? Stop spraying.
if (Distance(0,0,new_x,new_y) > max_dist)
{
last_x = new_x;
last_y = new_y;
SetAction("Idle");
return true;
}
if (GetAction() != "Spraying") SetAction("Spraying");
// Work in global coordinates
new_x += GetX(); new_y += GetY();
// (re-)start spraying
if (GetAction() != "Spraying") StartSpraying(clonk, new_x, new_y);
// Spray paint if position moved
if (new_x==last_x && new_y == last_y) return true;
var wdt = 2;
var dx=new_x-last_x, dy=new_y-last_y;
var d = Distance(dx,dy);
@ -83,6 +76,19 @@ public func ControlUseCancel(object clonk, int x, int y)
return true;
}
private func StartSpraying(object clonk, int x, int y)
{
// Go into spray mode and place an initial blob
last_x = x; last_y = y;
last_ldx=last_ldy=0;
var r = Random(90), wdt = 2;
var ldx = Sin(r, wdt), ldy = Cos(r, wdt);
DrawMaterialQuad(paint_col, x-ldx,y-ldy, x-ldy,y+ldx, x+ldx,y+ldy, x+ldy,y-ldx, DMQ_Bridge);
SetAction("Spraying");
return true;
}
local ActMap = {
Spraying = {
Prototype = Action,

View File

@ -2,12 +2,12 @@
Override screenshot functionality
--*/
global func PlayerControl(int plr, int ctrl)
global func PlayerControl(int plr, int ctrl, ...)
{
if (ctrl == CON_TryScreenshot)
{
CustomMessage(Format("$MsgCheater$", GetTaggedPlayerName(plr)));
Sound("Error", true);
Sound("UI::Error", true);
//var crew = GetCursor(plr); - used for cheating
//if (crew) crew->Punch(crew, 50);
return true;

Binary file not shown.

View File

@ -82,6 +82,7 @@ nicStage - Environemnt/Lightning/Thunder3 (https://www.freesound.org/peop
jrosin - Environemnt/Lightning/Thunder4 (https://www.freesound.org/people/jrosin/sounds/329978/ adapted by Maikel)
shaka9 - Environemnt/Lightning/Thunder5 (https://www.freesound.org/people/shaka9/sounds/160514/ adapted by Maikel)
Harbour11 - UI::Error, UI::Trumpet (both adapted by Sven2; used sound from http://freesound.org/people/Harbour11/sounds/194624/)
CosmicEmbers - Objects::LineSnap (cropped/pitch adjusted by Sven2; original from http://freesound.org/people/CosmicEmbers/sounds/161650/)
The following sounds use two sources:

View File

@ -0,0 +1,29 @@
// Makes sure the guide message is hidden when starting a dialogue and shown again when closing.
#appendto Dialogue
public func Interact(object clonk)
{
if (!dlg_interact || !dlg_name)
return inherited(clonk, ...);
var guide = FindObject(Find_ID(TutorialGuide), Find_Owner(clonk->GetOwner()));
if (!guide)
return inherited(clonk, ...);
if (dlg_status == DLG_Status_Stop)
{
if (this.guide_was_shown)
{
this.guide_was_shown = false;
guide->ShowGuide();
}
}
else if (dlg_status != DLG_Status_Remove && dlg_status != DLG_Status_Wait)
{
if (!guide->IsHidden())
{
this.guide_was_shown = true;
guide->HideGuide();
}
}
return inherited(clonk, ...);
}

View File

@ -62,6 +62,7 @@ private func InitVillageEntrance()
var site = CreateObjectAbove(ConstructionSite, 264, 386);
site.MeshTransformation = Trans_Mul(Trans_Rotate(RandomX(-30, 30), 0, 1, 0), Trans_Rotate(RandomX(-10, 10), 1, 0, 0));
site->Set(Sawmill);
site->MakeUncancellable();
site->CreateContents(Wood, 1);
site->CreateContents(Rock, 1);
@ -202,7 +203,7 @@ private func InitAI()
barrel->SetFilled("Water", 300);
npc_fireman->SetObjectLayer(npc_fireman);
npc_fireman->SetDir(DIR_Left);
npc_fireman->SetDialogue("Fireman", true);
npc_fireman->SetDialogue("Fireman", false);
npc_fireman->SetAlternativeSkin("MaleDarkHair");
// A builder which tells you where to place the flagpole.
@ -211,7 +212,7 @@ private func InitAI()
npc_builder->CreateContents(Hammer);
npc_builder->SetObjectLayer(npc_builder);
npc_builder->SetDir(DIR_Left);
npc_builder->SetDialogue("Builder", true);
npc_builder->SetDialogue("Builder", false);
npc_builder->SetAlternativeSkin("Carpenter");
// A farmer near the grain field.
@ -413,7 +414,9 @@ global func FxTutorialSawmillFinishedTimer(object target, proplist effect)
// Notify lumberjack the sawmill is done.
var dialogue_lumberjack = Dialogue->FindByName("Lumberjack");
if (dialogue_lumberjack)
dialogue_lumberjack->SetDialogueProgress(5, nil, true);
dialogue_lumberjack->SetDialogueProgress(5, nil, false);
Dialogue->FindByName("Fireman")->AddAttention();
Dialogue->FindByName("Builder")->AddAttention();
return FX_Execute_Kill;
}
return FX_OK;
@ -456,6 +459,10 @@ global func FxTutorialPlacedFlagpoleTimer(object target, proplist effect)
guide->ShowGuideMessage();
var new_effect = AddEffect("TutorialTalkedToLumberjack2", nil, 100, 5);
new_effect.plr = effect.plr;
// Notify lumberjack that player talked to other npc's.
var dialogue_lumberjack = Dialogue->FindByName("Lumberjack");
if (dialogue_lumberjack)
dialogue_lumberjack->SetDialogueProgress(6, nil, true);
return FX_Execute_Kill;
}
return FX_OK;

View File

@ -35,27 +35,35 @@ public func Dlg_Lumberjack_4(object clonk)
public func Dlg_Lumberjack_5(object clonk)
{
MessageBox("$DlgLumberjackWellDone$", clonk, dlg_target);
MessageBox("$DlgLumberjackTalkToOthers$", clonk, dlg_target);
StopDialogue();
SetDialogueProgress(5);
return true;
}
public func Dlg_Lumberjack_6(object clonk)
{
MessageBox("$DlgLumberjackFavor$", clonk, clonk);
MessageBox("$DlgLumberjackWellDone$", clonk, dlg_target);
return true;
}
public func Dlg_Lumberjack_7(object clonk)
{
MessageBox("$DlgLumberjackMines$", clonk, dlg_target);
MessageBox("$DlgLumberjackFavor$", clonk, clonk);
return true;
}
public func Dlg_Lumberjack_8(object clonk)
{
MessageBox("$DlgLumberjackMines$", clonk, dlg_target);
return true;
}
public func Dlg_Lumberjack_9(object clonk)
{
MessageBox("$DlgLumberjackLook$", clonk, clonk);
StopDialogue();
SetDialogueProgress(5);
SetDialogueProgress(6);
return true;
}

View File

@ -3,6 +3,7 @@ DlgLumberjackHello=Hallo, ich bin %s, die Holzfällerin des Dorfes.
DlgLumberjackReply=Ich heiße %s. Du schaust traurig aus.
DlgLumberjackSawmill=Ja, das stimmt. Mein Sägewerk wurde zerstört und ich finde keine Steine, um es wieder aufzubauen. Kannst du mir helfen?
DlgLumberjackRock=Ja, ich werde dir Steine finden.
DlgLumberjackTalkToOthers=Danke, vielleicht kannst du jetzt einem der anderen Dorfbewohner helfen.
DlgLumberjackWellDone=Danke vielmals, dass du das Sägewerk aufgebaut hast. Kann ich irgendwas für dich tun?
DlgLumberjackFavor=Tatsächlich kannst du das, ja. Ich brauche Holz, du hast nicht zufällig eine Axt?
DlgLumberjackMines=Nein, leider nicht. Ich habe meine Axt in der Mine fallen gelassen, als ich mich während des Angriffes versteckt habe.

View File

@ -3,6 +3,7 @@ DlgLumberjackHello=Hello I am %s, the lumberjack of this small village.
DlgLumberjackReply=My name is %s, you seem sad.
DlgLumberjackSawmill=Yes, indeed. My sawmill got destroyed and I can't find any rock to rebuild it. Can you help me?
DlgLumberjackRock=Yes, I'll find you some rock.
DlgLumberjackTalkToOthers=Thank you, maybe you can help one of the other villagers now.
DlgLumberjackWellDone=Thanks a lot, for constructing the sawmill. Can I do anything for you?
DlgLumberjackFavor=Actually you can, I need wood, do you happen to have an axe?
DlgLumberjackMines=No, I don't, but I have dropped my axe in the mines when I was hiding there during the attack.

View File

@ -1 +1 @@
Sky.jpg adapted from http://commons.wikimedia.org/wiki/File:Berge_mountains.JPG (Steinsplitter CC BY-SA 3.0)
Sky.jpg adapted from http://commons.wikimedia.org/wiki/File:Berge_mountains.JPG (Steinsplitter CC BY 3.0)

View File

@ -1,5 +1,5 @@
Clonkomotive
A once flourishing train route through Clonkomotive Canyon has been disrupted by heavy rockfall. The rockfall destroyed the necessary bridges to connect the cliffs in between the canyons, thereby disconnecting two villages on the route. You are left with the locomotive in one of the villages and now you need to rebuild the route to the other village. Luckily Nature has settled and the rockfall has become less severe.
Einst florierte die Eisenbahnstrecke durch den Clonkomotive Canyon, doch hat ein schwerer Steinschlag die Strecke zerstört. Die Brücken über die Schluchten wurden sämtlich vernichtet und die beiden Dörfer an den Enden des Canyons sind nun ohne Verbindung. Du findest dich in einem der Dörfer wieder und stehst vor der Aufgabe, die Strecke wieder herzurichten. Glücklicherweise hat sich der Steinschlag etwas beruhigt und ein Aufbau der Strecke ist überhaupt machbar.
Goal: Transport the locomotive to the village on the far right.
Ziel: Bringe die Lokomotive zum Dorf auf der rechten Seite.

View File

@ -1,2 +1,2 @@
Name=HeavyCrumb
Description=Hurts Clonks and buildings!
Name=Felsbrocken
Description=Verletzt Clonks und beschädigt Gebäude.

View File

@ -1,2 +1,2 @@
Name=HeavyCrumb
Description=Hurts Clonks and buildings!
Name=Boulder
Description=Hurts Clonks and damages buildings.

View File

@ -1,4 +1,4 @@
# Intro sequence messages
MsgDriveTrain=We only have to drive this train to the village on the other side of these canyons.
MsgOutOfFuel=Are we out of fuel again?!
MsgBridgesGone=Yes, and it seems all the bridges over the canyons have been destroyed as well.
MsgDriveTrain=Dieser Zug muss zum Dorf auf der anderen Seite des Canyons.
MsgOutOfFuel=Ist der Treibstoff etwa wieder alle?
MsgBridgesGone=Ja, aber die Brücken über die Schluchten sind sowieso zerstört worden.

View File

@ -1113,7 +1113,8 @@ C4Object* C4Game::CreateObjectConstruction(C4PropList * PropList,
return pObj;
}
C4Object* C4Game::OverlapObject(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, int32_t Plane)
// Finds an object (OCF_Exclusive) that blocks a potential construction site in the given rectangle
C4Object* C4Game::FindConstuctionSiteBlock(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt)
{
C4Rect rect1,rect2;
rect1.x=tx; rect1.y=ty; rect1.Wdt=wdt; rect1.Hgt=hgt;
@ -1121,7 +1122,7 @@ C4Object* C4Game::OverlapObject(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt
for (C4ObjectList *pObjs = Area.FirstObjectShapes(&pSector); pSector; pObjs = Area.NextObjectShapes(pObjs, &pSector))
for (C4Object *cObj : *pObjs)
if (cObj->Status && !cObj->Contained)
if (cObj->GetPlane() == Plane)
if (cObj->OCF & OCF_Exclusive)
{
rect2=cObj->Shape; rect2.x+=cObj->GetX(); rect2.y+=cObj->GetY();
if (rect1.Overlap(rect2)) return cObj;

View File

@ -191,7 +191,7 @@ public:
int32_t con=1, bool terrain=false);
C4Object *CreateInfoObject(C4ObjectInfo *cinf, int32_t owner,
int32_t tx=50, int32_t ty=50);
C4Object *OverlapObject(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt, int32_t Plane);
C4Object *FindConstuctionSiteBlock(int32_t tx, int32_t ty, int32_t wdt, int32_t hgt);
C4Object *FindObject(C4Def * pDef,
int32_t iX=0, int32_t iY=0, int32_t iWdt=0, int32_t iHgt=0,
DWORD ocf=OCF_All,

View File

@ -219,10 +219,7 @@ static C4ValueArray *FnFindConstructionSite(C4PropList * _this, C4PropList * Pro
if (ConstructionCheck(PropList,v1,v2))
return NULL;
// Search for real
bool result = !!FindConSiteSpot(v1, v2,
pDef->Shape.Wdt,pDef->Shape.Hgt,
pDef->GetPlane(),
20);
bool result = !!FindConSiteSpot(v1, v2, pDef->Shape.Wdt,pDef->Shape.Hgt, 20);
if(!result) return 0;
C4ValueArray *pArray = new C4ValueArray(2);
pArray->SetItem(0, C4VInt(v1));

View File

@ -368,10 +368,8 @@ void CPNGFile::WaitForSaves()
first = false;
#ifdef HAVE_WINTHREAD
Sleep(100);
#elif defined (__APPLE__)
#else
sched_yield();
#elif defined(HAVE_PTHREAD)
pthread_yield();
#endif
}
}

View File

@ -2709,8 +2709,7 @@ bool FindLevelGround(int32_t &rx, int32_t &ry, int32_t width, int32_t hrange)
// Starting from rx/ry, searches for a width of solid level ground with
// structure clearance (category). Returns bottom center of surface found.
bool FindConSiteSpot(int32_t &rx, int32_t &ry, int32_t wdt, int32_t hgt,
int32_t Plane, int32_t hrange)
bool FindConSiteSpot(int32_t &rx, int32_t &ry, int32_t wdt, int32_t hgt, int32_t hrange)
{
bool fFound=false;
@ -2762,10 +2761,10 @@ bool FindConSiteSpot(int32_t &rx, int32_t &ry, int32_t wdt, int32_t hgt,
// Check runs & object overlap
if (rl1>=wdt) if (cx1>0)
if (!Game.OverlapObject(cx1,cy1-hgt-10,wdt,hgt+40,Plane))
if (!Game.FindConstuctionSiteBlock(cx1,cy1-hgt-10,wdt,hgt+40))
{ rx=cx1+wdt/2; ry=cy1; fFound=true; break; }
if (rl2>=wdt) if (cx2<GBackWdt)
if (!Game.OverlapObject(cx2-wdt,cy2-hgt-10,wdt,hgt+40,Plane))
if (!Game.FindConstuctionSiteBlock(cx2-wdt,cy2-hgt-10,wdt,hgt+40))
{ rx=cx2-wdt/2; ry=cy2; fFound=true; break; }
}
@ -2992,7 +2991,7 @@ bool ConstructionCheck(C4PropList * PropList, int32_t iX, int32_t iY, C4Object *
}
// Check other structures
C4Object *other;
if ((other=Game.OverlapObject(rtx,rty,wdt,hgt,ndef->GetPlane())))
if ((other=Game.FindConstuctionSiteBlock(rtx,rty,wdt,hgt)))
{
if (pByObj) GameMsgObjectError(FormatString(LoadResStr("IDS_OBJ_NOOTHER"),other->GetName ()).getData(),pByObj);
return false;

View File

@ -352,7 +352,7 @@ bool FindLiquid(int32_t &rx, int32_t &ry, int32_t width, int32_t height);
bool FindTunnel(int32_t &rx, int32_t &ry, int32_t width, int32_t height);
bool FindSurfaceLiquid(int32_t &rx, int32_t &ry, int32_t width, int32_t height);
bool FindLevelGround(int32_t &rx, int32_t &ry, int32_t width, int32_t hrange);
bool FindConSiteSpot(int32_t &rx, int32_t &ry, int32_t wdt, int32_t hgt, int32_t Plane, int32_t hrange=-1);
bool FindConSiteSpot(int32_t &rx, int32_t &ry, int32_t wdt, int32_t hgt, int32_t hrange=-1);
bool FindThrowingPosition(int32_t iTx, int32_t iTy, C4Real fXDir, C4Real fYDir, int32_t iHeight, int32_t &rX, int32_t &rY);
bool PathFree(int32_t x1, int32_t y1, int32_t x2, int32_t y2);
bool PathFree(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t *ix, int32_t *iy);

View File

@ -91,22 +91,22 @@ bool C4FoWRegion::BindFramebuf()
if (y < pSurface->Hgt / 2 && x < pSurface->Wdt)
{
// Normals and intensity
pNewSurface->SetPixDw(x, pNewSurface->Hgt/2 - y, pSurface->GetPixDw(x, pSurface->Hgt/2 - y, false));
pNewBackSurface->SetPixDw(x, pNewBackSurface->Hgt/2 - y, pBackSurface->GetPixDw(x, pBackSurface->Hgt/2 - y, false));
pNewSurface->SetPixDw(x, pNewSurface->Hgt/2 - y - 1, pSurface->GetPixDw(x, pSurface->Hgt/2 - y - 1, false));
pNewBackSurface->SetPixDw(x, pNewBackSurface->Hgt/2 - y - 1, pBackSurface->GetPixDw(x, pBackSurface->Hgt/2 - y - 1, false));
// Color
pNewSurface->SetPixDw(x, pNewSurface->Hgt/2 - y + iHgt / 2, pSurface->GetPixDw(x, pSurface->Hgt/2 - y + pSurface->Hgt / 2, false));
pNewBackSurface->SetPixDw(x, pNewBackSurface->Hgt/2 - y + iHgt / 2, pBackSurface->GetPixDw(x, pBackSurface->Hgt/2 - y + pBackSurface->Hgt / 2, false));
pNewSurface->SetPixDw(x, pNewSurface->Hgt/2 - y + iHgt / 2 - 1, pSurface->GetPixDw(x, pSurface->Hgt/2 - y + pSurface->Hgt / 2 - 1, false));
pNewBackSurface->SetPixDw(x, pNewBackSurface->Hgt/2 - y + iHgt / 2 - 1, pBackSurface->GetPixDw(x, pBackSurface->Hgt/2 - y + pBackSurface->Hgt / 2 - 1, false));
}
else
{
// Normals and intensity
pNewSurface->SetPixDw(x, pNewSurface->Hgt/2 - y, 0x000000ff);
pNewBackSurface->SetPixDw(x, pNewBackSurface->Hgt/2 - y, 0x000000ff);
pNewSurface->SetPixDw(x, pNewSurface->Hgt/2 - y - 1, 0x000000ff);
pNewBackSurface->SetPixDw(x, pNewBackSurface->Hgt/2 - y - 1, 0x000000ff);
// Color
pNewSurface->SetPixDw(x, pNewSurface->Hgt/2 - y + iHgt / 2, 0x000000ff);
pNewBackSurface->SetPixDw(x, pNewBackSurface->Hgt/2 - y + iHgt / 2, 0x000000ff);
pNewSurface->SetPixDw(x, pNewSurface->Hgt/2 - y + iHgt / 2 - 1, 0x000000ff);
pNewBackSurface->SetPixDw(x, pNewBackSurface->Hgt/2 - y + iHgt / 2 - 1, 0x000000ff);
}
}
}

View File

@ -880,6 +880,7 @@ void StdMeshInstance::AnimationNode::CompileFunc(StdCompiler* pComp, const StdMe
const StdMeshBone* bone = Mesh->GetSkeleton().GetBoneByName(bone_name);
if(!bone) pComp->excCorrupt("No such bone: \"%s\"", bone_name.getData());
Custom.BoneIndex = bone->Index;
Custom.Transformation = new StdMeshTransformation;
}
else
{

View File

@ -1222,8 +1222,14 @@ void C4Object::DoDamage(int32_t iChange, int32_t iCausedBy, int32_t iCause)
void C4Object::DoEnergy(int32_t iChange, bool fExact, int32_t iCause, int32_t iCausedByPlr)
{
// iChange 100% = Physical 100000
if (!fExact) iChange=iChange*C4MaxPhysical/100;
if (!fExact)
{
// Clamp range of change to prevent integer overflow errors
// Do not clamp directly to (0...MaxEnergy)-current_energy, because
// the change value calculated here may be reduced by effect callbacks
int32_t scale = C4MaxPhysical / 100; // iChange 100% = Physical 100000
iChange = Clamp<int32_t>(iChange, std::numeric_limits<int32_t>::min()/scale, std::numeric_limits<int32_t>::max()/scale)*scale;
}
// Was zero?
bool fWasZero=(Energy==0);
// Mark last damage causing player to trace kills

View File

@ -517,7 +517,7 @@ void C4Player::PlaceReadyBase(int32_t &tx, int32_t &ty, C4Object **pFirstBase)
{
ctx=tx; cty=ty;
if (Game.C4S.PlrStart[PlrStartIndex].EnforcePosition
|| FindConSiteSpot(ctx,cty,def->Shape.Wdt,def->Shape.Hgt,def->GetPlane(),20))
|| FindConSiteSpot(ctx,cty,def->Shape.Wdt,def->Shape.Hgt,20))
if ((cbase=Game.CreateObjectConstruction(C4Id2Def(cid),NULL,Number,ctx,cty,FullCon,true)))
{
// FirstBase
@ -644,7 +644,7 @@ bool C4Player::ScenarioInit()
// Use nearest above-ground...
FindSolidGround(ptx,pty,30);
// Might have hit a small lake, or similar: Seach a real site spot from here
FindConSiteSpot(ptx, pty, 30,50,C4Plane_Structure, 400);
FindConSiteSpot(ptx, pty, 30, 50, 400);
}
// Place Readies