Merge branch 'master' into qteditor
184
CMakeLists.txt
|
@ -1,6 +1,6 @@
|
|||
# OpenClonk, http://www.openclonk.org
|
||||
#
|
||||
# Copyright (c) 2009-2015, The OpenClonk Team and contributors
|
||||
# Copyright (c) 2009-2016, The OpenClonk Team and contributors
|
||||
#
|
||||
# Distributed under the terms of the ISC license; see accompanying file
|
||||
# "COPYING" for details.
|
||||
|
@ -12,6 +12,11 @@
|
|||
# for the above references.
|
||||
|
||||
cmake_minimum_required (VERSION 3.0.2)
|
||||
|
||||
# Don't allow people to build "Release" builds because there's no reason to do that.
|
||||
# Use one of RelWithDebInfo or MinSizeRel instead.
|
||||
set(CMAKE_CONFIGURATION_TYPES Debug RelWithDebInfo MinSizeRel CACHE STRING "List of supported configuration types." FORCE)
|
||||
|
||||
project (openclonk CXX C)
|
||||
|
||||
# CMP0054: Only interpret if() arguments as variables or keywords when unquoted
|
||||
|
@ -45,93 +50,116 @@ set_property(GLOBAL PROPERTY USE_FOLDERS ${PROJECT_FOLDERS})
|
|||
############################################################################
|
||||
include(CheckCXXCompilerFlag)
|
||||
|
||||
set(OC_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
||||
separate_arguments(OC_CXX_FLAGS)
|
||||
set(OC_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
|
||||
separate_arguments(OC_CXX_FLAGS_DEBUG)
|
||||
set(OC_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS})
|
||||
separate_arguments(OC_EXE_LINKER_FLAGS)
|
||||
set(OC_EXE_LINKER_FLAGS_DEBUG ${CMAKE_EXE_LINKER_FLAGS_DEBUG})
|
||||
separate_arguments(OC_EXE_LINKER_FLAGS_DEBUG)
|
||||
|
||||
CHECK_CXX_COMPILER_FLAG("-std=gnu++14" USE_GCC_STD_14)
|
||||
if(USE_GCC_STD_14)
|
||||
list(APPEND OC_CXX_FLAGS "-std=gnu++14")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++14")
|
||||
endif()
|
||||
|
||||
# Enable link-time code generation. We have to do this manually because while
|
||||
# there is a INTERPROCEDURAL_OPTIMIZATION cmake flag, it's only implemented
|
||||
# for icc so far; https://cmake.org/Bug/view.php?id=15939
|
||||
function(add_linker_flags)
|
||||
include(CMakeParseArguments)
|
||||
set(options optimized debug)
|
||||
set(oneValueArgs FLAGS)
|
||||
set(multiValueArgs MODULES)
|
||||
|
||||
cmake_parse_arguments(_alf "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
# Adds some linker flags to all optimized build configurations
|
||||
set(_configurations "")
|
||||
if(_alf_optimized)
|
||||
list(APPEND _configurations MINSIZEREL RELWITHDEBINFO RELEASE)
|
||||
endif()
|
||||
if(_alf_debug)
|
||||
list(APPEND _configurations DEBUG)
|
||||
endif()
|
||||
|
||||
foreach(_module ${_alf_MODULES})
|
||||
string(TOUPPER "${_module}" _obj_type)
|
||||
foreach(_config ${_configurations})
|
||||
set(CMAKE_${_obj_type}_LINKER_FLAGS_${_config} "${CMAKE_${_obj_type}_LINKER_FLAGS_${_config}} ${_alf_FLAGS}" PARENT_SCOPE)
|
||||
endforeach()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
CHECK_CXX_COMPILER_FLAG("-flto" USE_GCC_STYLE_LTCG)
|
||||
if(USE_GCC_STYLE_LTCG)
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -flto")
|
||||
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -flto")
|
||||
add_linker_flags(optimized MODULES exe shared FLAGS -flto)
|
||||
|
||||
# Use GCC's ar and ranlib wrappers if necessary, because the plain ones
|
||||
# don't understand lto objects without an explicit plugin parameter
|
||||
if(CMAKE_C_COMPILER MATCHES "gcc$")
|
||||
set(LTCG_NEEDS_AR_WRAPPER 1)
|
||||
set(LTCG_AR_WRAPPER_PREFIX "${CMAKE_C_COMPILER}")
|
||||
elseif(CMAKE_C_COMPILER MATCHES "cc$")
|
||||
set(LTCG_NEEDS_AR_WRAPPER 1)
|
||||
set(LTCG_AR_WRAPPER_PREFIX "gcc")
|
||||
else()
|
||||
set(LTCG_NEEDS_AR_WRAPPER 0)
|
||||
endif()
|
||||
|
||||
if(LTCG_NEEDS_AR_WRAPPER)
|
||||
find_program(AR_WRAPPER "${LTCG_AR_WRAPPER_PREFIX}-ar")
|
||||
if (AR_WRAPPER)
|
||||
message("Using ${AR_WRAPPER} instead of ${CMAKE_AR} to support lto objects.")
|
||||
set(CMAKE_AR "${AR_WRAPPER}" CACHE FILEPATH "Path to an ar that supports lto objects." FORCE)
|
||||
endif()
|
||||
find_program(RANLIB_WRAPPER "${LTCG_AR_WRAPPER_PREFIX}-ranlib")
|
||||
if (RANLIB_WRAPPER)
|
||||
message("Using ${RANLIB_WRAPPER} instead of ${CMAKE_RANLIB} to support lto objects.")
|
||||
set(CMAKE_RANLIB "${RANLIB_WRAPPER}" CACHE FILEPATH "Path to a ranlib that supports lto objects." FORCE)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
list(APPEND OC_CXX_FLAGS /MP)
|
||||
list(REMOVE_ITEM OC_CXX_FLAGS_DEBUG /Gm)
|
||||
# Disable non-standard conversion from string literal to (nonconst) char*
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:strictStrings")
|
||||
|
||||
# Enable multi-core builds
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
|
||||
# Enable LTCG for release builds
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Ob2 /GL")
|
||||
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /Ob2 /GL")
|
||||
add_linker_flags(optimized MODULES exe shared static FLAGS /LTCG)
|
||||
|
||||
# Activate edit-and-continue
|
||||
list(REMOVE_ITEM OC_CXX_FLAGS_DEBUG /Zi)
|
||||
list(APPEND OC_CXX_FLAGS_DEBUG /ZI /Gy)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /ZI /Gy")
|
||||
|
||||
# do not link the release CRT in debug builds
|
||||
list(APPEND OC_EXE_LINKER_FLAGS_DEBUG "/NODEFAULTLIB:MSVCRT")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:MSVCRT")
|
||||
set(HAVE_PRECOMPILED_HEADERS ON CACHE INTERNAL "Compiler supports precompiled headers")
|
||||
|
||||
# Suppress warnings about "non-secure" functions
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_WARNINGS)
|
||||
# Disable warning C4244: 'conversion' conversion from 'type1' to 'type2', possible loss of data
|
||||
list(APPEND OC_CXX_FLAGS "/wd4244")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4244")
|
||||
# Disable warning C4267: 'var' : conversion from 'size_t' to 'type', possible loss of data (64 bit build only)
|
||||
list(APPEND OC_CXX_FLAGS "/wd4267")
|
||||
endif()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
list(APPEND OC_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} /wd4267")
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
list(APPEND OC_CXX_FLAGS -Wall -Wextra -Wextra-tokens -Wpointer-arith -Wno-cast-align -Wno-reorder -Wno-unused-parameter -Wnon-virtual-dtor -Woverloaded-virtual)
|
||||
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")
|
||||
endif()
|
||||
|
||||
if(WIN32 AND MINGW)
|
||||
# Activate DEP and ASLR
|
||||
list(APPEND OC_EXE_LINKER_FLAGS -Wl,--nxcompat -Wl,--dynamicbase)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--nxcompat -Wl,--dynamicbase")
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
# Don't put this into CMAKE_CXX_FLAGS because otherwise it is cached,
|
||||
# and when the path is changed both the old and new definition appears
|
||||
# in the list of flags.
|
||||
add_definitions("-DOC_SYSTEM_DATA_DIR=\"${CMAKE_INSTALL_PREFIX}/share/games/openclonk\"")
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
list(APPEND OC_CXX_FLAGS -fobjc-arc)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fobjc-arc")
|
||||
endif()
|
||||
|
||||
if(OC_CXX_FLAGS)
|
||||
list(REMOVE_DUPLICATES OC_CXX_FLAGS)
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS "" CACHE STRING "C++ compiler flags" FORCE)
|
||||
foreach(FLAG ${OC_CXX_FLAGS})
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAG}" CACHE STRING "C++ compiler flags" FORCE)
|
||||
endforeach()
|
||||
if(OC_CXX_FLAGS_DEBUG)
|
||||
list(REMOVE_DUPLICATES OC_CXX_FLAGS_DEBUG)
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "" CACHE STRING "Flags used by the compiler during debug builds." FORCE)
|
||||
foreach(FLAG ${OC_CXX_FLAGS_DEBUG})
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAG}" CACHE STRING "Flags used by the compiler during debug builds." FORCE)
|
||||
endforeach()
|
||||
if(OC_EXE_LINKER_FLAGS)
|
||||
list(REMOVE_DUPLICATES OC_EXE_LINKER_FLAGS)
|
||||
endif()
|
||||
set(CMAKE_EXE_LINKER_FLAGS "" CACHE STRING "Flags used by the linker." FORCE)
|
||||
foreach(FLAG ${OC_EXE_LINKER_FLAGS})
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${FLAG}" CACHE STRING "Flags used by the linker." FORCE)
|
||||
endforeach()
|
||||
if(OC_EXE_LINKER_FLAGS_DEBUG)
|
||||
list(REMOVE_DUPLICATES OC_EXE_LINKER_FLAGS_DEBUG)
|
||||
endif()
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "" CACHE STRING "Flags used by the linker during debug builds." FORCE)
|
||||
foreach(FLAG ${OC_EXE_LINKER_FLAGS_DEBUG})
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${FLAG}" CACHE STRING "Flags used by the linker during debug builds." FORCE)
|
||||
endforeach()
|
||||
|
||||
############################################################################
|
||||
# Check for compiler quirks and features
|
||||
############################################################################
|
||||
|
@ -177,7 +205,6 @@ CHECK_INCLUDE_FILE_CXX(sys/socket.h HAVE_SYS_SOCKET_H)
|
|||
CHECK_INCLUDE_FILE_CXX(sys/eventfd.h HAVE_SYS_EVENTFD_H)
|
||||
CHECK_INCLUDE_FILE_CXX(sys/file.h HAVE_SYS_FILE_H)
|
||||
CHECK_INCLUDE_FILES_CXX("X11/Xlib.h;X11/extensions/Xrandr.h" HAVE_X11_EXTENSIONS_XRANDR_H)
|
||||
CHECK_INCLUDE_FILES_CXX("X11/Xlib.h;X11/keysym.h" HAVE_X11_KEYSYM_H)
|
||||
CHECK_CXX_SOURCE_COMPILES("#include <getopt.h>\nint main(int argc, char * argv[]) { getopt_long(argc, argv, \"\", 0, 0); }" HAVE_GETOPT_H)
|
||||
|
||||
############################################################################
|
||||
|
@ -302,7 +329,7 @@ endif()
|
|||
# SDL
|
||||
if(USE_SDL_MAINLOOP)
|
||||
find_package(SDL2 REQUIRED)
|
||||
elseif(NOT WIN32)
|
||||
else()
|
||||
# for gamepads
|
||||
find_package(SDL2)
|
||||
endif()
|
||||
|
@ -480,20 +507,14 @@ set(OC_CLONK_SOURCES
|
|||
src/game/C4FullScreen.h
|
||||
src/game/C4Game.cpp
|
||||
src/game/C4Game.h
|
||||
src/game/C4GameScript.cpp
|
||||
src/game/C4GameScript.h
|
||||
src/game/C4GameVersion.h
|
||||
src/game/C4GraphicsSystem.cpp
|
||||
src/game/C4GraphicsSystem.h
|
||||
src/game/C4Physics.h
|
||||
src/game/C4Viewport.cpp
|
||||
src/game/C4Viewport.h
|
||||
src/gamescript/C4Effect.cpp
|
||||
src/gamescript/C4Effect.h
|
||||
src/gamescript/C4FindObject.cpp
|
||||
src/gamescript/C4FindObject.h
|
||||
src/gamescript/C4GameScript.cpp
|
||||
src/gamescript/C4GameScript.h
|
||||
src/gamescript/C4TransferZone.cpp
|
||||
src/gamescript/C4TransferZone.h
|
||||
src/graphics/Bitmap256.cpp
|
||||
src/graphics/Bitmap256.h
|
||||
src/graphics/C4Draw.cpp
|
||||
|
@ -607,7 +628,6 @@ set(OC_CLONK_SOURCES
|
|||
src/landscape/fow/C4FoWBeamTriangle.h
|
||||
src/landscape/C4Landscape.cpp
|
||||
src/landscape/C4Landscape.h
|
||||
src/landscape/C4LandscapeRenderClassic.cpp
|
||||
src/landscape/C4LandscapeRender.cpp
|
||||
src/landscape/C4LandscapeRender.h
|
||||
src/landscape/C4Map.cpp
|
||||
|
@ -640,6 +660,8 @@ set(OC_CLONK_SOURCES
|
|||
src/landscape/C4Texture.h
|
||||
src/landscape/C4TextureShape.cpp
|
||||
src/landscape/C4TextureShape.h
|
||||
src/landscape/C4TransferZone.cpp
|
||||
src/landscape/C4TransferZone.h
|
||||
src/landscape/C4Weather.cpp
|
||||
src/landscape/C4Weather.h
|
||||
src/lib/C4LogBuf.cpp
|
||||
|
@ -710,6 +732,8 @@ set(OC_CLONK_SOURCES
|
|||
src/object/C4Def.h
|
||||
src/object/C4DefList.cpp
|
||||
src/object/C4DefList.h
|
||||
src/object/C4FindObject.cpp
|
||||
src/object/C4FindObject.h
|
||||
src/object/C4GameObjects.cpp
|
||||
src/object/C4GameObjects.h
|
||||
src/object/C4Id.cpp
|
||||
|
@ -956,8 +980,6 @@ elseif(USE_WIN32_WINDOWS)
|
|||
endif()
|
||||
list(APPEND OC_GUI_SOURCES
|
||||
src/platform/C4WindowWin32.cpp
|
||||
src/platform/StdJoystick.cpp
|
||||
src/platform/StdJoystick.h
|
||||
)
|
||||
elseif(USE_COCOA)
|
||||
list(APPEND OC_GUI_SOURCES
|
||||
|
@ -1002,23 +1024,6 @@ endif()
|
|||
include_directories(
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/c4group
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/config
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/control
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/editor
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/game
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/gamescript
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/graphics
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/gui
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/landscape
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/landscape/fow
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/lib
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/network
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/object
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/platform
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/player
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/res
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/script
|
||||
)
|
||||
|
||||
# Mark thirdparty as system headers so we don't get warnings from them
|
||||
|
@ -1103,6 +1108,8 @@ src/script/C4AulLink.cpp
|
|||
src/script/C4AulParse.cpp
|
||||
src/script/C4AulScriptFunc.cpp
|
||||
src/script/C4AulScriptFunc.h
|
||||
src/script/C4Effect.cpp
|
||||
src/script/C4Effect.h
|
||||
src/script/C4PropList.cpp
|
||||
src/script/C4PropList.h
|
||||
src/script/C4Script.cpp
|
||||
|
@ -1176,12 +1183,13 @@ add_executable(openclonk-server
|
|||
src/platform/C4StdInProc.cpp
|
||||
src/platform/C4StdInProc.h
|
||||
)
|
||||
set_property(TARGET openclonk-server APPEND PROPERTY COMPILE_DEFINITIONS "USE_CONSOLE")
|
||||
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}
|
||||
|
|
2
COPYING
|
@ -1,5 +1,5 @@
|
|||
Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
|
||||
Copyright (c) 2009-2015, The OpenClonk Team and contributors
|
||||
Copyright (c) 2009-2016, The OpenClonk Team and contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# OpenClonk, http://www.openclonk.org
|
||||
#
|
||||
# Copyright (c) 2009-2015, The OpenClonk Team and contributors
|
||||
# Copyright (c) 2009-2016, The OpenClonk Team and contributors
|
||||
#
|
||||
# Distributed under the terms of the ISC license; see accompanying file
|
||||
# "COPYING" for details.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# OpenClonk, http://www.openclonk.org
|
||||
#
|
||||
# Copyright (c) 2011-2015, The OpenClonk Team and contributors
|
||||
# Copyright (c) 2011-2016, The OpenClonk Team and contributors
|
||||
#
|
||||
# Distributed under the terms of the ISC license; see accompanying file
|
||||
# "COPYING" for details.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# OpenClonk, http://www.openclonk.org
|
||||
#
|
||||
# Copyright (c) 2014-2015, The OpenClonk Team and contributors
|
||||
# Copyright (c) 2014-2016, The OpenClonk Team and contributors
|
||||
#
|
||||
# Distributed under the terms of the ISC license; see accompanying file
|
||||
# "COPYING" for details.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# OpenClonk, http://www.openclonk.org
|
||||
#
|
||||
# Copyright (c) 2015, The OpenClonk Team and contributors
|
||||
# Copyright (c) 2015-2016, The OpenClonk Team and contributors
|
||||
#
|
||||
# Distributed under the terms of the ISC license; see accompanying file
|
||||
# "COPYING" for details.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# OpenClonk, http://www.openclonk.org
|
||||
#
|
||||
# Copyright (c) 2015, The OpenClonk Team and contributors
|
||||
# Copyright (c) 2015-2016, The OpenClonk Team and contributors
|
||||
#
|
||||
# Distributed under the terms of the ISC license; see accompanying file
|
||||
# "COPYING" for details.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# OpenClonk, http://www.openclonk.org
|
||||
#
|
||||
# Copyright (c) 2011-2013, The OpenClonk Team and contributors
|
||||
# Copyright (c) 2011-2016, The OpenClonk Team and contributors
|
||||
#
|
||||
# Distributed under the terms of the ISC license; see accompanying file
|
||||
# "COPYING" for details.
|
||||
|
@ -26,6 +26,13 @@ ENDIF (READLINE_INCLUDE_DIR)
|
|||
|
||||
FIND_PATH(READLINE_INCLUDE_DIR readline.h PATH_SUFFIXES readline)
|
||||
|
||||
# Unmodified readline depends on symbols from termcap without explicitly
|
||||
# linking to it. Several distributions patch this to make it link against
|
||||
# terminfo from ncurses or another termcap library, but some don't. To avoid
|
||||
# having to run link tests, we'll just look for and use any termcap providing
|
||||
# library.
|
||||
FIND_LIBRARY(TERMCAP_LIBRARY NAMES tinfo termcap ncursesw ncurses cursesw curses)
|
||||
|
||||
SET(READLINE_NAMES readline libreadline)
|
||||
FIND_LIBRARY(READLINE_LIBRARY NAMES ${READLINE_NAMES} )
|
||||
|
||||
|
@ -35,10 +42,13 @@ INCLUDE(FindPackageHandleStandardArgs)
|
|||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(READLINE DEFAULT_MSG READLINE_LIBRARY READLINE_INCLUDE_DIR)
|
||||
|
||||
IF(READLINE_FOUND)
|
||||
SET( READLINE_LIBRARIES ${READLINE_LIBRARY} )
|
||||
if(TERMCAP_LIBRARY)
|
||||
set(READLINE_LIBRARIES ${READLINE_LIBRARY} ${TERMCAP_LIBRARY})
|
||||
else()
|
||||
set(READLINE_LIBRARIES ${READLINE_LIBRARY})
|
||||
endif()
|
||||
ELSE(READLINE_FOUND)
|
||||
SET( READLINE_LIBRARIES )
|
||||
ENDIF(READLINE_FOUND)
|
||||
|
||||
MARK_AS_ADVANCED( READLINE_LIBRARY READLINE_INCLUDE_DIR )
|
||||
|
||||
MARK_AS_ADVANCED( READLINE_LIBRARY TERMINFO_LIBRARY READLINE_INCLUDE_DIR )
|
||||
|
|
|
@ -17,9 +17,19 @@
|
|||
# SDL2_LIBRARIES - a list of libraries to link against to use SDL2
|
||||
# SDL2_FOUND - if false, SDL2 cannot be used
|
||||
|
||||
find_path(SDL2_INCLUDE_DIR SDL.h PATH_SUFFIXES SDL2 HINTS ENV SDL2DIR)
|
||||
find_path(SDL2_INCLUDE_DIR SDL.h
|
||||
HINTS
|
||||
$ENV{SDL2DIR}
|
||||
PATH_SUFFIXES SDL2 include
|
||||
)
|
||||
mark_as_advanced(SDL2_INCLUDE_DIR)
|
||||
find_library(SDL2_LIBRARY SDL2 HINTS ENV SDL2DIR)
|
||||
|
||||
find_library(SDL2_LIBRARY
|
||||
SDL2
|
||||
HINTS
|
||||
$ENV{SDL2DIR}
|
||||
PATH_SUFFIXES lib
|
||||
)
|
||||
mark_as_advanced(SDL2_LIBRARY)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# OpenClonk, http://www.openclonk.org
|
||||
#
|
||||
# Copyright (c) 2012-2015, The OpenClonk Team and contributors
|
||||
# Copyright (c) 2012-2016, The OpenClonk Team and contributors
|
||||
#
|
||||
# Distributed under the terms of the ISC license; see accompanying file
|
||||
# "COPYING" for details.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# OpenClonk, http://www.openclonk.org
|
||||
#
|
||||
# Copyright (c) 2012-2013, The OpenClonk Team and contributors
|
||||
# Copyright (c) 2012-2016, The OpenClonk Team and contributors
|
||||
#
|
||||
# Distributed under the terms of the ISC license; see accompanying file
|
||||
# "COPYING" for details.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# OpenClonk, http://www.openclonk.org
|
||||
#
|
||||
# Copyright (c) 2013, The OpenClonk Team and contributors
|
||||
# Copyright (c) 2013-2016, The OpenClonk Team and contributors
|
||||
#
|
||||
# Distributed under the terms of the ISC license; see accompanying file
|
||||
# "COPYING" for details.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# OpenClonk, http://www.openclonk.org
|
||||
#
|
||||
# Copyright (c) 2009-2015, The OpenClonk Team and contributors
|
||||
# Copyright (c) 2009-2016, The OpenClonk Team and contributors
|
||||
#
|
||||
# Distributed under the terms of the ISC license; see accompanying file
|
||||
# "COPYING" for details.
|
||||
|
|
|
@ -80,9 +80,6 @@
|
|||
/* Define to 1 if you have the <X11/extensions/Xrandr.h> header file. */
|
||||
#cmakedefine HAVE_X11_EXTENSIONS_XRANDR_H 1
|
||||
|
||||
/* Define to 1 if you have the <X11/keysym.h> header file. */
|
||||
#cmakedefine HAVE_X11_KEYSYM_H 1
|
||||
|
||||
/* compile without debug options */
|
||||
#cmakedefine NDEBUG 1
|
||||
|
||||
|
|
|
@ -71,21 +71,21 @@ clean:
|
|||
|
||||
sdk/content.xml: sdk/content.xml.in $(xmlfiles) build_contents.py experimental.py
|
||||
@echo generate $@
|
||||
@python build_contents.py $(xmlfiles)
|
||||
@python2 build_contents.py $(xmlfiles)
|
||||
|
||||
chm/en/Output.hhp: $(xmlfiles) chm/en/. build_hhp.py Template.hhp
|
||||
@echo generate $@
|
||||
@python build_hhp.py $@ Template.hhp $(xmlfiles)
|
||||
@python2 build_hhp.py $@ Template.hhp $(xmlfiles)
|
||||
chm/de/Output.hhp: $(xmlfiles) chm/de/. build_hhp.py Template.de.hhp
|
||||
@echo generate $@
|
||||
@python build_hhp.py $@ Template.de.hhp $(xmlfiles)
|
||||
@python2 build_hhp.py $@ Template.de.hhp $(xmlfiles)
|
||||
|
||||
$(sdk-de-dirs) $(online-dirs) $(chm-dirs):
|
||||
mkdir -p $@
|
||||
|
||||
doku.pot: $(xmlfiles) extra-strings.xml sdk/content.xml.in xml2po.py clonk.py
|
||||
@echo extract strings to $@
|
||||
@python xml2po.py -e -m clonk -o $@ $(xmlfiles) extra-strings.xml sdk/content.xml.in
|
||||
@python2 xml2po.py -e -m clonk -o $@ $(xmlfiles) extra-strings.xml sdk/content.xml.in
|
||||
|
||||
%.po: doku.pot
|
||||
@echo update $@
|
||||
|
@ -98,7 +98,7 @@ doku.pot: $(xmlfiles) extra-strings.xml sdk/content.xml.in xml2po.py clonk.py
|
|||
|
||||
sdk-de/%.xml: sdk/%.xml de.mo xml2po.py clonk.py
|
||||
@echo generate $@
|
||||
@python xml2po.py -e -m clonk -t de.mo -o $@ $<
|
||||
@python2 xml2po.py -e -m clonk -t de.mo -o $@ $<
|
||||
|
||||
define run-xslt
|
||||
@echo generate $@
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python2
|
||||
# -*- coding: utf-8 -*-
|
||||
import sys
|
||||
import xml.sax
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<doc>
|
||||
<title>CNAT - Contact Attachment</title>
|
||||
<h>CNAT - Contact Attachment</h>
|
||||
<text>In multiple places the engine uses ContactAttachment values (a bitmask) to manage the orientation of objects and processes. For example, a vertex of an object can have the <code id="CNAT">CNAT</code> bit <em>left</em>. If that object has <emlink href="definition/defcore.html">ContactCalls</emlink> activated, the engine calls on every contact of that vertex with the landscape the object script function <em>ContactLeft</em>. CNAT values are composed of the following bits:</text>
|
||||
<text>In multiple places the engine uses ContactAttachment values (a bitmask) to manage the orientation of objects and processes. For example, a vertex of an object can have the <code id="CNAT">CNAT</code> bit <em>left</em>. If that object has <emlink href="definition/properties.html">ContactCalls</emlink> activated, the engine calls on every contact of that vertex with the landscape the object script function <em>ContactLeft</em>. CNAT values are composed of the following bits:</text>
|
||||
<text>
|
||||
<table>
|
||||
<rowh>
|
||||
|
@ -40,6 +40,10 @@
|
|||
<col>CNAT_NoCollision</col>
|
||||
<col>Extra flag: non-colliding vertex</col>
|
||||
</row>
|
||||
<row>
|
||||
<col>CNAT_PhaseHalfVehicle</col>
|
||||
<col>Extra flag: Entirely suppress collisions with HalfVehicle</col>
|
||||
</row>
|
||||
<bitmask>CNAT</bitmask>
|
||||
</table>
|
||||
</text>
|
||||
|
|
|
@ -35,11 +35,6 @@
|
|||
<col>Integer</col>
|
||||
<col>Category of the object. Also see <emlink href="definition/category.html">object categories</emlink>.</col>
|
||||
</row>
|
||||
<row>
|
||||
<literal_col>ContactCalls</literal_col>
|
||||
<col>Integer</col>
|
||||
<col>0 or 1. If 1, Contactcalls are called in the object script.</col>
|
||||
</row>
|
||||
<row>
|
||||
<literal_col>Width</literal_col>
|
||||
<col>Integer</col>
|
||||
|
|
|
@ -101,7 +101,7 @@
|
|||
<row id="CONNECT">
|
||||
<col>DFA_CONNECT</col>
|
||||
<col>Line connections</col>
|
||||
<col>Only <emlink href="definition/lineconnect.html">line objects</emlink>. Connects <emlink href="script/fn/SetAction.html">target object 1</emlink> and <emlink href="script/fn/SetAction.html">target object 2</emlink>. If property LineMaxDistance is a nonzero integer, the line breaks when the target objects are further apart than the given distance.</col>
|
||||
<col>Only <emlink href="definition/lineconnect.html">line objects</emlink>. Connects <emlink href="script/fn/SetAction.html">target object 1</emlink> and <emlink href="script/fn/SetAction.html">target object 2</emlink>.</col>
|
||||
<col>CNAT_None</col>
|
||||
</row>
|
||||
<row id="PULL">
|
||||
|
|
|
@ -133,7 +133,7 @@ Stand = {
|
|||
<row id="Plane">
|
||||
<col><code>Plane</code></col>
|
||||
<col>int</col>
|
||||
<col>The Object's minor Z-Position. Negative values are behind the landscape, positive values before it. Use 1-399 for stuff behind Clonks, 401-999 for stuff before Clonks, and 1000+ for GUI objects.</col>
|
||||
<col>The Object's minor Z-Position. Negative values are behind the landscape, positive values before it. Use 1-399 for stuff behind Clonks, 401-999 for stuff before Clonks, and 1000+ for GUI objects. Global particles are on 900.</col>
|
||||
</row>
|
||||
<row id="SolidMaskPlane">
|
||||
<col><code>SolidMaskPlane</code></col>
|
||||
|
@ -180,6 +180,11 @@ Stand = {
|
|||
<col>Integer</col>
|
||||
<col>Bit mask indicating object boundaries: stop at map sides (C4D_Border_Sides), stop at map top (C4D_Border_Top), stop at map bottom (C4D_Border_Sides), stop at object layer boundaries (C4D_Border_Layer). For example BorderBound = C4D_Border_Top | C4D_Border_Bottom.</col>
|
||||
</row>
|
||||
<row>
|
||||
<literal_col>ContactCalls</literal_col>
|
||||
<col>bool</col>
|
||||
<col>True or false. If true, <emlink href="definition/cnat.html">ContactCalls</emlink> are called in the object script.</col>
|
||||
</row>
|
||||
</table>
|
||||
</text>
|
||||
</part>
|
||||
|
|
|
@ -188,11 +188,16 @@
|
|||
<col>object by</col>
|
||||
<col>Called before the object is hit or punched by another object. By returning <code>true</code>, QueryCatchBlow can reject physical blows.</col>
|
||||
</row>
|
||||
<row id="LineBreak">
|
||||
<literal_col>LineBreak</literal_col>
|
||||
<row id="OnLineBreak">
|
||||
<literal_col>OnLineBreak</literal_col>
|
||||
<col>int cause</col>
|
||||
<col>When a line object is broken. cause: 0 by movement, 1 because of a missing or incomplete target object.</col>
|
||||
</row>
|
||||
<row id="OnLineChange">
|
||||
<literal_col>OnLineChange</literal_col>
|
||||
<col>int cause</col>
|
||||
<col>When a line object is changed, that is when one of it vertices changed its position.</col>
|
||||
</row>
|
||||
<row id="BuildNeedsMaterial">
|
||||
<literal_col>BuildNeedsMaterial</literal_col>
|
||||
<col>id material_definition, int amount</col>
|
||||
|
|
|
@ -106,9 +106,12 @@
|
|||
<col>Inflammability.</col>
|
||||
</row>
|
||||
<row>
|
||||
<col>Incindiary</col>
|
||||
<col>Incendiary</col>
|
||||
<col>Integer</col>
|
||||
<col>This material incinerates objects.</col>
|
||||
<col>
|
||||
This material incinerates objects.
|
||||
<em>Note: For compatibility reasons, the misspelling "Incindiary" is also accepted if (and only if) no value with the correct spelling is set.</em>
|
||||
</col>
|
||||
</row>
|
||||
<row>
|
||||
<col>Corrode</col>
|
||||
|
@ -372,8 +375,11 @@
|
|||
<col>The background material.</col>
|
||||
</row>
|
||||
<row>
|
||||
<col>Incindiary</col>
|
||||
<col>All materials to be incinerated.</col>
|
||||
<col>Incendiary</col>
|
||||
<col>
|
||||
All materials that can incinerate objects.
|
||||
<em>Note: For compatibility reasons, the misspelling "Incindiary" is also accepted.</em>
|
||||
</col>
|
||||
</row>
|
||||
<row>
|
||||
<col>Extinguisher</col>
|
||||
|
|
|
@ -57,6 +57,8 @@
|
|||
<funclink>PV_KeyFrames</funclink>
|
||||
<funclink>PV_Wind</funclink>
|
||||
<funclink>PV_Gravity</funclink>
|
||||
<funclink>PV_Sin</funclink>
|
||||
<funclink>PV_Cos</funclink>
|
||||
</text>
|
||||
<text>
|
||||
<table>
|
||||
|
@ -149,7 +151,7 @@
|
|||
<row>
|
||||
<col>Attach</col>
|
||||
<col>bit mask</col>
|
||||
<col>Defines the attachment of the particles to the calling object. Can be a combination of ATTACH_Front, ATTACH_Back, and ATTACH_MoveRelative. For example <code>ATTACH_Front | ATTACH_MoveRelative</code></col>
|
||||
<col>Defines the attachment of the particles to the calling object. Can be a combination of ATTACH_Front, ATTACH_Back, and ATTACH_MoveRelative. For example <code>ATTACH_Front | ATTACH_MoveRelative. Non-attached particles are drawn on plane 900 (i.e. before most objects).</code></col>
|
||||
</row>
|
||||
</table>
|
||||
</text>
|
||||
|
|
|
@ -273,7 +273,7 @@
|
|||
return true;
|
||||
}</code>
|
||||
<text>most commands (except for asynchronous commands in the player menu) call a global script function:</text>
|
||||
<code>global func PlayerControl(int player, int control, C4ID control_extra, int x, int y, int strength, bool repeated, bool release)</code>
|
||||
<code>global func PlayerControl(int player, int control, C4ID control_extra, int x, int y, int strength, bool repeated, int state)</code>
|
||||
<text>For an explanation of the parameters see <funclink>PlayerControl</funclink>. Amongst others, the function receives the calling player in player as well as the command to be executed in control.</text>
|
||||
<text>As a simple example let's assume that in the global <em>PlayerControls.txt</em> the following command has been defined:</text>
|
||||
<code>[ControlDefs]
|
||||
|
@ -293,11 +293,11 @@
|
|||
Control=Jump
|
||||
Priority=50</code>
|
||||
<text>This defines a Jump key and the corresponding standard mapping on the keyboard for the first player. The following script is used to handle the control:</text>
|
||||
<code>global func PlayerControl(int player, int control, C4ID control_extra, int x, int y, int strength, bool repeated, bool release)
|
||||
<code>global func PlayerControl(int player, int control, C4ID control_extra, int x, int y, int strength, bool repeated, int state)
|
||||
{
|
||||
// Which command has been issued?
|
||||
// The constant CON_Jump has been declared automatically through the definition in PlayerControls.txt
|
||||
if (control == CON_Jump && !release)
|
||||
if (control == CON_Jump && state == CONS_Down)
|
||||
{
|
||||
// pressed the jump button. The clonk selected by the player shall jump
|
||||
var player_clonk = GetCursor(player);
|
||||
|
@ -319,17 +319,17 @@
|
|||
GUIDesc=Going underground
|
||||
ExtraData=Shovel</code>
|
||||
<text>Let shovel be the ID of a shovel object. In the global script there could be the following, generic handling for unknown commands, for example:</text>
|
||||
<code>global func PlayerControl(int player, int control, C4ID control_extra, int x, int y, int strength, bool repeated, bool release)
|
||||
<code>global func PlayerControl(int player, int control, C4ID control_extra, int x, int y, int strength, bool repeated, int state)
|
||||
{
|
||||
// Handling of known controls
|
||||
// [...]
|
||||
// control with own handling
|
||||
if (control_extra) return control_extra->PlayerControl(player, control, x, y, strength, repeat, release);
|
||||
if (control_extra) return control_extra->PlayerControl(player, control, x, y, strength, repeat, state);
|
||||
// unkown control
|
||||
return false;
|
||||
}</code>
|
||||
<text>And in the script of the shovel:</text>
|
||||
<code>func PlayerControl(int player, int control, int x, int y, int strength, bool repeated, bool release)
|
||||
<code>func PlayerControl(int player, int control, int x, int y, int strength, bool repeated, int state)
|
||||
{
|
||||
// Handling of known controls
|
||||
// Control dig directly in the shovel
|
||||
|
@ -353,6 +353,7 @@
|
|||
<li>Mappings can emulate permanent key presses using the <em>Hold</em>/<em>Release</em> flags.</li>
|
||||
<li><emlink href="playercontrols.xml#Repeat">Key repeats</emlink> are generated.</li>
|
||||
<li>The held state of the key can be queried in the script via <funclink>GetPlayerControlState</funclink>.</li>
|
||||
<li>If the command is bound to an analog stick or trigger on a controller, every change in position causes in a call to PlayerControl() with state = CONS_Moved.</li>
|
||||
</ul>
|
||||
</text>
|
||||
<text>A good example for this functionality is a directional command:</text>
|
||||
|
@ -362,7 +363,7 @@
|
|||
GUIDesc=Walk left
|
||||
Hold=1</code>
|
||||
<text>In the script the direction is transferred to the Clonk:</text>
|
||||
<code>global func PlayerControl(int player, int control, C4ID control_extra, int x, int y, int strength, bool repeated, bool release)
|
||||
<code>global func PlayerControl(int player, int control, C4ID control_extra, int x, int y, int strength, bool repeated, int state)
|
||||
{
|
||||
if (control == CON_Left) return UpdateControlDir(player);
|
||||
// ...
|
||||
|
|
|
@ -555,8 +555,8 @@ global func FxExplodeOnDeathCurseStop(object target, proplist effect, int reason
|
|||
<text>new_timer is the timer interval of the new effect; var1 to var4 are the parameters from AddEffect. Notice: in temporary calls, these parameters are not available - here they will be 0.</text>
|
||||
<text>If -1 is returned, the accepting effect is deleted also. Logically, the calling AddEffect function will then return -2.</text>
|
||||
<h>Fx*Damage</h>
|
||||
<text><code>int Fx*Damage (object target, proplist effect, int damage, int cause);</code></text>
|
||||
<text>Every effect receives this callback whenever the energy or damage value of the target object is to change. If the function is defined, it should then return whether to allow the change.</text>
|
||||
<text><code>int Fx*Damage (object target, proplist effect, int damage, int cause, int by_player);</code></text>
|
||||
<text>Every effect receives this callback whenever the energy or damage value of the target object is to change. If the function is defined, it should then return the damage to be done to the target.</text>
|
||||
<text id="damagecause">This callback is made upon life energy changes in living beings and damage value changes in non-livings - but not vice versa. cause contains the value change and reason:</text>
|
||||
<text>
|
||||
<table>
|
||||
|
|
|
@ -9,17 +9,17 @@
|
|||
<subcat>Vertices</subcat>
|
||||
<version>5.1 OC</version>
|
||||
<syntax>
|
||||
<rtype>int</rtype>
|
||||
<rtype>bool</rtype>
|
||||
<params>
|
||||
<param>
|
||||
<type>int</type>
|
||||
<name>x</name>
|
||||
<desc>X coordinate, relative to the object center</desc>
|
||||
<desc>X coordinate, relative to the object center.</desc>
|
||||
</param>
|
||||
<param>
|
||||
<type>int</type>
|
||||
<name>y</name>
|
||||
<desc>Y coordinate, relative to the object center</desc>
|
||||
<desc>Y coordinate, relative to the object center.</desc>
|
||||
</param>
|
||||
</params>
|
||||
</syntax>
|
||||
|
@ -32,6 +32,7 @@
|
|||
</example>
|
||||
</examples>
|
||||
<related>
|
||||
<funclink>InsertVertex</funclink>
|
||||
<funclink>GetVertex</funclink>
|
||||
<funclink>SetVertex</funclink>
|
||||
<funclink>GetVertexNum</funclink>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<func>
|
||||
<title>GetPlayerControlState</title>
|
||||
<category>Player</category>
|
||||
<version>5.1 OC</version>
|
||||
<version>5.1 OC (extended in 8.0 OC)</version>
|
||||
<syntax>
|
||||
<rtype>int</rtype>
|
||||
<params>
|
||||
|
@ -20,9 +20,15 @@
|
|||
<name>control</name>
|
||||
<desc>Control to query. A CON_* constant should be used here.</desc>
|
||||
</param>
|
||||
<param>
|
||||
<type>bool</type>
|
||||
<name>analog_strength</name>
|
||||
<desc>If true: Query current state of an analog control on a gamepad instead of the emulated button state.</desc>
|
||||
<optional />
|
||||
</param>
|
||||
</params>
|
||||
</syntax>
|
||||
<desc>Returns the current state of a control for a certain player. The return value is the strength of the control (e.g. for gamepad joysticks). If the control is assigned to a key, a value not equal to 0 means that the key is currently held down by the player.</desc>
|
||||
<desc>Returns the current state of a control for a certain player. If the control is assigned to a key, a value not equal to 0 means that the key is currently held down by the player. For analog controls on gamepads, the function either queries the current emulated button state (analog_strength = false), or the current position of the stick or trigger (analog_strength = true).</desc>
|
||||
<examples>
|
||||
<example>
|
||||
<code>
|
||||
|
@ -36,4 +42,5 @@ if (GetPlayerControlState(GetOwner(), CON_Left) != 0)
|
|||
</related>
|
||||
</func>
|
||||
<author>Zapper</author><date>2015-10</date>
|
||||
<author>Luchs</author><date>2016-02</date>
|
||||
</funcs>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<param>
|
||||
<type>int</type>
|
||||
<name>index</name>
|
||||
<desc>Index of the vertex to be changed.</desc>
|
||||
<desc>Index of the vertex to be changed, ranges from 0 to <funclink>GetVertexNum</funclink>.</desc>
|
||||
</param>
|
||||
<param>
|
||||
<type>int</type>
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
<?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>InsertVertex</title>
|
||||
<category>Objects</category>
|
||||
<subcat>Vertices</subcat>
|
||||
<version>8.0 OC</version>
|
||||
<syntax>
|
||||
<rtype>bool</rtype>
|
||||
<params>
|
||||
<param>
|
||||
<type>int</type>
|
||||
<name>index</name>
|
||||
<desc>Index of the vertex to be removed, ranges from 0 to <funclink>GetVertexNum</funclink>.</desc>
|
||||
</param>
|
||||
<param>
|
||||
<type>int</type>
|
||||
<name>x</name>
|
||||
<desc>X coordinate, relative to the object center.</desc>
|
||||
</param>
|
||||
<param>
|
||||
<type>int</type>
|
||||
<name>y</name>
|
||||
<desc>Y coordinate, relative to the object center.</desc>
|
||||
</param>
|
||||
</params>
|
||||
</syntax>
|
||||
<desc>Inserts a new vertex to an object.</desc>
|
||||
<remark>Notice: with any vertex updated caused by stretching or rotation of the object (e.g. building or growth) the vertices will be reset to their original defined position unless a special vertex mode is selected.</remark>
|
||||
<related>
|
||||
<funclink>AddVertex</funclink>
|
||||
<funclink>GetVertex</funclink>
|
||||
<funclink>SetVertex</funclink>
|
||||
<funclink>GetVertexNum</funclink>
|
||||
<funclink>RemoveVertex</funclink>
|
||||
</related>
|
||||
</func>
|
||||
<author>Maikel</author><date>2016-03</date>
|
||||
</funcs>
|
|
@ -0,0 +1,46 @@
|
|||
<?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>PV_Cos</title>
|
||||
<category>Particles</category>
|
||||
<version>8.0 OC</version>
|
||||
<syntax>
|
||||
<rtype>array</rtype>
|
||||
<params>
|
||||
<param>
|
||||
<type>int</type>
|
||||
<name>value</name>
|
||||
<desc>Value or value provider to calculate the cosine of. The result of <funclink>PV_Linear</funclink> can be used to evaluate the cosine function linearly over time.</desc>
|
||||
</param>
|
||||
<param>
|
||||
<type>int</type>
|
||||
<name>amplitude</name>
|
||||
<desc>Amplitude of result. May be a value or value provider.</desc>
|
||||
</param>
|
||||
<param>
|
||||
<type>int</type>
|
||||
<name>offset</name>
|
||||
<desc>Offset added to result. May be a value or value provider. Defaults to zero.</desc>
|
||||
<optional />
|
||||
</param>
|
||||
</params>
|
||||
</syntax>
|
||||
<desc>The value will is calculates as cos(value) * amplitude + offset with value given in degrees.</desc>
|
||||
<remark>See the <emlink href="particle/index.html">particle documentation</emlink> for further explanations of the particle system.</remark>
|
||||
<remark>See <funclink>PV_Random</funclink> for another example with PV_Cos.</remark>
|
||||
<related>
|
||||
<funclink>CreateParticle</funclink>
|
||||
<funclink>PV_Sin</funclink>
|
||||
<funclink>PV_Direction</funclink>
|
||||
<funclink>PV_Random</funclink>
|
||||
<funclink>PV_Step</funclink>
|
||||
<funclink>PV_Linear</funclink>
|
||||
<funclink>PV_Speed</funclink>
|
||||
<funclink>PV_KeyFrames</funclink>
|
||||
</related>
|
||||
</func>
|
||||
<author>Zapper</author><date>2016-02</date>
|
||||
</funcs>
|
|
@ -27,12 +27,37 @@
|
|||
<name>reroll_interval</name>
|
||||
<desc>Interval in frames after which a new random number will be drawn.</desc>
|
||||
<optional />
|
||||
</param>
|
||||
<param>
|
||||
<type>int</type>
|
||||
<name>seed</name>
|
||||
<desc>Particle-local seed that is used for the random rool. Can be used to draw the same random number two times (see example).</desc>
|
||||
<optional />
|
||||
</param>
|
||||
</params>
|
||||
</syntax>
|
||||
<desc>The value will be a random number in the interval from start_value to (not including) end_value. The values in between are not whole integers, but are also in fraction of integers. This means that PV_Random(0, 1) can not only return one value (the 0) but a lot of different values in the interval between 0 and 1.</desc>
|
||||
<remark>See the <emlink href="particle/index.html">particle documentation</emlink> for further explanations of the particle system.</remark>
|
||||
<related>
|
||||
<examples>
|
||||
<example>
|
||||
<code><funclink>CreateParticle</funclink>("MagicRing", 0, 0, PV_Random(-100, 100), -20, 100, {Prototype = Particles_Glimmer(), Size = PV_Random(0, 3, 10)}, 100);</code>
|
||||
<text>Creates 100 particles with a random speed in X direction and a random size (which changes every ten frames).</text>
|
||||
</example>
|
||||
<example>
|
||||
<code>
|
||||
var min_speed = 50;
|
||||
var max_speed = 100;
|
||||
var min_angle = 0;
|
||||
var max_angle = 360;
|
||||
<funclink>CreateParticle</funclink>("SphereSpark", 0, 0,
|
||||
<funclink>PV_Sin</funclink>(<funclink>PV_Random</funclink>(min_angle, max_angle, 0, 1), <funclink>PV_Random</funclink>(min_speed, max_speed, 0, 2)),
|
||||
<funclink>PV_Cos</funclink>(<funclink>PV_Random</funclink>(min_angle, max_angle, 0, 1), <funclink>PV_Random</funclink>(min_speed, max_speed, 0, 2)),
|
||||
PV_Random(10, 200),
|
||||
Particles_Glimmer(), 400);</code>
|
||||
<text>Uses the particle-local seed to draw the same angle and radius for the X and Y speed of the particle. This leads to a radial distribution (instead of a square). The seed parameter is set to the same number (here 1 and 2) where the same result should be drawn.</text>
|
||||
</example>
|
||||
</examples>
|
||||
<related>
|
||||
<funclink>CreateParticle</funclink>
|
||||
<funclink>PV_Linear</funclink>
|
||||
<funclink>PV_Direction</funclink>
|
||||
|
@ -40,6 +65,7 @@
|
|||
<funclink>PV_Speed</funclink>
|
||||
<funclink>PV_KeyFrames</funclink>
|
||||
<funclink>PV_Sin</funclink>
|
||||
<funclink>PV_Cos</funclink>
|
||||
<funclink>PC_Die</funclink>
|
||||
<funclink>PC_Bounce</funclink>
|
||||
</related>
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
</syntax>
|
||||
<desc>The value will is calculates as sin(value) * amplitude + offset with value given in degrees.</desc>
|
||||
<remark>See the <emlink href="particle/index.html">particle documentation</emlink> for further explanations of the particle system.</remark>
|
||||
<remark>See <funclink>PV_Random</funclink> for another example with PV_Sin.</remark>
|
||||
<examples>
|
||||
<example>
|
||||
<code><funclink>CreateParticle</funclink>("MagicRing", 0, 0, 0, 0, 100, {R=0xff,G=0x00,B=0x30, Size = PV_Sin(<funclink>PV_Linear</funclink>(0,180),10,0)}, 1);</code>
|
||||
|
@ -38,6 +39,7 @@
|
|||
</examples>
|
||||
<related>
|
||||
<funclink>CreateParticle</funclink>
|
||||
<funclink>PV_Cos</funclink>
|
||||
<funclink>PV_Direction</funclink>
|
||||
<funclink>PV_Random</funclink>
|
||||
<funclink>PV_Step</funclink>
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
<?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>PlayRumble</title>
|
||||
<category>Player</category>
|
||||
<version>8.0 OC</version>
|
||||
<syntax>
|
||||
<rtype>bool</rtype>
|
||||
<params>
|
||||
<param>
|
||||
<type>int</type>
|
||||
<name>player</name>
|
||||
<desc>Number of the player whose controller should rumble. Can be NO_OWNER to make all controllers rumble.</desc>
|
||||
</param>
|
||||
<param>
|
||||
<type>int</type>
|
||||
<name>strength</name>
|
||||
<desc>Strength of the rumble, between 0 and 1000.</desc>
|
||||
</param>
|
||||
<param>
|
||||
<type>int</type>
|
||||
<name>length</name>
|
||||
<desc>Duration of the rumble in milliseconds.</desc>
|
||||
</param>
|
||||
</params>
|
||||
</syntax>
|
||||
<desc>Plays a haptic effect on the given player's gamepad. Returns true if all parameters are valid; there is no way to know whether the rumble was actually played.</desc>
|
||||
<examples>
|
||||
<example>
|
||||
<code>
|
||||
<funclink>ShakeObjects</funclink>(<funclink>LandscapeWidth</funclink>()/2, <funclink>LandscapeHeight</funclink>()/2, <funclink>Distance</funclink>(<funclink>LandscapeWidth</funclink>(), <funclink>LandscapeHeight</funclink>())/2);
|
||||
PlayRumble(NO_OWNER, 1000, 2000);
|
||||
</code>
|
||||
<text>Earthquake: Shakes all Clonks and rumbles all controllers at full strength for two seconds.</text>
|
||||
</example>
|
||||
</examples>
|
||||
<related>
|
||||
<funclink>StopRumble</funclink>
|
||||
</related>
|
||||
</func>
|
||||
<author>Luchs</author><date>2016-02</date>
|
||||
</funcs>
|
|
@ -0,0 +1,80 @@
|
|||
<?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>PlayerControl</title>
|
||||
<category>Callbacks</category>
|
||||
<version>5.1 OC</version>
|
||||
<syntax>
|
||||
<rtype>bool</rtype>
|
||||
<params>
|
||||
<param>
|
||||
<type>int</type>
|
||||
<name>player</name>
|
||||
<desc>Number of the player who pressed the control.</desc>
|
||||
</param>
|
||||
<param>
|
||||
<type>int</type>
|
||||
<name>control</name>
|
||||
<desc>Number of the pressed control, defined as a CON_ constant via PlayerControls.txt.</desc>
|
||||
</param>
|
||||
<param>
|
||||
<type>id</type>
|
||||
<name>control_extra</name>
|
||||
<desc>Optional id defined with ExtraData in PlayerControls.txt.</desc>
|
||||
</param>
|
||||
<param>
|
||||
<type>int</type>
|
||||
<name>x</name>
|
||||
<desc>X coordinate for mouse controls.</desc>
|
||||
</param>
|
||||
<param>
|
||||
<type>int</type>
|
||||
<name>y</name>
|
||||
<desc>Y coordinate for mouse controls.</desc>
|
||||
</param>
|
||||
<param>
|
||||
<type>int</type>
|
||||
<name>strength</name>
|
||||
<desc>Current strength of the control. For key presses: 0 or 100. For analog stick or trigger movement (state = CONS_Moved): 0 to <code>PLRCON_MaxStrength</code>.</desc>
|
||||
</param>
|
||||
<param>
|
||||
<type>bool</type>
|
||||
<name>repeated</name>
|
||||
<desc>Whether the call is generated because of a held button.</desc>
|
||||
</param>
|
||||
<param>
|
||||
<type>int</type>
|
||||
<name>state</name>
|
||||
<desc>
|
||||
State of the key press. Possible values:
|
||||
<table>
|
||||
<rowh>
|
||||
<col>Constant</col>
|
||||
<col>Description</col>
|
||||
</rowh>
|
||||
<row>
|
||||
<literal_col>CONS_Down</literal_col>
|
||||
<col>Key has been pressed down.</col>
|
||||
</row>
|
||||
<row>
|
||||
<literal_col>CONS_Up</literal_col>
|
||||
<col>Key has been released. Only generated for held keys.</col>
|
||||
</row>
|
||||
<row>
|
||||
<literal_col>CONS_Moved</literal_col>
|
||||
<col>An analog control on a gamepad has been moved. Only generated for held keys.</col>
|
||||
</row>
|
||||
</table>
|
||||
</desc>
|
||||
</param>
|
||||
</params>
|
||||
</syntax>
|
||||
<desc>Called globally for each control command by players. See <emlink href="script/playercontrols.html">Player Controls</emlink>.</desc>
|
||||
<related><funclink>GetPlayerControlState</funclink></related>
|
||||
<related><emlink href="playercontrols.html">Player Controls</emlink></related>
|
||||
</func>
|
||||
<author>Luchs</author><date>2016-02</date>
|
||||
</funcs>
|
|
@ -9,12 +9,12 @@
|
|||
<subcat>Vertices</subcat>
|
||||
<version>5.1 OC</version>
|
||||
<syntax>
|
||||
<rtype>int</rtype>
|
||||
<rtype>bool</rtype>
|
||||
<params>
|
||||
<param>
|
||||
<type>int</type>
|
||||
<name>index</name>
|
||||
<desc>Index of the vertex to be removed.</desc>
|
||||
<desc>Index of the vertex to be removed, ranges from 0 to <funclink>GetVertexNum</funclink>.</desc>
|
||||
</param>
|
||||
</params>
|
||||
</syntax>
|
||||
|
@ -28,6 +28,7 @@
|
|||
</examples>
|
||||
<related>
|
||||
<funclink>AddVertex</funclink>
|
||||
<funclink>InsertVertex</funclink>
|
||||
<funclink>GetVertex</funclink>
|
||||
<funclink>SetVertex</funclink>
|
||||
<funclink>GetVertexNum</funclink>
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?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>SetHalfVehicleSolidMask</title>
|
||||
<category>Objects</category>
|
||||
<subcat>Status</subcat>
|
||||
<version>5.1 OC</version>
|
||||
<syntax>
|
||||
<rtype>void</rtype>
|
||||
<params>
|
||||
<param>
|
||||
<type>bool</type>
|
||||
<name>set</name>
|
||||
<desc>Whether to activate or deactivate</desc>
|
||||
</param>
|
||||
</params>
|
||||
</syntax>
|
||||
<desc>Change the material type of an activated solid mask. Activating HalfVehicle solid masks will allow objects to phase through the solid mask from below but keep normal behavior when standing on it or falling through. </desc>
|
||||
<remark>Solid areas will internally be drawn in the landscape using the "Vehicle" material.</remark>
|
||||
<examples>
|
||||
<example>
|
||||
<code>SetHalfVehicleSolidMask(true); // do not forget to pass the parameter!</code>
|
||||
<text></text>
|
||||
</example>
|
||||
</examples>
|
||||
</func>
|
||||
<author>Caesar</author><date>2016-01</date>
|
||||
</funcs>
|
|
@ -0,0 +1,26 @@
|
|||
<?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>StopRumble</title>
|
||||
<category>Player</category>
|
||||
<version>8.0 OC</version>
|
||||
<syntax>
|
||||
<rtype>bool</rtype>
|
||||
<params>
|
||||
<param>
|
||||
<type>int</type>
|
||||
<name>player</name>
|
||||
<desc>Number of the player whose controller should stop rumbling. Can be NO_OWNER to make all controllers stop.</desc>
|
||||
</param>
|
||||
</params>
|
||||
</syntax>
|
||||
<desc>Stops a rumble effect that was started with <funclink>PlayRumble</funclink>. Returns true if the given player is valid; there is no way to know whether there was actually a playing rumble effect.</desc>
|
||||
<related>
|
||||
<funclink>PlayRumble</funclink>
|
||||
</related>
|
||||
</func>
|
||||
<author>Luchs</author><date>2016-02</date>
|
||||
</funcs>
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* OpenClonk, http://www.openclonk.org
|
||||
*
|
||||
* Copyright (c) 2012-2015, The OpenClonk Team and contributors
|
||||
* Copyright (c) 2012-2016, The OpenClonk Team and contributors
|
||||
*
|
||||
* Distributed under the terms of the ISC license; see accompanying file
|
||||
* "COPYING" for details.
|
||||
|
|
|
@ -25,5 +25,5 @@ InMatConvertDepth=1
|
|||
|
||||
[Reaction]
|
||||
Type=Convert
|
||||
TargetSpec=Incindiary
|
||||
TargetSpec=Incendiary
|
||||
ConvertMat=Water
|
||||
|
|
|
@ -28,7 +28,7 @@ func FxSparkleStart(target, effect, temp)
|
|||
|
||||
func FxSparkleTimer(target, effect, effect_time)
|
||||
{
|
||||
if(this()->Contained() || !Random(2)) return FX_OK;
|
||||
if(this->Contained() || !Random(2)) return FX_OK;
|
||||
CreateParticle("MagicRing", 0, 0, 0, 0, effect.Interval, effect.particles, 1);
|
||||
return FX_OK;
|
||||
}
|
||||
|
|
|
@ -7,10 +7,17 @@
|
|||
|
||||
static g_player_spawn_positions;
|
||||
static g_map_width;
|
||||
static g_no_map, g_seed;
|
||||
|
||||
// Called be the engine: draw the complete map here.
|
||||
public func InitializeMap(proplist map)
|
||||
{
|
||||
// Don't draw a map when switching to the empty scenario section.
|
||||
if (g_no_map) return true;
|
||||
// Reloading the scenario section also resets the RNG. Call Random() a few times to get a new map each round.
|
||||
var i = g_seed++;
|
||||
while (i--) Random(2);
|
||||
|
||||
// Map type 0: One big island; more small islands above
|
||||
// Map type 1: Only many small islands
|
||||
var t = SCENPAR_MapType;
|
||||
|
|
|
@ -33,3 +33,31 @@ Default=0
|
|||
Name=$WeaponsExplosive$
|
||||
Description=$DescWeaponsExplosive$
|
||||
Value=1
|
||||
|
||||
[ParameterDef]
|
||||
Name=$Rounds$
|
||||
Description=$DescRounds$
|
||||
ID=Rounds
|
||||
Default=1
|
||||
|
||||
[Options]
|
||||
|
||||
[Option]
|
||||
Name=1
|
||||
Value=1
|
||||
|
||||
[Option]
|
||||
Name=2
|
||||
Value=2
|
||||
|
||||
[Option]
|
||||
Name=3
|
||||
Value=3
|
||||
|
||||
[Option]
|
||||
Name=5
|
||||
Value=5
|
||||
|
||||
[Option]
|
||||
Name=7
|
||||
Value=7
|
||||
|
|
|
@ -1,7 +1,61 @@
|
|||
/* Hot ice */
|
||||
|
||||
static g_remaining_rounds, g_winners, g_check_victory_effect;
|
||||
static g_gameover;
|
||||
|
||||
func Initialize()
|
||||
{
|
||||
g_remaining_rounds = SCENPAR_Rounds;
|
||||
g_winners = [];
|
||||
InitializeRound();
|
||||
|
||||
Scoreboard->Init([
|
||||
// Invisible team column for sorting players under their teams.
|
||||
{key = "team", title = "", sorted = true, desc = false, default = "", priority = 90},
|
||||
{key = "wins", title = "Wins", sorted = true, desc = true, default = 0, priority = 100},
|
||||
{key = "death", title = "", sorted = false, default = "", priority = 0},
|
||||
]);
|
||||
}
|
||||
|
||||
// Resets the scenario, redrawing the map.
|
||||
func ResetRound()
|
||||
{
|
||||
// Retrieve all Clonks.
|
||||
var clonks = FindObjects(Find_OCF(OCF_CrewMember));
|
||||
for (var clonk in clonks)
|
||||
{
|
||||
var container = clonk->Contained();
|
||||
if (container)
|
||||
{
|
||||
clonk->Exit();
|
||||
container->RemoveObject();
|
||||
}
|
||||
clonk->SetObjectStatus(C4OS_INACTIVE);
|
||||
}
|
||||
// Clear and redraw the map.
|
||||
g_no_map = true;
|
||||
LoadScenarioSection("Empty");
|
||||
g_no_map = false;
|
||||
LoadScenarioSection("main");
|
||||
InitializeRound();
|
||||
// Re-enable the players.
|
||||
for (var clonk in clonks)
|
||||
{
|
||||
clonk->SetObjectStatus(C4OS_NORMAL);
|
||||
SetCursor(clonk->GetOwner(), clonk);
|
||||
// Select the first item. This fixes item ordering.
|
||||
clonk->SetHandItemPos(0, 0);
|
||||
InitPlayerRound(clonk->GetOwner());
|
||||
}
|
||||
}
|
||||
|
||||
func InitializeRound()
|
||||
{
|
||||
// Checking for victory: Only active after a Clonk dies.
|
||||
g_check_victory_effect = AddEffect("CheckVictory", nil, 1, 0);
|
||||
g_player_spawn_index = 0;
|
||||
ShuffleArray(g_player_spawn_positions);
|
||||
|
||||
// Materials: Chests
|
||||
var i,pos;
|
||||
var ls_wdt = LandscapeWidth(), ls_hgt = LandscapeHeight();
|
||||
|
@ -41,15 +95,37 @@ func Initialize()
|
|||
if (pos=FindLocation(Loc_InRect(0,ls_hgt/2,ls_wdt,ls_hgt/3), Loc_Solid()))
|
||||
if (IsFirestoneSpot(pos.x,pos.y))
|
||||
CreateObjectAbove([Firestone,IronBomb][Random(Random(3))],pos.x,pos.y-1);
|
||||
|
||||
// The game starts after a delay to ensure that everyone is ready.
|
||||
GUI_Clock->CreateCountdown(3);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static g_player_spawn_positions, g_map_width, g_player_spawn_index;
|
||||
|
||||
global func ScoreboardTeam(int team) { return team * 100; }
|
||||
|
||||
func InitializePlayer(int plr)
|
||||
{
|
||||
// Add the player and their team to the scoreboard.
|
||||
Scoreboard->NewPlayerEntry(plr);
|
||||
Scoreboard->SetPlayerData(plr, "wins", "");
|
||||
var team = GetPlayerTeam(plr);
|
||||
Scoreboard->NewEntry(ScoreboardTeam(team), GetTeamName(team));
|
||||
Scoreboard->SetData(ScoreboardTeam(team), "team", "", ScoreboardTeam(team));
|
||||
Scoreboard->SetPlayerData(plr, "team", "", ScoreboardTeam(team) + 1);
|
||||
|
||||
return InitPlayerRound(plr);
|
||||
}
|
||||
|
||||
func InitPlayerRound(int plr)
|
||||
{
|
||||
// Unmark death on scoreboard.
|
||||
Scoreboard->SetPlayerData(plr, "death", "");
|
||||
// everything visible
|
||||
SetFoW(false, plr);
|
||||
SetPlayerViewLock(plr, true);
|
||||
// Player positioning.
|
||||
var ls_wdt = LandscapeWidth(), ls_hgt = LandscapeHeight();
|
||||
var crew = GetCrew(plr), start_pos;
|
||||
|
@ -86,13 +162,183 @@ func InitializePlayer(int plr)
|
|||
{
|
||||
var ammo = launcher->CreateContents(IronBomb);
|
||||
launcher->AddTimer(Scenario.ReplenishLauncherAmmo, 10);
|
||||
// Start reloading the launcher during the countdown.
|
||||
crew->SetHandItemPos(0, crew->GetItemPos(launcher));
|
||||
// This doesn't play the animation properly - simulate a click instead.
|
||||
/* crew->StartLoad(launcher); */
|
||||
crew->StartUseControl(CON_Use, 0, 0, launcher);
|
||||
crew->StopUseControl(0, 0, launcher);
|
||||
}
|
||||
}
|
||||
crew.MaxEnergy = 100000;
|
||||
crew->DoEnergy(1000);
|
||||
// Disable the Clonk during the countdown.
|
||||
crew->SetCrewEnabled(false);
|
||||
crew->SetComDir(COMD_Stop);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Called by the round start countdown.
|
||||
func OnCountdownFinished()
|
||||
{
|
||||
// Re-enable all Clonks.
|
||||
for (var clonk in FindObjects(Find_OCF(OCF_CrewMember)))
|
||||
{
|
||||
clonk->SetCrewEnabled(true);
|
||||
SetCursor(clonk->GetOwner(), clonk);
|
||||
}
|
||||
}
|
||||
|
||||
func OnClonkDeath(object clonk)
|
||||
{
|
||||
var plr = clonk->GetOwner();
|
||||
// Mark death on scoreboard.
|
||||
Scoreboard->SetPlayerData(plr, "death", "{{Scoreboard_Death}}");
|
||||
// Skip eliminated players, NO_OWNER, etc.
|
||||
if (GetPlayerName(plr))
|
||||
{
|
||||
var crew = CreateObject(Clonk, 0, 0, plr);
|
||||
crew->MakeCrewMember(plr);
|
||||
var relaunch = CreateObject(RelaunchContainer, LandscapeWidth() / 2, LandscapeHeight() / 2, plr);
|
||||
// We just use the relaunch object as a dumb container.
|
||||
crew->Enter(relaunch);
|
||||
// Allow scrolling around the landscape.
|
||||
SetPlayerViewLock(plr, false);
|
||||
}
|
||||
|
||||
// Check for victory after three seconds to allow stalemates.
|
||||
if (!g_gameover)
|
||||
g_check_victory_effect.Interval = 36 * 5;
|
||||
}
|
||||
|
||||
// Returns a list of colored player names, for example "Sven2, Maikel, Luchs"
|
||||
global func GetTeamPlayerNames(int team)
|
||||
{
|
||||
var str = "";
|
||||
for (var i = 0; i < GetPlayerCount(); i++)
|
||||
{
|
||||
var plr = GetPlayerByIndex(i);
|
||||
if (GetPlayerTeam(plr) == team)
|
||||
{
|
||||
var comma = "";
|
||||
if (str != "") comma = ", ";
|
||||
str = Format("%s%s<c %x>%s</c>", str, comma, GetPlayerColor(plr), GetPlayerName(plr));
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
global func FxCheckVictoryTimer(_, proplist effect)
|
||||
{
|
||||
var find_living = Find_And(Find_OCF(OCF_CrewMember), Find_NoContainer());
|
||||
var clonk = FindObject(find_living);
|
||||
var msg;
|
||||
if (!clonk)
|
||||
{
|
||||
// Stalemate!
|
||||
msg = "$Stalemate$";
|
||||
Log(msg);
|
||||
GameCall("ResetRound");
|
||||
}
|
||||
else if (!FindObject(find_living, Find_Hostile(clonk->GetOwner())))
|
||||
{
|
||||
// We have a winner!
|
||||
var team = GetPlayerTeam(clonk->GetOwner());
|
||||
PushBack(g_winners, team);
|
||||
// Announce the winning team.
|
||||
msg = Format("$WinningTeam$", GetTeamPlayerNames(team));
|
||||
Log(msg);
|
||||
|
||||
// Update the scoreboard.
|
||||
UpdateScoreboardWins(team);
|
||||
|
||||
if (--g_remaining_rounds > 0 || GetLeadingTeam() == nil)
|
||||
{
|
||||
var msg2 = CurrentRoundStr();
|
||||
Log(msg2);
|
||||
msg = Format("%s|%s", msg, msg2);
|
||||
GameCall("ResetRound");
|
||||
}
|
||||
else
|
||||
{
|
||||
GameCall("EliminateLosers");
|
||||
}
|
||||
}
|
||||
// Switching scenario sections makes the Log() messages hard to see, so announce them using a message as well.
|
||||
CustomMessage(msg);
|
||||
// Go to sleep again.
|
||||
effect.Interval = 0;
|
||||
return FX_OK;
|
||||
}
|
||||
|
||||
global func CurrentRoundStr()
|
||||
{
|
||||
if (g_remaining_rounds == 1)
|
||||
return "$LastRound$";
|
||||
else if (g_remaining_rounds > 1)
|
||||
return Format("$RemainingRounds$", g_remaining_rounds);
|
||||
else
|
||||
return "$Tiebreak$";
|
||||
}
|
||||
|
||||
global func UpdateScoreboardWins(int team)
|
||||
{
|
||||
var wins = GetTeamWins(team);
|
||||
Scoreboard->SetData(ScoreboardTeam(team), "wins", wins, wins);
|
||||
// We have to update each player as well to make the sorting work.
|
||||
for (var i = 0; i < GetPlayerCount(); i++)
|
||||
{
|
||||
var plr = GetPlayerByIndex(i);
|
||||
if (GetPlayerTeam(plr) == team)
|
||||
{
|
||||
Scoreboard->SetPlayerData(plr, "wins", "", wins);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
global func GetTeamWins(int team)
|
||||
{
|
||||
var wins = 0;
|
||||
for (var w in g_winners)
|
||||
if (w == team)
|
||||
wins++;
|
||||
return wins;
|
||||
}
|
||||
|
||||
// Returns the team which won the most rounds, or nil if there is a tie.
|
||||
global func GetLeadingTeam()
|
||||
{
|
||||
var teams = [], winning_team = g_winners[0];
|
||||
for (var w in g_winners)
|
||||
{
|
||||
teams[w] += 1;
|
||||
if (teams[w] > teams[winning_team])
|
||||
winning_team = w;
|
||||
}
|
||||
// Detect a tie.
|
||||
for (var i = 0; i < GetLength(teams); i++)
|
||||
{
|
||||
if (i != winning_team && teams[i] == teams[winning_team])
|
||||
return nil;
|
||||
}
|
||||
return winning_team;
|
||||
}
|
||||
|
||||
func EliminateLosers()
|
||||
{
|
||||
g_gameover = true;
|
||||
// Determine the winning team.
|
||||
var winning_team = GetLeadingTeam();
|
||||
// Eliminate everybody who isn't on the winning team.
|
||||
for (var i = 0; i < GetPlayerCount(); i++)
|
||||
{
|
||||
var plr = GetPlayerByIndex(i);
|
||||
if (GetPlayerTeam(plr) != winning_team)
|
||||
EliminatePlayer(plr);
|
||||
}
|
||||
// The scenario goal will end the scenario.
|
||||
}
|
||||
|
||||
/* Called periodically in grenade launcher */
|
||||
func ReplenishLauncherAmmo()
|
||||
{
|
||||
|
|
|
@ -10,3 +10,10 @@ WeaponsClassic=Klassisch
|
|||
DescWeaponsClassic=Bögen, Speere, Keulen und einige Feuersteine
|
||||
WeaponsExplosive=Explosiv
|
||||
DescWeaponsExplosive=Nur Granatwerfer mit Endlosmunition
|
||||
Rounds=Rundenzahl
|
||||
DescRounds=Mehrere Runden spielen
|
||||
Stalemate=Unentschieden!
|
||||
WinningTeam=Gewinner: %s
|
||||
RemainingRounds=Noch %d Runden.
|
||||
LastRound=Letzte Runde!
|
||||
Tiebreak=Entscheidende Runde!
|
||||
|
|
|
@ -10,3 +10,10 @@ WeaponsClassic=Classic
|
|||
DescWeaponsClassic=Bows, spears and clubs available in chests
|
||||
WeaponsExplosive=Explosive
|
||||
DescWeaponsExplosive=Only grenade lauchers and wind bags available
|
||||
Rounds=Number of rounds
|
||||
DescRounds=Play for multiple rounds
|
||||
Stalemate=Stalemate!
|
||||
WinningTeam=Winning team: %s
|
||||
RemainingRounds=%d rounds remaining.
|
||||
LastRound=Last round!
|
||||
Tiebreak=Tiebreak!
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
#appendto Goal_Melee
|
||||
|
||||
public func GetDescription(int plr)
|
||||
{
|
||||
// Count active enemy clonks.
|
||||
var hostile_count = ObjectCount(Find_OCF(OCF_CrewMember), Find_NoContainer(), Find_Hostile(plr));
|
||||
var message;
|
||||
if (!hostile_count)
|
||||
message = "$MsgGoalFulfilled$";
|
||||
else
|
||||
message = Format("$MsgGoalUnfulfilled$", hostile_count);
|
||||
|
||||
// Also report the remaining rounds.
|
||||
message = Format("%s|%s", message, CurrentRoundStr());
|
||||
|
||||
return message;
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
MsgGoalFulfilled=Eure Gegner sind eliminiert.
|
||||
MsgGoalUnfulfilled=Es sind noch %d Gegner im Spiel.
|
|
@ -0,0 +1,2 @@
|
|||
MsgGoalFulfilled=All opponents eliminated.
|
||||
MsgGoalUnfulfilled=There are still %d opponents in the game.
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
|
@ -3,38 +3,38 @@
|
|||
func InitializeObjects()
|
||||
{
|
||||
CreateObject(Rule_KillLogs, 50, 50);
|
||||
|
||||
CreateObject(Rule_Gravestones, 50, 50);
|
||||
CreateObject(Rule_Restart, 50, 50);
|
||||
|
||||
CreateObject(Goal_Melee, 50, 50);
|
||||
|
||||
ItemSpawn->Create(Firestone,407,389);
|
||||
ItemSpawn->Create(Firestone,423,389);
|
||||
ItemSpawn->Create(PowderKeg,669,261);
|
||||
ItemSpawn->Create(Bread,407,258);
|
||||
ItemSpawn->Create(Bread,352,258);
|
||||
ItemSpawn->Create(IronBomb,441,389);
|
||||
ItemSpawn->Create(IceWallKit,990,400);
|
||||
ItemSpawn->Create(Firestone,443,101);
|
||||
ItemSpawn->Create(IceWallKit,372,258);
|
||||
|
||||
var Chest001 = CreateObjectAbove(Chest, 1047, 359);
|
||||
|
||||
CreateObjectAbove(Idol, 313, 254);
|
||||
CreateObjectAbove(Idol, 315, 235);
|
||||
|
||||
var WoodenBridge001 = CreateObjectAbove(WoodenBridge, 1126, 372);
|
||||
var WoodenBridge001 = CreateObjectAbove(WoodenBridge, 513, 282);
|
||||
WoodenBridge001->SetCategory(C4D_StaticBack);
|
||||
var WoodenBridge002 = CreateObjectAbove(WoodenBridge, 513, 282);
|
||||
var WoodenBridge002 = CreateObjectAbove(WoodenBridge, 1126, 372);
|
||||
WoodenBridge002->SetCategory(C4D_StaticBack);
|
||||
|
||||
CreateObjectAbove(Goal_Flag, 507, 180);
|
||||
CreateObjectAbove(Goal_Flag, 497, 125);
|
||||
|
||||
CreateObjectAbove(Catapult, 728, 431);
|
||||
CreateObjectAbove(Catapult, 627, 269);
|
||||
CreateObjectAbove(Catapult, 558, 107);
|
||||
|
||||
var Cannon001 = CreateObjectAbove(Cannon, 692, 253);
|
||||
Cannon001->SetRDir(3);
|
||||
CreateObjectAbove(Cannon, 511, 179);
|
||||
|
||||
CreateObjectAbove(Airship, 369, 269);
|
||||
|
||||
Chest001->CreateContents(Boompack);
|
||||
CreateObjectAbove(Airship, 383, 181);
|
||||
|
||||
Chest001->CreateContents(IronBomb, 2);
|
||||
|
||||
|
|
|
@ -42,10 +42,12 @@ func Initialize()
|
|||
flag.Destruction = Scenario.OnFlagDestruction;
|
||||
flag.team = 1;
|
||||
flag.Plane = 274; // cannot be moved by airship
|
||||
flag.RejectWindbagForce = Clonk.IsClonk;
|
||||
if (flag->GetX() > LandscapeWidth()/2) ++flag.team;
|
||||
g_respawn_flags[flag.team] = flag;
|
||||
}
|
||||
// Weapon drops timer
|
||||
g_num_avail_weapons = 6;
|
||||
ScheduleCall(nil, Scenario.DoBalloonDrop, 36*8, 99999);
|
||||
return true;
|
||||
}
|
||||
|
@ -56,14 +58,17 @@ local weapon_list = [ // id, vertex, offx, offy, deployy
|
|||
[IceWallKit, 2, 0, -5, -10],
|
||||
[DynamiteBox, 0, 3, -5, -10],
|
||||
[BombArrow, 2, 0, -8, -10],
|
||||
[Boompack, 0, 0, 0, 0],
|
||||
[GrenadeLauncher, 3, 0, -4, -10]
|
||||
[GrenadeLauncher, 3, 0, -4, -10],
|
||||
[Boompack, 0, 0, 0, 0]
|
||||
];
|
||||
|
||||
static g_num_avail_weapons; // boompack available later
|
||||
|
||||
func DoBalloonDrop()
|
||||
{
|
||||
// Random weapon
|
||||
var wp = Scenario.weapon_list[Random(GetLength(Scenario.weapon_list))];
|
||||
if (FrameCounter() > 36*60*4) g_num_avail_weapons = 7; // enable boompacks after some time
|
||||
var wp = Scenario.weapon_list[Random(g_num_avail_weapons)];
|
||||
var x = LandscapeWidth()/4 + Random(LandscapeWidth()/2);
|
||||
var y = 0;
|
||||
var balloon = CreateObject(BalloonDeployed, x, y);
|
||||
|
@ -153,6 +158,8 @@ func RelaunchPlayer(int plr)
|
|||
crew->MakeCrewMember(plr);
|
||||
SetCursor(plr, crew, false);
|
||||
}
|
||||
// Reset available items in spawns
|
||||
for (var item_spawn in FindObjects(Find_ID(ItemSpawn))) item_spawn->Reset(plr);
|
||||
// Relaunch near current flag pos (will be adjusted on actual relaunch)
|
||||
crew->SetPosition(start_x, start_y);
|
||||
var relaunch = CreateObjectAbove(RelaunchContainer, start_x, start_y, plr);
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
id=Boomattack
|
||||
Version=7,0
|
||||
Category=C4D_Vehicle
|
||||
ContactCalls=1
|
||||
Width=15
|
||||
Height=27
|
||||
Offset=-7,-13
|
||||
|
|
|
@ -100,3 +100,4 @@ local PerspectiveTheta = 25;
|
|||
local PerspectivePhi = 30;
|
||||
local FlySpeed = 100;
|
||||
local Name = "$Name$";
|
||||
local ContactCalls = true;
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
id=BigBoomattack
|
||||
Version=6,0
|
||||
Category=C4D_Object
|
||||
ContactCalls=1
|
||||
Width=60
|
||||
Height=100
|
||||
Offset=-30,-50
|
||||
|
|
|
@ -109,4 +109,5 @@ local ActMap = {
|
|||
Hgt = 100
|
||||
},
|
||||
};
|
||||
local ContactCalls = true;
|
||||
*/
|
|
@ -2,7 +2,6 @@
|
|||
id=Boomattack
|
||||
Version=7,0
|
||||
Category=C4D_Vehicle
|
||||
ContactCalls=1
|
||||
Width=15
|
||||
Height=27
|
||||
Offset=-7,-13
|
||||
|
|
|
@ -130,4 +130,5 @@ local ActMap = {
|
|||
};
|
||||
|
||||
local FlySpeed = 100;
|
||||
local Name = "$Name$";
|
||||
local Name = "$Name$";
|
||||
local ContactCalls = true;
|
|
@ -1,25 +0,0 @@
|
|||
/**
|
||||
Tools Workshop
|
||||
|
||||
@author Clonkonaut
|
||||
*/
|
||||
|
||||
#appendto ToolsWorkshop
|
||||
|
||||
local is_station;
|
||||
|
||||
protected func Initialize()
|
||||
{
|
||||
is_station = true;
|
||||
return _inherited();
|
||||
}
|
||||
|
||||
// Appears in the bottom interaction bar, if cable is connected
|
||||
public func IsInteractable()
|
||||
{
|
||||
if (GetLength(this->~GetDestinations())) return true;
|
||||
return _inherited(...);
|
||||
}
|
||||
|
||||
public func GetCableXOffset() { return 15; }
|
||||
public func GetCableYOffset() { return 5; }
|
|
@ -1,9 +1,6 @@
|
|||
[DefCore]
|
||||
id=CableLine
|
||||
Version=6,0
|
||||
Version=7,0
|
||||
Category=C4D_StaticBack
|
||||
Width=12
|
||||
Height=8
|
||||
Offset=-6,-4
|
||||
Vertices=2
|
||||
#Line=1
|
||||
Line=1
|
Before Width: | Height: | Size: 141 B After Width: | Height: | Size: 141 B |
|
@ -0,0 +1,106 @@
|
|||
/*-- 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$";
|
|
@ -0,0 +1,2 @@
|
|||
TxtLinebroke=Seil gerissen
|
||||
Name=Seilbahnseil
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.8 KiB |
|
@ -9,7 +9,6 @@ public func IsToolProduct() { return true; }
|
|||
|
||||
/*-- Line connection --*/
|
||||
|
||||
// Use will connect power line to building at the clonk's position.
|
||||
protected func ControlUse(object clonk, int x, int y)
|
||||
{
|
||||
// Is there an object which accepts power lines?
|
||||
|
@ -17,20 +16,20 @@ protected func ControlUse(object clonk, int x, int y)
|
|||
// No such object -> message.
|
||||
if (!obj)
|
||||
return clonk->Message("$TxtNoNewLine$");
|
||||
// Is there a power line connected to this wire roll?
|
||||
// Is there a cable connected to this wire roll?
|
||||
var line = FindObject(Find_CableLine());
|
||||
// There already is a power line.
|
||||
// There already is a cable
|
||||
if (line)
|
||||
{
|
||||
if (obj == line->GetActionTarget(0) || obj == line->GetActionTarget(1))
|
||||
{
|
||||
// Power line is already connected to obj -> remove line.
|
||||
// Cable is already connected to obj -> remove line.
|
||||
line->RemoveObject();
|
||||
Sound("Objects::Connect");
|
||||
clonk->Message("$TxtLineRemoval$");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
// Connect existing power line to obj.
|
||||
if(line->GetActionTarget(0) == this)
|
||||
|
@ -40,15 +39,13 @@ protected func ControlUse(object clonk, int x, int y)
|
|||
else
|
||||
return;
|
||||
Sound("Objects::Connect");
|
||||
line->SetAction("Wait");
|
||||
line->UpdateDraw();
|
||||
obj->AddCableConnection(line);
|
||||
clonk->Message("$TxtConnect$", obj->GetName());
|
||||
//RemoveObject();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else // A new power line needs to be created.
|
||||
else // A new cable needs to be created.
|
||||
{
|
||||
line = CreateObjectAbove(CableLine, 0, 0, NO_OWNER);
|
||||
line->SetActionTargets(this, obj);
|
||||
|
@ -68,4 +65,4 @@ private func Find_CableLine(object obj)
|
|||
|
||||
local Name = "$Name$";
|
||||
local Description = "$Description$";
|
||||
local Collectible = 1;
|
||||
local Collectible = 1;
|
|
@ -0,0 +1,4 @@
|
|||
[DefCore]
|
||||
id=GUI_DestinationSelectionMenu
|
||||
Version=8,0
|
||||
Category=C4D_StaticBack | C4D_Environment
|
|
@ -0,0 +1,193 @@
|
|||
/**
|
||||
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();
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
Name=Zielwahlmenü
|
||||
Description=
|
|
@ -0,0 +1,4 @@
|
|||
Name=Destination Selection Menu
|
||||
Description=
|
||||
SelectDestination=Select a destination:
|
||||
SendTo=Send the cable car to %s
|
|
@ -0,0 +1,8 @@
|
|||
[DefCore]
|
||||
id=Icon_LibraryCableCar
|
||||
Version=8,0
|
||||
Category=C4D_StaticBack
|
||||
Picture=0,0,32,32
|
||||
Width=32
|
||||
Height=22
|
||||
Offset=-16,-16
|
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 3.9 KiB |
|
@ -1,209 +1,328 @@
|
|||
/**
|
||||
Cable Car
|
||||
Library object for the cable car.
|
||||
|
||||
|
||||
@author Randrian, Clonkonaut, Maikel
|
||||
|
||||
Cable cars must set up a movement speed using SetCableSpeed(x);
|
||||
Cable cars handle movement on their own. In order to move along a rail, cable cars must call DoMovement() regularly.
|
||||
E.g. using AddTimer("DoMovement", 1);
|
||||
*/
|
||||
|
||||
//#appendto Lorry
|
||||
// The speed with which the car travels along rails
|
||||
local lib_ccar_speed;
|
||||
// The rail (cable or crossing) that is currently traveled along or stayed at
|
||||
local lib_ccar_rail;
|
||||
// The direction (0 or 1) the rail is travelled along, translates into the cable's action targets (of which there should be two!)
|
||||
local lib_ccar_direction;
|
||||
// The travel progress on the current rail
|
||||
local lib_ccar_progress;
|
||||
// The length of the rail
|
||||
local lib_ccar_max_progress;
|
||||
// This target point for pathfinding
|
||||
local lib_ccar_destination;
|
||||
|
||||
local iMovementSpeed;
|
||||
/*--- Overloads ---*/
|
||||
|
||||
local pRailTarget;
|
||||
local rail_direction; // 2 up the line, 1 down the line, 0 no movement
|
||||
local rail_progress;
|
||||
local rail_max_prog;
|
||||
local rail_destination;
|
||||
// Overload these functions as you feel fit
|
||||
|
||||
// Called after the car is attached to a rail
|
||||
func Engaged() {}
|
||||
|
||||
// Called after the car is detached from the rail
|
||||
func Disengaged() {}
|
||||
|
||||
// To offset the position on the cable from the object's center
|
||||
// position is a 2-value-array [x,y]
|
||||
// prec is nil or a value to multiply your calculations with
|
||||
func GetCableOffset(array position, int prec) {}
|
||||
|
||||
// To add custom interaction menu entries after the regular cable car entries
|
||||
// custom_entry is a prototype for proper spacing of buttons
|
||||
// Use priorities > 2000 just to be sure
|
||||
func GetCableCarExtraMenuEntries(array menu_entries, proplist custom_entry, object clonk) {}
|
||||
|
||||
// Whenever movement is about to begin
|
||||
// Movement data like lib_ccar_direction is still nil at this moment
|
||||
func OnStart() {}
|
||||
|
||||
// Whenever the car stops its movement
|
||||
// failed is true if the movement to a destination was cancelled (usually because the path broke in the meantime)
|
||||
func OnStop(bool failed) {}
|
||||
|
||||
/*--- Interface ---*/
|
||||
|
||||
// Sets the speed of the cable car
|
||||
public func SetCableSpeed(int value)
|
||||
{
|
||||
lib_ccar_speed = value;
|
||||
}
|
||||
|
||||
// Positioning of the car along the cable
|
||||
// This should be called regularly, see header comment!
|
||||
public func DoMovement()
|
||||
{
|
||||
if (!GetRailTarget()) return;
|
||||
if (lib_ccar_destination == nil) return;
|
||||
if (lib_ccar_direction == nil) return;
|
||||
|
||||
var start = 1;
|
||||
var end = 0;
|
||||
if (lib_ccar_direction == 1)
|
||||
{
|
||||
start = 0;
|
||||
end = 1;
|
||||
}
|
||||
|
||||
lib_ccar_progress += lib_ccar_speed;
|
||||
var position = CreateArray(2);
|
||||
if (lib_ccar_progress >= lib_ccar_max_progress)
|
||||
{
|
||||
lib_ccar_rail->~Deactivation(1);
|
||||
lib_ccar_rail = lib_ccar_rail->GetActionTarget(end);
|
||||
lib_ccar_rail->GetCablePosition(position);
|
||||
GetCableOffset(position);
|
||||
SetPosition(position[0], position[1]);
|
||||
lib_ccar_direction = nil;
|
||||
CrossingReached();
|
||||
return;
|
||||
}
|
||||
|
||||
var prec = 100;
|
||||
var origin = CreateArray(2), ending = CreateArray(2);
|
||||
lib_ccar_rail->GetActionTarget(start)->GetCablePosition(origin, prec);
|
||||
lib_ccar_rail->GetActionTarget(end)->GetCablePosition(ending, prec);
|
||||
position[0] = origin[0] + (ending[0] - origin[0]) * lib_ccar_progress/lib_ccar_max_progress;
|
||||
position[1] = origin[1] + (ending[1] - origin[1]) * lib_ccar_progress/lib_ccar_max_progress;
|
||||
GetCableOffset(position, prec);
|
||||
SetPosition(position[0], position[1], 1, prec);
|
||||
}
|
||||
|
||||
/*--- Status ---*/
|
||||
|
||||
public func IsCableCar() { return true; }
|
||||
|
||||
public func GetRailTarget() { return pRailTarget; }
|
||||
public func GetRailTarget() { return lib_ccar_rail; }
|
||||
|
||||
public func EngageRail(object pRailpoint)
|
||||
public func IsTravelling() { return lib_ccar_destination; }
|
||||
|
||||
/* Interaction */
|
||||
|
||||
// Provides an own interaction menu.
|
||||
public func HasInteractionMenu() { return true; }
|
||||
|
||||
// Show settins in interaction menu
|
||||
public func GetInteractionMenus(object clonk)
|
||||
{
|
||||
if (! pRailpoint->IsCableCrossing()) return false;
|
||||
var menus = _inherited() ?? [];
|
||||
var cablecar_menu =
|
||||
{
|
||||
title = "$CableCarOptions$",
|
||||
entries_callback = this.GetCableCarMenuEntries,
|
||||
callback = nil,
|
||||
callback_hover = "OnCableCarHover",
|
||||
callback_target = this,
|
||||
BackgroundColor = RGB(0, 0, 50),
|
||||
Priority = 20
|
||||
};
|
||||
PushBack(menus, cablecar_menu);
|
||||
|
||||
return menus;
|
||||
}
|
||||
|
||||
public func GetCableCarMenuEntries(object clonk)
|
||||
{
|
||||
var control_prototype =
|
||||
{
|
||||
BackgroundColor = { Std = 0, Selected = RGB(100, 30, 30) },
|
||||
OnMouseIn = GuiAction_SetTag("Selected"),
|
||||
OnMouseOut = GuiAction_SetTag("Std"),
|
||||
Right = "2em"
|
||||
};
|
||||
|
||||
var custom_entry =
|
||||
{
|
||||
Right = "3em", Bottom = "2em",
|
||||
image = { Prototype = control_prototype },
|
||||
icon = { Left = "2em" }
|
||||
};
|
||||
|
||||
var menu_entries = [];
|
||||
|
||||
// Clickable buttons
|
||||
|
||||
if (!GetRailTarget())
|
||||
{
|
||||
// Engaging onto a rail
|
||||
var stations = FindObjects(Find_AtPoint(), Find_Func("IsCableStation"));
|
||||
var i = 0;
|
||||
for (var station in stations)
|
||||
{
|
||||
var engage = new custom_entry {
|
||||
Priority = 1000 + i,
|
||||
Tooltip = "$TooltipEngage$",
|
||||
OnClick = GuiAction_Call(this, "EngageRail", station),
|
||||
image = { Prototype = custom_entry.image, Symbol = station },
|
||||
icon = { Prototype = custom_entry.icon, Symbol = Icon_LibraryCableCar, GraphicsName = "Engage" }
|
||||
};
|
||||
PushBack(menu_entries, { symbol = station, extra_data = "Engage", custom = engage });
|
||||
i++;
|
||||
}
|
||||
// No station present
|
||||
if (i == 0)
|
||||
{
|
||||
var search = {
|
||||
Priority = 1000,
|
||||
Right = "100%", Bottom = "2em",
|
||||
text = { Text = "$NoStation$", Style = GUI_TextVCenter | GUI_TextHCenter}
|
||||
};
|
||||
PushBack(menu_entries, { symbol = this, extra_data = "NoStation", custom = search });
|
||||
}
|
||||
} else {
|
||||
// Start the trip
|
||||
if (!IsTravelling())
|
||||
{
|
||||
var go = new custom_entry {
|
||||
Priority = 1000,
|
||||
Tooltip = "$TooltipGo$",
|
||||
OnClick = GuiAction_Call(this, "OpenDestinationSelection", clonk),
|
||||
image = { Prototype = custom_entry.image, Symbol = Icon_Play }
|
||||
};
|
||||
PushBack(menu_entries, { symbol = this, extra_data = "Go", custom = go });
|
||||
|
||||
var disengage = new custom_entry {
|
||||
Priority = 1001,
|
||||
Tooltip = "$TooltipDisengage$",
|
||||
OnClick = GuiAction_Call(this, "DisengageRail"),
|
||||
image = { Prototype = custom_entry.image, Symbol = GetRailTarget() },
|
||||
icon = { Prototype = custom_entry.icon, Symbol = Icon_LibraryCableCar, GraphicsName = "Disengage" }
|
||||
};
|
||||
PushBack(menu_entries, { symbol = GetRailTarget(), extra_data = "Disengage", custom = disengage });
|
||||
}
|
||||
}
|
||||
// Add custom entries
|
||||
GetCableCarExtraMenuEntries(menu_entries, custom_entry, clonk);
|
||||
|
||||
return menu_entries;
|
||||
}
|
||||
|
||||
public func OnCableCarHover(symbol, extra_data, desc_menu_target, menu_id)
|
||||
{
|
||||
if (symbol == nil) return;
|
||||
|
||||
var text = "";
|
||||
if (extra_data == "Engage")
|
||||
text = Format("$DescEngage$", GetName(), symbol->GetName());
|
||||
if (extra_data == "Go")
|
||||
text = "$DescGo$";
|
||||
|
||||
GuiUpdate({ Text = text }, menu_id, 1, desc_menu_target);
|
||||
}
|
||||
|
||||
/*--- Travelling ---*/
|
||||
|
||||
// Attach the car onto a crossing
|
||||
public func EngageRail(object crossing, bool silent)
|
||||
{
|
||||
if (! crossing->~IsCableCrossing()) return false;
|
||||
|
||||
var position = CreateArray(2);
|
||||
pRailpoint->GetCablePosition(position);
|
||||
crossing->GetCablePosition(position);
|
||||
GetCableOffset(position);
|
||||
SetPosition(position[0], position[1]);
|
||||
SetSpeed(0,0);
|
||||
SetR(0);
|
||||
SetAction("OnRail");
|
||||
SetRDir(0);
|
||||
SetComDir(COMD_None);
|
||||
pRailTarget = pRailpoint;
|
||||
rail_direction = 0;
|
||||
lib_ccar_rail = crossing;
|
||||
lib_ccar_direction = nil;
|
||||
if (!silent) Sound("Objects::Connect");
|
||||
UpdateInteractionMenus(this.GetCableCarMenuEntries);
|
||||
|
||||
Engaged();
|
||||
}
|
||||
|
||||
// Detach the car from its current holding point (cable or crossing, does not matter)
|
||||
public func DisengageRail()
|
||||
{
|
||||
pRailTarget = nil;
|
||||
rail_direction = 0;
|
||||
rail_progress = 0;
|
||||
rail_max_prog = 0;
|
||||
rail_destination = nil;
|
||||
lib_ccar_rail = nil;
|
||||
lib_ccar_direction = nil;
|
||||
lib_ccar_progress = 0;
|
||||
lib_ccar_max_progress = 0;
|
||||
lib_ccar_destination = nil;
|
||||
UpdateInteractionMenus(this.GetCableCarMenuEntries);
|
||||
|
||||
Disengaged();
|
||||
}
|
||||
|
||||
// Sets a target point for travelling and starts the movement process
|
||||
public func SetDestination(dest)
|
||||
{
|
||||
if(GetType(dest) == C4V_Int)
|
||||
{
|
||||
dest = FindObjects(Find_Func("IsCableCrossing"))[dest];
|
||||
}
|
||||
rail_destination = dest;
|
||||
if(rail_direction == 0)
|
||||
CrossingReached();
|
||||
}
|
||||
|
||||
private func Disengaged() {}
|
||||
|
||||
/* Destination selection */
|
||||
|
||||
public func SelectDestination(object select_clonk, object station)
|
||||
{
|
||||
// Storage effect
|
||||
var effect = AddEffect("DestinationSelection", this, 1, 1, this);
|
||||
effect.select_clonk = select_clonk;
|
||||
effect.station = station;
|
||||
// Helping object
|
||||
effect.cablecar_sel = CreateObjectAbove(CableCar_Selector, 0,0, select_clonk->GetOwner());
|
||||
effect.cablecar_sel->FixTo(station);
|
||||
|
||||
effect.engaging_station = station;
|
||||
}
|
||||
|
||||
public func ShiftSelection(int direction, object selector)
|
||||
{
|
||||
// Determine effect
|
||||
var effect = nil, temp_effect;
|
||||
for (var i = 0; temp_effect = GetEffect("DestinationSelection", this, i); i++)
|
||||
if (temp_effect.cablecar_sel == selector)
|
||||
effect = temp_effect;
|
||||
if (!effect) return false;
|
||||
|
||||
var destinations = [];
|
||||
var connection_list = effect.engaging_station->GetDestinations();
|
||||
|
||||
// Get every possible destination
|
||||
for (var targets in connection_list)
|
||||
{
|
||||
// Is this a valid destination?
|
||||
if (! targets[0]->IsCableStation()) continue;
|
||||
// Check ownership
|
||||
if (targets[0]->GetOwner() != effect.select_clonk->GetOwner() && targets[0]->GetOwner() != NO_OWNER) continue;
|
||||
// Save it
|
||||
destinations[GetLength(destinations)] = targets[0];
|
||||
}
|
||||
// Add current station, for it is a destination
|
||||
destinations[GetLength(destinations)] = effect.engaging_station;
|
||||
// Determine destination actually seen
|
||||
for (var i = 0; i < GetLength(destinations); i++)
|
||||
if (destinations[i] == effect.station)
|
||||
break;
|
||||
// Scale exceeded? Reset to current station
|
||||
if (i == GetLength(destinations)) i--;
|
||||
else { // Select the new destination
|
||||
i += direction;
|
||||
if (i < 0) i = GetLength(destinations) - 1;
|
||||
if (i >= GetLength(destinations)) i = 0;
|
||||
}
|
||||
// Set the view
|
||||
effect.station = destinations[i];
|
||||
effect.cablecar_sel->FixTo(effect.station);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected func FxDestinationSelectionTimer(object target, effect)
|
||||
{
|
||||
// Check cancellation conditions
|
||||
if (! effect.select_clonk) return -1; // Clonk's gone
|
||||
if (! effect.select_clonk->GetAlive()) return -1; // Clonk's dead
|
||||
if (effect.select_clonk->GetActionTarget() != this) return -1; // Clonk's not grabbing anymore
|
||||
if (! effect.cablecar_sel) return -1; // Selector's gone
|
||||
if (! effect.engaging_station) return -1; // Engaging station's gone
|
||||
if (effect.engaging_station->OnFire()) return -1; // Engaging station's burning (destroyed)
|
||||
|
||||
// Check view
|
||||
if (! effect.station) ShiftSelection(0, effect.cablecar_sel); // Current view target is gone
|
||||
if (effect.station->OnFire()) ShiftSelection(0, effect.cablecar_sel); // Current view target is burning (destroyed)
|
||||
}
|
||||
|
||||
protected func FxDestinationSelectionStop(object target, effect, int reason, bool temp)
|
||||
{
|
||||
if (temp) return;
|
||||
|
||||
// Clonk's still alive? Reset Cursor
|
||||
if (effect.select_clonk && effect.select_clonk->GetAlive())
|
||||
{
|
||||
SetPlrView(effect.select_clonk->GetOwner(), effect.select_clonk);
|
||||
SetCursor(effect.select_clonk->GetOwner(), effect.select_clonk, true);
|
||||
}
|
||||
// Remove selector
|
||||
effect.cablecar_sel->RemoveObject();
|
||||
}
|
||||
|
||||
public func AcceptSelection(object selector)
|
||||
{
|
||||
// Determine effect
|
||||
var effect = nil, temp_effect;
|
||||
for (var i = 0; temp_effect = GetEffect("DestinationSelection", this, i); i++)
|
||||
if (temp_effect.cablecar_sel == selector)
|
||||
effect = temp_effect;
|
||||
if (!effect) return false;
|
||||
|
||||
// Reset cursor
|
||||
SetPlrView(effect.select_clonk->GetOwner(), effect.select_clonk);
|
||||
SetCursor(effect.select_clonk->GetOwner(), effect.select_clonk, true);
|
||||
effect.cablecar_sel->RemoveObject();
|
||||
// Ungrab & start!
|
||||
effect.select_clonk->ObjectControl(effect.select_clonk->GetOwner(), CON_Ungrab);
|
||||
SetDestination(effect.station);
|
||||
RemoveEffect(nil, this, effect, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
public func AbortSelection(object selector)
|
||||
{
|
||||
// Determine effect
|
||||
var effect = nil, temp_effect;
|
||||
for (var i = 0; temp_effect = GetEffect("DestinationSelection", this, i); i++)
|
||||
if (temp_effect.cablecar_sel == selector)
|
||||
effect = temp_effect;
|
||||
if (!effect) return false;
|
||||
|
||||
RemoveEffect(nil, this, effect);
|
||||
}
|
||||
|
||||
/* Movement */
|
||||
|
||||
private func CrossingReached()
|
||||
{
|
||||
var target;
|
||||
if(rail_destination != pRailTarget)
|
||||
{
|
||||
if(target = pRailTarget->GetNextWaypoint(rail_destination))
|
||||
MoveTo(target);
|
||||
else
|
||||
DeliveryFailed();
|
||||
}
|
||||
else if (deliver_to) {
|
||||
if (deliver_to == pRailTarget)
|
||||
return DeliverObjects();
|
||||
if (pRailTarget->RequestObjects(this, deliver_id, deliver_amount))
|
||||
ReturnDelivery();
|
||||
else
|
||||
DeliveryFailed();
|
||||
}
|
||||
}
|
||||
|
||||
private func MoveTo(dest)
|
||||
{
|
||||
if(GetType(dest) == C4V_Int)
|
||||
{
|
||||
dest = FindObjects(Find_Func("IsCableCrossing"))[dest];
|
||||
if (!dest) return;
|
||||
}
|
||||
|
||||
lib_ccar_destination = dest;
|
||||
|
||||
if(lib_ccar_direction == nil)
|
||||
{
|
||||
OnStart();
|
||||
CrossingReached();
|
||||
}
|
||||
}
|
||||
|
||||
// Whenever a crossing is reached it must be queried for the next crossing to go to
|
||||
func CrossingReached()
|
||||
{
|
||||
var target;
|
||||
if(lib_ccar_destination != lib_ccar_rail)
|
||||
{
|
||||
if(target = lib_ccar_rail->GetNextWaypoint(lib_ccar_destination))
|
||||
MoveTo(target);
|
||||
else
|
||||
DestinationFailed();
|
||||
}
|
||||
// Destination reached
|
||||
else {
|
||||
DestinationReached();
|
||||
}
|
||||
}
|
||||
|
||||
// When the current destination is reached
|
||||
func DestinationReached()
|
||||
{
|
||||
lib_ccar_destination = nil;
|
||||
lib_ccar_direction = nil;
|
||||
lib_ccar_progress = 0;
|
||||
lib_ccar_max_progress = 0;
|
||||
|
||||
OnStop(false);
|
||||
}
|
||||
|
||||
// When the way to the current destination has vanished somehow
|
||||
func DestinationFailed()
|
||||
{
|
||||
lib_ccar_destination = nil;
|
||||
lib_ccar_direction = nil;
|
||||
lib_ccar_progress = 0;
|
||||
lib_ccar_max_progress = 0;
|
||||
|
||||
OnStop(true);
|
||||
}
|
||||
|
||||
// Setup movement process
|
||||
func MoveTo(dest)
|
||||
{
|
||||
if(GetType(dest) == C4V_Int)
|
||||
{
|
||||
dest = FindObjects(Find_Func("IsCableCrossing"))[dest];
|
||||
if (!dest) return;
|
||||
}
|
||||
|
||||
var rail = 0;
|
||||
for(var test_rail in FindObjects(Find_Func("IsConnectedTo", pRailTarget)))
|
||||
for(var test_rail in FindObjects(Find_Func("IsConnectedTo", lib_ccar_rail)))
|
||||
{
|
||||
if(test_rail->IsConnectedTo(dest))
|
||||
{
|
||||
|
@ -212,74 +331,46 @@ private func MoveTo(dest)
|
|||
}
|
||||
}
|
||||
if(!rail)
|
||||
{
|
||||
Message("No Rail available!");
|
||||
return;
|
||||
}
|
||||
return DestinationFailed(); // Shouldn't happen
|
||||
|
||||
// Target the first or second action target?
|
||||
if(rail->GetActionTarget(0) == dest)
|
||||
{
|
||||
rail_direction = 1;
|
||||
rail_progress = 0;
|
||||
}
|
||||
lib_ccar_direction = 0;
|
||||
else
|
||||
{
|
||||
rail_direction = 2;
|
||||
rail_progress = 0;
|
||||
}
|
||||
rail->GetActionTarget(0)->AddActive(0);
|
||||
rail->GetActionTarget(1)->AddActive(0);
|
||||
rail->AddActive(0);
|
||||
lib_ccar_direction = 1;
|
||||
lib_ccar_progress = 0;
|
||||
var origin = CreateArray(2), ending = CreateArray(2);
|
||||
rail->GetActionTarget(0)->GetCablePosition(origin);
|
||||
rail->GetActionTarget(1)->GetCablePosition(ending);
|
||||
rail_max_prog = Distance(origin[0], origin[1], ending[0], ending[1]);
|
||||
pRailTarget = rail;
|
||||
rail->~Activation(1);
|
||||
lib_ccar_max_progress = Distance(origin[0], origin[1], ending[0], ending[1]);
|
||||
lib_ccar_rail = rail;
|
||||
}
|
||||
|
||||
protected func OnRail()
|
||||
/* Destination selection */
|
||||
|
||||
public func OpenDestinationSelection(object clonk)
|
||||
{
|
||||
if(rail_direction == 0 || rail_direction == nil) return;
|
||||
var start = 0;
|
||||
var end = 1;
|
||||
if(rail_direction == 1)
|
||||
{
|
||||
start = 1;
|
||||
end = 0;
|
||||
}
|
||||
if (!clonk) return;
|
||||
if (!GetRailTarget()) return;
|
||||
|
||||
rail_progress += iMovementSpeed;
|
||||
if(rail_progress >= rail_max_prog)
|
||||
{
|
||||
pRailTarget->GetActionTarget(0)->AddActive(1);
|
||||
pRailTarget->GetActionTarget(1)->AddActive(1);
|
||||
pRailTarget->AddActive(1);
|
||||
pRailTarget = pRailTarget->GetActionTarget(end);
|
||||
var position = CreateArray(2);
|
||||
pRailTarget->GetCablePosition(position);
|
||||
SetPosition(position[0], position[1]);
|
||||
rail_direction = 0;
|
||||
CrossingReached();
|
||||
return;
|
||||
}
|
||||
var plr = clonk->GetOwner();
|
||||
// Close interaction menu
|
||||
if (clonk->GetMenu())
|
||||
if (!clonk->TryCancelMenu())
|
||||
return;
|
||||
|
||||
var prec = 100;
|
||||
var origin = CreateArray(2), ending = CreateArray(2);
|
||||
pRailTarget->GetActionTarget(start)->GetCablePosition(origin, prec);
|
||||
pRailTarget->GetActionTarget(end)->GetCablePosition(ending, prec);
|
||||
var x = origin[0] + (ending[0] - origin[0]) * rail_progress/rail_max_prog;
|
||||
var y = origin[1] + (ending[1] - origin[1]) * rail_progress/rail_max_prog;
|
||||
SetPosition(x, y, 1, prec);
|
||||
GUI_DestinationSelectionMenu->CreateFor(clonk, this, GetRailTarget());
|
||||
}
|
||||
|
||||
/*-- Delivery --*/
|
||||
|
||||
/*
|
||||
local deliver_id, deliver_amount, deliver_to;
|
||||
|
||||
// Returns true when this car is not in move
|
||||
public func IsAvailable()
|
||||
{
|
||||
return !rail_destination;
|
||||
return !lib_ccar_destination;
|
||||
}
|
||||
|
||||
public func AddDelivery(object from, object to, id object_id, int amount)
|
||||
|
@ -299,8 +390,8 @@ public func DeliverObjects()
|
|||
{
|
||||
if (ContentsCount(deliver_id) < deliver_amount) return DeliveryFailed();
|
||||
for (var i = 0; i < deliver_amount; i++)
|
||||
FindContents(deliver_id)->Enter(pRailTarget);
|
||||
pRailTarget->DeliveryDone(deliver_id, deliver_amount);
|
||||
FindContents(deliver_id)->Enter(lib_ccar_rail);
|
||||
lib_ccar_rail->DeliveryDone(deliver_id, deliver_amount);
|
||||
deliver_id = false;
|
||||
deliver_amount = false;
|
||||
deliver_to = false;
|
||||
|
@ -310,3 +401,4 @@ private func DeliveryFailed()
|
|||
{
|
||||
|
||||
}
|
||||
*/
|
|
@ -1,7 +0,0 @@
|
|||
[DefCore]
|
||||
id=CableCar_Selector
|
||||
Version=6,0
|
||||
Category=C4D_StaticBack
|
||||
Width=1
|
||||
Height=1
|
||||
Offset=-1,-1
|
|
@ -1,43 +0,0 @@
|
|||
/*-- Cable car selector --*/
|
||||
|
||||
local cable_car;
|
||||
|
||||
|
||||
protected func Construction(object constructor)
|
||||
{
|
||||
cable_car = constructor;
|
||||
SetLightRange(10);
|
||||
this["Visibility"] = VIS_Owner;
|
||||
AddEffect("Particles", this, 1, 2, this);
|
||||
}
|
||||
|
||||
public func FixTo(object station)
|
||||
{
|
||||
// no owner? -> panic
|
||||
if (GetOwner() == NO_OWNER) return RemoveObject();
|
||||
// Set owner's view
|
||||
SetPosition(station->GetX(), station->GetY());
|
||||
SetPlrView(GetOwner(), this);
|
||||
SetCursor(GetOwner(), this, true);
|
||||
}
|
||||
|
||||
public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool repeat, bool release)
|
||||
{
|
||||
if (release) return false;
|
||||
|
||||
if (ctrl == CON_Left)
|
||||
return cable_car->ShiftSelection(-1, this);
|
||||
if (ctrl == CON_Right)
|
||||
return cable_car->ShiftSelection(+1, this);
|
||||
|
||||
if (ctrl == CON_Use || ctrl == CON_Interact)
|
||||
return cable_car->AcceptSelection(this);
|
||||
if (ctrl == CON_UseAlt)
|
||||
return cable_car->AbortSelection(this);
|
||||
}
|
||||
|
||||
protected func FxParticlesTimer(object target, effect, int time)
|
||||
{
|
||||
var angle = time*10 % 360;
|
||||
CreateParticle("SphereSpark", Sin(angle, 13), -Cos(angle, 13), 0, 0, PV_Random(20, 30), Particles_Spark());
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
CableCarOptions=Seilbahneinstellungen
|
||||
|
||||
TooltipEngage=Das Fahrzeug auf das Seil aufsetzen.
|
||||
DescEngage=%s bei %s auf das Seil aufsetzen.
|
||||
|
||||
TooltipGo=Wähle ein Ziel für das Fahrzeug.
|
||||
DescGo=Öffnet das Zielwahl-Menü für dieses Fahrzeug. Das Fahrzeug fährt los, sobald ein Ziel ausgewählt wurde.
|
||||
|
||||
NoStation=Schiebe das Fahrzeug vor eine Station, um es auf ein Seil zu setzen.
|
|
@ -0,0 +1,9 @@
|
|||
CableCarOptions=Cable Car Options
|
||||
|
||||
TooltipEngage=Put the car on the rail
|
||||
DescEngage=Put %s on the rail at %s.
|
||||
|
||||
TooltipGo=Select a destination for the car.
|
||||
DescGo=Opens the destination selection menu for this cable car. When you select a destination, the car will start going there.
|
||||
|
||||
NoStation=Push the cable car in front of a station to set it up.
|
Before Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 7.7 KiB |
|
@ -1,102 +1,159 @@
|
|||
/**
|
||||
Cable Station
|
||||
Library for cable stations and crossings. This is included by
|
||||
Library for cable stations and crossings. This is included by
|
||||
cable crossings, and should be included by structures which
|
||||
want to make use of the cable network.
|
||||
|
||||
@author Randrian, Clonkonaut, Maikel
|
||||
*/
|
||||
|
||||
//#appendto ToolsWorkshop
|
||||
/*--- Overloads ---*/
|
||||
|
||||
// Set to true to make this a station
|
||||
local is_station;
|
||||
// Overload these functions as you feel fit
|
||||
|
||||
/*-- State --*/
|
||||
// This function is called whenever a change in the cable network occured, i.e. destinations have been added / removed.
|
||||
private func DestinationsUpdated() { }
|
||||
|
||||
/** This object is a cable crossing
|
||||
* E.g. checked by whatever object wants to connect a cable (so it does not mean there is a cable connected!)
|
||||
// Called by cable lines whenever a car starts travelling along a connected cable.
|
||||
// Can be used to start animation or sounds or similar.
|
||||
// count is a value indicating the amount of activations.
|
||||
public func CableActivation(int count) { }
|
||||
|
||||
// Called likewise as Activation() whenever a car leaves the cable.
|
||||
// count is a value indicating the amount of deactivations (e.g. a cable with more than one car broke).
|
||||
public func CableDeactivation(int count) { }
|
||||
|
||||
/*--- Callbacks ---*/
|
||||
|
||||
// Be sure to always call these via _inherited();
|
||||
|
||||
func Initialize()
|
||||
{
|
||||
destination_list = [];
|
||||
return _inherited(...);
|
||||
}
|
||||
|
||||
/* Removes this crossing from the network
|
||||
It first clears every waypoint from the network and then renews the whole information.
|
||||
Optimisation welcome!
|
||||
*/
|
||||
func Destruction()
|
||||
{
|
||||
for (var connection in FindObjects(Find_Func("IsConnectedTo", this)))
|
||||
{
|
||||
if (! connection->~IsCableLine()) continue;
|
||||
var other_crossing = connection->~GetConnectedObject(this);
|
||||
if (! other_crossing->~IsCableCrossing()) continue;
|
||||
other_crossing->ClearConnections(this);
|
||||
}
|
||||
for (var connection in FindObjects(Find_Func("IsConnectedTo", this)))
|
||||
{
|
||||
if (! connection->~IsCableLine()) continue;
|
||||
var other_crossing = connection->~GetConnectedObject(this);
|
||||
if (! other_crossing->~IsCableCrossing()) continue;
|
||||
other_crossing->RenewConnections(this);
|
||||
}
|
||||
return _inherited(...);
|
||||
}
|
||||
|
||||
/*--- Status ---*/
|
||||
|
||||
local lib_crossing_is_station;
|
||||
|
||||
/** This object is a cable crossing.
|
||||
E.g. checked by whatever object wants to connect a cable.
|
||||
Does not mean that there actually is a cable connected to this crossing.
|
||||
*/
|
||||
public func IsCableCrossing() { return true; }
|
||||
/** Returns whether or not this object is a cable station
|
||||
* A station is a possible (i.e. selectable) destination for cable cars (whereas normal crossings do not appear in the destination selection process)
|
||||
*/
|
||||
public func IsCableStation() { return is_station; }
|
||||
|
||||
// For setting up the cable
|
||||
/** This function should return true if this crossing is considered a station.
|
||||
A station is selectable as a target if a lorry is sent its way.
|
||||
Functional buildings should always be a station, the 'crossing' building only if set to.
|
||||
*/
|
||||
public func IsCableStation() { return lib_crossing_is_station; }
|
||||
|
||||
/*--- Interface ---*/
|
||||
|
||||
// For switching the station status
|
||||
public func SetCableStation(bool station)
|
||||
{
|
||||
lib_crossing_is_station = station;
|
||||
}
|
||||
|
||||
// Returns the cable hookup position for proper positioning of a car along the line.
|
||||
public func GetCablePosition(array coordinates, int prec)
|
||||
{
|
||||
if (!prec) prec = 1;
|
||||
coordinates[0] = GetX(prec);
|
||||
coordinates[1] = GetY(prec);
|
||||
if (this->~GetCableXOffset()) coordinates[0] += this->~GetCableXOffset() * prec;
|
||||
if (this->~GetCableYOffset()) coordinates[1] += this->~GetCableYOffset() * prec;
|
||||
}
|
||||
|
||||
/* Local */
|
||||
|
||||
// Stores the next crossing (waypoint) to take when advancing to a certain final point
|
||||
// Scheme (2D array): [Desired final point, Next waypoint to take, Distance (not airline!) until final point]
|
||||
local destination_list;
|
||||
// According to this scheme, some constants for easy reading
|
||||
local const_finaldestination; // :D
|
||||
local const_nextwaypoint;
|
||||
local const_distance;
|
||||
|
||||
protected func Initialize() //
|
||||
{
|
||||
const_finaldestination = 0;
|
||||
const_nextwaypoint = 1;
|
||||
const_distance = 2;
|
||||
destination_list = [];
|
||||
return _inherited(...);
|
||||
}
|
||||
|
||||
/* Pathfinding for cable cars */
|
||||
|
||||
/** Returns the waypoint to take next for the desired final point \a end
|
||||
* @param end The final destination for the information is queried
|
||||
*/
|
||||
public func GetNextWaypoint(object end)
|
||||
{
|
||||
if (!destination_list) return nil;
|
||||
for (var item in destination_list)
|
||||
if (this.LineAttach)
|
||||
{
|
||||
if (!item) continue;
|
||||
if (item[const_finaldestination] == end)
|
||||
return item[const_nextwaypoint];
|
||||
coordinates[0] += this.LineAttach[0] * prec;
|
||||
coordinates[1] += this.LineAttach[1] * prec;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
/** Returns the actual traveling distance for the desired final point \a end
|
||||
* This is not the airline distance but the length of all cables to take via traveling
|
||||
* @param end The final destination for the information is queried
|
||||
*/
|
||||
public func GetLengthToTarget(object end)
|
||||
// Usually called by cable cars to retrieve selectable destinations for the destination selection menu.
|
||||
// Returns an array of three objects and one int, one station before and one station after the middle one and the middle one.
|
||||
// The int (fourth array value) is the overall amount of stations found.
|
||||
// If middle is not a station (anymore), the first three found objects are returned.
|
||||
public func GetDestinationList(object middle)
|
||||
{
|
||||
if (!destination_list) return nil;
|
||||
for (var item in destination_list)
|
||||
{
|
||||
if (!item) continue;
|
||||
if (item[const_finaldestination] == end)
|
||||
return item[const_distance];
|
||||
}
|
||||
return nil;
|
||||
var list = CreateArray();
|
||||
var ret = CreateArray(4);
|
||||
for (var destination in destination_list)
|
||||
if (destination[const_finaldestination]->IsCableStation())
|
||||
PushBack(list, destination[const_finaldestination]);
|
||||
if (GetLength(list) == 0) return ret;
|
||||
if (GetLength(list) == 1) return [nil, list[0], nil, 1];
|
||||
if (GetLength(list) == 2) return [list[0], list[1], nil, 2];
|
||||
if (GetLength(list) == 3) return [list[0], list[1], list[2], 3];
|
||||
|
||||
var middle_index = GetIndexOf(list, middle);
|
||||
if (middle_index == -1) middle_index = 1;
|
||||
var left_index = middle_index - 1;
|
||||
if (left_index < 0) left_index = GetLength(list) - 1;
|
||||
var right_index = middle_index + 1;
|
||||
if (right_index >= GetLength(list)) right_index = 0;
|
||||
|
||||
ret[0] = list[left_index];
|
||||
ret[1] = list[middle_index];
|
||||
ret[2] = list[right_index];
|
||||
ret[3] = GetLength(list);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Returns the destination array
|
||||
/*--- Maintaining the destination list ---*/
|
||||
|
||||
/* Functions:
|
||||
GetDestinations()
|
||||
AddCableConnection(object cable)
|
||||
AddCableDestinations(array new_list, object crossing)
|
||||
AddCableDestination(object new_destination, object crossing, int distance_add)
|
||||
ClearConnections(object crossing)
|
||||
RenewConnections(object crossing)
|
||||
*/
|
||||
|
||||
/** Returns the destination array so it can be used by other crossings.
|
||||
*/
|
||||
public func GetDestinations()
|
||||
{
|
||||
return destination_list[:];
|
||||
}
|
||||
|
||||
/* Set up pathfinding information */
|
||||
// Stores the next crossing (waypoint) to take when advancing to a certain final point
|
||||
// Scheme (2D array): [Desired final point, Next waypoint to take, Distance (not airline!) until final point]
|
||||
local destination_list;
|
||||
|
||||
// Constants for easier script reading
|
||||
// These correspond to the aforementioned values of destination_list
|
||||
local const_finaldestination = 0; // :D
|
||||
local const_nextwaypoint = 1;
|
||||
local const_distance = 2;
|
||||
|
||||
/** Adds a new connection via the cable \a cable to this crossing
|
||||
* Does nothing if the other connected objects of the cable is not a cable crossing
|
||||
* @param cable The newly connected cable
|
||||
Does nothing if the other connected object of the cable is not a cable crossing
|
||||
@param cable The newly connected cable
|
||||
*/
|
||||
public func AddCableConnection(object cable)
|
||||
{
|
||||
|
@ -104,7 +161,7 @@ public func AddCableConnection(object cable)
|
|||
if (!cable || ! cable->~IsCableLine())
|
||||
return false;
|
||||
// Line setup finished?
|
||||
var other_crossing = cable->~GetOtherConnection(this);
|
||||
var other_crossing = cable->~GetConnectedObject(this);
|
||||
if (! other_crossing->~IsCableCrossing())
|
||||
return false;
|
||||
// Acquire destinations of the other crossing, all these are now in reach
|
||||
|
@ -112,7 +169,7 @@ public func AddCableConnection(object cable)
|
|||
// Send own destinations, now in reach for the other one
|
||||
other_crossing->AddCableDestinations(destination_list[:], this);
|
||||
// Awesome, more power to the network!
|
||||
CheckRailStation();
|
||||
DestinationsUpdated();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -164,7 +221,7 @@ public func AddCableDestinations(array new_list, object crossing)
|
|||
if (list_item[const_finaldestination] != crossing)
|
||||
list_item[const_finaldestination]->AddCableDestination(this, crossing, distance_add);
|
||||
}
|
||||
CheckRailStation();
|
||||
DestinationsUpdated();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -193,7 +250,7 @@ public func AddCableDestination(object new_destination, object crossing, int dis
|
|||
if (!crossing_item) return false;
|
||||
// Save the new destination
|
||||
destination_list[GetLength(destination_list)] = [new_destination, crossing_item[const_nextwaypoint], crossing_item[const_distance] + distance_add];
|
||||
CheckRailStation();
|
||||
DestinationsUpdated();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -223,7 +280,7 @@ public func UpdateCableDestination(object known_destination, object crossing, in
|
|||
// Save the updated path
|
||||
destination_list[destination_item][const_nextwaypoint] = crossing_item[const_nextwaypoint];
|
||||
destination_list[destination_item][const_distance] = crossing_item[const_distance] + distance_add;
|
||||
CheckRailStation();
|
||||
DestinationsUpdated();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -240,7 +297,7 @@ public func ClearConnections(object crossing)
|
|||
for (var connection in FindObjects(Find_Func("IsConnectedTo", this)))
|
||||
{
|
||||
if (! connection->~IsCableLine()) continue;
|
||||
var other_crossing = connection->~GetOtherConnection(this);
|
||||
var other_crossing = connection->~GetConnectedObject(this);
|
||||
if (! other_crossing->~IsCableCrossing()) continue;
|
||||
other_crossing->ClearConnections();
|
||||
}
|
||||
|
@ -256,7 +313,7 @@ public func RenewConnections(object crossing)
|
|||
for(var connection in FindObjects(Find_Func("IsConnectedTo", this)))
|
||||
{
|
||||
if (! connection->~IsCableLine()) continue;
|
||||
var other_crossing = connection->~GetOtherConnection(this);
|
||||
var other_crossing = connection->~GetConnectedObject(this);
|
||||
if (! other_crossing->~IsCableCrossing()) continue;
|
||||
if (other_crossing == crossing) continue;
|
||||
destination_list[GetLength(destination_list)] = [other_crossing, other_crossing, ObjectDistance(other_crossing)];
|
||||
|
@ -264,113 +321,46 @@ public func RenewConnections(object crossing)
|
|||
}
|
||||
}
|
||||
|
||||
/* Station behaviour */
|
||||
/*--- Pathfinding ---*/
|
||||
|
||||
// Prevents the automatic change of the stations status when set to station mode
|
||||
local bManualSetting;
|
||||
|
||||
// IsInteractable is stored in the appendto definitions!
|
||||
|
||||
// A clonk wants to change my station status
|
||||
public func Interact(object pClonk)
|
||||
{
|
||||
// Check ownership
|
||||
if (GetOwner() != NO_OWNER && GetOwner() != pClonk->GetOwner()) return false;
|
||||
// Clonk pushes a cable car?
|
||||
if (pClonk->GetActionTarget() && pClonk->GetActionTarget()->~IsCableCar())
|
||||
{
|
||||
var car = pClonk->GetActionTarget();
|
||||
// Disengage
|
||||
if (car->GetRailTarget() == this)
|
||||
{
|
||||
car->DisengageRail();
|
||||
return true;
|
||||
}
|
||||
// Engage
|
||||
car->EngageRail(this);
|
||||
car->SelectDestination(pClonk, this);
|
||||
return true;
|
||||
}
|
||||
// Change status
|
||||
if (is_station)
|
||||
bManualSetting = false;
|
||||
else
|
||||
bManualSetting = true;
|
||||
CheckRailStation();
|
||||
return _inherited(...);
|
||||
}
|
||||
|
||||
public func GetInteractionMetaInfo(object clonk)
|
||||
{
|
||||
if (is_station)
|
||||
return {IconID = Library_CableStation, IconName = "UnsetStation", Description = "$UnsetStationDesc$"};
|
||||
else
|
||||
return {IconID = Library_CableStation, IconName = "SetStation", Description = "$SetStationDesc$"};
|
||||
}
|
||||
|
||||
/* Animation stuff */
|
||||
|
||||
/** Overload me to do wheel animation
|
||||
@return \c nil.
|
||||
/* Functions:
|
||||
GetNextWaypoint(object end)
|
||||
GetLengthToTarget(object end)
|
||||
*/
|
||||
protected func TurnWheel()
|
||||
{
|
||||
/* EMPTY: Should be overloaded */
|
||||
return;
|
||||
}
|
||||
|
||||
local iActiveCount;
|
||||
// Start/End animation
|
||||
// Call AddActive(0) if any next waypoint wants to start the animation (because a cable car is passing by)
|
||||
// Call AddActive(1) if the cable car passed the line, stopping the animation
|
||||
// Counts up to multiple animated connections
|
||||
public func AddActive(fRemove)
|
||||
{
|
||||
if(!fRemove)
|
||||
iActiveCount++;
|
||||
else
|
||||
iActiveCount--;
|
||||
if(iActiveCount <= 0 && GetAction() == "Active")
|
||||
SetAction("Wait");
|
||||
if(iActiveCount > 0 && GetAction() == "Wait")
|
||||
SetAction("Active");
|
||||
}
|
||||
|
||||
/** Overload me to check station behaviour
|
||||
@return \c nil.
|
||||
/** Returns the waypoint to take next for the desired final point \a end
|
||||
* @param end The final destination for the information is queried
|
||||
*/
|
||||
private func CheckRailStation()
|
||||
public func GetNextWaypoint(object end)
|
||||
{
|
||||
/* EMPTY: Should be overloaded */
|
||||
return _inherited(...);
|
||||
if (!destination_list) return nil;
|
||||
for (var item in destination_list)
|
||||
{
|
||||
if (!item) continue;
|
||||
if (item[const_finaldestination] == end)
|
||||
return item[const_nextwaypoint];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
/* Destruction */
|
||||
|
||||
/* Removes this crossing from the network
|
||||
It first clears every waypoint from the network and then renews the whole information.
|
||||
Optimisation welcome!
|
||||
/** Returns the actual traveling distance for the desired final point \a end
|
||||
* This is not the airline distance but the length of all cables to take via traveling
|
||||
* @param end The final destination for the information is queried
|
||||
*/
|
||||
protected func Destruction()
|
||||
public func GetLengthToTarget(object end)
|
||||
{
|
||||
for (var connection in FindObjects(Find_Func("IsConnectedTo", this)))
|
||||
if (!destination_list) return nil;
|
||||
for (var item in destination_list)
|
||||
{
|
||||
if (! connection->~IsCableLine()) continue;
|
||||
var other_crossing = connection->~GetOtherConnection(this);
|
||||
if (! other_crossing->~IsCableCrossing()) continue;
|
||||
other_crossing->ClearConnections(this);
|
||||
}
|
||||
for (var connection in FindObjects(Find_Func("IsConnectedTo", this)))
|
||||
{
|
||||
if (! connection->~IsCableLine()) continue;
|
||||
var other_crossing = connection->~GetOtherConnection(this);
|
||||
if (! other_crossing->~IsCableCrossing()) continue;
|
||||
other_crossing->RenewConnections(this);
|
||||
if (!item) continue;
|
||||
if (item[const_finaldestination] == end)
|
||||
return item[const_distance];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
/*-- Auto production --*/
|
||||
|
||||
/*
|
||||
public func CheckAcquire(id object_id, int amount)
|
||||
{
|
||||
var container = false;
|
||||
|
@ -421,7 +411,7 @@ public func DeliveryDone(id object_id, int amount)
|
|||
}
|
||||
|
||||
/*-- Object requests and deliveries --*/
|
||||
|
||||
/*
|
||||
local reservations; // two dimensional array with ongoing deliveries: [[ID, amount]]
|
||||
|
||||
public func CheckAvailability(id object_id, int amount)
|
||||
|
@ -469,4 +459,4 @@ public func RequestObjects(object requester, id request_id, int amount)
|
|||
for (var i = 0; i < amount; i++)
|
||||
FindContents(request_id)->Enter(requester);
|
||||
return true;
|
||||
}
|
||||
}*/
|
|
@ -1,5 +0,0 @@
|
|||
Name=Cable Crossing
|
||||
SetStation=Bahnhof einrichten
|
||||
SetStationDesc=Diese Kreuzung zu einem Bahnhof umschalten
|
||||
UnsetStation=Bahnhof abschalten
|
||||
UnsetStationDesc=Diese Kreuzung von einem Bahnhof auf eine Kreuzung zurückschalten
|
|
@ -1,5 +0,0 @@
|
|||
Name=Cable Crossing
|
||||
SetStation=Set station
|
||||
SetStationDesc=Change crossing to station
|
||||
UnsetStation=Reset station
|
||||
UnsetStationDesc=Change station to crossing
|
After Width: | Height: | Size: 1.5 MiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 141 B |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.5 KiB |