diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ed535f8a..5591d0454 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,7 @@ separate_arguments(OC_EXE_LINKER_FLAGS_DEBUG) ############################################################################ # User selectable options ############################################################################ -option(PROJECT_FOLDERS "Put source files into subfolders in project file" ON) +option(PROJECT_FOLDERS "Put source files into subfolders in project file" ON) option(USE_GL "Enable OpenGL support" ON) SET(INITIAL_USE_SDL_MAINLOOP_VALUE OFF) SET(INITIAL_USE_OPEN_AL OFF) @@ -56,7 +56,7 @@ if(WIN32 AND FALSE) # disable DX option while it doesn't work anyway list(APPEND CMAKE_LIBRARY_PATH $ENV{DXSDK_DIR}/Lib/x86) endif() else() - + endif() else() SET(USE_DIRECTX OFF) @@ -324,6 +324,8 @@ set(OC_CLONK_SOURCES src/gui/C4GameOptions.h src/gui/C4GameOverDlg.cpp src/gui/C4GameOverDlg.h + src/gui/C4GfxErrorDlg.cpp + src/gui/C4GfxErrorDlg.h src/gui/C4GuiButton.cpp src/gui/C4GuiCheckBox.cpp src/gui/C4GuiComboBox.cpp @@ -874,14 +876,14 @@ if(APPLE) src/res/Ift_Trans.png src/res/NoIft_Trans.png ) - + # Add icon resources set_source_files_properties( ${OC_BUNDLE_RESOURCES} PROPERTIES MACOSX_PACKAGE_LOCATION Resources ) list(APPEND OC_SYSTEM_SOURCES ${OC_BUNDLE_RESOURCES}) - + endif() ############################################################################ @@ -925,6 +927,7 @@ add_executable(netpuncher EXCLUDE_FROM_ALL ) add_executable(c4script + include/c4script/c4script.h src/c4group/C4Group.cpp src/c4group/C4Group.h src/c4group/CStdFile.cpp @@ -955,6 +958,7 @@ add_executable(c4script src/script/C4StringTable.cpp src/script/C4PropList.cpp src/script/C4ScriptHost.cpp + src/script/C4ScriptStandalone.cpp src/script/C4ValueArray.cpp src/script/C4Value.cpp src/script/C4ValueMap.cpp @@ -988,7 +992,7 @@ if(HAVE_PTHREAD) pthread ) target_link_libraries(c4script - pthread + pthread ) endif() if(USE_CONSOLE) @@ -1018,7 +1022,7 @@ if (APPLE) SET_TARGET_PROPERTIES(c4group PROPERTIES XCODE_ATTRIBUTE_GCC_PFE_FILE_C_DIALECTS "c++ objective-c++") endif() -# This expands some variables in Info.plist as a side-effect. XCode might then +# This expands some variables in Info.plist as a side-effect. XCode might then # expand a second time, using the same syntax. Try not to get confused by this! set_target_properties(clonk PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/src/res/Info.plist") @@ -1274,11 +1278,11 @@ ENDIF() # TODO: Check for convert at configure step? install(DIRECTORY DESTINATION share/icons/hicolor/48x48/apps) install(CODE " -EXECUTE_PROCESS(COMMAND \"convert\" \"${CMAKE_CURRENT_SOURCE_DIR}/src/res/oc.ico[2]\" \"${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/48x48/apps/clonk.png\" RESULT_VARIABLE CONVERT_RESULT) +EXECUTE_PROCESS(COMMAND \"convert\" \"${CMAKE_CURRENT_SOURCE_DIR}/src/res/oc.ico[2]\" \"$ENV{DESTDIR}/${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/48x48/apps/clonk.png\" RESULT_VARIABLE CONVERT_RESULT) IF(NOT \${CONVERT_RESULT} EQUAL 0) MESSAGE(SEND_ERROR \"Creating icon failed\") ENDIF() -FILE(MAKE_DIRECTORY ${CMAKE_INSTALL_PREFIX}/share/openclonk) +FILE(MAKE_DIRECTORY $ENV{DESTDIR}/${CMAKE_INSTALL_PREFIX}/share/openclonk) ") set(OC_C4GROUPS @@ -1305,7 +1309,7 @@ foreach(group ${OC_C4GROUPS}) else() INSTALL(CODE " MESSAGE(\"Packing and installing ${group}...\") - EXECUTE_PROCESS(COMMAND \"${CMAKE_CURRENT_BINARY_DIR}/c4group\" \"${CMAKE_CURRENT_SOURCE_DIR}/planet/${group}\" -t \"${CMAKE_INSTALL_PREFIX}/share/openclonk/${group}\" RESULT_VARIABLE PACK_RESULT) + EXECUTE_PROCESS(COMMAND \"${CMAKE_CURRENT_BINARY_DIR}/c4group\" \"${CMAKE_CURRENT_SOURCE_DIR}/planet/${group}\" -t \"$ENV{DESTDIR}/${CMAKE_INSTALL_PREFIX}/share/openclonk/${group}\" RESULT_VARIABLE PACK_RESULT) IF(NOT \${PACK_RESULT} EQUAL 0) MESSAGE(SEND_ERROR \"Packing ${group} failed\") ENDIF() diff --git a/Makefile.am b/Makefile.am index b2bac5b34..23420bdf5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -149,6 +149,7 @@ src/platform/StdRegistry.h \ src/platform/StdScheduler.cpp \ src/platform/StdScheduler.h \ src/zlib/gzio.c \ +src/zlib/gzio.h \ src/zlib/zutil.h clonk_SOURCES = \ @@ -318,6 +319,8 @@ src/gui/C4GameOptions.cpp \ src/gui/C4GameOptions.h \ src/gui/C4GameOverDlg.cpp \ src/gui/C4GameOverDlg.h \ +src/gui/C4GfxErrorDlg.cpp \ +src/gui/C4GfxErrorDlg.h \ src/gui/C4GuiButton.cpp \ src/gui/C4GuiCheckBox.cpp \ src/gui/C4GuiComboBox.cpp \ @@ -534,6 +537,7 @@ src/script/C4Value.cpp \ src/script/C4Value.h \ src/script/C4ValueMap.cpp \ src/script/C4ValueMap.h \ +thirdparty/timsort/sort.h \ thirdparty/tinyxml/tinystr.cpp \ thirdparty/tinyxml/tinystr.h \ thirdparty/tinyxml/tinyxml.cpp \ @@ -687,6 +691,7 @@ endif ## c4script shell c4script_SOURCES = \ +include/c4script/c4script.h \ src/lib/C4SimpleLog.cpp \ src/lib/C4Real.cpp \ src/lib/C4Random.cpp \ @@ -698,6 +703,7 @@ src/script/C4AulParse.cpp \ src/script/C4StringTable.cpp \ src/script/C4PropList.cpp \ src/script/C4ScriptHost.cpp \ +src/script/C4ScriptStandalone.cpp \ src/script/C4ValueArray.cpp \ src/script/C4Value.cpp \ src/script/C4ValueMap.cpp \ diff --git a/docs/de.po b/docs/de.po index c5a5f4573..27742ef59 100644 --- a/docs/de.po +++ b/docs/de.po @@ -15375,7 +15375,7 @@ msgstr "int/array" #: sdk/definition/properties.xml:56(col) msgid "Controls the visibility of the object. See the detailed documentation of possible values." -msgstr "Steuert die Sichtbarkeit des Objekts. Detailierte Dokumentation möglicher Werte" +msgstr "Steuert die Sichtbarkeit des Objekts. Detailierte Dokumentation möglicher Werte" #: sdk/definition/properties.xml:110(col) #: sdk/definition/properties.xml:115(col) diff --git a/docs/sdk/script/fn/DrawDefMap.xml b/docs/sdk/script/fn/DrawDefMap.xml index 892023510..03fc71041 100644 --- a/docs/sdk/script/fn/DrawDefMap.xml +++ b/docs/sdk/script/fn/DrawDefMap.xml @@ -35,14 +35,9 @@ map_name Name of the map to be used from Landscape.txt. - - bool - ignore_sky - If true, the old material is retained whenever Sky would be drawn. - - Draws a dynamic map within the specified rectangle using a given map specification from Landscape.txt. + Draws a dynamic map within the specified rectangle over the old landscape using a given map specification from Landscape.txt. The Landscape.txt component is usually removed from memory after scenario initialization. To keep it in memory for later use by this command you should specify the option KeepMapCreator=1 in Scenario.txt section [Landscape]. diff --git a/docs/sdk/script/fn/DrawMap.xml b/docs/sdk/script/fn/DrawMap.xml index d0cc9ff2f..b228d98cd 100644 --- a/docs/sdk/script/fn/DrawMap.xml +++ b/docs/sdk/script/fn/DrawMap.xml @@ -35,19 +35,14 @@ map Definition of the dynamic map. The enclosing map { ... } tag must be present. - - bool - ignore_sky - If true, the old material is retained whenever Sky would be drawn. - - Draws a dynamic map within the specified rectangle. This is done using the same evaluation as with Landscape.txt components. + Draws a dynamic map within the specified rectangle over the old landscape. This is done using the same evaluation as with Landscape.txt components. As maximum string length in C4Script is limited by internal buffers you should use DrawDefMap for very complex maps. - DrawMap(0,0,LandscapeWidth(), LandscapeHeight()/2, "map Empty{}"); - Empties the top half of the map. + DrawMap(0,0,LandscapeWidth(), LandscapeHeight()/2, "map Earth{overlay{mat = Earth;};};"); + Fills the top half of the map with earth. DrawDefMap diff --git a/include/c4script/c4script.h b/include/c4script/c4script.h new file mode 100644 index 000000000..5ad4f8a03 --- /dev/null +++ b/include/c4script/c4script.h @@ -0,0 +1,32 @@ +/* + * OpenClonk, http://www.openclonk.org + * + * Copyright (c) 2012 Günther Brammer + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef C4SCRIPTSTANDALONE_H +#define C4SCRIPTSTANDALONE_H + +#ifdef __cplusplus +extern "C" { +#endif + +int c4s_runscript(const char * filename); + +#ifdef __cplusplus +} +#endif + +#endif // C4SCRIPTSTANDALONE_H diff --git a/planet/BackToTheRocks.ocf/Boomrace.ocs/System.ocg/Clonk.c b/planet/BackToTheRocks.ocf/Boomrace.ocs/System.ocg/Clonk.c index ec3cd95cc..d1c750a9e 100644 --- a/planet/BackToTheRocks.ocf/Boomrace.ocs/System.ocg/Clonk.c +++ b/planet/BackToTheRocks.ocf/Boomrace.ocs/System.ocg/Clonk.c @@ -11,5 +11,5 @@ protected func RejectCollect(id objid, object obj) public func MaxContentsCount() { - return 1; + return 2; } diff --git a/planet/BackToTheRocks.ocf/FrozenFortress.ocs/Scrolls.ocd/FrostboltScroll.ocd/DefCore.txt b/planet/BackToTheRocks.ocf/FrozenFortress.ocs/Scrolls.ocd/FrostboltScroll.ocd/DefCore.txt index 25fd74e4f..c23daff5d 100644 --- a/planet/BackToTheRocks.ocf/FrozenFortress.ocs/Scrolls.ocd/FrostboltScroll.ocd/DefCore.txt +++ b/planet/BackToTheRocks.ocf/FrozenFortress.ocs/Scrolls.ocd/FrostboltScroll.ocd/DefCore.txt @@ -9,7 +9,7 @@ Vertices=3 VertexX=0,-3,3 VertexY=-3,2,2 VertexFriction=40,40,40 -Picture=0,0,8,8 +Picture=0,0,64,64 Value=25 Mass=2 Rotate=1 diff --git a/planet/BackToTheRocks.ocf/FrozenFortress.ocs/Scrolls.ocd/HardeningScroll.ocd/DefCore.txt b/planet/BackToTheRocks.ocf/FrozenFortress.ocs/Scrolls.ocd/HardeningScroll.ocd/DefCore.txt index 6ccf27fd3..0ff44d148 100644 --- a/planet/BackToTheRocks.ocf/FrozenFortress.ocs/Scrolls.ocd/HardeningScroll.ocd/DefCore.txt +++ b/planet/BackToTheRocks.ocf/FrozenFortress.ocs/Scrolls.ocd/HardeningScroll.ocd/DefCore.txt @@ -9,7 +9,7 @@ Vertices=3 VertexX=0,-3,3 VertexY=-3,2,2 VertexFriction=40,40,40 -Picture=0,0,8,8 +Picture=0,0,64,64 Value=25 Mass=2 Rotate=1 diff --git a/planet/BackToTheRocks.ocf/FrozenFortress.ocs/Scrolls.ocd/WindScroll.ocd/DefCore.txt b/planet/BackToTheRocks.ocf/FrozenFortress.ocs/Scrolls.ocd/WindScroll.ocd/DefCore.txt index 05cce8ac0..d333630e5 100644 --- a/planet/BackToTheRocks.ocf/FrozenFortress.ocs/Scrolls.ocd/WindScroll.ocd/DefCore.txt +++ b/planet/BackToTheRocks.ocf/FrozenFortress.ocs/Scrolls.ocd/WindScroll.ocd/DefCore.txt @@ -9,7 +9,7 @@ Vertices=3 VertexX=0,-3,3 VertexY=-3,2,2 VertexFriction=40,40,40 -Picture=0,0,8,8 +Picture=0,0,64,64 Value=25 Mass=2 Rotate=1 diff --git a/planet/BackToTheRocks.ocf/MoltenMonarch.ocs/System.ocg/King_Club.c b/planet/BackToTheRocks.ocf/MoltenMonarch.ocs/System.ocg/King_Club.c index d5031ccf1..6f0e8fa22 100644 --- a/planet/BackToTheRocks.ocf/MoltenMonarch.ocs/System.ocg/King_Club.c +++ b/planet/BackToTheRocks.ocf/MoltenMonarch.ocs/System.ocg/King_Club.c @@ -27,7 +27,6 @@ func DoStrike(clonk, angle) var damage=5*1000; if (king_size) damage+=3000; - var f=ApplyShieldFactor(clonk, obj, damage); ApplyWeaponBash(obj, 400, angle); obj->DoEnergy(-damage, true, FX_Call_EngGetPunched, clonk->GetOwner()); } diff --git a/planet/BackToTheRocks.ocf/Overcast.ocs/Scrolls.ocd/FireballScroll.ocd/DefCore.txt b/planet/BackToTheRocks.ocf/Overcast.ocs/Scrolls.ocd/FireballScroll.ocd/DefCore.txt index 59a5a6326..7af379dff 100644 --- a/planet/BackToTheRocks.ocf/Overcast.ocs/Scrolls.ocd/FireballScroll.ocd/DefCore.txt +++ b/planet/BackToTheRocks.ocf/Overcast.ocs/Scrolls.ocd/FireballScroll.ocd/DefCore.txt @@ -9,7 +9,7 @@ Vertices=3 VertexX=0,-3,3 VertexY=-3,2,2 VertexFriction=40,40,40 -Picture=0,0,8,8 +Picture=0,0,64,64 Value=25 Mass=2 Rotate=1 diff --git a/planet/BackToTheRocks.ocf/Overcast.ocs/Scrolls.ocd/TeleportScroll.ocd/DefCore.txt b/planet/BackToTheRocks.ocf/Overcast.ocs/Scrolls.ocd/TeleportScroll.ocd/DefCore.txt index 08492301d..00901c5d3 100644 --- a/planet/BackToTheRocks.ocf/Overcast.ocs/Scrolls.ocd/TeleportScroll.ocd/DefCore.txt +++ b/planet/BackToTheRocks.ocf/Overcast.ocs/Scrolls.ocd/TeleportScroll.ocd/DefCore.txt @@ -9,7 +9,7 @@ Vertices=3 VertexX=0,-3,3 VertexY=-3,2,2 VertexFriction=40,40,40 -Picture=0,0,8,8 +Picture=0,0,64,64 Value=25 Mass=2 Rotate=1 diff --git a/planet/BackToTheRocks.ocf/Overcast.ocs/Scrolls.ocd/WindScroll.ocd/DefCore.txt b/planet/BackToTheRocks.ocf/Overcast.ocs/Scrolls.ocd/WindScroll.ocd/DefCore.txt index 05cce8ac0..d333630e5 100644 --- a/planet/BackToTheRocks.ocf/Overcast.ocs/Scrolls.ocd/WindScroll.ocd/DefCore.txt +++ b/planet/BackToTheRocks.ocf/Overcast.ocs/Scrolls.ocd/WindScroll.ocd/DefCore.txt @@ -9,7 +9,7 @@ Vertices=3 VertexX=0,-3,3 VertexY=-3,2,2 VertexFriction=40,40,40 -Picture=0,0,8,8 +Picture=0,0,64,64 Value=25 Mass=2 Rotate=1 diff --git a/planet/BackToTheRocks.ocf/ThunderousSkies.ocs/Scrolls.ocd/FireballScroll.ocd/DefCore.txt b/planet/BackToTheRocks.ocf/ThunderousSkies.ocs/Scrolls.ocd/FireballScroll.ocd/DefCore.txt index 59a5a6326..7af379dff 100644 --- a/planet/BackToTheRocks.ocf/ThunderousSkies.ocs/Scrolls.ocd/FireballScroll.ocd/DefCore.txt +++ b/planet/BackToTheRocks.ocf/ThunderousSkies.ocs/Scrolls.ocd/FireballScroll.ocd/DefCore.txt @@ -9,7 +9,7 @@ Vertices=3 VertexX=0,-3,3 VertexY=-3,2,2 VertexFriction=40,40,40 -Picture=0,0,8,8 +Picture=0,0,64,64 Value=25 Mass=2 Rotate=1 diff --git a/planet/BackToTheRocks.ocf/ThunderousSkies.ocs/Scrolls.ocd/ThunderScroll.ocd/DefCore.txt b/planet/BackToTheRocks.ocf/ThunderousSkies.ocs/Scrolls.ocd/ThunderScroll.ocd/DefCore.txt index a7fb29dfa..c1aed6103 100644 --- a/planet/BackToTheRocks.ocf/ThunderousSkies.ocs/Scrolls.ocd/ThunderScroll.ocd/DefCore.txt +++ b/planet/BackToTheRocks.ocf/ThunderousSkies.ocs/Scrolls.ocd/ThunderScroll.ocd/DefCore.txt @@ -9,7 +9,7 @@ Vertices=3 VertexX=0,-3,3 VertexY=-3,2,2 VertexFriction=40,40,40 -Picture=0,0,8,8 +Picture=0,0,64,64 Value=25 Mass=2 Rotate=1 diff --git a/planet/BackToTheRocks.ocf/ThunderousSkies.ocs/Scrolls.ocd/WindScroll.ocd/DefCore.txt b/planet/BackToTheRocks.ocf/ThunderousSkies.ocs/Scrolls.ocd/WindScroll.ocd/DefCore.txt index 05cce8ac0..d333630e5 100644 --- a/planet/BackToTheRocks.ocf/ThunderousSkies.ocs/Scrolls.ocd/WindScroll.ocd/DefCore.txt +++ b/planet/BackToTheRocks.ocf/ThunderousSkies.ocs/Scrolls.ocd/WindScroll.ocd/DefCore.txt @@ -9,7 +9,7 @@ Vertices=3 VertexX=0,-3,3 VertexY=-3,2,2 VertexFriction=40,40,40 -Picture=0,0,8,8 +Picture=0,0,64,64 Value=25 Mass=2 Rotate=1 diff --git a/planet/BeyondTheRocks.ocf/GoldRush.ocs/Landscape.txt b/planet/BeyondTheRocks.ocf/GoldRush.ocs/Landscape.txt index 48f4b4a1d..e31f0fe01 100644 --- a/planet/BeyondTheRocks.ocf/GoldRush.ocs/Landscape.txt +++ b/planet/BeyondTheRocks.ocf/GoldRush.ocs/Landscape.txt @@ -62,6 +62,8 @@ map Goldmine { }; RandomMat & overlay { mat=Earth; tex=earth_rough; }; RandomMat & overlay { mat=Earth; tex=earth_dry; }; + RandomSpots & overlay { mat=Earth; tex=earth_topsoil; }; + RandomSpots & overlay { mat=Earth; tex=earth_midsoil; }; RandomSpots & overlay { mat=Coal; tex=coal; }; RandomSpots & overlay { mat=Sulphur; tex=sulphur; }; RandomSpots & overlay { mat=Ore; tex=Ore; }; @@ -71,6 +73,7 @@ map Goldmine { x=0; y=58; wdt=100; hgt=12; turbulence=10; lambda=3; loosebounds=1; mask=1; + RandomMat & overlay { mat=Earth; tex=earth_topsoil; }; RandomMat & overlay { mat=Coal; tex=coal; }; RandomMat & overlay { mat=Sulphur; tex=sulphur; }; }; @@ -79,11 +82,13 @@ map Goldmine { x=0; y=72; wdt=100; hgt=12; turbulence=10; lambda=3; loosebounds=1; mask=1; + RandomMat & overlay { mat=Earth; tex=earth_midsoil; }; RandomMat & overlay { mat=Rock; tex=rock; }; RandomMat & overlay { mat=Ore; tex=ore; }; RandomSpots & overlay { mat=Rock; tex=rock_cracked; }; RandomSpots & overlay { mat=Rock; tex=rock_cracked; }; RandomSpots & overlay { mat=Rock; tex=rock_cracked; }; + RandomSpots & overlay { mat=Rock; tex=rock_cracked; }; }; // Bottom layer with gold. overlay { @@ -96,6 +101,7 @@ map Goldmine { RandomSpots & overlay { mat=Gold; tex=gold; }; RandomSpots & overlay { mat=Gold; tex=gold; }; RandomMat & overlay { mat=Gold; tex=gold; }; + RandomMat & overlay { mat=Gold; tex=gold; }; }; // Border of earth and sand. overlay { diff --git a/planet/BeyondTheRocks.ocf/GoldRush.ocs/Scenario.txt b/planet/BeyondTheRocks.ocf/GoldRush.ocs/Scenario.txt index cefcf7ee3..12a8345f5 100644 --- a/planet/BeyondTheRocks.ocf/GoldRush.ocs/Scenario.txt +++ b/planet/BeyondTheRocks.ocf/GoldRush.ocs/Scenario.txt @@ -14,30 +14,30 @@ Rules=Rule_EnergyNeed=1;Rule_TeamAccount=1; [Player1] Wealth=10 Crew=Clonk=2 -Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;CableReel=1;Dynamite=1;DynamiteBox=1; +Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;DynamiteBox=1; HomeBaseMaterial=Shovel=2;Pickaxe=2;Axe=2;Hammer=2;Dynamite=10;Loam=10;Wood=20;Metal=10;Clonk=2;Lorry=1; [Player2] Wealth=10 Crew=Clonk=2 -Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;CableReel=1;Dynamite=1;DynamiteBox=1; +Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;DynamiteBox=1; HomeBaseMaterial=Shovel=2;Pickaxe=2;Axe=2;Hammer=2;Dynamite=10;Loam=10;Wood=20;Metal=10;Clonk=2;Lorry=1; [Player3] Wealth=10 Crew=Clonk=2 -Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;CableReel=1;Dynamite=1;DynamiteBox=1; +Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;DynamiteBox=1; HomeBaseMaterial=Shovel=2;Pickaxe=2;Axe=2;Hammer=2;Dynamite=10;Loam=10;Wood=20;Metal=10;Clonk=2;Lorry=1; [Player4] Wealth=10 Crew=Clonk=2 -Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;CableReel=1;Dynamite=1;DynamiteBox=1; +Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;DynamiteBox=1; HomeBaseMaterial=Shovel=2;Pickaxe=2;Axe=2;Hammer=2;Dynamite=10;Loam=10;Wood=20;Metal=10;Clonk=2;Lorry=1; [Landscape] InEarth=Rock=1;Firestone=3;Loam=2 -InEarthLevel=30,0,0,100 +InEarthLevel=40 Sky=Clouds2 MapWidth=100 MapHeight=75 @@ -45,5 +45,5 @@ MapHeight=75 [Weather] Climate=0 YearSpeed=0 -Wind=1,100,-100,100 +Wind=0,100,-100,100 diff --git a/planet/BeyondTheRocks.ocf/GoldRush.ocs/Script.c b/planet/BeyondTheRocks.ocf/GoldRush.ocs/Script.c index f33f30af4..2521b9c30 100644 --- a/planet/BeyondTheRocks.ocf/GoldRush.ocs/Script.c +++ b/planet/BeyondTheRocks.ocf/GoldRush.ocs/Script.c @@ -13,7 +13,7 @@ protected func Initialize() goal->SetWealthGoal(400); // Place some trees. - for (var i = 0; i < 12 + Random(4); i++) + for (var i = 0; i < 16 + Random(4); i++) PlaceVegetation(Tree_Coniferous, 0, LandscapeHeight() / 3, LandscapeWidth(), LandscapeHeight(), 1000 * (61 + Random(40))); // place some sprout berries @@ -29,34 +29,6 @@ protected func Initialize() var time = CreateObject(Environment_Time); time->SetTime(600); time->SetCycleSpeed(12); - - // Create a small settlement to test stuff. - /* - var foundry = CreateConstruction(Foundry, 300, FindHeight(300), NO_OWNER, 100, true); - CreateObject(Barrel, 300, FindHeight(300), NO_OWNER)->PutLiquid("Water", 300); - foundry->CreateContents(Coal,3); - foundry->CreateContents(Ore,3); - var flag = CreateConstruction(Flagpole, 360, FindHeight(360), NO_OWNER, 100, true); - var workshop = CreateConstruction(ToolsWorkshop, 420, FindHeight(420), NO_OWNER, 100, true); - workshop->CreateContents(Wood, 10); - workshop->CreateContents(Metal, 10); - workshop->CreateContents(Coal, 10); - workshop->CreateContents(Sulphur, 10); - var wind = CreateConstruction(WindGenerator, 480, FindHeight(480), NO_OWNER, 100, true); - var line = CreateObject(PowerLine); - line->SetActionTargets(wind, workshop); - var sawmill = CreateConstruction(Sawmill, 520, FindHeight(520), NO_OWNER, 100, true); - var line = CreateObject(PowerLine); - line->SetActionTargets(wind, sawmill); - CreateConstruction(Elevator, 220, FindHeight(220), NO_OWNER, 100, true)->CreateShaft(100); - - // Create a lorry with necessary equipment to start a settlement. - var lorry = CreateObject(Lorry, 300, FindHeight(300)); - lorry->CreateContents(Wood, 6); - lorry->CreateContents(Metal, 4); - lorry->CreateContents(Dynamite, 3); - lorry->CreateContents(Loam, 3); - */ return; } @@ -70,13 +42,6 @@ private func FindHeight(int x) protected func InitializePlayer(int plr) { - // first player gets the base to test. - /* - var flagpole = FindObject(Find_ID(Flagpole)); - if (flagpole && !GetPlayerName(flagpole->GetOwner())) - flagpole->SetOwner(plr); - */ - // Increase wealth goal per player. var goal = FindObject(Find_ID(Goal_Wealth)); if (goal) @@ -91,15 +56,9 @@ protected func InitializePlayer(int plr) crew->CreateContents(Shovel); // First clonk can construct, others can mine. if (index == 0) - { crew->CreateContents(Hammer); - crew->CreateContents(CableReel); - } else - { crew->CreateContents(Axe); - crew->CreateContents(CableReel); - } index++; } return; diff --git a/planet/BeyondTheRocks.ocf/IronPeak.ocs/Scenario.txt b/planet/BeyondTheRocks.ocf/IronPeak.ocs/Scenario.txt index b9ed1eb99..788907758 100644 --- a/planet/BeyondTheRocks.ocf/IronPeak.ocs/Scenario.txt +++ b/planet/BeyondTheRocks.ocf/IronPeak.ocs/Scenario.txt @@ -14,25 +14,25 @@ Rules=Rule_EnergyNeed=1;Rule_TeamAccount=1; [Player1] Wealth=40 Crew=Clonk=2 -Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;CableReel=1;Dynamite=1;DynamiteBox=1; +Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;DynamiteBox=1; HomeBaseMaterial=Shovel=2;Pickaxe=2;Axe=2;Hammer=2;Dynamite=10;Loam=10;Wood=20;Metal=10;Clonk=2;Lorry=1; [Player2] Wealth=40 Crew=Clonk=2 -Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;CableReel=1;Dynamite=1;DynamiteBox=1; +Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;DynamiteBox=1; HomeBaseMaterial=Shovel=2;Pickaxe=2;Axe=2;Hammer=2;Dynamite=10;Loam=10;Wood=20;Metal=10;Clonk=2;Lorry=1; [Player3] Wealth=40 Crew=Clonk=2 -Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;CableReel=1;Dynamite=1;DynamiteBox=1; +Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;DynamiteBox=1; HomeBaseMaterial=Shovel=2;Pickaxe=2;Axe=2;Hammer=2;Dynamite=10;Loam=10;Wood=20;Metal=10;Clonk=2;Lorry=1; [Player4] Wealth=40 Crew=Clonk=2 -Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;CableReel=1;Dynamite=1;DynamiteBox=1; +Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;DynamiteBox=1; HomeBaseMaterial=Shovel=2;Pickaxe=2;Axe=2;Hammer=2;Dynamite=10;Loam=10;Wood=20;Metal=10;Clonk=2;Lorry=1; [Landscape] @@ -47,4 +47,5 @@ BottomOpen=1 Climate=100 YearSpeed=0 Wind=1,100,-100,100 +Rain=40 diff --git a/planet/BeyondTheRocks.ocf/IronPeak.ocs/Script.c b/planet/BeyondTheRocks.ocf/IronPeak.ocs/Script.c index 19583f56f..9ac5e8751 100644 --- a/planet/BeyondTheRocks.ocf/IronPeak.ocs/Script.c +++ b/planet/BeyondTheRocks.ocf/IronPeak.ocs/Script.c @@ -35,7 +35,6 @@ protected func Initialize() //lorry->CreateContents(Wood, 16); //lorry->CreateContents(Metal, 4); //lorry->CreateContents(Dynamite, 3); - //lorry->CreateContents(CableReel, 3); // TODO: Make sure lorry stays on mountains. // Place some coniferous trees, but only up to 2/3 of the mountain. @@ -58,7 +57,7 @@ protected func Initialize() SetGamma(RGB(0,0,blue), RGB(128-blue,128-blue,128+blue), RGB(255-blue,255-blue,255)); // Some natural disasters. - var earthquakes = CreateObject(Earthquake); + //var earthquakes = CreateObject(Earthquake); // earthquakes->SetChance(30); // TODO: Rockfall. @@ -163,8 +162,7 @@ protected func InitializePlayer(int plr) { crew->CreateContents(Hammer); crew->CreateContents(Axe); - crew->CreateContents(CableReel); - crew->CreateContents(Dynamite); + crew->CreateContents(Dynamite, 2); } else { diff --git a/planet/Objects.ocd/Clonk.ocd/DefCore.txt b/planet/Objects.ocd/Clonk.ocd/DefCore.txt index 9362ef664..9f911da4a 100644 --- a/planet/Objects.ocd/Clonk.ocd/DefCore.txt +++ b/planet/Objects.ocd/Clonk.ocd/DefCore.txt @@ -12,7 +12,6 @@ VertexCNAT=0,4,8,1,2,1,2 VertexFriction=300,300,100,300,300,300,300 Value=25 Mass=50 -Picture=192,100,32,40 Collection=-8,-10,16,27 ContactIncinerate=10 CrewMember=1 diff --git a/planet/Objects.ocd/Effects.ocd/Explosion.ocd/ExploSmokeFastFade.ocd/Graphics.png b/planet/Objects.ocd/Effects.ocd/Explosion.ocd/ExploSmokeFastFade.ocd/Graphics.png new file mode 100644 index 000000000..8c2fd16c7 Binary files /dev/null and b/planet/Objects.ocd/Effects.ocd/Explosion.ocd/ExploSmokeFastFade.ocd/Graphics.png differ diff --git a/planet/Objects.ocd/Effects.ocd/Explosion.ocd/ExploSmokeFastFade.ocd/Particle.txt b/planet/Objects.ocd/Effects.ocd/Explosion.ocd/ExploSmokeFastFade.ocd/Particle.txt new file mode 100644 index 000000000..da3848d9b --- /dev/null +++ b/planet/Objects.ocd/Effects.ocd/Explosion.ocd/ExploSmokeFastFade.ocd/Particle.txt @@ -0,0 +1,11 @@ +[Particle] +Name=ExploSmokeFastFade +MaxCount=800 +InitFn=StdInit +ExecFn=StdExec +DrawFn=Std +Face=0,0,64,64,-32,-32 +Delay=0 +Repeats=1 +AlphaFade=2 +FadeDelay=1 diff --git a/planet/Objects.ocd/Effects.ocd/StarSpark.ocd/Graphics.png b/planet/Objects.ocd/Effects.ocd/StarSpark.ocd/Graphics.png new file mode 100644 index 000000000..20ea95e30 Binary files /dev/null and b/planet/Objects.ocd/Effects.ocd/StarSpark.ocd/Graphics.png differ diff --git a/planet/Objects.ocd/Effects.ocd/StarSpark.ocd/Particle.txt b/planet/Objects.ocd/Effects.ocd/StarSpark.ocd/Particle.txt new file mode 100644 index 000000000..554ce75a8 --- /dev/null +++ b/planet/Objects.ocd/Effects.ocd/StarSpark.ocd/Particle.txt @@ -0,0 +1,17 @@ +[Particle] +Name=StarSpark +MaxCount=1500 +InitFn=StdInit +ExecFn=StdExec +CollisionFn=Die +DrawFn=Std +Face=0,0,32,32,-16,-16 +Delay=0 +Repeats=1 +GravityAcc=50 +VertexCount=1 +VertexY=0 +AlphaFade=8 +Additive=1 +RByV=3 +Attach=1 \ No newline at end of file diff --git a/planet/Objects.ocd/Environment.ocd/Clouds.ocd/AcidRain.ocd/DefCore.txt b/planet/Objects.ocd/Environment.ocd/Clouds.ocd/AcidRain.ocd/DefCore.txt deleted file mode 100644 index 6540a67a3..000000000 --- a/planet/Objects.ocd/Environment.ocd/Clouds.ocd/AcidRain.ocd/DefCore.txt +++ /dev/null @@ -1,9 +0,0 @@ -[DefCore] -id=Environment_AcidRain -Version=5,2,0,1 -Category=C4D_StaticBack|C4D_Environment -Width=1 -Height=1 -Value=1 -Picture=0,0,64,64 - diff --git a/planet/Objects.ocd/Environment.ocd/Clouds.ocd/AcidRain.ocd/Graphics.png b/planet/Objects.ocd/Environment.ocd/Clouds.ocd/AcidRain.ocd/Graphics.png deleted file mode 100644 index e90c5d293..000000000 Binary files a/planet/Objects.ocd/Environment.ocd/Clouds.ocd/AcidRain.ocd/Graphics.png and /dev/null differ diff --git a/planet/Objects.ocd/Environment.ocd/Clouds.ocd/AcidRain.ocd/Script.c b/planet/Objects.ocd/Environment.ocd/Clouds.ocd/AcidRain.ocd/Script.c deleted file mode 100644 index 5d5c87e08..000000000 --- a/planet/Objects.ocd/Environment.ocd/Clouds.ocd/AcidRain.ocd/Script.c +++ /dev/null @@ -1 +0,0 @@ -local Name = "$Name$"; diff --git a/planet/Objects.ocd/Environment.ocd/Clouds.ocd/AcidRain.ocd/StringTblDE.txt b/planet/Objects.ocd/Environment.ocd/Clouds.ocd/AcidRain.ocd/StringTblDE.txt deleted file mode 100644 index ec659f1a9..000000000 --- a/planet/Objects.ocd/Environment.ocd/Clouds.ocd/AcidRain.ocd/StringTblDE.txt +++ /dev/null @@ -1 +0,0 @@ -Name=Säureregen diff --git a/planet/Objects.ocd/Environment.ocd/Clouds.ocd/AcidRain.ocd/StringTblUS.txt b/planet/Objects.ocd/Environment.ocd/Clouds.ocd/AcidRain.ocd/StringTblUS.txt deleted file mode 100644 index a22dce521..000000000 --- a/planet/Objects.ocd/Environment.ocd/Clouds.ocd/AcidRain.ocd/StringTblUS.txt +++ /dev/null @@ -1 +0,0 @@ -Name=Acid Rain diff --git a/planet/Objects.ocd/Environment.ocd/Clouds.ocd/Cloud.ocd/DefCore.txt b/planet/Objects.ocd/Environment.ocd/Clouds.ocd/Cloud.ocd/DefCore.txt index 669dfbd6e..1723d0485 100644 --- a/planet/Objects.ocd/Environment.ocd/Clouds.ocd/Cloud.ocd/DefCore.txt +++ b/planet/Objects.ocd/Environment.ocd/Clouds.ocd/Cloud.ocd/DefCore.txt @@ -1,9 +1,7 @@ [DefCore] id=Cloud Version=5,2,0,1 -Category=C4D_Vehicle|C4D_Background -Timer=25 -TimerCall=TimedEvents +Category=C4D_Vehicle | C4D_Background Width=512 Height=350 Offset=-256,-175 diff --git a/planet/Objects.ocd/Environment.ocd/Clouds.ocd/Cloud.ocd/Script.c b/planet/Objects.ocd/Environment.ocd/Clouds.ocd/Cloud.ocd/Script.c index 116551462..53b0e44ab 100644 --- a/planet/Objects.ocd/Environment.ocd/Clouds.ocd/Cloud.ocd/Script.c +++ b/planet/Objects.ocd/Environment.ocd/Clouds.ocd/Cloud.ocd/Script.c @@ -1,21 +1,43 @@ -/*--- Cloud ---*/ +/** + Cloud + Generic cloud, features: rain (water, acid) and thunder. + The clouds have periods of condensing, idle and raining. + Different types of rain (water, acid) are hardcoded. + + TODO: Make dependent on scenario setting. + TODO: Make for all material types. + + @authors Ringwaul, Maikel +*/ + + +// Cloud modes: idle, raining, condensing. +static const CLOUD_ModeIdle = 0; +static const CLOUD_ModeRaining = 1; +static const CLOUD_ModeCondensing = 2; +local mode; +// The time a cloud is in this mode. +local mode_time; + +local water; // number of water pixels the cloud contains. +local acid; // number of acid pixels the cloud contains. +local lightning_chance; // chance of lightning strikes 0-100. +local evap_x; // x coordinate for evaporation -local szMat, iSize, iCondensing; -local iSearchY; -local iWaitTime; -local iAcidity; -local iStrikeChance; protected func Initialize() { - //Cloud defaults and modifiers - iCondensing = 0; - iSize = RandomX(300,500); - SetClrModulation(RGB(255,255,255)); - iSearchY = 0; - iAcidity=0; - iWaitTime = RandomX(130,190); - var iGraphics = RandomX(1,3); + // Clouds start idle. + mode = CLOUD_ModeIdle; + mode_time = 360 + RandomX(-60, 60); + + // Default values for rain. + water = RandomX(200, 300); + acid = 0; + + // Cloud defaults + lightning_chance = 0; + evap_x = 0; DoCon(Random(75)); @@ -31,145 +53,226 @@ protected func Initialize() //Failsafe for stupid grounded clouds if(GetMaterial(0,30)!=Material("Sky")) SetPosition(GetX(), GetY()-180); - -} - -public func Precipitation() -{ - var iLaunch; - - if (GetTemperature() < 0 && iAcidity == 0) szMat = "Snow"; - if (GetTemperature() >= 1 && iAcidity == 0) szMat = "Water"; - if (iAcidity >= 1) szMat="Acid"; - - //Reroute function to Evaporation if cloud is growing - if(iCondensing == 1) return(Evaporation()); - if(iSize <= 50 && iAcidity==0) iCondensing = 1; - - //water-snow precipitation - if(iWaitTime == 0 && szMat != "Acid") - { - RainDrop(); - iSize = --iSize; - } - - //acid precipitation - if(iWaitTime == 0 && szMat == "Acid") - { - RainDrop(); - iAcidity = --iAcidity; - } - //Lightning Strike; only during rain - if(iWaitTime <= 0 && iSize >= 650 && Random(100) >= 100-(iStrikeChance/16) && szMat=="Water") LaunchLightning(GetX(), GetY(), RandomX(60, 100), 0, 100, 100, 10, true); -} - -public func TimedEvents() -{ - var iRight = LandscapeWidth() - 10; - - if(iWaitTime != 0) (iWaitTime = --iWaitTime); - if(iWaitTime == 0) Precipitation(); - WindDirection(); - CloudShade(); - //Makes clouds loop around map; - if(GetX() >= iRight) SetPosition(12, GetY()); - if(GetX() <= 10) SetPosition(LandscapeWidth()-12, GetY()); - if(GetY() <= 5) SetPosition(0,6); - if(GetYDir()!=0) SetYDir(0); - - while(Stuck()) SetPosition(GetX(),GetY()-5); -} - -protected func Evaporation() //Creates a search line every x-amount(currently five) of pixels to check for water beneath the cloud -{ - var iSearchX = GetX(); - var iPrecision = 5; - if(iSize >= 700 || iAcidity >= 100) - { - iCondensing = 0; - iSearchY = 0; - iWaitTime = RandomX(130,190); - } - //line below prevents clouds evaporating through solids - if(GetMaterial(0, iSearchY) != Material("Water") && GetMaterial(0, iSearchY) != Material("Acid") && GetMaterial(0, iSearchY) != Material("Sky")) return(iSearchY=0); - if(GetMaterial(0, iSearchY) == Material("Water")) - { - ExtractMaterialAmount(0, iSearchY,Material("Water"), 3); - iSize = iSize+3; - } - if(ObjectCount(Find_ID(Environment_AcidRain))>=1 && GetMaterial(0, iSearchY) == Material("Acid")) { - ExtractMaterialAmount(0, iSearchY,Material("Acid"), 3); - iAcidity = iAcidity+3; - } - //advance search point - if(GetMaterial(0, iSearchY) != Material("Water") && GetMaterial(0, iSearchY) != Material("Acid")) - iSearchY += iPrecision; - - if(iSearchY + GetY() >= LandscapeHeight()) (iSearchY = 0); + // Add effect to process all cloud features. + AddEffect("ProcessCloud", this, 100, 5, this); + return; } -private func CloudShade() +protected func FxProcessCloudStart(object target, proplist effect, int temporary) { -//Shades the clouds based on iSize: the water density value of the cloud. - var iShade = iSize*425/1000; - var iShade2 = iSize-600; - var iShade3 = (iAcidity*255/100)/2; - - if(iSize <= 600) SetObjAlpha(iShade); - if(iSize > 600) SetObjAlpha(255); - if(iSize > 600 && szMat=="Water") SetClrModulation(RGBa(255-iShade2,255-iShade2,255-iShade2, 255)); - if(iAcidity >= 1) SetClrModulation(RGBa(255-iShade3,255,255-iShade3, 255-iShade)); + // Make sure the effect interval is 5. + if (!temporary) + effect.Interval = 5; + return 1; } -public func RainDrop() +protected func FxProcessCloudTimer() { - var angle = RandomX(0,359); + // Move clouds. + MoveCloud(); + // Update mode time. + mode_time--; + if (mode_time <= 0) + { + // Change mode, reset timer. + mode = (mode + 1) % 3; + mode_time = 360 + RandomX(-60, 60); + } + // Process modes. + if (mode == CLOUD_ModeIdle) + { + /* Empty */ + } + else if (mode == CLOUD_ModeRaining) + { + Precipitation(); + ThunderStrike(); + } + else if (mode == CLOUD_ModeCondensing) + { + Evaporation(); + } + // Update cloud appearance. + ShadeCloud(); + + return 1; +} + +private func MoveCloud() +{ + // Move according to wind. + var wind = GetWind(); + if (wind >= 7) + SetXDir(Random(355), 1000); + else if (wind <= -7) + SetXDir(-Random(355), 1000); + else + SetXDir(); + // Loop clouds around the map. + if (GetX() >= LandscapeWidth() - 10) + SetPosition(12, GetY()); + if (GetX() <= 10) + SetPosition(LandscapeWidth()-12, GetY()); + // Some other safety. + if (GetY() <= 5) + SetPosition(0, 6); + if (GetYDir()!=0) + SetYDir(0); + while (Stuck()) + SetPosition(GetX(), GetY() - 5); + return; +} + +private func Precipitation() +{ + // Precipitaion: water or snow. + if (water > 0) + { + if (GetTemperature() > 0) + RainDrop("Water"); + else + RainDrop("Snow"); + water--; + } + + // Precipitation: acid. + if (acid > 0) + { + RainDrop("Acid"); + acid--; + } + // If out of liquids, skip mode. + if (water == 0 && acid == 0) + mode_time = 0; + + return; +} + +// Raindrop somewhere from the cloud. +private func RainDrop(string mat) +{ + var angle = RandomX(0, 359); var dist = Random(51); - CastPXS(szMat, 1, 1, Sin(angle,dist),Cos(angle,dist)); + CastPXS(mat, 1, 1, Sin(angle,dist),Cos(angle,dist)); +} + +// Launches possibly one thunder strike from the cloud. +private func ThunderStrike() +{ + // Determine whether to launch a strike. + if (water < 100) + return; + if (Random(100) >= lightning_chance || Random(5)) + return; + + // Find random position in the cloud. + var con = GetCon(); + var wdt = GetDefWidth() * con / 250; + var hgt = GetDefHeight() * con / 350; + var x = GetX() + RandomX(-wdt, wdt); + var y = GetY() + RandomX(-hgt, hgt); + var str = con + RandomX(-20, 20); + // Launch lightning. + return LaunchLightning(x, y, str, 0, str / 5, str / 10, str / 10, true); +} + +// Tries to evaporate liquids from the surface. +protected func Evaporation() +{ + var prec = 5; + + // Found enough water/acid, skip condensing phase. + if (water >= 700 || acid >= 100) + { + mode_time = 0; + return; + } + + // determine new x coordinate from the cloud to test for liquids. + var wdt = GetDefWidth() * GetCon() * 3 / 4; + evap_x += prec; + if (evap_x > wdt) + evap_x = - wdt; + + // Test the line downwards from this coordinate. + var y = 0; + while (!GBackSemiSolid(evap_x, y) && y < LandscapeHeight()) + y += prec; + + // Try to extract water. + if(GetMaterial(evap_x, y) == Material("Water")) + { + ExtractMaterialAmount(evap_x, y, Material("Water"), 3); + water += 3; + } + + // Try to extract acid. + if(GetMaterial(evap_x, y) == Material("Acid")) + { + ExtractMaterialAmount(evap_x, y, Material("Acid"), 3); + acid += 3; + } + + // Also add some rain by scenario value. + var mat = GetScenarioVal("Precipitation"); + if (Random(100) < GetScenarioVal("Rain")) + { + if (mat == "Water") + water++; + if (mat == "Acid") + acid++; + } + + return; +} + +//Shades the clouds based on iSize: the water density value of the cloud. +private func ShadeCloud() +{ + var shade = Min(water*425/1000, 255); + var shade2 = Min(water-600, 255); + var shade3 = (acid*255/100)/2; + + if (water <= 600) + SetObjAlpha(shade); + if (water > 600) + SetClrModulation(RGBa(255-shade2, 255-shade2, 255-shade2, 255)); + if (acid > 0) + SetClrModulation(RGBa(255-shade3, 255, 255-shade3, 255-shade)); + return; } //For use as scenario setting. Can work after initialize, if you really want to. -global func AdjustLightningFrequency(int iFreq) +global func AdjustLightningFrequency(int freq) { - for(var Cloud in FindObjects(Find_ID(Cloud))) - Cloud->SetLightningFrequency(iFreq); - return(iFreq); + for (var cloud in FindObjects(Find_ID(Cloud))) + cloud->SetLightningFrequency(freq); + return; } //Routes the global adjust function's variable to the clouds. -public func SetLightningFrequency(int iFreq) +public func SetLightningFrequency(int freq) { - iStrikeChance=iFreq; + lightning_chance = freq; } -private func WindDirection() -{ - var iWind = GetWind(); - - if(iWind >= 7) SetXDir(Random(355),1000); - if(iWind <= -7) SetXDir(-Random(355),1000); - if(iWind < 6 && iWind > -6) SetXDir(); -} - -func Definition(def) { - SetProperty("ActMap", { -Fly = { - Prototype = Action, - Name = "Fly", - Procedure = DFA_FLOAT, - Speed = 20, - Accel = 16, - Decel = 16, - X = 0, - Y = 0, - Wdt = 512, - Hgt = 350, - Length = 16, - Delay = 0, - NextAction = "Fly", - TurnAction = "Turn", -}, -}, def); -} +local ActMap = { + Fly = { + Prototype = Action, + Name = "Fly", + Procedure = DFA_FLOAT, + Speed = 20, + Accel = 16, + Decel = 16, + X = 0, + Y = 0, + Wdt = 512, + Hgt = 350, + Length = 16, + Delay = 0, + NextAction = "Fly", + TurnAction = "Turn", + }, +}; local Name = "Cloud"; diff --git a/planet/Objects.ocd/Environment.ocd/Earthquake.ocd/Script.c b/planet/Objects.ocd/Environment.ocd/Earthquake.ocd/Script.c index 9a7c0a0f6..209025778 100644 --- a/planet/Objects.ocd/Environment.ocd/Earthquake.ocd/Script.c +++ b/planet/Objects.ocd/Environment.ocd/Earthquake.ocd/Script.c @@ -100,13 +100,13 @@ protected func FxIntEarthquakeTimer(object target, effect, int time) return FX_OK; // Get strength. var str = effect.strength; - // Shake viewport. - if (!Random(10)) - ShakeViewPort(str, x, y); // Get quake coordinates. var x = effect.x; var y = effect.y; var l = 4 * str; + // Shake viewport. + if (!Random(10)) + ShakeViewPort(str, x, y); // Shake ground & objects. ShakeFree(x, y, Random(str / 2) + str / 5 + 5); for (var obj in FindObjects(Find_NoContainer(), Find_OCF(OCF_Alive), Find_InRect(x - l, y - l, l, l))) diff --git a/planet/Objects.ocd/Environment.ocd/Time.ocd/Script.c b/planet/Objects.ocd/Environment.ocd/Time.ocd/Script.c index 7170368b4..45baf1989 100644 --- a/planet/Objects.ocd/Environment.ocd/Time.ocd/Script.c +++ b/planet/Objects.ocd/Environment.ocd/Time.ocd/Script.c @@ -69,7 +69,7 @@ protected func Initialize() // Create moon and stars. if (FindObject(Find_ID(Environment_Celestial))) { - var moon=CreateObject(Moon, LandscapeWidth() / 2, LandscapeHeight() / 6); + CreateObject(Moon, LandscapeWidth() / 2, LandscapeHeight() / 6); PlaceStars(); } return; diff --git a/planet/Objects.ocd/Environment.ocd/Vegetation.ocd/SproutBerryBush.ocd/Script.c b/planet/Objects.ocd/Environment.ocd/Vegetation.ocd/SproutBerryBush.ocd/Script.c index ea4ffe092..8eeed1ae6 100644 --- a/planet/Objects.ocd/Environment.ocd/Vegetation.ocd/SproutBerryBush.ocd/Script.c +++ b/planet/Objects.ocd/Environment.ocd/Vegetation.ocd/SproutBerryBush.ocd/Script.c @@ -18,6 +18,17 @@ static const SproutBerryBush_water_per_berry = 10; static const SproutBerryBush_max_sprouts = 8; static const SproutBerryBush_evolve_steps_per_new_sprout = 2; +// static function +func Place(int amount) +{ + // place some sprout berries + var bush = PlaceVegetation(SproutBerryBush, 0, LandscapeHeight() / 3, LandscapeWidth(), LandscapeHeight(), 100000); + if(bush) + for (var i = 1; i < amount; i++) + PlaceVegetation(SproutBerryBush, bush->GetX() - 200, bush->GetY() - 200, 400, 400, 100000); + return true; +} + func Construction() { SetCon(100); diff --git a/planet/Objects.ocd/Environment.ocd/Vegetation.ocd/Trees.ocd/Coniferous.ocd/Script.c b/planet/Objects.ocd/Environment.ocd/Vegetation.ocd/Trees.ocd/Coniferous.ocd/Script.c index e8cbb2863..a608997d3 100644 --- a/planet/Objects.ocd/Environment.ocd/Vegetation.ocd/Trees.ocd/Coniferous.ocd/Script.c +++ b/planet/Objects.ocd/Environment.ocd/Vegetation.ocd/Trees.ocd/Coniferous.ocd/Script.c @@ -3,10 +3,12 @@ #include Library_Plant private func SeedAreaSize() { return 400; } +private func SeedChance() { return 50; } +private func SeedAmount() { return 12; } func Construction() { - StartGrowth(1); + StartGrowth(5); inherited(...); } diff --git a/planet/Objects.ocd/Goals.ocd/DeathMatch.ocd/Script.c b/planet/Objects.ocd/Goals.ocd/DeathMatch.ocd/Script.c index 21fb97f51..7503a77b0 100644 --- a/planet/Objects.ocd/Goals.ocd/DeathMatch.ocd/Script.c +++ b/planet/Objects.ocd/Goals.ocd/DeathMatch.ocd/Script.c @@ -59,7 +59,6 @@ protected func JoinPlayer(int plr) { var clonk = GetCrew(plr); clonk->DoEnergy(100000); - var x, y; var pos = FindRelaunchPos(plr); clonk->SetPosition(pos[0], pos[1]); return; diff --git a/planet/Objects.ocd/Goals.ocd/KingOfTheHill.ocd/KingOfTheHillLocation.ocd/Script.c b/planet/Objects.ocd/Goals.ocd/KingOfTheHill.ocd/KingOfTheHillLocation.ocd/Script.c index a94493d51..4e691a154 100644 --- a/planet/Objects.ocd/Goals.ocd/KingOfTheHill.ocd/KingOfTheHillLocation.ocd/Script.c +++ b/planet/Objects.ocd/Goals.ocd/KingOfTheHill.ocd/KingOfTheHillLocation.ocd/Script.c @@ -142,7 +142,7 @@ func CreateStarCircle() if(GetType(stars) != C4V_Array) stars=[]; - for(star in stars) star->RemoveObject(); + for(var star in stars) star->RemoveObject(); stars=[]; var amount=radius / 15; diff --git a/planet/Objects.ocd/Goals.ocd/KingOfTheHill.ocd/Script.c b/planet/Objects.ocd/Goals.ocd/KingOfTheHill.ocd/Script.c index 33a3b5949..cc4a717c0 100644 --- a/planet/Objects.ocd/Goals.ocd/KingOfTheHill.ocd/Script.c +++ b/planet/Objects.ocd/Goals.ocd/KingOfTheHill.ocd/Script.c @@ -274,9 +274,6 @@ func RefreshScoreboard() SetScoreboardData(SBRD_Caption,SBRD_Points,Format("{{Sword}} / %d", GetPointLimit()),SBRD_Caption); SetScoreboardData(SBRD_Caption,SBRD_Deaths,"{{Clonk}}",SBRD_Caption); - - var points=GetTeamPoints(); - for(var cnt=0;cntDoEnergy(100000); - var x, y; var pos = FindRelaunchPos(plr); clonk->SetPosition(pos[0], pos[1]); return; diff --git a/planet/Objects.ocd/Goals.ocd/Parkour.ocd/Script.c b/planet/Objects.ocd/Goals.ocd/Parkour.ocd/Script.c index f0a641e88..91a35888d 100644 --- a/planet/Objects.ocd/Goals.ocd/Parkour.ocd/Script.c +++ b/planet/Objects.ocd/Goals.ocd/Parkour.ocd/Script.c @@ -426,7 +426,7 @@ protected func FxIntDirNextCPTimer(object target, effect) // Find nearest CP. var nextcp; for (var cp in FindObjects(Find_ID(ParkourCheckpoint), Find_Func("FindCPMode", PARKOUR_CP_Check | PARKOUR_CP_Finish), Sort_Distance(target->GetX() - GetX(), target->GetY() - GetY()))) - if (!cp->ClearedByPlayer(plr) && (cp->IsActiveForPlayer(plr) || cp->IsActiveForTeam(GetPlayerTeam(plr)))) + if (!cp->ClearedByPlayer(plr) && (cp->IsActiveForPlayer(plr) || cp->IsActiveForTeam(team))) { nextcp = cp; break; diff --git a/planet/Objects.ocd/HUD.ocd/Menu.ocd/ContentsMenuController.ocd/Script.c b/planet/Objects.ocd/HUD.ocd/Menu.ocd/ContentsMenuController.ocd/Script.c index dbfeff90d..ab8c4c2a3 100644 --- a/planet/Objects.ocd/HUD.ocd/Menu.ocd/ContentsMenuController.ocd/Script.c +++ b/planet/Objects.ocd/HUD.ocd/Menu.ocd/ContentsMenuController.ocd/Script.c @@ -4,9 +4,15 @@ @author Newton, Maikel */ +// this array contains all the menus +// index 0 = calling object +// index >0 = first crew, then containers local circ_menus; local menu_object; +local crew_count; +local container_count; + /** Creates a content menu for the calling object. This is supposed to be a crew member, controlled by a player. @return a pointer to the created menu, or \c nil if failed. @@ -23,10 +29,21 @@ global func CreateContentsMenus() controller->SetMenuObject(this); this->SetMenu(controller); + var index = 0; + + // add the clonk itself + controller->AddContentMenu(this, index, true); + + // add all nearby crewmembers + var teammates = FindObjects(Find_Distance(20), Find_OCF(OCF_CrewMember), Find_Owner(GetOwner()), Find_Exclude(this)); + index = 1; + for(var t in teammates) + controller->AddContentMenu(t, index++, true); + // Add content menus for all containers at the position of the caller. - var containers = FindObjects(Find_Or(Find_Not(Find_Exclude(this)), Find_And(Find_AtPoint(), Find_NoContainer(), Find_Func("IsContainer"))), Sort_Func("SortInventoryObjs")); - for(var index = 0; index < GetLength(containers); index++) - controller->AddContentMenu(containers[index], index, GetLength(containers)); + var containers = FindObjects(Find_AtPoint(), Find_NoContainer(), Find_OCF(OCF_Fullcon), Find_Func("IsContainer"), Sort_Func("SortInventoryObjs")); + for(var c in containers) + controller->AddContentMenu(c, index++, false); // Show and return content menu. controller->Show(); @@ -81,7 +98,7 @@ func Hide() prop.Menu->Hide(); } -func AddContentMenu(object container, int pos, int length) +func AddContentMenu(object container, int pos, bool isCrew) { var menu = CreateObject(GUI_Menu, 0, 0, GetOwner()); @@ -91,7 +108,12 @@ func AddContentMenu(object container, int pos, int length) menu->SetDragDropMenu(true); PutContentsIntoMenu(menu, container); - circ_menus[pos] = {Object = container, Menu = menu}; + circ_menus[pos] = {Object = container, Menu = menu, IsCrew = isCrew}; + + if(isCrew) + crew_count++; + else + container_count++; // Track external changes in containers. AddEffect("ContainerTracker", container, 100, 1, this, nil, menu); @@ -103,18 +125,41 @@ func AddContentMenu(object container, int pos, int length) // Draws the contents menus to the right positions. private func UpdateContentMenus() { - var menu_count = GetLength(circ_menus); - for (var index = 0; index < menu_count; index++) + // for positioning to the left + var index_crew = 0; + // for positioning to the right + var index_containers = 1; // containers start with an offset of 1 + + // calculate left edge + var r = 160; + var d = 2*r/3; + var dx = Sqrt(r**2 - d**2); + var x_base = 800 - dx*(container_count-1); + var y_base = 320; + + for(var prop in circ_menus) { - var menu = circ_menus[index].Menu; - var r = 160; - var d = 2*r/3; - var dx = Sqrt(r**2 - d**2); + var menu = prop.Menu; - // Determine x-position. - var x = 800 + dx * (2*index - menu_count + 1); - // Alternate y-position. - var y = 320 + (-1)**index * d; + var x,y; + + if(prop.IsCrew) + { + x = x_base - dx * (2*index_crew); + y = y_base + 2*d - (-1)**index_crew * d; + + index_crew++; + } + else + { + // Determine x-position. + //x = 800 + dx * (2*index_containers - container_count + 1); + x = x_base + dx*(2*index_containers); + // Alternate y-position. + y = y_base + (-1)**(index_containers) * d; + + index_containers++; + } // TODO: reduce size of menus to fit more into screen. menu->SetPosition(x, y); } @@ -125,7 +170,12 @@ private func PutContentsIntoMenu(object menu, object container) { if (container->~ NoStackedContentMenu()) { - var contents = FindObjects(Find_Container(container)); + var contents; + // get contents in special order if possible + if(!(contents = (container->~GetItems()))) + // else just take everything we find. + contents = FindObjects(Find_Container(container)); + for (var content in contents) if (!AddContentsMenuItem(content, menu)) return; @@ -278,7 +328,12 @@ public func OnExternalContentChange(object menu, object container) } // Reopen the changed menu. - AddContentMenu(container, index, length); + var isCrew = container->GetOCF() & OCF_CrewMember; + if(isCrew) + crew_count--; + else + container_count--; + AddContentMenu(container, index, isCrew); Show(); return; } @@ -386,7 +441,8 @@ private func UpdateAfterTakenObjects(proplist p_source, object menuItem) // otherwise, update // repair "holes" - var remaining_objects = RemoveHoles(objects); + var remaining_objects = objects[:]; + RemoveHoles(remaining_objects); //Log("%v",remaining_objects); menuItem->SetData(remaining_objects); diff --git a/planet/Objects.ocd/HUD.ocd/Menu.ocd/MenuItem.ocd/Script.c b/planet/Objects.ocd/HUD.ocd/Menu.ocd/MenuItem.ocd/Script.c index 66040df6c..ebe5a438c 100644 --- a/planet/Objects.ocd/HUD.ocd/Menu.ocd/MenuItem.ocd/Script.c +++ b/planet/Objects.ocd/HUD.ocd/Menu.ocd/MenuItem.ocd/Script.c @@ -52,7 +52,6 @@ public func MouseSelectionAlt(int plr) // Called to determine which object is dragged. public func MouseDrag(int plr) { - //Log("%s->MouseDrag(%d) for owner: %d, menu: %s, dd: %v", GetName(), plr, GetOwner(), item_menu->GetName(), item_menu->IsDragDropMenu()); // Check if the owners match. if (plr != GetOwner()) return; @@ -91,6 +90,31 @@ public func MouseDragDone(self, object target) return item_menu->OnItemDragDone(self, target); } +// Called if the mouse cursor starts hovering over this item. +public func OnMouseOver(int plr, object dragged) +{ + if (plr != GetOwner()) return; + + // make it appear bigger + SetObjDrawTransform(1100, 0, 0, 0, 1100, 0, 1); + + + // Forward command to menu. + return item_menu->OnMouseOverItem(this, dragged); +} + +// Called if the mouse cursor stops hovering over this item. +public func OnMouseOut(int plr, object dragged) +{ + if (plr != GetOwner()) return; + + // standard size again + SetObjDrawTransform(1000, 0, 0, 0, 1000, 0, 1); + + // Forward command to menu. + return item_menu->OnMouseOutItem(this, dragged); +} + /* Menu item properties */ public func SetMenu(object menu) diff --git a/planet/Objects.ocd/HUD.ocd/Menu.ocd/Script.c b/planet/Objects.ocd/HUD.ocd/Menu.ocd/Script.c index e01c7ab40..8bfae2a3a 100644 --- a/planet/Objects.ocd/HUD.ocd/Menu.ocd/Script.c +++ b/planet/Objects.ocd/HUD.ocd/Menu.ocd/Script.c @@ -165,12 +165,12 @@ private func GetItemPosition(int n, int total) // Packing 7 or less circles. if (total <= 7) { - if (n == 1) + if (n == 7) return [0, 0]; else { - var x = Cos(60 * (n-1), 2 * MENU_Radius / 3); - var y = -Sin(60 * (n-1), 2 * MENU_Radius / 3); + var x = -Cos(60 * (n+1), 2 * MENU_Radius / 3); + var y = -Sin(60 * (n+1), 2 * MENU_Radius / 3); return [x, y]; } } @@ -178,18 +178,18 @@ private func GetItemPosition(int n, int total) // Packing 19 or less circles. if (total <= 19) { - if (n == 1) + if (n == 7) return [0, 0]; - else if (n <= 7) + else if (n < 7) { - var x = Cos(60 * (n-1), 2 * MENU_Radius / 5); - var y = -Sin(60 * (n-1), 2 * MENU_Radius / 5); + var x = -Cos(60 * (n+1), 2 * MENU_Radius / 5); + var y = -Sin(60 * (n+1), 2 * MENU_Radius / 5); return [x, y]; } else { - var x = Cos(30 * (n-7) + 15, 31 * MENU_Radius / 40); - var y = -Sin(30 * (n-7) + 15, 31 * MENU_Radius / 40); + var x = -Cos(30 * (n-5) + 15, 31 * MENU_Radius / 40); + var y = -Sin(30 * (n-5) + 15, 31 * MENU_Radius / 40); return [x, y]; } } @@ -197,24 +197,24 @@ private func GetItemPosition(int n, int total) // Packing 37 or less circles. if (total <= 37) { - if (n == 1) + if (n == 7) return [0, 0]; - else if (n <= 7) + else if (n < 7) { - var x = Cos(60 * (n-1), 2 * MENU_Radius / 7); - var y = -Sin(60 * (n-1), 2 * MENU_Radius / 7); + var x = -Cos(60 * (n+1), 2 * MENU_Radius / 7); + var y = -Sin(60 * (n+1), 2 * MENU_Radius / 7); return [x, y]; } else if (n <= 19) { - var x = Cos(30 * (n-7) + 15, 31 * MENU_Radius / 56); - var y = -Sin(30 * (n-7) + 15, 31 * MENU_Radius / 56); + var x = -Cos(30 * (n-5) + 15, 31 * MENU_Radius / 56); + var y = -Sin(30 * (n-5) + 15, 31 * MENU_Radius / 56); return [x, y]; } else { - var x = Cos(30 * (n-19), 61 * MENU_Radius / 72); - var y = -Sin(30 * (n-19), 61 * MENU_Radius / 72); + var x = -Cos(30 * (n-17), 61 * MENU_Radius / 72); + var y = -Sin(30 * (n-17), 61 * MENU_Radius / 72); return [x, y]; } } @@ -333,7 +333,6 @@ public func OnItemDropped(object drop_item, object on_item) if (!menu_commander) return; // Forward to commander. - // Log("Item dropped %s", drop_item->GetName()); return menu_commander->~OnItemDropped(this, drop_item, on_item); } @@ -342,7 +341,24 @@ public func OnItemDragDone(object drag_item, object on_item) { if (!menu_commander) return; - // Log("Item dragged %s", drag_item->GetName()); // Forward to commander. return menu_commander->~OnItemDragDone(this, drag_item, on_item); } + +// Called if the mouse cursor enters hovering over an item. +public func OnMouseOverItem(object over_item, object dragged_item) +{ + if (!menu_commander) return; + + // Forward to commander. + return menu_commander->~OnMouseOverItem(this, over_item, dragged_item); +} + +// Called if the mouse cursor exits hovering over an item. +public func OnMouseOutItem(object out_item, object dragged_item) +{ + if (!menu_commander) return; + + // Forward to commander. + return menu_commander->~OnMouseOutItem(this, out_item, dragged_item); +} diff --git a/planet/Objects.ocd/Helpers.ocd/FloatingMessage.ocd/Script.c b/planet/Objects.ocd/Helpers.ocd/FloatingMessage.ocd/Script.c index 19a5a50b8..535a6aac4 100644 --- a/planet/Objects.ocd/Helpers.ocd/FloatingMessage.ocd/Script.c +++ b/planet/Objects.ocd/Helpers.ocd/FloatingMessage.ocd/Script.c @@ -42,8 +42,8 @@ func FadeOut(int speed, step) func FxFadeOutTimer(target, effect) { - if(alpha < 5) return RemoveObject(); alpha -= effect.step; + if(alpha < 5) return RemoveObject(); Update(); return 1; } @@ -60,7 +60,8 @@ func SetColor(int r2, g2, b2, a) func Update() { - this->Message(Format("@%s", RGBa(r, g, b, alpha), msg)); + // the lacking is on purpose + this->Message(Format("@%s", RGBa(255, 255, 255, alpha), RGBa(r, g, b, alpha), msg)); } public func Initialize() @@ -69,5 +70,8 @@ public func Initialize() SetComDir(COMD_None); SetSpeed(0, -20); alpha=255; + r = 255; + g = 255; + b = 255; return true; } \ No newline at end of file diff --git a/planet/Objects.ocd/Helpers.ocd/ItemSpark.ocd/Script.c b/planet/Objects.ocd/Helpers.ocd/ItemSpark.ocd/Script.c index c5e78dd13..4e657bbe9 100644 --- a/planet/Objects.ocd/Helpers.ocd/ItemSpark.ocd/Script.c +++ b/planet/Objects.ocd/Helpers.ocd/ItemSpark.ocd/Script.c @@ -102,7 +102,7 @@ func FxCheckStuckTimer(_, effect) func FxSparkleTimer(_, effect) { - var x=RandomX(-4, 4); + //var x=RandomX(-4, 4); //var p="ItemSpark"; //if(Random(2)) p="ItemSparkA"; //CreateParticle(p, x, (4-Abs(x))/2, -x/2, -3, 40, RGBa(50,50,150+Random(100), 200), nil); diff --git a/planet/Objects.ocd/Helpers.ocd/StatusSymbol.ocd/DefCore.txt b/planet/Objects.ocd/Helpers.ocd/StatusSymbol.ocd/DefCore.txt new file mode 100644 index 000000000..0304144dd --- /dev/null +++ b/planet/Objects.ocd/Helpers.ocd/StatusSymbol.ocd/DefCore.txt @@ -0,0 +1,10 @@ +[DefCore] +id=StatusSymbol +Version=4,10,0,0 +Category=C4D_Vehicle | C4D_MouseIgnore +Width=1 +Height=1 +Offset=-1,-1 +Vertices=1 +VertexY=14 +NoGet=1 \ No newline at end of file diff --git a/planet/Objects.ocd/Helpers.ocd/StatusSymbol.ocd/Graphics.png b/planet/Objects.ocd/Helpers.ocd/StatusSymbol.ocd/Graphics.png new file mode 100644 index 000000000..d8e8ac9c6 Binary files /dev/null and b/planet/Objects.ocd/Helpers.ocd/StatusSymbol.ocd/Graphics.png differ diff --git a/planet/Objects.ocd/Helpers.ocd/StatusSymbol.ocd/Script.c b/planet/Objects.ocd/Helpers.ocd/StatusSymbol.ocd/Script.c new file mode 100644 index 000000000..18d2e8942 --- /dev/null +++ b/planet/Objects.ocd/Helpers.ocd/StatusSymbol.ocd/Script.c @@ -0,0 +1,139 @@ +/** + StatusSymbol.ocd + Shows a certain state of an object. +*/ + +local Name = "$Name$"; +local Description = "$Description$"; + +local symbols; +local message; + +local ActMap= +{ + Be = + { + Prototype = Action, + Name="Be", + Procedure=DFA_ATTACH, + NextAction="Be", + Length=1, + FacetBase=1, + AbortCall = "AttachTargetLost" + } +}; + +func AttachTargetLost(){return RemoveObject();} + +func Init(to) +{ + symbols=[]; + SetAction("Be", to); + + // above the object + var hgt = to->GetDefCoreVal("Height", "DefCore") / 2; + SetVertex(0, VTX_Y, hgt); + var x = to->GetVertex(0, VTX_X); + SetVertex(0, VTX_X, x); +} + +public func GetStatusSymbolHelper(to) +{ + var obj = FindObject(Find_ID(StatusSymbol), Find_ActionTarget(to)); + if(obj) return obj; + obj = CreateObject(StatusSymbol, 0, 0, to->GetOwner()); + obj->Init(to); + return obj; +} + +global func AddStatusSymbol(ID) +{ + if(!this) return false; + var h = StatusSymbol->GetStatusSymbolHelper(this); + if(!h) return false; + + h->Add(ID); + return true; +} + +global func RemoveStatusSymbol(ID) +{ + if(!this) return false; + var h = StatusSymbol->GetStatusSymbolHelper(this); + if(!h) return false; + h->Remove(ID); + return true; +} + +func Add(what) +{ + Blink(); + var e = -1; + for(var i=0;iMessage(message); +} + +func Blink() +{ + if(GetEffect("Blinking", this)) + RemoveEffect("Blinking", this); + AddEffect("Blinking", this, 1, 36, this); +} + +func FxBlinkingStart(target, effect, temp) +{ + if(temp) return; + effect.cycle = 1; +} + +func FxBlinkingTimer(target, effect) +{ + this.Visibility = this->GetActionTarget().Visibility; + + if(((++effect.cycle) % 2) == 0) + { + this->Message(""); + return 1; + } + this->Message(message); + return 1; +} + \ No newline at end of file diff --git a/planet/Objects.ocd/Helpers.ocd/StatusSymbol.ocd/StringTblDE.txt b/planet/Objects.ocd/Helpers.ocd/StatusSymbol.ocd/StringTblDE.txt new file mode 100644 index 000000000..b065bbc2a --- /dev/null +++ b/planet/Objects.ocd/Helpers.ocd/StatusSymbol.ocd/StringTblDE.txt @@ -0,0 +1,2 @@ +Name=StatusSymbol.ocd +Description=Shows a certain state of an object. \ No newline at end of file diff --git a/planet/Objects.ocd/Helpers.ocd/StatusSymbol.ocd/StringTblUS.txt b/planet/Objects.ocd/Helpers.ocd/StatusSymbol.ocd/StringTblUS.txt new file mode 100644 index 000000000..b065bbc2a --- /dev/null +++ b/planet/Objects.ocd/Helpers.ocd/StatusSymbol.ocd/StringTblUS.txt @@ -0,0 +1,2 @@ +Name=StatusSymbol.ocd +Description=Shows a certain state of an object. \ No newline at end of file diff --git a/planet/Objects.ocd/Icons.ocd/SlimNumber.ocd/DefCore.txt b/planet/Objects.ocd/Icons.ocd/SlimNumber.ocd/DefCore.txt index 1b51df48e..ff2ffa64d 100644 --- a/planet/Objects.ocd/Icons.ocd/SlimNumber.ocd/DefCore.txt +++ b/planet/Objects.ocd/Icons.ocd/SlimNumber.ocd/DefCore.txt @@ -2,7 +2,7 @@ id=Icon_SlimNumber Version=5,2,0,1 Category=C4D_StaticBack -Picture=0,0,64,64 +Picture=0,0,32,64 Width=32 Height=64 Offset=-16,-32 diff --git a/planet/Objects.ocd/Items.ocd/Foodstuff.ocd/Bread.ocd/DefCore.txt b/planet/Objects.ocd/Items.ocd/Foodstuff.ocd/Bread.ocd/DefCore.txt index 15d60b43c..0d9f3e401 100644 --- a/planet/Objects.ocd/Items.ocd/Foodstuff.ocd/Bread.ocd/DefCore.txt +++ b/planet/Objects.ocd/Items.ocd/Foodstuff.ocd/Bread.ocd/DefCore.txt @@ -12,4 +12,4 @@ VertexFriction=50,100,100 Value=10 Mass=2 Components=Flour=1 -Picture=8,0,16,16 \ No newline at end of file +Picture=32,0,64,64 diff --git a/planet/Objects.ocd/Items.ocd/Resources.ocd/Coal.ocd/DefCore.txt b/planet/Objects.ocd/Items.ocd/Resources.ocd/Coal.ocd/DefCore.txt index 0b046b500..eae72f611 100644 --- a/planet/Objects.ocd/Items.ocd/Resources.ocd/Coal.ocd/DefCore.txt +++ b/planet/Objects.ocd/Items.ocd/Resources.ocd/Coal.ocd/DefCore.txt @@ -5,7 +5,7 @@ Category=C4D_Object Width=8 Height=8 Offset=-4,-4 -Picture=0,0,8,8 +Picture=0,0,64,64 Vertices=3 VertexX=0,2,-2 VertexY=1,-1,-1 diff --git a/planet/Objects.ocd/Items.ocd/Resources.ocd/Coal.ocd/Script.c b/planet/Objects.ocd/Items.ocd/Resources.ocd/Coal.ocd/Script.c index 9eae78f6f..99ca575ee 100644 --- a/planet/Objects.ocd/Items.ocd/Resources.ocd/Coal.ocd/Script.c +++ b/planet/Objects.ocd/Items.ocd/Resources.ocd/Coal.ocd/Script.c @@ -14,7 +14,7 @@ protected func Hit(x, y) } public func IsFuel() { return true; } -public func GetFuelAmount() { return 100; } +public func GetFuelAmount() { return 30; } local Collectible = 1; local Name = "$Name$"; diff --git a/planet/Objects.ocd/Items.ocd/Resources.ocd/GoldBar.ocd/DefCore.txt b/planet/Objects.ocd/Items.ocd/Resources.ocd/GoldBar.ocd/DefCore.txt index 322b972ea..a054a23ca 100644 --- a/planet/Objects.ocd/Items.ocd/Resources.ocd/GoldBar.ocd/DefCore.txt +++ b/planet/Objects.ocd/Items.ocd/Resources.ocd/GoldBar.ocd/DefCore.txt @@ -12,6 +12,6 @@ VertexCNAT=1,2,16 VertexFriction=30,30,30 Value=25 Mass=16 -Picture=0,4,13,13 +Picture=0,20,64,64 Components=Nugget=3 Rotate=1 diff --git a/planet/Objects.ocd/Items.ocd/Resources.ocd/Ice.ocd/DefCore.txt b/planet/Objects.ocd/Items.ocd/Resources.ocd/Ice.ocd/DefCore.txt index 6e8a46413..564cdae82 100644 --- a/planet/Objects.ocd/Items.ocd/Resources.ocd/Ice.ocd/DefCore.txt +++ b/planet/Objects.ocd/Items.ocd/Resources.ocd/Ice.ocd/DefCore.txt @@ -7,7 +7,7 @@ TimerCall=Check Width=8 Height=8 Offset=-4,-4 -Picture=0,0,8,8 +Picture=0,0,64,64 Vertices=3 VertexX=0,2,-2 VertexY=1,-1,-1 diff --git a/planet/Objects.ocd/Items.ocd/Resources.ocd/Loam.ocd/DefCore.txt b/planet/Objects.ocd/Items.ocd/Resources.ocd/Loam.ocd/DefCore.txt index 79d3b042f..14f9a6ebd 100644 --- a/planet/Objects.ocd/Items.ocd/Resources.ocd/Loam.ocd/DefCore.txt +++ b/planet/Objects.ocd/Items.ocd/Resources.ocd/Loam.ocd/DefCore.txt @@ -5,7 +5,7 @@ Category=C4D_Object Width=8 Height=8 Offset=-4,-4 -Picture=0,0,8,8 +Picture=0,0,64,64 Vertices=2 VertexX=0,0 VertexY=3,-3 diff --git a/planet/Objects.ocd/Items.ocd/Resources.ocd/Loam.ocd/Script.c b/planet/Objects.ocd/Items.ocd/Resources.ocd/Loam.ocd/Script.c index 25c011180..514fb3a31 100644 --- a/planet/Objects.ocd/Items.ocd/Resources.ocd/Loam.ocd/Script.c +++ b/planet/Objects.ocd/Items.ocd/Resources.ocd/Loam.ocd/Script.c @@ -60,6 +60,8 @@ func FxIntBridgeTimer(clonk, effect) // clonk faces bridge direction var tdir = 0; + // get global drawing coordinates + var x = target_x + GetX(), y = target_y + GetY(); if (x > 0) ++tdir; clonk->SetDir(tdir); @@ -67,9 +69,6 @@ func FxIntBridgeTimer(clonk, effect) var min_dt = 3; if (target_y < -20 && !Abs(target_x*5/target_y)) min_dt=2; - // get global drawing coordinates - var x = target_x + GetX(), y = target_y + GetY(); - // bridge speed by dig physical var speed = clonk.ActMap.Dig.Speed/6; diff --git a/planet/Objects.ocd/Items.ocd/Resources.ocd/Metal.ocd/DefCore.txt b/planet/Objects.ocd/Items.ocd/Resources.ocd/Metal.ocd/DefCore.txt index 78bb365a6..563dca3e6 100644 --- a/planet/Objects.ocd/Items.ocd/Resources.ocd/Metal.ocd/DefCore.txt +++ b/planet/Objects.ocd/Items.ocd/Resources.ocd/Metal.ocd/DefCore.txt @@ -14,4 +14,4 @@ Value=8 Mass=12 Components=Ore=1 Rotate=1 -Picture=0,4,13,13 +Picture=0,20,64,64 diff --git a/planet/Objects.ocd/Items.ocd/Resources.ocd/Ore.ocd/DefCore.txt b/planet/Objects.ocd/Items.ocd/Resources.ocd/Ore.ocd/DefCore.txt index d9a70bfa2..b633f1be8 100644 --- a/planet/Objects.ocd/Items.ocd/Resources.ocd/Ore.ocd/DefCore.txt +++ b/planet/Objects.ocd/Items.ocd/Resources.ocd/Ore.ocd/DefCore.txt @@ -5,7 +5,7 @@ Category=C4D_Object Width=8 Height=8 Offset=-4,-4 -Picture=0,0,8,8 +Picture=0,0,64,64 Vertices=3 VertexX=0,2,-2 VertexY=1,-1,-1 diff --git a/planet/Objects.ocd/Items.ocd/Resources.ocd/Snow.ocd/DefCore.txt b/planet/Objects.ocd/Items.ocd/Resources.ocd/Snow.ocd/DefCore.txt index 41b066e71..74bfa32bb 100644 --- a/planet/Objects.ocd/Items.ocd/Resources.ocd/Snow.ocd/DefCore.txt +++ b/planet/Objects.ocd/Items.ocd/Resources.ocd/Snow.ocd/DefCore.txt @@ -7,7 +7,7 @@ TimerCall=Check Width=8 Height=8 Offset=-4,-4 -Picture=0,0,8,8 +Picture=0,0,64,64 Vertices=3 VertexX=0,2,-2 VertexY=1,-1,-1 diff --git a/planet/Objects.ocd/Items.ocd/Resources.ocd/Sulphur.ocd/DefCore.txt b/planet/Objects.ocd/Items.ocd/Resources.ocd/Sulphur.ocd/DefCore.txt index 9400307ba..a86bea810 100644 --- a/planet/Objects.ocd/Items.ocd/Resources.ocd/Sulphur.ocd/DefCore.txt +++ b/planet/Objects.ocd/Items.ocd/Resources.ocd/Sulphur.ocd/DefCore.txt @@ -5,7 +5,7 @@ Category=C4D_Object Width=8 Height=8 Offset=-4,-4 -Picture=0,0,8,8 +Picture=0,0,64,64 Vertices=3 VertexX=0,2,-2 VertexY=1,-1,-1 diff --git a/planet/Objects.ocd/Items.ocd/Resources.ocd/Wood.ocd/Script.c b/planet/Objects.ocd/Items.ocd/Resources.ocd/Wood.ocd/Script.c index d49238b14..7d3bf9362 100644 --- a/planet/Objects.ocd/Items.ocd/Resources.ocd/Wood.ocd/Script.c +++ b/planet/Objects.ocd/Items.ocd/Resources.ocd/Wood.ocd/Script.c @@ -12,7 +12,7 @@ func Incineration() } public func IsFuel() { return true; } -public func GetFuelAmount() { return 50; } +public func GetFuelAmount() { return 15; } public func IsSawmillProduct() { return true; } local Collectible = 1; diff --git a/planet/Objects.ocd/Items.ocd/Tools.ocd/Axe.ocd/Script.c b/planet/Objects.ocd/Items.ocd/Tools.ocd/Axe.ocd/Script.c index bd279cecf..b46252707 100644 --- a/planet/Objects.ocd/Items.ocd/Tools.ocd/Axe.ocd/Script.c +++ b/planet/Objects.ocd/Items.ocd/Tools.ocd/Axe.ocd/Script.c @@ -116,8 +116,8 @@ public func ControlUseStart(object clonk, int iX, int iY) return true; var rand = Random(2)+1; - var animation = Format("SwordSlash%d.%s", rand, arm); var arm = "R"; + var animation = Format("SwordSlash%d.%s", rand, arm); var length = 15; carry_bone = "pos_hand2"; @@ -306,7 +306,6 @@ func CheckStrike(iTime) var width=10; var height=20; - var angle=0; for(var obj in FindObjects(Find_AtRect(offset_x - width/2, offset_y - height/2, width, height), Find_NoContainer(), diff --git a/planet/Objects.ocd/Items.ocd/Tools.ocd/Boompack.ocd/DefCore.txt b/planet/Objects.ocd/Items.ocd/Tools.ocd/Boompack.ocd/DefCore.txt index e5f0d6e65..6913389cb 100644 --- a/planet/Objects.ocd/Items.ocd/Tools.ocd/Boompack.ocd/DefCore.txt +++ b/planet/Objects.ocd/Items.ocd/Tools.ocd/Boompack.ocd/DefCore.txt @@ -9,7 +9,6 @@ Vertices=4 VertexX=0,0,-4,4 VertexY=3,-6,10,10 VertexFriction=80,60,60 -Picture=0,0,16,16 Value=12 Mass=20 Components=Blackpowder=3;Wood=1;Metal=1; diff --git a/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/DefCore.txt b/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/DefCore.txt deleted file mode 100644 index c581b1ab9..000000000 --- a/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/DefCore.txt +++ /dev/null @@ -1,15 +0,0 @@ -[DefCore] -id=CableReel -Version=5,2,0,1 -Category=C4D_Object -Width=8 -Height=6 -Offset=-4,-3 -Vertices=3 -VertexX=0,2,-2 -VertexY=1,-1,-1 -VertexFriction=50,50,50 -Value=10 -Mass=15 -Components=Metal=1 -Picture=0,6,64,64 diff --git a/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/Graphics.png b/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/Graphics.png deleted file mode 100644 index 2eedb36aa..000000000 Binary files a/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/Graphics.png and /dev/null differ diff --git a/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/PowerLine.ocd/DefCore.txt b/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/PowerLine.ocd/DefCore.txt deleted file mode 100644 index 0063d2298..000000000 --- a/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/PowerLine.ocd/DefCore.txt +++ /dev/null @@ -1,6 +0,0 @@ -[DefCore] -id=PowerLine -Version=5,2,0,1 -Category=C4D_StaticBack -Vertices=2 -Line=1 diff --git a/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/PowerLine.ocd/Graphics.png b/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/PowerLine.ocd/Graphics.png deleted file mode 100644 index 753695654..000000000 Binary files a/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/PowerLine.ocd/Graphics.png and /dev/null differ diff --git a/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/PowerLine.ocd/Script.c b/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/PowerLine.ocd/Script.c deleted file mode 100644 index d4d271793..000000000 --- a/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/PowerLine.ocd/Script.c +++ /dev/null @@ -1,62 +0,0 @@ -/*-- Power line --*/ - -protected func Initialize() -{ - SetAction("Connect"); - SetVertexXY(0, GetX(), GetY()); - SetVertexXY(1, GetX(), GetY()); - SetProperty("LineColors", [RGB(80,80,80), RGB(80,80,80)]); - return; -} - -// Returns true if this object is a functioning power line. -public func IsPowerLine() -{ - return GetAction() == "Connect"; -} - -// Returns whether this power line is connected to an object. -public func IsConnectedTo(object obj) -{ - return GetActionTarget(0) == obj || GetActionTarget(1) == obj; -} - -// Returns the object which is connected to obj through this power line. -public func GetConnectedObject(object obj) -{ - if (GetActionTarget(0) == obj) - return GetActionTarget(1); - if (GetActionTarget(1) == obj) - return GetActionTarget(0); - return; -} - -protected func LineBreak(bool no_msg) -{ - Sound("LineBreak"); - if (!no_msg) - BreakMessage(); - return; -} - -private func BreakMessage() -{ - var line_end = GetActionTarget(0); - if (line_end->GetID() != CableReel) - line_end = GetActionTarget(1); - - line_end->Message("$TxtLinebroke$"); - return; -} - -local ActMap = { - Connect = { - Prototype = Action, - Name = "Connect", - Procedure = DFA_CONNECT, - NextAction = "Connect", - }, -}; - -local Name = "$Name$"; - diff --git a/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/PowerLine.ocd/StringTblDE.txt b/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/PowerLine.ocd/StringTblDE.txt deleted file mode 100644 index 5b460374d..000000000 --- a/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/PowerLine.ocd/StringTblDE.txt +++ /dev/null @@ -1,2 +0,0 @@ -TxtLinebroke=Leitung gerissen -Name=Stromleitung diff --git a/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/PowerLine.ocd/StringTblUS.txt b/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/PowerLine.ocd/StringTblUS.txt deleted file mode 100644 index 6be18aa69..000000000 --- a/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/PowerLine.ocd/StringTblUS.txt +++ /dev/null @@ -1,2 +0,0 @@ -TxtLinebroke=Line broke -Name=Power line \ No newline at end of file diff --git a/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/Script.c b/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/Script.c deleted file mode 100644 index fe1cd1da1..000000000 --- a/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/Script.c +++ /dev/null @@ -1,70 +0,0 @@ -/*-- Cable reel --*/ - -protected func Hit() -{ - Sound("RockHit?"); -} - -public func IsToolProduct() { return true; } - -/*-- Line connection --*/ - -// Use will connect power line to building at the clonk's position. -protected func ControlUse(object clonk, int x, int y) -{ - // Is there an object which accepts power lines? - var obj = FindObject(Find_AtPoint(), Find_Func("CanPowerConnect")); - // No such object -> message. - if (!obj) - return clonk->Message("$TxtNoNewLine$"); - // Is there a power line connected to this wire roll? - var line = FindObject(Find_PowerLine()); - // There already is a power line. - if (line) - { - if (obj == line->GetActionTarget(0) || obj == line->GetActionTarget(1)) - { - // Power line is already connected to obj -> remove line. - line->RemoveObject(); - Sound("Connect"); - clonk->Message("$TxtLineRemoval$"); - return true; - } - else - { - // Connect existing power line to obj. - if(line->GetActionTarget(0) == this) - line->SetActionTargets(obj, line->GetActionTarget(1)); - else if(line->GetActionTarget(1) == this) - line->SetActionTargets(line->GetActionTarget(0), obj); - else - return; - Sound("Connect"); - clonk->Message("$TxtConnect$", obj->GetName()); - RemoveObject(); - return true; - } - } - else // A new power line needs to be created. - { - line = CreateObject(PowerLine, 0, 0, NO_OWNER); - line->SetActionTargets(this, obj); - Sound("Connect"); - clonk->Message("$TxtConnect$", obj->GetName()); - return true; - } - return true; -} - -// Finds all power lines connected to obj (can be nil in local calls). -private func Find_PowerLine(object obj) -{ - if (!obj) - obj = this; - return [C4FO_Func, "IsConnectedTo", obj]; -} - -local Name = "$Name$"; -local Description = "$Description$"; -local Collectible = 1; -local Rebuy = true; diff --git a/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/StringTblDE.txt b/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/StringTblDE.txt deleted file mode 100644 index 698c82526..000000000 --- a/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/StringTblDE.txt +++ /dev/null @@ -1,6 +0,0 @@ -TxtConnectLine=Leitung verbinden -TxtNoNewLine=Hier kann keine neue Leitung verlegt werden. -TxtLineRemoval=Stromleitung abgenommen. -TxtConnect=Stromleitung verbunden|mit %s -Name=Kabelspule -Description=Drücke [Benutzen] vor einem Gebäude und ein weiteres Mal vor einem anderen Gebäude, um diese beiden mit einem Stromkabel zu verbinden. \ No newline at end of file diff --git a/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/StringTblUS.txt b/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/StringTblUS.txt deleted file mode 100644 index 81b3c1f03..000000000 --- a/planet/Objects.ocd/Items.ocd/Tools.ocd/CableReel.ocd/StringTblUS.txt +++ /dev/null @@ -1,6 +0,0 @@ -TxtConnectLine=Connect line -TxtNoNewLine=Cannot create a new line here. -TxtLineRemoval=Power line disconnected. -TxtConnect=Power line connected|to %s -Name=Cable reel -Description=Press [Use] in front of a structure and another time in front of another structure to connect both with a power line. \ No newline at end of file diff --git a/planet/Objects.ocd/Items.ocd/Tools.ocd/Dynamite.ocd/DefCore.txt b/planet/Objects.ocd/Items.ocd/Tools.ocd/Dynamite.ocd/DefCore.txt index 93a879b04..080091f6d 100644 --- a/planet/Objects.ocd/Items.ocd/Tools.ocd/Dynamite.ocd/DefCore.txt +++ b/planet/Objects.ocd/Items.ocd/Tools.ocd/Dynamite.ocd/DefCore.txt @@ -5,7 +5,7 @@ Category=C4D_Object Width=3 Height=10 Offset=-2,-5 -Picture=4,0,16,16 +Picture=16,0,64,64 Vertices=3 VertexX=-2,+2,0 VertexY=5,5,-5 diff --git a/planet/Objects.ocd/Items.ocd/Tools.ocd/DynamiteBox.ocd/Script.c b/planet/Objects.ocd/Items.ocd/Tools.ocd/DynamiteBox.ocd/Script.c index baac24d9d..961620cf3 100644 --- a/planet/Objects.ocd/Items.ocd/Tools.ocd/DynamiteBox.ocd/Script.c +++ b/planet/Objects.ocd/Items.ocd/Tools.ocd/DynamiteBox.ocd/Script.c @@ -76,7 +76,6 @@ private func UpdatePicture() var s = 400; var yoffs = 14000; var xoffs = 22000; - var spacing = 14000; SetGraphics(Format("%d", iCount), Icon_Number, 12, GFXOV_MODE_Picture); SetObjDrawTransform(s, 0, xoffs, 0, s, yoffs, 12); diff --git a/planet/Objects.ocd/Items.ocd/Tools.ocd/GrappleBow.ocd/Hook.ocd/Script.c b/planet/Objects.ocd/Items.ocd/Tools.ocd/GrappleBow.ocd/Hook.ocd/Script.c index d61dfb069..3fba86440 100644 --- a/planet/Objects.ocd/Items.ocd/Tools.ocd/GrappleBow.ocd/Hook.ocd/Script.c +++ b/planet/Objects.ocd/Items.ocd/Tools.ocd/GrappleBow.ocd/Hook.ocd/Script.c @@ -319,7 +319,7 @@ public func FxIntGrappleControlTimer(object target, fxnum, int time) var angle = rope->GetClonkAngle(); var off = rope->GetClonkOff(); // off = [0,0]; - var pos = rope->GetClonkPos(); + //var pos = rope->GetClonkPos(); //target->SetPosition(pos[0], pos[1], nil, Rope_Precision); target.MyAngle = angle; //angle = 0; diff --git a/planet/Objects.ocd/Items.ocd/Tools.ocd/GrappleBow.ocd/Rope.ocd/Script.c b/planet/Objects.ocd/Items.ocd/Tools.ocd/GrappleBow.ocd/Rope.ocd/Script.c index 16ae08d49..1d98b93e2 100644 --- a/planet/Objects.ocd/Items.ocd/Tools.ocd/GrappleBow.ocd/Rope.ocd/Script.c +++ b/planet/Objects.ocd/Items.ocd/Tools.ocd/GrappleBow.ocd/Rope.ocd/Script.c @@ -159,7 +159,6 @@ local last_point; func UpdateLines() { - var fTimeStep = 1; var oldangle; for(var i=1; i < ParticleCount; i++) { @@ -240,18 +239,6 @@ func GetClonkPos() func GetClonkOff() { return Vec_Sub(particles[-1][0],last_point); - var clonk = objects[1][0]; - var speed = [clonk->GetXDir(Rope_Precision), clonk->GetYDir(Rope_Precision)]; - var offset = speed; - offset[0] = offset[0]*1000/Rope_Precision; - offset[1] = offset[1]*1000/Rope_Precision; - if(!ClonkOldSpeed) - { - ClonkOldSpeed = offset; - } - var ret = ClonkOldSpeed; - ClonkOldSpeed = offset; - return ret; } func SetLineTransform(obj, int r, int xoff, int yoff, int length, int layer, int MirrorSegments) { diff --git a/planet/Objects.ocd/Items.ocd/Tools.ocd/JarOfWinds.ocd/DefCore.txt b/planet/Objects.ocd/Items.ocd/Tools.ocd/JarOfWinds.ocd/DefCore.txt index dec0db45d..78c6724cd 100644 --- a/planet/Objects.ocd/Items.ocd/Tools.ocd/JarOfWinds.ocd/DefCore.txt +++ b/planet/Objects.ocd/Items.ocd/Tools.ocd/JarOfWinds.ocd/DefCore.txt @@ -9,7 +9,7 @@ Vertices=4 VertexX=-1,3,-1,-5 VertexY=-4,0,4,0 VertexFriction=50,50,50,50 -Picture=0,1,9,9 +Picture=0,0,64,64 Value=14 Mass=15 Components=Rock=6;Metal=1; diff --git a/planet/Objects.ocd/Items.ocd/Tools.ocd/JarOfWinds.ocd/Script.c b/planet/Objects.ocd/Items.ocd/Tools.ocd/JarOfWinds.ocd/Script.c index fb043c153..90b968f08 100644 --- a/planet/Objects.ocd/Items.ocd/Tools.ocd/JarOfWinds.ocd/Script.c +++ b/planet/Objects.ocd/Items.ocd/Tools.ocd/JarOfWinds.ocd/Script.c @@ -117,22 +117,22 @@ private func FireWeapon(object pClonk,iX,iY) for(var i=10; i<32; i++) { var R = RandomX(-20,20); - var SX = Sin(180 - Angle(0,0,iX,iY) + R,i); - var SY = Cos(180 - Angle(0,0,iX,iY) + R,i); + var SX = Sin(180 - iAngle + R,i); + var SY = Cos(180 - iAngle + R,i); if(!GBackSolid(SX,SY)) { CreateParticle("Air", SX,SY, - Sin(180 - Angle(0,0,iX,iY) + (R),(Amount / 2) + 25), - Cos(180 - Angle(0,0,iX,iY) + (R),(Amount / 2) + 25), + Sin(180 - iAngle + (R),(Amount / 2) + 25), + Cos(180 - iAngle + (R),(Amount / 2) + 25), Max(i + 30, 90) + 75, ); } } - var sinspeed = Sin(180 - Angle(0,0,iX,iY) + (R / 2),(Amount) + 15); - var cosspeed = Cos(180 - Angle(0,0,iX,iY) + (R / 2),(Amount) + 15); + var sinspeed = Sin(180 - iAngle + (R / 2),(Amount) + 15); + var cosspeed = Cos(180 - iAngle + (R / 2),(Amount) + 15); if(pClonk->GetAction() != "Walk") { //Makes the clonk firing it be pushed backwards a bit @@ -144,9 +144,9 @@ private func FireWeapon(object pClonk,iX,iY) for( var obj in FindObjects( Find_Or( - Find_Distance(10,Sin(180 - Angle(0,0,iX,iY),20),Cos(180 - Angle(0,0,iX,iY),20)), - Find_Distance(18,Sin(180 - Angle(0,0,iX,iY),40),Cos(180 - Angle(0,0,iX,iY),40)), - Find_Distance(25,Sin(180 - Angle(0,0,iX,iY),70),Cos(180 - Angle(0,0,iX,iY),70)) + Find_Distance(10,Sin(180 - iAngle,20),Cos(180 - iAngle,20)), + Find_Distance(18,Sin(180 - iAngle,40),Cos(180 - iAngle,40)), + Find_Distance(25,Sin(180 - iAngle,70),Cos(180 - iAngle,70)) ), Find_Not(Find_Category(C4D_Structure)), Find_Not(Find_Func("NoWindjarForce")), diff --git a/planet/Objects.ocd/Items.ocd/Tools.ocd/Pickaxe.ocd/DefCore.txt b/planet/Objects.ocd/Items.ocd/Tools.ocd/Pickaxe.ocd/DefCore.txt index a106fd0c8..602c60811 100644 --- a/planet/Objects.ocd/Items.ocd/Tools.ocd/Pickaxe.ocd/DefCore.txt +++ b/planet/Objects.ocd/Items.ocd/Tools.ocd/Pickaxe.ocd/DefCore.txt @@ -9,7 +9,6 @@ Vertices=4 VertexX=0,-4,4,0 VertexY=-4,-3,-3,4 VertexFriction=50,100,100,40 -Picture=10,0,64,64 Value=10 Mass=20 Components=Wood=1;Metal=1; diff --git a/planet/Objects.ocd/Items.ocd/Tools.ocd/Pickaxe.ocd/Script.c b/planet/Objects.ocd/Items.ocd/Tools.ocd/Pickaxe.ocd/Script.c index b96082204..c028e4c89 100644 --- a/planet/Objects.ocd/Items.ocd/Tools.ocd/Pickaxe.ocd/Script.c +++ b/planet/Objects.ocd/Items.ocd/Tools.ocd/Pickaxe.ocd/Script.c @@ -89,8 +89,6 @@ protected func DoSwing(object clonk, int ix, int iy) ++iDist; } - var x = Sin(180-angle,iDist-8); - var y = Cos(180-angle,iDist-8); var x2 = Sin(180-angle,iDist); var y2 = Cos(180-angle,iDist); diff --git a/planet/Objects.ocd/Items.ocd/Tools.ocd/Ropebridge.ocd/BridgePost.ocd/DefCore.txt b/planet/Objects.ocd/Items.ocd/Tools.ocd/Ropebridge.ocd/BridgePost.ocd/DefCore.txt index 927575aae..2514993e5 100644 --- a/planet/Objects.ocd/Items.ocd/Tools.ocd/Ropebridge.ocd/BridgePost.ocd/DefCore.txt +++ b/planet/Objects.ocd/Items.ocd/Tools.ocd/Ropebridge.ocd/BridgePost.ocd/DefCore.txt @@ -2,11 +2,11 @@ id=Ropebridge_Post Version=5,2,0,1 Category=C4D_Structure -Picture=20,0,64,64 +Picture=0,0,96,128 Width=12 Height=16 Offset=-6,-10 Vertices=2 VertexY=5,5 VertexX=-2,2 -Rotate=0 \ No newline at end of file +Rotate=0 diff --git a/planet/Objects.ocd/Items.ocd/Tools.ocd/Ropebridge.ocd/Script.c b/planet/Objects.ocd/Items.ocd/Tools.ocd/Ropebridge.ocd/Script.c index aef5c43c8..9d49e8847 100644 --- a/planet/Objects.ocd/Items.ocd/Tools.ocd/Ropebridge.ocd/Script.c +++ b/planet/Objects.ocd/Items.ocd/Tools.ocd/Ropebridge.ocd/Script.c @@ -75,10 +75,6 @@ public func MakeBridge(obj1, obj2) func FxIntHangTimer() { TimeStep(); - var iLeft = objects[0][0]->GetX()-GetX(); - var iRight = objects[1][0]->GetX()-GetX(); - var iTop = Min(objects[0][0]->GetY(),objects[1][0]->GetY())-GetY(); - var iDown = segments[GetLength(segments)/2]->GetY()-GetY(); for(var i = 1; i < ParticleCount-1; i++) particles[i][2] = [0,segments[i]->~GetLoadWeight()]; } @@ -138,7 +134,6 @@ func DrawRopeLine2(start, end, i, int index) func UpdateLines() { - var fTimeStep = 1; var oldangle = Angle(particles[1][0][0], particles[1][0][1], particles[0][0][0], particles[0][0][1]); for(var i=1; i < ParticleCount; i++) { diff --git a/planet/Objects.ocd/Items.ocd/Tools.ocd/Ropeladder.ocd/LadderSegment.ocd/DefCore.txt b/planet/Objects.ocd/Items.ocd/Tools.ocd/Ropeladder.ocd/LadderSegment.ocd/DefCore.txt index d550dccb8..573632662 100644 --- a/planet/Objects.ocd/Items.ocd/Tools.ocd/Ropeladder.ocd/LadderSegment.ocd/DefCore.txt +++ b/planet/Objects.ocd/Items.ocd/Tools.ocd/Ropeladder.ocd/LadderSegment.ocd/DefCore.txt @@ -8,4 +8,4 @@ Offset=-3,-7 Vertices=2 VertexX=0,0 VertexY=-5,5 -Picture=0,0,36,32 +Picture=0,0,50,80 diff --git a/planet/Objects.ocd/Items.ocd/Tools.ocd/Ropeladder.ocd/Script.c b/planet/Objects.ocd/Items.ocd/Tools.ocd/Ropeladder.ocd/Script.c index af04b210f..798a8228a 100644 --- a/planet/Objects.ocd/Items.ocd/Tools.ocd/Ropeladder.ocd/Script.c +++ b/planet/Objects.ocd/Items.ocd/Tools.ocd/Ropeladder.ocd/Script.c @@ -278,7 +278,6 @@ private func RopeRemoved() /* --------------------- Graphics of segments ---------------------- */ func UpdateLines() { - var fTimeStep = 1; var oldangle; for(var i=1; i < ParticleCount; i++) { diff --git a/planet/Objects.ocd/Items.ocd/Tools.ocd/TeleGlove.ocd/DefCore.txt b/planet/Objects.ocd/Items.ocd/Tools.ocd/TeleGlove.ocd/DefCore.txt index fd09c6d55..59af346e0 100644 --- a/planet/Objects.ocd/Items.ocd/Tools.ocd/TeleGlove.ocd/DefCore.txt +++ b/planet/Objects.ocd/Items.ocd/Tools.ocd/TeleGlove.ocd/DefCore.txt @@ -9,7 +9,6 @@ Vertices=3 VertexX=0,-3,3 VertexY=-3,2,2 VertexFriction=40,40,40 -Picture=0,0,8,8 Value=20 Mass=7 Components=Metal=2;Crystal=2; diff --git a/planet/Objects.ocd/Items.ocd/Tools.ocd/TeleGlove.ocd/Script.c b/planet/Objects.ocd/Items.ocd/Tools.ocd/TeleGlove.ocd/Script.c index cdd6e3502..e80a32096 100644 --- a/planet/Objects.ocd/Items.ocd/Tools.ocd/TeleGlove.ocd/Script.c +++ b/planet/Objects.ocd/Items.ocd/Tools.ocd/TeleGlove.ocd/Script.c @@ -144,6 +144,7 @@ public func ControlUseHolding(object clonk, ix, iy) CreateParticle("Spark1", Sin(xp, Random(distp)), -Cos(yp, Random(distp)), Sin(xp, 10), -Cos(yp, 10), RandomX(30,90), RGB(185,250,250)); } + var target; if(target_object) { radiusparticle = 30; @@ -160,7 +161,7 @@ public func ControlUseHolding(object clonk, ix, iy) { radiusparticle = 60; - var target = FindObject(Find_Exclude(this), + target = FindObject(Find_Exclude(this), Find_NoContainer(), Find_Category(C4D_Object), Find_And(Find_Distance(radius, ix, iy), diff --git a/planet/Objects.ocd/Items.ocd/Weapons.ocd/Bow.ocd/Arrow.ocd/DefCore.txt b/planet/Objects.ocd/Items.ocd/Weapons.ocd/Bow.ocd/Arrow.ocd/DefCore.txt index bf60368b6..224c4ab97 100644 --- a/planet/Objects.ocd/Items.ocd/Weapons.ocd/Bow.ocd/Arrow.ocd/DefCore.txt +++ b/planet/Objects.ocd/Items.ocd/Weapons.ocd/Bow.ocd/Arrow.ocd/DefCore.txt @@ -11,6 +11,6 @@ VertexFriction=120,120,120 Value=15 Mass=8 Components=Wood=3 -Picture=4,0,21,21 +Picture=12,0,64,64 Rotate=1 Float=1 diff --git a/planet/Objects.ocd/Items.ocd/Weapons.ocd/Bow.ocd/Arrow.ocd/HelpArrow.ocd/DefCore.txt b/planet/Objects.ocd/Items.ocd/Weapons.ocd/Bow.ocd/Arrow.ocd/HelpArrow.ocd/DefCore.txt index 4dd93ef55..bad195077 100644 --- a/planet/Objects.ocd/Items.ocd/Weapons.ocd/Bow.ocd/Arrow.ocd/HelpArrow.ocd/DefCore.txt +++ b/planet/Objects.ocd/Items.ocd/Weapons.ocd/Bow.ocd/Arrow.ocd/HelpArrow.ocd/DefCore.txt @@ -11,6 +11,5 @@ VertexFriction=120,120,120 Value=15 Mass=15 Components=Wood=5 -Picture=4,0,21,21 Rotate=1 Float=1 diff --git a/planet/Objects.ocd/Items.ocd/Weapons.ocd/Club.ocd/DefCore.txt b/planet/Objects.ocd/Items.ocd/Weapons.ocd/Club.ocd/DefCore.txt index 78a3413bb..425344d79 100644 --- a/planet/Objects.ocd/Items.ocd/Weapons.ocd/Club.ocd/DefCore.txt +++ b/planet/Objects.ocd/Items.ocd/Weapons.ocd/Club.ocd/DefCore.txt @@ -9,7 +9,6 @@ Vertices=2 VertexX=0,0 VertexY=-7,7 VertexFriction=50,50 -Picture=10,10,54,54 Value=10 Mass=20 Components=Wood=1;Metal=1; diff --git a/planet/Objects.ocd/Items.ocd/Weapons.ocd/Club.ocd/Script.c b/planet/Objects.ocd/Items.ocd/Weapons.ocd/Club.ocd/Script.c index eee27f715..dcd87af0d 100644 --- a/planet/Objects.ocd/Items.ocd/Weapons.ocd/Club.ocd/Script.c +++ b/planet/Objects.ocd/Items.ocd/Weapons.ocd/Club.ocd/Script.c @@ -194,7 +194,6 @@ func DoStrike(clonk, angle) if(obj->GetOCF() & OCF_Alive) { var damage=5*1000; - var f=ApplyShieldFactor(clonk, obj, damage); ApplyWeaponBash(obj, 400, angle); obj->DoEnergy(-damage, true, FX_Call_EngGetPunched, clonk->GetOwner()); } diff --git a/planet/Objects.ocd/Items.ocd/Weapons.ocd/IronBomb.ocd/DefCore.txt b/planet/Objects.ocd/Items.ocd/Weapons.ocd/IronBomb.ocd/DefCore.txt index 3b0cc3ebe..e0f3b27bf 100644 --- a/planet/Objects.ocd/Items.ocd/Weapons.ocd/IronBomb.ocd/DefCore.txt +++ b/planet/Objects.ocd/Items.ocd/Weapons.ocd/IronBomb.ocd/DefCore.txt @@ -5,7 +5,7 @@ Category=C4D_Object Width=6 Height=6 Offset=-3,-3 -Picture=6,0,16,16 +Picture=24,0,64,64 Vertices=3 VertexX=0,3,-3 VertexY=-2,2,2 diff --git a/planet/Objects.ocd/Items.ocd/Weapons.ocd/Musket.ocd/Ammo.ocd/DefCore.txt b/planet/Objects.ocd/Items.ocd/Weapons.ocd/Musket.ocd/Ammo.ocd/DefCore.txt index 41a808a5b..62ab9f4ea 100644 --- a/planet/Objects.ocd/Items.ocd/Weapons.ocd/Musket.ocd/Ammo.ocd/DefCore.txt +++ b/planet/Objects.ocd/Items.ocd/Weapons.ocd/Musket.ocd/Ammo.ocd/DefCore.txt @@ -9,7 +9,7 @@ Vertices=3 VertexX=0,-3,3 VertexY=0,1,1 VertexFriction=50 -Picture=8,0,8,8 +Picture=64,0,64,64 Value=10 Mass=5 Components=Metal=1;Blackpowder=1; diff --git a/planet/Objects.ocd/Libraries.ocd/Base.ocd/Script.c b/planet/Objects.ocd/Libraries.ocd/Base.ocd/Script.c index 7757c3435..692eb0441 100644 --- a/planet/Objects.ocd/Libraries.ocd/Base.ocd/Script.c +++ b/planet/Objects.ocd/Libraries.ocd/Base.ocd/Script.c @@ -317,9 +317,7 @@ func UpdateClonkSellMenus() func OpenSellMenu(object pClonk, int iSelection, bool fNoListUpdate) { // Filled with [idDef, iCount, pObj] arrays - var aList = []; var aArray; - var pObj; var iIndex; if(!fNoListUpdate) UpdateSellList(); diff --git a/planet/Objects.ocd/Libraries.ocd/ClonkControl.ocd/Crosshair.ocd/Script.c b/planet/Objects.ocd/Libraries.ocd/ClonkControl.ocd/Crosshair.ocd/Script.c index 1d196d646..b82df0628 100644 --- a/planet/Objects.ocd/Libraries.ocd/ClonkControl.ocd/Crosshair.ocd/Script.c +++ b/planet/Objects.ocd/Libraries.ocd/ClonkControl.ocd/Crosshair.ocd/Script.c @@ -44,7 +44,6 @@ public func FxMoveTimer() var angle_diff = Normalize(target_angle - angle, -1800, 10); if (angle_diff == 0) angle_diff = 1; - var dir = angle_diff / Abs(angle_diff); angle = angle + angle_diff * analog_strength / 100 / 8; } diff --git a/planet/Objects.ocd/Libraries.ocd/ClonkControl.ocd/Script.c b/planet/Objects.ocd/Libraries.ocd/ClonkControl.ocd/Script.c index 5cea1667b..d397c282f 100644 --- a/planet/Objects.ocd/Libraries.ocd/ClonkControl.ocd/Script.c +++ b/planet/Objects.ocd/Libraries.ocd/ClonkControl.ocd/Script.c @@ -61,6 +61,14 @@ public func GetItem(int i) return inventory[i]; } +/* returns all items in the inventory */ +public func GetItems() +{ + var inv = inventory[:]; + RemoveHoles(inv); + return inv; +} + // For the HUD: this object shows its items in the HUD (i.e. has the GetItem function) public func HUDShowItems() { return true; } @@ -770,10 +778,10 @@ public func ObjectCommand(string command, object target, int tx, int ty, object { // special control for throw and jump // but only with controls, not with general commands - if (command == "Throw") this->~ControlThrow(target,tx,ty); - else if (command == "Jump") this->~ControlJump(); + if (command == "Throw") return this->~ControlThrow(target,tx,ty); + else if (command == "Jump") return this->~ControlJump(); // else standard command - else SetCommand(command,target,tx,ty,target2); + else return SetCommand(command,target,tx,ty,target2); // this function might be obsolete: a normal SetCommand does make a callback to // script before it is executed: ControlCommand(szCommand, pTarget, iTx, iTy) @@ -1121,8 +1129,6 @@ public func CanEnter() // Handles enter and exit private func ObjectControlEntrance(int plr, int ctrl) { - var proc = GetProcedure(); - // enter if (ctrl == CON_Enter) { diff --git a/planet/Objects.ocd/Libraries.ocd/Constructor.ocd/ConstructionMenu.ocd/Script.c b/planet/Objects.ocd/Libraries.ocd/Constructor.ocd/ConstructionMenu.ocd/Script.c index 442b7e8ab..605109508 100644 --- a/planet/Objects.ocd/Libraries.ocd/Constructor.ocd/ConstructionMenu.ocd/Script.c +++ b/planet/Objects.ocd/Libraries.ocd/Constructor.ocd/ConstructionMenu.ocd/Script.c @@ -77,9 +77,7 @@ public func HideConstructionInfo() /* Menu properties */ -public func IsProductionMenu() { return true; } -// UpdateCursor is called -public func CursorUpdatesEnabled() { return true; } +public func IsConstructionMenu() { return true; } public func Close() { @@ -95,21 +93,6 @@ public func HasCommander(object producer) return false; } -// Callback if the mouse is moved -public func UpdateCursor(int dx, int dy) -{ - var item = FindObject(Find_AtPoint(dx, dy), Find_ID(GUI_MenuItem)); - if (!item || item->GetMenu() != this) - { - if (constructinfo_shown) - HideConstructionInfo(); - return; - } - if (item == constructinfo_shown) - return; - ShowConstructionInfo(item); -} - /* Callbacks from the menu items, to be translated into commands for the producer. */ // Called when a click outside the menu has been made. @@ -151,3 +134,18 @@ public func OnItemDragDone(object drag_item, object on_item) return _inherited(drag_item, on_item, ...); } +// Called if the mouse cursor enters hovering over an item. +public func OnMouseOverItem(object over_item, object dragged_item) +{ + ShowConstructionInfo(over_item); + + return _inherited(over_item, dragged_item, ...); +} + +// Called if the mouse cursor exits hovering over an item. +public func OnMouseOutItem(object out_item, object dragged_item) +{ + HideConstructionInfo(); + + return _inherited(out_item, dragged_item, ...); +} \ No newline at end of file diff --git a/planet/Objects.ocd/Libraries.ocd/ElevatorControl.ocd/Script.c b/planet/Objects.ocd/Libraries.ocd/ElevatorControl.ocd/Script.c index 237957003..e181a4d00 100644 --- a/planet/Objects.ocd/Libraries.ocd/ElevatorControl.ocd/Script.c +++ b/planet/Objects.ocd/Libraries.ocd/ElevatorControl.ocd/Script.c @@ -31,7 +31,7 @@ func ControlStop(object clonk, int control) { var effect = GetEffect("ElevatorControl", this); effect.controlled = nil; - return effect.case->ControlStop(clonk, control);; + return effect.case->ControlStop(clonk, control); } return _inherited(clonk, control); } diff --git a/planet/Objects.ocd/Libraries.ocd/Flag.ocd/Script.c b/planet/Objects.ocd/Libraries.ocd/Flag.ocd/Script.c index 1f8918cab..32d0955a5 100644 --- a/planet/Objects.ocd/Libraries.ocd/Flag.ocd/Script.c +++ b/planet/Objects.ocd/Libraries.ocd/Flag.ocd/Script.c @@ -14,7 +14,7 @@ public func IsFlagpole(){return true;} global func GetFlagpoleForPosition(int x, int y) { - if(GetType(LibraryFlag_flag_list) != C4V_Array) return NO_OWNER; + if(GetType(LibraryFlag_flag_list) != C4V_Array) return nil; var oldest = nil, oldest_time = 0; @@ -45,6 +45,52 @@ func RefreshAllFlagLinks() { f->ScheduleRefreshLinkedFlags(); } + + // update power balance for power helpers after refreshing the linked flags + Schedule(nil, "Library_Flag->RefreshAllPowerHelpers()", 2, 0); + AddEffect("ScheduleRefreshAllPowerHelpers", 0, 1, 2, nil, Library_Flag); +} + +func FxScheduleRefreshAllPowerHelpersTimer() +{ + Library_Flag->RefreshAllPowerHelpers(); + return -1; +} + +func RefreshAllPowerHelpers() +{ + // no power helpers created yet + if(GetType(Library_Power_power_compounds) != C4V_Array) + return; + + // special handling for neutral + var neutral = nil; + for(var obj in Library_Power_power_compounds) + { + if(!obj.neutral) continue; + neutral = obj; + break; + } + + if(neutral) + { + RefreshPowerHelper(neutral); + } + + // same for all helpers - delete / refresh + for(var i = GetLength(Library_Power_power_compounds); --i >= 0;) + { + var obj = Library_Power_power_compounds[i]; + if(GetLength(obj.power_links) == 0 && GetLength(obj.sleeping_links) == 0) + { + obj->RemoveObject(); + Library_Power_power_compounds[i] = Library_Power_power_compounds[GetLength(Library_Power_power_compounds) - 1]; + SetLength(Library_Power_power_compounds, GetLength(Library_Power_power_compounds) - 1); + continue; + } + + obj->CheckPowerBalance(); + } } func RedrawFlagRadius() @@ -89,58 +135,6 @@ func RedrawFlagRadius() } } - // check allied flags - // don't draw inner border - /* - if(draw && GetLength(other_flags)) - { - var own_flags = []; - - for(var f in LibraryFlag_flag_list) - { - if(f->GetOwner() != GetOwner()) continue; - if(f == this) continue; - own_flags[i++] = f; - } - - // sort own flags for age - insert sort okay here since probably 99% sorted already - for(var fi = 1; fi < GetLength(own_flags); ++fi) - { - var ft = own_flags[fi]; - var t = ft->GetFlagConstructionTime(); - for(var ci = fi-1; ci >= 0; ++ci) - { - if(own_flags[ci]->GetFlagConstructionTime() >= t) continue; - - // right position? - if(ci == fi-1) break; - - // move to the right - for(var mi = ci+1;miGetX(),f->GetY())<(FLAG_DISTANCE)) - { - if(GetLifeTime()> f->GetLifeTime() && e->GetLifeTime() < f->GetLifeTime()) - draw=true; - } - } - } - } - } //if(draw) - */ if(!draw) { if(marker_index < GetLength(lflag.range_markers)) @@ -162,63 +156,6 @@ func RedrawFlagRadius() lflag.range_markers[marker_index] = marker; } - // uter Border - /* - for(var i=0; i<10; i++) - { - SetLength(outers,0); - var f=nil; - draw=true; - var x= Sin(i*36 - time, lflag.radius); - var y=-Cos(i*36 - time, lflag.radius); - if(flags) - for(var f in flags) - { - if(Distance(GetX()+x,GetY()+y,f->GetX(),f->GetY())GetLifeTime() < target->GetLifeTime()) - { - outers[GetLength(outers)] = f; - } - else - draw=false; - } - } - if(outers) - { - var newf=nil; - for(var f in outers) - { - var d=0; - if(f->GetLifeTime()>d) - { - d=f->GetLifeTime(); - newf=f; - } - } - } - if(!newf) continue; - var fl=nil; - fl = FindObjects(Find_ID(FlagPole),Find_Exclude(target), Find_Owner(GetOwner()), Find_Distance(FLAG_DISTANCE ,x,y),Sort_Func("GetLifeTime")); - if(fl[0] && draw && flags) - { - draw=false; - for(var f in flags) - { - for(var e in fl) - { - if(Distance(GetX()+x,GetY()+y,f->GetX(),f->GetY())<(FLAG_DISTANCE)) - { - if(GetLifeTime()> f->GetLifeTime() && e->GetLifeTime() < f->GetLifeTime()) - draw=true; - } - } - } - } - if(!draw) - continue; - CreateParticle("Magic",Sin(i*36 - time, FLAG_DISTANCE+1),-Cos(i*36 - time, FLAG_DISTANCE+1),0,0,10+Random(4),newf.color); - }*/ } func RefreshOwnershipOfSurrounding() @@ -232,25 +169,11 @@ func RefreshOwnershipOfSurrounding() obj->~OnOwnerChange(old); } } - -public func Construction() +public func Initialize() { - if(GetType(LibraryFlag_flag_list) != C4V_Array) - LibraryFlag_flag_list = []; - - if(GetIndexOf(this, LibraryFlag_flag_list) == -1) + if(GetIndexOf(LibraryFlag_flag_list, this) == -1) LibraryFlag_flag_list[GetLength(LibraryFlag_flag_list)] = this; - - lflag = - { - construction_time = FrameCounter(), - radius = LibraryFlag_standard_radius, - range_markers = [], - linked_flags = [], - energy_producers = [], - energy_consumers = [] - }; - + // redraw RedrawAllFlagRadiuses(); @@ -258,8 +181,23 @@ public func Construction() RefreshOwnershipOfSurrounding(); // linked flags - optimization for power system - RefreshLinkedFlags(); + RefreshAllFlagLinks(); +} + +public func Construction() +{ + if(GetType(LibraryFlag_flag_list) != C4V_Array) + LibraryFlag_flag_list = []; + lflag = + { + construction_time = FrameCounter(), + radius = LibraryFlag_standard_radius, + range_markers = [], + linked_flags = [], + power_helper = nil + }; + return _inherited(...); } @@ -326,7 +264,7 @@ func RefreshLinkedFlags() for(var flag in LibraryFlag_flag_list) { if(!IsAllied(flag->GetOwner(), owner)) continue; - if(GetIndexOf(flag, current) != -1) continue; + if(GetIndexOf(current, flag) != -1) continue; if(flag == this) continue; if(ObjectDistance(oldflag, flag) > oldflag->GetFlagRadius() + flag->GetFlagRadius()) continue; @@ -335,10 +273,64 @@ func RefreshLinkedFlags() } } + lflag.linked_flags = current; + + // update flag links for all linked flags - no need for every flag to do that + // meanwhile, adjust power helper. Merge if necessary + // since we don't know whether flag links have been lost we will create a new power helper and possibly remove old ones + Library_Power->Init(); // make sure the power system is set up + var old = lflag.power_helper; + lflag.power_helper = CreateObject(Library_Power, 0, 0, NO_OWNER); + Library_Power_power_compounds[GetLength(Library_Power_power_compounds)] = lflag.power_helper; + + // list of helpers yet to merge + var to_merge = [old]; + + // copy from me + lflag.linked_flags = current; for(var other in lflag.linked_flags) { other->CopyLinkedFlags(this, lflag.linked_flags); + + if(GetIndexOf(to_merge, other.lflag.power_helper) == -1) + to_merge[GetLength(to_merge)] = other.lflag.power_helper; + other.lflag.power_helper = lflag.power_helper; + } + + // for every object in to_merge check if it actually (still) belongs to the group + for(var h in to_merge) + { + if(h == nil) + continue; + RefreshPowerHelper(h); + } +} + +func RefreshPowerHelper(h) +{ + // merge both power_links and sleeping_links + for(var o in h.power_links) + { + if(o == nil) continue; // possible + + var actual = Library_Power->GetPowerHelperForObject(o.obj); + if(actual == h) continue; // right one already + // remove from old and add to new + h->RemovePowerLink(o.obj, true); + actual->AddPowerLink(o.obj, o.amount, true); + } + + for(var i = GetLength(h.sleeping_links); --i >= 0;) + { + var o = h.sleeping_links[i]; + var actual = Library_Power->GetPowerHelperForObject(o.obj); + if(actual == h) continue; // right one already + // remove from old one and add to new + actual.sleeping_links[GetLength(actual.sleeping_links)] = o; + + h.sleeping_links[i] = h.sleeping_links[GetLength(h.sleeping_links) - 1]; + SetLength(h.sleeping_links, GetLength(h.sleeping_links) - 1); } } @@ -351,6 +343,10 @@ public func CopyLinkedFlags(object from, array flaglist) StopRefreshLinkedFlags(); } +public func GetPowerHelper(){return lflag.power_helper;} +public func SetPowerHelper(object to){lflag.power_helper = to;} + +public func GetLinkedFlags(){return lflag.linked_flags;} private func ClearFlagMarkers() { diff --git a/planet/Objects.ocd/Libraries.ocd/Ownable.ocd/Script.c b/planet/Objects.ocd/Libraries.ocd/Ownable.ocd/Script.c index 48d5c6d44..83b32f6b9 100644 --- a/planet/Objects.ocd/Libraries.ocd/Ownable.ocd/Script.c +++ b/planet/Objects.ocd/Libraries.ocd/Ownable.ocd/Script.c @@ -12,4 +12,10 @@ public func IsInteractable(object clonk) { if(Hostile(GetOwner(), clonk->GetOwner())) return false; return _inherited(clonk, ...); +} + +func Initialize() +{ + // set right owner + SetOwner(GetOwnerOfPosition(0, 0)); } \ No newline at end of file diff --git a/planet/Objects.ocd/Libraries.ocd/Plant.ocd/Script.c b/planet/Objects.ocd/Libraries.ocd/Plant.ocd/Script.c index 75f110985..dd627e49f 100644 --- a/planet/Objects.ocd/Libraries.ocd/Plant.ocd/Script.c +++ b/planet/Objects.ocd/Libraries.ocd/Plant.ocd/Script.c @@ -36,24 +36,17 @@ public func IsPlant() /** Chance to reproduce plant. Chances are one out of return value. Default is 500. @return the chance, higher = less chance. */ -private func SeedChance() -{ - return 500; -} +private func SeedChance() { return 500; } + /** Distance the seeds may travel. Default is 300. @return the maximum distance. */ -private func SeedAreaSize() -{ - return 300; -} +private func SeedAreaSize() { return 300; } + /** The amount of plants allowed within SeedAreaSize. Default is 8. @return the maximum amount of plants. */ -private func SeedAmount() -{ - return 8; -} +private func SeedAmount() { return 8; } /** Automated positioning via RootSurface, make sure to call this if needed (in case Construction is overloaded) */ diff --git a/planet/Objects.ocd/Libraries.ocd/Power.ocd/DefCore.txt b/planet/Objects.ocd/Libraries.ocd/Power.ocd/DefCore.txt new file mode 100644 index 000000000..cbce74f68 --- /dev/null +++ b/planet/Objects.ocd/Libraries.ocd/Power.ocd/DefCore.txt @@ -0,0 +1,7 @@ +[DefCore] +id=Library_Power +Version=4,10,0,0 +Category=C4D_StaticBack +Width=1 +Height=1 +Offset=-1,-1 \ No newline at end of file diff --git a/planet/Objects.ocd/Libraries.ocd/Power.ocd/Graphics.png b/planet/Objects.ocd/Libraries.ocd/Power.ocd/Graphics.png new file mode 100644 index 000000000..9bb8607e9 Binary files /dev/null and b/planet/Objects.ocd/Libraries.ocd/Power.ocd/Graphics.png differ diff --git a/planet/Objects.ocd/Libraries.ocd/Power.ocd/Script.c b/planet/Objects.ocd/Libraries.ocd/Power.ocd/Script.c new file mode 100644 index 000000000..9330c352e --- /dev/null +++ b/planet/Objects.ocd/Libraries.ocd/Power.ocd/Script.c @@ -0,0 +1,415 @@ +/** + Power + Cares about power management of a base. + + callbacks: + QueryWaivePowerRequest() + OnNotEnoughPower() + OnEnoughPower() + OnRemovedFromPowerSleepingQueue(): called when the object was removed from the sleeping queue + + globals: + MakePowerConsumer(int amount) + MakePowerProducer(int amount) + IsPowerAvailable(int amount) + +*/ + +local Name = "$Name$"; +local Description = "$Description$"; + +static Library_Power_power_compounds; + +// for the helper definitions +local power_links; // producers and consumers +local sleeping_links; +local power_balance; // performance +local neutral; // is "the" neutral helper? + +func Initialize() +{ + power_links = []; + sleeping_links = []; + power_balance = 0; + neutral = false; +} + + +func AddPowerProducer(object p, int a) +{ + return AddPowerLink(p, a); +} + +func AddPowerConsumer(object p, int a) +{ + + // possibly sleeping? + { + for(var i = GetLength(sleeping_links); --i >= 0;) + { + var o = sleeping_links[i]; + if(o.obj != p) continue; + + // did not affect power balance, we can just remove/change the link + if(a == 0) // remove + { + sleeping_links[i] = sleeping_links[GetLength(sleeping_links) - 1]; + SetLength(sleeping_links, GetLength(sleeping_links) - 1); + + // message + var diff = 0; + { + var t = CreateObject(FloatingMessage, o.obj->GetX() - GetX(), o.obj->GetY() - GetY(), NO_OWNER); + t->SetMessage(Format("%d{{Library_PowerConsumer}}", diff)); + t->SetColor(255, 0, 0); + t->SetYDir(-10); + t->FadeOut(4, 8); + } + + o.obj->~OnRemovedFromPowerSleepingQueue(); + return true; + } + sleeping_links[i].amount = a; + return true; + } + } + + // not asleep + return AddPowerLink(p, -a); +} + +func RemovePowerLink(object p) +{ + return AddPowerLink(p, 0); +} + +func AddPowerLink(object p, int a, bool surpress_balance_check) +{ + var n = {obj = p, amount = a}; + + var before = 0; + var found = false; + var first_empty = -1; + var diff = 0; + for(var i = GetLength(power_links); --i >= 0;) + { + var o = power_links[i]; + if(o == nil) // possible + { + first_empty = i; + continue; + } + + if(o.obj == nil) // removed from outside + { + power_links[i] = nil; + continue; + } + + if(o.obj != p) continue; + found = true; + + diff = a - o.amount; + power_balance += diff; + + if(a == 0) + { + before = power_links[i].amount; + power_links[i] = nil; + } + else power_links[i] = n; + break; + } + + if(!found) + { + // place to insert? + if(a != 0) + { + if(first_empty != -1) + power_links[first_empty] = n; + else + power_links[GetLength(power_links)] = n; + } + diff = n.amount; + power_balance += diff; + } + + diff = n.amount; + if((diff > 0) || ((a == 0) && (before > 0))) + { + var t = CreateObject(FloatingMessage, n.obj->GetX() - GetX(), n.obj->GetY() - GetY(), NO_OWNER); + t->SetMessage(Format("+%d{{Library_PowerConsumer}}", diff)); + t->SetColor(0, 255, 0); + t->SetYDir(-10); + t->FadeOut(4, 8); + } + else if((diff < 0) || ((a == 0) && (before < 0))) + { + var t = CreateObject(FloatingMessage, n.obj->GetX() - GetX(), n.obj->GetY() - GetY(), NO_OWNER); + t->SetMessage(Format("%d{{Library_PowerConsumer}}", diff)); + t->SetColor(255, 0, 0); + t->SetYDir(-10); + t->FadeOut(4, 8); + } + if(n.amount < 0) + n.obj->~OnEnoughPower(); // might be reverted soon, though + + if(!surpress_balance_check) + CheckPowerBalance(); + return true; +} + +func CheckPowerBalance() +{ + // special handling for ownerless links + // always sleep + if(neutral) + { + for(var i = GetLength(power_links); --i >= 0;) + { + var o = power_links[i]; + if(o == nil) continue; + if(o.amount > 0) continue; // producer + SleepLink(i); + } + return false; + } + + //Message("@Power: %d", power_balance); + + if(power_balance >= 0) // alrighty + { + // we are good to go + // we could revive sleeping links at this point + + if(GetLength(sleeping_links)) + { + for(var i = GetLength(sleeping_links); --i >= 0;) + { + var o = sleeping_links[i]; + if(o.obj == nil) + { + sleeping_links[i] = sleeping_links[GetLength(sleeping_links) - 1]; + SetLength(sleeping_links, GetLength(sleeping_links) - 1); + continue; + } + if(power_balance + o.amount < 0) continue; + + // found link to revive! + UnsleepLink(i); + + // can not continue since UnsleepLink changes the array + return true; + } + } + + return true; + } + + // something happened + // something evil + + // look for consumer to kick out of system + // best-fit strategy (or volunteers) + + var best_fit = 0xFFFFFF; + var best_volunteer = 0; + var best = -1; + var abs_diff = Abs(power_balance); + for(var i = GetLength(power_links); --i >= 0;) + { + var o = power_links[i]; + if(o == nil) continue; + if(o.amount > 0) continue; // producer + + var d = Abs(((-o.amount) - abs_diff)); + + var v = o.obj->~QueryWaivePowerRequest(); + + if(!best_volunteer) // no volunteers yet + { + if((d < best_fit) || (best == nil) || (v > 0)) + { + best_fit = d; + best = i; + + if(v) + best_volunteer = v; + } + } + else // we already have volunteers + { + if(v < best_volunteer) continue; + best_volunteer = v; + best = i; + } + } + + // total blackout? No consumer active anymore? + if(best == -1) + { + return false; + } + + // has object + SleepLink(best); + + // recurse + // might revive weaker consumer or sleep another one + CheckPowerBalance(); + + return false; +} + +func SleepLink(int index) +{ + if(index < 0 || index >= GetLength(power_links)) + return FatalError("SleepLink() called without valid index!"); + + // only consumers, sleeping producers does not make sense... + var o = power_links[index]; + if(o.amount > 0) return FatalError("SleepLink() trying to sleep producer!"); + + // delete from list + power_links[index] = nil; + power_balance -= o.amount; + sleeping_links[GetLength(sleeping_links)] = o; + + // sadly not enough power anymore + o.obj->~OnNotEnoughPower(); + + return true; +} + +func UnsleepLink(int index) +{ + if(index < 0 || index >= GetLength(sleeping_links)) + return FatalError("UnsleepLink() called without valid index!"); + + var o = sleeping_links[index]; + + // delete + sleeping_links[index] = sleeping_links[GetLength(sleeping_links) - 1]; + SetLength(sleeping_links, GetLength(sleeping_links) - 1); + + return AddPowerLink(o.obj, o.amount); // revives the link +} + +// get requested power of nodes that are currently sleeping +public func GetPendingPowerAmount() +{ + var sum = 0; + for(var i = GetLength(sleeping_links); --i >= 0;) + { + sum += -sleeping_links[i].amount; + } + return sum; +} + +// should always be above zero - otherwise an object would have been deactivated +public func GetPowerBalance() +{ + return power_balance; +} + +public func IsPowerAvailable(object obj, int amount) +{ + // ignore object for now + return power_balance > amount; +} + +public func Init() +{ + if(GetType(Library_Power_power_compounds) != C4V_Array) + Library_Power_power_compounds = []; +} + +// static +func GetPowerHelperForObject(object who) +{ + var w; + while(w = who->~GetActualPowerConsumer()) + { + if(w == who) break; // nope + who = w; + } + var flag = GetFlagpoleForPosition(who->GetX() - GetX(), who->GetY() - GetY()); + + var helper = nil; + if(!flag) // neutral - needs neutral helper + { + for(var obj in Library_Power_power_compounds) + { + if(!obj.neutral) continue; + helper = obj; + break; + } + + if(helper == nil) // not yet created? + { + helper = CreateObject(Library_Power, 0, 0, NO_OWNER); + helper.neutral = true; + Library_Power_power_compounds[GetLength(Library_Power_power_compounds)] = helper; + } + + } + else + { + helper=flag->GetPowerHelper(); + + if(helper == nil) + { + helper = CreateObject(Library_Power, 0, 0, NO_OWNER); + Library_Power_power_compounds[GetLength(Library_Power_power_compounds)] = helper; + + // add to all linked flags + flag->SetPowerHelper(helper); + for(var f in flag->GetLinkedFlags()) + { + if(f->GetPowerHelper() != nil) // assert + FatalError("Flags in compound have different power helper!"); + f->SetPowerHelper(helper); + } + } + } + + return helper; +} + +global func GetPendingPowerAmount() +{ + if(!this) return 0; + Library_Power->Init(); + return (Library_Power->GetPowerHelperForObject(this))->GetPendingPowerAmount(); +} + +global func GetCurrentPowerBalance() +{ + if(!this) return 0; + Library_Power->Init(); + return (Library_Power->GetPowerHelperForObject(this))->GetPowerBalance(); +} + +global func MakePowerProducer(int amount) +{ + if(!this) return false; + Library_Power->Init(); + return (Library_Power->GetPowerHelperForObject(this))->AddPowerProducer(this, amount); +} + +global func IsPowerAvailable(int amount) +{ + if(!this) return false; + Library_Power->Init(); + return (Library_Power->GetPowerHelperForObject(this))->IsPowerAvailable(this, amount); +} + +global func MakePowerConsumer(int amount) +{ + if(!this) return false; + Library_Power->Init(); + return (Library_Power->GetPowerHelperForObject(this))->AddPowerConsumer(this, amount); +} + +// helper object \ No newline at end of file diff --git a/planet/Objects.ocd/Libraries.ocd/Power.ocd/StringTblDE.txt b/planet/Objects.ocd/Libraries.ocd/Power.ocd/StringTblDE.txt new file mode 100644 index 000000000..7210f2d27 --- /dev/null +++ b/planet/Objects.ocd/Libraries.ocd/Power.ocd/StringTblDE.txt @@ -0,0 +1,2 @@ +Name=Energy +Description=Kümmert sich um das Energiemanagement. \ No newline at end of file diff --git a/planet/Objects.ocd/Libraries.ocd/Power.ocd/StringTblUS.txt b/planet/Objects.ocd/Libraries.ocd/Power.ocd/StringTblUS.txt new file mode 100644 index 000000000..468234fbd --- /dev/null +++ b/planet/Objects.ocd/Libraries.ocd/Power.ocd/StringTblUS.txt @@ -0,0 +1,2 @@ +Name=Power +Description=Cares about power management of a base. \ No newline at end of file diff --git a/planet/Objects.ocd/Libraries.ocd/PowerConsumer.ocd/Script.c b/planet/Objects.ocd/Libraries.ocd/PowerConsumer.ocd/Script.c index c72bee0e2..7278e7407 100644 --- a/planet/Objects.ocd/Libraries.ocd/PowerConsumer.ocd/Script.c +++ b/planet/Objects.ocd/Libraries.ocd/PowerConsumer.ocd/Script.c @@ -1,114 +1,64 @@ /** Power consumer - Should be included by all power consumers. The consumer can check and consume power by calling - the function CheckPower(int power_check, bool no_substract), see below for an explanation. + Cares about showing the "No Power"-symbol + and provides CurrentlyHasPower() + The rest is handled by Library_Power +*/ + +local PowerConsumer_has_power = 0; + + +public func CurrentlyHasPower() +{ + return PowerConsumer_has_power; +} + +// interface to power handling: + +// is the object just a part of a building? +// elevator <-> case for example +public func GetActualPowerConsumer() +{ + return nil; +} + +// how much would you like to withdraw your power request? +// normal objects: not so much, battery: very much! +public func QueryWaivePowerRequest() +{ + return 0; +} + +// the object requested power but there is no power! +// should possibly not use MakePowerConsumer/Producer in this callback +public func OnNotEnoughPower() +{ + PowerConsumer_has_power = false; - @author Maikel -*/ - - -/** Determines whether the object is a power consumer. - @return \c true if the object is a power consumer and \c false otherwise. -*/ -public func IsPowerConsumer() -{ - return true; + // show symbol + this->AddStatusSymbol(Library_PowerConsumer); } -/** Determines whether a power line can be connected. - @return \c true if a power line can be connected to this object, \c false otherwise. -*/ -public func CanPowerConnect() // Other name? +// called when the object was deleted from the sleeping queue +// that means, the object had requested power before +public func OnRemovedFromPowerSleepingQueue() { - return GetCon() >= 100; + // remove symbol + this->RemoveStatusSymbol(Library_PowerConsumer); } -/*-- Power consumption --*/ - -/** Inspects the network connected to the calling consumer for power. - @param power_check amount of power to extract from the network. - @param no_substract determines whether the check should substract power_check. - @return \c true if the amount of power was available in the network, \c false otherwise. -*/ -public func CheckPower(int power_check, bool no_substract) +// called when consumer was sleeping but power is available again +// should possibly not use MakePowerConsumer/Producer in this callback +public func OnEnoughPower() { - // Power consumer only need energy if the rule is active. - if (!FindObject(Find_ID(Rule_EnergyNeed))) - return true; - // Check all power generators connected to this consumer and sort them according to priority. - // TODO: Maybe substract partial amounts from high priority generators. - for (var generator in FindObjects(Find_PowerGenerator(), Sort_GeneratorPriority())) - { - var power = generator->GetPower(); - if (power > power_check) - { - if (!no_substract) - generator->DoPower(-power_check); - RemoveEffect("EnergyNeed", this); - return true; - } - } - if (!GetEffect("EnergyNeed", this)) AddEffect("EnergyNeed", this, 100, 12, this); - return false; + PowerConsumer_has_power = true; + + // remove symbol + this->RemoveStatusSymbol(Library_PowerConsumer); } -// Finds all power generators connected to consumer (can be nil in local calls). -private func Find_PowerGenerator(object consumer) +func Destruction() { - if (!consumer) - consumer = this; - return [C4FO_Func, "IsPowerGeneratorFor", consumer]; -} - -// Sorts power generators according to GetGeneratorPriority(), highest return value -> first in array. -private func Sort_GeneratorPriority() -{ - return [C4SO_Reverse, [C4SO_Func, "GetGeneratorPriority"]]; -} - -/*-- Effect to show energy need --*/ - -private func FxEnergyNeedStart(object target, effect, int temp) -{ - // Start showing energy need symbol. - target->SetGraphics(nil, Library_PowerConsumer, GFX_Overlay, GFXOV_MODE_Base); - target->SetObjDrawTransform(1000, 0, 0, 0, 1000, -500 * GetID()->GetDefCoreVal("Height", "DefCore"), GFX_Overlay); - effect.show_symbol = true; // Effect is showing symbol. - return 1; -} - -private func FxEnergyNeedTimer(object target, effect, int time) -{ - // Alternate showing of the symbol: timer interval of AddEffect determines alternation time. - if (effect.show_symbol) // Effect was showing symbol. - { - // Do not show symbol. - target->SetGraphics(nil, nil, GFX_Overlay, GFXOV_MODE_Base); - effect.show_symbol = false; - } - else // Effect was not showing symbol. - { - // Do show symbol. - target->SetGraphics(nil, Library_PowerConsumer, GFX_Overlay, GFXOV_MODE_Base); - target->SetObjDrawTransform(1000, 0, 0, 0, 1000, -500 * GetID()->GetDefCoreVal("Height", "DefCore"), GFX_Overlay); - effect.show_symbol = true; - } - return 1; -} - -private func FxEnergyNeedStop(object target, effect, int iReason, bool temp) -{ - // Stop showing energy need symbol. - target->SetGraphics(nil, nil, GFX_Overlay, GFXOV_MODE_Base); - return 1; -} - -private func FxEnergyNeedEffect(string name, object target) -{ - // Only one energy need effect per consumer. - if (name == "EnergyNeed") - return -1; - return 1; -} - - + MakePowerProducer(0); + return _inherited(...); +} \ No newline at end of file diff --git a/planet/Objects.ocd/Libraries.ocd/PowerGenerator.ocd/Graphics.png b/planet/Objects.ocd/Libraries.ocd/PowerGenerator.ocd/Graphics.png deleted file mode 100644 index 753695654..000000000 Binary files a/planet/Objects.ocd/Libraries.ocd/PowerGenerator.ocd/Graphics.png and /dev/null differ diff --git a/planet/Objects.ocd/Libraries.ocd/PowerGenerator.ocd/Script.c b/planet/Objects.ocd/Libraries.ocd/PowerGenerator.ocd/Script.c deleted file mode 100644 index da17b5632..000000000 --- a/planet/Objects.ocd/Libraries.ocd/PowerGenerator.ocd/Script.c +++ /dev/null @@ -1,133 +0,0 @@ -/** - Power generator - Should be included by all power generators. - Explanation of the interface see public funcs below. - - @author Maikel -*/ - - -// Local variable to keep track of the power level inside the generator. -local power; - -/** Determines whether the object is a power generator. - @return \c true if the object is a power generator and \c false otherwise. -*/ -public func IsPowerGenerator() -{ - return true; -} - -/** Determines whether a power line can be connected. - @return \c true if a power line can be connected to this object, \c false otherwise. -*/ -public func CanPowerConnect() // Other name? -{ - return GetCon() >= 100; -} - -/** Determines the power capacity of the generator, i.e. the maximum amount of power it can store. Should be overloaded by the generator. - @return the power capacity. -*/ -public func GetCapacity() -{ - return 0; -} - -/** Determines the generator's priority, consumers preferably drain from generators with the higher priorities. Should be overloaded by the generator. - @return the generator's priority. -*/ -public func GetGeneratorPriority() -{ - return 1; -} - -/*-- Power network --*/ -// Functions to check the power network. - -/** Determines whether the calling object is a power generator for the specified consumer. - @param consumer object for which to check if the generator is connected to it. - @return \c true if the calling generator is connected to the consumer, \c false otherwise. -*/ -public func IsPowerGeneratorFor(object consumer, object next, object old_line, array pwr_list) -{ - if (!next) // Initial call to this function. - { - next = consumer; - pwr_list = []; - } - for (var line in FindObjects(Find_PowerLine(next))) // Check all lines connected to next. - { - if (line == old_line) // Recursive -> Not backwards<->forwards through lines. - continue; - //if (!line->IsConnectedWith(next)) // Power line connected with consumer. - // continue; - var end = line -> GetConnectedObject(next); // What is on the line's other end. - if (!end) // Nothing on the other end. - continue; - if (end == consumer) // End of a recursive loop. - continue; - if (GetIndexOf(end, pwr_list) != -1) // We already know this. - continue; - if (end == this) // Found this object, i.e. the generator. - return true; - pwr_list[GetLength(pwr_list)] = end; - if (IsPowerGeneratorFor(consumer, end, line, pwr_list)) // This building is not found, continue with next end as next building. - return true; - } - return false; -} - -// Finds all power lines connected to line (can be nil in local calls). -private func Find_PowerLine(object line) -{ - if (!line) - line = this; - return [C4FO_Func, "IsConnectedTo", line]; -} - -/*-- Power generation --*/ -// Functions that manipulate the power level. - -/** Determines the power level. - @return the current power level of this object. -*/ -public func GetPower() -{ - return power; -} - -/** Sets the current power level of the calling object. - @param to_power the new power level. - @return nil. -*/ -public func SetPower(int to_power) -{ - power = BoundBy(to_power, 0, GetCapacity()); - return; -} - - -/** Changes the current power level of the calling object. - @param do_power the amount of power to be added. - @return nil. -*/ -public func DoPower(int do_power) -{ - power = BoundBy(power + do_power, 0, GetCapacity()); - return; -} - -/*-- Debug --*/ - -protected func Initialize() -{ - //AddEffect("ShowPower", this, 100, 10, this); - return _inherited(...); -} - -private func FxShowPowerTimer(object target, int num, int time) -{ - Message("Power:%d", target->GetPower()); - return true; -} diff --git a/planet/Objects.ocd/Libraries.ocd/PowerGenerator.ocd/DefCore.txt b/planet/Objects.ocd/Libraries.ocd/PowerProducer.ocd/DefCore.txt similarity index 65% rename from planet/Objects.ocd/Libraries.ocd/PowerGenerator.ocd/DefCore.txt rename to planet/Objects.ocd/Libraries.ocd/PowerProducer.ocd/DefCore.txt index 2eb0de5af..99fe1f2ef 100644 --- a/planet/Objects.ocd/Libraries.ocd/PowerGenerator.ocd/DefCore.txt +++ b/planet/Objects.ocd/Libraries.ocd/PowerProducer.ocd/DefCore.txt @@ -1,4 +1,4 @@ [DefCore] -id=Library_PowerGenerator +id=Library_PowerProducer Version=5,2,0,1 Category=C4D_StaticBack diff --git a/planet/Objects.ocd/Libraries.ocd/PowerProducer.ocd/Graphics.png b/planet/Objects.ocd/Libraries.ocd/PowerProducer.ocd/Graphics.png new file mode 100644 index 000000000..a28d190b8 Binary files /dev/null and b/planet/Objects.ocd/Libraries.ocd/PowerProducer.ocd/Graphics.png differ diff --git a/planet/Objects.ocd/Libraries.ocd/PowerProducer.ocd/Script.c b/planet/Objects.ocd/Libraries.ocd/PowerProducer.ocd/Script.c new file mode 100644 index 000000000..1a2f852f0 --- /dev/null +++ b/planet/Objects.ocd/Libraries.ocd/PowerProducer.ocd/Script.c @@ -0,0 +1,10 @@ +/** + Power producer + Should be included by all power generators. +*/ + +func Destruction() +{ + MakePowerProducer(0); + return _inherited(...); +} diff --git a/planet/Objects.ocd/Libraries.ocd/Producer.ocd/Icons.ocd/Acid.ocd/DefCore.txt b/planet/Objects.ocd/Libraries.ocd/Producer.ocd/Icons.ocd/Acid.ocd/DefCore.txt index d67d1629b..29e6387cf 100644 --- a/planet/Objects.ocd/Libraries.ocd/Producer.ocd/Icons.ocd/Acid.ocd/DefCore.txt +++ b/planet/Objects.ocd/Libraries.ocd/Producer.ocd/Icons.ocd/Acid.ocd/DefCore.txt @@ -2,7 +2,7 @@ id=Icon_Producer_Acid Version=5,2,0,1 Category=C4D_StaticBack -Picture=0,0,64,64 +Picture=0,0,128,128 Width=64 Height=64 Offset=-32,-32 diff --git a/planet/Objects.ocd/Libraries.ocd/Producer.ocd/Icons.ocd/Fuel.ocd/DefCore.txt b/planet/Objects.ocd/Libraries.ocd/Producer.ocd/Icons.ocd/Fuel.ocd/DefCore.txt index 32279c9c5..baf8e7e1b 100644 --- a/planet/Objects.ocd/Libraries.ocd/Producer.ocd/Icons.ocd/Fuel.ocd/DefCore.txt +++ b/planet/Objects.ocd/Libraries.ocd/Producer.ocd/Icons.ocd/Fuel.ocd/DefCore.txt @@ -2,7 +2,7 @@ id=Icon_Producer_Fuel Version=5,2,0,1 Category=C4D_StaticBack -Picture=0,0,64,64 +Picture=0,0,128,128 Width=64 Height=64 Offset=-32,-32 diff --git a/planet/Objects.ocd/Libraries.ocd/Producer.ocd/Icons.ocd/Lava.ocd/DefCore.txt b/planet/Objects.ocd/Libraries.ocd/Producer.ocd/Icons.ocd/Lava.ocd/DefCore.txt index 68aabfa5a..6a332e978 100644 --- a/planet/Objects.ocd/Libraries.ocd/Producer.ocd/Icons.ocd/Lava.ocd/DefCore.txt +++ b/planet/Objects.ocd/Libraries.ocd/Producer.ocd/Icons.ocd/Lava.ocd/DefCore.txt @@ -2,7 +2,7 @@ id=Icon_Producer_Lava Version=5,2,0,1 Category=C4D_StaticBack -Picture=0,0,64,64 +Picture=0,0,128,128 Width=64 Height=64 Offset=-32,-32 diff --git a/planet/Objects.ocd/Libraries.ocd/Producer.ocd/Icons.ocd/Oil.ocd/DefCore.txt b/planet/Objects.ocd/Libraries.ocd/Producer.ocd/Icons.ocd/Oil.ocd/DefCore.txt index 3b2af3cb8..566d23818 100644 --- a/planet/Objects.ocd/Libraries.ocd/Producer.ocd/Icons.ocd/Oil.ocd/DefCore.txt +++ b/planet/Objects.ocd/Libraries.ocd/Producer.ocd/Icons.ocd/Oil.ocd/DefCore.txt @@ -2,7 +2,7 @@ id=Icon_Producer_Oil Version=5,2,0,1 Category=C4D_StaticBack -Picture=0,0,64,64 +Picture=0,0,128,128 Width=64 Height=64 Offset=-32,-32 diff --git a/planet/Objects.ocd/Libraries.ocd/Producer.ocd/Icons.ocd/Water.ocd/DefCore.txt b/planet/Objects.ocd/Libraries.ocd/Producer.ocd/Icons.ocd/Water.ocd/DefCore.txt index 2dedbb617..33389158b 100644 --- a/planet/Objects.ocd/Libraries.ocd/Producer.ocd/Icons.ocd/Water.ocd/DefCore.txt +++ b/planet/Objects.ocd/Libraries.ocd/Producer.ocd/Icons.ocd/Water.ocd/DefCore.txt @@ -2,7 +2,7 @@ id=Icon_Producer_Water Version=5,2,0,1 Category=C4D_StaticBack -Picture=0,0,64,64 +Picture=0,0,128,128 Width=64 Height=64 Offset=-32,-32 diff --git a/planet/Objects.ocd/Libraries.ocd/Producer.ocd/ProductionMenu.ocd/Script.c b/planet/Objects.ocd/Libraries.ocd/Producer.ocd/ProductionMenu.ocd/Script.c index 8c7ac9140..62f494f97 100644 --- a/planet/Objects.ocd/Libraries.ocd/Producer.ocd/ProductionMenu.ocd/Script.c +++ b/planet/Objects.ocd/Libraries.ocd/Producer.ocd/ProductionMenu.ocd/Script.c @@ -115,8 +115,6 @@ public func HideProductInfo() /* Menu properties */ public func IsProductionMenu() { return true; } -// UpdateCursor is called -public func CursorUpdatesEnabled() { return true; } public func AddQueueItem(object item) { @@ -217,21 +215,6 @@ public func HasCommander(object producer) return false; } -// Callback if the mouse is moved -public func UpdateCursor(int dx, int dy) -{ - var item = FindObject(Find_AtPoint(dx, dy), Find_ID(GUI_MenuItem)); - if (!item || item->GetMenu() != this) - { - if (productinfo_shown) - HideProductInfo(); - return; - } - if (item == productinfo_shown) - return; - ShowProductInfo(item); -} - /* Callbacks from the menu items, to be translated into commands for the producer. */ // Called when a click outside the menu has been made. @@ -309,3 +292,19 @@ public func OnItemDragDone(object drag_item, object on_item) return _inherited(drag_item, on_item, ...); } +// Called if the mouse cursor enters hovering over an item. +public func OnMouseOverItem(object over_item, object dragged_item) +{ + ShowProductInfo(over_item); + + return _inherited(over_item, dragged_item, ...); +} + +// Called if the mouse cursor exits hovering over an item. +public func OnMouseOutItem(object out_item, object dragged_item) +{ + HideProductInfo(); + + return _inherited(out_item, dragged_item, ...); +} + diff --git a/planet/Objects.ocd/Libraries.ocd/Producer.ocd/Script.c b/planet/Objects.ocd/Libraries.ocd/Producer.ocd/Script.c index de8218981..8bd5bb3a6 100644 --- a/planet/Objects.ocd/Libraries.ocd/Producer.ocd/Script.c +++ b/planet/Objects.ocd/Libraries.ocd/Producer.ocd/Script.c @@ -336,7 +336,8 @@ protected func FxProcessQueueTimer(object target, proplist effect) private func ProductionTime(id product) { return product->~GetProductionTime(); } private func FuelNeed(id product) { return product->~GetFuelNeed(); } private func LiquidNeed(id product) { return product->~GetLiquidNeed(); } -private func PowerNeed(id product) { return product->~GetPowerNeed(); } + +private func PowerNeed() { return 200; } private func Produce(id product) { @@ -354,7 +355,7 @@ private func Produce(id product) if (!CheckLiquids(product)) return false; // Check need for power. - if (!CheckForPower(product)) + if (!CheckForPower()) return false; // Everything available? Start production. @@ -443,15 +444,9 @@ private func CheckLiquids(id product, bool remove) return true; } -private func CheckForPower(id product) +private func CheckForPower() { - if (PowerNeed() > 0) - { - // At least ten percent of the power need must be in the network. - if (!CheckPower(PowerNeed() / 10, true)) - return false; - } - return true; + return true; // always assume that power is available } private func IsProducing() @@ -463,7 +458,7 @@ private func IsProducing() protected func FxProcessProductionStart(object target, proplist effect, int temporary, id product) { - if (temporary != 0) + if (temporary) return 1; // Set product. @@ -472,47 +467,49 @@ protected func FxProcessProductionStart(object target, proplist effect, int temp // Set production duration to zero. effect.Duration = 0; - // Set energy usage to zero. - effect.Energy = 0; - // Production is active. effect.Active = true; - - //Log("Production started on %i", effect.Product); - + // Callback to the producer. this->~OnProductionStart(effect.Product); + // consume power + if(PowerNeed() > 0) + MakePowerConsumer(PowerNeed()); + return 1; } +public func OnNotEnoughPower() +{ + var effect = GetEffect("ProcessProduction", this); + if(effect) + { + effect.Active = false; + this->~OnProductionHold(effect.Product, effect.Duration); + } + else + FatalError("Producer effect removed when power still active!"); + return _inherited(...); +} + +public func OnEnoughPower() +{ + var effect = GetEffect("ProcessProduction", this); + if(effect) + { + effect.Active = true; + this->~OnProductionContinued(effect.Product, effect.Duration); + } + else + FatalError("Producer effect removed when power still active!"); + return _inherited(...); +} + protected func FxProcessProductionTimer(object target, proplist effect, int time) { - // Check if energy is available. - if (PowerNeed() > 0) - { - var eng = PowerNeed() * (effect.Duration + effect.Interval) / ProductionTime(); - if (CheckPower(eng - effect.Energy)) - { - // Energy available, add to Energy value and continue production. - effect.Energy = eng; - if (!effect.Active) - { - this->~OnProductionContinued(effect.Product, effect.Duration); - effect.Active = true; - } - } - else - { - // Hold production if energy is not available, callback to the producer. - if (effect.Active) - { - this->~OnProductionHold(effect.Product, effect.Duration); - effect.Active = false; - } - return 1; - } - } + if (!effect.Active) + return 1; // Add effect interval to production duration. effect.Duration += effect.Interval; @@ -526,10 +523,16 @@ protected func FxProcessProductionTimer(object target, proplist effect, int time return 1; } -protected func FxProcessProductionStop(object target, proplist effect, int reason) +protected func FxProcessProductionStop(object target, proplist effect, int reason, bool temp) { + if(temp) return; + + // no need to consume power anymore + MakePowerConsumer(0); + if (reason != 0) return 1; + // Callback to the producer. //Log("Production finished on %i after %d frames", effect.Product, effect.Duration); this->~OnProductionFinish(effect.Product); diff --git a/planet/Objects.ocd/Libraries.ocd/RopePhysics.ocd/Script.c b/planet/Objects.ocd/Libraries.ocd/RopePhysics.ocd/Script.c index 6e0343f3c..7db116f73 100644 --- a/planet/Objects.ocd/Libraries.ocd/RopePhysics.ocd/Script.c +++ b/planet/Objects.ocd/Libraries.ocd/RopePhysics.ocd/Script.c @@ -443,10 +443,9 @@ public func ConstraintLength() { // Satisfy all stick constraints (move the particles to fit the length) var normal_restlength = Rope_SegmentLength*Rope_Precision; - var normal_restlength2 = normal_restlength*normal_restlength; - var restlength, restlength2; - var x1, x2, invmass1, invmass2; - var delta = [0,0], deltaDot, deltalength, diff; + var restlength; + var invmass1, invmass2; + var delta = [0,0], deltaDot, deltalength; // diff for(var i=0; i < ParticleCount-1; i++) { // Keep length @@ -594,9 +593,6 @@ func ForcesOnObjects() if( obj->GetAction() == "Climb") obj->SetAction("Jump"); - var xdist = particles[j][0][0]-obj->GetX(Rope_Precision); - var ydist = particles[j][0][1]-obj->GetY(Rope_Precision); - obj->SetXDir( particles[j][0][0]-particles[j][1][0], Rope_Precision); obj->SetYDir( particles[j][0][1]-particles[j][1][1], Rope_Precision); } diff --git a/planet/Objects.ocd/Rules.ocd/TeamAccount.ocd/Script.c b/planet/Objects.ocd/Rules.ocd/TeamAccount.ocd/Script.c index 036ba051c..f12847df9 100644 --- a/planet/Objects.ocd/Rules.ocd/TeamAccount.ocd/Script.c +++ b/planet/Objects.ocd/Rules.ocd/TeamAccount.ocd/Script.c @@ -58,7 +58,7 @@ protected func OnTeamSwitch(int player, int new_team, int old_team) if (!Hostile(player, GetPlayerByIndex(i))) count++; } - var share = GetWealth(player) / count; + //var share = GetWealth(player) / count; // Add player to new team, i.e. add his wealth. // TODO Implement diff --git a/planet/Objects.ocd/Structures.ocd/Compensator.ocd/BurningBattery.ocd/DefCore.txt b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/BurningBattery.ocd/DefCore.txt new file mode 100644 index 000000000..80f31c3aa --- /dev/null +++ b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/BurningBattery.ocd/DefCore.txt @@ -0,0 +1,19 @@ +[DefCore] +id=Compensator_BurningBattery +Version=4,10,0,0 +Category=C4D_Object +Width=10 +Height=10 +Offset=-5,-5 +Vertices=1 +VertexX=0 +VertexFriction=20 +Value=1 +Mass=20 +Components=Compensatory_BurningBattery=1 +Projectile=1 +Rotate=1 +NoStabilize=1 +Timer=2 +TimerCall=DoSmoke + diff --git a/planet/Objects.ocd/Structures.ocd/Compensator.ocd/BurningBattery.ocd/Graphics.2.png b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/BurningBattery.ocd/Graphics.2.png new file mode 100644 index 000000000..e6cf991fa Binary files /dev/null and b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/BurningBattery.ocd/Graphics.2.png differ diff --git a/planet/Objects.ocd/Structures.ocd/Compensator.ocd/BurningBattery.ocd/Script.c b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/BurningBattery.ocd/Script.c new file mode 100644 index 000000000..bfda4154f --- /dev/null +++ b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/BurningBattery.ocd/Script.c @@ -0,0 +1,25 @@ +/** + BurningBattery + A part of a compensator! +*/ + +local Name = "$Name$"; +local Description = "$Description$"; +local Collectible = 0; +local time; + +func Initialize() +{ + SetRDir(RandomX(-200, 200)); +} + +func Hit() +{ + Explode(20); +} + +func DoSmoke() +{ + ++time; + CreateParticle("ExploSmokeFastFade", RandomX(-5,5), RandomX(-5,5), 0, 0, Max(10, 300 - time * 5), RGB(100, 100, 100)); +} \ No newline at end of file diff --git a/planet/Objects.ocd/Structures.ocd/Compensator.ocd/BurningBattery.ocd/StringTblDE.txt b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/BurningBattery.ocd/StringTblDE.txt new file mode 100644 index 000000000..cce90976d --- /dev/null +++ b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/BurningBattery.ocd/StringTblDE.txt @@ -0,0 +1,2 @@ +Name=Brennende Batterie +Description=Ein Teil eines Kompensators. \ No newline at end of file diff --git a/planet/Objects.ocd/Structures.ocd/Compensator.ocd/BurningBattery.ocd/StringTblUS.txt b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/BurningBattery.ocd/StringTblUS.txt new file mode 100644 index 000000000..28cebf292 --- /dev/null +++ b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/BurningBattery.ocd/StringTblUS.txt @@ -0,0 +1,2 @@ +Name=BurningBattery +Description=A part of a compensator! \ No newline at end of file diff --git a/planet/Objects.ocd/Structures.ocd/Compensator.ocd/ChargeShower.ocd/DefCore.txt b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/ChargeShower.ocd/DefCore.txt new file mode 100644 index 000000000..fb70ea49a --- /dev/null +++ b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/ChargeShower.ocd/DefCore.txt @@ -0,0 +1,12 @@ +[DefCore] +id=Compensator_ChargeShower +Version=4,10,0,0 +Category=C4D_StaticBack +Width=11 +Height=19 +Offset=-5,-10 +BlitMode=1 +Vertices=1 +VertexX=0 +VertexFriction=50 + diff --git a/planet/Objects.ocd/Structures.ocd/Compensator.ocd/ChargeShower.ocd/Graphics.4.png b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/ChargeShower.ocd/Graphics.4.png new file mode 100644 index 000000000..d12820a51 Binary files /dev/null and b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/ChargeShower.ocd/Graphics.4.png differ diff --git a/planet/Objects.ocd/Structures.ocd/Compensator.ocd/ChargeShower.ocd/Script.c b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/ChargeShower.ocd/Script.c new file mode 100644 index 000000000..4acf6e3ec --- /dev/null +++ b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/ChargeShower.ocd/Script.c @@ -0,0 +1,73 @@ +/** + ChargeShower + Shows stuff. +*/ + +local Name = "$Name$"; +local Description = "$Description$"; + +local current, to; + +local ActMap = { + Turn = { + Prototype = Action, + Name = "Turn", + Procedure = DFA_ATTACH, + Length=6, + Delay=4, + X = 0, + Y = 0, + Wdt = 11, + Hgt = 19, + NextAction = "Turn" + } + }; + +func AttachTargetLost() +{ + return RemoveObject(); +} + +func To(int i) +{ + to = i; + if(!GetEffect("Adjust", this)) + AddEffect("Adjust", this, 1, 2, this); +} + +func FxAdjustTimer() +{ + if(current == to) + return -1; + + if(current < to) + ++current; + else --current; + + Set(current); + + return 1; +} + +func Set(int i) +{ + SetObjDrawTransform((800 * i)/100, 0, 0, 0, 900, -150); +} + +func Init(to) +{ + var x = GetX() - to->GetX(); + var y = GetY() - to->GetY(); + SetVertexXY(0, -x, -y); + SetAction("Turn", to); + SetPhase(Random(5)); + this.Layer = to.Layer - 1; +} + +public func Initialize() +{ + to=0; + current=0; + Set(to); + return true; +} \ No newline at end of file diff --git a/planet/Objects.ocd/Structures.ocd/Compensator.ocd/ChargeShower.ocd/StringTblDE.txt b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/ChargeShower.ocd/StringTblDE.txt new file mode 100644 index 000000000..50d827134 --- /dev/null +++ b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/ChargeShower.ocd/StringTblDE.txt @@ -0,0 +1,2 @@ +Name=ChargeShower +Description=Shows stuff. \ No newline at end of file diff --git a/planet/Objects.ocd/Structures.ocd/Compensator.ocd/ChargeShower.ocd/StringTblUS.txt b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/ChargeShower.ocd/StringTblUS.txt new file mode 100644 index 000000000..50d827134 --- /dev/null +++ b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/ChargeShower.ocd/StringTblUS.txt @@ -0,0 +1,2 @@ +Name=ChargeShower +Description=Shows stuff. \ No newline at end of file diff --git a/planet/Objects.ocd/Structures.ocd/Compensator.ocd/Compensator.png b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/Compensator.png new file mode 100644 index 000000000..0db92948e Binary files /dev/null and b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/Compensator.png differ diff --git a/planet/Objects.ocd/Structures.ocd/Compensator.ocd/Compensator.skeleton b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/Compensator.skeleton new file mode 100644 index 000000000..54a906eda Binary files /dev/null and b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/Compensator.skeleton differ diff --git a/planet/Objects.ocd/Structures.ocd/Compensator.ocd/DefCore.txt b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/DefCore.txt new file mode 100644 index 000000000..7bfcc20d4 --- /dev/null +++ b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/DefCore.txt @@ -0,0 +1,20 @@ +[DefCore] +id=Compensator +Version=5,2,0,1 +Category=C4D_Structure +TimerCall=EnergyCheck +Timer=100 +Width=30 +Height=20 +Offset=-15,-10 +Vertices=6 +VertexX=0,-12,12,-15,15,0 +VertexY=0,-4,-4,10,10,10 +VertexFriction=50, 50,50,100,100 +Value=20 +Mass=100 +Components=Coal=1;Metal=1 +Exclusive=1 +BlastIncinerate=1 +ContactIncinerate=1 +Construction=1 diff --git a/planet/Objects.ocd/Structures.ocd/Compensator.ocd/Graphics.mesh b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/Graphics.mesh new file mode 100644 index 000000000..c3a5ffd09 Binary files /dev/null and b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/Graphics.mesh differ diff --git a/planet/Objects.ocd/Structures.ocd/Compensator.ocd/Scene.material b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/Scene.material new file mode 100644 index 000000000..e71e23fdc --- /dev/null +++ b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/Scene.material @@ -0,0 +1,23 @@ +material Compensator +{ + receive_shadows on + technique + { + pass + { + ambient 0.500000 0.500000 0.500000 1.000000 + diffuse 0.640000 0.640000 0.640000 1.000000 + specular 0.000000 0.000000 0.000000 1.000000 12.500000 + emissive 0.000000 0.000000 0.000000 1.000000 + scene_blend alpha_blend + depth_write off + cull_hardware none + texture_unit + { + texture Compensator.png + tex_address_mode wrap + filtering trilinear + } + } + } +} diff --git a/planet/Objects.ocd/Structures.ocd/Compensator.ocd/Script.c b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/Script.c new file mode 100644 index 000000000..cf23af5b4 --- /dev/null +++ b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/Script.c @@ -0,0 +1,188 @@ +/*-- compensator --*/ + +#include Library_Ownable +#include Library_PowerProducer +#include Library_PowerConsumer + +static const Compensator_max_seconds = 15; +static const Compensator_power_usage = 50; + +local power_seconds; + + +local Name = "$Name$"; +local Description = "$Description$"; +local leftcharge, rightcharge, lastcharge; +local anim; + +func Construction() +{ + power_seconds = 0; + lastcharge = 0; + + anim = PlayAnimation("Charge", 1, Anim_Const(GetAnimationLength("Charge")), Anim_Const(1000)); + + return _inherited(...); +} + +func Initialize() +{ + leftcharge = CreateObject(Compensator_ChargeShower, -7, 10, NO_OWNER); + leftcharge->Init(this); + rightcharge = CreateObject(Compensator_ChargeShower, 6, 10, NO_OWNER); + rightcharge->Init(this); + return _inherited(...); +} + +func OnNotEnoughPower() +{ + // not enough power to sustain a battery - turn off + if(GetEffect("ConsumePower", this)) + RemoveEffect("ConsumePower", this); + + ScheduleCall(this, "UnmakePowerConsumer", 1, 0); + return _inherited(...); +} + +func UnmakePowerConsumer(){MakePowerConsumer(0);} + +// devour energy +func OnEnoughPower() +{ + if(!GetEffect("ConsumePower", this)) + AddEffect("ConsumePower", this, 1, 36, this); + return _inherited(...); +} + +func SetCharge(int to) +{ + power_seconds = BoundBy(to, 0, Compensator_max_seconds); + RefreshAnimationPosition(); +} + +func RefreshAnimationPosition() +{ + var charge = (power_seconds * 100) / Compensator_max_seconds; + /*var current = GetAnimationPosition(anim); + var len = GetAnimationLength("Charge"); + SetAnimationPosition(anim, Anim_Linear(current, current, len - (charge * len) / 100, 35, ANIM_Hold));*/ + leftcharge->To(Min(charge, 50)*2); + rightcharge->To(Max(0, charge-50)*2); +} + +func FxConsumePowerTimer(target, effect, time) +{ + ++power_seconds; + RefreshAnimationPosition(); + // fully charged? + if(power_seconds >= Compensator_max_seconds) + { + MakePowerConsumer(0); + return -1; + } + return 1; +} + +func EnergyCheck() +{ + if(GetCon() < 100) return; + + // consuming - everything is alright + if(GetEffect("ConsumePower", this)) + return true; + // producing - nothing to change either + if(GetEffect("ProducePower", this)) + return true; + + // neutral compensators don't do anything + if(GetOwner() == NO_OWNER) return false; + + // are we needed? + if(power_seconds > 0) + { + var s = GetPendingPowerAmount(); + if(s > 0) + { + // turn on, start the machines! + AddEffect("ProducePower", this, 1, 36, this); + return true; + } + } + + // fully charged + if(power_seconds >= Compensator_max_seconds) + return false; + + // can we leech power? + var p = GetCurrentPowerBalance(); + + // we have some play here? + if(p >= Compensator_power_usage) + { + MakePowerConsumer(Compensator_power_usage); + return true; + } + + return false; +} + +func FxProducePowerStart(target, effect, temp) +{ + if(temp) return; + MakePowerProducer(Compensator_power_usage); + + // todo: effects + AddEffect("Sparkle", this, 1, 1, this); +} + +func FxSparkleTimer(target, effect, time) +{ + effect.Interval *= 2; + if(effect.Interval > 35*3) return -1; + + CreateParticle("StarSpark", RandomX(-3,3), RandomX(-14, -10), RandomX(-5,5), RandomX(-8, 0), 30, RGB(200, 200, 255), this); + CreateParticle("StarSpark", RandomX(-3,3), RandomX(-14, -10), RandomX(-5,5), RandomX(-8, 0), 30, RGB(200, 200, 255), this); +} + +func FxProducePowerTimer(target, effect, time) +{ + --power_seconds; + RefreshAnimationPosition(); + if(power_seconds <= 0) + { + return -1; + } + + // stop when not needed + if((GetCurrentPowerBalance() >= Compensator_power_usage) && GetPendingPowerAmount() == 0) + return -1; + + return 1; +} + +func FxProducePowerStop(target, effect, reason, temp) +{ + if(temp) return; + MakePowerProducer(0); + + if(GetEffect("Sparkle", this)) + RemoveEffect("Sparkle", this); +} + +func Incineration() +{ + if(power_seconds == 0) + return Extinguish(); + + + for(var i = 0; i < 2; ++i) + { + var x = -7 + 14 * i; + var b = CreateObject(Compensator_BurningBattery, x, 6, NO_OWNER); + b->SetController(GetController()); // killtracing + + b->SetSpeed(-30 + 60 * i + RandomX(-10, 10), RandomX(-50, -30)); + } + + Explode(30); +} diff --git a/planet/Objects.ocd/Structures.ocd/Compensator.ocd/StringTblDE.txt b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/StringTblDE.txt new file mode 100644 index 000000000..94a54bc54 --- /dev/null +++ b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/StringTblDE.txt @@ -0,0 +1,2 @@ +Name=Kompensator +Description=Kann Energie über kurze Zeit puffern. diff --git a/planet/Objects.ocd/Structures.ocd/Compensator.ocd/StringTblUS.txt b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/StringTblUS.txt new file mode 100644 index 000000000..792454958 --- /dev/null +++ b/planet/Objects.ocd/Structures.ocd/Compensator.ocd/StringTblUS.txt @@ -0,0 +1,2 @@ +Name=Compensator +Description=Is able to puffer a small amount of energy over some time. diff --git a/planet/Objects.ocd/Structures.ocd/Elevator.ocd/Case.ocd/Script.c b/planet/Objects.ocd/Structures.ocd/Elevator.ocd/Case.ocd/Script.c index 642fa3b05..6e9f93c6d 100644 --- a/planet/Objects.ocd/Structures.ocd/Elevator.ocd/Case.ocd/Script.c +++ b/planet/Objects.ocd/Structures.ocd/Elevator.ocd/Case.ocd/Script.c @@ -1,5 +1,7 @@ /*-- Elevator case --*/ +#include Library_PowerConsumer + local elevator; func Connect(object connect_to) @@ -7,6 +9,9 @@ func Connect(object connect_to) elevator = connect_to; SetComDir(COMD_None); SetAction("Drive"); + + // request power + MakePowerConsumer(50); } /* Movement behaviour */ @@ -15,6 +20,40 @@ local move_to, // Y-coordinate to move to on its own move_to_delay, // Delay before moving move_to_target; // Target to move to +// for the position +func GetActualPowerConsumer() +{ + return elevator; +} + +// the lift may not need power when not used +func QueryWaivePowerRequest() +{ + if(!movement && !drill) + return 10; + else return 0; +} + +func OnNotEnoughPower() +{ + // Stop movement if moving + Halt(); + movement = 0; + ClearMoveTo(); + if (drill) + { + SetAction("Drive"); + Sound("ElevatorDrilling", nil, nil, nil, -1); + drill = false; + } + return _inherited(...); +} + +func OnEnoughPower() +{ + return _inherited(...); +} + func Movement() // TimerCall { // No elevator?! @@ -24,22 +63,9 @@ func Movement() // TimerCall if (!ActIdle()) SetAction("Idle"); return; } - // Check for power - if (!elevator->CheckPower(1, true)) - { - // Stop movement if moving - Halt(); - movement = 0; - ClearMoveTo(); - if (drill) - { - SetAction("Drive"); - Sound("ElevatorDrilling", nil, nil, nil, -1); - drill = false; - } - return; - } - + + + // Fetch vehicles for (var vehicle in FindObjects(Find_InRect(-5, -5, 10, 10), Find_Category(C4D_Vehicle), Find_NoContainer(), Find_Func("FitsInElevator"))) { @@ -50,7 +76,11 @@ func Movement() // TimerCall vehicle->SetR(); AddEffect("ElevatorControl", vehicle, 30, 5, nil, nil, this); } - + + // no power? + if(!CurrentlyHasPower()) + return; + // Start or stop drilling if (drill && GetAction() == "Drive") { @@ -86,8 +116,6 @@ func Movement() // TimerCall { if (Abs(GetYDir()) == 1) elevator->StartEngine(); SetYDir(GetYDir() + movement); - // Elevator consumes 1 power per frame - elevator->CheckPower(1); return; } } @@ -122,7 +150,6 @@ func Movement() // TimerCall if (move_to > GetY() && GetYDir() < this.RushSpeed) SetYDir(GetYDir() + 1); if (Abs(GetYDir()) == 1) elevator->StartEngine(); - elevator->CheckPower(1); return; } diff --git a/planet/Objects.ocd/Structures.ocd/Elevator.ocd/Script.c b/planet/Objects.ocd/Structures.ocd/Elevator.ocd/Script.c index 49e85aa9c..ff2164b9a 100644 --- a/planet/Objects.ocd/Structures.ocd/Elevator.ocd/Script.c +++ b/planet/Objects.ocd/Structures.ocd/Elevator.ocd/Script.c @@ -1,6 +1,6 @@ /*-- Elevator --*/ -#include Library_PowerConsumer +#include Library_Ownable local case, rope; diff --git a/planet/Objects.ocd/Structures.ocd/Flagpole.ocd/DefCore.txt b/planet/Objects.ocd/Structures.ocd/Flagpole.ocd/DefCore.txt index db5add571..1ebc2f0a5 100644 --- a/planet/Objects.ocd/Structures.ocd/Flagpole.ocd/DefCore.txt +++ b/planet/Objects.ocd/Structures.ocd/Flagpole.ocd/DefCore.txt @@ -15,3 +15,4 @@ Components=Wood=4;Metal=1 Picture=30,0,80,94 Exclusive=1 Construction=1 +ColorByOwner=1 diff --git a/planet/Objects.ocd/Structures.ocd/Foundry.ocd/Script.c b/planet/Objects.ocd/Structures.ocd/Foundry.ocd/Script.c index 0a5c91050..9397280df 100644 --- a/planet/Objects.ocd/Structures.ocd/Foundry.ocd/Script.c +++ b/planet/Objects.ocd/Structures.ocd/Foundry.ocd/Script.c @@ -5,9 +5,12 @@ Melts iron ore to metal, using some sort of fuel. --*/ - +#include Library_Ownable #include Library_Producer +// does not need power +func PowerNeed() { return 0; } + public func Construction() { diff --git a/planet/Objects.ocd/Structures.ocd/Idol.ocd/Script.c b/planet/Objects.ocd/Structures.ocd/Idol.ocd/Script.c index 91bc421fb..54f4fd760 100644 --- a/planet/Objects.ocd/Structures.ocd/Idol.ocd/Script.c +++ b/planet/Objects.ocd/Structures.ocd/Idol.ocd/Script.c @@ -1,2 +1,5 @@ + +#include Library_Ownable + local Name = "$Name$"; local Touchable = 1; diff --git a/planet/Objects.ocd/Structures.ocd/Pump.ocd/Script.c b/planet/Objects.ocd/Structures.ocd/Pump.ocd/Script.c index 99cff22fc..7ed6997ae 100644 --- a/planet/Objects.ocd/Structures.ocd/Pump.ocd/Script.c +++ b/planet/Objects.ocd/Structures.ocd/Pump.ocd/Script.c @@ -5,6 +5,7 @@ Pumps liquids using drain and source pipes. --*/ +#include Library_Ownable #include Library_PowerConsumer @@ -14,6 +15,7 @@ public func IsLiquidPump() { return true; } protected func Initialize() { SetAction("Wait"); + MakePowerConsumer(100); return; } @@ -28,6 +30,27 @@ public func GetSource() { return source_pipe; } public func SetDrain(object pipe) { drain_pipe = pipe; } public func GetDrain() { return drain_pipe; } +func QueryWaivePowerRequest() +{ + // don't need power if not pumping anyway + if(GetAction() == "Wait") + return 50; + return 0; +} + +func OnNotEnoughPower() +{ + if(GetAction() == "Pump") + SetAction("Wait"); + return _inherited(...); +} + +func OnEnoughPower() +{ + OnWaitStart(); + return _inherited(...); +} + protected func OnPumpStart() { if (!ReadyToPump()) @@ -46,9 +69,6 @@ local aMaterials=["", 0]; //contained liquids protected func Pumping() { - // Only proceed if there is enough power available. - if (!CheckPower(2)) - return SetAction("Wait"); // Pump liquids. if (!source_pipe) return SetAction("Wait"); @@ -77,6 +97,9 @@ protected func Pumping() // Returns whether the pump can pump some liquid. private func ReadyToPump() { + // no power? + if(!CurrentlyHasPower()) + return false; // If there is no source pipe, return false. if (!source_pipe) return false; diff --git a/planet/Objects.ocd/Structures.ocd/Sawmill.ocd/Script.c b/planet/Objects.ocd/Structures.ocd/Sawmill.ocd/Script.c index 795b1750f..645c59632 100644 --- a/planet/Objects.ocd/Structures.ocd/Sawmill.ocd/Script.c +++ b/planet/Objects.ocd/Structures.ocd/Sawmill.ocd/Script.c @@ -5,6 +5,7 @@ Cuts trees or other objects into wood. Accepts only objects purely made from wood. --*/ +#include Library_Ownable #include Library_Producer public func Construction() @@ -22,12 +23,15 @@ public func Initialize() /*-- Interaction --*/ +// Sawmill can't be accessed as a container. +public func IsContainer() { return false; } + // Automatically search for trees in front of sawmill // Temporary solution? protected func FindTrees() { var tree = FindObject(Find_AtPoint(), Find_Func("IsTree"), Find_Not(Find_Func("IsStanding"))); - if (!tree) return; + if (!tree || GetCon() < 100) return; Saw(tree); } @@ -57,7 +61,7 @@ private func IsProduct(id product_id) return product_id->~IsSawmillProduct(); } private func ProductionTime() { return 100; } -private func PowerNeed(id product) { return 100; } +private func PowerNeed() { return 100; } public func NeedRawMaterial(id rawmat_id) { @@ -83,8 +87,11 @@ public func OnProductionHold(id product) public func OnProductionContinued(id product) { - SpinOn(); - AddEffect("Sawing", this, 100, 1, this); + if (!GetEffect("Sawing", this)) + { + SpinOn(); + AddEffect("Sawing", this, 100, 1, this); + } } public func OnProductionFinish(id product) @@ -121,10 +128,11 @@ public func OnProductEjection(object product) protected func RejectCollect(id id_def, object collect) { // Don't collect wood - if(id_def == Wood) return true; - if(collect->~IsSawmillIngredient() || CheckWoodObject(collect)) return false; - else + if (id_def == Wood) return true; + if (collect->~IsSawmillIngredient() || CheckWoodObject(collect)) + return false; + return true; } /*-- Animation --*/ diff --git a/planet/Objects.ocd/Structures.ocd/SteamEngine.ocd/DefCore.txt b/planet/Objects.ocd/Structures.ocd/SteamEngine.ocd/DefCore.txt index bb49f9402..db8738e8d 100644 --- a/planet/Objects.ocd/Structures.ocd/SteamEngine.ocd/DefCore.txt +++ b/planet/Objects.ocd/Structures.ocd/SteamEngine.ocd/DefCore.txt @@ -13,7 +13,7 @@ VertexFriction=50,50,100,100 Value=180 Mass=4000 Components=Rock=6;Metal=3 -Collection=-69,20,20,22 +Collection=-31,9,10,10 Exclusive=1 BlastIncinerate=130 Construction=1 diff --git a/planet/Objects.ocd/Structures.ocd/SteamEngine.ocd/Graphics.mesh b/planet/Objects.ocd/Structures.ocd/SteamEngine.ocd/Graphics.mesh index e41956f59..857be44df 100644 Binary files a/planet/Objects.ocd/Structures.ocd/SteamEngine.ocd/Graphics.mesh and b/planet/Objects.ocd/Structures.ocd/SteamEngine.ocd/Graphics.mesh differ diff --git a/planet/Objects.ocd/Structures.ocd/SteamEngine.ocd/Script.c b/planet/Objects.ocd/Structures.ocd/SteamEngine.ocd/Script.c index 207ece275..064785ff0 100644 --- a/planet/Objects.ocd/Structures.ocd/SteamEngine.ocd/Script.c +++ b/planet/Objects.ocd/Structures.ocd/SteamEngine.ocd/Script.c @@ -1,71 +1,120 @@ /*-- Steam engine --*/ -#include Library_PowerGenerator +#include Library_Ownable +#include Library_PowerProducer -/*-- Power system --*/ - -public func GetCapacity() { return 500; } -public func GetGeneratorPriority() { return 128; } +static const SteamEngine_produced_power = 300; local iFuelAmount; +local power_seconds; func Construction() { iFuelAmount = 0; + power_seconds = 0; return _inherited(...); } +public func IsContainer() { return true; } + +protected func RejectEntrance(object obj) +{ + if (obj->~IsFuel()) + return false; + return true; +} + +protected func RejectCollect(id item, object obj) +{ + // Just return RejectEntrance for this object. + return RejectEntrance(obj); +} + func ContentsCheck() { + //Ejects non fuel items immediately + var fuel; + if(fuel = FindObject(Find_Container(this), Find_Not(Find_Func("IsFuel")))) + { + fuel->Exit(-53,21, -20, -1, -1, -30); + Sound("Chuff"); //I think a 'chuff' or 'metal clonk' sound could be good here -Ringwaul + } + // Still active? - if(!ActIdle()) + if(!ActIdle()) return true; + // or still warm water in the tank?! + if(GetEffect("CreatesPower", this)) return true; - - // No need for power? - if(GetPower() >= GetCapacity()) - return true; - + + // not needed? + if(GetPendingPowerAmount() == 0) + return false; + // Still has some fuel? if(iFuelAmount) return SetAction("Work"); - var pFuel; // Search for new fuel - if(pFuel = FindObject(Find_Container(this), Find_Func("IsFuel"))) + if(fuel = FindObject(Find_Container(this), Find_Func("IsFuel"))) { - iFuelAmount += pFuel->~GetFuelAmount(); - pFuel->RemoveObject(); + iFuelAmount += fuel->~GetFuelAmount(); + fuel->RemoveObject(); SetAction("Work"); - return 1; + return true; } - //Ejects non fuel items immediately - if(pFuel = FindObject(Find_Container(this), !Find_Func("IsFuel"))) { - pFuel->Exit(-53,21, -20, -1, -1, -30); - Sound("Chuff"); //I think a 'chuff' or 'metal clonk' sound could be good here -Ringwaul - } - - return 0; + return false; } func ConsumeFuel() -{ - // Are we full? Stop - if(GetPower() >= GetCapacity()) - return SetAction("Idle"); +{ + if(iFuelAmount > 0) + { + // every fuel unit gives power for one second + --iFuelAmount; + power_seconds += 1; + if(!GetEffect("CreatesPower", this)) + AddEffect("CreatesPower", this, 1, 36, this); + } - // Use up fuel and create power - DoPower(50); - if(iFuelAmount) - iFuelAmount--; - // All used up? - if(!iFuelAmount) + if(!iFuelAmount || ((GetPendingPowerAmount() == 0) && (GetCurrentPowerBalance() >= SteamEngine_produced_power))) { SetAction("Idle"); ContentsCheck(); } } +func FxCreatesPowerStart(target, effect, temp) +{ + if(temp) return; + // fixed amount + MakePowerProducer(SteamEngine_produced_power); + + AddEffect("Smoking", this, 1, 5, this); +} + +func FxCreatesPowerTimer(target, effect) +{ + if(power_seconds == 0) return -1; + --power_seconds; +} + +func FxCreatesPowerStop(target, effect, reason, temp) +{ + if(temp) return; + // disable producer + MakePowerProducer(0); + + if(GetEffect("Smoking", this)) + RemoveEffect("Smoking", this); +} + +func FxSmokingTimer() +{ + Smoke(20, -15, 10); + return 1; +} + local ActMap = { Work = { Prototype = Action, @@ -75,10 +124,6 @@ Work = { FlipDir = 1, Length = 20, Delay = 2, - X = 0, - Y = 0, - Wdt = 110, - Hgt = 80, NextAction = "Work", Animation = "Work", EndCall = "ConsumeFuel", diff --git a/planet/Objects.ocd/Structures.ocd/SteamEngine.ocd/steam.skeleton b/planet/Objects.ocd/Structures.ocd/SteamEngine.ocd/steam.skeleton index 1c9f23380..a465a3a96 100644 Binary files a/planet/Objects.ocd/Structures.ocd/SteamEngine.ocd/steam.skeleton and b/planet/Objects.ocd/Structures.ocd/SteamEngine.ocd/steam.skeleton differ diff --git a/planet/Objects.ocd/Structures.ocd/ToolsWorkshop.ocd/Script.c b/planet/Objects.ocd/Structures.ocd/ToolsWorkshop.ocd/Script.c index bb6ee0f71..3bb53b277 100644 --- a/planet/Objects.ocd/Structures.ocd/ToolsWorkshop.ocd/Script.c +++ b/planet/Objects.ocd/Structures.ocd/ToolsWorkshop.ocd/Script.c @@ -1,13 +1,15 @@ /*-- Tools workshop --*/ -#include Library_PowerConsumer +#include Library_Ownable #include Library_Producer +local hold_production; public func Initialize() { // SetProperty("MeshTransformation", Trans_Rotate(RandomX(-30,30),0,1,0)); + hold_production = false; return _inherited(...); } @@ -21,7 +23,7 @@ public func IsProduct(id product_id) } private func ProductionTime() { return 150; } -private func PowerNeed(id product) { return 150; } +private func PowerNeed() { return 150; } public func NeedRawMaterial(id rawmat_id) { @@ -32,17 +34,19 @@ public func OnProductionStart(id product) { SetSign(product); AddEffect("Working", this, 100, 1, this); + hold_production = false; return; } public func OnProductionHold(id product) { + hold_production = true; return; } public func OnProductionContinued(id product) { - + hold_production = false; return; } @@ -55,7 +59,8 @@ public func OnProductionFinish(id product) protected func FxWorkingTimer() { - Smoking(); + if(!hold_production) + Smoking(); return 1; } @@ -70,9 +75,8 @@ public func SetSign(id def) { if (!def) return SetGraphics("", nil, 1, 4); - var iSize = Max(def->GetDefCoreVal("Picture", "DefCore", 2), def->GetDefCoreVal("Picture", "DefCore", 3)); SetGraphics("", def, 1, 4); - SetObjDrawTransform(200, 0, 460*iSize, 0, 200, 90*iSize, 1); + SetObjDrawTransform(200, 0, 19500, 0, 200, 2500, 1); } local ActMap = { diff --git a/planet/Objects.ocd/Structures.ocd/WindGenerator.ocd/DefCore.txt b/planet/Objects.ocd/Structures.ocd/WindGenerator.ocd/DefCore.txt index 9c839039f..b7f6f2921 100644 --- a/planet/Objects.ocd/Structures.ocd/WindGenerator.ocd/DefCore.txt +++ b/planet/Objects.ocd/Structures.ocd/WindGenerator.ocd/DefCore.txt @@ -14,7 +14,6 @@ VertexFriction=50,50,50,100,100 Value=45 Mass=900 Components=Wood=4;Metal=1 -Picture=30,0,80,94 Exclusive=1 ContactIncinerate=4 BlastIncinerate=60 diff --git a/planet/Objects.ocd/Structures.ocd/WindGenerator.ocd/Script.c b/planet/Objects.ocd/Structures.ocd/WindGenerator.ocd/Script.c index dc3d5347d..62c79dd96 100644 --- a/planet/Objects.ocd/Structures.ocd/WindGenerator.ocd/Script.c +++ b/planet/Objects.ocd/Structures.ocd/WindGenerator.ocd/Script.c @@ -1,6 +1,7 @@ /*-- Wind generator --*/ -#include Library_PowerGenerator +#include Library_Ownable +#include Library_PowerProducer public func GetCapacity() { return 500; } public func GetGeneratorPriority() { return 256; } @@ -8,7 +9,7 @@ public func GetGeneratorPriority() { return 256; } /* Initialisierung */ local wind_anim; - +local last_wind; protected func Construction() { SetProperty("MeshTransformation",Trans_Mul(Trans_Rotate(RandomX(-15,15),0,1,0), Trans_Translate(1200,0,0))); @@ -25,8 +26,17 @@ protected func Initialize() func Wind2Turn() { - DoPower(Abs(GetWind()/3)); - + if(GetCon() < 100) return; + + var power = Abs(GetWind()); + if(power < 5) power = 0; + else power = Max(((power + 5) / 25), 1) * 50; + + if(last_wind != power) + { + last_wind = power; + MakePowerProducer(last_wind); + } // Fade linearly in time until next timer call var start = 0; var end = GetAnimationLength("Turn"); diff --git a/planet/Objects.ocd/Structures.ocd/Windmill.ocd/Script.c b/planet/Objects.ocd/Structures.ocd/Windmill.ocd/Script.c index f3cb27c15..fd6e0e8e7 100644 --- a/planet/Objects.ocd/Structures.ocd/Windmill.ocd/Script.c +++ b/planet/Objects.ocd/Structures.ocd/Windmill.ocd/Script.c @@ -2,12 +2,16 @@ Windmill Authors: Ringwaul, Clonkonaut - Crushes seeds into flour if there is wind or another power source. + Crushes seeds into flour using power - is an own power producer too --*/ +#include Library_Ownable #include Library_Producer +#include Library_PowerConsumer +#include Library_PowerProducer local wind_anim; +local last_wind; protected func Construction() { @@ -25,6 +29,8 @@ protected func Initialize() func Wind2Turn() { + if(GetCon() < 100) return; + // Fade linearly in time until next timer call var start = 0; var end = GetAnimationLength("Spin"); @@ -33,11 +39,20 @@ func Wind2Turn() start = end; end = 0; } - + + var power = Abs(GetWind()); + if(power < 5) power = 0; + else power = Max(((power + 5) / 25), 1) * 50; + + if(last_wind != power) + { + last_wind = power; + MakePowerProducer(last_wind); + } + // Number of frames for one revolution: the more wind the more revolutions per frame. - var wind = Abs(GetWind()); - if(wind == 0) wind = 1; - var l = 18000/wind; + if(last_wind == 0) last_wind = 1; + var l = 18000/last_wind; // Note ending is irrelevant since this is called again after 35 frames if(l > 0) @@ -50,13 +65,6 @@ func Wind2Turn() } } -// Overloaded from PowerConsumer -// As long as their is wind, the windmill has power -public func CheckPower() -{ - if (Abs(GetWind())) return true; - return inherited(...); -} /*-- Production --*/ @@ -67,7 +75,7 @@ private func IsProduct(id product_id) return product_id->~IsWindmillProduct(); } private func ProductionTime() { return 290; } -private func PowerNeed(id product) { return 100; } +private func PowerNeed() { return 75; } public func NeedRawMaterial(id rawmat_id) { diff --git a/planet/Objects.ocd/Structures.ocd/WoodenCabin.ocd/Script.c b/planet/Objects.ocd/Structures.ocd/WoodenCabin.ocd/Script.c index c096a50fd..39de5b8c3 100644 --- a/planet/Objects.ocd/Structures.ocd/WoodenCabin.ocd/Script.c +++ b/planet/Objects.ocd/Structures.ocd/WoodenCabin.ocd/Script.c @@ -1,5 +1,6 @@ /*-- Wooden Cabin --*/ +#include Library_Ownable #include Library_DoorControl public func Initialize() diff --git a/planet/Objects.ocd/Vehicles.ocd/Airship.ocd/AirshipBurnt.ocd/DefCore.txt b/planet/Objects.ocd/Vehicles.ocd/Airship.ocd/AirshipBurnt.ocd/DefCore.txt index 292123926..d9edcee2a 100644 --- a/planet/Objects.ocd/Vehicles.ocd/Airship.ocd/AirshipBurnt.ocd/DefCore.txt +++ b/planet/Objects.ocd/Vehicles.ocd/Airship.ocd/AirshipBurnt.ocd/DefCore.txt @@ -14,4 +14,3 @@ Value=34 Mass=60 Components=Metal=4;Wood=1; SolidMask=64,0,64,54,0,0 -Picture=128,0,128,128,0,0 \ No newline at end of file diff --git a/planet/System.ocg/Array.c b/planet/System.ocg/Array.c index 4b03abf4e..24384e187 100644 --- a/planet/System.ocg/Array.c +++ b/planet/System.ocg/Array.c @@ -1,5 +1,6 @@ /* Global Array helper functions */ +// concatenates two arrays and returns a new array global func Concatenate(array first, array second) { var result = CreateArray(GetLength(first)+GetLength(second)); @@ -11,6 +12,7 @@ global func Concatenate(array first, array second) return result; } +// returns a new array that contains the values of the first array minus the values of the second array global func Subtract(array subject, array subtract) { var diff = []; @@ -31,13 +33,143 @@ global func Subtract(array subject, array subtract) return diff; } +// removes nil values from an array, returns the amount of values removed global func RemoveHoles(array leerdammer) { - // gouda is a cheese with no holes ;-) - var gouda = []; - var hole = nil; - for (var piece in leerdammer) - if (piece != hole) - gouda[GetLength(gouda)] = piece; - return gouda; + var move = 0; + var len = GetLength(leerdammer); + for(var i = 0; i < len; ++i) + { + if(leerdammer[i] == nil) + { + ++move; + continue; + } + leerdammer[i - move] = leerdammer[i]; + } + SetLength(leerdammer, len - move); + // assert IsGouda(leerdammer) + return move; +} + +// removes duplicate entries - returns the number of entries removed +global func RemoveDuplicates(array arr) +{ + var working = []; + var cnt = 0; + + var len = GetLength(arr); + for(var i = 0; i < len; ++i) + { + if(IsValueInArray(working, arr[i])) + { + ++cnt; + continue; + } + working[GetLength(working)] = arr[i]; + } + SetLength(arr, GetLength(working)); + for(var i = GetLength(working); --i >= 0;) + arr[i] = working[i]; + return cnt; +} + + + +// tests whether a value is in an array +global func IsValueInArray(array arr, /*any*/ value) +{ + return GetIndexOf(arr, value) != -1; +} + +// removes a value from an array +global func RemoveArrayValue(array arr, /*any*/ value, bool unstable) +{ + var i = GetIndexOf(arr, value); + if(i == -1) + return false; + if(unstable == true) + return RemoveArrayIndexUnstable(arr, i); + else return RemoveArrayIndex(arr, i); +} + + +// randomly shuffles an array +global func ShuffleArray(array arr) +{ + var len = GetLength(arr); + var working = arr[:]; + + while(--len >= 0) + { + var i = Random(GetLength(working)); + arr[len] = working[i]; + RemoveArrayIndexUnstable(working, i); + } + + return true; +} + +//deletes an index from an array, does not change the order of items in the array +global func RemoveArrayIndex(array arr, int index, bool unstable) +{ + if(unstable == true) + return RemoveArrayIndexUnstable(arr, index); + // move all elements right of index to the left + var len = GetLength(arr); + for(var i = index; i < len - 1; ++i) + arr[i] = arr[i+1]; + SetLength(arr, GetLength(arr) - 1); + return true; +} + +// deletes an array item - might change the order of elements, but is faster +global func RemoveArrayIndexUnstable(array arr, int index) +{ + arr[index] = arr[-1]; + SetLength(arr, GetLength(arr) - 1); + return true; +} + +//inserts an element at the end of an array +global func PushBack(array arr, /*any*/ value) +{ + arr[GetLength(arr)] = value; + return true; +} + +// inserts an element at the beginning of an array +global func PushFront(array arr, /*any*/ value) +{ + SetLength(arr, GetLength(arr) + 1); + + // move elements one to the right + for(var i = GetLength(arr)-1; i > 0;--i) + arr[i] = arr[i-1]; + arr[0] = value; + return true; +} + +// removes the last element from an array and returns it +global func PopBack(array arr) +{ + if(GetLength(arr) == 0) + return nil; + var o = arr[-1]; + SetLength(arr, GetLength(arr) - 1); + return o; +} + +// removes the first element from an array and returns it +// obviously a bit slower than PopBack +global func PopFront(array arr) +{ + var len = GetLength(arr); + if(len == 0) + return nil; + var o = arr[0]; + for(var i = 1; i < len; ++i) + arr[i - 1] = arr[i]; + SetLength(arr, GetLength(arr) - 1); + return o; } \ No newline at end of file diff --git a/planet/System.ocg/Commits.c b/planet/System.ocg/Commits.c index d0d628fdf..52c465fd3 100644 --- a/planet/System.ocg/Commits.c +++ b/planet/System.ocg/Commits.c @@ -127,8 +127,8 @@ global func PlaceObjects(id id, int amount, string mat_str, int x, int y, int wd { var i, j; var rndx, rndy, obj; - var mtype, mat; - var func, objhgt = id->GetDefCoreVal("Height", "DefCore"); + var mat; + var objhgt = id->GetDefCoreVal("Height", "DefCore"); mat = Material(mat_str); // Some failsavety. @@ -337,3 +337,8 @@ global func FindPosInMat(string sMat, int iXStart, int iYStart, int iWidth, int } return 0; // No location found. } + +global func MovePosition(int x, int y, int prec) +{ + SetPosition(GetX(prec) + x, GetY(prec) + y, nil, prec); +} diff --git a/planet/System.ocg/HitChecks.c b/planet/System.ocg/HitChecks.c index 78bde9639..e2e6c0fcd 100644 --- a/planet/System.ocg/HitChecks.c +++ b/planet/System.ocg/HitChecks.c @@ -55,7 +55,7 @@ global func FxHitCheckDoCheck(object target, proplist effect) if (live) shooter = target; - if (Distance(oldx, oldy, newx, newy) <= Max(1, Max(Abs(target->GetXDir()), Abs(target->GetYDir()))) * 2) + if (dist <= Max(1, Max(Abs(target->GetXDir()), Abs(target->GetYDir()))) * 2) { // We search for objects along the line on which we moved since the last check // and sort by distance (closer first). diff --git a/planet/System.ocg/LanguageDE.txt b/planet/System.ocg/LanguageDE.txt index a859e74b6..0d3337af9 100644 --- a/planet/System.ocg/LanguageDE.txt +++ b/planet/System.ocg/LanguageDE.txt @@ -38,6 +38,7 @@ IDS_BTN_RELOAD=&Aktualisieren IDS_BTN_RENAME=Umbenennen IDS_BTN_RESETCONFIG=Konfiguration zurücksetzen IDS_BTN_RESETKEYBOARD=Alle zurücksetzen +IDS_BTN_RESTART=Neu &Starten IDS_BTN_RETRY=Wiederholen IDS_BTN_SIMPLE=<- Einfach IDS_BTN_START=Starten @@ -784,6 +785,9 @@ IDS_MSG_FREEVIEW=Freie Sicht IDS_MSG_FULLSCREEN=Vollbild IDS_MSG_FULLSCREEN_DESC=Vollbildmodus aktivieren. IDS_MSG_GFXENGINE_DESC=Gibt an, welcher Grafikmodus benutzt wird. Änderungen greifen erst beim nächsten Programmstart. +IDS_MSG_GFXERR_RESINVAL=Ungültige Auflösung! +IDS_MSG_GFXERR_RESNOTFOUND=Die gewählte Auflösung wird vom System anscheinend nicht unterstützt. +IDS_MSG_GFXERR_TXT=OpenClonk konnte OpenGL nicht laden. Prüfen Sie, ob Ihr Grafiktreiber aktuell ist und OpenGL 1.3 unterstützt. IDS_MSG_HASDISCONNECTED=%s hat die Verbindung beendet (%s). IDS_MSG_HASJOINEDTHECHANNEL=%s ist dem Chat-Kanal beigetreten. IDS_MSG_HASLEFTTHECHANNEL=%s hat den Chat-Kanal verlassen (%s) diff --git a/planet/System.ocg/LanguageUS.txt b/planet/System.ocg/LanguageUS.txt index 78bc2e008..8d7a640b3 100644 --- a/planet/System.ocg/LanguageUS.txt +++ b/planet/System.ocg/LanguageUS.txt @@ -38,6 +38,7 @@ IDS_BTN_RELOAD=Reloa&d IDS_BTN_RENAME=Rename IDS_BTN_RESETCONFIG=Reset configuration IDS_BTN_RESETKEYBOARD=Reset all +IDS_BTN_RESTART=Restart IDS_BTN_RETRY=Retry IDS_BTN_SIMPLE=<- Basic IDS_BTN_START=Start @@ -783,6 +784,9 @@ IDS_MSG_FREEVIEW=free view IDS_MSG_FULLSCREEN=Fullscreen IDS_MSG_FULLSCREEN_DESC=Use fullscreen mode. IDS_MSG_GFXENGINE_DESC=Determines the rendering engine. Changes take effect when the game is restarted. +IDS_MSG_GFXERR_RESINVAL=Invalid resolution! +IDS_MSG_GFXERR_RESNOTFOUND=This resolution is probably not supportet by your system. +IDS_MSG_GFXERR_TXT=OpenClonk could not load OpenGL. Please check if your graphics card driver is up-to-date and supports OpenGL 1.3. IDS_MSG_HASDISCONNECTED=%s has disconnected (%s). IDS_MSG_HASJOINEDTHECHANNEL=%s has joined the channel. IDS_MSG_HASLEFTTHECHANNEL=%s has left the channel (%s) diff --git a/planet/System.ocg/Player.c b/planet/System.ocg/Player.c index 946c79dee..bb7b67522 100644 --- a/planet/System.ocg/Player.c +++ b/planet/System.ocg/Player.c @@ -59,8 +59,8 @@ global func GetTaggedTeamName(int team) // Brightens dark colors, to be readable on dark backgrounds. global func MakeColorReadable(int color) { - // Determine alpha. - var a = ((color >> 24 & 255) << 24); + // Determine alpha. Not needed at the moment + //var a = ((color >> 24 & 255) << 24); // Strip alpha. color = color & 16777215; // Calculate brightness: 50% red, 87% green, 27% blue (Max 164 * 255). diff --git a/planet/System.ocg/PlayerControl.c b/planet/System.ocg/PlayerControl.c index 46ad57147..05ab83bd0 100644 --- a/planet/System.ocg/PlayerControl.c +++ b/planet/System.ocg/PlayerControl.c @@ -204,7 +204,6 @@ global func Control2Effect(int plr, int ctrl, int x, int y, int strength, bool r // Count down from EffectCount, in case effects get deleted var i = GetEffectCount("*Control*", this), iEffect; - var res; while (i--) { iEffect = GetEffect("*Control*", this, i); @@ -465,6 +464,21 @@ global func ObjectComLetGo(int vx, int vy) return true; } +/* Mouse Hovering */ + +// Engine callback when the mouse hovers over an object (entering) or stops hovering over an object (leaving). +// Either leaving, entering or both are set. They can be nil, but never both at the same time. +// dragged is an object being drag(¬ dropped yet) +global func MouseHover(int player, object leaving, object entering, object dragged) +{ + // Leaving the hovering zone should be processed first. + if(leaving) + leaving->~OnMouseOut(player, dragged); + // Then process entering a new hovering zone. + if(entering) + entering->~OnMouseOver(player, dragged); + return true; +} /* Drag & Drop */ diff --git a/planet/Tests.ocf/AirRace.ocs/Script.c b/planet/Tests.ocf/AirRace.ocs/Script.c index ef23d4ab6..65e0a5151 100644 --- a/planet/Tests.ocf/AirRace.ocs/Script.c +++ b/planet/Tests.ocf/AirRace.ocs/Script.c @@ -126,7 +126,7 @@ protected func OnPlayerRespawn(int plr, object cp) var clonk = GetCrew(plr); var plane = CreateObject(Plane, cp->GetX(), cp->GetY(), plr); clonk->Enter(plane); - plane->CreateContents(Bullet); + //plane->CreateContents(Bullet); // there is no bullet def var mode = cp->GetCPMode(); if (mode & PARKOUR_CP_Start) plane->SetR(90); @@ -163,9 +163,9 @@ private func FindPlaneAngle(object cp) protected func GivePlrBonus(int plr, object cp) { - var plane = GetCursor(plr)->Contained(); - if (plane && plane->GetID() == Plane) - plane->CreateContents(Bullet); + //var plane = GetCursor(plr)->Contained(); + //if (plane && plane->GetID() == Plane) + //plane->CreateContents(Bullet); // there is no bullet def return; } diff --git a/planet/Tests.ocf/CableLorrys.ocs/CableCars.ocd/Structures.ocd/Crossing.ocd/DefCore.txt b/planet/Tests.ocf/CableLorrys.ocs/CableCars.ocd/Structures.ocd/Crossing.ocd/DefCore.txt index 24949a753..1d232bdb0 100644 --- a/planet/Tests.ocf/CableLorrys.ocs/CableCars.ocd/Structures.ocd/Crossing.ocd/DefCore.txt +++ b/planet/Tests.ocf/CableLorrys.ocs/CableCars.ocd/Structures.ocd/Crossing.ocd/DefCore.txt @@ -12,8 +12,8 @@ VertexFriction=50,100,100 Value=40 Mass=5 #Components=Metal=1 -Picture=0,0,20,20 +Picture=0,0,160,160 Exclusive=1 BlastIncinerate=50 Construction=1 -Collection=-10,-10,20,20 \ No newline at end of file +Collection=-10,-10,20,20 diff --git a/planet/Tests.ocf/CableLorrys.ocs/CableCars.ocd/Vehicles.ocd/Lorry.ocd/DefCore.txt b/planet/Tests.ocf/CableLorrys.ocs/CableCars.ocd/Vehicles.ocd/Lorry.ocd/DefCore.txt index f1336e005..1956ec2f9 100644 --- a/planet/Tests.ocf/CableLorrys.ocs/CableCars.ocd/Vehicles.ocd/Lorry.ocd/DefCore.txt +++ b/planet/Tests.ocf/CableLorrys.ocs/CableCars.ocd/Vehicles.ocd/Lorry.ocd/DefCore.txt @@ -20,7 +20,4 @@ Rotate=30 UprightAttach=0 TimerCall=TurnWheels Timer=1 -BorderBound=1 - -[Physicals] -Float=200 +BorderBound=1 \ No newline at end of file diff --git a/planet/Tests.ocf/Experimental.ocd/CableReel.ocd/Script.c b/planet/Tests.ocf/Experimental.ocd/CableReel.ocd/Script.c index 89f40ac94..60846dd64 100644 --- a/planet/Tests.ocf/Experimental.ocd/CableReel.ocd/Script.c +++ b/planet/Tests.ocf/Experimental.ocd/CableReel.ocd/Script.c @@ -56,7 +56,6 @@ protected func ControlUse(object clonk, int x, int y) clonk->Message("$TxtConnect$", obj->GetName()); return true; } - return true; } // Finds all power lines connected to obj (can be nil in local calls). diff --git a/planet/Tests.ocf/Experimental.ocd/FireGlobe.ocd/DefCore.txt b/planet/Tests.ocf/Experimental.ocd/FireGlobe.ocd/DefCore.txt index f158d2d63..8f11d69b7 100644 --- a/planet/Tests.ocf/Experimental.ocd/FireGlobe.ocd/DefCore.txt +++ b/planet/Tests.ocf/Experimental.ocd/FireGlobe.ocd/DefCore.txt @@ -7,7 +7,7 @@ Offset=-5,-5 Vertices=1 VertexY=0 VertexFriction=100 -Picture=0,0,10,10 +Picture=0,0,60,60 Value=8 Mass=1 Rotate=1 diff --git a/planet/Tests.ocf/Experimental.ocd/LiftTower.ocd/Rope.ocd/Script.c b/planet/Tests.ocf/Experimental.ocd/LiftTower.ocd/Rope.ocd/Script.c index efc10fab0..599cfb193 100644 --- a/planet/Tests.ocf/Experimental.ocd/LiftTower.ocd/Rope.ocd/Script.c +++ b/planet/Tests.ocf/Experimental.ocd/LiftTower.ocd/Rope.ocd/Script.c @@ -73,7 +73,6 @@ local last_point; func UpdateLines() { - var fTimeStep = 1; var oldangle; for(var i=1; i < ParticleCount; i++) { @@ -188,14 +187,11 @@ func ForcesOnObjects() if( obj->GetAction() == "Climb") obj->SetAction("Jump"); - var xdist = particles[j][0][0]-obj->GetX(Rope_Precision); - var ydist = particles[j][0][1]-obj->GetY(Rope_Precision); - var xdir = BoundBy(particles[j][0][0]-particles[j][1][0], -100, 100); var ydir = particles[j][0][1]-particles[j][1][1]; if (!obj->GetContact(-1)) - ydir = BoundBy(ydir, -100, 100); + ydir = BoundBy(ydir, -50, 50); if (pull_position && pull_frame != FrameCounter() && !Distance(pull_position[0], pull_position[1], obj->GetX(), obj->GetY())) { @@ -218,7 +214,7 @@ func ForcesOnObjects() pull_frame = FrameCounter(); obj->SetXDir( xdir, Rope_Precision); - obj->SetYDir( ydir, Rope_Precision); + obj->SetYDir( obj->GetYDir() + ydir, Rope_Precision); //Log("%v, %v", xdir, ydir); } } @@ -246,8 +242,7 @@ public func DoLength(int dolength) if (obj2->Contained()) obj2 = obj2->Contained(); // Line would be shorter than the distance? Do nothing - if (dolength < 0 && ObjectDistance(obj, obj2) > GetLineLength()/100) return Log("NO!"); - Log("%v, Line length: %v, Segment length: %v", ObjectDistance(obj, obj2), GetLineLength()/100 - Rope_SegmentLength, Rope_SegmentLength); + if (dolength < 0 && ObjectDistance(obj, obj2) > GetLineLength()/100) return; return _inherited(dolength); } diff --git a/planet/Tests.ocf/Lines.ocs/Script.c b/planet/Tests.ocf/Lines.ocs/Script.c index 8a9489374..86b74b197 100644 --- a/planet/Tests.ocf/Lines.ocs/Script.c +++ b/planet/Tests.ocf/Lines.ocs/Script.c @@ -6,8 +6,8 @@ func Initialize() CreateObject(Ropeladder, 328, 564); CreateObject(Ropeladder, 226, 330); - var Rock1 = CreateObject(Rock, 159, 363); - var Rock2 = CreateObject(Rock, 232, 388); + CreateObject(Rock, 159, 363); + CreateObject(Rock, 232, 388); var Anchor1 = CreateObject(Ropebridge_Post, 515, 547); var Anchor2 = CreateObject(Ropebridge_Post, 602, 538); diff --git a/planet/Tests.ocf/Moss_Test.ocs/Moss.ocd/DefCore.txt b/planet/Tests.ocf/Moss_Test.ocs/Moss.ocd/DefCore.txt index 43ad70ed8..5c819a78a 100644 --- a/planet/Tests.ocf/Moss_Test.ocs/Moss.ocd/DefCore.txt +++ b/planet/Tests.ocf/Moss_Test.ocs/Moss.ocd/DefCore.txt @@ -5,7 +5,7 @@ Category=C4D_Object Width=8 Height=8 Offset=-4,-4 -Picture=0,0,8,8 +Picture=0,0,64,64 Vertices=3 VertexX=0,2,-2 VertexY=1,-1,-1 @@ -18,4 +18,4 @@ ContactIncinerate=1 BlastIncinerate=1 Rotate=1 Float=1 -Collectible=1 \ No newline at end of file +Collectible=1 diff --git a/planet/Tests.ocf/Settlement.ocs/Script.c b/planet/Tests.ocf/Settlement.ocs/Script.c index 50215eec5..5386dbafa 100644 --- a/planet/Tests.ocf/Settlement.ocs/Script.c +++ b/planet/Tests.ocf/Settlement.ocs/Script.c @@ -22,7 +22,6 @@ protected func InitializePlayer(int plr) var clonk = GetCrew(plr); clonk->CreateContents(Shovel); var lorry = CreateObject(Lorry, clonk->GetX(), clonk->GetY(), plr); - lorry->CreateContents(CableReel, 4); lorry->CreateContents(Pipe, 2); return; } diff --git a/planet/Tutorial.ocf/Tutorial02.ocs/Script.c b/planet/Tutorial.ocf/Tutorial02.ocs/Script.c index 313016d75..0a06b3b80 100644 --- a/planet/Tutorial.ocf/Tutorial02.ocs/Script.c +++ b/planet/Tutorial.ocf/Tutorial02.ocs/Script.c @@ -15,7 +15,7 @@ protected func Initialize() goal->CreateGoalFlag(2950, 280); // Create all objects, vehicles, chests used by the player. - var effect, firestone, chest, powderkeg, ropeladder, grapple, cata, dynamite; + var effect, firestone, chest, powderkeg, grapple, dynamite; // Dynamite box to blast through mine. var dyn1 = CreateObject(Dynamite, 242, 665, NO_OWNER); diff --git a/planet/Tutorial.ocf/Tutorial03.ocs/Script.c b/planet/Tutorial.ocf/Tutorial03.ocs/Script.c index 30d3eb729..a70877d08 100644 --- a/planet/Tutorial.ocf/Tutorial03.ocs/Script.c +++ b/planet/Tutorial.ocf/Tutorial03.ocs/Script.c @@ -144,7 +144,7 @@ protected func OnGuideMessageShown(int plr, int index) { // Show first three targets with the arrow. if (index == 0) - for (target in FindObjects(Find_ID(PracticeTarget), Find_InRect(100, 450, 350, 150))) + for (var target in FindObjects(Find_ID(PracticeTarget), Find_InRect(100, 450, 350, 150))) TutArrowShowTarget(target, RandomX(-45, 45), 24); // Show javelin chest with an arrow. if (index == 1) @@ -173,7 +173,7 @@ protected func OnGuideMessageRemoved(int plr, int index) private func MakeTarget(int x, int y, bool flying) { if (flying == nil) - balloon = false; + var balloon = false; var target = CreateObject(PracticeTarget, x, y, NO_OWNER); if (flying == true) diff --git a/planet/Tutorial.ocf/Tutorial04.ocs/Script.c b/planet/Tutorial.ocf/Tutorial04.ocs/Script.c index aaf56f0fc..25f6d8a28 100644 --- a/planet/Tutorial.ocf/Tutorial04.ocs/Script.c +++ b/planet/Tutorial.ocf/Tutorial04.ocs/Script.c @@ -228,7 +228,7 @@ protected func OnGuideMessageShown(int plr, int index) { // Show first four targets with the arrow. if (index == 0) - for (target in FindObjects(Find_ID(SwordTarget))) + for (var target in FindObjects(Find_ID(SwordTarget))) { var angle = RandomX(-45, 45); if (target->GetY() > 620) diff --git a/planet/Tutorial.ocf/Tutorial04.ocs/System.ocg/AIMusketAttack.c b/planet/Tutorial.ocf/Tutorial04.ocs/System.ocg/AIMusketAttack.c index 9c2d6979f..bbed7ac4b 100644 --- a/planet/Tutorial.ocf/Tutorial04.ocs/System.ocg/AIMusketAttack.c +++ b/planet/Tutorial.ocf/Tutorial04.ocs/System.ocg/AIMusketAttack.c @@ -28,7 +28,6 @@ protected func AI_MusketAttack(object clonk, int x, int y, object target) // Shoot a lead shot. var dx = target->GetX() - clonk->GetX(); var dy = target->GetY() - clonk->GetY(); - var dist = Distance(0, 0, dx, dy); ControlUseStart(clonk, dx, dy); ControlUseStop(clonk, dx, dy); diff --git a/src/C4Application.cpp b/src/C4Application.cpp index 120e25298..a42607c28 100644 --- a/src/C4Application.cpp +++ b/src/C4Application.cpp @@ -52,6 +52,8 @@ #include +#include + static C4Network2IRCClient ApplicationIRCClient; C4Application::C4Application(): @@ -161,7 +163,7 @@ bool C4Application::DoInit(int argc, char * argv[]) if (!isEditor) { if (!(pWindow = FullScreen.Init(this))) - { Clear(); return false; } + { Clear(); ShowGfxErrorDialog(); return false; } } else { @@ -178,7 +180,7 @@ bool C4Application::DoInit(int argc, char * argv[]) // Initialize D3D/OpenGL bool success = DDrawInit(this, isEditor, false, Config.Graphics.ResX, Config.Graphics.ResY, Config.Graphics.BitDepth, Config.Graphics.Engine, Config.Graphics.Monitor); - if (!success) { LogFatal(LoadResStr("IDS_ERR_DDRAW")); Clear(); return false; } + if (!success) { LogFatal(LoadResStr("IDS_ERR_DDRAW")); Clear(); ShowGfxErrorDialog(); return false; } if (!isEditor) { diff --git a/src/C4Include.h b/src/C4Include.h index eadc99376..b4b21bd92 100644 --- a/src/C4Include.h +++ b/src/C4Include.h @@ -20,7 +20,12 @@ * See clonk_trademark_license.txt for full license. */ -/* Main header to include all others */ +/* This header is included first from every source file. It serves three purposes: + - PlatformAbstraction.h + - Common utility functionality that's used everywhere + - Speeding up the compilation by precompiling this header +All of our headers are designed to be used with C4Include.h included before and +don't need to include this file or any of the files it includes. */ #ifndef INC_C4Include #define INC_C4Include diff --git a/src/C4Prototypes.h b/src/C4Prototypes.h index d879cdc02..16f9e96cd 100644 --- a/src/C4Prototypes.h +++ b/src/C4Prototypes.h @@ -145,6 +145,7 @@ class C4AbstractApp; class C4Window; class C4Surface; class CStdStream; +class CStdGLCtx; namespace C4GUI { diff --git a/src/c4group/CStdFile.h b/src/c4group/CStdFile.h index 05fb37b5a..80e6d2957 100644 --- a/src/c4group/CStdFile.h +++ b/src/c4group/CStdFile.h @@ -27,11 +27,10 @@ #include #include // for StdThreadCheck #include +#include // for gzFile const int CStdFileBufSize = 4096; -typedef void* gzFile; - class CStdStream { public: diff --git a/src/editor/C4Console.cpp b/src/editor/C4Console.cpp index c8dcf3b43..5decfd491 100644 --- a/src/editor/C4Console.cpp +++ b/src/editor/C4Console.cpp @@ -590,7 +590,7 @@ void C4ConsoleGUI::PropertyDlgUpdate(C4ObjectList &rSelection) {} void C4ConsoleGUI::RecordingEnabled() {} void C4ConsoleGUI::SetCaptionToFileName(char const*) {} void C4ConsoleGUI::SetCursor(C4ConsoleGUI::Cursor) {} -void C4ConsoleGUI::SetInputFunctions(std::list >&) {} +void C4ConsoleGUI::SetInputFunctions(std::list&) {} void C4ConsoleGUI::ShowAboutWithCopyright(StdStrBuf&) {} void C4ConsoleGUI::ToolsDlgInitMaterialCtrls(C4ToolsDlg*) {} bool C4ConsoleGUI::ToolsDlgOpen(C4ToolsDlg*) {return 0;} diff --git a/src/game/landscape/C4Material.cpp b/src/game/landscape/C4Material.cpp index 17e10c77d..0634f7eaa 100644 --- a/src/game/landscape/C4Material.cpp +++ b/src/game/landscape/C4Material.cpp @@ -676,10 +676,15 @@ bool C4MaterialMap::CrossMapMaterials() // Called after load printf("%s -> %s: %p\n", Map[cnt].Name, Map[cnt2].Name, ppReactionMap[(cnt2+1)*(Num+1) + cnt+1]->pFunc); #endif // Get hardcoded system material indices + const C4TexMapEntry* earth_entry = ::TextureMap.GetEntry(::TextureMap.GetIndexMatTex(Game.C4S.Landscape.Material)); + if(!earth_entry) + { LogFatal(FormatString("Earth material \"%s\" not found!", Game.C4S.Landscape.Material).getData()); return false; } + MVehic = Get("Vehicle"); MCVehic = Mat2PixColDefault(MVehic); MTunnel = Get("Tunnel"); MWater = Get("Water"); - MEarth = Get(Game.C4S.Landscape.Material); + MEarth = Get(earth_entry->GetMaterialName()); + if ((MVehic==MNone) || (MTunnel==MNone)) { LogFatal(LoadResStr("IDS_PRC_NOSYSMATS")); return false; } return true; diff --git a/src/game/object/C4Def.cpp b/src/game/object/C4Def.cpp index 06c6287f0..37eb36d13 100644 --- a/src/game/object/C4Def.cpp +++ b/src/game/object/C4Def.cpp @@ -117,10 +117,6 @@ bool C4Def::LoadDefCore(C4Group &hGroup) hGroup.Rename(C4CFN_DefCore, C4CFN_DefCore ".old"); Save(hGroup);*/ - // Adjust picture rect - if ((PictureRect.Wdt==0) || (PictureRect.Hgt==0)) - PictureRect.Set(0,0,Shape.Wdt,Shape.Hgt); - // Check mass if (Mass < 0) { @@ -477,6 +473,10 @@ bool C4Def::Load(C4Group &hGroup, MainFace.Set(NULL,0,0,Shape.Wdt,Shape.Hgt); } + // Adjust picture rect + if ((PictureRect.Wdt==0) || (PictureRect.Hgt==0)) + PictureRect.Set(0,0,Shape.Wdt*Graphics.Bmp.Bitmap->Scale, Shape.Hgt*Graphics.Bmp.Bitmap->Scale); + // validate TopFace if (TopFace.x<0 || TopFace.y<0 || TopFace.x+TopFace.Wdt>Graphics.Bmp.Bitmap->Wdt || TopFace.y+TopFace.Hgt>Graphics.Bmp.Bitmap->Hgt) { @@ -488,6 +488,7 @@ bool C4Def::Load(C4Group &hGroup, else { TopFace.Default(); + PictureRect.Default(); SolidMask.Default(); } @@ -499,65 +500,11 @@ bool C4Def::Load(C4Group &hGroup, void C4Def::Draw(C4Facet &cgo, bool fSelected, DWORD iColor, C4Object *pObj, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform* trans) { - - // default: def picture rect - C4Rect fctPicRect = PictureRect; - C4Facet fctPicture; - - // if assigned: use object specific rect and graphics - if (pObj) if (pObj->PictureRect.Wdt) fctPicRect = pObj->PictureRect; - - if (fSelected) + if(fSelected) pDraw->DrawBoxDw(cgo.Surface, cgo.X, cgo.Y, cgo.X + cgo.Wdt - 1, cgo.Y + cgo.Hgt - 1, C4RGB(0xca, 0, 0)); C4DefGraphics* graphics = pObj ? pObj->GetGraphics() : &Graphics; - - // specific object color? - if (pObj) pObj->PrepareDrawing(); - - switch (graphics->Type) - { - case C4DefGraphics::TYPE_Bitmap: - fctPicture.Set(graphics->GetBitmap(iColor),fctPicRect.x,fctPicRect.y,fctPicRect.Wdt,fctPicRect.Hgt); - fctPicture.DrawT(cgo,true,iPhaseX,iPhaseY,trans); - break; - case C4DefGraphics::TYPE_Mesh: - // TODO: Allow rendering of a mesh directly, without instance (to render pose; no animation) - std::auto_ptr dummy; - StdMeshInstance* instance; - - C4Value value; - if (pObj) - { - instance = pObj->pMeshInstance; - pObj->GetProperty(P_PictureTransformation, &value); - } - else - { - dummy.reset(new StdMeshInstance(*graphics->Mesh)); - instance = dummy.get(); - GetProperty(P_PictureTransformation, &value); - } - - StdMeshMatrix matrix; - if (C4ValueToMatrix(value, &matrix)) - pDraw->SetMeshTransform(&matrix); - - pDraw->SetPerspective(true); - pDraw->RenderMesh(*instance, cgo.Surface, cgo.X,cgo.Y, cgo.Wdt, cgo.Hgt, pObj ? pObj->Color : iColor, trans); - pDraw->SetPerspective(false); - pDraw->SetMeshTransform(NULL); - - break; - } - - if (pObj) pObj->FinishedDrawing(); - - // draw overlays - if (pObj && pObj->pGfxOverlay) - for (C4GraphicsOverlay *pGfxOvrl = pObj->pGfxOverlay; pGfxOvrl; pGfxOvrl = pGfxOvrl->GetNext()) - if (pGfxOvrl->IsPicture()) - pGfxOvrl->DrawPicture(cgo, pObj, trans); + graphics->Draw(cgo, iColor, pObj, iPhaseX, iPhaseY, trans); } int32_t C4Def::GetValue(C4Object *pInBase, int32_t iBuyPlayer) diff --git a/src/game/object/C4DefGraphics.cpp b/src/game/object/C4DefGraphics.cpp index 0d87b520e..97fc2ad59 100644 --- a/src/game/object/C4DefGraphics.cpp +++ b/src/game/object/C4DefGraphics.cpp @@ -160,9 +160,9 @@ bool C4DefGraphics::LoadMesh(C4Group &hGroup, StdMeshSkeletonLoader& loader) try { if (hGroup.LoadEntry(C4CFN_DefMesh, &buf, &size, 1)) - Mesh = StdMeshLoader::LoadMeshBinary(buf, size, ::MeshMaterialManager, loader); + Mesh = StdMeshLoader::LoadMeshBinary(buf, size, ::MeshMaterialManager, loader, hGroup.GetName()); else if (hGroup.LoadEntry(C4CFN_DefMeshXml, &buf, &size, 1)) - Mesh = StdMeshLoader::LoadMeshXml(buf, size, ::MeshMaterialManager, loader); + Mesh = StdMeshLoader::LoadMeshXml(buf, size, ::MeshMaterialManager, loader, hGroup.GetName()); else return false; delete[] buf; @@ -294,6 +294,63 @@ bool C4DefGraphics::CopyGraphicsFrom(C4DefGraphics &rSource) return true; } +void C4DefGraphics::Draw(C4Facet &cgo, DWORD iColor, C4Object *pObj, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform* trans) +{ + // default: def picture rect + C4Rect fctPicRect = pDef->PictureRect; + C4Facet fctPicture; + + // if assigned: use object specific rect and graphics + if (pObj) if (pObj->PictureRect.Wdt) fctPicRect = pObj->PictureRect; + + // specific object color? + if (pObj) pObj->PrepareDrawing(); + + switch(Type) + { + case C4DefGraphics::TYPE_Bitmap: + fctPicture.Set(GetBitmap(iColor),fctPicRect.x,fctPicRect.y,fctPicRect.Wdt,fctPicRect.Hgt); + fctPicture.DrawTUnscaled(cgo,true,iPhaseX,iPhaseY,trans); + break; + case C4DefGraphics::TYPE_Mesh: + // TODO: Allow rendering of a mesh directly, without instance (to render pose; no animation) + std::auto_ptr dummy; + StdMeshInstance* instance; + + C4Value value; + if (pObj) + { + instance = pObj->pMeshInstance; + pObj->GetProperty(P_PictureTransformation, &value); + } + else + { + dummy.reset(new StdMeshInstance(*Mesh, 1.0f)); + instance = dummy.get(); + pDef->GetProperty(P_PictureTransformation, &value); + } + + StdMeshMatrix matrix; + if (C4ValueToMatrix(value, &matrix)) + pDraw->SetMeshTransform(&matrix); + + pDraw->SetPerspective(true); + pDraw->RenderMesh(*instance, cgo.Surface, cgo.X,cgo.Y, cgo.Wdt, cgo.Hgt, pObj ? pObj->Color : iColor, trans); + pDraw->SetPerspective(false); + pDraw->SetMeshTransform(NULL); + + break; + } + + if (pObj) pObj->FinishedDrawing(); + + // draw overlays + if (pObj && pObj->pGfxOverlay) + for (C4GraphicsOverlay *pGfxOvrl = pObj->pGfxOverlay; pGfxOvrl; pGfxOvrl = pGfxOvrl->GetNext()) + if (pGfxOvrl->IsPicture()) + pGfxOvrl->DrawPicture(cgo, pObj, trans); +} + void C4DefGraphics::DrawClr(C4Facet &cgo, bool fAspect, DWORD dwClr) { if (Type != TYPE_Bitmap) return; // TODO @@ -595,7 +652,7 @@ void C4GraphicsOverlay::UpdateFacet() if (pSourceGfx->Type == C4DefGraphics::TYPE_Bitmap) fctBlit.Set(pSourceGfx->GetBitmap(), 0, 0, pDef->Shape.Wdt, pDef->Shape.Hgt, pDef->Shape.x+pDef->Shape.Wdt/2, pDef->Shape.y+pDef->Shape.Hgt/2); else - pMeshInstance = new StdMeshInstance(*pSourceGfx->Mesh); + pMeshInstance = new StdMeshInstance(*pSourceGfx->Mesh, 1.0f); break; case MODE_Action: // graphics of specified action @@ -630,7 +687,7 @@ void C4GraphicsOverlay::UpdateFacet() C4String* AnimationName = action->GetPropertyStr(P_Animation); if (!AnimationName) return; - pMeshInstance = new StdMeshInstance(*pSourceGfx->Mesh); + pMeshInstance = new StdMeshInstance(*pSourceGfx->Mesh, 1.0f); const StdMeshAnimation* Animation = pSourceGfx->Mesh->GetAnimationByName(AnimationName->GetData()); if (!Animation) return; @@ -646,10 +703,7 @@ void C4GraphicsOverlay::UpdateFacet() case MODE_IngamePicture: case MODE_Picture: // def picture fZoomToShape = true; - if (pSourceGfx->Type == C4DefGraphics::TYPE_Bitmap) - fctBlit.Set(pSourceGfx->GetBitmap(), pDef->PictureRect.x, pDef->PictureRect.y, pDef->PictureRect.Wdt, pDef->PictureRect.Hgt); - else - pMeshInstance = new StdMeshInstance(*pSourceGfx->Mesh); + // drawn at runtime break; case MODE_ExtraGraphics: // like ColorByOwner-sfc @@ -695,7 +749,9 @@ bool C4GraphicsOverlay::IsValid(const C4Object *pForObj) const } else if (pSourceGfx) { - if (pSourceGfx->Type == C4DefGraphics::TYPE_Bitmap) + if(eMode == MODE_Picture || eMode == MODE_IngamePicture) + return true; + else if (pSourceGfx->Type == C4DefGraphics::TYPE_Bitmap) return !!fctBlit.Surface; else return !!pMeshInstance; @@ -880,6 +936,8 @@ void C4GraphicsOverlay::Draw(C4TargetFacet &cgo, C4Object *pForObj, int32_t iByP // drawing specific object? else if (OverlayObj) { + // TODO: Shouldn't have called PrepareDrawing/set ClrModulation here, since + // OverlayObj drawing will do it on its own. if (eMode == MODE_ObjectPicture) { C4Facet fctTarget; @@ -919,6 +977,27 @@ void C4GraphicsOverlay::Draw(C4TargetFacet &cgo, C4Object *pForObj, int32_t iByP pForObj->pDrawTransform = pPrevTrf; } } + else if(eMode == MODE_Picture || eMode == MODE_IngamePicture) + { + float twdt, thgt; + if (fZoomToShape) + { + twdt = pForObj->Shape.Wdt; + thgt = pForObj->Shape.Hgt; + } + else + { + twdt = pSourceGfx->pDef->Shape.Wdt; + thgt = pSourceGfx->pDef->Shape.Hgt; + } + + C4TargetFacet ccgo; + ccgo.Set(cgo.Surface, offX-twdt/2, offY-thgt/2, twdt, thgt, cgo.TargetX, cgo.TargetY); + C4DrawTransform trf(Transform, offX, offY); + + // Don't set pForObj because we don't draw the picture of pForObj, but the picture of another definition on top of pForObj: + pSourceGfx->Draw(ccgo, pForObj->Color, NULL, iPhase, 0, &trf); + } else { // no object specified: Draw from fctBlit @@ -937,7 +1016,7 @@ void C4GraphicsOverlay::Draw(C4TargetFacet &cgo, C4Object *pForObj, int32_t iByP fctBlit.DrawT(cgo.Surface, offX - fctBlit.Wdt/2 + fctBlit.TargetX, offY - fctBlit.Hgt/2 + fctBlit.TargetY, iPhase, 0, &trf); } - else if(eMode == MODE_Base || eMode == MODE_Action) + else { C4Def *pDef = pSourceGfx->pDef; @@ -958,34 +1037,6 @@ void C4GraphicsOverlay::Draw(C4TargetFacet &cgo, C4Object *pForObj, int32_t iByP pDraw->RenderMesh(*pMeshInstance, cgo.Surface, offX - pDef->Shape.Wdt/2.0, offY - pDef->Shape.Hgt/2.0, pDef->Shape.Wdt, pDef->Shape.Hgt, pForObj->Color, &trf); pDraw->SetMeshTransform(NULL); } - else - { - C4Def *pDef = pSourceGfx->pDef; - - float twdt, thgt; - if (fZoomToShape) - { - twdt = pForObj->Shape.Wdt; - thgt = pForObj->Shape.Hgt; - } - else - { - twdt = pDef->Shape.Wdt; - thgt = pDef->Shape.Hgt; - } - - C4Value value; - pDef->GetProperty(P_PictureTransformation, &value); - StdMeshMatrix matrix; - if (C4ValueToMatrix(value, &matrix)) - pDraw->SetMeshTransform(&matrix); - - C4DrawTransform trf(Transform, offX, offY); - pDraw->SetPerspective(true); - pDraw->RenderMesh(*pMeshInstance, cgo.Surface, offX - twdt/2, offY - thgt/2, twdt, thgt, pForObj->Color, &trf); - pDraw->SetPerspective(false); - pDraw->SetMeshTransform(NULL); - } } // cleanup @@ -1022,8 +1073,7 @@ void C4GraphicsOverlay::DrawRankSymbol(C4Facet &cgo, C4Object *rank_obj) void C4GraphicsOverlay::DrawPicture(C4Facet &cgo, C4Object *pForObj, C4DrawTransform* trans) { assert(IsPicture()); - // update object color - if (pForObj && fctBlit.Surface) fctBlit.Surface->SetClr(pForObj->Color); + // special blit mode if (dwBlitMode == C4GFXBLIT_PARENT) { @@ -1037,38 +1087,16 @@ void C4GraphicsOverlay::DrawPicture(C4Facet &cgo, C4Object *pForObj, C4DrawTrans if (pMeshInstance) pMeshInstance->SetFaceOrderingForClrModulation(dwClrModulation); } - // draw at given rect - if (!pMeshInstance) - { - // the picture we are rendering is the one with trans applied, and the overlay transformation - // is applied to the picture we are rendering, so apply it afterwards. Note that - // C4BltTransform::operator*= does this = other * this. - C4DrawTransform trf(Transform, cgo.X+float(cgo.Wdt)/2, cgo.Y+float(cgo.Hgt)/2); - if(trans) trf *= *trans; - fctBlit.DrawT(cgo, true, iPhase, 0, &trf); - } - else - { - C4Def *pDef = pSourceGfx->pDef; + // the picture we are rendering is the one with trans applied, and the overlay transformation + // is applied to the picture we are rendering, so apply it afterwards. Note that + // C4BltTransform::operator*= does this = other * this. + C4DrawTransform trf(Transform, cgo.X + cgo.Wdt/2.0f, cgo.Y + cgo.Hgt/2.0f); + if(trans) trf *= *trans; - C4Value value; - pDef->GetProperty(P_PictureTransformation, &value); - StdMeshMatrix matrix; - if (C4ValueToMatrix(value, &matrix)) - pDraw->SetMeshTransform(&matrix); + // Don't set pForObj because we don't draw the picture of pForObj, but the picture of another definition on top of pForObj: + pSourceGfx->Draw(cgo, pForObj->Color, NULL, iPhase, 0, &trf); - // the picture we are rendering is the one with trans applied, and the overlay transformation - // is applied to the picture we are rendering, so apply it afterwards. Note that - // C4BltTransform::operator*= does this = other * this. - C4DrawTransform trf(Transform, cgo.X+float(pForObj->Shape.Wdt)/2, cgo.Y+float(pForObj->Shape.Hgt)/2); - if(trans) trf *= *trans; - - pDraw->SetPerspective(true); - pDraw->RenderMesh(*pMeshInstance, cgo.Surface, cgo.X, cgo.Y, pForObj->Shape.Wdt, pForObj->Shape.Hgt, pForObj->Color, &trf); - pDraw->SetPerspective(false); - pDraw->SetMeshTransform(NULL); - } // cleanup if (dwBlitMode == C4GFXBLIT_PARENT) { @@ -1081,7 +1109,6 @@ void C4GraphicsOverlay::DrawPicture(C4Facet &cgo, C4Object *pForObj, C4DrawTrans } } - bool C4GraphicsOverlay::operator == (const C4GraphicsOverlay &rCmp) const { // compare relevant fields diff --git a/src/game/object/C4DefGraphics.h b/src/game/object/C4DefGraphics.h index 7f597c520..655a158dd 100644 --- a/src/game/object/C4DefGraphics.h +++ b/src/game/object/C4DefGraphics.h @@ -81,6 +81,8 @@ public: { return Type == TYPE_Mesh || !!Bmp.BitmapClr; } // Mesh can always apply PlayerColor (if used in its material) bool CopyGraphicsFrom(C4DefGraphics &rSource); // copy bitmaps from source graphics + void Draw(C4Facet &cgo, DWORD iColor, C4Object *pObj, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform* trans); + virtual const char *GetName() { return NULL; } // return name to be stored in safe game files C4AdditionalDefGraphics *GetNext() { return pNext; } diff --git a/src/game/object/C4Object.cpp b/src/game/object/C4Object.cpp index a878d9a07..fac64c1a0 100644 --- a/src/game/object/C4Object.cpp +++ b/src/game/object/C4Object.cpp @@ -249,7 +249,7 @@ bool C4Object::Init(C4PropList *pDef, C4Object *pCreator, pGraphics = &Def->Graphics; if (pGraphics->Type == C4DefGraphics::TYPE_Mesh) { - pMeshInstance = new StdMeshInstance(*pGraphics->Mesh); + pMeshInstance = new StdMeshInstance(*pGraphics->Mesh, Def->GrowthType ? 1.0f : static_cast(Con)/static_cast(FullCon)); pMeshInstance->SetFaceOrderingForClrModulation(ColorMod); } else @@ -487,7 +487,7 @@ void C4Object::UpdateGraphics(bool fGraphicsChanged, bool fTemp) delete pMeshInstance; if (pGraphics->Type == C4DefGraphics::TYPE_Mesh) { - pMeshInstance = new StdMeshInstance(*pGraphics->Mesh); + pMeshInstance = new StdMeshInstance(*pGraphics->Mesh, Def->GrowthType ? 1.0f : static_cast(Con)/static_cast(FullCon)); pMeshInstance->SetFaceOrderingForClrModulation(ColorMod); } else @@ -1333,7 +1333,9 @@ void C4Object::DoCon(int32_t iChange) // Con Zero Removal if (Con<=0) AssignRemoval(); - + // Mesh Graphics Update + else if(pMeshInstance) + pMeshInstance->SetCompletion(Def->GrowthType ? 1.0f : static_cast(Con)/static_cast(FullCon)); } void C4Object::DoExperience(int32_t change) @@ -2238,37 +2240,40 @@ void C4Object::DrawTopFace(C4TargetFacet &cgo, int32_t iByPlayer, DrawMode eDraw offX + Shape.GetX(), offY + Shape.GetY() + Shape.Hgt - fctConSign.Hgt, fctConSign.Wdt, fctConSign.Hgt, true); } - // FacetTopFace: Override TopFace.GetX()/GetY() - C4PropList* pActionDef = GetAction(); - if (pActionDef && pActionDef->GetPropertyInt(P_FacetTopFace)) + if(TopFace.Surface) { - int32_t iPhase = Action.Phase; - if (pActionDef->GetPropertyInt(P_Reverse)) iPhase = pActionDef->GetPropertyInt(P_Length) - 1 - Action.Phase; - TopFace.X = pActionDef->GetPropertyInt(P_X) + Def->TopFace.x + pActionDef->GetPropertyInt(P_Wdt) * iPhase; - TopFace.Y = pActionDef->GetPropertyInt(P_Y) + Def->TopFace.y + pActionDef->GetPropertyInt(P_Hgt) * Action.DrawDir; + // FacetTopFace: Override TopFace.GetX()/GetY() + C4PropList* pActionDef = GetAction(); + if (pActionDef && pActionDef->GetPropertyInt(P_FacetTopFace)) + { + int32_t iPhase = Action.Phase; + if (pActionDef->GetPropertyInt(P_Reverse)) iPhase = pActionDef->GetPropertyInt(P_Length) - 1 - Action.Phase; + TopFace.X = pActionDef->GetPropertyInt(P_X) + Def->TopFace.x + pActionDef->GetPropertyInt(P_Wdt) * iPhase; + TopFace.Y = pActionDef->GetPropertyInt(P_Y) + Def->TopFace.y + pActionDef->GetPropertyInt(P_Hgt) * Action.DrawDir; + } + // ensure correct color is set + if (GetGraphics()->Bmp.BitmapClr) GetGraphics()->Bmp.BitmapClr->SetClr(Color); + // color modulation + if (!eDrawMode) PrepareDrawing(); + // Draw top face bitmap + if (Con!=FullCon && Def->GrowthType) + // stretched + pDraw->Blit(TopFace.Surface, + TopFace.X, TopFace.Y, TopFace.Wdt, TopFace.Hgt, + cgo.Surface, + offX + Shape.GetX() + float(Def->TopFace.tx * Con) / FullCon, offY + Shape.GetY() + float(Def->TopFace.ty * Con) / FullCon, + float(TopFace.Wdt * Con) / FullCon, float(TopFace.Hgt * Con) / FullCon, + true, pDrawTransform ? &C4DrawTransform(*pDrawTransform, offX, offY) : NULL); + else + // normal + pDraw->Blit(TopFace.Surface, + TopFace.X,TopFace.Y, + TopFace.Wdt,TopFace.Hgt, + cgo.Surface, + offX + Shape.GetX() + Def->TopFace.tx, offY + Shape.GetY() + Def->TopFace.ty, + TopFace.Wdt, TopFace.Hgt, + true, pDrawTransform ? &C4DrawTransform(*pDrawTransform, offX, offY) : NULL); } - // ensure correct color is set - if (GetGraphics()->Bmp.BitmapClr) GetGraphics()->Bmp.BitmapClr->SetClr(Color); - // color modulation - if (!eDrawMode) PrepareDrawing(); - // Draw top face bitmap - if (Con!=FullCon && Def->GrowthType) - // stretched - pDraw->Blit(TopFace.Surface, - TopFace.X, TopFace.Y, TopFace.Wdt, TopFace.Hgt, - cgo.Surface, - offX + Shape.GetX() + float(Def->TopFace.tx * Con) / FullCon, offY + Shape.GetY() + float(Def->TopFace.ty * Con) / FullCon, - float(TopFace.Wdt * Con) / FullCon, float(TopFace.Hgt * Con) / FullCon, - true, pDrawTransform ? &C4DrawTransform(*pDrawTransform, offX, offY) : NULL); - else - // normal - pDraw->Blit(TopFace.Surface, - TopFace.X,TopFace.Y, - TopFace.Wdt,TopFace.Hgt, - cgo.Surface, - offX + Shape.GetX() + Def->TopFace.tx, offY + Shape.GetY() + Def->TopFace.ty, - TopFace.Wdt, TopFace.Hgt, - true, pDrawTransform ? &C4DrawTransform(*pDrawTransform, offX, offY) : NULL); // end of color modulation if (!eDrawMode) FinishedDrawing(); } @@ -2372,7 +2377,7 @@ void C4Object::CompileFunc(StdCompiler *pComp, C4ValueNumbers * numbers) if(pComp->isCompiler()) { assert(!pMeshInstance); - pMeshInstance = new StdMeshInstance(*pGraphics->Mesh); + pMeshInstance = new StdMeshInstance(*pGraphics->Mesh, Def->GrowthType ? 1.0f : static_cast(Con)/static_cast(FullCon)); } pComp->Value(mkNamingAdapt(mkParAdapt(*pMeshInstance, C4MeshDenumeratorFactory), "Mesh")); diff --git a/src/game/script/C4GameScript.cpp b/src/game/script/C4GameScript.cpp index ccf94f23a..41e02bbd6 100644 --- a/src/game/script/C4GameScript.cpp +++ b/src/game/script/C4GameScript.cpp @@ -1589,16 +1589,18 @@ static long FnDrawMatChunks(C4AulContext *cctx, long tx, long ty, long twdt, lon return ::Landscape.DrawChunks(tx, ty, twdt, thgt, icntx, icnty, FnStringPar(strMaterial), FnStringPar(strTexture), bIFT != 0); } -static long FnDrawMap(C4AulContext *cctx, long iX, long iY, long iWdt, long iHgt, C4String *szMapDef, bool ignoreSky) +static long FnDrawMap(C4AulContext *cctx, long iX, long iY, long iWdt, long iHgt, C4String *szMapDef) { // draw it! - return ::Landscape.DrawMap(iX, iY, iWdt, iHgt, FnStringPar(szMapDef), ignoreSky); + // don't clear the old map before drawing + return ::Landscape.DrawMap(iX, iY, iWdt, iHgt, FnStringPar(szMapDef), true); } -static long FnDrawDefMap(C4AulContext *cctx, long iX, long iY, long iWdt, long iHgt, C4String *szMapDef, bool ignoreSky) +static long FnDrawDefMap(C4AulContext *cctx, long iX, long iY, long iWdt, long iHgt, C4String *szMapDef) { // draw it! - return ::Landscape.DrawDefMap(iX, iY, iWdt, iHgt, FnStringPar(szMapDef), ignoreSky); + // don't clear the old map before drawing + return ::Landscape.DrawDefMap(iX, iY, iWdt, iHgt, FnStringPar(szMapDef), true); } static bool FnCreateParticle(C4AulContext *cthr, C4String *szName, long iX, long iY, long iXDir, long iYDir, long a, long b, C4Object *pObj, bool fBack) diff --git a/src/game/script/C4Script.h b/src/game/script/C4Script.h index 4a082a495..ea77ce8a3 100644 --- a/src/game/script/C4Script.h +++ b/src/game/script/C4Script.h @@ -148,6 +148,7 @@ bool C4ValueToMatrix(const C4ValueArray& array, StdMeshMatrix* matrix); #define PSF_MouseSelection "~MouseSelection" // int iByPlr #define PSF_MouseSelectionAlt "~MouseSelectionAlt" // int iByPlr #define PSF_MouseDragDrop "~MouseDragDrop" // int iPlr, C4Object *source, C4Object *target +#define PSF_MouseHover "~MouseHover" // int iPlr, C4Object* old, C4Object* new, C4Object* drag // Proplist diff --git a/src/gui/C4GfxErrorDlg.cpp b/src/gui/C4GfxErrorDlg.cpp new file mode 100644 index 000000000..f3e250d68 --- /dev/null +++ b/src/gui/C4GfxErrorDlg.cpp @@ -0,0 +1,153 @@ +/* + * OpenClonk, http://www.openclonk.org + * + * Copyright (c) 2012, Julius Michaelis + * + * Portions might be copyrighted by other authors who have contributed + * to OpenClonk. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * See isc_license.txt for full license and disclaimer. + * + * "Clonk" is a registered trademark of Matthes Bender. + * See clonk_trademark_license.txt for full license. + */ + +/* Functions for displaying a settings dialogue to users when the graphics system failed */ + +#include + +#ifdef _WIN32 + +#include +#include +#include +#include +#include + +static int edittext_toi(HWND hWnd, int field) +{ + WCHAR buf[512]; buf[511] = 0; + GetDlgItemTextW(hWnd,field,buf,509); + StdStrBuf data(buf); + const char* bufp = data.getData(); + while(*bufp == ' ') ++bufp; + int res = strtol(bufp, NULL, 0); + if(errno != ERANGE) + return res; + return -1; +} + +static INT_PTR CALLBACK GfxErrProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + switch(Msg) + { + case WM_INITDIALOG: + // Set Icon, Caption and static Texts + SendMessage(hWnd,WM_SETICON,ICON_BIG,(LPARAM)LoadIcon(Application.GetInstance(),MAKEINTRESOURCE(IDI_00_C4X))); + SendMessage(hWnd,WM_SETICON,ICON_SMALL,(LPARAM)LoadIcon(Application.GetInstance(),MAKEINTRESOURCE(IDI_00_C4X))); + SetWindowTextW(hWnd, GetWideChar(C4ENGINECAPTION)); + SetDlgItemTextW(hWnd,IDC_GFXERR_MSG ,GetWideChar(LoadResStr("IDS_MSG_GFXERR_TXT"))); + SetDlgItemTextW(hWnd,IDC_GFXERR_RES ,GetWideChar(LoadResStr("IDS_CTL_RESOLUTION"))); + SetDlgItemTextW(hWnd,IDC_GFXERR_FSCRN,GetWideChar(LoadResStr("IDS_MSG_FULLSCREEN"))); + SetDlgItemTextW(hWnd,IDCANCEL ,GetWideChar(LoadResStr("IDS_DLG_EXIT"))); + SetDlgItemTextW(hWnd,IDOK ,GetWideChar(LoadResStr("IDS_BTN_RESTART"))); + // Set Options + SendMessage(GetDlgItem(hWnd, IDC_GFXERR_FSCRN), BM_SETCHECK, Config.Graphics.Windowed?0:1, 0); + SetDlgItemTextW(hWnd,IDC_GFXERR_XINP ,FormatString("%d",Config.Graphics.ResX).GetWideChar()); + SetDlgItemTextW(hWnd,IDC_GFXERR_YINP ,FormatString("%d",Config.Graphics.ResY).GetWideChar()); + return TRUE; + + case WM_DESTROY: + EndDialog(hWnd,1); + return TRUE; + + case WM_COMMAND: + { + switch(LOWORD(wParam)) + { + case IDCANCEL: + EndDialog(hWnd,1); + return TRUE; + case IDC_GFXERR_FSCRN: + case IDC_GFXERR_XINP: + case IDC_GFXERR_YINP: + { // Handle Resolution values + if(SendMessage(GetDlgItem(hWnd, IDC_GFXERR_FSCRN),BM_GETCHECK,0,0) == BST_CHECKED) + { + int resx = edittext_toi(hWnd,IDC_GFXERR_XINP); + int resy = edittext_toi(hWnd,IDC_GFXERR_YINP); + if(resx < 1 || resy < 1) // res. will be 0 if the user supplies an invalid value + SetDlgItemTextW(hWnd,IDC_GFXERR_INVAL,GetWideChar(LoadResStr("IDS_MSG_GFXERR_RESINVAL"))); + else + { + // Check if res is in list of supportet + bool found = false; + int32_t idx = 0, iXRes, iYRes, iBitDepth; + while (Application.GetIndexedDisplayMode(idx++, &iXRes, &iYRes, &iBitDepth, NULL, Config.Graphics.Monitor)) + if (iBitDepth == Config.Graphics.BitDepth) + if(iXRes == resx && iYRes == resy) + { + found = true; + break; + } + SetDlgItemTextW(hWnd,IDC_GFXERR_INVAL,found?L"":GetWideChar(LoadResStr("IDS_MSG_GFXERR_RESNOTFOUND"))); + } + } + else + SetDlgItemTextW(hWnd,IDC_GFXERR_INVAL,L""); + return TRUE; + } + case IDOK: + { + int resx = edittext_toi(hWnd,IDC_GFXERR_XINP); + int resy = edittext_toi(hWnd,IDC_GFXERR_YINP); + if(resx < 1 || resy < 1) break; + Config.Graphics.Windowed = !(SendMessage(GetDlgItem(hWnd, IDC_GFXERR_FSCRN),BM_GETCHECK,0,0) == BST_CHECKED); + Config.Graphics.ResX = resx; + Config.Graphics.ResY = resy; + Config.Save(); + TCHAR selfpath[4096]; + GetModuleFileName(NULL, selfpath, 4096); + STARTUPINFOW siStartupInfo; + PROCESS_INFORMATION piProcessInfo; + memset(&siStartupInfo, 0, sizeof(siStartupInfo)); + memset(&piProcessInfo, 0, sizeof(piProcessInfo)); + siStartupInfo.cb = sizeof(siStartupInfo); + CreateProcessW(selfpath, L"", + NULL, NULL, FALSE, 0, NULL, Config.General.ExePath.GetWideChar(), &siStartupInfo, &piProcessInfo); + EndDialog(hWnd,2); + return TRUE; + } + } + } + } + return FALSE; +} + +void ShowGfxErrorDialog() +{ + int ret = DialogBox(Application.GetInstance(), MAKEINTRESOURCE(IDD_GFXERROR), NULL, GfxErrProcedure); + if (ret == 0 || ret == -1) + { + LPVOID lpMsgBuf; + DWORD err = GetLastError(); + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, NULL ); + LogF("Error in GfxErrorDlg: %d - %s", err, StdStrBuf((wchar_t*)lpMsgBuf).getData()); + LocalFree(lpMsgBuf); + } +} + +#else +void ShowGfxErrorDialog(){} // To be implemented? It's mainly a windows (users') problem. +#endif diff --git a/src/gui/C4GfxErrorDlg.h b/src/gui/C4GfxErrorDlg.h new file mode 100644 index 000000000..2c43d7f43 --- /dev/null +++ b/src/gui/C4GfxErrorDlg.h @@ -0,0 +1,11 @@ +/* + * OpenClonk, http://www.openclonk.org + * + * This file is ineligible for copyright and therefore in the public domain, + * because it does not reach the required threshold of originality. + * + * "Clonk" is a registered trademark of Matthes Bender. + * See clonk_trademark_license.txt for full license. + */ + +void ShowGfxErrorDialog(); diff --git a/src/gui/C4MouseControl.cpp b/src/gui/C4MouseControl.cpp index f3b2d2c19..9eaef1e51 100644 --- a/src/gui/C4MouseControl.cpp +++ b/src/gui/C4MouseControl.cpp @@ -575,80 +575,95 @@ void C4MouseControl::UpdateCursorTarget() { int32_t iLastCursor = Cursor; - // Scrolling: no other target - if (Scrolling) { TargetObject=NULL; return; } + C4Object* OldTargetObject = TargetObject; - // On target region - if (TargetRegion) + if (Scrolling) { + // Scrolling: no other target + TargetObject=NULL; + } + else if(TargetRegion) + { + // On target region TargetObject=NULL; if (Help) Cursor=C4MC_Cursor_Help; - return; - } - - // Target object - TargetObject=GetTargetObject(); - if (TargetObject && FogOfWar && !(TargetObject->Category & C4D_IgnoreFoW)) TargetObject = NULL; - - // Movement - if (!FogOfWar && !IsPassive()) Cursor=C4MC_Cursor_Crosshair; - - // Target action - if (TargetObject && !IsPassive()) - { - // default cursor for object; also set if not in FoW - Cursor=C4MC_Cursor_Crosshair; - - // select custom region. Can select an object if it does not have the MD_NoClick - // flag set. If we are currently dragging then selection depends on it being a drop target. - bool CanSelect; - if(Drag == C4MC_Drag_Script) - CanSelect = (TargetObject->GetPropertyInt(P_MouseDrag) & C4MC_MD_DropTarget) != 0; - else - CanSelect = (TargetObject->GetPropertyInt(P_MouseDrag) & C4MC_MD_NoClick) == 0; - - if ( (TargetObject->Category & C4D_MouseSelect) && CanSelect) - Cursor=C4MC_Cursor_Select; - else - TargetObject = NULL; - } - - // Help - if (Help) - Cursor=C4MC_Cursor_Help; - // passive cursor - else if (IsPassive()) - Cursor=C4MC_Cursor_Region; - - // Time on target: caption - if (Cursor==iLastCursor) - { - TimeOnTargetObject++; - if (TimeOnTargetObject>=C4MC_Time_on_Target) - { - const char* idCaption = 0; - const char *szName = ""; - bool fDouble = false; - if (TargetObject) szName=TargetObject->GetName(); - // Target caption by cursor - switch (Cursor) - { - case C4MC_Cursor_Select: idCaption="IDS_CON_SELECT"; break; - case C4MC_Cursor_Help: idCaption="IDS_CON_NAME"; break; - } - // Set caption - if (idCaption) if (!KeepCaption) - { - // Caption by cursor - Caption.Format(LoadResStr(idCaption), szName); - if (fDouble) { Caption.AppendChar('|'); Caption.Append(LoadResStr("IDS_CON_DOUBLECLICK")); } - IsHelpCaption = false; - } - } } else - TimeOnTargetObject=0; + { + // Target object + TargetObject=GetTargetObject(); + if (TargetObject && FogOfWar && !(TargetObject->Category & C4D_IgnoreFoW)) TargetObject = NULL; + // Movement + if (!FogOfWar && !IsPassive()) Cursor=C4MC_Cursor_Crosshair; + + // Target action + if (TargetObject && !IsPassive()) + { + // default cursor for object; also set if not in FoW + Cursor=C4MC_Cursor_Crosshair; + + // select custom region. Can select an object if it does not have the MD_NoClick + // flag set. If we are currently dragging then selection depends on it being a drop target. + bool CanSelect; + if(Drag == C4MC_Drag_Script) + CanSelect = (TargetObject->GetPropertyInt(P_MouseDrag) & C4MC_MD_DropTarget) != 0; + else + CanSelect = (TargetObject->GetPropertyInt(P_MouseDrag) & C4MC_MD_NoClick) == 0; + + if ( (TargetObject->Category & C4D_MouseSelect) && CanSelect) + Cursor=C4MC_Cursor_Select; + else + TargetObject = NULL; + } + + // Help + if (Help) + Cursor=C4MC_Cursor_Help; + // passive cursor + else if (IsPassive()) + Cursor=C4MC_Cursor_Region; + + // Time on target: caption + if (Cursor==iLastCursor) + { + TimeOnTargetObject++; + if (TimeOnTargetObject>=C4MC_Time_on_Target) + { + const char* idCaption = 0; + const char *szName = ""; + bool fDouble = false; + if (TargetObject) szName=TargetObject->GetName(); + // Target caption by cursor + switch (Cursor) + { + case C4MC_Cursor_Select: idCaption="IDS_CON_SELECT"; break; + case C4MC_Cursor_Help: idCaption="IDS_CON_NAME"; break; + } + // Set caption + if (idCaption) if (!KeepCaption) + { + // Caption by cursor + Caption.Format(LoadResStr(idCaption), szName); + if (fDouble) { Caption.AppendChar('|'); Caption.Append(LoadResStr("IDS_CON_DOUBLECLICK")); } + IsHelpCaption = false; + } + } + } + else + TimeOnTargetObject=0; + } + + // Make a script callback if the object being hovered changes + if(OldTargetObject != TargetObject) + { + // TODO: This might put a heavy load on the network, depending on the number of + // selectable objects around. If it turns out to be a problem we might want to + // deduce these hover callbacks client-side instead. + // Or, make sure to send this at most once per control frame. + Game.Input.Add(CID_Script, new C4ControlScript( + FormatString("%s(%d,Object(%d),Object(%d),Object(%d))", PSF_MouseHover, (int)Player, OldTargetObject ? (int)(OldTargetObject->Number) : 0, TargetObject ? (int)(TargetObject->Number) : 0, DragObject ? (int)(DragObject->Number) : 0).getData())); + } } int32_t C4MouseControl::UpdateSingleSelection() @@ -770,6 +785,7 @@ void C4MouseControl::LeftUp() { // Update status flag LeftButtonDown=false; + if(!RightButtonDown) DownTarget = NULL; // Ignore left up after double click if (LeftDoubleIgnoreUp) { LeftDoubleIgnoreUp=false; return; } // Evaluate by drag status @@ -824,8 +840,6 @@ void C4MouseControl::DragNone() if ( (LeftButtonDown || RightButtonDown) && ((Abs(GameX-DownX)>C4MC_DragSensitivity) || (Abs(GameY-DownY)>C4MC_DragSensitivity)) ) { - // don't begin dragging from FoW; unless it's a menu - if (FogOfWar && DownCursor != C4MC_Cursor_Region) return; bool fAllowDrag = true; switch (DownCursor) { @@ -842,21 +856,20 @@ void C4MouseControl::DragNone() break; } // check if target object allows scripted dragging - if (fAllowDrag && TargetObject) + if (fAllowDrag && DownTarget && (!FogOfWar || (DownTarget->Category & C4D_IgnoreFoW))) { C4Object *drag_image_obj; C4ID drag_image_id; // Drag only if MD_SOURCE is set and drag image is present - if ( (TargetObject->GetPropertyInt(P_MouseDrag) & C4MC_MD_DragSource) && - TargetObject->GetDragImage(&drag_image_obj, &drag_image_id)) - //if (TargetObject->GetDragImage(&drag_image_obj, &drag_image_id)) + if ( (DownTarget->GetPropertyInt(P_MouseDrag) & C4MC_MD_DragSource) && + DownTarget->GetDragImage(&drag_image_obj, &drag_image_id)) { Drag=C4MC_Drag_Script; if(drag_image_obj) DragImageObject = drag_image_obj; else DragImageDef = C4Id2Def(drag_image_id); - DragObject = TargetObject; + DragObject = DownTarget; } } @@ -906,6 +919,8 @@ void C4MouseControl::RightUp() { // Update status flag RightButtonDown=false; + if(!LeftButtonDown) DownTarget = NULL; + // Evaluate by drag status switch (Drag) { diff --git a/src/gui/C4UpdateDlg.cpp b/src/gui/C4UpdateDlg.cpp index 519db0619..850869d6f 100644 --- a/src/gui/C4UpdateDlg.cpp +++ b/src/gui/C4UpdateDlg.cpp @@ -295,7 +295,7 @@ bool C4UpdateDlg::ApplyUpdate(const char *strUpdateFile, bool fDeleteUpdate, C4G bool C4UpdateDlg::IsValidUpdate(const char *szVersion) { - StdStrBuf strVersion; strVersion.Format("%d.%d.%d.%d", C4XVER1, C4XVER2, C4XVER3, C4XVER4); + StdStrBuf strVersion; strVersion.Format("%d.%d.%d", C4XVER1, C4XVER2, C4XVER3); if (szVersion == NULL || strlen(szVersion) == 0) return false; return strcmp(szVersion,strVersion.getData()) != 0; } diff --git a/src/lib/StdMesh.cpp b/src/lib/StdMesh.cpp index 724bd242c..9cf7663e4 100644 --- a/src/lib/StdMesh.cpp +++ b/src/lib/StdMesh.cpp @@ -45,12 +45,19 @@ namespace // Helper to sort faces for FaceOrdering struct StdMeshInstanceFaceOrderingCmpPred { - const StdSubMeshInstance& m_inst; const StdMeshVertex* m_vertices; + StdSubMeshInstance::FaceOrdering m_face_ordering; const StdMeshMatrix& m_global_trans; - StdMeshInstanceFaceOrderingCmpPred(const StdSubMeshInstance& inst, const StdMeshMatrix& global_trans): - m_inst(inst), m_vertices(m_inst.GetVertices()), m_global_trans(global_trans) {} + StdMeshInstanceFaceOrderingCmpPred(const StdMeshInstance& mesh_inst, const StdSubMeshInstance& sub_inst, + StdSubMeshInstance::FaceOrdering face_ordering, const StdMeshMatrix& global_trans): + m_face_ordering(face_ordering), m_global_trans(global_trans) + { + if(sub_inst.GetNumVertices() > 0) + m_vertices = &sub_inst.GetVertices()[0]; + else + m_vertices = &mesh_inst.GetSharedVertices()[0]; + } inline float get_z(const StdMeshVertex& vtx) const { @@ -71,7 +78,7 @@ namespace int compare(const StdMeshFace& face1, const StdMeshFace& face2) const { // TODO: Need to apply attach matrix in case of attached meshes - switch (m_inst.GetFaceOrdering()) + switch (m_face_ordering) { case StdSubMeshInstance::FO_Fixed: assert(false); @@ -89,7 +96,7 @@ namespace float z1 = std::max(std::max(z11, z12), z13); float z2 = std::max(std::max(z21, z22), z23); - if (m_inst.GetFaceOrdering() == StdSubMeshInstance::FO_FarthestToNearest) + if (m_face_ordering == StdSubMeshInstance::FO_FarthestToNearest) return (z1 < z2 ? -1 : (z1 > z2 ? +1 : 0)); else return (z2 < z1 ? -1 : (z2 > z1 ? +1 : 0)); @@ -415,17 +422,39 @@ void StdMesh::PostInit() std::sort(SubMeshes.begin(), SubMeshes.end(), StdMeshSubMeshVisibilityCmpPred()); } -StdSubMeshInstance::StdSubMeshInstance(const StdSubMesh& submesh): - Vertices(submesh.GetNumVertices()), Faces(submesh.GetNumFaces()), +StdSubMeshInstance::StdSubMeshInstance(StdMeshInstance& instance, const StdSubMesh& submesh, float completion): + Vertices(submesh.GetNumVertices()), Material(NULL), CurrentFaceOrdering(FO_Fixed) { // Copy initial Vertices/Faces for (unsigned int i = 0; i < submesh.GetNumVertices(); ++i) Vertices[i] = submesh.GetVertex(i); + LoadFacesForCompletion(instance, submesh, completion); + + SetMaterial(submesh.GetMaterial()); +} + +void StdSubMeshInstance::LoadFacesForCompletion(StdMeshInstance& instance, const StdSubMesh& submesh, float completion) +{ + // First: Copy all faces + Faces.resize(submesh.GetNumFaces()); for (unsigned int i = 0; i < submesh.GetNumFaces(); ++i) Faces[i] = submesh.GetFace(i); - SetMaterial(submesh.GetMaterial()); + if(completion < 1.0f) + { + // Second: Order by Y position. StdMeshInstanceFaceOrderingCmpPred orders by Z position, + // however we can simply give an appropriate transformation matrix to the face ordering. + // At this point, all vertices are in the OGRE coordinate frame, and Z in OGRE equals + // Y in Clonk, so we are fine without additional transformation. + StdMeshInstanceFaceOrderingCmpPred pred(instance, *this, FO_FarthestToNearest, StdMeshMatrix::Identity()); + g_pred = &pred; + StdMesh_tim_sort(&Faces[0], Faces.size()); + g_pred = NULL; + + // Third: Only use the first few ones + Faces.resize(static_cast(completion * submesh.GetNumFaces() + 0.5)); + } } void StdSubMeshInstance::SetMaterial(const StdMeshMaterial& material) @@ -696,16 +725,21 @@ void StdMeshInstance::AttachedMesh::DenumeratePointers() ChildDenumerator->DenumeratePointers(this); } -StdMeshInstance::StdMeshInstance(const StdMesh& mesh): - Mesh(&mesh), +StdMeshInstance::StdMeshInstance(const StdMesh& mesh, float completion): + Mesh(&mesh), SharedVertices(mesh.GetSharedVertices().size()), Completion(completion), BoneTransforms(Mesh->GetNumBones(), StdMeshMatrix::Identity()), SubMeshInstances(Mesh->GetNumSubMeshes()), AttachParent(NULL), BoneTransformsDirty(false) { + // Copy initial shared vertices + for (unsigned int i = 0; i < SharedVertices.size(); ++i) + SharedVertices[i] = mesh.GetSharedVertices()[i]; + + // Create submesh instances for (unsigned int i = 0; i < Mesh->GetNumSubMeshes(); ++i) { const StdSubMesh& submesh = Mesh->GetSubMesh(i); - SubMeshInstances[i] = new StdSubMeshInstance(submesh); + SubMeshInstances[i] = new StdSubMeshInstance(*this, submesh, completion); } } @@ -752,6 +786,16 @@ void StdMeshInstance::SetFaceOrderingForClrModulation(uint32_t clrmod) (*iter)->Child->SetFaceOrderingForClrModulation(clrmod); } +void StdMeshInstance::SetCompletion(float completion) +{ + Completion = completion; + + // TODO: Load all submesh faces and then determine the ones to use from the + // full pool. + for(unsigned int i = 0; i < Mesh->GetNumSubMeshes(); ++i) + SubMeshInstances[i]->LoadFacesForCompletion(*this, Mesh->GetSubMesh(i), completion); +} + StdMeshInstance::AnimationNode* StdMeshInstance::PlayAnimation(const StdStrBuf& animation_name, int slot, AnimationNode* sibling, ValueProvider* position, ValueProvider* weight) { const StdMeshAnimation* animation = Mesh->GetAnimationByName(animation_name); @@ -965,7 +1009,7 @@ void StdMeshInstance::ExecuteAnimation(float dt) StdMeshInstance::AttachedMesh* StdMeshInstance::AttachMesh(const StdMesh& mesh, AttachedMesh::Denumerator* denumerator, const StdStrBuf& parent_bone, const StdStrBuf& child_bone, const StdMeshMatrix& transformation, uint32_t flags) { - StdMeshInstance* instance = new StdMeshInstance(mesh); + StdMeshInstance* instance = new StdMeshInstance(mesh, 1.0f); AttachedMesh* attach = AttachMesh(*instance, denumerator, parent_bone, child_bone, transformation, flags, true); if (!attach) { delete instance; delete denumerator; return NULL; } return attach; @@ -1082,34 +1126,14 @@ bool StdMeshInstance::UpdateBoneTransforms() // Compute transformation for each vertex. We could later think about // doing this on the GPU using a vertex shader. This would then probably // need to go to CStdGL::PerformMesh and CStdD3D::PerformMesh. - // (can only work for fixed face ordering though) + // But first, we need to move vertex data to the GPU. + if(!Mesh->GetSharedVertices().empty()) + ApplyBoneTransformToVertices(Mesh->GetSharedVertices(), SharedVertices); for (unsigned int i = 0; i < SubMeshInstances.size(); ++i) { const StdSubMesh& submesh = Mesh->GetSubMesh(i); - std::vector& instance_vertices = SubMeshInstances[i]->Vertices; - assert(submesh.GetNumVertices() == instance_vertices.size()); - for (unsigned int j = 0; j < instance_vertices.size(); ++j) - { - const StdSubMesh::Vertex& vertex = submesh.GetVertex(j); - StdMeshVertex& instance_vertex = instance_vertices[j]; - if (!vertex.BoneAssignments.empty()) - { - instance_vertex.x = instance_vertex.y = instance_vertex.z = 0.0f; - instance_vertex.nx = instance_vertex.ny = instance_vertex.nz = 0.0f; - instance_vertex.u = vertex.u; instance_vertex.v = vertex.v; - - for (unsigned int k = 0; k < vertex.BoneAssignments.size(); ++k) - { - const StdMeshVertexBoneAssignment& assignment = vertex.BoneAssignments[k]; - - instance_vertex += assignment.Weight * (BoneTransforms[assignment.BoneIndex] * vertex); - } - } - else - { - instance_vertex = vertex; - } - } + if(!submesh.GetVertices().empty()) + ApplyBoneTransformToVertices(submesh.GetVertices(), SubMeshInstances[i]->Vertices); } } @@ -1156,7 +1180,7 @@ void StdMeshInstance::ReorderFaces(StdMeshMatrix* global_trans) StdSubMeshInstance& inst = *SubMeshInstances[i]; if(inst.CurrentFaceOrdering != StdSubMeshInstance::FO_Fixed) { - StdMeshInstanceFaceOrderingCmpPred pred(inst, global_trans ? *global_trans : StdMeshMatrix::Identity()); + StdMeshInstanceFaceOrderingCmpPred pred(*this, inst, inst.CurrentFaceOrdering, global_trans ? *global_trans : StdMeshMatrix::Identity()); // The usage of timsort instead of std::sort at this point is twofold. // First, it's faster in our case where the array is already sorted in @@ -1312,6 +1336,9 @@ bool StdMeshInstance::ExecuteAnimationNode(AnimationNode* node) min = Fix0; max = itofix(1); break; + default: + assert(false); + break; } const C4Real old_value = provider->Value; @@ -1334,8 +1361,6 @@ bool StdMeshInstance::ExecuteAnimationNode(AnimationNode* node) // Remove right child as it has less weight StopAnimation(node->LinearInterpolation.ChildRight); } - - } else { @@ -1365,3 +1390,28 @@ bool StdMeshInstance::ExecuteAnimationNode(AnimationNode* node) return true; } +void StdMeshInstance::ApplyBoneTransformToVertices(const std::vector& mesh_vertices, std::vector& instance_vertices) +{ + assert(mesh_vertices.size() == instance_vertices.size()); + for (unsigned int j = 0; j < instance_vertices.size(); ++j) + { + const StdSubMesh::Vertex& vertex = mesh_vertices[j]; + StdMeshVertex& instance_vertex = instance_vertices[j]; + if (!vertex.BoneAssignments.empty()) + { + instance_vertex.x = instance_vertex.y = instance_vertex.z = 0.0f; + instance_vertex.nx = instance_vertex.ny = instance_vertex.nz = 0.0f; + instance_vertex.u = vertex.u; instance_vertex.v = vertex.v; + + for (unsigned int k = 0; k < vertex.BoneAssignments.size(); ++k) + { + const StdMeshVertexBoneAssignment& assignment = vertex.BoneAssignments[k]; + instance_vertex += assignment.Weight * (BoneTransforms[assignment.BoneIndex] * vertex); + } + } + else + { + instance_vertex = vertex; + } + } +} diff --git a/src/lib/StdMesh.h b/src/lib/StdMesh.h index 2d8ff320a..9de6b382e 100644 --- a/src/lib/StdMesh.h +++ b/src/lib/StdMesh.h @@ -127,6 +127,7 @@ public: std::vector BoneAssignments; }; + const std::vector& GetVertices() const { return Vertices; } const Vertex& GetVertex(size_t i) const { return Vertices[i]; } size_t GetNumVertices() const { return Vertices.size(); } @@ -138,7 +139,7 @@ public: private: StdSubMesh(); - std::vector Vertices; + std::vector Vertices; // Empty if we use shared vertices std::vector Faces; const StdMeshMaterial* Material; @@ -154,9 +155,13 @@ class StdMesh public: ~StdMesh(); + typedef StdSubMesh::Vertex Vertex; + const StdSubMesh& GetSubMesh(size_t i) const { return SubMeshes[i]; } size_t GetNumSubMeshes() const { return SubMeshes.size(); } + const std::vector& GetSharedVertices() const { return SharedVertices; } + const StdMeshBone& GetBone(size_t i) const { return *Bones[i]; } size_t GetNumBones() const { return Bones.size(); } const StdMeshBone* GetBoneByName(const StdStrBuf& name) const; @@ -176,6 +181,8 @@ private: StdMesh(const StdMesh& other); // non-copyable StdMesh& operator=(const StdMesh& other); // non-assignable + std::vector SharedVertices; + std::vector SubMeshes; std::vector Bones; // Master Bone Table @@ -198,11 +205,12 @@ public: FO_NearestToFarthest }; - StdSubMeshInstance(const StdSubMesh& submesh); + StdSubMeshInstance(class StdMeshInstance& instance, const StdSubMesh& submesh, float completion); + void LoadFacesForCompletion(class StdMeshInstance& instance, const StdSubMesh& submesh, float completion); // Get vertex of instance, with current animation applied. This needs to // go elsewhere if/when we want to calculate this on the hardware. - const StdMeshVertex* GetVertices() const { return &Vertices[0]; } + const std::vector& GetVertices() const { return Vertices; } size_t GetNumVertices() const { return Vertices.size(); } // Get face of instance. The instance faces are the same as the mesh faces, @@ -264,14 +272,15 @@ class StdMeshInstance friend class StdMeshMaterialUpdate; friend class StdMeshUpdate; public: - StdMeshInstance(const StdMesh& mesh); + StdMeshInstance(const StdMesh& mesh, float completion = 1.0f); ~StdMeshInstance(); typedef StdSubMeshInstance::FaceOrdering FaceOrdering; - //FaceOrdering GetFaceOrdering() const { return CurrentFaceOrdering; } - void SetFaceOrdering(FaceOrdering ordering); - void SetFaceOrderingForClrModulation(uint32_t clrmod); + enum AttachMeshFlags { + AM_None = 0, + AM_DrawBefore = 1 << 0 + }; // Provider for animation position or weight. class ValueProvider @@ -412,27 +421,6 @@ public: }; }; - AnimationNode* PlayAnimation(const StdStrBuf& animation_name, int slot, AnimationNode* sibling, ValueProvider* position, ValueProvider* weight); - AnimationNode* PlayAnimation(const StdMeshAnimation& animation, int slot, AnimationNode* sibling, ValueProvider* position, ValueProvider* weight); - void StopAnimation(AnimationNode* node); - - AnimationNode* GetAnimationNodeByNumber(unsigned int number); - AnimationNode* GetRootAnimationForSlot(int slot); - // child bone transforms are dirty (saves matrix inversion for unanimated attach children). - // Set new value providers for a node's position or weight - cannot be in - // class AnimationNode since we need to mark BoneTransforms dirty. - void SetAnimationPosition(AnimationNode* node, ValueProvider* position); - void SetAnimationWeight(AnimationNode* node, ValueProvider* weight); - - // Update animations; call once a frame - // dt is used for texture animation, skeleton animation is updated via value providers - void ExecuteAnimation(float dt); - - enum AttachMeshFlags { - AM_None = 0, - AM_DrawBefore = 1 << 0 - }; - class AttachedMesh { friend class StdMeshInstance; @@ -487,6 +475,33 @@ public: typedef std::vector AttachedMeshList; typedef AttachedMeshList::const_iterator AttachedMeshIter; + //FaceOrdering GetFaceOrdering() const { return CurrentFaceOrdering; } + void SetFaceOrdering(FaceOrdering ordering); + void SetFaceOrderingForClrModulation(uint32_t clrmod); + + const std::vector& GetSharedVertices() const { return SharedVertices; } + size_t GetNumSharedVertices() const { return SharedVertices.size(); } + + // Set completion of the mesh. For incompleted meshes not all faces will be available. + void SetCompletion(float completion); + float GetCompletion() const { return Completion; } + + AnimationNode* PlayAnimation(const StdStrBuf& animation_name, int slot, AnimationNode* sibling, ValueProvider* position, ValueProvider* weight); + AnimationNode* PlayAnimation(const StdMeshAnimation& animation, int slot, AnimationNode* sibling, ValueProvider* position, ValueProvider* weight); + void StopAnimation(AnimationNode* node); + + AnimationNode* GetAnimationNodeByNumber(unsigned int number); + AnimationNode* GetRootAnimationForSlot(int slot); + // child bone transforms are dirty (saves matrix inversion for unanimated attach children). + // Set new value providers for a node's position or weight - cannot be in + // class AnimationNode since we need to mark BoneTransforms dirty. + void SetAnimationPosition(AnimationNode* node, ValueProvider* position); + void SetAnimationWeight(AnimationNode* node, ValueProvider* weight); + + // Update animations; call once a frame + // dt is used for texture animation, skeleton animation is updated via value providers + void ExecuteAnimation(float dt); + // Create a new instance and attach it to this mesh. Takes ownership of denumerator AttachedMesh* AttachMesh(const StdMesh& mesh, AttachedMesh::Denumerator* denumerator, const StdStrBuf& parent_bone, const StdStrBuf& child_bone, const StdMeshMatrix& transformation = StdMeshMatrix::Identity(), uint32_t flags = AM_None); // Attach an instance to this instance. Takes ownership of denumerator. If own_child is true deletes instance on detach. @@ -536,9 +551,14 @@ protected: AnimationNodeList::iterator GetStackIterForSlot(int slot, bool create); bool ExecuteAnimationNode(AnimationNode* node); + void ApplyBoneTransformToVertices(const std::vector& mesh_vertices, std::vector& instance_vertices); const StdMesh* Mesh; + float Completion; // NoSave + + std::vector SharedVertices; + AnimationNodeList AnimationNodes; // for simple lookup of animation nodes by their unique number AnimationNodeList AnimationStack; // contains top level nodes only, ordered by slot number std::vector BoneTransforms; diff --git a/src/lib/StdMeshLoader.h b/src/lib/StdMeshLoader.h index e91f8cfec..6385f3b51 100644 --- a/src/lib/StdMeshLoader.h +++ b/src/lib/StdMeshLoader.h @@ -39,7 +39,8 @@ public: class StdMeshLoader { public: -class LoaderException : public std::runtime_error { public: LoaderException(const char *msg) : std::runtime_error(msg) {} }; + class StdMeshXML; + class LoaderException : public std::runtime_error { public: LoaderException(const char *msg) : std::runtime_error(msg) {} }; // filename is only used to show it in error messages. The model is // loaded from src. Throws LoaderException. diff --git a/src/lib/StdMeshLoaderBinary.cpp b/src/lib/StdMeshLoaderBinary.cpp index de3fc8ef1..fbf2befff 100644 --- a/src/lib/StdMeshLoaderBinary.cpp +++ b/src/lib/StdMeshLoaderBinary.cpp @@ -33,7 +33,7 @@ namespace { - bool VertexDeclarationIsSane(const boost::ptr_vector &decl) + bool VertexDeclarationIsSane(const boost::ptr_vector &decl, const char *filename) { bool semanticSeen[Ogre::Mesh::ChunkGeometryVertexDeclElement::VDES_MAX + 1] = { false }; BOOST_FOREACH(Ogre::Mesh::ChunkGeometryVertexDeclElement element, decl) @@ -43,6 +43,11 @@ namespace case Ogre::Mesh::ChunkGeometryVertexDeclElement::VDES_Texcoords: // Normally, you can use multiple texture coordinates, but we currently support only one. // So complain if we get multiple sets. + if (semanticSeen[element.semantic]) + { + DebugLogF("[FIXME] %s: Vertex declaration with multiple sets of texture coordinates found; game will only use the first.", filename && *filename ? filename : ""); + } + break; case Ogre::Mesh::ChunkGeometryVertexDeclElement::VDES_Position: case Ogre::Mesh::ChunkGeometryVertexDeclElement::VDES_Normals: case Ogre::Mesh::ChunkGeometryVertexDeclElement::VDES_Diffuse: @@ -93,9 +98,9 @@ namespace } } - std::vector ReadSubmeshGeometry(const Ogre::Mesh::ChunkGeometry &geo) + std::vector ReadSubmeshGeometry(const Ogre::Mesh::ChunkGeometry &geo, const char *filename) { - if (!VertexDeclarationIsSane(geo.vertexDeclaration)) + if (!VertexDeclarationIsSane(geo.vertexDeclaration, filename)) throw Ogre::Mesh::InvalidVertexDeclaration(); // Get maximum size of a vertex according to the declaration @@ -144,6 +149,7 @@ namespace vertex.nx = vertex.ny = vertex.nz = 0; vertex.x = vertex.y = vertex.z = 0; vertex.u = vertex.v = 0; + bool read_tex = false; // Read vertex declaration BOOST_FOREACH(Ogre::Mesh::ChunkGeometryVertexDeclElement element, geo.vertexDeclaration) { @@ -162,8 +168,11 @@ namespace vertex.nz = values[2]; break; case Ogre::Mesh::ChunkGeometryVertexDeclElement::VDES_Texcoords: - vertex.u = values[0]; - vertex.v = values[1]; + if (!read_tex) { + vertex.u = values[0]; + vertex.v = values[1]; + read_tex = true; + } break; default: // We ignore unhandled element semantics. @@ -242,7 +251,7 @@ StdMesh *StdMeshLoader::LoadMeshBinary(const char *src, size_t length, const Std sm.Faces[face].Vertices[2] = csm.faceVertices[face * 3 + 2]; } Ogre::Mesh::ChunkGeometry &geo = *(csm.hasSharedVertices ? cmesh.geometry : csm.geometry); - sm.Vertices = ReadSubmeshGeometry(geo); + sm.Vertices = ReadSubmeshGeometry(geo, filename); // Read bone assignments std::vector &boneAssignments = (csm.hasSharedVertices ? cmesh.boneAssignments : csm.boneAssignments); diff --git a/src/lib/StdMeshLoaderBinaryChunks.cpp b/src/lib/StdMeshLoaderBinaryChunks.cpp index 8a27cc65d..d94c70f12 100644 --- a/src/lib/StdMeshLoaderBinaryChunks.cpp +++ b/src/lib/StdMeshLoaderBinaryChunks.cpp @@ -417,12 +417,11 @@ namespace Ogre { name = stream->Read(); duration = stream->Read(); - while (Chunk::Peek(stream) == CID_Animation_Track) + while (!stream->AtEof() && Chunk::Peek(stream) == CID_Animation_Track) { Chunk *chunk = Chunk::Read(stream); assert(chunk->GetType() == CID_Animation_Track); tracks.push_back(static_cast(chunk)); - if (stream->AtEof()) break; } } diff --git a/src/lib/StdMeshLoaderXml.cpp b/src/lib/StdMeshLoaderXml.cpp index ef6838eb3..b17f34781 100644 --- a/src/lib/StdMeshLoaderXml.cpp +++ b/src/lib/StdMeshLoaderXml.cpp @@ -25,7 +25,7 @@ #include // Helper class to load things from an XML file with error checking -class StdMeshXML +class StdMeshLoader::StdMeshXML { public: StdMeshXML(const char* filename, const char* xml_data); @@ -36,6 +36,9 @@ public: TiXmlElement* RequireFirstChild(TiXmlElement* element, const char* child); + void LoadGeometry(StdMesh& mesh, std::vector& vertices, TiXmlElement* boneassignments_elem); + void LoadBoneAssignments(StdMesh& mesh, std::vector& vertices, TiXmlElement* boneassignments_elem); + void Error(const StdStrBuf& message, TiXmlElement* element) const; void Error(const StdStrBuf& message, int row) const; @@ -44,7 +47,7 @@ private: StdStrBuf FileName; }; -StdMeshXML::StdMeshXML(const char* filename, const char* xml_data): +StdMeshLoader::StdMeshXML::StdMeshXML(const char* filename, const char* xml_data): FileName(filename) { Document.Parse(xml_data); @@ -52,14 +55,14 @@ StdMeshXML::StdMeshXML(const char* filename, const char* xml_data): Error(StdStrBuf(Document.ErrorDesc()), Document.ErrorRow()); } -const char* StdMeshXML::RequireStrAttribute(TiXmlElement* element, const char* attribute) const +const char* StdMeshLoader::StdMeshXML::RequireStrAttribute(TiXmlElement* element, const char* attribute) const { const char* value = element->Attribute(attribute); if (!value) Error(FormatString("Element '%s' does not have attribute '%s'", element->Value(), attribute), element); return value; } -int StdMeshXML::RequireIntAttribute(TiXmlElement* element, const char* attribute) const +int StdMeshLoader::StdMeshXML::RequireIntAttribute(TiXmlElement* element, const char* attribute) const { int retval; if (element->QueryIntAttribute(attribute, &retval) != TIXML_SUCCESS) @@ -67,7 +70,7 @@ int StdMeshXML::RequireIntAttribute(TiXmlElement* element, const char* attribute return retval; } -float StdMeshXML::RequireFloatAttribute(TiXmlElement* element, const char* attribute) const +float StdMeshLoader::StdMeshXML::RequireFloatAttribute(TiXmlElement* element, const char* attribute) const { float retval = 0; if (element->QueryFloatAttribute(attribute, &retval) != TIXML_SUCCESS) @@ -75,7 +78,7 @@ float StdMeshXML::RequireFloatAttribute(TiXmlElement* element, const char* attri return retval; } -TiXmlElement* StdMeshXML::RequireFirstChild(TiXmlElement* element, const char* child) +TiXmlElement* StdMeshLoader::StdMeshXML::RequireFirstChild(TiXmlElement* element, const char* child) { TiXmlElement* retval; @@ -95,16 +98,148 @@ TiXmlElement* StdMeshXML::RequireFirstChild(TiXmlElement* element, const char* c return retval; } -void StdMeshXML::Error(const StdStrBuf& message, TiXmlElement* element) const +void StdMeshLoader::StdMeshXML::Error(const StdStrBuf& message, TiXmlElement* element) const { Error(message, element->Row()); } -void StdMeshXML::Error(const StdStrBuf& message, int row) const +void StdMeshLoader::StdMeshXML::Error(const StdStrBuf& message, int row) const { throw StdMeshLoader::LoaderException(FormatString("%s:%u: %s", FileName.getData(), row, message.getData()).getData()); } +void StdMeshLoader::StdMeshXML::LoadGeometry(StdMesh& mesh, std::vector& vertices, TiXmlElement* geometry_elem) +{ + // Check whether mesh has any vertices so far -- we need this later for + // initialization of bounding box and bounding sphere. + bool hasVertices = false; + if(!mesh.SharedVertices.empty()) hasVertices = true; + for(unsigned int i = 0; i < mesh.SubMeshes.size(); ++i) + if(!mesh.SubMeshes[i].Vertices.empty()) + hasVertices = true; + + int VertexCount = RequireIntAttribute(geometry_elem, "vertexcount"); + vertices.resize(VertexCount); + + static const unsigned int POSITIONS = 1; + static const unsigned int NORMALS = 2; + static const unsigned int TEXCOORDS = 4; + + // Individual vertex attributes can be split up in multiple vertex buffers + unsigned int loaded_attributes = 0; + for(TiXmlElement* buffer_elem = geometry_elem->FirstChildElement("vertexbuffer"); buffer_elem != NULL; buffer_elem = buffer_elem->NextSiblingElement("vertexbuffer")) + { + unsigned int attributes = 0; + if(buffer_elem->Attribute("positions")) attributes |= POSITIONS; + if(buffer_elem->Attribute("normals")) attributes |= NORMALS; + if(buffer_elem->Attribute("texture_coords")) attributes |= TEXCOORDS; + + unsigned int i; + TiXmlElement* vertex_elem; + for (vertex_elem = buffer_elem->FirstChildElement("vertex"), i = 0; vertex_elem != NULL && i < vertices.size(); vertex_elem = vertex_elem->NextSiblingElement("vertex"), ++i) + { + if(attributes & POSITIONS) + { + TiXmlElement* position_elem = RequireFirstChild(vertex_elem, "position"); + + vertices[i].x = RequireFloatAttribute(position_elem, "x"); + vertices[i].y = RequireFloatAttribute(position_elem, "y"); + vertices[i].z = RequireFloatAttribute(position_elem, "z"); + + const float d = std::sqrt(vertices[i].x*vertices[i].x + + vertices[i].y*vertices[i].y + + vertices[i].z*vertices[i].z); + + // Construct BoundingBox + StdMeshBox& BoundingBox = mesh.BoundingBox; + if (i == 0 && !hasVertices) + { + // First vertex + BoundingBox.x1 = BoundingBox.x2 = vertices[i].x; + BoundingBox.y1 = BoundingBox.y2 = vertices[i].y; + BoundingBox.z1 = BoundingBox.z2 = vertices[i].z; + mesh.BoundingRadius = d; + } + else + { + BoundingBox.x1 = Min(vertices[i].x, BoundingBox.x1); + BoundingBox.x2 = Max(vertices[i].x, BoundingBox.x2); + BoundingBox.y1 = Min(vertices[i].y, BoundingBox.y1); + BoundingBox.y2 = Max(vertices[i].y, BoundingBox.y2); + BoundingBox.z1 = Min(vertices[i].z, BoundingBox.z1); + BoundingBox.z2 = Max(vertices[i].z, BoundingBox.z2); + mesh.BoundingRadius = Max(mesh.BoundingRadius, d); + } + } + + if(attributes & NORMALS) + { + TiXmlElement* normal_elem = RequireFirstChild(vertex_elem, "normal"); + + vertices[i].nx = RequireFloatAttribute(normal_elem, "x"); + vertices[i].ny = RequireFloatAttribute(normal_elem, "y"); + vertices[i].nz = RequireFloatAttribute(normal_elem, "z"); + } + + if(attributes & TEXCOORDS) + { + TiXmlElement* texcoord_elem = RequireFirstChild(vertex_elem, "texcoord"); + vertices[i].u = RequireFloatAttribute(texcoord_elem, "u"); + vertices[i].v = RequireFloatAttribute(texcoord_elem, "v"); + } + } + + if(vertex_elem != NULL) + Error(FormatString("Too many vertices in vertexbuffer"), buffer_elem); + if(i < vertices.size()) + Error(FormatString("Not enough vertices in vertexbuffer"), buffer_elem); + + loaded_attributes |= attributes; + } + + static const unsigned int REQUIRED_ATTRIBUTES = POSITIONS | NORMALS | TEXCOORDS; + if((loaded_attributes & REQUIRED_ATTRIBUTES) != REQUIRED_ATTRIBUTES) + Error(FormatString("Not all required vertex attributes (positions, normals, texcoords) present in mesh geometry"), geometry_elem); +} + +void StdMeshLoader::StdMeshXML::LoadBoneAssignments(StdMesh& mesh, std::vector& vertices, TiXmlElement* boneassignments_elem) +{ + for (TiXmlElement* vertexboneassignment_elem = boneassignments_elem->FirstChildElement("vertexboneassignment"); vertexboneassignment_elem != NULL; vertexboneassignment_elem = vertexboneassignment_elem->NextSiblingElement("vertexboneassignment")) + { + int BoneID = RequireIntAttribute(vertexboneassignment_elem, "boneindex"); + int VertexIndex = RequireIntAttribute(vertexboneassignment_elem, "vertexindex"); + float weight = RequireFloatAttribute(vertexboneassignment_elem, "weight"); + + if (VertexIndex < 0 || static_cast(VertexIndex) >= vertices.size()) + Error(FormatString("Vertex index in bone assignment (%d) is out of range", VertexIndex), vertexboneassignment_elem); + + StdMeshBone* bone = NULL; + for (unsigned int i = 0; !bone && i < mesh.Bones.size(); ++i) + if (mesh.Bones[i]->ID == BoneID) + bone = mesh.Bones[i]; + + if (!bone) Error(FormatString("There is no such bone with ID %d", BoneID), vertexboneassignment_elem); + + StdSubMesh::Vertex& vertex = vertices[VertexIndex]; + vertex.BoneAssignments.push_back(StdMeshVertexBoneAssignment()); + StdMeshVertexBoneAssignment& assignment = vertex.BoneAssignments.back(); + assignment.BoneIndex = bone->Index; + assignment.Weight = weight; + } + + // Normalize vertex bone assignment weights (this is not guaranteed in the + // Ogre file format). + for (unsigned int i = 0; i < vertices.size(); ++i) + { + StdSubMesh::Vertex& vertex = vertices[i]; + float sum = 0.0f; + for (unsigned int j = 0; j < vertex.BoneAssignments.size(); ++j) + sum += vertex.BoneAssignments[j].Weight; + for (unsigned int j = 0; j < vertex.BoneAssignments.size(); ++j) + vertex.BoneAssignments[j].Weight /= sum; + } +} + StdMesh *StdMeshLoader::LoadMeshXml(const char* xml_data, size_t size, const StdMeshMatManager& manager, StdMeshSkeletonLoader& skel_loader, const char* filename) { StdMeshXML xml(filename ? filename : "", xml_data); @@ -112,13 +247,17 @@ StdMesh *StdMeshLoader::LoadMeshXml(const char* xml_data, size_t size, const Std std::auto_ptr mesh(new StdMesh); TiXmlElement* mesh_elem = xml.RequireFirstChild(NULL, "mesh"); + + // Load shared geometry, if any + TiXmlElement* sharedgeometry_elem = mesh_elem->FirstChildElement("sharedgeometry"); + if(sharedgeometry_elem != NULL) + xml.LoadGeometry(*mesh, mesh->SharedVertices, sharedgeometry_elem); + TiXmlElement* submeshes_elem = xml.RequireFirstChild(mesh_elem, "submeshes"); TiXmlElement* submesh_elem_base = xml.RequireFirstChild(submeshes_elem, "submesh"); for (TiXmlElement* submesh_elem = submesh_elem_base; submesh_elem != NULL; submesh_elem = submesh_elem->NextSiblingElement("submesh")) { - TiXmlElement* geometry_elem = xml.RequireFirstChild(submesh_elem, "geometry"); - mesh->SubMeshes.push_back(StdSubMesh()); StdSubMesh& submesh = mesh->SubMeshes.back(); @@ -127,88 +266,20 @@ StdMesh *StdMeshLoader::LoadMeshXml(const char* xml_data, size_t size, const Std if (!submesh.Material) xml.Error(FormatString("There is no such material named '%s'", material), submesh_elem); - int VertexCount = xml.RequireIntAttribute(geometry_elem, "vertexcount"); - submesh.Vertices.resize(VertexCount); - - static const unsigned int POSITIONS = 1; - static const unsigned int NORMALS = 2; - static const unsigned int TEXCOORDS = 4; - - // Individual vertex attributes can be split up in multiple vertex buffers - unsigned int loaded_attributes = 0; - for(TiXmlElement* buffer_elem = geometry_elem->FirstChildElement("vertexbuffer"); buffer_elem != NULL; buffer_elem = buffer_elem->NextSiblingElement("vertexbuffer")) + const char* usesharedvertices = submesh_elem->Attribute("usesharedvertices"); + const std::vector* vertices; + if(!usesharedvertices || strcmp(usesharedvertices, "true") != 0) { - unsigned int attributes = 0; - if(buffer_elem->Attribute("positions")) attributes |= POSITIONS; - if(buffer_elem->Attribute("normals")) attributes |= NORMALS; - if(buffer_elem->Attribute("texture_coords")) attributes |= TEXCOORDS; - - unsigned int i; - TiXmlElement* vertex_elem; - for (vertex_elem = buffer_elem->FirstChildElement("vertex"), i = 0; vertex_elem != NULL && i < submesh.Vertices.size(); vertex_elem = vertex_elem->NextSiblingElement("vertex"), ++i) - { - if(attributes & POSITIONS) - { - TiXmlElement* position_elem = xml.RequireFirstChild(vertex_elem, "position"); - - submesh.Vertices[i].x = xml.RequireFloatAttribute(position_elem, "x"); - submesh.Vertices[i].y = xml.RequireFloatAttribute(position_elem, "y"); - submesh.Vertices[i].z = xml.RequireFloatAttribute(position_elem, "z"); - - const float d = std::sqrt(submesh.Vertices[i].x*submesh.Vertices[i].x - + submesh.Vertices[i].y*submesh.Vertices[i].y - + submesh.Vertices[i].z*submesh.Vertices[i].z); - - // Construct BoundingBox - StdMeshBox &BoundingBox = mesh->BoundingBox; - if (i == 0 && mesh->SubMeshes.size() == 1) - { - // First vertex - BoundingBox.x1 = BoundingBox.x2 = submesh.Vertices[i].x; - BoundingBox.y1 = BoundingBox.y2 = submesh.Vertices[i].y; - BoundingBox.z1 = BoundingBox.z2 = submesh.Vertices[i].z; - mesh->BoundingRadius = d; - } - else - { - BoundingBox.x1 = Min(submesh.Vertices[i].x, BoundingBox.x1); - BoundingBox.x2 = Max(submesh.Vertices[i].x, BoundingBox.x2); - BoundingBox.y1 = Min(submesh.Vertices[i].y, BoundingBox.y1); - BoundingBox.y2 = Max(submesh.Vertices[i].y, BoundingBox.y2); - BoundingBox.z1 = Min(submesh.Vertices[i].z, BoundingBox.z1); - BoundingBox.z2 = Max(submesh.Vertices[i].z, BoundingBox.z2); - mesh->BoundingRadius = Max(mesh->BoundingRadius, d); - } - } - - if(attributes & NORMALS) - { - TiXmlElement* normal_elem = xml.RequireFirstChild(vertex_elem, "normal"); - - submesh.Vertices[i].nx = xml.RequireFloatAttribute(normal_elem, "x"); - submesh.Vertices[i].ny = xml.RequireFloatAttribute(normal_elem, "y"); - submesh.Vertices[i].nz = xml.RequireFloatAttribute(normal_elem, "z"); - } - - if(attributes & TEXCOORDS) - { - TiXmlElement* texcoord_elem = xml.RequireFirstChild(vertex_elem, "texcoord"); - submesh.Vertices[i].u = xml.RequireFloatAttribute(texcoord_elem, "u"); - submesh.Vertices[i].v = xml.RequireFloatAttribute(texcoord_elem, "v"); - } - } - - if(vertex_elem != NULL) - xml.Error(FormatString("Too many vertices in vertexbuffer"), buffer_elem); - if(i < submesh.Vertices.size()) - xml.Error(FormatString("Not enough vertices in vertexbuffer"), buffer_elem); - - loaded_attributes |= attributes; + TiXmlElement* geometry_elem = xml.RequireFirstChild(submesh_elem, "geometry"); + xml.LoadGeometry(*mesh, submesh.Vertices, geometry_elem); + vertices = &submesh.Vertices; + } + else + { + if(mesh->SharedVertices.empty()) + xml.Error(StdCopyStrBuf("Submesh specifies to use shared vertices but there is no shared geometry"), submesh_elem); + vertices = &mesh->SharedVertices; } - - static const unsigned int REQUIRED_ATTRIBUTES = POSITIONS | NORMALS | TEXCOORDS; - if((loaded_attributes & REQUIRED_ATTRIBUTES) != REQUIRED_ATTRIBUTES) - xml.Error(FormatString("Not all required vertex attributes (positions, normals, texcoords) present in mesh geometry"), geometry_elem); TiXmlElement* faces_elem = xml.RequireFirstChild(submesh_elem, "faces"); int FaceCount = xml.RequireIntAttribute(faces_elem, "count"); @@ -225,7 +296,7 @@ StdMesh *StdMeshLoader::LoadMeshXml(const char* xml_data, size_t size, const Std for (unsigned int j = 0; j < 3; ++j) { - if (v[j] < 0 || static_cast(v[j]) >= submesh.Vertices.size()) + if (v[j] < 0 || static_cast(v[j]) >= vertices->size()) xml.Error(FormatString("Vertex index v%u (%d) is out of range", j+1, v[j]), face_elem); submesh.Faces[i].Vertices[j] = v[j]; } @@ -318,46 +389,22 @@ StdMesh *StdMeshLoader::LoadMeshXml(const char* xml_data, size_t size, const Std if (bones[i]->Parent == NULL) mesh->AddMasterBone(bones[i]); + // Vertex<->Bone assignments for shared geometry + if(sharedgeometry_elem) + { + TiXmlElement* boneassignments_elem = xml.RequireFirstChild(mesh_elem, "boneassignments"); + xml.LoadBoneAssignments(*mesh, mesh->SharedVertices, boneassignments_elem); + } + // Vertex<->Bone assignments for all vertices (need to go through SubMeshes again...) unsigned int submesh_index = 0; for (TiXmlElement* submesh_elem = submesh_elem_base; submesh_elem != NULL; submesh_elem = submesh_elem->NextSiblingElement("submesh"), ++submesh_index) { StdSubMesh& submesh = mesh->SubMeshes[submesh_index]; - - TiXmlElement* boneassignments_elem = xml.RequireFirstChild(submesh_elem, "boneassignments"); - for (TiXmlElement* vertexboneassignment_elem = boneassignments_elem->FirstChildElement("vertexboneassignment"); vertexboneassignment_elem != NULL; vertexboneassignment_elem = vertexboneassignment_elem->NextSiblingElement("vertexboneassignment")) + if(!submesh.Vertices.empty()) { - int BoneID = xml.RequireIntAttribute(vertexboneassignment_elem, "boneindex"); - int VertexIndex = xml.RequireIntAttribute(vertexboneassignment_elem, "vertexindex"); - float weight = xml.RequireFloatAttribute(vertexboneassignment_elem, "weight"); - - if (VertexIndex < 0 || static_cast(VertexIndex) >= submesh.Vertices.size()) - xml.Error(FormatString("Vertex index in bone assignment (%d) is out of range", VertexIndex), vertexboneassignment_elem); - - StdMeshBone* bone = NULL; - for (unsigned int i = 0; !bone && i < bones.size(); ++i) - if (bones[i]->ID == BoneID) - bone = bones[i]; - - if (!bone) xml.Error(FormatString("There is no such bone with index %d", BoneID), vertexboneassignment_elem); - - StdSubMesh::Vertex& vertex = submesh.Vertices[VertexIndex]; - vertex.BoneAssignments.push_back(StdMeshVertexBoneAssignment()); - StdMeshVertexBoneAssignment& assignment = vertex.BoneAssignments.back(); - assignment.BoneIndex = bone->Index; - assignment.Weight = weight; - } - - // Normalize vertex bone assignment weights (this is not guaranteed in the - // Ogre file format). - for (unsigned int i = 0; i < submesh.Vertices.size(); ++i) - { - StdSubMesh::Vertex& vertex = submesh.Vertices[i]; - float sum = 0.0f; - for (unsigned int j = 0; j < vertex.BoneAssignments.size(); ++j) - sum += vertex.BoneAssignments[j].Weight; - for (unsigned int j = 0; j < vertex.BoneAssignments.size(); ++j) - vertex.BoneAssignments[j].Weight /= sum; + TiXmlElement* boneassignments_elem = xml.RequireFirstChild(submesh_elem, "boneassignments"); + xml.LoadBoneAssignments(*mesh, submesh.Vertices, boneassignments_elem); } } @@ -441,16 +488,18 @@ StdMesh *StdMeshLoader::LoadMeshXml(const char* xml_data, size_t size, const Std else { // Mesh has no skeleton + // Bone assignements do not make sense then, as the + // actual bones are defined in the skeleton file. for (TiXmlElement* submesh_elem = submesh_elem_base; submesh_elem != NULL; submesh_elem = submesh_elem->NextSiblingElement("submesh")) { TiXmlElement* boneassignments_elem = submesh_elem->FirstChildElement("boneassignments"); if (boneassignments_elem) - { - // Bone assignements do not make sense then, as the - // actual bones are defined in the skeleton file. xml.Error(StdStrBuf("Mesh has bone assignments, but no skeleton"), boneassignments_elem); - } } + + TiXmlElement* boneassignments_elem = mesh_elem->FirstChildElement("boneassignments"); + if (boneassignments_elem) + xml.Error(StdStrBuf("Mesh has bone assignments, but no skeleton"), boneassignments_elem); } // Apply parent transformation to each bone transformation. We need to diff --git a/src/lib/StdMeshMaterial.cpp b/src/lib/StdMeshMaterial.cpp index 435d01eaa..04333fef9 100644 --- a/src/lib/StdMeshMaterial.cpp +++ b/src/lib/StdMeshMaterial.cpp @@ -839,6 +839,7 @@ StdMeshMaterialPass::StdMeshMaterialPass(): Emissive[0] = Emissive[1] = Emissive[2] = 0.0f; Emissive[3] = 0.0f; Shininess = 0.0f; SceneBlendFactors[0] = SB_One; SceneBlendFactors[1] = SB_Zero; + AlphaToCoverage = false; } void StdMeshMaterialPass::Load(StdMeshMaterialParserCtx& ctx) diff --git a/src/lib/StdMeshUpdate.cpp b/src/lib/StdMeshUpdate.cpp index 6245e3401..b9cbec202 100644 --- a/src/lib/StdMeshUpdate.cpp +++ b/src/lib/StdMeshUpdate.cpp @@ -104,7 +104,7 @@ void StdMeshUpdate::Update(StdMeshInstance* instance, const StdMesh& new_mesh) c delete instance->SubMeshInstances[i]; instance->SubMeshInstances.resize(new_mesh.GetNumSubMeshes()); for (unsigned int i = 0; i < instance->SubMeshInstances.size(); ++i) - instance->SubMeshInstances[i] = new StdSubMeshInstance(new_mesh.GetSubMesh(i)); + instance->SubMeshInstances[i] = new StdSubMeshInstance(*instance, new_mesh.GetSubMesh(i), instance->GetCompletion()); // Update child bone of attach parent. If the bone does not exist anymore // in the updated mesh, then detach the mesh from its parent diff --git a/src/lib/texture/C4Facet.cpp b/src/lib/texture/C4Facet.cpp index 540d94551..fa12e9a98 100644 --- a/src/lib/texture/C4Facet.cpp +++ b/src/lib/texture/C4Facet.cpp @@ -117,6 +117,45 @@ void C4Facet::DrawT(C4Facet &cgo, bool fAspect, int32_t iPhaseX, int32_t iPhaseY true,pTransform); } +void C4Facet::DrawTUnscaled(C4Surface * sfcTarget, float iX, float iY, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform *pTransform) +{ + if (!pDraw || !Surface || !sfcTarget || !Wdt || !Hgt) return; + + pDraw->BlitUnscaled(Surface, + float(X+Wdt*iPhaseX),float(Y+Hgt*iPhaseY),float(Wdt),float(Hgt), + sfcTarget, + iX,iY,Wdt,Hgt,true,pTransform); +} + +void C4Facet::DrawTUnscaled(C4Facet &cgo, bool fAspect, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform *pTransform) +{ + if (!pDraw || !Surface || !cgo.Surface || !Wdt || !Hgt) return; + + // Drawing area + C4Facet ccgo = cgo; + // Adjust for fixed aspect ratio + if (fAspect) + { + // By height + if (100*cgo.Wdt/Wdt<100*cgo.Hgt/Hgt) + { + ccgo.Hgt=Hgt*cgo.Wdt/Wdt; + ccgo.Y+=(cgo.Hgt-ccgo.Hgt)/2; + } + // By width + else if (100*cgo.Hgt/Hgt<100*cgo.Wdt/Wdt) + { + ccgo.Wdt=Wdt*cgo.Hgt/Hgt; + ccgo.X+=(cgo.Wdt-ccgo.Wdt)/2; + } + } + + pDraw->BlitUnscaled(Surface, + float(X+Wdt*iPhaseX),float(Y+Hgt*iPhaseY),float(Wdt),float(Hgt), + ccgo.Surface,ccgo.X,ccgo.Y,ccgo.Wdt,ccgo.Hgt, + true,pTransform); +} + void C4Facet::Draw(C4Facet &cgo, bool fAspect, int32_t iPhaseX, int32_t iPhaseY, bool fTransparent) { // Valid parameter check diff --git a/src/lib/texture/C4Facet.h b/src/lib/texture/C4Facet.h index 6e7bb1b35..fc45f08af 100644 --- a/src/lib/texture/C4Facet.h +++ b/src/lib/texture/C4Facet.h @@ -142,6 +142,8 @@ public: void DrawFullScreen(C4Facet &cgo); void DrawT(C4Surface * sfcTarget, float iX, float iY, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform *pTransform); // draw with transformation (if pTransform is assigned) void DrawT(C4Facet &cgo, bool fAspect, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform *pTransform); + void DrawTUnscaled(C4Surface * sfcTarget, float iX, float iY, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform *pTransform); // interpret source coordinates as unscaled + void DrawTUnscaled(C4Facet &cgo, bool fAspect, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform *pTransform); void DrawXT(C4Surface * sfcTarget, float iX, float iY, int32_t iWdt, int32_t iHgt, int32_t iPhaseX, int32_t iPhaseY, C4DrawTransform *pTransform); void DrawClr(C4Facet &cgo, bool fAspect=true, DWORD dwClr=0); // set surface color and draw void DrawXClr(C4Surface * sfcTarget, int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, DWORD dwClr); // set surface color and draw diff --git a/src/network/C4Network2Client.cpp b/src/network/C4Network2Client.cpp index b5649e9fa..307dd8b6d 100644 --- a/src/network/C4Network2Client.cpp +++ b/src/network/C4Network2Client.cpp @@ -268,6 +268,8 @@ void C4Network2Client::AddLocalAddrs(int16_t iPortTCP, int16_t iPortUDP) for(struct ifaddrs* addr = addrs; addr != NULL; addr = addr->ifa_next) { struct sockaddr* ad = addr->ifa_addr; + if(ad == NULL) continue; + if(ad->sa_family == AF_INET && (~addr->ifa_flags & IFF_LOOPBACK)) // Choose only non-loopback IPv4 devices addr_vec.push_back(&reinterpret_cast(ad)->sin_addr); } diff --git a/src/platform/StdDDraw2.cpp b/src/platform/StdDDraw2.cpp index aaa08bae4..a09f60afb 100644 --- a/src/platform/StdDDraw2.cpp +++ b/src/platform/StdDDraw2.cpp @@ -503,6 +503,14 @@ void C4Draw::Blit8Fast(CSurface8 * sfcSource, int fx, int fy, bool C4Draw::Blit(C4Surface * sfcSource, float fx, float fy, float fwdt, float fhgt, C4Surface * sfcTarget, float tx, float ty, float twdt, float thgt, bool fSrcColKey, const C4BltTransform *pTransform) +{ + return BlitUnscaled(sfcSource, fx * sfcSource->Scale, fy * sfcSource->Scale, fwdt * sfcSource->Scale, fhgt * sfcSource->Scale, + sfcTarget, tx, ty, twdt, thgt, fSrcColKey, pTransform); +} + +bool C4Draw::BlitUnscaled(C4Surface * sfcSource, float fx, float fy, float fwdt, float fhgt, + C4Surface * sfcTarget, float tx, float ty, float twdt, float thgt, + bool fSrcColKey, const C4BltTransform *pTransform) { // safety if (!sfcSource || !sfcTarget || !twdt || !thgt || !fwdt || !fhgt) return false; @@ -524,10 +532,6 @@ bool C4Draw::Blit(C4Surface * sfcSource, float fx, float fy, float fwdt, float f twdt *= Zoom; thgt *= Zoom; } - fx *= sfcSource->Scale; - fy *= sfcSource->Scale; - fwdt *= sfcSource->Scale; - fhgt *= sfcSource->Scale; // emulated blit? if (!sfcTarget->IsRenderTarget()) return Blit8(sfcSource, int(fx), int(fy), int(fwdt), int(fhgt), sfcTarget, int(tx), int(ty), int(twdt), int(thgt), fSrcColKey, pTransform); diff --git a/src/platform/StdDDraw2.h b/src/platform/StdDDraw2.h index aed6d8ab3..c5f7e28f8 100644 --- a/src/platform/StdDDraw2.h +++ b/src/platform/StdDDraw2.h @@ -243,6 +243,9 @@ public: bool Blit(C4Surface * sfcSource, float fx, float fy, float fwdt, float fhgt, C4Surface * sfcTarget, float tx, float ty, float twdt, float thgt, bool fSrcColKey=false, const C4BltTransform *pTransform=NULL); + bool BlitUnscaled(C4Surface * sfcSource, float fx, float fy, float fwdt, float fhgt, + C4Surface * sfcTarget, float tx, float ty, float twdt, float thgt, + bool fSrcColKey=false, const C4BltTransform *pTransform=NULL); bool RenderMesh(StdMeshInstance &instance, C4Surface * sfcTarget, float tx, float ty, float twdt, float thgt, DWORD dwPlayerColor, C4BltTransform* pTransform); // Call PrepareMaterial with Mesh's material before virtual void PerformBlt(C4BltData &rBltData, C4TexRef *pTex, DWORD dwModClr, bool fMod2, bool fExact) = 0; virtual void PerformMesh(StdMeshInstance &instance, float tx, float ty, float twdt, float thgt, DWORD dwPlayerColor, C4BltTransform* pTransform) = 0; diff --git a/src/platform/StdFont.cpp b/src/platform/StdFont.cpp index 9d17987eb..64da6e9bd 100644 --- a/src/platform/StdFont.cpp +++ b/src/platform/StdFont.cpp @@ -865,6 +865,7 @@ void CStdFont::DrawText(C4Surface * sfcDest, float iX, float iY, DWORD dwColor, // regular char // get texture coordinates fctFromBlt = GetCharacterFacet(c); + if(!fctFromBlt.Surface) continue; w2=int(fctFromBlt.Wdt*fZoom); h2=int(fctFromBlt.Hgt*fZoom); pDraw->ActivateBlitModulation(dwColor); } diff --git a/src/platform/StdGL.cpp b/src/platform/StdGL.cpp index 869f82315..eddb70181 100644 --- a/src/platform/StdGL.cpp +++ b/src/platform/StdGL.cpp @@ -710,11 +710,12 @@ namespace } } - void RenderSubMeshImpl(const StdSubMeshInstance& instance, DWORD dwModClr, DWORD dwBlitMode, DWORD dwPlayerColor, bool parity) + void RenderSubMeshImpl(const StdMeshInstance& mesh_instance, const StdSubMeshInstance& instance, DWORD dwModClr, DWORD dwBlitMode, DWORD dwPlayerColor, bool parity) { const StdMeshMaterial& material = instance.GetMaterial(); assert(material.BestTechniqueIndex != -1); const StdMeshMaterialTechnique& technique = material.Techniques[material.BestTechniqueIndex]; + const StdMeshVertex* vertices = instance.GetVertices().empty() ? &mesh_instance.GetSharedVertices()[0] : &instance.GetVertices()[0]; // Render each pass for (unsigned int i = 0; i < technique.Passes.size(); ++i) @@ -818,19 +819,28 @@ namespace glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1); glFrontFace(parity ? GL_CW : GL_CCW); - switch (pass.CullHardware) + if(mesh_instance.GetCompletion() < 1.0f) { - case StdMeshMaterialPass::CH_Clockwise: - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - break; - case StdMeshMaterialPass::CH_CounterClockwise: - glEnable(GL_CULL_FACE); - glCullFace(GL_FRONT); - break; - case StdMeshMaterialPass::CH_None: + // Backfaces might be visible when completion is < 1.0f since front + // faces might be omitted. glDisable(GL_CULL_FACE); - break; + } + else + { + switch (pass.CullHardware) + { + case StdMeshMaterialPass::CH_Clockwise: + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + break; + case StdMeshMaterialPass::CH_CounterClockwise: + glEnable(GL_CULL_FACE); + glCullFace(GL_FRONT); + break; + case StdMeshMaterialPass::CH_None: + glDisable(GL_CULL_FACE); + break; + } } // Overwrite blend mode with default alpha blending when alpha in clrmod @@ -861,7 +871,7 @@ namespace // states that "The texture coordinate state for other client texture units // is not updated, regardless of whether the client texture unit is enabled // or not." - glInterleavedArrays(GL_N3F_V3F, sizeof(StdMeshVertex), &instance.GetVertices()[0].nx); + glInterleavedArrays(GL_N3F_V3F, sizeof(StdMeshVertex), &vertices->nx); glMatrixMode(GL_TEXTURE); GLuint have_texture = 0; @@ -890,7 +900,7 @@ namespace glBindTexture(GL_TEXTURE_2D, have_texture); } glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, sizeof(StdMeshVertex), &instance.GetVertices()[0].u); + glTexCoordPointer(2, GL_FLOAT, sizeof(StdMeshVertex), &vertices->u); // Setup texture coordinate transform glLoadIdentity(); @@ -1114,7 +1124,7 @@ namespace // Render each submesh for (unsigned int i = 0; i < mesh.GetNumSubMeshes(); ++i) - RenderSubMeshImpl(instance.GetSubMesh(i), dwModClr, dwBlitMode, dwPlayerColor, parity); + RenderSubMeshImpl(instance, instance.GetSubMesh(i), dwModClr, dwBlitMode, dwPlayerColor, parity); #if 0 // Draw attached bone @@ -1228,6 +1238,11 @@ void CStdGL::PerformMesh(StdMeshInstance &instance, float tx, float ty, float tw glMatrixMode(GL_PROJECTION); glPushMatrix(); + // Mesh extents + const float b = fabs(v2.x - v1.x)/2.0f; + const float h = fabs(v2.y - v1.y)/2.0f; + const float l = fabs(v2.z - v1.z)/2.0f; + if (!fUsePerspective) { // Orthographic projection. The orthographic projection matrix @@ -1303,6 +1318,14 @@ void CStdGL::PerformMesh(StdMeshInstance &instance, float tx, float ty, float tw glScalef(iWdt/2.0, -iHgt/2.0, 1.0f); glTranslatef(1.0f, -1.0f, 0.0f); + // Fix for the case when we have a non-square target + const float ta = twdt / thgt; + const float ma = b / h; + if(ta <= 1 && ta/ma <= 1) + glScalef(std::max(ta, ta/ma), std::max(ta, ta/ma), 1.0f); + else if(ta >= 1 && ta/ma >= 1) + glScalef(std::max(1.0f/ta, ma/ta), std::max(1.0f/ta, ma/ta), 1.0f); + // Apply perspective projection. After this, x and y range from // -1 to 1, and this is mapped into tx/ty/twdt/thgt by the above code. // Aspect is 1.0f which is accounted for above. @@ -1323,19 +1346,9 @@ void CStdGL::PerformMesh(StdMeshInstance &instance, float tx, float ty, float tw } else { - // Mesh extents - const float b = fabs(v2.x - v1.x)/2.0f; - const float h = fabs(v2.y - v1.y)/2.0f; - const float l = fabs(v2.z - v1.z)/2.0f; - // Setup camera position so that the mesh with uniform transformation - // fits well into the rectangle twdt/thgt (without distortion). - float EyeR; - if (thgt < twdt) - EyeR = l + std::max(b/TAN_FOV, h/TAN_FOV * twdt/thgt); - else - EyeR = l + std::max(b/TAN_FOV * thgt/twdt, h/TAN_FOV); - + // fits well into a square target (without distortion). + const float EyeR = l + std::max(b/TAN_FOV, h/TAN_FOV); const float EyeX = MeshCenter.x; const float EyeY = MeshCenter.y; const float EyeZ = MeshCenter.z + EyeR; @@ -1415,6 +1428,7 @@ void CStdGL::PerformMesh(StdMeshInstance &instance, float tx, float ty, float tw glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); + glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); //glDisable(GL_BLEND); glShadeModel(GL_FLAT); @@ -1870,8 +1884,11 @@ bool CStdGL::RestoreDeviceObjects() RenderTarget = pApp->pWindow->pSurface; // BGRA Pixel Formats, Multitexturing, Texture Combine Environment Modes - if (!GLEW_VERSION_1_3) - { + // Check for GL 1.2 and two functions from 1.3 we need. + if( !GLEW_VERSION_1_2 || + glActiveTexture == NULL || + glClientActiveTexture == NULL + ) { return Error(" gl: OpenGL Version 1.3 or higher required. A better graphics driver will probably help."); } diff --git a/src/res/engine.rc b/src/res/engine.rc index bef0fd820..d08dd5cd6 100644 --- a/src/res/engine.rc +++ b/src/res/engine.rc @@ -18,7 +18,7 @@ LANGUAGE LANG_GERMAN, SUBLANG_GERMAN // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. -IDI_00_C4X ICON DISCARDABLE "oc.ico" +IDI_00_C4X ICON DISCARDABLE "oc.ico" IDI_01_OCS ICON DISCARDABLE "ocs.ico" IDI_02_OCG ICON DISCARDABLE "ocg.ico" IDI_03_OCF ICON DISCARDABLE "ocf.ico" @@ -165,6 +165,24 @@ BEGIN ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL END +IDD_GFXERROR DIALOGEX 200, 200, 300, 200 +STYLE DS_MODALFRAME | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | + WS_SYSMENU | DS_CENTER +CAPTION "OCOGLERR" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + LTEXT "ERRORMSGGFX",IDC_GFXERR_MSG,6,20,294,33 + LTEXT "RES",IDC_GFXERR_RES,40,72,100,11 + LTEXT "X:",IDC_GFXERR_X,100,86,20,11 + EDITTEXT IDC_GFXERR_XINP,120,85,35,13, ES_RIGHT | WS_TABSTOP + LTEXT "Y:",IDC_GFXERR_Y,100,100,20,11 + EDITTEXT IDC_GFXERR_YINP,120,99,35,13, ES_RIGHT | WS_TABSTOP + LTEXT "INVAL",IDC_GFXERR_INVAL,170,86,110,33 + AUTOCHECKBOX "FULLSCREEN",IDC_GFXERR_FSCRN, 40, 135, 100, 11, WS_TABSTOP + DEFPUSHBUTTON "RESTART",IDOK, 180,174,60,14, WS_TABSTOP + PUSHBUTTON "CANCEL",IDCANCEL,60,174,60,14, WS_TABSTOP +END + ///////////////////////////////////////////////////////////////////////////// // // Bitmap diff --git a/src/res/resource.h b/src/res/resource.h index af880b5b8..dfec3c6d1 100644 --- a/src/res/resource.h +++ b/src/res/resource.h @@ -53,10 +53,19 @@ #define IDC_STATICMATERIAL 2025 #define IDC_STATICTEXTURE 2027 #define IDC_STATICTIME 2028 +#define IDC_GFXERR_MSG 2029 +#define IDC_GFXERR_RES 2030 +#define IDC_GFXERR_X 2031 +#define IDC_GFXERR_XINP 2032 +#define IDC_GFXERR_Y 2033 +#define IDC_GFXERR_YINP 2034 +#define IDC_GFXERR_FSCRN 2035 +#define IDC_GFXERR_INVAL 2036 #define IDD_COMPONENT 3000 #define IDD_CONSOLE 3001 #define IDD_PROPERTIES 3002 #define IDD_TOOLS 3003 +#define IDD_GFXERROR 3004 #define IDI_00_C4X 4000 #define IDI_01_OCS 4001 #define IDI_02_OCG 4002 diff --git a/src/script/C4AulExec.cpp b/src/script/C4AulExec.cpp index 88dfdf624..dee1a9815 100644 --- a/src/script/C4AulExec.cpp +++ b/src/script/C4AulExec.cpp @@ -1116,10 +1116,12 @@ C4Value C4AulScript::DirectExec(C4Object *pObj, const char *szScript, const char } catch (C4AulError *ex) { - ex->show(); - delete ex; delete pFunc; delete pScript; + ex->show(); + if(fPassErrors) + throw; + delete ex; return C4VNull; } pScript->State = ASS_PARSED; diff --git a/src/script/C4Script.cpp b/src/script/C4Script.cpp index 96df808cb..16cea440a 100644 --- a/src/script/C4Script.cpp +++ b/src/script/C4Script.cpp @@ -385,15 +385,15 @@ static C4Value FnGetLength(C4AulContext *cthr, C4Value *pPars) static C4Value FnGetIndexOf(C4AulContext *cthr, C4Value *pPars) { // find first occurance of first parameter in array - // support GetIndexOf(x, 0) - if (!pPars[1]) return C4VInt(-1); - // if the second param is nonzero, it must be an array - const C4ValueArray * pArray = pPars[1].getArray(); + // support GetIndexOf(0, x) + if (!pPars[0]) return C4VInt(-1); + // if the first param is nonzero, it must be an array + const C4ValueArray * pArray = pPars[0].getArray(); if (!pArray) - throw new C4AulExecError(cthr->Obj, "func \"GetIndexOf\" par 1 cannot be converted to array"); + throw new C4AulExecError(cthr->Obj, "func \"GetIndexOf\" par 0 cannot be converted to array"); int32_t iSize = pArray->GetSize(); for (int32_t i = 0; iGetItem(i)) + if (pPars[1] == pArray->GetItem(i)) // element found return C4VInt(i); // element not found @@ -614,7 +614,7 @@ C4ScriptFnDef C4ScriptFnMap[]= { "Format", 1 ,C4V_String ,{ C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V &FnFormat_C4V, 0 }, { "GetLength", 1 ,C4V_Int ,{ C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,0, FnGetLength }, - { "GetIndexOf", 1 ,C4V_Int ,{ C4V_Any ,C4V_Array ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,0, FnGetIndexOf }, + { "GetIndexOf", 1 ,C4V_Int ,{ C4V_Array ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,0, FnGetIndexOf }, { "eval", 1 ,C4V_Any ,{ C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnEval, 0 }, diff --git a/src/script/C4ScriptStandalone.cpp b/src/script/C4ScriptStandalone.cpp new file mode 100644 index 000000000..303c8e187 --- /dev/null +++ b/src/script/C4ScriptStandalone.cpp @@ -0,0 +1,126 @@ +/* + * OpenClonk, http://www.openclonk.org + * + * Copyright (c) 2011-2012 Günther Brammer + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "../../include/c4script/c4script.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +C4Config Config; +C4Config::C4Config() {} +C4Config::~C4Config() {} +const char * C4Config::AtRelativePath(char const*s) {return s;} + +C4DefList Definitions; +C4DefList::C4DefList() {} +C4DefList::~C4DefList() {} +C4Def* C4DefList::ID2Def(C4ID id) {return NULL;} +C4Def * C4DefList::GetDef(int) {return 0;} +int C4DefList::GetDefCount() {return 0;} +void C4DefList::CallEveryDefinition() {} +void C4DefList::ResetIncludeDependencies() {} +bool C4DefList::DrawFontImage(const char* szImageTag, C4Facet& rTarget, C4DrawTransform* pTransform) { return false; } +float C4DefList::GetFontImageAspect(const char* szImageTag) { return -1.0f; } + +C4MaterialMap MaterialMap; +C4MaterialMap::C4MaterialMap() {} +C4MaterialMap::~C4MaterialMap() {} +void C4MaterialMap::UpdateScriptPointers() {} + +C4AulDebug *C4AulDebug::pDebug; +void C4AulDebug::DebugStepIn(C4AulBCC*) {} +void C4AulDebug::DebugStepOut(C4AulBCC*, C4AulScriptContext*, C4Value*) {} +void C4AulDebug::DebugStep(C4AulBCC*) {} + +C4GameObjects Objects; +C4GameObjects::C4GameObjects() {} +C4GameObjects::~C4GameObjects() {} +void C4GameObjects::UpdateScriptPointers() {} +void C4GameObjects::Clear(bool) {} +void C4GameObjects::Default() {} +bool C4GameObjects::Remove(C4Object*) {return 0;} +bool C4GameObjects::AssignInfo() {return 0;} +bool C4GameObjects::ValidateOwners() {return 0;} +C4Value C4GameObjects::GRBroadcast(char const*, C4AulParSet*, bool, bool) {return C4Value();} +C4Object * C4GameObjects::ObjectPointer(int) {return 0;} + +C4ObjectList::C4ObjectList() {} +C4ObjectList::~C4ObjectList() {} +void C4ObjectList::Default() {} +void C4ObjectList::Clear() {} +void C4ObjectList::InsertLinkBefore(C4ObjectLink*, C4ObjectLink*) {} +void C4ObjectList::InsertLink(C4ObjectLink*, C4ObjectLink*) {} +void C4ObjectList::RemoveLink(C4ObjectLink*) {} +bool C4ObjectList::Add(C4Object*, C4ObjectList::SortType, C4ObjectList*) {return 0;} +bool C4ObjectList::Remove(C4Object*) {return 0;} +bool C4ObjectList::AssignInfo() {return 0;} +bool C4ObjectList::ValidateOwners() {return 0;} + +void C4NotifyingObjectList::InsertLinkBefore(C4ObjectLink *pLink, C4ObjectLink *pBefore) {} +void C4NotifyingObjectList::InsertLink(C4ObjectLink*, C4ObjectLink*) {} +void C4NotifyingObjectList::RemoveLink(C4ObjectLink*) {} + +C4Reloc Reloc; +bool C4Reloc::Open(C4Group&, char const*) const {return false;} + +void C4LSector::Clear() {} +void C4Def::IncludeDefinition(C4Def*) {} +bool EraseItemSafe(const char *szFilename) {return false;} +void AddDbgRec(C4RecordChunkType, const void *, int) {} + +int c4s_runscript(const char * filename) +{ + InitCoreFunctionMap(&ScriptEngine); + + C4Group File; + if (!File.Open(GetWorkingDirectory())) + { + fprintf(stderr, "Open failed: %s\n", File.GetError()); + return 1; + } + + // get scripts + StdStrBuf fn; + File.ResetSearch(); + if (!File.FindNextEntry(filename, &fn)) + { + fprintf(stderr, "FindNextEntry failed: %s\n", File.GetError()); + return 1; + } + GameScript.Load(File, fn.getData(), NULL, NULL); + + // Link script engine (resolve includes/appends, generate code) + ScriptEngine.Link(&::Definitions); + + // Set name list for globals + ScriptEngine.GlobalNamed.SetNameList(&ScriptEngine.GlobalNamedNames); + GameScript.Call("Main"); + GameScript.Clear(); + ScriptEngine.Clear(); + return 0; +} diff --git a/src/script/shell.cpp b/src/script/shell.cpp index 2b0c61531..63138d2ec 100644 --- a/src/script/shell.cpp +++ b/src/script/shell.cpp @@ -1,7 +1,7 @@ /* * OpenClonk, http://www.openclonk.org * - * Copyright (c) 2011 Günther Brammer + * Copyright (c) 2012 Günther Brammer * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -16,109 +16,11 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -C4Config Config; -C4Config::C4Config() {} -C4Config::~C4Config() {} -const char * C4Config::AtRelativePath(char const*s) {return s;} - -C4DefList Definitions; -C4DefList::C4DefList() {} -C4DefList::~C4DefList() {} -C4Def* C4DefList::ID2Def(C4ID id) {return NULL;} -C4Def * C4DefList::GetDef(int) {return 0;} -int C4DefList::GetDefCount() {return 0;} -void C4DefList::CallEveryDefinition() {} -void C4DefList::ResetIncludeDependencies() {} -bool C4DefList::DrawFontImage(const char* szImageTag, C4Facet& rTarget, C4DrawTransform* pTransform) { return false; } -float C4DefList::GetFontImageAspect(const char* szImageTag) { return -1.0f; } - -C4MaterialMap MaterialMap; -C4MaterialMap::C4MaterialMap() {} -C4MaterialMap::~C4MaterialMap() {} -void C4MaterialMap::UpdateScriptPointers() {} - -C4AulDebug *C4AulDebug::pDebug; -void C4AulDebug::DebugStepIn(C4AulBCC*) {} -void C4AulDebug::DebugStepOut(C4AulBCC*, C4AulScriptContext*, C4Value*) {} -void C4AulDebug::DebugStep(C4AulBCC*) {} - -C4GameObjects Objects; -C4GameObjects::C4GameObjects() {} -C4GameObjects::~C4GameObjects() {} -void C4GameObjects::UpdateScriptPointers() {} -void C4GameObjects::Clear(bool) {} -void C4GameObjects::Default() {} -bool C4GameObjects::Remove(C4Object*) {return 0;} -bool C4GameObjects::AssignInfo() {return 0;} -bool C4GameObjects::ValidateOwners() {return 0;} -C4Value C4GameObjects::GRBroadcast(char const*, C4AulParSet*, bool, bool) {return C4Value();} -C4Object * C4GameObjects::ObjectPointer(int) {return 0;} - -C4ObjectList::C4ObjectList() {} -C4ObjectList::~C4ObjectList() {} -void C4ObjectList::Default() {} -void C4ObjectList::Clear() {} -void C4ObjectList::InsertLinkBefore(C4ObjectLink*, C4ObjectLink*) {} -void C4ObjectList::InsertLink(C4ObjectLink*, C4ObjectLink*) {} -void C4ObjectList::RemoveLink(C4ObjectLink*) {} -bool C4ObjectList::Add(C4Object*, C4ObjectList::SortType, C4ObjectList*) {return 0;} -bool C4ObjectList::Remove(C4Object*) {return 0;} -bool C4ObjectList::AssignInfo() {return 0;} -bool C4ObjectList::ValidateOwners() {return 0;} - -void C4NotifyingObjectList::InsertLinkBefore(C4ObjectLink *pLink, C4ObjectLink *pBefore) {} -void C4NotifyingObjectList::InsertLink(C4ObjectLink*, C4ObjectLink*) {} -void C4NotifyingObjectList::RemoveLink(C4ObjectLink*) {} - -C4Reloc Reloc; -bool C4Reloc::Open(C4Group&, char const*) const {return false;} - -void C4LSector::Clear() {} -void C4Def::IncludeDefinition(C4Def*) {} -bool EraseItemSafe(const char *szFilename) {return false;} -void AddDbgRec(C4RecordChunkType, const void *, int) {} +// Do not include C4Include.h - this file tests whether +// c4script.h is useable without that. +#include "../../include/c4script/c4script.h" int main(int argc, const char * argv[]) { - InitCoreFunctionMap(&ScriptEngine); - - C4Group File; - if (!File.Open(GetWorkingDirectory())) - { - fprintf(stderr, "Open failed: %s\n", File.GetError()); - return 1; - } - - // get scripts - StdStrBuf fn; - File.ResetSearch(); - if (!File.FindNextEntry(argv[1], &fn)) - { - fprintf(stderr, "FindNextEntry failed: %s\n", File.GetError()); - return 1; - } - GameScript.Load(File, fn.getData(), NULL, NULL); - - // Link script engine (resolve includes/appends, generate code) - ScriptEngine.Link(&::Definitions); - - // Set name list for globals - ScriptEngine.GlobalNamed.SetNameList(&ScriptEngine.GlobalNamedNames); - GameScript.Call("Main"); - GameScript.Clear(); - ScriptEngine.Clear(); - return 0; + return c4s_runscript(argv[1]); } diff --git a/tools/install/oc.nsi b/tools/install/oc.nsi index 0a420560c..fc6114f7c 100644 --- a/tools/install/oc.nsi +++ b/tools/install/oc.nsi @@ -65,14 +65,14 @@ FunctionEnd !insertmacro MUI_UNPAGE_INSTFILES ; Language files -!insertmacro MUI_LANGUAGE "German" !insertmacro MUI_LANGUAGE "English" +!insertmacro MUI_LANGUAGE "German" ; Additional language strings -LangString MUI_TEXT_USERPATH ${LANG_German} "Benutzerpfad" -LangString MUI_TEXT_USERPATH ${LANG_English} "User Path" +LangString OC_TEXT_USERPATH ${LANG_German} "Benutzerpfad" +LangString OC_TEXT_USERPATH ${LANG_English} "User Path" -!insertmacro MUI_RESERVEFILE_LANGDLL +;!insertmacro MUI_RESERVEFILE_LANGDLL ;ReserveFile "${NSISDIR}\Plugins\*.dll" ; MUI end ------ @@ -132,14 +132,14 @@ Section CreateShortcut "$DESKTOP\OpenClonk.lnk" "$INSTDIR\Clonk.exe" ; Create user path shortcut in program directory - CreateShortCut "$INSTDIR\$(MUI_TEXT_USERPATH).lnk" "%APPDATA%\OpenClonk" + CreateShortCut "$INSTDIR\$(OC_TEXT_USERPATH).lnk" "%APPDATA%\OpenClonk" ; Start menu shortcuts CreateDirectory "$SMPROGRAMS\OpenClonk" CreateShortCut "$SMPROGRAMS\OpenClonk\OpenClonk.lnk" "$INSTDIR\Clonk.exe" CreateShortCut "$SMPROGRAMS\OpenClonk\OpenClonk Editor.lnk" "$INSTDIR\Clonk.exe" "--editor" CreateShortCut "$SMPROGRAMS\OpenClonk\${PRODUCT_WEB_SITE_NAME}.lnk" "$INSTDIR\${PRODUCT_WEB_SITE_NAME}.url" - CreateShortCut "$SMPROGRAMS\OpenClonk\$(MUI_TEXT_USERPATH).lnk" "%APPDATA%\OpenClonk" + CreateShortCut "$SMPROGRAMS\OpenClonk\$(OC_TEXT_USERPATH).lnk" "%APPDATA%\OpenClonk" EndStartMenu: ; Uninstaller info @@ -238,7 +238,7 @@ Section Uninstall Delete "$INSTDIR\uninst.exe" Delete "$INSTDIR\GameExplorer.txt" Delete "$INSTDIR\${PRODUCT_WEB_SITE_NAME}.url" - Delete "$INSTDIR\$(MUI_TEXT_USERPATH).lnk" + Delete "$INSTDIR\$(OC_TEXT_USERPATH).lnk" RMDir "$INSTDIR"