Compare commits
66 Commits
Author | SHA1 | Date |
---|---|---|
Romain Naour | f8136fcbc5 | |
Romain Naour | 54d2ce7e07 | |
Romain Naour | 923d355c91 | |
Nicolas Hake | c1ee1bdac7 | |
Nicolas Hake | c291488034 | |
Maikel de Vries | 5c6fadfb26 | |
Maikel de Vries | 4dc3fe5928 | |
Maikel de Vries | 168277abdb | |
Maikel de Vries | a7e1f59369 | |
Maikel de Vries | 90ea896814 | |
Maikel de Vries | 7c0ae67289 | |
Maikel de Vries | 07b0f51742 | |
Maikel de Vries | 0aba4f88fc | |
Maikel de Vries | a935a9d4ac | |
Maikel de Vries | 97f87019b7 | |
Maikel de Vries | a85a3201d9 | |
Maikel de Vries | e0e570e9c9 | |
Maikel de Vries | 68d901b61c | |
Maikel de Vries | 2c4676d63c | |
Armin Burgmeier | d952012331 | |
Maikel de Vries | 0f67b7bb70 | |
Maikel de Vries | 2a59351edd | |
Maikel de Vries | 0c0c5df94d | |
Maikel de Vries | 84063e1917 | |
Maikel de Vries | b88e72c67a | |
Maikel de Vries | 459b081033 | |
Maikel de Vries | 44b377d637 | |
Maikel de Vries | 2c43ac6bac | |
Maikel de Vries | c2ac2bda42 | |
Nicolas Hake | 0e45bb8ee9 | |
Maikel de Vries | 66f52a4097 | |
Nicolas Hake | 3e0ed99c83 | |
Nicolas Hake | 49a1b5aaf7 | |
Maikel de Vries | 0eeaf99266 | |
Lukas Werling | 03d05ff98f | |
Maikel de Vries | fabe8302eb | |
Maikel de Vries | 0f48bb2a86 | |
Maikel de Vries | 64c08e1510 | |
Lukas Werling | 32df251d2e | |
Lukas Werling | 2159895280 | |
Lukas Werling | 846ba60d46 | |
Lukas Werling | e10d4b3bf5 | |
Lukas Werling | a091874546 | |
Lukas Werling | cd1f540b1e | |
Kevin Zheng | d57e0e08d2 | |
Lukas Werling | 1f20add428 | |
Maikel de Vries | 9af9e5d98f | |
Maikel de Vries | 39d55a6c3f | |
Lukas Werling | ff44b26d4c | |
Maikel de Vries | 721d808df3 | |
Maikel de Vries | 22cd0d03d6 | |
Maikel de Vries | c46b66002c | |
Lukas Werling | 85d9c2c410 | |
Lukas Werling | 8f863d8905 | |
Lukas Werling | 7a0c323099 | |
Lukas Werling | be31964c2e | |
Lukas Werling | ce9245c55c | |
Maikel de Vries | 92a7087bf7 | |
Maikel de Vries | c7262aa317 | |
Maikel de Vries | d3bc20f168 | |
Maikel de Vries | 6ac777e705 | |
Maikel de Vries | 6ec655cbce | |
Lukas Werling | 7694ae5020 | |
Lukas Werling | 78833d10ee | |
Lukas Werling | 3b0b66909e | |
Lukas Werling | 4262fd0c08 |
493
CMakeLists.txt
|
@ -48,6 +48,7 @@ CMAKE_DEPENDENT_OPTION(USE_WIN32_WINDOWS "Use Microsoft Desktop App User Interfa
|
|||
CMAKE_DEPENDENT_OPTION(USE_SDL_MAINLOOP "Use SDL to create windows etc. Qt editor." ON "NOT USE_COCOA AND NOT USE_WIN32_WINDOWS AND NOT HEADLESS_ONLY" OFF)
|
||||
option(WITH_AUTOMATIC_UPDATE "Automatic updates are downloaded from the project website." OFF)
|
||||
option(HEADLESS_ONLY "Only build headless parts. Somewhat reduces dependencies. (still needs libpng because that one's small and hard to remove.) Only tested with make/gcc/linux." OFF)
|
||||
option(C4GROUP_TOOL_ONLY "Only build c4group binary." OFF)
|
||||
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ${PROJECT_FOLDERS})
|
||||
|
||||
|
@ -158,7 +159,7 @@ endif()
|
|||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wextra-tokens -Wpointer-arith -Wno-cast-align -Wno-reorder -Wno-unused-parameter -Wnon-virtual-dtor -Woverloaded-virtual")
|
||||
elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wredundant-decls -Wendif-labels -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -Winit-self -Wsign-promo -Wno-reorder -Wno-unused-parameter -Wnon-virtual-dtor -Woverloaded-virtual")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wredundant-decls -Wendif-labels -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -Winit-self -Wsign-promo -Wno-reorder -Wno-unused-parameter -Wnon-virtual-dtor -Woverloaded-virtual -Wformat-security")
|
||||
endif()
|
||||
|
||||
if(WIN32 AND MINGW)
|
||||
|
@ -177,6 +178,12 @@ endif()
|
|||
############################################################################
|
||||
# Check for compiler quirks and features
|
||||
############################################################################
|
||||
if(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CROSSCOMPILING)
|
||||
include(HandleGccCrossIncludePaths)
|
||||
HANDLE_GCC_CROSS_INCLUDE_PATHS(CXX c++)
|
||||
HANDLE_GCC_CROSS_INCLUDE_PATHS(C c)
|
||||
endif()
|
||||
|
||||
include(CheckCXXSourceCompiles)
|
||||
include(RequireCXXSourceCompiles)
|
||||
include(CheckCXXSymbolExists)
|
||||
|
@ -224,25 +231,30 @@ CHECK_CXX_SOURCE_COMPILES("#include <getopt.h>\nint main(int argc, char * argv[]
|
|||
# Locate libraries
|
||||
############################################################################
|
||||
SET(JPEG_NAMES ${JPEG_NAMES} libjpeg jpeg-static)
|
||||
if(NOT HEADLESS_ONLY)
|
||||
if(NOT HEADLESS_ONLY AND NOT C4GROUP_TOOL_ONLY)
|
||||
find_package(Freetype REQUIRED)
|
||||
include_directories(
|
||||
${FREETYPE_INCLUDE_DIRS})
|
||||
link_directories(
|
||||
${FREETYPE_LIBRARY_DIRS})
|
||||
endif()
|
||||
find_package(JPEG REQUIRED)
|
||||
find_package(PNG REQUIRED)
|
||||
|
||||
# Needed for c4group
|
||||
find_package(ZLIB REQUIRED)
|
||||
include_directories(
|
||||
${JPEG_INCLUDE_DIR}
|
||||
${PNG_INCLUDE_DIR}
|
||||
${ZLIB_INCLUDE_DIR})
|
||||
if(CMAKE_SYSTEM MATCHES "Windows")
|
||||
message(STATUS "Using Win32 threading.")
|
||||
else()
|
||||
find_package("Threads" REQUIRED)
|
||||
SET(HAVE_PTHREAD ${CMAKE_USE_PTHREADS_INIT} CACHE INTERNAL "libpthread available")
|
||||
|
||||
if (NOT C4GROUP_TOOL_ONLY)
|
||||
find_package(JPEG REQUIRED)
|
||||
find_package(PNG REQUIRED)
|
||||
include_directories(
|
||||
${JPEG_INCLUDE_DIR}
|
||||
${PNG_INCLUDE_DIR}
|
||||
${ZLIB_INCLUDE_DIR})
|
||||
if(CMAKE_SYSTEM MATCHES "Windows")
|
||||
message(STATUS "Using Win32 threading.")
|
||||
else()
|
||||
find_package("Threads" REQUIRED)
|
||||
SET(HAVE_PTHREAD ${CMAKE_USE_PTHREADS_INIT} CACHE INTERNAL "libpthread available")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# FINDLIB works the same as find_library, but also marks the resulting var as
|
||||
|
@ -267,19 +279,20 @@ if(NOT HAVE_GETOPT_H)
|
|||
set(GETOPT_LIBRARIES getopt)
|
||||
endif()
|
||||
|
||||
# TinyXML
|
||||
find_package(TinyXML)
|
||||
if(NOT TinyXML_FOUND)
|
||||
add_subdirectory(thirdparty/tinyxml)
|
||||
set_property(TARGET tinyxml PROPERTY FOLDER "Third-party libraries")
|
||||
set(TinyXML_INCLUDE_DIRS thirdparty/tinyxml)
|
||||
set(TinyXML_LIBRARIES tinyxml)
|
||||
set(TinyXML_FOUND TRUE)
|
||||
if (NOT C4GROUP_TOOL_ONLY)
|
||||
# TinyXML
|
||||
find_package(TinyXML)
|
||||
if(NOT TinyXML_FOUND)
|
||||
add_subdirectory(thirdparty/tinyxml)
|
||||
set_property(TARGET tinyxml PROPERTY FOLDER "Third-party libraries")
|
||||
set(TinyXML_INCLUDE_DIRS thirdparty/tinyxml)
|
||||
set(TinyXML_LIBRARIES tinyxml)
|
||||
set(TinyXML_FOUND TRUE)
|
||||
endif()
|
||||
include_directories(SYSTEM ${TinyXML_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
include_directories(SYSTEM ${TinyXML_INCLUDE_DIRS})
|
||||
|
||||
if(NOT HEADLESS_ONLY)
|
||||
if(NOT HEADLESS_ONLY AND NOT C4GROUP_TOOL_ONLY)
|
||||
find_package(OpenGL)
|
||||
find_package(GLEW REQUIRED)
|
||||
include_directories(${GLEW_INCLUDE_DIRS})
|
||||
|
@ -291,13 +304,26 @@ if(NOT HEADLESS_ONLY)
|
|||
CHECK_CXX_SOURCE_COMPILES("#include <GL/glew.h>\nvoid GLAPIENTRY OpenGLDebugProc(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* message, const void* userParam) {}\nint main() { GLDEBUGPROCARB proc = &OpenGLDebugProc; }" GLDEBUGPROCARB_USERPARAM_IS_CONST)
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
FINDLIB(X11_LIBRARIES X11)
|
||||
if(NOT C4GROUP_TOOL_ONLY)
|
||||
if(UNIX AND NOT APPLE)
|
||||
FINDLIB(X11_LIBRARIES X11)
|
||||
|
||||
set(Backward_DIR thirdparty/backward-cpp)
|
||||
find_package(Backward)
|
||||
if(Backward_FOUND)
|
||||
set(HAVE_BACKWARD 1)
|
||||
set(Backward_DIR thirdparty/backward-cpp)
|
||||
find_package(Backward)
|
||||
if(Backward_FOUND)
|
||||
set(HAVE_BACKWARD 1)
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED PROC_SELF_EXE)
|
||||
macro(FIND_PROC_SELF_EXE path)
|
||||
if(EXISTS ${path})
|
||||
set(PROC_SELF_EXE ${path} CACHE FILEPATH "Path to /proc/self/exe (Linux) or equivalent")
|
||||
endif()
|
||||
endmacro()
|
||||
FIND_PROC_SELF_EXE(/proc/self/exe) # Linux
|
||||
FIND_PROC_SELF_EXE(/proc/curproc/file) # FreeBSD
|
||||
FIND_PROC_SELF_EXE(/proc/curproc/exe) # NetBSD
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@ -309,71 +335,75 @@ if (WIN32)
|
|||
set(HAVE_DBGHELP ${DBGHELP_FOUND})
|
||||
endif()
|
||||
|
||||
find_package(Upnp)
|
||||
if(UPNP_FOUND)
|
||||
include_directories(SYSTEM ${UPNP_INCLUDE_DIR})
|
||||
endif()
|
||||
if(NOT C4GROUP_TOOL_ONLY)
|
||||
find_package(Upnp)
|
||||
if(UPNP_FOUND)
|
||||
include_directories(SYSTEM ${UPNP_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
find_package(Readline)
|
||||
if(READLINE_FOUND)
|
||||
include_directories(SYSTEM ${READLINE_INCLUDE_DIR})
|
||||
endif()
|
||||
SET(HAVE_LIBREADLINE ${READLINE_FOUND} CACHE INTERNAL "libreadline available")
|
||||
find_package(Readline)
|
||||
if(READLINE_FOUND)
|
||||
include_directories(SYSTEM ${READLINE_INCLUDE_DIR})
|
||||
endif()
|
||||
SET(HAVE_LIBREADLINE ${READLINE_FOUND} CACHE INTERNAL "libreadline available")
|
||||
|
||||
find_package(GTK3 COMPONENTS gthread gio gobject glib OPTIONAL_COMPONENTS gtksourceview)
|
||||
find_package(GTK3 COMPONENTS gthread gio gobject glib OPTIONAL_COMPONENTS gtksourceview)
|
||||
|
||||
# Select an audio library
|
||||
find_package("Audio")
|
||||
if(Audio_FOUND)
|
||||
include_directories(${Audio_INCLUDE_DIRS})
|
||||
endif()
|
||||
# Select an audio library
|
||||
find_package("Audio")
|
||||
if(Audio_FOUND)
|
||||
include_directories(${Audio_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
# SDL
|
||||
if(USE_SDL_MAINLOOP)
|
||||
find_package(SDL2 REQUIRED)
|
||||
else()
|
||||
# for gamepads
|
||||
find_package(SDL2)
|
||||
endif()
|
||||
set(HAVE_SDL ${SDL2_FOUND})
|
||||
include_directories(SYSTEM ${SDL2_INCLUDE_DIRS})
|
||||
# SDL
|
||||
if(USE_SDL_MAINLOOP)
|
||||
find_package(SDL2 REQUIRED)
|
||||
else()
|
||||
# for gamepads
|
||||
find_package(SDL2)
|
||||
endif()
|
||||
set(HAVE_SDL ${SDL2_FOUND})
|
||||
include_directories(SYSTEM ${SDL2_INCLUDE_DIRS})
|
||||
|
||||
# Qt5 for editor
|
||||
find_path(Qt5DIR qt.pro PATHS ${CMAKE_ADDITIONAL_DEPS_PATH}/qt-5.5.0)
|
||||
find_package(Qt5Widgets 5.4 PATHS ${Qt5DIR}/qtbase/lib/cmake/Qt5Widgets)
|
||||
if(Qt5Widgets_FOUND)
|
||||
SET(WITH_QT_EDITOR ${Qt5Widgets_FOUND} "Qt editor dialogues available")
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
# As moc files are generated in the binary dir, tell CMake
|
||||
# to always look for includes there:
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
else()
|
||||
message("Qt5Widgets not found. Building openclonk without editor.")
|
||||
UNSET(WITH_QT_EDITOR)
|
||||
# Qt5 for editor
|
||||
find_path(Qt5DIR qt.pro PATHS ${CMAKE_ADDITIONAL_DEPS_PATH}/qt-5.5.0)
|
||||
find_package(Qt5Widgets 5.4 PATHS ${Qt5DIR}/qtbase/lib/cmake/Qt5Widgets)
|
||||
if(Qt5Widgets_FOUND)
|
||||
SET(WITH_QT_EDITOR ${Qt5Widgets_FOUND} "Qt editor dialogues available")
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
# As moc files are generated in the binary dir, tell CMake
|
||||
# to always look for includes there:
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
else()
|
||||
message("Qt5Widgets not found. Building openclonk without editor.")
|
||||
UNSET(WITH_QT_EDITOR)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
############################################################################
|
||||
# generated source files
|
||||
############################################################################
|
||||
find_program(GLIB_COMPILE_RESOURCES glib-compile-resources)
|
||||
if(NOT C4GROUP_TOOL_ONLY)
|
||||
find_program(GLIB_COMPILE_RESOURCES glib-compile-resources)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT mape-resource.c
|
||||
COMMAND
|
||||
${GLIB_COMPILE_RESOURCES} "--internal" "--generate"
|
||||
"--target" "mape-resource.c"
|
||||
"--sourcedir" ${CMAKE_CURRENT_SOURCE_DIR}/src/res
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/res/mape.xml"
|
||||
MAIN_DEPENDENCY src/res/mape.xml
|
||||
DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/res/ocd.ico
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/res/ocf.ico
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/res/ocg.ico
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/res/ocm.ico
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/res/ocs.ico
|
||||
VERBATIM
|
||||
)
|
||||
add_custom_command(
|
||||
OUTPUT mape-resource.c
|
||||
COMMAND
|
||||
${GLIB_COMPILE_RESOURCES} "--internal" "--generate"
|
||||
"--target" "mape-resource.c"
|
||||
"--sourcedir" ${CMAKE_CURRENT_SOURCE_DIR}/src/res
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/res/mape.xml"
|
||||
MAIN_DEPENDENCY src/res/mape.xml
|
||||
DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/res/ocd.ico
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/res/ocf.ico
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/res/ocg.ico
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/res/ocm.ico
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/res/ocs.ico
|
||||
VERBATIM
|
||||
)
|
||||
endif()
|
||||
|
||||
############################################################################
|
||||
# Mac OS bundle setup
|
||||
|
@ -973,7 +1003,7 @@ include_directories(SYSTEM
|
|||
############################################################################
|
||||
add_definitions(-DHAVE_CONFIG_H)
|
||||
|
||||
add_library(libmisc
|
||||
add_library(libmisc STATIC
|
||||
src/C4Include.cpp
|
||||
src/c4group/C4Group.cpp
|
||||
src/c4group/C4Group.h
|
||||
|
@ -1038,7 +1068,7 @@ if(UNIX AND NOT APPLE)
|
|||
target_link_libraries(libmisc rt)
|
||||
endif()
|
||||
|
||||
add_library(libc4script
|
||||
add_library(libc4script STATIC
|
||||
src/C4Include.cpp
|
||||
src/c4group/C4ComponentHost.cpp
|
||||
src/c4group/C4ComponentHost.h
|
||||
|
@ -1072,6 +1102,8 @@ src/script/C4PropList.h
|
|||
src/script/C4Script.cpp
|
||||
src/script/C4ScriptHost.cpp
|
||||
src/script/C4ScriptHost.h
|
||||
src/script/C4ScriptLibraries.cpp
|
||||
src/script/C4ScriptLibraries.h
|
||||
src/script/C4StringTable.cpp
|
||||
src/script/C4StringTable.h
|
||||
src/script/C4Value.cpp
|
||||
|
@ -1081,10 +1113,11 @@ src/script/C4ValueArray.h
|
|||
src/script/C4ValueMap.cpp
|
||||
src/script/C4ValueMap.h
|
||||
)
|
||||
add_subdirectory(thirdparty/blake2)
|
||||
set_property(TARGET blake2 PROPERTY FOLDER "Third-party libraries")
|
||||
target_link_libraries(libc4script blake2 libmisc)
|
||||
|
||||
target_link_libraries(libc4script libmisc)
|
||||
|
||||
add_library(libopenclonk
|
||||
add_library(libopenclonk STATIC
|
||||
src/c4group/C4Extra.cpp
|
||||
src/c4group/C4Extra.h
|
||||
src/control/C4PlayerInfoConflicts.cpp
|
||||
|
@ -1154,7 +1187,7 @@ target_link_libraries(c4script
|
|||
${GETOPT_LIBRARIES}
|
||||
)
|
||||
|
||||
if(NOT HEADLESS_ONLY)
|
||||
if(NOT HEADLESS_ONLY AND NOT C4GROUP_TOOL_ONLY)
|
||||
add_executable(openclonk WIN32 MACOSX_BUNDLE
|
||||
${OC_SYSTEM_SOURCES}
|
||||
${OC_GUI_SOURCES}
|
||||
|
@ -1194,40 +1227,42 @@ if(NOT HEADLESS_ONLY)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
add_executable(openclonk-server
|
||||
${OC_SYSTEM_SOURCES}
|
||||
${OC_CLONK_SOURCES}
|
||||
src/platform/C4AppT.cpp
|
||||
src/platform/C4StdInProc.cpp
|
||||
src/platform/C4StdInProc.h
|
||||
)
|
||||
target_compile_definitions(openclonk-server PRIVATE "USE_CONSOLE")
|
||||
if(NOT C4GROUP_TOOL_ONLY)
|
||||
add_executable(openclonk-server
|
||||
${OC_SYSTEM_SOURCES}
|
||||
${OC_CLONK_SOURCES}
|
||||
src/platform/C4AppT.cpp
|
||||
src/platform/C4StdInProc.cpp
|
||||
src/platform/C4StdInProc.h
|
||||
)
|
||||
target_compile_definitions(openclonk-server PRIVATE "USE_CONSOLE")
|
||||
|
||||
target_link_libraries(openclonk-server
|
||||
${PNG_LIBRARIES}
|
||||
${JPEG_LIBRARIES}
|
||||
${EXECINFO_LIBRARY}
|
||||
${SDL2_LIBRARIES}
|
||||
${READLINE_LIBRARIES}
|
||||
${Audio_LIBRARIES}
|
||||
${GETOPT_LIBRARIES}
|
||||
${TinyXML_LIBRARIES}
|
||||
${DBGHELP_LIBRARIES}
|
||||
libmisc
|
||||
libc4script
|
||||
libopenclonk
|
||||
)
|
||||
if(UPNP_FOUND)
|
||||
target_link_libraries(openclonk-server ${UPNP_LIBRARIES})
|
||||
endif()
|
||||
if(USE_COCOA)
|
||||
target_link_libraries(openclonk-server "-framework Cocoa")
|
||||
endif()
|
||||
if(HAVE_BACKWARD)
|
||||
target_link_libraries(openclonk-server Backward::Backward)
|
||||
target_link_libraries(openclonk-server
|
||||
${PNG_LIBRARIES}
|
||||
${JPEG_LIBRARIES}
|
||||
${EXECINFO_LIBRARY}
|
||||
${SDL2_LIBRARIES}
|
||||
${READLINE_LIBRARIES}
|
||||
${Audio_LIBRARIES}
|
||||
${GETOPT_LIBRARIES}
|
||||
${TinyXML_LIBRARIES}
|
||||
${DBGHELP_LIBRARIES}
|
||||
libmisc
|
||||
libc4script
|
||||
libopenclonk
|
||||
)
|
||||
if(UPNP_FOUND)
|
||||
target_link_libraries(openclonk-server ${UPNP_LIBRARIES})
|
||||
endif()
|
||||
if(USE_COCOA)
|
||||
target_link_libraries(openclonk-server "-framework Cocoa")
|
||||
endif()
|
||||
if(HAVE_BACKWARD)
|
||||
target_link_libraries(openclonk-server Backward::Backward)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(GTK3_FOUND AND GTK3_gtksourceview_FOUND AND NOT HEADLESS_ONLY)
|
||||
if(GTK3_FOUND AND GTK3_gtksourceview_FOUND AND NOT HEADLESS_ONLY AND NOT C4GROUP_TOOL_ONLY)
|
||||
add_executable(mape ${MAPE_BASE_SOURCES} ${MAPE_SOURCES})
|
||||
target_compile_options(mape PRIVATE ${GTK3_COMPILE_DEFINITIONS} ${GTK3_gtksourceview_COMPILE_DEFINITIONS})
|
||||
set_property(TARGET mape PROPERTY FOLDER "Utilities")
|
||||
|
@ -1254,17 +1289,19 @@ target_link_libraries(c4group
|
|||
libmisc
|
||||
)
|
||||
|
||||
add_executable(netpuncher EXCLUDE_FROM_ALL
|
||||
src/netpuncher/C4PuncherHash.h
|
||||
src/netpuncher/main.cpp
|
||||
)
|
||||
if(NOT C4GROUP_TOOL_ONLY)
|
||||
add_executable(netpuncher EXCLUDE_FROM_ALL
|
||||
src/netpuncher/C4PuncherHash.h
|
||||
src/netpuncher/main.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(netpuncher
|
||||
libmisc
|
||||
)
|
||||
target_link_libraries(netpuncher
|
||||
libmisc
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(libmisc iphlpapi ws2_32)
|
||||
if(WIN32)
|
||||
target_link_libraries(libmisc iphlpapi ws2_32)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS $<$<CONFIG:Debug>:_DEBUG>)
|
||||
|
@ -1281,7 +1318,7 @@ if (APPLE AND NOT CMAKE_GENERATOR STREQUAL "Xcode")
|
|||
set(EXECUTABLE_NAME openclonk)
|
||||
endif()
|
||||
|
||||
if(NOT HEADLESS_ONLY)
|
||||
if(NOT HEADLESS_ONLY AND NOT C4GROUP_TOOL_ONLY)
|
||||
set_target_properties(openclonk PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/src/res/Info.plist")
|
||||
endif()
|
||||
|
||||
|
@ -1367,7 +1404,9 @@ endif()
|
|||
############################################################################
|
||||
# Miscellaneous
|
||||
############################################################################
|
||||
add_subdirectory(tests)
|
||||
if(NOT C4GROUP_TOOL_ONLY)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
|
||||
|
@ -1415,18 +1454,20 @@ IF(WITH_AUTOMATIC_UPDATE)
|
|||
INSTALL(CODE "MESSAGE(SEND_ERROR \"Installation is only supported for WITH_AUTOMATIC_UPDATE disabled\")")
|
||||
ENDIF()
|
||||
|
||||
# hack to build the data on install, see
|
||||
# http://public.kitware.com/Bug/view.php?id=8438
|
||||
add_custom_target(data)
|
||||
set_property(TARGET data PROPERTY FOLDER "Setup")
|
||||
install(
|
||||
CODE
|
||||
"execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target data
|
||||
)"
|
||||
)
|
||||
if(NOT C4GROUP_TOOL_ONLY)
|
||||
# hack to build the data on install, see
|
||||
# http://public.kitware.com/Bug/view.php?id=8438
|
||||
add_custom_target(data)
|
||||
set_property(TARGET data PROPERTY FOLDER "Setup")
|
||||
install(
|
||||
CODE
|
||||
"execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target data
|
||||
)"
|
||||
)
|
||||
endif()
|
||||
|
||||
if (NOT APPLE)
|
||||
if (NOT APPLE AND NOT C4GROUP_TOOL_ONLY)
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/res/oc32.png
|
||||
DESTINATION share/icons/hicolor/32x32/apps
|
||||
|
@ -1461,78 +1502,88 @@ ENDIF()
|
|||
|
||||
# When cross-compiling, import c4group from a native build
|
||||
IF(CMAKE_CROSSCOMPILING)
|
||||
SET(IMPORT_NATIVE_TOOLS "IMPORT_NATIVE_TOOLS-NOTFOUND" CACHE FILEPATH "Export file from a native build")
|
||||
INCLUDE(${IMPORT_NATIVE_TOOLS})
|
||||
SET(native_c4group native-c4group)
|
||||
FIND_PROGRAM(C4GROUP_PATH NAMES c4group PATHS)
|
||||
|
||||
IF (NOT C4GROUP_PATH)
|
||||
SET(IMPORT_NATIVE_TOOLS "IMPORT_NATIVE_TOOLS-NOTFOUND" CACHE FILEPATH "Export file from a native build")
|
||||
INCLUDE(${IMPORT_NATIVE_TOOLS})
|
||||
SET(native_c4group native-c4group)
|
||||
ELSE()
|
||||
SET(native_c4group ${C4GROUP_PATH})
|
||||
ENDIF()
|
||||
ELSE()
|
||||
SET(native_c4group c4group)
|
||||
ENDIF()
|
||||
|
||||
# NOTE: The scripts that does the autobuilds and ultimately the automated
|
||||
# releases as well do keep their own list of group files around currently.
|
||||
# So if you change anything here, change it in the release scripts as well.
|
||||
# See openclonk-release-scripts.git/groupcontent.py
|
||||
set(OC_C4GROUPS
|
||||
Graphics.ocg
|
||||
Material.ocg
|
||||
Sound.ocg
|
||||
System.ocg
|
||||
Objects.ocd
|
||||
Decoration.ocd
|
||||
Arena.ocf
|
||||
Parkour.ocf
|
||||
Defense.ocf
|
||||
Missions.ocf
|
||||
Tutorials.ocf
|
||||
Worlds.ocf
|
||||
)
|
||||
if(APPLE)
|
||||
list(APPEND OC_C4GROUPS Music.ocg)
|
||||
endif()
|
||||
|
||||
foreach(group ${OC_C4GROUPS})
|
||||
if (APPLE)
|
||||
if (CMAKE_GENERATOR STREQUAL Xcode)
|
||||
add_custom_command(TARGET openclonk
|
||||
POST_BUILD COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tools/osx_pack_gamedata.sh"
|
||||
"$<TARGET_FILE:${native_c4group}>"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/planet/${group}"
|
||||
# leave out third parameter here so the script can figure out Xcode-ish paths as usual
|
||||
DEPENDS "${native_c4group}"
|
||||
)
|
||||
else()
|
||||
add_custom_command(TARGET openclonk
|
||||
POST_BUILD COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tools/osx_pack_gamedata.sh"
|
||||
"$<TARGET_FILE:${native_c4group}>"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/planet/${group}"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/openclonk.app/Contents/Resources"
|
||||
DEPENDS "${native_c4group}"
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${group}
|
||||
COMMAND "${native_c4group}" ARGS "${CMAKE_CURRENT_SOURCE_DIR}/planet/${group}" -t "${CMAKE_CURRENT_BINARY_DIR}/${group}"
|
||||
MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/planet/${group}
|
||||
DEPENDS "${native_c4group}"
|
||||
VERBATIM
|
||||
)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${group} DESTINATION share/games/openclonk)
|
||||
if(NOT C4GROUP_TOOL_ONLY)
|
||||
# NOTE: The scripts that does the autobuilds and ultimately the automated
|
||||
# releases as well do keep their own list of group files around currently.
|
||||
# So if you change anything here, change it in the release scripts as well.
|
||||
# See openclonk-release-scripts.git/groupcontent.py
|
||||
set(OC_C4GROUPS
|
||||
Graphics.ocg
|
||||
Material.ocg
|
||||
Sound.ocg
|
||||
System.ocg
|
||||
Objects.ocd
|
||||
Decoration.ocd
|
||||
Arena.ocf
|
||||
Parkour.ocf
|
||||
Defense.ocf
|
||||
Missions.ocf
|
||||
Tutorials.ocf
|
||||
Worlds.ocf
|
||||
)
|
||||
if(APPLE)
|
||||
list(APPEND OC_C4GROUPS Music.ocg)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
foreach(group ${OC_C4GROUPS})
|
||||
if (APPLE)
|
||||
if (CMAKE_GENERATOR STREQUAL Xcode)
|
||||
add_custom_command(TARGET openclonk
|
||||
POST_BUILD COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tools/osx_pack_gamedata.sh"
|
||||
"$<TARGET_FILE:${native_c4group}>"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/planet/${group}"
|
||||
# leave out third parameter here so the script can figure out Xcode-ish paths as usual
|
||||
DEPENDS "${native_c4group}"
|
||||
)
|
||||
else()
|
||||
add_custom_command(TARGET openclonk
|
||||
POST_BUILD COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tools/osx_pack_gamedata.sh"
|
||||
"$<TARGET_FILE:${native_c4group}>"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/planet/${group}"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/openclonk.app/Contents/Resources"
|
||||
DEPENDS "${native_c4group}"
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${group}
|
||||
COMMAND "${native_c4group}" ARGS "${CMAKE_CURRENT_SOURCE_DIR}/planet/${group}" -t "${CMAKE_CURRENT_BINARY_DIR}/${group}"
|
||||
MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/planet/${group}
|
||||
DEPENDS "${native_c4group}"
|
||||
VERBATIM
|
||||
)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${group} DESTINATION share/games/openclonk)
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(NOT APPLE)
|
||||
if(NOT HEADLESS_ONLY)
|
||||
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/planet/Music.ocg DESTINATION share/games/openclonk)
|
||||
endif()
|
||||
# group files (game data)
|
||||
add_custom_target(groups DEPENDS ${OC_C4GROUPS})
|
||||
set_property(TARGET groups PROPERTY FOLDER "Setup")
|
||||
add_dependencies(data groups)
|
||||
if(NOT C4GROUP_TOOL_ONLY)
|
||||
# group files (game data)
|
||||
add_custom_target(groups DEPENDS ${OC_C4GROUPS})
|
||||
set_property(TARGET groups PROPERTY FOLDER "Setup")
|
||||
add_dependencies(data groups)
|
||||
endif()
|
||||
# Install binaries
|
||||
install(TARGETS c4group DESTINATION bin)
|
||||
endif()
|
||||
if(NOT HEADLESS_ONLY)
|
||||
if(NOT HEADLESS_ONLY AND NOT C4GROUP_TOOL_ONLY)
|
||||
if(NOT APPLE)
|
||||
# Install new files
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/openclonk.desktop DESTINATION share/applications)
|
||||
|
@ -1558,26 +1609,28 @@ endif()
|
|||
# setup_openclonk.exe
|
||||
############################################################################
|
||||
|
||||
find_program(MAKENSIS makensis PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS])
|
||||
if(NOT C4GROUP_TOOL_ONLY)
|
||||
find_program(MAKENSIS makensis PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS])
|
||||
|
||||
if(NOT HEADLESS_ONLY)
|
||||
add_custom_command(
|
||||
OUTPUT setup_openclonk.exe
|
||||
COMMAND ${MAKENSIS} -NOCD -DSRCDIR=${CMAKE_CURRENT_SOURCE_DIR} -DPROGRAMFILES=$PROGRAMFILES "-DPRODUCT_NAME=${C4ENGINENAME}" "-DPRODUCT_COMPANY=${C4PROJECT}" "-DCLONK=$<TARGET_FILE_DIR:openclonk>\\$<TARGET_FILE_NAME:openclonk>" "-DC4GROUP=$<TARGET_FILE_DIR:c4group>\\$<TARGET_FILE_NAME:c4group>" ${CMAKE_CURRENT_SOURCE_DIR}/tools/install/oc.nsi "-XOutFile setup_openclonk.exe"
|
||||
MAIN_DEPENDENCY
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/install/oc.nsi
|
||||
DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/install/header.bmp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/install/inst.ico
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/install/uninst.ico
|
||||
${OC_C4GROUPS} openclonk c4group
|
||||
VERBATIM
|
||||
)
|
||||
if(NOT HEADLESS_ONLY)
|
||||
add_custom_command(
|
||||
OUTPUT setup_openclonk.exe
|
||||
COMMAND ${MAKENSIS} -NOCD -DSRCDIR=${CMAKE_CURRENT_SOURCE_DIR} -DPROGRAMFILES=$PROGRAMFILES "-DPRODUCT_NAME=${C4ENGINENAME}" "-DPRODUCT_COMPANY=${C4PROJECT}" "-DCLONK=$<TARGET_FILE_DIR:openclonk>\\$<TARGET_FILE_NAME:openclonk>" "-DC4GROUP=$<TARGET_FILE_DIR:c4group>\\$<TARGET_FILE_NAME:c4group>" ${CMAKE_CURRENT_SOURCE_DIR}/tools/install/oc.nsi "-XOutFile setup_openclonk.exe"
|
||||
MAIN_DEPENDENCY
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/install/oc.nsi
|
||||
DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/install/header.bmp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/install/inst.ico
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tools/install/uninst.ico
|
||||
${OC_C4GROUPS} openclonk c4group
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
add_custom_target(setup
|
||||
DEPENDS setup_openclonk.exe groups
|
||||
)
|
||||
set_property(TARGET setup PROPERTY FOLDER "Setup")
|
||||
add_custom_target(setup
|
||||
DEPENDS setup_openclonk.exe groups
|
||||
)
|
||||
set_property(TARGET setup PROPERTY FOLDER "Setup")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
############################################################################
|
||||
|
|
17
Credits.txt
|
@ -1,15 +1,17 @@
|
|||
<Engine and Tools>
|
||||
Sven Eberhardt (Sven2)
|
||||
Armin Burgmeier (Clonk-Karl)
|
||||
Günther Brammer (Günther)
|
||||
Nicolas Hake (Isilkor)
|
||||
Armin Burgmeier (Clonk-Karl)
|
||||
Lukas Werling (Luchs)
|
||||
Martin Plicht (Mortimer)
|
||||
Julius Michaelis (JCaesar)
|
||||
Peter Wortmann (PeterW)
|
||||
Julius Michaelis (Caesar)
|
||||
|
||||
<Scripting and Content>
|
||||
Maikel de Vries (Maikel)
|
||||
David Dormagen (Zapper)
|
||||
Mark Haßelbusch (Marky)
|
||||
Felix Wagner (Clonkonaut)
|
||||
Bernhard Bonigl (Boni)
|
||||
|
||||
|
@ -26,11 +28,8 @@ Martin Strohmeier (K-Pone)
|
|||
<Administration>
|
||||
Tobias Zwick (Newton)
|
||||
|
||||
<Thanks to our package maintainers>
|
||||
Benedict Etzel (B_E), Philipp Kern (pkern), Kevin Zheng and more
|
||||
|
||||
<Special Thanks to Contributors>
|
||||
Martin Adam (Win), Florian Graier (Nachtfalter), Mark Haßelbusch (Marky), Merten Ehmig (pluto), Benjamin Herr (Loriel), Armin Schäfer, Pyrit, Philip Holzmann (Batman), Alexander Semeniuk (AlteredARMOR), Andriel, Peewee, Oliver Schneider (ker), Fabian Pietsch, Manuel Rieke (MrBeast), Felix Riese (Fungiform), Carl-Philip Hänsch (Carli), Sebastian Rühl, Gurkenglas and many more:
|
||||
Luchs, Asmageddon, mizipzor, Tim Blume, Apfelclonk, Sven-Hendrik Haase, Lauri Niskanen (Ape), Daniel Theuke (ST-DDT), Russell, Stan, TomyLobo, Clonkine, Koronis, Johannes Nixdorf (mixi), grgecko, Dominik Bayerl, Misty de Meo, Lorenz Schwittmann, hasufell, Jan Heberer, dylanstrategie, Checkmaty, Faby
|
||||
|
||||
Also, big thanks to Matthes Bender and all those who contributed to previous Clonk titles for the passion they put into the game and for agreeing to make Clonk open source.
|
||||
Contributors for OpenClonk 8.0: George Tokmaji (Fulgen), Martin Adam (Win), Merten Ehmig (pluto), Florian Graier (Nachtfalter), Philip Holzmann (Foaly), Dominik Bayerl (Kanibal), Linus Heckemann (sphalerite), Pyrit, Thomas Wiest (KKenny), Armin Schäfer, Tushar Maheshwari, jok, Tarte, Philip Kern (pkern), Arne Schauf (NativeException), Matthias Mailänder, marsmoon
|
||||
Previous contributors: Tim Blume, Sven-Hendrik Haase, Carl-Philip Hänsch (Carli), Jan Heberer, Benjamin Herr (Loriel), Lauri Niskanen (Ape), Johannes Nixdorf (mixi), Misty de Meo, Fabian Pietsch, Manuel Rieke (MrBeast), Felix Riese (Fungiform), Sebastian Rühl, Oliver Schneider (ker), Lorenz Schwittmann, Alexander Semeniuk (AlteredARMOR), Daniel Theuke (ST-DDT), Andriel, Apfelclonk, Asmageddon, Checkmaty, Clonkine, dylanstrategie, Faby, grgecko, Gurkenglas, hasufell, Koronis, mizipzor, Peewee, Russell, Stan, TomyLobo
|
||||
Also thanks to our Linux package maintainers Benedict Etzel (B_E), Linus Heckemann (sphalerite), Philip Kern (pkern), Matthias Mailänder, Julian Ospald (hasufell), Kevin Zheng, and more
|
||||
Finally, a big thanks to Matthes Bender and all those who contributed to previous Clonk titles for the passion they put into the game and for agreeing to make Clonk open source.
|
||||
|
|
|
@ -23,8 +23,8 @@ SET(C4ENGINENAME "OpenClonk")
|
|||
SET(C4ENGINENICK "openclonk")
|
||||
|
||||
SET(C4XVER1 8)
|
||||
SET(C4XVER2 0)
|
||||
SET(C4XVER2 1)
|
||||
|
||||
# Set this variable to any string for pre-release versions, like "alpha" or
|
||||
# "rc1". Don't supply a value (FALSE) for release versions.
|
||||
SET(C4VERSIONEXTRA "rc1")
|
||||
SET(C4VERSIONEXTRA FALSE)
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
# OpenClonk, http://www.openclonk.org
|
||||
#
|
||||
# Copyright (c) 2018, The OpenClonk Team and contributors
|
||||
#
|
||||
# Distributed under the terms of the ISC license; see accompanying file
|
||||
# "COPYING" for details.
|
||||
#
|
||||
# "Clonk" is a registered trademark of Matthes Bender, used with permission.
|
||||
# See accompanying file "TRADEMARK" for details.
|
||||
#
|
||||
# To redistribute this file separately, substitute the full license texts
|
||||
# for the above references.
|
||||
|
||||
# GCC6 doesn't work well with CMake while cross-compiling. See bugs:
|
||||
# https://gitlab.kitware.com/cmake/cmake/issues/16291
|
||||
# https://gitlab.kitware.com/cmake/cmake/issues/16919
|
||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70129
|
||||
|
||||
function(HANDLE_GCC_CROSS_INCLUDE_PATHS _lang _gcc_lang_flag)
|
||||
set(_compiler "${CMAKE_${_lang}_COMPILER}")
|
||||
set(_compile_flags "${CMAKE_${_lang}_FLAGS}")
|
||||
separate_arguments(_compile_flags UNIX_COMMAND "${_compile_flags}")
|
||||
execute_process(
|
||||
COMMAND ${_compiler} ${_compile_flags} -v -E -x ${_gcc_lang_flag} /dev/null
|
||||
OUTPUT_QUIET
|
||||
ERROR_VARIABLE _compiler_output
|
||||
)
|
||||
if ("${_compiler_output}" MATCHES "#include <\\.\\.\\.> search starts here:\n *(.*)\nEnd of search list\\.")
|
||||
string(REGEX REPLACE "[\n ]+" " " _search_list "${CMAKE_MATCH_1}")
|
||||
separate_arguments(_search_list)
|
||||
foreach(_directory ${_search_list})
|
||||
get_filename_component(_fixed_component "${_directory}" REALPATH)
|
||||
set(_resolved_list ${_resolved_list} "${_fixed_component}")
|
||||
endforeach()
|
||||
set(CMAKE_${_lang}_IMPLICIT_INCLUDE_DIRECTORIES ${CMAKE_${_lang}_IMPLICIT_INCLUDE_DIRECTORIES} ${_resolved_list} PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
|
@ -118,3 +118,6 @@
|
|||
|
||||
/* Include OpenAL extensions (alext.h) for sound modifiers */
|
||||
#cmakedefine HAVE_ALEXT 1
|
||||
|
||||
/* Path to /proc/self/exe (Linux) or equivalent */
|
||||
#cmakedefine PROC_SELF_EXE "${PROC_SELF_EXE}"
|
||||
|
|
|
@ -60,11 +60,6 @@
|
|||
<col>Integer</col>
|
||||
<col>Weight of the object. Rock 10, clonk 50, hut 1000, castle 10000.</col>
|
||||
</row>
|
||||
<row>
|
||||
<literal_col>Components</literal_col>
|
||||
<col>ID list</col>
|
||||
<col>Elements from which the object is composed. Uncompleted or half grown objects will only have the respective fraction of the components.</col>
|
||||
</row>
|
||||
<row>
|
||||
<literal_col>SolidMask</literal_col>
|
||||
<col>6 integers</col>
|
||||
|
|
|
@ -122,9 +122,14 @@
|
|||
</row>
|
||||
<row>
|
||||
<col>FoWEnabled</col>
|
||||
<col>Integer</col>
|
||||
<col>Bool</col>
|
||||
<col>0 or 1. If 0, FoW is disabled, and the whole landscape is visible. Default 1.</col>
|
||||
</row>
|
||||
<row>
|
||||
<col>EvaluateOnAbort</col>
|
||||
<col>Bool</col>
|
||||
<col>If enabled, the game will be evaluated even when aborted by the player. This is intended for scenarios like Tower of Despair that save progress in players. Default false.</col>
|
||||
</row>
|
||||
</table>
|
||||
</text>
|
||||
<text>
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<!DOCTYPE funcs
|
||||
SYSTEM '../../../clonk.dtd'>
|
||||
<?xml-stylesheet type="text/xsl" href="../../../clonk.xsl"?>
|
||||
<funcs>
|
||||
<func>
|
||||
<title>IsEditor</title>
|
||||
<category>Global</category>
|
||||
<version>8.0 OC</version>
|
||||
<syntax><rtype>bool</rtype></syntax>
|
||||
<desc>Returns whether the current game is an editor game.</desc>
|
||||
<examples>
|
||||
<example>
|
||||
<code>public func InitializePlayer(int plr)
|
||||
{
|
||||
if (IsEditor())
|
||||
<funclink>SetWealth</funclink>funclink>(plr, 10**4);
|
||||
}</code>
|
||||
<text>Gives the player a lot of wealth for testing purposes in editor mode.</text>
|
||||
</example>
|
||||
</examples>
|
||||
</func>
|
||||
<author>Maikel</author><date>2018-02</date>
|
||||
</funcs>
|
|
@ -468,14 +468,14 @@ func IsFirestoneSpot(int x, int y)
|
|||
}
|
||||
|
||||
// ============= Themes =============
|
||||
static const HotIce = new Global {
|
||||
static const DefaultTheme = new Global
|
||||
{
|
||||
InitializeRound = func() { },
|
||||
LavaMat = "^DuroLava",
|
||||
IceMats = ["^Ice-ice", "^Ice-ice2"],
|
||||
AltMatRatio = 50,
|
||||
BackgroundMat = nil,
|
||||
Sky = "Default",
|
||||
|
||||
PlayList = nil,
|
||||
InitializeMusic = func()
|
||||
{
|
||||
|
@ -489,17 +489,31 @@ static const HotIce = new Global {
|
|||
SetPlayList(this.PlayList, NO_OWNER, true);
|
||||
SetGlobalSoundModifier(nil);
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
static const EciToh = new HotIce {
|
||||
static const HotIce = new DefaultTheme
|
||||
{
|
||||
InitializeRound = func()
|
||||
{
|
||||
Stalactite->Place(10 + Random(3));
|
||||
}
|
||||
};
|
||||
|
||||
static const EciToh = new DefaultTheme
|
||||
{
|
||||
LavaMat = "DuroLava",
|
||||
IceMats = ["Coal", "Rock-rock"],
|
||||
AltMatRatio = 8,
|
||||
BackgroundMat = "Tunnel",
|
||||
InitializeRound = func()
|
||||
{
|
||||
Stalactite->Place(10 + Random(3));
|
||||
}
|
||||
};
|
||||
|
||||
static const MiamiIce = new HotIce {
|
||||
static const MiamiIce = new DefaultTheme
|
||||
{
|
||||
IceMats = ["^BlackIce-black", "^BlackIce-black"],
|
||||
Sky = "SkyMiami",
|
||||
PlayList =
|
||||
|
@ -526,6 +540,5 @@ static const MiamiIce = new HotIce {
|
|||
o->SetClrModulation(HSL(time, 255, 100));
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
}
|
||||
};
|
||||
|
|
|
@ -17,7 +17,7 @@ protected func Initialize()
|
|||
// Objects fade after 7 seconds.
|
||||
CreateObject(Rule_ObjectFade)->DoFadeTime(7 * 36);
|
||||
CreateObject(Rule_KillLogs);
|
||||
CreateObject(Rule_Gravestones);
|
||||
CreateObject(Rule_Gravestones)->SetFadeOut(3 * 36);
|
||||
GetRelaunchRule()->SetLastWeaponUse(false);
|
||||
|
||||
//make lava collapse
|
||||
|
@ -101,7 +101,7 @@ global func FxDeathByFireTimer(object target, effect fx, int timer)
|
|||
}
|
||||
}
|
||||
|
||||
CreateParticle("Fire", PV_Random(55, 90), PV_Random(0, 40), PV_Random(-1, 1), PV_Random(0, 20), PV_Random(10, 40), fx.particles, 20);
|
||||
CreateParticle("Fire", PV_Random(55, 95), PV_Random(0, 40), PV_Random(-1, 1), PV_Random(0, 20), PV_Random(10, 40), fx.particles, 20);
|
||||
}
|
||||
|
||||
global func FxLavaBrickResetTimer(object target, effect, int timer)
|
||||
|
|
|
@ -35,9 +35,9 @@ protected func Initialize()
|
|||
|
||||
var waterfall;
|
||||
waterfall = CreateWaterfall(130, 53, 2, "Water");
|
||||
waterfall->SetDirection(4, 0, 3, 6);
|
||||
waterfall->SetDirection(6, 3, 2, 3);
|
||||
waterfall = CreateWaterfall(144, 50, 8, "Water");
|
||||
waterfall->SetDirection(6, 0, 5, 6);
|
||||
waterfall->SetDirection(9, 3, 3, 3);
|
||||
CreateLiquidDrain(100, 315, 10);
|
||||
CreateLiquidDrain(130, 315, 10);
|
||||
CreateLiquidDrain(160, 315, 10);
|
||||
|
|
Before Width: | Height: | Size: 203 B After Width: | Height: | Size: 203 B |
|
@ -1,4 +1,9 @@
|
|||
/* Spray can */
|
||||
/**
|
||||
Spray can
|
||||
Let out the little artist in you!
|
||||
|
||||
@author Sven2
|
||||
*/
|
||||
|
||||
local last_x, last_y, last_ldx, last_ldy;
|
||||
local paint_col;
|
||||
|
@ -6,13 +11,13 @@ local max_dist = 50;
|
|||
|
||||
static SprayCan_last_col;
|
||||
|
||||
protected func Construction()
|
||||
public func Construction()
|
||||
{
|
||||
SetPaintCol(SprayCan_last_col++);
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
func SetPaintCol(int idx)
|
||||
public func SetPaintCol(int idx)
|
||||
{
|
||||
idx %= 5;
|
||||
var tex_name = Format("Paint%s",["Red", "Green", "Teal", "Yellow", "White"][idx]);
|
||||
|
@ -39,7 +44,7 @@ public func HoldingEnabled() { return true; }
|
|||
public func ControlUseHolding(object clonk, int new_x, int new_y)
|
||||
{
|
||||
// Out of reach? Stop spraying.
|
||||
if (Distance(0,0,new_x,new_y) > max_dist)
|
||||
if (Distance(0, 0, new_x, new_y) > max_dist)
|
||||
{
|
||||
SetAction("Idle");
|
||||
return true;
|
||||
|
@ -49,16 +54,22 @@ public func ControlUseHolding(object clonk, int new_x, int new_y)
|
|||
new_x += GetX(); new_y += GetY();
|
||||
|
||||
// (re-)start spraying
|
||||
if (GetAction() != "Spraying") StartSpraying(clonk, new_x, new_y);
|
||||
if (GetAction() != "Spraying")
|
||||
StartSpraying(clonk, new_x, new_y);
|
||||
|
||||
// Spray paint if position moved
|
||||
if (new_x==last_x && new_y == last_y) return true;
|
||||
if (new_x == last_x && new_y == last_y)
|
||||
return true;
|
||||
var wdt = 2;
|
||||
var dx=new_x-last_x, dy=new_y-last_y;
|
||||
var d = Distance(dx,dy);
|
||||
var ldx = dy*wdt/d, ldy = -dx*wdt/d;
|
||||
if (!last_ldx && !last_ldy) { last_ldx=ldx; last_ldy=ldy; }
|
||||
DrawMaterialQuad(paint_col, last_x-last_ldx,last_y-last_ldy, last_x+last_ldx,last_y+last_ldy, new_x+ldx,new_y+ldy, new_x-ldx,new_y-ldy, DMQ_Bridge);
|
||||
var dx = new_x - last_x, dy = new_y - last_y;
|
||||
var d = Distance(dx, dy);
|
||||
var ldx = dy * wdt / d, ldy = -dx *wdt / d;
|
||||
if (!last_ldx && !last_ldy)
|
||||
{
|
||||
last_ldx = ldx;
|
||||
last_ldy = ldy;
|
||||
}
|
||||
DrawMaterialQuad(paint_col, last_x - last_ldx, last_y - last_ldy, last_x + last_ldx, last_y + last_ldy, new_x + ldx, new_y + ldy, new_x - ldx, new_y - ldy, DMQ_Bridge);
|
||||
last_x = new_x; last_y = new_y;
|
||||
last_ldx = ldx; last_ldy = ldy;
|
||||
return true;
|
||||
|
@ -80,14 +91,25 @@ private func StartSpraying(object clonk, int x, int y)
|
|||
{
|
||||
// Go into spray mode and place an initial blob
|
||||
last_x = x; last_y = y;
|
||||
last_ldx=last_ldy=0;
|
||||
last_ldx = last_ldy = 0;
|
||||
var r = Random(90), wdt = 2;
|
||||
var ldx = Sin(r, wdt), ldy = Cos(r, wdt);
|
||||
DrawMaterialQuad(paint_col, x-ldx,y-ldy, x-ldy,y+ldx, x+ldx,y+ldy, x+ldy,y-ldx, DMQ_Bridge);
|
||||
DrawMaterialQuad(paint_col, x - ldx, y - ldy, x - ldy, y + ldx, x + ldx, y + ldy, x + ldy, y - ldx, DMQ_Bridge);
|
||||
SetAction("Spraying");
|
||||
return true;
|
||||
}
|
||||
|
||||
public func Definition(def)
|
||||
{
|
||||
SetProperty("PictureTransformation", Trans_Rotate(-30, 0, 1, 1), def);
|
||||
}
|
||||
|
||||
|
||||
/*-- Properties --*/
|
||||
|
||||
local Collectible = true;
|
||||
local Name = "$Name$";
|
||||
local Description = "$Description$";
|
||||
|
||||
local ActMap = {
|
||||
Spraying = {
|
||||
|
@ -96,15 +118,7 @@ local ActMap = {
|
|||
Length = 1,
|
||||
Delay = 1,
|
||||
Name = "Spraying",
|
||||
Sound = "SprayCan::SprayCan",
|
||||
Sound = "Objects::SprayCan",
|
||||
NextAction = "Spraying",
|
||||
}
|
||||
};
|
||||
|
||||
func Definition(def) {
|
||||
SetProperty("PictureTransformation",Trans_Rotate(-30,0,1,1),def);
|
||||
}
|
||||
|
||||
local Collectible = 1;
|
||||
local Name = "$Name$";
|
||||
local Description = "$Description$";
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.1 KiB |
|
@ -20,12 +20,18 @@ public func Initialize()
|
|||
|
||||
public func CheckObjects()
|
||||
{
|
||||
// Find all the objects on the switch.
|
||||
var obj_on_switch = FindObjects(Find_InRect(-20, -30, 40, 30), Find_AtRect(-20, -10, 40, 8), Find_NoContainer(), Find_Not(Find_Category(C4D_StaticBack)));
|
||||
for (var index = GetLength(obj_on_switch) - 1; index >= 0; index--)
|
||||
{
|
||||
var obj = obj_on_switch[index];
|
||||
if (!obj->GetContact(-1, CNAT_Bottom) || obj->Stuck())
|
||||
RemoveArrayIndex(obj_on_switch, index);
|
||||
}
|
||||
// Get the total mass on the switch.
|
||||
var total_mass = 0;
|
||||
var obj_on_switch = FindObjects(Find_InRect(-20, -30, 40, 30), Find_NoContainer(), Find_Not(Find_Category(C4D_StaticBack)));
|
||||
for (var obj in obj_on_switch)
|
||||
if (obj->GetContact(-1, CNAT_Bottom))
|
||||
total_mass += obj->GetMass();
|
||||
var total_mass = 0;
|
||||
for (var obj in obj_on_switch)
|
||||
total_mass += obj->GetMass();
|
||||
// Determine desired position.
|
||||
var desired_y = 0;
|
||||
if (total_mass >= this.SwitchMass)
|
||||
|
@ -36,9 +42,12 @@ public func CheckObjects()
|
|||
// Determine movement change and move switch plus object on it.
|
||||
var change = BoundBy(desired_y - y_position, -1, 1);
|
||||
for (var obj in obj_on_switch)
|
||||
if (obj->GetContact(-1, CNAT_Bottom))
|
||||
obj->SetPosition(obj->GetX(), obj->GetY() + change);
|
||||
obj->SetPosition(obj->GetX(), obj->GetY() + change);
|
||||
SetPosition(GetX(), GetY() + change);
|
||||
// Do not make objects stuck.
|
||||
for (var obj in obj_on_switch)
|
||||
if (obj->Stuck())
|
||||
obj->SetPosition(obj->GetX(), obj->GetY() - change);
|
||||
y_position += change;
|
||||
// Do moving of target door or perform user actions.
|
||||
if (y_position == desired_y)
|
||||
|
@ -71,6 +80,7 @@ public func SaveScenarioObject(proplist props)
|
|||
{
|
||||
if (!inherited(props, ...)) return false;
|
||||
if (up_action || down_action) props->AddCall("Action", this, "SetActions", up_action, down_action);
|
||||
if (this.SwitchMass != GetID().SwitchMass) props->AddSet("SwitchMass", this, "SwitchMass", this.SwitchMass);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -82,6 +92,7 @@ public func Definition(proplist def)
|
|||
if (!def.EditorProps) def.EditorProps = {};
|
||||
def.EditorProps.up_action = new UserAction.Prop { Name="$UpAction$" };
|
||||
def.EditorProps.down_action = new UserAction.Prop { Name="$DownAction$" };
|
||||
def.EditorProps.SwitchMass = { Type = "int", Name = "$SwitchMassAction$", EditorHelp = "$SwitchMassActionHelp$" };
|
||||
return _inherited(def, ...);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,3 +2,5 @@ Name=Bodenschalter
|
|||
Description=Antiker Gewichtssensor.
|
||||
UpAction=Aktion 'Hoch'
|
||||
DownAction=Aktion 'Runter'
|
||||
SwitchMassAction=Schaltermasse
|
||||
SwitchMassActionHelp=Benötigte Masse um den Schalter aus zu lösen.
|
|
@ -2,3 +2,5 @@ Name=Floor Switch
|
|||
Description=Ancient weight sensor.
|
||||
UpAction='Up' action
|
||||
DownAction='Down' action
|
||||
SwitchMassAction=Switch mass
|
||||
SwitchMassActionHelp=Mass needed to trigger the switch.
|
|
@ -12,7 +12,7 @@ static const KEYPADMENU_BackgroundColor = 0x77000000;
|
|||
static const KEYPADMENU_HoverColor = 0x99888888;
|
||||
static const KEYPADMENU_BarColor = 0x99888888;
|
||||
|
||||
local code, correct_code;
|
||||
local code, correct_code, correct_code_hashed;
|
||||
local correct_code_action, wrong_code_action;
|
||||
local replacement_images;
|
||||
local menu, menu_id, menu_target, menu_controller;
|
||||
|
@ -40,6 +40,12 @@ public func SetKeypadCode(string to_code)
|
|||
return;
|
||||
}
|
||||
|
||||
public func SetKeypadHashedCode(string to_code)
|
||||
{
|
||||
correct_code_hashed = to_code;
|
||||
return;
|
||||
}
|
||||
|
||||
public func GiveAccess(object clonk)
|
||||
{
|
||||
SetSwitchState(true, clonk);
|
||||
|
@ -115,10 +121,17 @@ private func UpdateKeypadGraphics()
|
|||
|
||||
public func SaveScenarioObject(proplist props)
|
||||
{
|
||||
if (!_inherited(props, ...)) return false;
|
||||
if (correct_code) props->AddCall("Code", this, "SetKeypadCode", Format("%v", correct_code));
|
||||
if (correct_code_action || wrong_code_action) props->AddCall("Action", this, "SetCodeActions", correct_code_action, wrong_code_action);
|
||||
if (replacement_images) props->AddCall("Replacements", this, "SetReplacementImages", replacement_images);
|
||||
if (!_inherited(props, ...))
|
||||
return false;
|
||||
// Store the hashed code, but override if the scenario designer changed the code.
|
||||
if (correct_code)
|
||||
props->AddCall("Code", this, "SetKeypadHashedCode", Format("%v", Crypto->ComputeHash(correct_code)));
|
||||
else if (correct_code_hashed)
|
||||
props->AddCall("Code", this, "SetKeypadHashedCode", Format("%v", correct_code_hashed));
|
||||
if (correct_code_action || wrong_code_action)
|
||||
props->AddCall("Action", this, "SetCodeActions", correct_code_action, wrong_code_action);
|
||||
if (replacement_images)
|
||||
props->AddCall("Replacements", this, "SetReplacementImages", replacement_images);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -358,13 +371,13 @@ public func EnterKeypadCode()
|
|||
}
|
||||
else
|
||||
{
|
||||
if (correct_code == nil)
|
||||
if (correct_code == nil && correct_code_hashed == nil)
|
||||
{
|
||||
code = nil;
|
||||
menu.code.value.Text = "$MsgNoCode$";
|
||||
Sound("UI::Error", {player = menu_controller->GetOwner()});
|
||||
}
|
||||
else if (correct_code == code)
|
||||
else if (correct_code == code || correct_code_hashed == Crypto->ComputeHash(code))
|
||||
{
|
||||
code = nil;
|
||||
Sound("UI::Confirmed", {player = menu_controller->GetOwner()});
|
||||
|
@ -398,7 +411,7 @@ public func EnterKeypadCode()
|
|||
public func ResetKeypadCode()
|
||||
{
|
||||
// Only allow resetting the code if the clonk (menu_target) has entered the correct code before.
|
||||
if (correct_code == nil)
|
||||
if (correct_code == nil && correct_code_hashed == nil)
|
||||
{
|
||||
menu_controller.code_reset_state = "reset";
|
||||
menu.code.text.Text = "$MsgEnterNewCode$";
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[DefCore]
|
||||
id=DummyChild
|
||||
id=StoneSign
|
||||
Version=8,0
|
||||
Category=C4D_StaticBack
|
||||
Width=8
|
||||
Width=10
|
||||
Height=8
|
||||
Offset=-4,-4
|
||||
Offset=-5,-4
|
|
@ -0,0 +1,21 @@
|
|||
material StoneSign
|
||||
{
|
||||
receive_shadows on
|
||||
technique
|
||||
{
|
||||
pass
|
||||
{
|
||||
ambient 0.800000011920929 0.800000011920929 0.800000011920929 1.0
|
||||
diffuse 0.6400000190734865 0.6400000190734865 0.6400000190734865 1.0
|
||||
specular 0.06589147448539734 0.06589147448539734 0.06589147448539734 1.0 31.5
|
||||
emissive 0.0 0.0 0.0 1.0
|
||||
|
||||
texture_unit
|
||||
{
|
||||
texture StoneSignDiffuse.jpg
|
||||
tex_address_mode wrap
|
||||
filtering trilinear
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
Stone Sign
|
||||
Is attached to a wall and has an inscription.
|
||||
|
||||
@author Maikel, Foaly (graphics)
|
||||
*/
|
||||
|
||||
#include EnvPack_Guidepost
|
||||
|
||||
|
||||
public func Construction()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Color for messages.
|
||||
public func GetColor() { return 0xffb0b0b0; }
|
||||
|
||||
public func Definition(proplist def)
|
||||
{
|
||||
// Inscription editor props.
|
||||
if (!def.EditorProps)
|
||||
def.EditorProps = {};
|
||||
def.EditorProps.inscription = { Name="$Inscription$", Type="string", EditorHelp="$InscriptionHelp$", Set="SetInscription", Save="Inscription", Translatable=true };
|
||||
def.MeshTransformation = Trans_Mul(Trans_Translate(-5600, -300), Trans_Rotate(90, 0, 1, 0));
|
||||
def.PictureTransformation = Trans_Rotate(90, 0, 1, 0);
|
||||
}
|
||||
|
||||
|
||||
/*-- Properties --*/
|
||||
|
||||
local Name = "$Name$";
|
||||
local Description = "$Description$";
|
After Width: | Height: | Size: 35 KiB |
|
@ -0,0 +1,4 @@
|
|||
Name=Steintafel
|
||||
Description=Behält wichtige Informationen.
|
||||
Inscription=Beschriftung
|
||||
InscriptionHelp=Text der beim Lesen der Steintafel angezeigt wird.
|
|
@ -0,0 +1,4 @@
|
|||
Name=Stone Sign
|
||||
Description=Contains important information.
|
||||
Inscription=Inscription
|
||||
InscriptionHelp=Text that can be read by interacting with the stone sign.
|
|
@ -0,0 +1,14 @@
|
|||
Texture Sources:
|
||||
All textures have been modified.
|
||||
|
||||
Rope Texture:
|
||||
Tim van de Vall <timvandevall.com>
|
||||
Special permission for use in OpenClonk under the CC BY 3.0 license.
|
||||
|
||||
Wood Texture:
|
||||
Public Domain - CC0
|
||||
|
||||
Metal Texture:
|
||||
"Grzesiek" <https://www.flickr.com/photos/stoyan/>
|
||||
<https://www.flickr.com/photos/stoyan/387961807/>
|
||||
CC BY 2.0 (licensed under CC BY 3.0 after modification)
|
|
@ -1,4 +1,7 @@
|
|||
[DefCore]
|
||||
id=Library_CableCar
|
||||
id=WoodenSign
|
||||
Version=8,0
|
||||
Category=C4D_StaticBack
|
||||
Width=12
|
||||
Height=10
|
||||
Offset=-6,-5
|
|
@ -0,0 +1,27 @@
|
|||
material WoodenSign
|
||||
{
|
||||
receive_shadows on
|
||||
technique
|
||||
{
|
||||
pass
|
||||
{
|
||||
scene_blend one zero
|
||||
|
||||
alpha_rejection greater_equal 128
|
||||
alpha_to_coverage on
|
||||
cull_hardware none
|
||||
|
||||
ambient 0.800000011920929 0.800000011920929 0.800000011920929 1.0
|
||||
diffuse 0.6400000190734865 0.6400000190734865 0.6400000190734865 1.0
|
||||
specular 0.09375 0.09375 0.09375 0.0 52.25
|
||||
emissive 0.0 0.0 0.0 0.0
|
||||
|
||||
texture_unit
|
||||
{
|
||||
texture WoodenSign.jpg
|
||||
tex_address_mode wrap
|
||||
filtering trilinear
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
Wooden Sign
|
||||
Is attached to a wall and has an inscription.
|
||||
|
||||
@author Maikel, Foaly (graphics)
|
||||
*/
|
||||
|
||||
#include EnvPack_Guidepost
|
||||
|
||||
|
||||
public func Construction()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
public func Definition(def)
|
||||
{
|
||||
// Inscription editor props.
|
||||
if (!def.EditorProps)
|
||||
def.EditorProps = {};
|
||||
def.EditorProps.inscription = { Name="$Inscription$", Type="string", EditorHelp="$InscriptionHelp$", Set="SetInscription", Save="Inscription", Translatable=true };
|
||||
def.MeshTransformation = Trans_Mul(Trans_Translate(-600, -400), Trans_Rotate(90, 0, 1, 0),Trans_Scale(900));
|
||||
def.PictureTransformation = Trans_Rotate(90, 0, 1, 0);
|
||||
}
|
||||
|
||||
|
||||
/*-- Properties --*/
|
||||
|
||||
local Name = "$Name$";
|
||||
local Description = "$Description$";
|
|
@ -0,0 +1,4 @@
|
|||
Name=Holzbrett
|
||||
Description=Behält wichtige Informationen.
|
||||
Inscription=Beschriftung
|
||||
InscriptionHelp=Text der beim Lesen des Holzbrettes angezeigt wird.
|
|
@ -0,0 +1,4 @@
|
|||
Name=Wooden Sign
|
||||
Description=Contains important information.
|
||||
Inscription=Inscription
|
||||
InscriptionHelp=Text that can be read by interacting with the wooden sign.
|
After Width: | Height: | Size: 43 KiB |
After Width: | Height: | Size: 109 KiB |
|
@ -1,19 +1,20 @@
|
|||
/**
|
||||
Guidepost
|
||||
|
||||
@author Graphics Dustin Neß (dness.de), Script Sven2
|
||||
*/
|
||||
|
||||
local Name="$Name$";
|
||||
local Description="$Description$";
|
||||
|
||||
local inscription = "";
|
||||
|
||||
|
||||
// Players can read the sign via the interaction bar.
|
||||
public func IsInteractable() { return inscription != ""; }
|
||||
|
||||
// Adapt appearance in the interaction bar.
|
||||
public func GetInteractionMetaInfo(object clonk)
|
||||
{
|
||||
return { Description = "$MsgRead$", IconName = nil, IconID = GetID(), Selected = false };
|
||||
return { Description = "$MsgRead$", Selected = false };
|
||||
}
|
||||
|
||||
// Called on player interaction.
|
||||
|
@ -33,19 +34,30 @@ public func SetInscription(to_text)
|
|||
// Color for messages
|
||||
public func GetColor() { return 0xffcf9c1a; }
|
||||
|
||||
protected func Construction()
|
||||
public func Construction()
|
||||
{
|
||||
// Pick an angle range that looks good (some angles show it from the side, which looks weird)
|
||||
var angle;
|
||||
if (!Random(2)) angle = -80 + Random(105); else angle = 90 + Random(110);
|
||||
this.MeshTransformation = Trans_Mul(Trans_Rotate(angle,0,10), GetID().MeshTransformation);
|
||||
if (!Random(2))
|
||||
angle = -80 + Random(105);
|
||||
else
|
||||
angle = 90 + Random(110);
|
||||
this.MeshTransformation = Trans_Mul(Trans_Rotate(angle, 0, 10), GetID().MeshTransformation);
|
||||
}
|
||||
|
||||
public func Definition(def)
|
||||
public func Definition(proplist def)
|
||||
{
|
||||
// Model file is way too large
|
||||
// Model file is way too large.
|
||||
def.MeshTransformation = Trans_Scale(360);
|
||||
// Inscription props
|
||||
if (!def.EditorProps) def.EditorProps = {};
|
||||
def.EditorProps.inscription = { Name="$Inscription$", Type="string", EditorHelp="$InscriptionHelp$", Set="SetInscription", Save="Inscription", Translatable=true };
|
||||
def.PictureTransformation = Trans_Scale(900);
|
||||
// Inscription props.
|
||||
if (!def.EditorProps)
|
||||
def.EditorProps = {};
|
||||
def.EditorProps.inscription = { Name = "$Inscription$", Type = "string", EditorHelp = "$InscriptionHelp$", Set = "SetInscription", Save = "Inscription", Translatable = true };
|
||||
}
|
||||
|
||||
|
||||
/*-- Properties --*/
|
||||
|
||||
local Name = "$Name$";
|
||||
local Description = "$Description$";
|
||||
|
|
|
@ -1,24 +1,29 @@
|
|||
/**
|
||||
@author Nachtfalter
|
||||
Guidepost
|
||||
|
||||
@author Sven2, Nachtfalter (graphics)
|
||||
*/
|
||||
|
||||
#include EnvPack_Guidepost
|
||||
|
||||
local Name="$Name$";
|
||||
local Description="$Description$";
|
||||
|
||||
protected func Construction(...)
|
||||
public func Construction(...)
|
||||
{
|
||||
// Pick an angle range that looks good (some angles show it from the side, which looks weird)
|
||||
var angle;
|
||||
if (!Random(2)) angle = -60 + Random(90); else angle = 120 + Random(90);
|
||||
this.MeshTransformation = Trans_Mul(Trans_Rotate(angle,0,10), GetID().MeshTransformation);
|
||||
return _inherited(...);
|
||||
// Pick an angle range that looks good (some angles show it from the side or back, which looks weird).
|
||||
this.MeshTransformation = Trans_Mul(Trans_Rotate(-60 + Random(90), 0, 10), GetID().MeshTransformation);
|
||||
return;
|
||||
}
|
||||
|
||||
public func Definition(def)
|
||||
public func Definition(proplist def)
|
||||
{
|
||||
_inherited(def);
|
||||
// Model file is way too large
|
||||
// Model file is way too large.
|
||||
def.MeshTransformation = Trans_Scale(130);
|
||||
def.PictureTransformation = Trans_Mul(Trans_Translate(-5000, -60000, 150000), Trans_Rotate(-20, 0, 1), Trans_Scale(400));
|
||||
}
|
||||
|
||||
|
||||
/*-- Properties --*/
|
||||
|
||||
local Name = "$Name$";
|
||||
local Description = "$Description$";
|
|
@ -1,5 +0,0 @@
|
|||
[DefCore]
|
||||
id=Ambience
|
||||
Version=8,0
|
||||
Category=C4D_StaticBack | C4D_Rule
|
||||
Picture=0,0,128,128
|
Before Width: | Height: | Size: 14 KiB |
|
@ -1,298 +0,0 @@
|
|||
/**
|
||||
Ambience
|
||||
Controls sound and music depending on the environment the player is in
|
||||
|
||||
@author Sven2
|
||||
*/
|
||||
|
||||
local exec_counter; // counter to distribute execution of players across frames
|
||||
local last_environment; // array indexed by player number: pointer to environment the player was in last
|
||||
local environments; // array of available environments for which it is checked if the player is in. sorted by priority.
|
||||
|
||||
// Initialization
|
||||
protected func Initialize()
|
||||
{
|
||||
// Base environment
|
||||
Environment = {
|
||||
actions = [],
|
||||
min_change_delay = 1,
|
||||
min_initial_change_delay = 5,
|
||||
AddSound = this.Env_AddSound,
|
||||
AddAction = this.Env_AddAction,
|
||||
SetMusic = this.Env_SetMusic
|
||||
};
|
||||
// Register default environments (overloadable)
|
||||
this->InitializeEnvironments();
|
||||
// Periodic execution of ambience events
|
||||
last_environment = [];
|
||||
AddTimer(this.Execute, 10);
|
||||
return true;
|
||||
}
|
||||
|
||||
func InitializeEnvironments()
|
||||
{
|
||||
// Register all standard environments
|
||||
environments = [];
|
||||
// Underwater: Clonk is swimming in water
|
||||
var underwater = this.env_underwater = new Environment {};
|
||||
underwater->SetMusic("underwater");
|
||||
underwater.CheckPlayer = this.EnvCheck_Underwater;
|
||||
AddEnvironment(underwater, 1400);
|
||||
// City: Clonk is surrounded by buildings
|
||||
var city = this.env_city = new Environment {};
|
||||
city->SetMusic("city");
|
||||
city.CheckPlayer = this.EnvCheck_City;
|
||||
AddEnvironment(city, 1200);
|
||||
// Lava: Lava material is nearby
|
||||
var lava = this.env_lava = new Environment {};
|
||||
lava->SetMusic("lava");
|
||||
lava.CheckPlayer = this.EnvCheck_Lava;
|
||||
lava.mat_mask = CreateArray(); // material mask for lava materials. +1 cuz sky.
|
||||
lava.mat_mask[Material("Lava")+1] = true; // loop over materials and check incindiary instead? Whoever introduces the next lava type can do that...
|
||||
lava.mat_mask[Material("DuroLava")+1] = true;
|
||||
lava.min_change_delay = 3; // Easy to miss lava on search.
|
||||
AddEnvironment(lava, 1000);
|
||||
// Underground: Clonk in front of tunnel
|
||||
var underground = this.env_underground = new Environment {};
|
||||
underground->SetMusic("underground");
|
||||
underground.CheckPlayer = this.EnvCheck_Underground;
|
||||
AddEnvironment(underground, 800);
|
||||
// Mountains: Overground and lots of rock around
|
||||
var mountains = this.env_mountains = new Environment {};
|
||||
mountains->SetMusic("mountains");
|
||||
mountains.CheckPlayer = this.EnvCheck_Mountains;
|
||||
mountains.mat_mask = CreateArray(); // material mask for mountain materials. +1 cuz sky.
|
||||
mountains.mat_mask[Material("Rock")+1] = true;
|
||||
mountains.mat_mask[Material("Granite")+1] = true;
|
||||
mountains.mat_mask[Material("Ore")+1] = true;
|
||||
mountains.mat_mask[Material("Gold")+1] = true;
|
||||
mountains.min_change_delay = 3; // Pretty unstable condition
|
||||
AddEnvironment(mountains, 600);
|
||||
// Snow: It's snowing around the clonk
|
||||
var snow = this.env_snow = new Environment {};
|
||||
snow->SetMusic("snow");
|
||||
snow.CheckPlayer = this.EnvCheck_Snow;
|
||||
snow.min_change_delay = 6; // Persist a while after snowing stopped
|
||||
snow.mat = Material("Snow");
|
||||
AddEnvironment(snow, 400);
|
||||
// Night: Sunlight blocked by planet
|
||||
var night = this.env_night = new Environment {};
|
||||
night->SetMusic("night");
|
||||
night.CheckPlayer = this.EnvCheck_Night;
|
||||
AddEnvironment(night, 200);
|
||||
// Overground: Default environment
|
||||
var overground = this.env_overground = new Environment {};
|
||||
overground->SetMusic("overground");
|
||||
overground.CheckPlayer = this.EnvCheck_Overground;
|
||||
overground->AddSound("UI::Ding", 100);
|
||||
AddEnvironment(overground, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
private func Execute()
|
||||
{
|
||||
// Per-player execution every third timer (~.8 seconds)
|
||||
var i=GetPlayerCount(C4PT_User);
|
||||
while (i--) if (!(++exec_counter % 3))
|
||||
{
|
||||
ExecutePlayer(GetPlayerByIndex(i, C4PT_User));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private func ExecutePlayer(int plr)
|
||||
{
|
||||
var cursor = GetCursor(plr);
|
||||
// Determine environment the player is currently in
|
||||
var environment = nil;
|
||||
if (cursor)
|
||||
{
|
||||
var last_env = last_environment[plr];
|
||||
var x = cursor->GetX(), y = cursor->GetY();
|
||||
for (var test_environment in environments)
|
||||
{
|
||||
if (environment = test_environment->CheckPlayer(cursor, x, y, test_environment == last_env))
|
||||
{
|
||||
// We've found a matchign environment.
|
||||
// Was it a change? Then check delays first
|
||||
if (test_environment != last_env)
|
||||
{
|
||||
if (last_env && last_env.no_change_delay)
|
||||
{
|
||||
// Environment should change but a delay is specified. Keep last environment for now.
|
||||
--last_env.no_change_delay;
|
||||
environment = last_env;
|
||||
break;
|
||||
}
|
||||
// New environment and change delay has passed.
|
||||
environment.no_change_delay = environment.min_initial_change_delay;
|
||||
Log("%s environment: %s", GetPlayerName(plr), environment.music);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Was no change: Reset change delays
|
||||
environment.no_change_delay = Max(environment.no_change_delay, environment.min_change_delay);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
last_environment[plr] = environment;
|
||||
if (!environment) return true;
|
||||
// Music by environment
|
||||
this->SetPlayList(environment.music, plr, true, 3000);
|
||||
// Sounds and actions by environment
|
||||
for (var action in environment.actions)
|
||||
if (Random(1000) < action.chance)
|
||||
cursor->Call(action.fn, action.par[0], action.par[1], action.par[2], action.par[3], action.par[4]);
|
||||
return true;
|
||||
}
|
||||
|
||||
func InitializePlayer(int plr)
|
||||
{
|
||||
// Newly joining players should have set playlist immediately (so they don't start playing a random song just to switch it immediately)
|
||||
ExecutePlayer(plr);
|
||||
return true;
|
||||
}
|
||||
|
||||
func RemovePlayer(int plr)
|
||||
{
|
||||
// Ensure newly joining players don't check on another player's environment
|
||||
last_environment[plr] = nil;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected func Activate(int byplr)
|
||||
{
|
||||
MessageWindow(this.Description, byplr);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Environment functions */
|
||||
|
||||
func AddEnvironment(proplist new_env, priority)
|
||||
{
|
||||
if (GetType(priority)) new_env.Priority = priority;
|
||||
this.environments[GetLength(environments)] = new_env;
|
||||
SortArrayByProperty(this.environments, "Priority", true);
|
||||
return true;
|
||||
}
|
||||
|
||||
private func Env_AddSound(string snd_name, chance)
|
||||
{
|
||||
return Env_AddAction(Global.Sound, snd_name, chance ?? 50);
|
||||
}
|
||||
|
||||
private func Env_AddAction(afn, par0, par1, par2, par3, par4)
|
||||
{
|
||||
return this.actions[GetLength(this.actions)] = { fn=afn, par=[par0, par1, par2, par3, par4] };
|
||||
}
|
||||
|
||||
private func Env_SetMusic(string playlist)
|
||||
{
|
||||
this.music = playlist;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Default environment checks */
|
||||
|
||||
private func EnvCheck_Underwater(object cursor, int x, int y, bool is_current)
|
||||
{
|
||||
// Clonk should be swimming
|
||||
if (cursor->GetProcedure() != "SWIM") return nil;
|
||||
// For initial change, clonk should also be diving: Check for breath below 80%
|
||||
// Use > instead of >= to ensure 0-breath-clonks can also get the environment
|
||||
if (!is_current && cursor->GetBreath() > cursor.MaxBreath*4/5) return nil;
|
||||
return this;
|
||||
}
|
||||
|
||||
private func EnvCheck_City(object cursor, int x, int y, bool is_current)
|
||||
{
|
||||
// There must be buildings around the clonk
|
||||
var building_count = cursor->ObjectCount(cursor->Find_AtRect(-180,-100,360,200), Find_Func("IsStructure"));
|
||||
// 3 buildings to start the environment. Just 1 building to sustain it.
|
||||
if (building_count < 3-2*is_current) return nil;
|
||||
return this;
|
||||
}
|
||||
|
||||
private func EnvCheck_Lava(object cursor, int x, int y, bool is_current)
|
||||
{
|
||||
// Check for lava pixels. First check if the last lava pixel we found is still in place.
|
||||
var search_range;
|
||||
if (is_current)
|
||||
{
|
||||
if (this.mat_mask[GetMaterial(this.last_x, this.last_y)+1])
|
||||
if (Distance(this.last_x, this.last_y, x, y) < 140)
|
||||
return this;
|
||||
search_range = 140;
|
||||
}
|
||||
else
|
||||
{
|
||||
search_range = 70;
|
||||
}
|
||||
// Now search for lava in search range
|
||||
var ang = Random(360);
|
||||
for (; search_range >= 0; search_range -= 10)
|
||||
{
|
||||
ang += 200;
|
||||
var x2 = x + Sin(ang, search_range);
|
||||
var y2 = y + Cos(ang, search_range);
|
||||
if (this.mat_mask[GetMaterial(x2, y2)+1])
|
||||
{
|
||||
// Lava found!
|
||||
this.last_x = x2;
|
||||
this.last_y = y2;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
// No lava found
|
||||
return nil;
|
||||
}
|
||||
|
||||
private func EnvCheck_Underground(object cursor, int x, int y, bool is_current)
|
||||
{
|
||||
// Check for underground: No sky at cursor or above
|
||||
if (GetMaterial(x,y)<0) return nil;
|
||||
if (GetMaterial(x,y-30)<0) return nil;
|
||||
if (GetMaterial(x-10,y-20)<0) return nil;
|
||||
if (GetMaterial(x+10,y-20)<0) return nil;
|
||||
return this;
|
||||
}
|
||||
|
||||
private func EnvCheck_Mountains(object cursor, int x, int y, bool is_current)
|
||||
{
|
||||
// Check for mountains: Rock materials below
|
||||
var num_rock;
|
||||
for (var y2=0; y2<=45; y2+=15)
|
||||
for (var x2=-75; x2<=75; x2+=15)
|
||||
num_rock += this.mat_mask[GetMaterial(x+x2,y+y2)+1];
|
||||
// need 15pts on first check; 5 to sustain
|
||||
if (num_rock < 15-is_current*10) return nil;
|
||||
return this;
|
||||
}
|
||||
|
||||
private func EnvCheck_Snow(object cursor, int x, int y, bool is_current)
|
||||
{
|
||||
// Must be snowing from above
|
||||
if (GetPXSCount(this.mat, x-300, y-200, 600, 300) < 20 - is_current*15) return nil;
|
||||
return this;
|
||||
}
|
||||
|
||||
private func EnvCheck_Night(object cursor, int x, int y, bool is_current)
|
||||
{
|
||||
// Night time.
|
||||
if (!Time->IsNight()) return nil;
|
||||
return this;
|
||||
}
|
||||
|
||||
private func EnvCheck_Overground(object cursor, int x, int y, bool is_current)
|
||||
{
|
||||
// This is the fallback environment
|
||||
return this;
|
||||
}
|
||||
|
||||
/*-- Proplist --*/
|
||||
|
||||
local Name = "$Name$";
|
||||
local Description = "$Description$";
|
||||
local Environment;
|
|
@ -1,2 +0,0 @@
|
|||
Name=Ambiente
|
||||
Description=Regelt die Geraeuschkulisse.
|
|
@ -1,3 +0,0 @@
|
|||
Name=Ambience
|
||||
Description=Controls environmental sounds and music.
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
[DefCore]
|
||||
id=Fireglobe
|
||||
Category=C4D_Object
|
||||
Width=10
|
||||
Height=10
|
||||
Offset=-5,-5
|
||||
Vertices=1
|
||||
VertexY=0
|
||||
VertexFriction=100
|
||||
Picture=0,0,60,60
|
||||
Value=8
|
||||
Mass=1
|
||||
Rotate=1
|
Before Width: | Height: | Size: 5.8 KiB |
|
@ -1,7 +0,0 @@
|
|||
[DefCore]
|
||||
id=VisualPath
|
||||
Version=8,0
|
||||
Category=C4D_StaticBack
|
||||
Width=1
|
||||
Height=1
|
||||
Picture=0,0,1,1
|
Before Width: | Height: | Size: 851 B |
|
@ -1,46 +0,0 @@
|
|||
|
||||
public func Set(int sx, int sy, int ex, int ey) {
|
||||
//SetObjectBlitMode(GFX_BLIT_Additive);
|
||||
SetAction("Vis");
|
||||
SetPosition(sx,sy);
|
||||
SetClrModulation(RGB(255,0,0));
|
||||
|
||||
var cl = 1000*Distance(sx,sy,ex,ey)/256;
|
||||
var w = 650;
|
||||
var r = Angle(sx,sy,ex,ey)-180;
|
||||
|
||||
var fsin = -Sin(r, 1000), fcos = Cos(r, 1000);
|
||||
|
||||
var xoff = -4;
|
||||
var yoff = 0;
|
||||
|
||||
var width = +fcos*w/1000, height = +fcos*cl/1000;
|
||||
var xskew = +fsin*cl/1000, yskew = -fsin*w/1000;
|
||||
|
||||
var xadjust = +fcos*xoff + fsin*yoff;
|
||||
var yadjust = -fsin*xoff + fcos*yoff;
|
||||
|
||||
// set matrix values
|
||||
SetObjDrawTransform (
|
||||
width, xskew, xadjust,
|
||||
yskew, height, yadjust
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
local ActMap = {
|
||||
Vis = {
|
||||
Prototype = Action,
|
||||
Name = "Vis",
|
||||
Procedure = DFA_FLOAT,
|
||||
Length = 1,
|
||||
X = 0,
|
||||
Y = 0,
|
||||
Wdt = 32,
|
||||
Hgt = 256,
|
||||
OffX = -16,
|
||||
OffY = 0,
|
||||
NextAction = "Hold"
|
||||
},
|
||||
};
|
||||
local Name = "Path";
|
|
@ -1,206 +0,0 @@
|
|||
/*
|
||||
FireGlobe
|
||||
Author: Newton
|
||||
|
||||
*/
|
||||
|
||||
|
||||
local sx,sy,ex,ey;
|
||||
local vis;
|
||||
local aimed;
|
||||
|
||||
func Construction()
|
||||
{
|
||||
vis = nil;
|
||||
aimed = false;
|
||||
}
|
||||
|
||||
func ControlUse(object clonk, int x, int y)
|
||||
{
|
||||
if(!aimed) return false;
|
||||
|
||||
// fire fireball
|
||||
var angle = Angle(0,0,x,y);
|
||||
Exit();
|
||||
Launch(angle,120,clonk);
|
||||
SetDivert(sx,sy,ex,ey);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
func ControlUseStart(object clonk, int x, int y)
|
||||
{
|
||||
if(aimed) return false;
|
||||
|
||||
sx = x+clonk->GetX();
|
||||
sy = y+clonk->GetY();
|
||||
|
||||
if(vis) vis->RemoveObject();
|
||||
vis = CreateObjectAbove(VisualPath,0,0,clonk->GetOwner());
|
||||
vis->Set(sx,sy,x+clonk->GetX(),y+clonk->GetY());
|
||||
vis["Visibility"]=VIS_Owner;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
func HoldingEnabled() { return true; }
|
||||
|
||||
func ControlUseHolding(object clonk, int x, int y)
|
||||
{
|
||||
if(aimed) return false;
|
||||
|
||||
if(vis) vis->Set(sx,sy,x+clonk->GetX(),y+clonk->GetY());
|
||||
}
|
||||
|
||||
func ControlUseStop(object clonk, int x, int y)
|
||||
{
|
||||
if(aimed) return false;
|
||||
|
||||
ex = x+clonk->GetX();
|
||||
ey = y+clonk->GetY();
|
||||
|
||||
vis->Set(sx,sy,ex,ey);
|
||||
aimed=true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public func DelLine()
|
||||
{
|
||||
if(vis) vis->RemoveObject();
|
||||
}
|
||||
|
||||
public func Deselection()
|
||||
{
|
||||
DelLine();
|
||||
}
|
||||
|
||||
public func Destruction()
|
||||
{
|
||||
DelLine();
|
||||
}
|
||||
|
||||
|
||||
public func Launch(int angle, int str, object shooter)
|
||||
{
|
||||
var xdir = Sin(angle,str);
|
||||
var ydir = Cos(angle,-str);
|
||||
SetXDir(xdir);
|
||||
SetYDir(ydir);
|
||||
|
||||
AddEffect("HitCheck", this, 1,1, nil,nil, shooter);
|
||||
AddEffect("InFlight", this, 1,1, this);
|
||||
}
|
||||
|
||||
|
||||
public func SetDivert(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
var inflight = GetEffect("InFlight",this);
|
||||
inflight.ax = x1;
|
||||
inflight.ay = y1;
|
||||
inflight.bx = x2;
|
||||
inflight.by = y2;
|
||||
inflight.freeflight = true;
|
||||
}
|
||||
|
||||
public func HitObject(object obj)
|
||||
{
|
||||
Hit();
|
||||
}
|
||||
|
||||
public func Hit()
|
||||
{
|
||||
DelLine();
|
||||
Explode(20);
|
||||
}
|
||||
|
||||
// rotate arrow according to speed
|
||||
public func FxInFlightStart(object target, effect, int temp)
|
||||
{
|
||||
if(temp) return;
|
||||
effect.x = target->GetX();
|
||||
effect.y = target->GetY();
|
||||
}
|
||||
|
||||
public func FxInFlightTimer(object target, effect, int time)
|
||||
{
|
||||
var oldx = effect.x;
|
||||
var oldy = effect.y;
|
||||
var newx = target->GetX();
|
||||
var newy = target->GetY();
|
||||
|
||||
if(effect.freeflight)
|
||||
{
|
||||
var ax = effect.ax;
|
||||
var ay = effect.ay;
|
||||
var bx = effect.bx;
|
||||
var by = effect.by;
|
||||
|
||||
var pos = Intersect(oldx, oldy, newx, newy, ax, ay, bx, by);
|
||||
if (pos != nil)
|
||||
{
|
||||
var angle = Angle(ax, ay, bx, by);
|
||||
var speed = 60;
|
||||
target->SetXDir(Sin(angle,speed));
|
||||
target->SetYDir(-Cos(angle, speed));
|
||||
|
||||
effect.freeflight = false;
|
||||
}
|
||||
}
|
||||
|
||||
effect.x = newx;
|
||||
effect.y = newy;
|
||||
}
|
||||
|
||||
// Returns nil or coordinates of intersection.
|
||||
global func Intersect(int Ax, int Ay, int Bx, int By, int Px, int Py, int Qx, int Qy)
|
||||
{
|
||||
var BAx = Bx-Ax;
|
||||
var BAy = By-Ay;
|
||||
var PAx = Px-Ax;
|
||||
var PAy = Py-Ay;
|
||||
var QPx = Qx-Px;
|
||||
var QPy = Qy-Py;
|
||||
|
||||
var denominator = (BAy*QPx - BAx*QPy);
|
||||
var numerator = (BAx*PAy - BAy*PAx);
|
||||
// parallel!
|
||||
if(denominator == 0)
|
||||
{
|
||||
if(numerator != 0) return nil;
|
||||
// on same line somewhere
|
||||
else
|
||||
{
|
||||
return [Ax, Ay];
|
||||
}
|
||||
}
|
||||
|
||||
// in parameter bounds?
|
||||
var Y = 10000 * numerator/denominator;
|
||||
|
||||
if(!Inside(Y,0,10000)) return nil;
|
||||
|
||||
// we don't want division by zero...
|
||||
if(BAy != 0) {
|
||||
numerator = (PAy + Y*QPy/10000);
|
||||
denominator = BAy;
|
||||
}
|
||||
else if(BAx != 0) {
|
||||
numerator = (PAx + Y*QPx/10000);
|
||||
denominator = BAx;
|
||||
}
|
||||
|
||||
// in parameter bounds
|
||||
var X = 10000*numerator / denominator;
|
||||
|
||||
if(!Inside(X,0,10000)) return nil;
|
||||
|
||||
// this is the point...
|
||||
var x = Ax+X*(BAx)/10000;
|
||||
var y = Ay+X*(BAy)/10000;
|
||||
|
||||
return [x, y];
|
||||
}
|
||||
|
||||
local Name = "$Name$";
|
||||
local Collectible = 1;
|
|
@ -1 +0,0 @@
|
|||
Name=Feuerglob
|
|
@ -1 +0,0 @@
|
|||
Name=Fire globe
|
|
@ -1,55 +0,0 @@
|
|||
|
||||
material _missing_material_
|
||||
{
|
||||
receive_shadows off
|
||||
technique
|
||||
{
|
||||
pass
|
||||
{
|
||||
ambient 0.1 0.1 0.1 1.0
|
||||
diffuse 0.8 0.0 0.0 1.0
|
||||
specular 0.5 0.5 0.5 1.0 12.5
|
||||
emissive 0.3 0.3 0.3 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// blender material: flightless_bird_material
|
||||
material flightless_bird_material
|
||||
{
|
||||
receive_shadows on
|
||||
technique
|
||||
{
|
||||
pass flightless_bird_material
|
||||
{
|
||||
ambient 0.800000011920929 0.800000011920929 0.800000011920929 0.0
|
||||
diffuse 0.800000011920929 0.800000011920929 0.800000011920929 0.0
|
||||
specular 0.0 0.0 0.0 0.0 12.5
|
||||
emissive 0.0 0.0 0.0 0.0
|
||||
alpha_to_coverage off
|
||||
colour_write on
|
||||
cull_hardware clockwise
|
||||
depth_check on
|
||||
depth_func less_equal
|
||||
depth_write on
|
||||
illumination_stage
|
||||
light_clip_planes off
|
||||
light_scissor off
|
||||
lighting on
|
||||
normalise_normals off
|
||||
polygon_mode solid
|
||||
scene_blend one zero
|
||||
scene_blend_op add
|
||||
shading gouraud
|
||||
transparent_sorting on
|
||||
texture_unit
|
||||
{
|
||||
texture color.png
|
||||
tex_address_mode wrap
|
||||
scale 1.0 1.0
|
||||
colour_op alpha_blend
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 525 KiB |
|
@ -1,17 +0,0 @@
|
|||
Information for developers:
|
||||
This folder should contain all experimental objects which may be used
|
||||
throughout different scenario's. This aids object designers, cause they
|
||||
may then combine new and old objects more easily, not having to move
|
||||
objects around from scenario to scenario. Please abide this rule if you
|
||||
plan to put experimental objects into the repository. Note that scenario
|
||||
specific objects may still be located in their respective scenario,
|
||||
however, be sure that there will not be any reason to use them elsewhere.
|
||||
|
||||
Another decent thing to check before committing, are C4Script warnings
|
||||
and errors. Also try to keep runtime errors at a minimum. This to prevent
|
||||
other developers from having to fix objects they don't know the details
|
||||
of, in order to develop their own objects.
|
||||
|
||||
Finished objects may be moved to Objects.ocd, though make sure beforehand
|
||||
that these objects do not break anything. Also they shouldn't cause any
|
||||
C4Script warnings or errors, or runtime errors.
|
|
@ -1,14 +0,0 @@
|
|||
[DefCore]
|
||||
id=LiftTower
|
||||
Version=8,0
|
||||
Category=C4D_Structure
|
||||
Width=23
|
||||
Height=68
|
||||
Offset=-11,-10
|
||||
Vertices=4
|
||||
VertexX=-11,11,-11,11
|
||||
VertexY=-10,-10,58,58
|
||||
VertexFriction=50,50,100,100
|
||||
Mass=4500
|
||||
Exclusive=1
|
||||
Construction=1
|
|
@ -1,13 +0,0 @@
|
|||
[DefCore]
|
||||
id=LiftTower_Hook
|
||||
Version=8,0
|
||||
Category=C4D_Object
|
||||
Width=8
|
||||
Height=8
|
||||
Offset=-4,-4
|
||||
Vertices=3
|
||||
VertexX=0,2,-2
|
||||
VertexY=1,-1,-1
|
||||
VertexFriction=50,50,50
|
||||
Mass=4
|
||||
Rotate=1
|
Before Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 511 B |
|
@ -1,140 +0,0 @@
|
|||
/*-- Hook --*/
|
||||
|
||||
local tower, rope;
|
||||
|
||||
/* Connection */
|
||||
|
||||
public func ControlUse(object clonk, int x, int y)
|
||||
{
|
||||
// Search for objects to connect with!
|
||||
var connect = FindObjects(Find_Category(C4D_Vehicle), Find_AtPoint(), Find_Not(Find_Func("NoLiftTowerConnection")), Find_Not(Find_Func("IsEnvironment")));
|
||||
if (!GetLength(connect)) return true;
|
||||
if (GetLength(connect) == 1) return ConnectTo(connect[0]);
|
||||
|
||||
var menu = clonk->CreateRingMenu(GetID(), this);
|
||||
for (var connect_object in connect)
|
||||
menu->AddItem(connect_object);
|
||||
menu->Show();
|
||||
}
|
||||
|
||||
public func Selected(object menu, object selected)
|
||||
{
|
||||
return ConnectTo(selected->GetSymbol());
|
||||
}
|
||||
|
||||
public func ConnectTo(object connect)
|
||||
{
|
||||
Hook();
|
||||
/* rope->BreakRope(true);
|
||||
SetRope(true);
|
||||
rope->Connect(tower, connect);*/
|
||||
rope->Reconnect(connect);
|
||||
AddEffect("Connecting", this, 1, 1, this, nil, connect);
|
||||
return true;
|
||||
}
|
||||
|
||||
private func Hook()
|
||||
{
|
||||
if (Contained()) Exit();
|
||||
this.Collectible = 0;
|
||||
SetCategory(C4D_StaticBack);
|
||||
}
|
||||
private func Unhook()
|
||||
{
|
||||
this.Collectible = 1;
|
||||
SetCategory(C4D_Object);
|
||||
}
|
||||
|
||||
private func FxConnectingStart(object target, effect, int temp, object connect_object)
|
||||
{
|
||||
if (temp) return;
|
||||
effect.connection = connect_object;
|
||||
}
|
||||
|
||||
private func FxConnectingTimer(object target, effect)
|
||||
{
|
||||
if (!rope)
|
||||
{
|
||||
Unhook();
|
||||
return -1;
|
||||
}
|
||||
if (!effect.connection)
|
||||
{
|
||||
Unhook();
|
||||
rope->BreakRope(true);
|
||||
SetRope();
|
||||
return -1;
|
||||
}
|
||||
SetPosition(effect.connection->GetX(), effect.connection->GetY());
|
||||
}
|
||||
|
||||
public func Connected()
|
||||
{
|
||||
return GetEffect("Connecting", this);
|
||||
}
|
||||
|
||||
public func IsInteractable(object clonk)
|
||||
{
|
||||
return !this.Collectible && clonk->GetAction() == "Walk";
|
||||
}
|
||||
|
||||
public func GetInteractionMetaInfo(object clonk)
|
||||
{
|
||||
return { IconID = LiftTower_Hook, Description = "$Unhook$" };
|
||||
}
|
||||
|
||||
public func Interact(object clonk)
|
||||
{
|
||||
if(clonk->Collect(this))
|
||||
{
|
||||
RemoveEffect("Connecting", this);
|
||||
Unhook();
|
||||
rope->BreakRope(true);
|
||||
SetRope();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Events */
|
||||
|
||||
protected func Hit()
|
||||
{
|
||||
Sound("Hits::Materials::Metal::LightMetalHit?");
|
||||
}
|
||||
|
||||
func Construction(object constructor)
|
||||
{
|
||||
tower = constructor;
|
||||
}
|
||||
|
||||
func Initialize()
|
||||
{
|
||||
AddTimer("Rotation", 2);
|
||||
}
|
||||
|
||||
func SetRope(bool no_connect)
|
||||
{
|
||||
rope = CreateObjectAbove(LiftTower_Rope,0,0,NO_OWNER);
|
||||
if (!no_connect) rope->Connect(tower, this);
|
||||
tower->SetRope(rope);
|
||||
return rope;
|
||||
}
|
||||
|
||||
public func Destruction()
|
||||
{
|
||||
if(rope)
|
||||
rope->HookRemoved();
|
||||
}
|
||||
|
||||
protected func Rotation()
|
||||
{
|
||||
if (!rope) return;
|
||||
SetR(rope->GetHookAngle());
|
||||
}
|
||||
|
||||
public func NoLiftTowerConnection() { return true; }
|
||||
|
||||
local Name = "$Name$";
|
||||
local Description = "$Description$";
|
||||
local Collectible = 1;
|
|
@ -1,3 +0,0 @@
|
|||
Name=Haken
|
||||
Description=Drücke [Benutzen] vor einem Fahrzeug oder einem anderen großen Gegenstand, um den Haken zu befestigen.
|
||||
Unhook=Haken abnehmen.
|
|
@ -1,3 +0,0 @@
|
|||
Name=Hook
|
||||
Description=Press [Use] in front of a vehicle or another big object to attach the hook.
|
||||
Unhook=Unhook object.
|
|
@ -1,8 +0,0 @@
|
|||
[DefCore]
|
||||
id=LiftTower_Rope
|
||||
Version=8,0
|
||||
Category=C4D_StaticBack
|
||||
Vertices=2
|
||||
Width=2
|
||||
Height=12
|
||||
Offset=-1,-6
|
Before Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 767 B |
Before Width: | Height: | Size: 4.0 KiB |
|
@ -1,255 +0,0 @@
|
|||
/*
|
||||
Lift Tower Rope
|
||||
Author: Randrian, Clonkonaut
|
||||
|
||||
The rope used for the lift tower.
|
||||
Connect(obj1, obj2) connects two objects
|
||||
BreakRope() breaks the rope
|
||||
*/
|
||||
|
||||
#include Library_Rope
|
||||
|
||||
static const Library_Rope_MAXLENGTH = 1000;
|
||||
|
||||
// Call this to break the rope.
|
||||
public func BreakRope(bool silent)
|
||||
{
|
||||
if(lib_rope_length == -1) return;
|
||||
lib_rope_length = -1;
|
||||
var act1 = lib_rope_objects[0][0];
|
||||
var act2 = lib_rope_objects[1][0];
|
||||
SetAction("Idle");
|
||||
// notify action targets.
|
||||
if (act1 != nil && !silent)
|
||||
act1->~OnRopeBreak();
|
||||
if (act2 != nil && !silent)
|
||||
act2->~OnRopeBreak();
|
||||
RemoveRope();
|
||||
RemoveObject();
|
||||
return;
|
||||
}
|
||||
|
||||
/* --------------------- Callbacks form the rope ---------------------- */
|
||||
|
||||
/* To be overloaded for special segment behaviour */
|
||||
private func CreateSegment(int index, object previous)
|
||||
{
|
||||
if(index == 0) return;
|
||||
var segment;
|
||||
segment = CreateObjectAbove(LiftTower_Rope);
|
||||
return segment;
|
||||
}
|
||||
|
||||
/*-- Rope connecting --*/
|
||||
|
||||
// Connects two objects to the rope, but the length will vary on their positions.
|
||||
public func Connect(object obj1, object obj2, int max_length)
|
||||
{
|
||||
StartRopeConnect(obj1, obj2);
|
||||
if (!max_length) max_length = Library_Rope_MAXLENGTH;
|
||||
SetMaxLength(max_length);
|
||||
SetFixed(true, false);
|
||||
|
||||
SetAction("Hide");
|
||||
|
||||
AddEffect("IntHang", this, 1, 1, this);
|
||||
return;
|
||||
}
|
||||
|
||||
public func Reconnect(object reconnect)
|
||||
{
|
||||
lib_rope_objects[1][0] = reconnect;
|
||||
}
|
||||
|
||||
public func GetConnectStatus() { return !lib_rope_length_auto; }
|
||||
|
||||
public func HookRemoved()
|
||||
{
|
||||
BreakRope();
|
||||
}
|
||||
|
||||
func FxIntHangTimer() { TimeStep(); }
|
||||
|
||||
func UpdateLines()
|
||||
{
|
||||
var oldangle;
|
||||
for(var i=1; i < lib_rope_particle_count; i++)
|
||||
{
|
||||
// Update the Position of the Segment
|
||||
lib_rope_segments[i]->SetPosition(GetPartX(i), GetPartY(i));
|
||||
|
||||
// Calculate the angle to the previous segment
|
||||
var angle = Angle(lib_rope_particles[i].x, lib_rope_particles[i].y, lib_rope_particles[i-1].x, lib_rope_particles[i-1].y);
|
||||
|
||||
// Draw the left line
|
||||
var start = [lib_rope_particles[i-1].x, lib_rope_particles[i-1].y];
|
||||
var end = [lib_rope_particles[i].x, lib_rope_particles[i].y];
|
||||
|
||||
if(i == 1 && lib_rope_particle_count > 2)
|
||||
{
|
||||
angle = Angle(lib_rope_particles[2].x, lib_rope_particles[2].y, lib_rope_particles[0].x, lib_rope_particles[0].y);
|
||||
end = [lib_rope_particles[0].x, lib_rope_particles[0].y];
|
||||
end[0] += -Sin(angle, 45*LIB_ROPE_Precision/10);
|
||||
end[1] += +Cos(angle, 45*LIB_ROPE_Precision/10);
|
||||
lib_rope_segments[i]->SetGraphics("Invis");
|
||||
}
|
||||
|
||||
if(i == 2)
|
||||
{
|
||||
angle = Angle(lib_rope_particles[2].x, lib_rope_particles[2].y, lib_rope_particles[0].x, lib_rope_particles[0].y);
|
||||
start = [lib_rope_particles[0].x, lib_rope_particles[0].y];
|
||||
start[0] += -Sin(angle, 45*LIB_ROPE_Precision/10);
|
||||
start[1] += +Cos(angle, 45*LIB_ROPE_Precision/10);
|
||||
lib_rope_segments[i]->SetGraphics("Short");
|
||||
}
|
||||
|
||||
var diff = Vec_Sub(end,start);
|
||||
var point = Vec_Add(start, Vec_Div(diff, 2));
|
||||
var diffangle = Vec_Angle(diff, [0,0]);
|
||||
var length = Vec_Length(diff)*1000/LIB_ROPE_Precision/10;
|
||||
|
||||
if(i == lib_rope_particle_count-1)
|
||||
{
|
||||
var old = [lib_rope_particles[i-2].x, lib_rope_particles[i-2].y];
|
||||
var old_diff = Vec_Sub(start,old);
|
||||
var o_length = Vec_Length(old_diff)*1000/LIB_ROPE_Precision/10;
|
||||
if(!o_length) diff = old_diff;
|
||||
else diff = Vec_Div(Vec_Mul(old_diff, length),o_length);
|
||||
diffangle = Vec_Angle(diff, [0,0]);
|
||||
point = Vec_Add(start, Vec_Div(diff, 2));
|
||||
}
|
||||
|
||||
lib_rope_segments[i]->SetGraphics(nil);
|
||||
SetLineTransform(lib_rope_segments[i], -diffangle, point[0]*10-GetPartX(i)*1000,point[1]*10-GetPartY(i)*1000, length );
|
||||
|
||||
// Remember the angle
|
||||
oldangle = angle;
|
||||
}
|
||||
}
|
||||
|
||||
public func GetHookAngle()
|
||||
{
|
||||
if(lib_rope_particle_count > 3)
|
||||
return Angle(lib_rope_particles[-2].x, lib_rope_particles[-2].y, lib_rope_particles[-3].x, lib_rope_particles[-3].y)+180;
|
||||
}
|
||||
|
||||
public func SetLineTransform(obj, int r, int xoff, int yoff, int length, int layer, int MirrorSegments) {
|
||||
if(!MirrorSegments) MirrorSegments = 1;
|
||||
var fsin=Sin(r, 1000), fcos=Cos(r, 1000);
|
||||
// set matrix values
|
||||
obj->SetObjDrawTransform (
|
||||
+fcos*MirrorSegments, +fsin*length/1000, xoff,
|
||||
-fsin*MirrorSegments, +fcos*length/1000, yoff,layer
|
||||
);
|
||||
}
|
||||
|
||||
/* Overload */
|
||||
|
||||
local pull_position, pull_faults, pull_frame;
|
||||
|
||||
// Altered to not just pull the objects into the rope's direction but
|
||||
// if the object doesn't not move it is tried to shake it free by applying
|
||||
// impulses to every direction
|
||||
func ForcesOnObjects()
|
||||
{
|
||||
if(!lib_rope_length) return;
|
||||
|
||||
var redo = LengthAutoTryCount();
|
||||
while(lib_rope_length_auto && redo)
|
||||
{
|
||||
var speed = Vec_Length(Vec_Sub([lib_rope_particles[-1].x, lib_rope_particles[-1].y], [lib_rope_particles[-1].oldx, lib_rope_particles[-1].oldy]));
|
||||
if(lib_rope_length == GetMaxLength())
|
||||
{
|
||||
if(ObjContact(lib_rope_objects[1][0]))
|
||||
speed = 40;
|
||||
else speed = 100;
|
||||
}
|
||||
if(speed > 150) DoLength(1);
|
||||
else if(speed < 50) DoLength(-1);
|
||||
else redo = 0;
|
||||
if(redo) redo --;
|
||||
}
|
||||
var j = 0;
|
||||
if (PullObjects())
|
||||
for (var i = 0; i < 2; i++)
|
||||
{
|
||||
if (i == 1) j = lib_rope_particle_count-1;
|
||||
var obj = lib_rope_objects[i][0];
|
||||
|
||||
if (obj == nil || !lib_rope_objects[i][1]) continue;
|
||||
|
||||
if (obj->Contained())
|
||||
obj = obj->Contained();
|
||||
|
||||
if (obj->GetAction() == "Walk" || obj->GetAction() == "Scale" || obj->GetAction() == "Hangle" || obj->GetAction() == "Climb")
|
||||
obj->SetAction("Jump");
|
||||
|
||||
var xdir = BoundBy(lib_rope_particles[j].x-lib_rope_particles[j].oldx, -100, 100);
|
||||
var ydir = lib_rope_particles[j].y-lib_rope_particles[j].oldy;
|
||||
|
||||
if (!obj->GetContact(-1))
|
||||
ydir = BoundBy(ydir, -120, 120);
|
||||
|
||||
if (pull_position && pull_frame != FrameCounter() && !Distance(pull_position[0], pull_position[1], obj->GetX(), obj->GetY()))
|
||||
{
|
||||
if (!pull_faults)
|
||||
{
|
||||
ydir *= -1;
|
||||
pull_faults++;
|
||||
}
|
||||
else
|
||||
{
|
||||
xdir *= -1;
|
||||
pull_faults = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pull_position = [obj->GetX(), obj->GetY()];
|
||||
pull_faults = 0;
|
||||
}
|
||||
pull_frame = FrameCounter();
|
||||
|
||||
obj->SetXDir( xdir, LIB_ROPE_Precision);
|
||||
obj->SetYDir( obj->GetYDir(LIB_ROPE_Precision) + ydir, LIB_ROPE_Precision);
|
||||
}
|
||||
}
|
||||
|
||||
// Altered to function in 'ConnectPull' mode
|
||||
public func ConstraintObjects()
|
||||
{
|
||||
if(lib_rope_length < GetMaxLength()) // in the rope library this is
|
||||
{
|
||||
for (var i = 0, i2 = 0; i < 2; i++ || i2--)
|
||||
SetParticleToObject(i2, i);
|
||||
}
|
||||
}
|
||||
|
||||
// This is called constantly by the lift tower as long as something is reeled in
|
||||
// Altered so the rope will not get shorter than the distance between the tower
|
||||
// and the hooked up object
|
||||
public func DoLength(int dolength)
|
||||
{
|
||||
var obj = lib_rope_objects[0][0]; // First connected object
|
||||
var obj2 = lib_rope_objects[1][0]; // Second connected object
|
||||
// I guess this is not possible but just to be sure
|
||||
if (!obj || !obj2) return _inherited(dolength);
|
||||
if (obj->Contained()) obj = obj->Contained();
|
||||
if (obj2->Contained()) obj2 = obj2->Contained();
|
||||
|
||||
// Line would be shorter than the distance? Do nothing
|
||||
if (dolength < 0 && ObjectDistance(obj, obj2) > GetLineLength()/100) return;
|
||||
return _inherited(dolength);
|
||||
}
|
||||
|
||||
func Definition(def)
|
||||
{
|
||||
def.LineColors = [RGB(66,33,00), RGB(66,33,00)];
|
||||
}
|
||||
local ActMap = {
|
||||
Hide = {
|
||||
Prototype = Action,
|
||||
Name = "Hide",
|
||||
},
|
||||
};
|
||||
local Name = "$Name$";
|
|
@ -1 +0,0 @@
|
|||
Name=Seil
|
|
@ -1 +0,0 @@
|
|||
Name=Rope
|
|
@ -1,14 +0,0 @@
|
|||
material Material
|
||||
{
|
||||
receive_shadows on
|
||||
technique
|
||||
{
|
||||
pass
|
||||
{
|
||||
ambient 0.500000 0.500000 0.500000 1.000000
|
||||
diffuse 0.584337 0.584337 0.584337 1.000000
|
||||
specular 0.500000 0.500000 0.500000 1.000000 12.500000
|
||||
emissive 0.000000 0.000000 0.000000 1.000000
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,171 +0,0 @@
|
|||
/*--
|
||||
LiftTower
|
||||
Authors: Clonkonaut
|
||||
--*/
|
||||
|
||||
local hook, rope;
|
||||
local hook_pos, anim_no, stopped, direction;
|
||||
|
||||
static const LIFTTOWER_HOOK_LOOSEDIST = 50;
|
||||
|
||||
public func Construction()
|
||||
{
|
||||
SetProperty("MeshTransformation",Trans_Rotate(RandomX(-20,20),0,1,0));
|
||||
return _inherited(...);
|
||||
}
|
||||
|
||||
protected func Initialize()
|
||||
{
|
||||
OnRopeBreak();
|
||||
hook_pos = CreateArray();
|
||||
anim_no = PlayAnimation("Turn", 10, Anim_Const(0));
|
||||
stopped = true;
|
||||
AddEffect("SpinWheel", this, 0, 5);
|
||||
}
|
||||
|
||||
/* Rope */
|
||||
|
||||
func OnRopeBreak()
|
||||
{
|
||||
if (!hook)
|
||||
hook = CreateObjectAbove(LiftTower_Hook, 0,0, NO_OWNER);
|
||||
hook->Enter(this);
|
||||
}
|
||||
|
||||
/* Interaction */
|
||||
|
||||
func IsInteractable(object clonk)
|
||||
{
|
||||
return GetCon() >= 100;
|
||||
}
|
||||
|
||||
func GetInteractionMetaInfo()
|
||||
{
|
||||
if (!hook) OnRopeBreak();
|
||||
|
||||
if (hook->Contained() == this)
|
||||
return { IconID = LiftTower_Hook, Description = "$TakeHook$" };
|
||||
else
|
||||
return { IconID = LiftTower_Hook, Description = "$Grab$" };
|
||||
}
|
||||
|
||||
func Interact(object clonk)
|
||||
{
|
||||
if (!hook) OnRopeBreak();
|
||||
|
||||
if (hook->Contained() == this)
|
||||
{
|
||||
if (clonk->Collect(hook,nil,nil,true))
|
||||
hook->SetRope();
|
||||
}
|
||||
else
|
||||
{
|
||||
clonk->ObjectCommand("Grab", this);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
func SetRope(object rope_to_set)
|
||||
{
|
||||
rope = rope_to_set;
|
||||
}
|
||||
|
||||
/* Control */
|
||||
|
||||
public func ControlUp(object clonk)
|
||||
{
|
||||
return DrawIn();
|
||||
}
|
||||
public func ControlStop(object clonk)
|
||||
{
|
||||
return RemoveEffect("DrawIn", this);
|
||||
}
|
||||
|
||||
public func DrawIn()
|
||||
{
|
||||
if (!rope) return false;
|
||||
if (!hook) OnRopeBreak();
|
||||
if (hook->Contained() == this) return false;
|
||||
if (ObjectDistance(hook) < LIFTTOWER_HOOK_LOOSEDIST) return false;
|
||||
if (GetEffect("DrawIn", this)) return false;
|
||||
rope->ConnectPull();
|
||||
return AddEffect("DrawIn", this, 1, 1, this);
|
||||
}
|
||||
|
||||
private func FxDrawInTimer(effect)
|
||||
{
|
||||
if (!rope) return -1;
|
||||
if (!hook)
|
||||
{
|
||||
OnRopeBreak();
|
||||
return -1;
|
||||
}
|
||||
rope->DoLength(-1);
|
||||
if (ObjectDistance(hook) < LIFTTOWER_HOOK_LOOSEDIST) return -1;
|
||||
}
|
||||
|
||||
private func FxDrawInStop(object target, effect, int temp)
|
||||
{
|
||||
if (temp) return;
|
||||
if (!rope) return;
|
||||
rope->ConnectLoose();
|
||||
}
|
||||
|
||||
/* Animation */
|
||||
|
||||
protected func FxSpinWheelTimer()
|
||||
{
|
||||
if (!hook) return StopWheel();
|
||||
if (hook->Contained() == this) return StopWheel();
|
||||
if (hook->GetX() == hook_pos[0])
|
||||
if (hook->GetY() == hook_pos[1])
|
||||
return StopWheel();
|
||||
|
||||
stopped = false;
|
||||
var new_direction = false;
|
||||
if (!direction)
|
||||
{
|
||||
direction = 100;
|
||||
new_direction = true;
|
||||
}
|
||||
if (Distance(GetX(),GetY(), hook->GetX(), hook->GetY()) < Distance(GetX(),GetY(), hook_pos[0], hook_pos[1]))
|
||||
{
|
||||
if (direction > 0)
|
||||
{
|
||||
direction = -100;
|
||||
new_direction = true;
|
||||
}
|
||||
}
|
||||
else if (direction < 0)
|
||||
{
|
||||
direction = 100;
|
||||
new_direction = true;
|
||||
}
|
||||
hook_pos = [hook->GetX(), hook->GetY()];
|
||||
if (!new_direction) return;
|
||||
|
||||
if (direction < 0)
|
||||
anim_no = PlayAnimation("Turn", 10, Anim_Linear(GetAnimationPosition(anim_no), GetAnimationLength("Turn"), 0, 40, ANIM_Loop));
|
||||
else
|
||||
anim_no = PlayAnimation("Turn", 10, Anim_Linear(GetAnimationPosition(anim_no), 0, GetAnimationLength("Turn"), 40, ANIM_Loop));
|
||||
}
|
||||
|
||||
private func StopWheel()
|
||||
{
|
||||
if (stopped) return;
|
||||
var position = GetAnimationPosition(anim_no);
|
||||
stopped = true;
|
||||
direction = 0;
|
||||
anim_no = PlayAnimation("Turn", 10, Anim_Const(position), Anim_Const(1000));
|
||||
}
|
||||
|
||||
func Definition(def) {
|
||||
SetProperty("PictureTransformation", Trans_Mul(Trans_Translate(2000,0,7000),Trans_Rotate(-20,1,0,0),Trans_Rotate(30,0,1,0)), def);
|
||||
}
|
||||
|
||||
local Name = "$Name$";
|
||||
local Description = "$Description$";
|
||||
local Touchable = 2;
|
||||
local ContainBlast = true;
|
||||
local BlastIncinerate = 100;
|
|
@ -1,4 +0,0 @@
|
|||
Name=Hebeturm
|
||||
Description=Um schwere Lasten zu heben.
|
||||
TakeHook=Haken nehmen.
|
||||
Grab=Anfassen
|
|
@ -1,4 +0,0 @@
|
|||
Name=Lift Tower
|
||||
Description=For pulling heavy loads.
|
||||
TakeHook=Take the hook.
|
||||
Grab=Grab
|
|
@ -1,14 +0,0 @@
|
|||
[DefCore]
|
||||
id=LiquidTank
|
||||
Version=8,0
|
||||
Category=C4D_Structure
|
||||
Width=40
|
||||
Height=72
|
||||
Offset=-20,-36
|
||||
Vertices=6
|
||||
VertexX=-16,16,-18,18,-18,18
|
||||
VertexY=35,35,0,0,-20,-20
|
||||
VertexFriction=100,100,50,50,50,50
|
||||
Mass=800
|
||||
Exclusive=1
|
||||
Construction=1
|
Before Width: | Height: | Size: 2.4 KiB |
|
@ -1,174 +0,0 @@
|
|||
/**
|
||||
Liquid Tank
|
||||
Holds liquids of any type and can be opened to create a flood.
|
||||
|
||||
@author Maikel
|
||||
*/
|
||||
|
||||
|
||||
#include Library_Structure
|
||||
#include Library_Ownable
|
||||
#include Library_Tank
|
||||
|
||||
|
||||
public func Initialize()
|
||||
{
|
||||
return _inherited(...);
|
||||
}
|
||||
|
||||
public func Construction(object creator)
|
||||
{
|
||||
return _inherited(creator, ...);
|
||||
}
|
||||
|
||||
public func IsHammerBuildable() { return true; }
|
||||
|
||||
|
||||
/*-- Liquid Control --*/
|
||||
|
||||
// Only accept a single liquid at the same time, but accept any liquid type.
|
||||
public func IsLiquidContainerForMaterial(string liquid)
|
||||
{
|
||||
for (var liquid_content in GetLiquidContents())
|
||||
if (GetLiquidDef(liquid) != GetLiquidDef(liquid_content->GetID()))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public func GetLiquidContainerMaxFillLevel(liquid_name)
|
||||
{
|
||||
return this.LiquidCapacity;
|
||||
}
|
||||
|
||||
// The liquid tank may have one drain and one source.
|
||||
public func QueryConnectPipe(object pipe, bool do_msg)
|
||||
{
|
||||
if (GetDrainPipe() && GetSourcePipe())
|
||||
{
|
||||
if (do_msg) pipe->Report("$MsgHasPipes$");
|
||||
return true;
|
||||
}
|
||||
else if (GetSourcePipe() && pipe->IsSourcePipe())
|
||||
{
|
||||
if (do_msg) pipe->Report("$MsgSourcePipeProhibited$");
|
||||
return true;
|
||||
}
|
||||
else if (GetDrainPipe() && pipe->IsDrainPipe())
|
||||
{
|
||||
if (do_msg) pipe->Report("$MsgDrainPipeProhibited$");
|
||||
return true;
|
||||
}
|
||||
else if (pipe->IsAirPipe())
|
||||
{
|
||||
if (do_msg) pipe->Report("$MsgPipeProhibited$");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set to source or drain pipe.
|
||||
public func OnPipeConnect(object pipe, string specific_pipe_state)
|
||||
{
|
||||
if (PIPE_STATE_Source == specific_pipe_state)
|
||||
{
|
||||
SetSourcePipe(pipe);
|
||||
pipe->SetSourcePipe();
|
||||
}
|
||||
else if (PIPE_STATE_Drain == specific_pipe_state)
|
||||
{
|
||||
SetDrainPipe(pipe);
|
||||
pipe->SetDrainPipe();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!GetDrainPipe())
|
||||
OnPipeConnect(pipe, PIPE_STATE_Drain);
|
||||
else if (!GetSourcePipe())
|
||||
OnPipeConnect(pipe, PIPE_STATE_Source);
|
||||
}
|
||||
pipe->Report("$MsgConnectedPipe$");
|
||||
}
|
||||
|
||||
|
||||
/*-- Interaction --*/
|
||||
|
||||
public func IsInteractable(object clonk)
|
||||
{
|
||||
if (GetCon() < 100)
|
||||
return false;
|
||||
return !Hostile(GetOwner(), clonk->GetOwner());
|
||||
}
|
||||
|
||||
public func GetInteractionMetaInfo(object clonk)
|
||||
{
|
||||
if (GetEffect("FxDisperseLiquid", this))
|
||||
return { Description = "$MsgCloseTank$", IconName = nil, IconID = Icon_Enter, Selected = false };
|
||||
return { Description = "$MsgOpenTank$", IconName = nil, IconID = Icon_Exit, Selected = false };
|
||||
}
|
||||
|
||||
public func Interact(object clonk)
|
||||
{
|
||||
var fx = GetEffect("FxDisperseLiquid", this);
|
||||
if (fx)
|
||||
{
|
||||
fx->Remove();
|
||||
return true;
|
||||
}
|
||||
CreateEffect(FxDisperseLiquid, 100, 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
local FxDisperseLiquid = new Effect
|
||||
{
|
||||
Construction = func()
|
||||
{
|
||||
this.Interval = 2;
|
||||
return FX_OK;
|
||||
},
|
||||
Timer = func()
|
||||
{
|
||||
var liquid = Target->Contents();
|
||||
if (!liquid || !liquid->~IsLiquid())
|
||||
return FX_OK;
|
||||
if (liquid->GetLiquidAmount() <= Target.DispersionRate)
|
||||
{
|
||||
liquid->Exit();
|
||||
liquid->SetPosition(Target->GetX(), Target->GetY());
|
||||
liquid->Disperse(180, 40);
|
||||
}
|
||||
else
|
||||
{
|
||||
liquid->RemoveLiquid(nil, Target.DispersionRate);
|
||||
liquid = liquid->GetID()->CreateLiquid(Target.DispersionRate);
|
||||
liquid->SetPosition(Target->GetX(), Target->GetY());
|
||||
liquid->Disperse(180, 40);
|
||||
}
|
||||
// TODO: Sound.
|
||||
return FX_OK;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*-- Contents Control --*/
|
||||
|
||||
public func IsContainer() { return true; }
|
||||
|
||||
protected func RejectCollect(id item, object obj)
|
||||
{
|
||||
// Accept liquids only.
|
||||
if (obj->~IsLiquid())
|
||||
return _inherited(item, obj, ...);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*-- Properties --*/
|
||||
|
||||
local Name = "$Name$";
|
||||
local Description ="$Description$";
|
||||
local BlastIncinerate = 100;
|
||||
local FireproofContainer = true;
|
||||
local HitPoints = 90;
|
||||
local Components = {Wood = 3, Metal = 2};
|
||||
local LiquidCapacity = 10000;
|
||||
local DispersionRate = 40;
|
|
@ -1,11 +0,0 @@
|
|||
Name=Tank
|
||||
Description=Hier können Flüssigkeiten gespeichert werden, aber nur eine Art gleichzeitig.
|
||||
|
||||
MsgConnectedPipe=Rohr angeschlossen.
|
||||
MsgPipeProhibited=Dieses Rohr kann nicht an den Tank angeschlossen werden.
|
||||
MsgHasPipes=Der Tank hat schon ein Zu- und Abflussrohr.
|
||||
MsgSourcePipeProhibited=Zuflussrohre können nicht an den Tank angeschlossen werden.
|
||||
MsgDrainPipeProhibited=Abflussrohre können nicht an den Tank angeschlossen werden.
|
||||
|
||||
MsgOpenTank=Ventil öffnen
|
||||
MsgCloseTank=Ventil schließen
|
|
@ -1,11 +0,0 @@
|
|||
Name=Liquid Tank
|
||||
Description=Liquids can be stored here, but only one type of liquid at the same time.
|
||||
|
||||
MsgConnectedPipe=Connected pipe.
|
||||
MsgPipeProhibited=This pipe cannot be connected to the liquid tank.
|
||||
MsgHasPipes=Liquid tank already has a source and a drain pipe.
|
||||
MsgSourcePipeProhibited=Unable to connect source pipe to the liquid tank.
|
||||
MsgDrainPipeProhibited=Unable to connect drain pipe to the liquid tank.
|
||||
|
||||
MsgOpenTank=Open valve
|
||||
MsgCloseTank=Close valve
|
|
@ -1,6 +0,0 @@
|
|||
[DefCore]
|
||||
id=CableLine
|
||||
Version=8,0
|
||||
Category=C4D_StaticBack
|
||||
Vertices=2
|
||||
Line=1
|
Before Width: | Height: | Size: 141 B |
|
@ -1,106 +0,0 @@
|
|||
/*-- Cable line --*/
|
||||
|
||||
func Initialize()
|
||||
{
|
||||
SetAction("Connect");
|
||||
SetVertexXY(0, GetX(), GetY());
|
||||
SetVertexXY(1, GetX(), GetY());
|
||||
SetProperty("LineColors", [RGB(20, 20, 50), RGB(20, 20, 50)]);
|
||||
}
|
||||
|
||||
public func IsCableLine() { return GetAction() == "Connect"; }
|
||||
|
||||
/** Returns whether this cable is connected to an object. */
|
||||
public func IsConnectedTo(object obj)
|
||||
{
|
||||
return GetActionTarget(0) == obj || GetActionTarget(1) == obj;
|
||||
}
|
||||
|
||||
/** Connects this cable to obj1 and obj2. */
|
||||
public func SetConnectedObjects(obj1, obj2)
|
||||
{
|
||||
if (GetActionTarget(0)) GetActionTarget(0)->~CableDeactivation(activations);
|
||||
if (GetActionTarget(1)) GetActionTarget(1)->~CableDeactivation(activations);
|
||||
|
||||
SetVertexXY(0, obj1->GetX(), obj1->GetY());
|
||||
SetVertexXY(1, obj2->GetX(), obj2->GetY());
|
||||
SetActionTargets(obj1, obj2);
|
||||
obj1->AddCableConnection(this);
|
||||
}
|
||||
|
||||
/** Returns the object which is connected to obj through this cable. */
|
||||
public func GetConnectedObject(object obj)
|
||||
{
|
||||
if (GetActionTarget(0) == obj)
|
||||
return GetActionTarget(1);
|
||||
if (GetActionTarget(1) == obj)
|
||||
return GetActionTarget(0);
|
||||
}
|
||||
|
||||
/* Breaking */
|
||||
|
||||
func LineBreak(bool no_msg)
|
||||
{
|
||||
Sound("Objects::Connect");
|
||||
if (GetActionTarget(0)) GetActionTarget(0)->~CableDeactivation(activations);
|
||||
if (GetActionTarget(1)) GetActionTarget(1)->~CableDeactivation(activations);
|
||||
if (!no_msg)
|
||||
BreakMessage();
|
||||
}
|
||||
|
||||
func BreakMessage()
|
||||
{
|
||||
var line_end = GetActionTarget(0);
|
||||
if (line_end->GetID() != CableLorryReel)
|
||||
line_end = GetActionTarget(1);
|
||||
if (line_end->Contained()) line_end = line_end->Contained();
|
||||
|
||||
line_end->Message("$TxtLinebroke$");
|
||||
}
|
||||
|
||||
/* Activation */
|
||||
|
||||
local activations = 0;
|
||||
|
||||
/** Called by cable cars whenever one proceeds onto this cable. Will be forwarded to connected objects.
|
||||
count increases the activation value. Stations will stop animation only if all activations are deactivated. */
|
||||
public func Activation(int count)
|
||||
{
|
||||
// Count must be > 0
|
||||
if (count < 1) return FatalError("Cable Line: Activation() was called with count < 1.");
|
||||
activations += count;
|
||||
if (GetActionTarget(0)) GetActionTarget(0)->~CableActivation(count);
|
||||
if (GetActionTarget(1)) GetActionTarget(1)->~CableActivation(count);
|
||||
}
|
||||
|
||||
/** Called by cable cars whenever one proceeds off this cable. Will be forwarded to connected objects.
|
||||
count decreases the activation value. Stations will stop animation only if all activations are deactivated. */
|
||||
public func Deactivation(int count)
|
||||
{
|
||||
// Count must be > 0
|
||||
if (count < 1) return FatalError("Cable Line: Deactivation() was called with count < 1.");
|
||||
activations -= count;
|
||||
if (GetActionTarget(0)) GetActionTarget(0)->~CableDeactivation(count);
|
||||
if (GetActionTarget(1)) GetActionTarget(1)->~CableDeactivation(count);
|
||||
}
|
||||
|
||||
/* Saving */
|
||||
|
||||
public func SaveScenarioObject(props)
|
||||
{
|
||||
if (!inherited(props, ...)) return false;
|
||||
SaveScenarioObjectAction(props);
|
||||
if (IsCableLine()) props->AddCall("Connection", this, "SetConnectedObjects", GetActionTarget(0), GetActionTarget(1));
|
||||
return true;
|
||||
}
|
||||
|
||||
local ActMap = {
|
||||
Connect = {
|
||||
Prototype = Action,
|
||||
Name = "Connect",
|
||||
Procedure = DFA_CONNECT,
|
||||
NextAction = "Connect"
|
||||
}
|
||||
};
|
||||
|
||||
local Name = "$Name$";
|
|
@ -1,2 +0,0 @@
|
|||
TxtLinebroke=Seil gerissen
|
||||
Name=Seilbahnseil
|
|
@ -1,2 +0,0 @@
|
|||
TxtLinebroke=Line broke
|
||||
Name=Cable line
|
|
@ -1,14 +0,0 @@
|
|||
[DefCore]
|
||||
id=CableLorryReel
|
||||
Version=8,0
|
||||
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
|
||||
Picture=0,6,64,64
|
Before Width: | Height: | Size: 6.8 KiB |
|
@ -1,68 +0,0 @@
|
|||
/*-- Cable reel --*/
|
||||
|
||||
protected func Hit()
|
||||
{
|
||||
Sound("Hits::Materials::Rock::RockHit?");
|
||||
}
|
||||
|
||||
public func IsToolProduct() { return true; }
|
||||
|
||||
/*-- Line connection --*/
|
||||
|
||||
protected func ControlUse(object clonk, int x, int y)
|
||||
{
|
||||
// Is there an object which accepts power lines?
|
||||
var obj = FindObject(Find_AtPoint(), Find_Func("IsCableCrossing"));
|
||||
// No such object -> message.
|
||||
if (!obj)
|
||||
return clonk->Message("$TxtNoNewLine$");
|
||||
// Is there a cable connected to this wire roll?
|
||||
var line = FindObject(Find_CableLine());
|
||||
// There already is a cable
|
||||
if (line)
|
||||
{
|
||||
if (obj == line->GetActionTarget(0) || obj == line->GetActionTarget(1))
|
||||
{
|
||||
// Cable is already connected to obj -> remove line.
|
||||
line->RemoveObject();
|
||||
Sound("Objects::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("Objects::Connect");
|
||||
obj->AddCableConnection(line);
|
||||
clonk->Message("$TxtConnect$", obj->GetName());
|
||||
//RemoveObject();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else // A new cable needs to be created.
|
||||
{
|
||||
line = CreateObjectAbove(CableLine, 0, 0, NO_OWNER);
|
||||
line->SetActionTargets(this, obj);
|
||||
Sound("Objects::Connect");
|
||||
clonk->Message("$TxtConnect$", obj->GetName());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Finds all power lines connected to obj (can be nil in local calls).
|
||||
private func Find_CableLine(object obj)
|
||||
{
|
||||
if (!obj)
|
||||
obj = this;
|
||||
return [C4FO_Func, "IsConnectedTo", obj];
|
||||
}
|
||||
|
||||
local Name = "$Name$";
|
||||
local Description = "$Description$";
|
||||
local Collectible = 1;
|
|
@ -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.
|
|
@ -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.
|
|
@ -1,4 +0,0 @@
|
|||
[DefCore]
|
||||
id=GUI_DestinationSelectionMenu
|
||||
Version=8,0
|
||||
Category=C4D_StaticBack | C4D_Environment
|
|
@ -1,193 +0,0 @@
|
|||
/**
|
||||
DestinationSelectionMenu
|
||||
Handles the destination selection for cable cars.
|
||||
|
||||
@author Clonkonaut
|
||||
*/
|
||||
|
||||
local Name = "$Name$";
|
||||
local Description = "$Description$";
|
||||
|
||||
// used as a static function
|
||||
public func CreateFor(object cursor, object car, object station)
|
||||
{
|
||||
if (!cursor) return;
|
||||
if (!car) return;
|
||||
if (!station) return;
|
||||
|
||||
var obj = CreateObject(GUI_DestinationSelectionMenu, AbsX(0), AbsY(0), cursor->GetOwner());
|
||||
obj.Visibility = VIS_Owner;
|
||||
|
||||
obj->Init(cursor, car, station);
|
||||
cursor->SetMenu(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
// The Clonk whom the menu was opened for
|
||||
local cursor;
|
||||
// The menu id of the opened menu
|
||||
local menu_id;
|
||||
// The cable car which opened this menu
|
||||
local cable_car;
|
||||
// The station the cable car is hooked up to
|
||||
local cable_station;
|
||||
// A dummy object used to bring light to stations when previewed
|
||||
local dummy;
|
||||
|
||||
public func Close() { return RemoveObject(); }
|
||||
public func IsDestinationMenu() { return true; }
|
||||
public func Show() { this.Visibility = VIS_Owner; return true; }
|
||||
public func Hide() { this.Visibility = VIS_None; return true; }
|
||||
// Called when the menu is open and the player clicks outside.
|
||||
public func OnMouseClick() { return Close(); }
|
||||
|
||||
func Destruction()
|
||||
{
|
||||
if (menu_id)
|
||||
GuiClose(menu_id);
|
||||
if (dummy)
|
||||
dummy->RemoveObject();
|
||||
if (cursor)
|
||||
SetPlrView(cursor->GetOwner(), cursor, true);
|
||||
}
|
||||
|
||||
public func Init(object cursor, object car, object station)
|
||||
{
|
||||
this.cursor = cursor;
|
||||
this.cable_car = car;
|
||||
this.cable_station = station;
|
||||
this.dummy = CreateObject(Dummy, AbsX(station->GetX()), AbsY(station->GetY()), GetOwner());
|
||||
dummy.Visibility = VIS_Owner;
|
||||
dummy->SetLightRange(5, 20);
|
||||
|
||||
var dest_list = station->GetDestinationList(nil);
|
||||
|
||||
var dest_menu = {
|
||||
Target = this,
|
||||
Decoration = GUI_MenuDeco,
|
||||
BackgroundColor = RGB(0, 0, 0),
|
||||
Bottom = "3em",
|
||||
Left = "50% - 5em",
|
||||
Right = "50% + 5em",
|
||||
Priority = 1,
|
||||
Player = cursor->GetOwner(),
|
||||
caption = {
|
||||
Text = "$SelectDestination$",
|
||||
Bottom = "1em",
|
||||
Priority = 2,
|
||||
},
|
||||
buttons = {
|
||||
Top = "1em",
|
||||
Style = GUI_GridLayout,
|
||||
Priority = 999
|
||||
}
|
||||
};
|
||||
|
||||
FillDestinationButtons(dest_menu, dest_list);
|
||||
|
||||
GuiOpen(dest_menu);
|
||||
}
|
||||
|
||||
func FillDestinationButtons(proplist menu, array list)
|
||||
{
|
||||
var priority = 1000;
|
||||
// Left button
|
||||
var left = {
|
||||
Right = "2em",
|
||||
Bottom = "2em",
|
||||
Symbol = Icon_LibraryCableCar,
|
||||
GraphicsName = "LeftGrey",
|
||||
BackgroundColor = { Std = RGB(0, 0, 0), Hover = RGB(100, 30, 30) },
|
||||
Priority = ++priority
|
||||
};
|
||||
if (list[3] > 3)
|
||||
{
|
||||
left.OnMouseIn = GuiAction_SetTag("Hover");
|
||||
left.OnMouseOut = GuiAction_SetTag("Std");
|
||||
left.GraphicsName = "Left";
|
||||
left.OnClick = GuiAction_Call(this, "ShiftSelection", list[0]);
|
||||
}
|
||||
// List buttons
|
||||
var list_button = {
|
||||
Right = "2em",
|
||||
Bottom = "2em",
|
||||
BackgroundColor = { Std = RGB(0, 0, 0), Hover = RGB(100, 30, 30) },
|
||||
OnMouseOut = GuiAction_SetTag("Std")
|
||||
};
|
||||
var buttons = CreateArray(3);
|
||||
for (var i = 0; i < 3; i++)
|
||||
{
|
||||
if (list[i])
|
||||
{
|
||||
buttons[i] = new list_button{
|
||||
Symbol = list[i],
|
||||
Tooltip = Format("$SendTo$", list[i]->GetName()),
|
||||
OnMouseIn = [GuiAction_SetTag("Hover"), GuiAction_Call(this, "PreviewDestination", list[i])],
|
||||
OnClick = GuiAction_Call(this, "SelectDestination", list[i]),
|
||||
Priority = ++priority
|
||||
};
|
||||
} else {
|
||||
buttons[i] = new list_button {};
|
||||
}
|
||||
}
|
||||
// Right button
|
||||
var right = {
|
||||
Right = "2em",
|
||||
Bottom = "2em",
|
||||
Symbol = Icon_LibraryCableCar,
|
||||
GraphicsName = "Grey",
|
||||
BackgroundColor = { Std = RGB(0, 0, 0), Hover = RGB(100, 30, 30) },
|
||||
Priority = ++priority
|
||||
};
|
||||
if (list[3] > 3)
|
||||
{
|
||||
right.OnMouseIn = GuiAction_SetTag("Hover");
|
||||
right.OnMouseOut = GuiAction_SetTag("Std");
|
||||
right.GraphicsName = nil;
|
||||
right.OnClick = GuiAction_Call(this, "ShiftSelection", list[2]);
|
||||
}
|
||||
// Assemble
|
||||
menu.buttons.left = left;
|
||||
menu.buttons.first = buttons[0];
|
||||
menu.buttons.second = buttons[1];
|
||||
menu.buttons.third = buttons[2];
|
||||
menu.buttons.right = right;
|
||||
}
|
||||
|
||||
func PreviewDestination(object to_preview, int plr, int menu_id, int submenu_id, object target)
|
||||
{
|
||||
if (to_preview == nil) return;
|
||||
if (dummy == nil)
|
||||
{
|
||||
dummy = CreateObject(Dummy, AbsX(to_preview->GetX()), AbsY(to_preview->GetY()), GetOwner());
|
||||
dummy.Visibility = VIS_Owner;
|
||||
dummy->SetLightRange(5, 20);
|
||||
}
|
||||
|
||||
SetPlrView(plr, to_preview, true);
|
||||
dummy->SetPosition(to_preview->GetX(), to_preview->GetY());
|
||||
}
|
||||
|
||||
func ShiftSelection(object new_middle, int plr, int menu_id, int submenu_id, object target)
|
||||
{
|
||||
if (!cable_station) return;
|
||||
if (!menu_id) return;
|
||||
|
||||
var update = { buttons = { } };
|
||||
var list = cable_station->GetDestinationList(new_middle);
|
||||
|
||||
FillDestinationButtons(update, list);
|
||||
GuiUpdate(update, menu_id);
|
||||
Sound("UI::Click", true, nil, plr);
|
||||
}
|
||||
|
||||
func SelectDestination(object target, int plr, int menu_id, int submenu_id, object target)
|
||||
{
|
||||
if (target == nil) return;
|
||||
if (!cable_car) return;
|
||||
|
||||
cable_car->SetDestination(target);
|
||||
Sound("UI::Click", true, nil, plr);
|
||||
|
||||
RemoveObject();
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
Name=Zielwahlmenü
|
||||
Description=
|
|
@ -1,4 +0,0 @@
|
|||
Name=Destination Selection Menu
|
||||
Description=
|
||||
SelectDestination=Select a destination:
|
||||
SendTo=Send the cable car to %s
|
Before Width: | Height: | Size: 154 B |