Compare commits
130 Commits
Author | SHA1 | Date |
---|---|---|
George Sokianos | c076098ad9 | |
George Sokianos | 5dd814e452 | |
George Sokianos | 43c8bd610f | |
George Sokianos | 6a78b47ae6 | |
George Sokianos | 2b1fd35298 | |
lprobert | fc6bb50460 | |
lprobert | 2aba6c4338 | |
Linus Probert | 39bc060a77 | |
Linus Probert | abef4ed9a6 | |
Linus Probert | 26c5448a30 | |
Linus Probert | 1a559741e2 | |
Linus Probert | 38207e03d1 | |
Linus Probert | e636ec1e53 | |
417e7d3cc8 | ||
Linus Probert | 4edeb17ddc | |
Linus Probert | de770ccc9f | |
Linus Probert | 8a347790c1 | |
Linus Probert | 5a9335576a | |
Linus Probert | b385f6e73a | |
Linus Probert | 4106a856fc | |
Linus Probert | 8221304df8 | |
Linus Probert | 4ceb82f171 | |
Linus Probert | 9e5e1d0a1e | |
Linus Probert | 6d323ca500 | |
Linus Probert | 9aefed0d00 | |
Linus Probert | f102e49daf | |
Linus Probert | 392edd843c | |
Boris Vanhoof | 6584981d10 | |
Boris Vanhoof | d2cf79710a | |
Boris Vanhoof | 78e9413188 | |
Linus Probert | af957eb662 | |
Linus Probert | 1d988d7f2f | |
Linus Probert | 68f4e152d3 | |
Linus Probert | 7f232beb32 | |
Linus Probert | 12aff9afad | |
Linus Probert | 2dc25c9b53 | |
Linus Probert | 5e67ca7ef7 | |
Linus Probert | cac3fea106 | |
Linus Probert | 9ed80acbee | |
Linus Probert | 05cbce0abc | |
Linus Probert | 6c135c6b9c | |
Linus Probert | fb031e2af3 | |
Linus Probert | b861e6e452 | |
Linus Probert | 046551ad6d | |
Linus Probert | 8fb1bbcc1e | |
Linus Probert | 35164a9876 | |
Linus Probert | dd3e84d70d | |
Linus Probert | 8f21e8bfb2 | |
Linus Probert | 2b743160aa | |
Linus Probert | 7ddaab816e | |
Linus Probert | 43ca8f4560 | |
Linus Probert | ef5cd4e244 | |
Linus Probert | b00e607dec | |
Linus Probert | 67e29d609d | |
Linus Probert | 81e7df1920 | |
Linus Probert | 18effa2416 | |
Linus Probert | c043ad09cf | |
Linus Probert | 223a3b00c1 | |
Linus Probert | 2ca78e2ec7 | |
Linus Probert | 0476d4d1bd | |
Linus Probert | 826cbe11ff | |
Linus Probert | fcc6527a93 | |
Linus Probert | b409b76eca | |
Andriy Svyryd | b0753901ec | |
Andriy Svyryd | 86e6f66b58 | |
Linus Probert | c0a4a4eb93 | |
Linus Probert | c917981bad | |
Linus Probert | c2b8fd40eb | |
Linus Probert | 7a59d15be0 | |
Linus Probert | c9fde8dde1 | |
Linus Probert | c4811ed073 | |
Linus Probert | eceb241162 | |
Linus Probert | cea891f87d | |
Linus Probert | 8e282304ad | |
Linus Probert | 53703f1761 | |
Linus Probert | ce182ad20f | |
Linus Probert | ebfe2715e0 | |
Linus Probert | 2ae6ada297 | |
Linus Probert | 18987e2c2a | |
Linus Probert | 59a1e81c6e | |
Linus Probert | 1065216b67 | |
Linus Probert | 68533f05b3 | |
Linus Probert | 38dc3deb2c | |
Linus Probert | beda4f6c7e | |
Linus Probert | e50d40fb1c | |
Linus Probert | 0983bd1bd2 | |
Linus Probert | 184b42ff5a | |
Linus Probert | e42e0243af | |
Linus Probert | 756afbae9d | |
Linus Probert | 40a20e936c | |
Linus Probert | af930f6b23 | |
Linus Probert | c4fd16d925 | |
Linus Probert | f840b28839 | |
Linus Probert | 7fbeaa3907 | |
Linus Probert | 3e43c30bcb | |
Linus Probert | fd3a625249 | |
Linus Probert | d749861477 | |
Linus Probert | 7ab5ece83b | |
Linus Probert | 8c9622d6bd | |
Linus Probert | af0c61684d | |
Linus Probert | 46fbdc1b3c | |
Linus Probert | b40c54a88d | |
Linus Probert | 8f20f36db7 | |
Linus Probert | 3ba33d8852 | |
Linus Probert | 447c1a773c | |
Linus Probert | 7e1dffb45e | |
Linus Probert | 6009aa17f1 | |
Linus Probert | 9b4a7b6cfc | |
Linus Probert | 63812fbe05 | |
Linus Probert | c6a022e2db | |
Linus Probert | 06ca6c3e1e | |
Linus Probert | bab5fd7980 | |
Linus Probert | 68f44090ed | |
Linus Probert | 959fae1730 | |
Linus Probert | ca41520c06 | |
Linus Probert | 88f4703d00 | |
Linus Probert | 486c1bb641 | |
Linus Probert | 206f95f3b6 | |
Linus Probert | 1c4e600dd4 | |
Linus Probert | 57a16888b8 | |
Linus Probert | 13ca11c70e | |
Linus Probert | 33efba87b5 | |
Linus Probert | 5d61a91139 | |
Linus Probert | 6542e4f1d0 | |
Linus Probert | 7b47c6a6bf | |
Linus Probert | 16d9035941 | |
Linus Probert | 4054c37caa | |
Linus Probert | ad227f1bed | |
Linus Probert | 37ba189e54 | |
Linus Probert | 645a02c99e |
|
@ -0,0 +1,12 @@
|
||||||
|
# These are supported funding model platforms
|
||||||
|
|
||||||
|
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||||
|
patreon: # Replace with a single Patreon username
|
||||||
|
open_collective: # Replace with a single Open Collective username
|
||||||
|
ko_fi: LiquidityC
|
||||||
|
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||||
|
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||||
|
liberapay: # Replace with a single Liberapay username
|
||||||
|
issuehunt: # Replace with a single IssueHunt username
|
||||||
|
otechie: # Replace with a single Otechie username
|
||||||
|
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
|
@ -1,3 +1,5 @@
|
||||||
|
/.vscode/
|
||||||
|
/vscode_build/
|
||||||
/CMakeSettings.json
|
/CMakeSettings.json
|
||||||
/_build/
|
/_build/
|
||||||
/*.dll
|
/*.dll
|
||||||
|
@ -13,3 +15,7 @@
|
||||||
/steam_appid.txt
|
/steam_appid.txt
|
||||||
/*.so
|
/*.so
|
||||||
/breakhack*.run
|
/breakhack*.run
|
||||||
|
compile_commands.json
|
||||||
|
*.o
|
||||||
|
breakhack
|
||||||
|
|
||||||
|
|
2
.vimrc
2
.vimrc
|
@ -5,5 +5,5 @@ nnoremap <F4> :ter ++close env LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./ ./_build/debu
|
||||||
|
|
||||||
packadd termdebug
|
packadd termdebug
|
||||||
let g:termdebug_wide = 1
|
let g:termdebug_wide = 1
|
||||||
let g:syntastic_c_include_dirs = [ '_build/debug', '/usr/include/SDL2', 'steamworks_c_wrapper/src', 'physfs-3.0/src', 'bh_random/src' ]
|
let g:syntastic_c_include_dirs = [ '_build/debug', '/usr/include/SDL2', 'steamworks_c_wrapper/src', 'physfs-3.0/src', 'bh_random/src', 'checksum/src' ]
|
||||||
let g:syntastic_cpp_include_dirs = [ 'steamworks_c_wrapper/sdk/public/steam', 'bh_random/src' ]
|
let g:syntastic_cpp_include_dirs = [ 'steamworks_c_wrapper/sdk/public/steam', 'bh_random/src' ]
|
||||||
|
|
188
CMakeLists.txt
188
CMakeLists.txt
|
@ -5,11 +5,15 @@ SET(CMAKE_COLOR_MAKEFILE ON)
|
||||||
project(breakhack C)
|
project(breakhack C)
|
||||||
|
|
||||||
set(breakhack_GAME_TITLE "BreakHack")
|
set(breakhack_GAME_TITLE "BreakHack")
|
||||||
set(breakhack_MAJOR_VERSION 2)
|
set(breakhack_MAJOR_VERSION 4)
|
||||||
set(breakhack_MINOR_VERSION 1)
|
set(breakhack_MINOR_VERSION 0)
|
||||||
set(breakhack_PATCH_VERSION 4)
|
set(breakhack_PATCH_VERSION 3)
|
||||||
set(breakhack_RELEASE_TYPE "")
|
set(breakhack_RELEASE_TYPE "")
|
||||||
|
|
||||||
|
# Checksums
|
||||||
|
set(breakhack_STEAMAPI_DLL_CHECKSUM 0x18dba28)
|
||||||
|
set(breakhack_STEAMAPI_SO_CHECKSUM 0x1f5786b)
|
||||||
|
|
||||||
include(FindLua)
|
include(FindLua)
|
||||||
include(FindPhysFS)
|
include(FindPhysFS)
|
||||||
include(build/cmake/FindSDL2.cmake)
|
include(build/cmake/FindSDL2.cmake)
|
||||||
|
@ -40,6 +44,7 @@ if (STEAM)
|
||||||
add_subdirectory(steamworks_c_wrapper)
|
add_subdirectory(steamworks_c_wrapper)
|
||||||
endif()
|
endif()
|
||||||
add_subdirectory(bh_random)
|
add_subdirectory(bh_random)
|
||||||
|
add_subdirectory(checksum)
|
||||||
|
|
||||||
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
|
if ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
|
||||||
set(CLANG 1)
|
set(CLANG 1)
|
||||||
|
@ -47,6 +52,10 @@ elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
|
||||||
set(GCC 1)
|
set(GCC 1)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if ("${CMAKE_GENERATOR}" STREQUAL "Ninja")
|
||||||
|
set(NINJA 1)
|
||||||
|
endif()
|
||||||
|
|
||||||
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
|
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
|
||||||
set(OSX 1)
|
set(OSX 1)
|
||||||
endif()
|
endif()
|
||||||
|
@ -68,15 +77,17 @@ endif()
|
||||||
|
|
||||||
IF ( MSVC )
|
IF ( MSVC )
|
||||||
MESSAGE ( STATUS "Setting MSVC MT switches")
|
MESSAGE ( STATUS "Setting MSVC MT switches")
|
||||||
SET (
|
string (REPLACE
|
||||||
CMAKE_C_FLAGS_DEBUG
|
"/MDd"
|
||||||
"${CMAKE_C_FLAGS_DEBUG} /MTd"
|
"/MTd"
|
||||||
CACHE STRING "MSVC MT flags " FORCE
|
CMAKE_C_FLAGS_DEBUG
|
||||||
|
${CMAKE_C_FLAGS_DEBUG}
|
||||||
)
|
)
|
||||||
SET (
|
string (REPLACE
|
||||||
CMAKE_C_FLAGS_RELEASE
|
"/MDd"
|
||||||
"${CMAKE_C_FLAGS_RELEASE} /MT"
|
"/MTd"
|
||||||
CACHE STRING "MSVC MT flags " FORCE
|
CMAKE_C_FLAGS_RELEASE
|
||||||
|
${CMAKE_C_FLAGS_RELEASE}
|
||||||
)
|
)
|
||||||
ELSEIF ( WIN32 )
|
ELSEIF ( WIN32 )
|
||||||
SET (
|
SET (
|
||||||
|
@ -128,6 +139,7 @@ include_directories(
|
||||||
${LUA_INCLUDE_DIR}
|
${LUA_INCLUDE_DIR}
|
||||||
sqlite3
|
sqlite3
|
||||||
bh_random/src
|
bh_random/src
|
||||||
|
checksum/src
|
||||||
)
|
)
|
||||||
|
|
||||||
if (CMOCKA_FOUND)
|
if (CMOCKA_FOUND)
|
||||||
|
@ -153,17 +165,6 @@ set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG")
|
||||||
if (STEAM)
|
if (STEAM)
|
||||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSTEAM_BUILD")
|
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSTEAM_BUILD")
|
||||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DSTEAM_BUILD")
|
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DSTEAM_BUILD")
|
||||||
endif ()
|
|
||||||
if (MINGW)
|
|
||||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DMINGW")
|
|
||||||
endif (MINGW)
|
|
||||||
if (NOT MSVC)
|
|
||||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D__FNAME__='\"$(subst ${CMAKE_SOURCE_DIR}/,,$(abspath $<))\"'")
|
|
||||||
else (NOT MSVC)
|
|
||||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D__FNAME__=__FILE__")
|
|
||||||
endif (NOT MSVC)
|
|
||||||
|
|
||||||
if (STEAM)
|
|
||||||
set(STEAM_SOURCES
|
set(STEAM_SOURCES
|
||||||
src/steam/steamworks_api_wrapper
|
src/steam/steamworks_api_wrapper
|
||||||
)
|
)
|
||||||
|
@ -171,59 +172,74 @@ else ()
|
||||||
set(STEAM_SOURCES "")
|
set(STEAM_SOURCES "")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
if (MINGW)
|
||||||
|
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DMINGW")
|
||||||
|
endif (MINGW)
|
||||||
|
|
||||||
|
if (NOT MSVC)
|
||||||
|
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D__FNAME__='\"$(subst ${CMAKE_SOURCE_DIR}/,,$(abspath $<))\"'")
|
||||||
|
else ()
|
||||||
|
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D__FNAME__=__FILE__")
|
||||||
|
endif ()
|
||||||
|
|
||||||
# PROGRAMS:
|
# PROGRAMS:
|
||||||
add_executable(breakhack
|
add_executable(breakhack
|
||||||
src/main
|
src/main.c
|
||||||
src/texture
|
src/texture.c
|
||||||
src/screenresolution
|
src/screenresolution.c
|
||||||
src/sprite
|
src/sprite.c
|
||||||
src/util
|
src/sprite_util.c
|
||||||
src/player
|
src/util.c
|
||||||
src/map
|
src/event.c
|
||||||
src/map_lua
|
src/player.c
|
||||||
src/camera
|
src/save.c
|
||||||
src/timer
|
src/map.c
|
||||||
src/roommatrix
|
src/map_lua.c
|
||||||
src/position
|
src/camera.c
|
||||||
src/monster
|
src/timer.c
|
||||||
src/stats
|
src/roommatrix.c
|
||||||
src/actiontext
|
src/position.c
|
||||||
src/random
|
src/monster.c
|
||||||
src/time
|
src/stats.c
|
||||||
src/linkedlist
|
src/actiontext.c
|
||||||
src/hashtable
|
src/random.c
|
||||||
src/gui
|
src/time.c
|
||||||
src/item
|
src/linkedlist.c
|
||||||
src/item_builder
|
src/hashtable.c
|
||||||
src/pointer
|
src/gui.c
|
||||||
src/gui_button
|
src/item.c
|
||||||
src/particle_engine
|
src/item_builder.c
|
||||||
src/menu
|
src/pointer.c
|
||||||
src/collisions
|
src/gui_button.c
|
||||||
src/keyboard
|
src/particle_engine.c
|
||||||
src/input
|
src/particle_emitter.c
|
||||||
src/mixer
|
src/menu.c
|
||||||
src/io_util
|
src/collisions.c
|
||||||
src/physfsrwops
|
src/keyboard.c
|
||||||
src/skillbar
|
src/input.c
|
||||||
src/texturecache
|
src/mixer.c
|
||||||
src/skill
|
src/io_util.c
|
||||||
src/projectile
|
src/physfsrwops.c
|
||||||
src/vector2d
|
src/skillbar.c
|
||||||
src/map_room_modifiers
|
src/texturecache.c
|
||||||
sqlite3/sqlite3
|
src/skill.c
|
||||||
src/db
|
src/projectile.c
|
||||||
src/settings
|
src/vector2d.c
|
||||||
src/actiontextbuilder
|
src/map_room_modifiers.c
|
||||||
src/animation
|
sqlite3/sqlite3.c
|
||||||
src/trap
|
src/db.c
|
||||||
src/artifact
|
src/settings.c
|
||||||
src/screen
|
src/actiontextbuilder.c
|
||||||
src/hiscore
|
src/animation.c
|
||||||
src/object
|
src/trap.c
|
||||||
src/gui_util
|
src/artifact.c
|
||||||
src/tooltip
|
src/screen.c
|
||||||
src/gamecontroller
|
src/hiscore.c
|
||||||
|
src/object.c
|
||||||
|
src/gui_util.c
|
||||||
|
src/tooltip.c
|
||||||
|
src/gamecontroller.c
|
||||||
|
src/effect_util.c
|
||||||
${STEAM_SOURCES}
|
${STEAM_SOURCES}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -245,6 +261,7 @@ target_link_libraries(breakhack
|
||||||
${LUA_LIBRARIES}
|
${LUA_LIBRARIES}
|
||||||
${PHYSFS_LIBRARY}
|
${PHYSFS_LIBRARY}
|
||||||
bh_random
|
bh_random
|
||||||
|
checksum
|
||||||
)
|
)
|
||||||
|
|
||||||
if (STEAM)
|
if (STEAM)
|
||||||
|
@ -254,11 +271,11 @@ if (STEAM)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
set_target_properties(breakhack PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE")
|
set_target_properties(breakhack PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE /NODEFAULTLIB:MSVCRTD")
|
||||||
set_target_properties(breakhack PROPERTIES COMPILE_DEFINITIONS_DEBUG "_CONSOLE")
|
set_target_properties(breakhack PROPERTIES COMPILE_DEFINITIONS_DEBUG "_CONSOLE")
|
||||||
set_target_properties(breakhack PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:CONSOLE")
|
set_target_properties(breakhack PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:CONSOLE")
|
||||||
set_target_properties(breakhack PROPERTIES COMPILE_DEFINITIONS_RELWITHDEBINFO "_CONSOLE")
|
set_target_properties(breakhack PROPERTIES COMPILE_DEFINITIONS_RELWITHDEBINFO "_CONSOLE")
|
||||||
set_target_properties(breakhack PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS")
|
set_target_properties(breakhack PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS /NODEFAULTLIB:MSVCRTD")
|
||||||
set_target_properties(breakhack PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS")
|
set_target_properties(breakhack PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS")
|
||||||
endif (MSVC)
|
endif (MSVC)
|
||||||
|
|
||||||
|
@ -266,19 +283,19 @@ endif (MSVC)
|
||||||
IF (CMOCKA_FOUND AND NOT OSX AND NOT CLANG)
|
IF (CMOCKA_FOUND AND NOT OSX AND NOT CLANG)
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
enable_testing()
|
enable_testing()
|
||||||
add_executable(test_util test/test_util src/util)
|
add_executable(test_util test/test_util.c src/util.c)
|
||||||
target_link_libraries(test_util ${CMOCKA_LIBRARY})
|
target_link_libraries(test_util ${CMOCKA_LIBRARY})
|
||||||
add_test(test_util test_util)
|
add_test(test_util test_util)
|
||||||
|
|
||||||
add_executable(test_linkedlist test/test_linkedlist src/linkedlist src/util)
|
add_executable(test_linkedlist test/test_linkedlist.c src/linkedlist.c src/util.c)
|
||||||
target_link_libraries(test_linkedlist ${CMOCKA_LIBRARY})
|
target_link_libraries(test_linkedlist ${CMOCKA_LIBRARY})
|
||||||
add_test(test_linkedlist test_linkedlist)
|
add_test(test_linkedlist test_linkedlist)
|
||||||
|
|
||||||
add_executable(test_hashtable test/test_hashtable src/hashtable src/util)
|
add_executable(test_hashtable test/test_hashtable.c src/hashtable.c src/util.c)
|
||||||
target_link_libraries(test_hashtable ${CMOCKA_LIBRARY})
|
target_link_libraries(test_hashtable ${CMOCKA_LIBRARY})
|
||||||
add_test(test_hashtable test_hashtable)
|
add_test(test_hashtable test_hashtable)
|
||||||
|
|
||||||
add_executable(test_input test/test_input src/input src/keyboard)
|
add_executable(test_input test/test_input.c src/input.c src/keyboard.c)
|
||||||
target_link_libraries(test_input
|
target_link_libraries(test_input
|
||||||
${CMOCKA_LIBRARY}
|
${CMOCKA_LIBRARY}
|
||||||
${SDL2_LIBRARY}
|
${SDL2_LIBRARY}
|
||||||
|
@ -292,7 +309,7 @@ ENDIF ()
|
||||||
# LINT:
|
# LINT:
|
||||||
if (CPPCHECK_FOUND)
|
if (CPPCHECK_FOUND)
|
||||||
add_custom_target(lint
|
add_custom_target(lint
|
||||||
COMMAND ${CPPCHECK_EXECUTABLE} --force --language=c --template=gcc --error-exitcode=1 --quiet --enable=warning,style,performance,portability,information,missingInclude src/
|
COMMAND ${CPPCHECK_EXECUTABLE} --force --language=c --template=gcc --error-exitcode=1 --quiet --suppress=missingInclude --enable=warning,style,performance,portability,information,missingInclude src/
|
||||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||||
COMMENT "Run cppcheck"
|
COMMENT "Run cppcheck"
|
||||||
)
|
)
|
||||||
|
@ -319,16 +336,13 @@ if (NOT DEBUG_BUILD)
|
||||||
"monstergen.lua"
|
"monstergen.lua"
|
||||||
"trapgen.lua"
|
"trapgen.lua"
|
||||||
"chestgen.lua"
|
"chestgen.lua"
|
||||||
|
"layoutparser.lua"
|
||||||
"pitlayouts.dat"
|
"pitlayouts.dat"
|
||||||
|
"walllayouts.dat"
|
||||||
|
"shoplayouts.dat"
|
||||||
|
"lockedroomlayouts.dat"
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data
|
||||||
)
|
)
|
||||||
if (WIN32 AND NOT MSVC)
|
|
||||||
add_definitions(-mwindows)
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
if (WIN32)
|
|
||||||
add_definitions(-mconsole)
|
|
||||||
endif()
|
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
SET(CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT "Release")
|
SET(CMAKE_INSTALL_SYSTEM_RUNTIME_COMPONENT "Release")
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
Apart from basic compile tools (*GCC/Clang, Make*) you'll also need to install **sdl2, sdl2-image, sdl2-ttf, sdl2-mixer** (If on a debian based dist you need to install the *dev* packages).
|
||||||
|
Optionally you can also install **cppcheck** and **physfs**
|
||||||
|
|
||||||
|
Once that is done run the following:
|
||||||
|
```bash
|
||||||
|
mkdir _build
|
||||||
|
cd _build
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Debug .. # Build type flag is optional
|
||||||
|
make
|
||||||
|
```
|
|
@ -0,0 +1,16 @@
|
||||||
|
Compile on Windows with Visual Studio
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
1. Install [Visual Studio Community 2019](https://visualstudio.microsoft.com/vs/community/) with the "Desktop development with C++" workload
|
||||||
|
2. Install [CMake](https://cmake.org/download/)
|
||||||
|
3. Install [NSIS](https://nsis.sourceforge.io/Download)
|
||||||
|
4. Download and unzip [SDL2-devel-2.x.x-VC.zip](https://www.libsdl.org/download-2.0.php), [SDL2_image-devel-2.x.x-VC.zip](https://www.libsdl.org/projects/SDL_image/), [SDL2_mixer-devel-2.x.x-VC.zip](https://www.libsdl.org/projects/SDL_mixer/), [SDL2_ttf-devel-2.x.x-VC.zip](https://www.libsdl.org/projects/SDL_ttf/)
|
||||||
|
5. Open Developer Command Prompt for VS 2019 and run the following, substituting paths as appropriate:
|
||||||
|
```batch
|
||||||
|
SET SDL2DIR=C:\repos\breakhackBuild\SDL2-2.0.9
|
||||||
|
SET SDL2MIXERDIR=C:\repos\breakhackBuild\SDL2_mixer-2.0.4
|
||||||
|
SET SDL2_IMAGE=C:\repos\breakhackBuild\SDL2_image-2.0.4
|
||||||
|
SET SDLTTFDIR=C:\repos\breakhackBuild\SDL2_ttf-2.0.15
|
||||||
|
cmake -S C:\repos\breakhack -B C:\repos\breakhackBuild
|
||||||
|
cmake --build C:\repos\breakhackBuild --target package --config Release
|
||||||
|
```
|
30
Makefile
30
Makefile
|
@ -7,12 +7,12 @@ release:
|
||||||
.PHONY: release
|
.PHONY: release
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@make clean -sC _build/debug
|
@make -sC _build/debug clean
|
||||||
@make clean -sC _build/release
|
@make -sC _build/release clean
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
|
|
||||||
test:
|
test:
|
||||||
@make test -sC _build/debug
|
@make -sC _build/debug test
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
|
|
||||||
run: $(all)
|
run: $(all)
|
||||||
|
@ -21,12 +21,30 @@ run: $(all)
|
||||||
|
|
||||||
playtest: $(all)
|
playtest: $(all)
|
||||||
@LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./ ./_build/release/breakhack
|
@LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./ ./_build/release/breakhack
|
||||||
.PHONY: run
|
.PHONY: playtest
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
@make lint -sC _build/debug
|
@make -sC _build/debug lint
|
||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
|
|
||||||
package:
|
package:
|
||||||
@make package -sC _build/release
|
@make -sC _build/release package
|
||||||
.PHONY: package
|
.PHONY: package
|
||||||
|
|
||||||
|
setup:
|
||||||
|
@mkdir -p _build/release
|
||||||
|
@mkdir -p _build/debug
|
||||||
|
@cd _build/debug/ && \
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=YES ../.. && \
|
||||||
|
cd -
|
||||||
|
@cd _build/debug/ && \
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Release ../.. && \
|
||||||
|
cd -
|
||||||
|
@ln -s _build/debug/compile_commands.json
|
||||||
|
@echo "Setup complete"
|
||||||
|
.PHONY: setup
|
||||||
|
|
||||||
|
teardown:
|
||||||
|
@rm -rf _build
|
||||||
|
@rm compile_commands.json
|
||||||
|
.PHONY: teardown
|
||||||
|
|
|
@ -0,0 +1,503 @@
|
||||||
|
#
|
||||||
|
# Project: breakhack
|
||||||
|
#
|
||||||
|
# Created on: 29-08-2022 21:00:37
|
||||||
|
# by George Sokianos
|
||||||
|
#
|
||||||
|
|
||||||
|
###################################################################
|
||||||
|
##
|
||||||
|
##//// Objects
|
||||||
|
##
|
||||||
|
###################################################################
|
||||||
|
|
||||||
|
breakhack_OBJ := \
|
||||||
|
src/actiontext.o src/actiontextbuilder.o src/animation.o \
|
||||||
|
src/artifact.o src/camera.o src/collisions.o \
|
||||||
|
src/db.o src/effect_util.o src/event.o \
|
||||||
|
src/gamecontroller.o src/gui_button.o src/gui.o \
|
||||||
|
src/gui_util.o src/hashtable.o src/hiscore.o \
|
||||||
|
src/input.o src/io_util.o src/item_builder.o \
|
||||||
|
src/item.o src/keyboard.o src/linkedlist.o \
|
||||||
|
src/main.o src/map.o src/map_lua.o \
|
||||||
|
src/map_room_modifiers.o src/menu.o src/mixer.o \
|
||||||
|
src/monster.o src/object.o src/particle_emitter.o \
|
||||||
|
src/particle_engine.o src/physfsrwops.o src/player.o \
|
||||||
|
src/pointer.o src/position.o src/projectile.o \
|
||||||
|
src/random.o src/roommatrix.o src/save.o \
|
||||||
|
src/screen.o src/screenresolution.o src/settings.o \
|
||||||
|
src/skill.o src/skillbar.o src/sprite.o \
|
||||||
|
src/sprite_util.o src/stats.o src/texture.o \
|
||||||
|
src/texturecache.o src/time.o src/timer.o \
|
||||||
|
src/tooltip.o src/trap.o src/util.o \
|
||||||
|
src/vector2d.o bh_random/src/bh_random.o
|
||||||
|
|
||||||
|
|
||||||
|
###################################################################
|
||||||
|
##
|
||||||
|
##//// Variables and Environment
|
||||||
|
##
|
||||||
|
###################################################################
|
||||||
|
|
||||||
|
CC := gcc:bin/gcc
|
||||||
|
|
||||||
|
INCPATH := -I. -I/sdk/local/newlib/include/SDL2 -Ibh_random/src \
|
||||||
|
-I/sdk/local/common/include/lua53
|
||||||
|
# -DDEBUG
|
||||||
|
|
||||||
|
CFLAGS := $(INCPATH) -Wall -Wwrite-strings -Wno-discarded-qualifiers
|
||||||
|
# \
|
||||||
|
# -g -gstabs
|
||||||
|
# -ggdb -gdwarf-2
|
||||||
|
|
||||||
|
LFLAGS := -lauto -lSDL2_image -lSDL2_ttf -lfreetype -ltiff -lwebp -lpng -ljpeg \
|
||||||
|
-llua53 -lsqlite3 -lz \
|
||||||
|
-lSDL2_mixer -lmikmod -lmodplug -lFLAC -logg \
|
||||||
|
-lSDL2 -lphysfs -lpthread -athread=native -lstdc++
|
||||||
|
# \
|
||||||
|
# -g -gstabs
|
||||||
|
# -ggdb -gdwarf-2
|
||||||
|
# -lunix
|
||||||
|
|
||||||
|
# -lenet -lcrypto -lSDL2_gl4es -lglu_gl4es -lgl4es -lopenal \
|
||||||
|
###################################################################
|
||||||
|
##
|
||||||
|
##//// General rules
|
||||||
|
##
|
||||||
|
###################################################################
|
||||||
|
|
||||||
|
.PHONY: all all-before all-after clean clean-custom realclean
|
||||||
|
|
||||||
|
all: all-before breakhack all-after
|
||||||
|
|
||||||
|
all-before:
|
||||||
|
# You can add rules here to execute before the project is built
|
||||||
|
|
||||||
|
all-after:
|
||||||
|
# You can add rules here to execute after the project is built
|
||||||
|
|
||||||
|
clean: clean-custom
|
||||||
|
@echo "Cleaning compiler objects..."
|
||||||
|
@rm -f $(breakhack_OBJ)
|
||||||
|
|
||||||
|
realclean:
|
||||||
|
@echo "Cleaning compiler objects and targets..."
|
||||||
|
@rm -f $(breakhack_OBJ) breakhack
|
||||||
|
|
||||||
|
|
||||||
|
###################################################################
|
||||||
|
##
|
||||||
|
##//// Targets
|
||||||
|
##
|
||||||
|
###################################################################
|
||||||
|
|
||||||
|
breakhack: $(breakhack_OBJ)
|
||||||
|
@echo "Linking breakhack"
|
||||||
|
@gcc:bin/gcc -o breakhack $(breakhack_OBJ) $(LFLAGS)
|
||||||
|
@echo "Removing stale debug target: breakhack"
|
||||||
|
@rm -f breakhack.debug
|
||||||
|
|
||||||
|
|
||||||
|
###################################################################
|
||||||
|
##
|
||||||
|
##//// Standard rules
|
||||||
|
##
|
||||||
|
###################################################################
|
||||||
|
|
||||||
|
# A default rule to make all the objects listed below
|
||||||
|
# because we are hiding compiler commands from the output
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
@echo "Compiling $<"
|
||||||
|
@$(CC) -c $< -o $*.o $(CFLAGS)
|
||||||
|
|
||||||
|
src/actiontext.o: src/actiontext.c src/actiontext.h \
|
||||||
|
src/position.h src/sprite.h src/texture.h \
|
||||||
|
src/camera.h src/roommatrix.h src/timer.h \
|
||||||
|
src/vector2d.h src/util.h src/update_data.h \
|
||||||
|
src/player.h src/stats.h src/skill.h \
|
||||||
|
src/linkedlist.h src/input.h src/artifact.h \
|
||||||
|
src/map.h src/defines.h src/monster.h \
|
||||||
|
src/map_room_modifiers.h src/object.h src/doorlocktype.h
|
||||||
|
|
||||||
|
src/actiontextbuilder.o: src/actiontextbuilder.c src/actiontextbuilder.h src/actiontext.h \
|
||||||
|
src/position.h src/sprite.h src/timer.h \
|
||||||
|
src/vector2d.h src/camera.h src/update_data.h \
|
||||||
|
src/player.h src/map.h src/roommatrix.h \
|
||||||
|
src/gui.h src/util.h
|
||||||
|
|
||||||
|
src/animation.o: src/animation.c src/animation.h src/timer.h \
|
||||||
|
src/camera.h src/position.h src/vector2d.h \
|
||||||
|
src/sprite.h src/texture.h \
|
||||||
|
src/dimension.h src/roommatrix.h src/defines.h \
|
||||||
|
src/map_room_modifiers.h src/input.h
|
||||||
|
|
||||||
|
src/artifact.o: src/artifact.c src/artifact.h src/sprite.h \
|
||||||
|
src/texture.h src/position.h src/camera.h \
|
||||||
|
src/roommatrix.h src/timer.h \
|
||||||
|
src/vector2d.h src/util.h src/texturecache.h \
|
||||||
|
src/dimension.h src/particle_engine.h src/player.h \
|
||||||
|
src/stats.h src/actiontext.h src/skill.h \
|
||||||
|
src/linkedlist.h src/input.h src/random.h \
|
||||||
|
|
||||||
|
|
||||||
|
src/camera.o: src/camera.c src/camera.h src/position.h \
|
||||||
|
src/timer.h src/vector2d.h src/map.h \
|
||||||
|
src/linkedlist.h src/sprite.h src/texture.h \
|
||||||
|
src/roommatrix.h src/defines.h src/config.h \
|
||||||
|
src/monster.h src/stats.h src/actiontext.h \
|
||||||
|
src/player.h src/doorlocktype.h src/particle_emitter.h \
|
||||||
|
src/skill.h src/input.h src/artifact.h \
|
||||||
|
src/map_room_modifiers.h src/object.h src/util.h
|
||||||
|
|
||||||
|
src/collisions.o: src/collisions.c src/collisions.h
|
||||||
|
|
||||||
|
src/db.o: src/db.c src/db.h
|
||||||
|
|
||||||
|
src/effect_util.o: src/effect_util.c src/gui.h src/linkedlist.h \
|
||||||
|
src/sprite.h src/texture.h src/position.h \
|
||||||
|
src/camera.h src/roommatrix.h src/timer.h \
|
||||||
|
src/vector2d.h src/player.h \
|
||||||
|
src/stats.h src/actiontext.h src/skill.h \
|
||||||
|
src/input.h src/artifact.h src/monster.h src/doorlocktype.h \
|
||||||
|
src/particle_emitter.h src/dimension.h src/defines.h \
|
||||||
|
src/config.h src/map_room_modifiers.h
|
||||||
|
|
||||||
|
src/event.o: src/event.c src/event.h src/player.h \
|
||||||
|
src/sprite.h src/stats.h \
|
||||||
|
src/actiontext.h src/camera.h src/skill.h \
|
||||||
|
src/linkedlist.h src/input.h src/artifact.h
|
||||||
|
|
||||||
|
src/gamecontroller.o: src/gamecontroller.c src/gamecontroller.h
|
||||||
|
|
||||||
|
src/gui_button.o: src/gui_button.c src/util.h src/gui_button.h \
|
||||||
|
src/pointer.h src/sprite.h src/camera.h \
|
||||||
|
src/input.h src/texture.h src/position.h \
|
||||||
|
src/roommatrix.h src/timer.h src/linkedlist.h \
|
||||||
|
src/vector2d.h
|
||||||
|
|
||||||
|
src/gui.o: src/gui.c src/gui.h src/linkedlist.h \
|
||||||
|
src/sprite.h src/texture.h src/position.h \
|
||||||
|
src/camera.h src/roommatrix.h src/timer.h \
|
||||||
|
src/vector2d.h src/player.h \
|
||||||
|
src/stats.h src/actiontext.h src/skill.h \
|
||||||
|
src/input.h src/artifact.h src/util.h \
|
||||||
|
src/map.h \
|
||||||
|
src/defines.h src/config.h src/monster.h \
|
||||||
|
src/doorlocktype.h src/particle_emitter.h src/map_room_modifiers.h \
|
||||||
|
src/object.h src/texturecache.h \
|
||||||
|
src/dimension.h src/gui_util.h
|
||||||
|
|
||||||
|
src/gui_util.o: src/gui_util.c src/texturecache.h src/texture.h \
|
||||||
|
src/dimension.h src/position.h \
|
||||||
|
src/camera.h src/gui_util.h src/sprite.h \
|
||||||
|
src/roommatrix.h src/timer.h
|
||||||
|
|
||||||
|
src/hashtable.o: src/hashtable.c src/hashtable.h src/defines.h \
|
||||||
|
src/config.h
|
||||||
|
|
||||||
|
src/hiscore.o: src/hiscore.c src/hiscore.h src/linkedlist.h \
|
||||||
|
src/player.h src/sprite.h \
|
||||||
|
src/stats.h src/actiontext.h src/camera.h \
|
||||||
|
src/skill.h src/input.h src/artifact.h \
|
||||||
|
src/db.h
|
||||||
|
|
||||||
|
src/input.o: src/input.c src/input.h
|
||||||
|
|
||||||
|
src/io_util.o: src/io_util.c src/physfsrwops.h src/io_util.h
|
||||||
|
|
||||||
|
src/item_builder.o: src/item_builder.c src/item_builder.h \
|
||||||
|
src/item.h src/sprite.h src/position.h \
|
||||||
|
src/player.h src/camera.h src/linkedlist.h \
|
||||||
|
src/texture.h src/dimension.h \
|
||||||
|
src/timer.h src/vector2d.h src/util.h \
|
||||||
|
src/gui.h src/roommatrix.h src/stats.h \
|
||||||
|
src/actiontext.h src/skill.h src/input.h \
|
||||||
|
src/artifact.h src/mixer.h src/gamestate.h \
|
||||||
|
src/random.h src/texturecache.h src/defines.h \
|
||||||
|
src/map_room_modifiers.h src/sprite_util.h src/map.h \
|
||||||
|
src/config.h src/monster.h src/doorlocktype.h \
|
||||||
|
src/particle_emitter.h
|
||||||
|
|
||||||
|
src/item.o: src/item.c src/item.h src/sprite.h \
|
||||||
|
src/texture.h src/position.h src/camera.h \
|
||||||
|
src/roommatrix.h src/timer.h src/player.h \
|
||||||
|
src/stats.h src/actiontext.h \
|
||||||
|
src/skill.h src/linkedlist.h src/input.h \
|
||||||
|
src/artifact.h src/vector2d.h src/util.h \
|
||||||
|
src/mixer.h src/gamestate.h src/gui.h \
|
||||||
|
src/actiontextbuilder.h src/update_data.h
|
||||||
|
|
||||||
|
src/keyboard.o: src/keyboard.c src/keyboard.h src/defines.h \
|
||||||
|
src/config.h
|
||||||
|
|
||||||
|
src/linkedlist.o: src/linkedlist.c src/linkedlist.h
|
||||||
|
|
||||||
|
src/main.o: src/main.c /sdk/local/newlib/include/SDL2/SDL_main.h \
|
||||||
|
src/linkedlist.h src/player.h src/sprite.h \
|
||||||
|
src/texture.h src/position.h src/camera.h \
|
||||||
|
src/roommatrix.h src/timer.h src/stats.h \
|
||||||
|
src/actiontext.h src/vector2d.h src/skill.h \
|
||||||
|
src/input.h src/artifact.h src/screenresolution.h \
|
||||||
|
src/dimension.h src/map.h src/defines.h \
|
||||||
|
src/config.h src/monster.h src/doorlocktype.h \
|
||||||
|
src/particle_emitter.h src/map_room_modifiers.h src/object.h \
|
||||||
|
src/map_lua.h src/gamestate.h src/gui.h \
|
||||||
|
src/util.h src/item_builder.h src/item.h \
|
||||||
|
src/pointer.h src/gui_button.h src/particle_engine.h \
|
||||||
|
src/menu.h src/keyboard.h \
|
||||||
|
src/mixer.h src/random.h src/skillbar.h \
|
||||||
|
src/texturecache.h src/update_data.h src/settings.h \
|
||||||
|
src/actiontextbuilder.h src/screen.h src/hiscore.h \
|
||||||
|
src/io_util.h src/tooltip.h src/gamecontroller.h \
|
||||||
|
src/time.h src/sprite_util.h src/event.h \
|
||||||
|
src/save.h src/steam/steamworks_api_wrapper.h src/defines.h
|
||||||
|
|
||||||
|
src/map.o: src/map.c src/map.h src/linkedlist.h \
|
||||||
|
src/sprite.h src/texture.h src/position.h \
|
||||||
|
src/camera.h src/roommatrix.h src/timer.h \
|
||||||
|
src/vector2d.h src/defines.h src/config.h \
|
||||||
|
src/monster.h src/stats.h src/actiontext.h \
|
||||||
|
src/player.h src/doorlocktype.h src/particle_emitter.h \
|
||||||
|
src/skill.h src/input.h src/artifact.h \
|
||||||
|
src/map_room_modifiers.h src/object.h src/map_lua.h \
|
||||||
|
src/util.h src/item.h src/item_builder.h \
|
||||||
|
src/gui.h src/particle_engine.h src/dimension.h \
|
||||||
|
src/update_data.h src/trap.h src/mixer.h
|
||||||
|
|
||||||
|
src/map_lua.o: src/map_lua.c src/map_lua.h src/map.h \
|
||||||
|
src/linkedlist.h src/sprite.h \
|
||||||
|
src/camera.h src/position.h src/timer.h \
|
||||||
|
src/defines.h src/monster.h src/player.h \
|
||||||
|
src/map_room_modifiers.h src/object.h src/doorlocktype.h \
|
||||||
|
src/config.h src/util.h src/stats.h \
|
||||||
|
src/io_util.h src/texturecache.h src/texture.h \
|
||||||
|
src/dimension.h src/trap.h src/roommatrix.h \
|
||||||
|
src/actiontext.h src/skill.h src/input.h \
|
||||||
|
src/artifact.h src/update_data.h src/gui.h \
|
||||||
|
src/vector2d.h src/item.h src/item_builder.h
|
||||||
|
|
||||||
|
src/map_room_modifiers.o: src/map_room_modifiers.c src/map_room_modifiers.h src/vector2d.h \
|
||||||
|
src/player.h src/sprite.h src/texture.h \
|
||||||
|
src/position.h src/camera.h src/roommatrix.h \
|
||||||
|
src/timer.h src/stats.h src/actiontext.h \
|
||||||
|
src/skill.h src/linkedlist.h src/input.h \
|
||||||
|
src/artifact.h src/defines.h
|
||||||
|
|
||||||
|
src/menu.o: src/menu.c src/menu.h src/camera.h \
|
||||||
|
src/position.h src/timer.h src/vector2d.h \
|
||||||
|
src/linkedlist.h src/texture.h \
|
||||||
|
src/dimension.h src/sprite.h src/roommatrix.h \
|
||||||
|
src/util.h src/defines.h src/map_room_modifiers.h \
|
||||||
|
src/input.h src/config.h src/gui_button.h \
|
||||||
|
src/pointer.h src/keyboard.h src/mixer.h \
|
||||||
|
src/gamestate.h src/collisions.h
|
||||||
|
|
||||||
|
src/mixer.o: src/mixer.c src/mixer.h src/gamestate.h \
|
||||||
|
src/util.h src/io_util.h src/settings.h
|
||||||
|
|
||||||
|
src/monster.o: src/monster.c src/monster.h src/sprite.h \
|
||||||
|
src/texture.h src/position.h src/camera.h \
|
||||||
|
src/roommatrix.h src/timer.h src/stats.h \
|
||||||
|
src/actiontext.h src/vector2d.h src/player.h \
|
||||||
|
src/skill.h src/linkedlist.h src/input.h \
|
||||||
|
src/artifact.h src/doorlocktype.h src/particle_emitter.h \
|
||||||
|
src/dimension.h src/util.h src/random.h \
|
||||||
|
src/gui.h src/item.h src/item_builder.h \
|
||||||
|
src/map.h src/defines.h src/config.h \
|
||||||
|
src/map_room_modifiers.h src/object.h src/particle_engine.h \
|
||||||
|
src/update_data.h src/actiontextbuilder.h src/texturecache.h \
|
||||||
|
src/trap.h src/mixer.h
|
||||||
|
|
||||||
|
src/object.o: src/object.c src/object.h src/camera.h \
|
||||||
|
src/position.h src/timer.h src/vector2d.h \
|
||||||
|
src/player.h src/sprite.h src/stats.h \
|
||||||
|
src/actiontext.h src/skill.h src/linkedlist.h \
|
||||||
|
src/input.h src/artifact.h src/texture.h \
|
||||||
|
src/roommatrix.h src/util.h src/mixer.h \
|
||||||
|
src/gamestate.h src/random.h src/texturecache.h
|
||||||
|
|
||||||
|
src/particle_emitter.o: src/particle_emitter.c src/particle_emitter.h src/timer.h \
|
||||||
|
src/position.h src/dimension.h
|
||||||
|
|
||||||
|
src/particle_engine.o: src/particle_engine.c src/particle_engine.h src/position.h \
|
||||||
|
src/dimension.h src/camera.h src/timer.h \
|
||||||
|
src/vector2d.h src/linkedlist.h src/util.h \
|
||||||
|
src/defines.h src/config.h
|
||||||
|
|
||||||
|
src/physfsrwops.o: src/physfsrwops.c src/physfsrwops.h
|
||||||
|
|
||||||
|
src/player.o: src/player.c src/player.h src/sprite.h \
|
||||||
|
src/texture.h src/position.h src/camera.h \
|
||||||
|
src/roommatrix.h src/timer.h src/stats.h \
|
||||||
|
src/actiontext.h src/vector2d.h src/skill.h \
|
||||||
|
src/linkedlist.h src/input.h src/artifact.h \
|
||||||
|
src/monster.h src/doorlocktype.h src/particle_emitter.h \
|
||||||
|
src/dimension.h src/util.h src/gui.h \
|
||||||
|
src/item.h src/particle_engine.h src/keyboard.h \
|
||||||
|
src/defines.h src/config.h src/mixer.h \
|
||||||
|
src/gamestate.h src/random.h src/projectile.h \
|
||||||
|
src/map_room_modifiers.h src/update_data.h src/map.h \
|
||||||
|
src/texturecache.h src/actiontextbuilder.h \
|
||||||
|
src/animation.h src/trap.h src/gamecontroller.h \
|
||||||
|
src/event.h src/effect_util.h src/steam/steamworks_api_wrapper.h \
|
||||||
|
src/defines.h
|
||||||
|
|
||||||
|
src/pointer.o: src/pointer.c src/pointer.h src/sprite.h \
|
||||||
|
src/texture.h src/position.h src/camera.h \
|
||||||
|
src/roommatrix.h src/timer.h src/vector2d.h \
|
||||||
|
src/input.h src/util.h src/particle_engine.h
|
||||||
|
|
||||||
|
src/position.o: src/position.c src/position.h src/defines.h
|
||||||
|
|
||||||
|
src/projectile.o: src/projectile.c src/projectile.h src/sprite.h \
|
||||||
|
src/texture.h src/position.h src/camera.h \
|
||||||
|
src/roommatrix.h src/timer.h \
|
||||||
|
src/vector2d.h src/defines.h src/map_room_modifiers.h \
|
||||||
|
src/input.h src/update_data.h src/player.h \
|
||||||
|
src/map.h src/gui.h src/config.h \
|
||||||
|
src/util.h src/texturecache.h src/dimension.h \
|
||||||
|
src/stats.h src/actiontext.h src/skill.h \
|
||||||
|
src/linkedlist.h src/artifact.h src/monster.h \
|
||||||
|
src/doorlocktype.h src/particle_emitter.h src/mixer.h \
|
||||||
|
src/gamestate.h src/item_builder.h src/item.h \
|
||||||
|
src/random.h src/object.h src/effect_util.h
|
||||||
|
|
||||||
|
src/random.o: src/random.c src/time.h src/random.h
|
||||||
|
|
||||||
|
src/roommatrix.o: src/roommatrix.c src/defines.h src/config.h \
|
||||||
|
src/roommatrix.h src/position.h src/camera.h \
|
||||||
|
src/timer.h src/vector2d.h \
|
||||||
|
src/map_room_modifiers.h src/input.h src/util.h \
|
||||||
|
src/map.h src/linkedlist.h src/sprite.h src/texture.h \
|
||||||
|
src/monster.h src/stats.h src/actiontext.h \
|
||||||
|
src/player.h src/doorlocktype.h src/particle_emitter.h \
|
||||||
|
src/skill.h src/artifact.h src/object.h \
|
||||||
|
src/item.h src/update_data.h src/gui.h
|
||||||
|
|
||||||
|
src/save.o: src/save.c src/save.h src/player.h \
|
||||||
|
src/sprite.h src/stats.h \
|
||||||
|
src/actiontext.h src/camera.h src/skill.h \
|
||||||
|
src/linkedlist.h src/input.h src/artifact.h \
|
||||||
|
src/db.h src/defines.h src/config.h
|
||||||
|
|
||||||
|
src/screen.o: src/screen.c src/screen.h src/texture.h \
|
||||||
|
src/dimension.h \
|
||||||
|
src/position.h src/camera.h src/linkedlist.h \
|
||||||
|
src/sprite.h src/roommatrix.h src/timer.h \
|
||||||
|
src/vector2d.h src/util.h src/hiscore.h \
|
||||||
|
src/player.h src/stats.h src/actiontext.h \
|
||||||
|
src/skill.h src/input.h
|
||||||
|
|
||||||
|
src/screenresolution.o: src/screenresolution.c src/defines.h src/config.h \
|
||||||
|
src/util.h src/screenresolution.h
|
||||||
|
|
||||||
|
src/settings.o: src/settings.c src/settings.h src/util.h \
|
||||||
|
src/defines.h src/config.h
|
||||||
|
|
||||||
|
src/skill.o: src/skill.c src/texturecache.h src/texture.h \
|
||||||
|
src/dimension.h src/position.h \
|
||||||
|
src/camera.h src/skill.h src/roommatrix.h \
|
||||||
|
src/defines.h src/map_room_modifiers.h src/input.h \
|
||||||
|
src/sprite.h src/timer.h src/vector2d.h \
|
||||||
|
src/util.h src/player.h src/stats.h \
|
||||||
|
src/actiontext.h src/linkedlist.h src/artifact.h \
|
||||||
|
src/config.h src/monster.h src/doorlocktype.h \
|
||||||
|
src/particle_emitter.h src/mixer.h src/gamestate.h \
|
||||||
|
src/gui.h src/random.h src/particle_engine.h \
|
||||||
|
src/projectile.h src/update_data.h src/map.h \
|
||||||
|
src/item.h src/animation.h src/trap.h \
|
||||||
|
src/tooltip.h src/actiontextbuilder.h
|
||||||
|
|
||||||
|
src/skillbar.o: src/skillbar.c src/defines.h src/config.h \
|
||||||
|
src/skillbar.h src/linkedlist.h src/camera.h \
|
||||||
|
src/position.h src/timer.h src/vector2d.h \
|
||||||
|
src/player.h src/sprite.h src/stats.h \
|
||||||
|
src/actiontext.h src/skill.h src/input.h \
|
||||||
|
src/artifact.h src/texture.h \
|
||||||
|
src/dimension.h src/util.h src/roommatrix.h \
|
||||||
|
src/map_room_modifiers.h src/keyboard.h src/texturecache.h \
|
||||||
|
src/particle_engine.h src/update_data.h src/map.h \
|
||||||
|
src/monster.h src/object.h src/doorlocktype.h
|
||||||
|
|
||||||
|
src/sprite.o: src/sprite.c src/sprite.h src/texture.h \
|
||||||
|
src/dimension.h \
|
||||||
|
src/position.h src/camera.h src/timer.h \
|
||||||
|
src/vector2d.h src/roommatrix.h src/defines.h \
|
||||||
|
src/map_room_modifiers.h src/input.h src/util.h \
|
||||||
|
src/update_data.h src/player.h src/stats.h \
|
||||||
|
src/actiontext.h src/skill.h src/linkedlist.h \
|
||||||
|
src/artifact.h src/map.h src/monster.h \
|
||||||
|
src/object.h src/doorlocktype.h
|
||||||
|
|
||||||
|
src/sprite_util.o: src/sprite_util.c src/sprite_util.h src/sprite.h \
|
||||||
|
src/texture.h src/position.h src/camera.h \
|
||||||
|
src/roommatrix.h src/timer.h
|
||||||
|
|
||||||
|
src/stats.o: src/stats.c src/gui.h \
|
||||||
|
src/linkedlist.h src/sprite.h src/texture.h \
|
||||||
|
src/position.h src/camera.h src/roommatrix.h \
|
||||||
|
src/timer.h src/vector2d.h src/player.h \
|
||||||
|
src/stats.h src/actiontext.h src/skill.h \
|
||||||
|
src/input.h src/artifact.h src/random.h \
|
||||||
|
src/util.h src/defines.h
|
||||||
|
|
||||||
|
src/texture.o: src/texture.c src/texture.h \
|
||||||
|
src/dimension.h src/position.h \
|
||||||
|
src/camera.h src/timer.h src/vector2d.h \
|
||||||
|
src/util.h
|
||||||
|
|
||||||
|
src/texturecache.o: src/texturecache.c src/texturecache.h \
|
||||||
|
src/texture.h src/dimension.h \
|
||||||
|
src/position.h src/camera.h src/hashtable.h \
|
||||||
|
src/defines.h src/config.h src/util.h
|
||||||
|
|
||||||
|
src/time.o: src/time.c src/time.h
|
||||||
|
|
||||||
|
src/timer.o: src/timer.c src/util.h
|
||||||
|
|
||||||
|
src/tooltip.o: src/tooltip.c src/tooltip.h src/camera.h \
|
||||||
|
src/position.h src/timer.h \
|
||||||
|
src/vector2d.h src/sprite.h src/texture.h \
|
||||||
|
src/roommatrix.h src/gui_util.h src/defines.h \
|
||||||
|
src/config.h src/gui.h src/linkedlist.h \
|
||||||
|
src/player.h src/stats.h src/actiontext.h \
|
||||||
|
src/skill.h src/input.h src/artifact.h \
|
||||||
|
src/texturecache.h
|
||||||
|
|
||||||
|
src/trap.o: src/trap.c src/trap.h \
|
||||||
|
src/sprite.h src/texture.h src/position.h \
|
||||||
|
src/camera.h src/roommatrix.h src/timer.h \
|
||||||
|
src/player.h src/stats.h src/actiontext.h \
|
||||||
|
src/skill.h src/linkedlist.h src/input.h \
|
||||||
|
src/artifact.h src/update_data.h src/map.h \
|
||||||
|
src/gui.h src/vector2d.h src/util.h \
|
||||||
|
src/random.h
|
||||||
|
|
||||||
|
src/util.o: src/util.c src/time.h src/defines.h \
|
||||||
|
src/config.h
|
||||||
|
|
||||||
|
src/vector2d.o: src/vector2d.c
|
||||||
|
|
||||||
|
bh_random/src/bh_random.o:
|
||||||
|
@g++ -c bh_random/src/bh_random.cpp -o bh_random/src/bh_random.o $(CFLAGS)
|
||||||
|
|
||||||
|
|
||||||
|
# prepare an archive for the program
|
||||||
|
release:
|
||||||
|
@echo "Creating release files..."
|
||||||
|
@mkdir -p release/breakhack
|
||||||
|
@cp -r release_files/* release/breakhack/
|
||||||
|
@cp -r data release/breakhack/
|
||||||
|
@cp -r assets release/breakhack/
|
||||||
|
@cp breakhack release/breakhack/
|
||||||
|
@strip release/breakhack/breakhack
|
||||||
|
@cp README.md release/breakhack/
|
||||||
|
@cp README_Amiga.md release/breakhack/
|
||||||
|
@cp LICENSE.txt release/breakhack/
|
||||||
|
@cp CREDITS.md release/breakhack/
|
||||||
|
@echo "Creating release archive..."
|
||||||
|
@lha -aeqr3 a breakhack-OS4.lha release/
|
||||||
|
@echo "Clean release files..."
|
||||||
|
@delete release ALL QUIET FORCE
|
||||||
|
|
13
README.md
13
README.md
|
@ -1,3 +1,4 @@
|
||||||
|
[![maintenance](https://img.shields.io/badge/maintenance-passively--maintained-orange)](https://img.shields.io/badge/maintenance-passively--maintained-orange)
|
||||||
[![Build Status](https://travis-ci.org/Oliveshark/breakhack.svg?branch=master)](https://travis-ci.org/Oliveshark/breakhack)
|
[![Build Status](https://travis-ci.org/Oliveshark/breakhack.svg?branch=master)](https://travis-ci.org/Oliveshark/breakhack)
|
||||||
[![Build status](https://ci.appveyor.com/api/projects/status/2a18npdntkmlx3dc?svg=true)](https://ci.appveyor.com/project/LiquidityC/breakhack)
|
[![Build status](https://ci.appveyor.com/api/projects/status/2a18npdntkmlx3dc?svg=true)](https://ci.appveyor.com/project/LiquidityC/breakhack)
|
||||||
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/fc02d56fa7194e61b2c7d260fd2e4186)](https://www.codacy.com/app/LiquidityC/breakhack?utm_source=github.com&utm_medium=referral&utm_content=Oliveshark/breakhack&utm_campaign=Badge_Grade)
|
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/fc02d56fa7194e61b2c7d260fd2e4186)](https://www.codacy.com/app/LiquidityC/breakhack?utm_source=github.com&utm_medium=referral&utm_content=Oliveshark/breakhack&utm_campaign=Badge_Grade)
|
||||||
|
@ -46,16 +47,8 @@ BreakHack is released under two different licenses.
|
||||||
|
|
||||||
Compile
|
Compile
|
||||||
-------
|
-------
|
||||||
Apart from basic compile tools (*GCC/Clang, Make*) you'll also need to install **sdl2, sdl2-image, sdl2-ttf, sdl2-mixer** (If on a debian based dist you need to install the *dev* packages).
|
* [Linux](LINUX_BUILD_INSTRUCTIONS.md)
|
||||||
Optionally you can also install **cppcheck** and **physfs**
|
* [Windows (Visual Studio)](MSVC_BUILD_INSTRUCTIONS.md)
|
||||||
|
|
||||||
Once that is done run the following:
|
|
||||||
```bash
|
|
||||||
mkdir _build
|
|
||||||
cd _build
|
|
||||||
cmake -DCMAKE_BUILD_TYPE=Debug .. # Build type flag is optional
|
|
||||||
make
|
|
||||||
```
|
|
||||||
|
|
||||||
Contribute
|
Contribute
|
||||||
----------
|
----------
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
# breakhack for AmigaOS 4.1 FE
|
||||||
|
|
||||||
|
breakhack is a small roguelike game for having some good time, while
|
||||||
|
you wait for your amiga to compile or render a screen. It is developed
|
||||||
|
by Linus Probert and you can find it for various platforms on Steam.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Extract the archive wherever you want and run the *breakhack* binary.
|
||||||
|
|
||||||
|
## I would like to thank
|
||||||
|
|
||||||
|
- Linus Probert for creating this awesome game and open sourcing it
|
||||||
|
- Capehill for his tireless work on SDL port for AmigaOS 4.1 FE
|
||||||
|
- Roman "kas1e" Kargin and Nouvel "HunoPPC" Hugues for their help
|
||||||
|
with libphysfs
|
||||||
|
|
||||||
|
## Known issues
|
||||||
|
There are some issues with the Fullscreen graphics, depending which
|
||||||
|
Renderer driver is used. I might fix them in the future.
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
If you enjoy what I am doing and would like to keep me up during the night,
|
||||||
|
please consider to buy me a coffee at:
|
||||||
|
https://ko-fi.com/walkero
|
||||||
|
|
||||||
|
## Known issues
|
||||||
|
|
||||||
|
You can find the known issues at
|
||||||
|
https://git.walkero.gr/walkero/breakhack/issues
|
||||||
|
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
## [4.0.3r2] - 2023-07-04
|
||||||
|
### Changed
|
||||||
|
- Compiled with latest SDL 2.0.28 that has a better support for 16bit
|
||||||
|
screens. Now it works under Qemu. Tested with Software rendering
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fixed the hiscore date. Now it is saved on UTC +8 years which is
|
||||||
|
the Amiga epoch diff against the unix one. This doesn affect the
|
||||||
|
old hi-scores though
|
||||||
|
|
||||||
|
## [4.0.3r1] - 2022-12-21
|
||||||
|
### Added
|
||||||
|
- First release for AmigaOS 4
|
||||||
|
|
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 548 B |
Binary file not shown.
After Width: | Height: | Size: 321 B |
Binary file not shown.
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 4.3 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -8,20 +8,22 @@ if (NOT CMAKE_BUILD_TYPE)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
add_library(bh_random STATIC
|
add_library(bh_random STATIC
|
||||||
src/bh_random
|
src/bh_random.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
IF ( MSVC )
|
IF ( MSVC )
|
||||||
MESSAGE ( STATUS "Setting MSVC MT switches")
|
MESSAGE ( STATUS "Setting MSVC MT switches")
|
||||||
SET (
|
string (REPLACE
|
||||||
CMAKE_CXX_FLAGS_DEBUG
|
"/MDd"
|
||||||
"${CMAKE_CXX_FLAGS_DEBUG} /MTd"
|
"/MTd"
|
||||||
CACHE STRING "MSVC MT flags " FORCE
|
CMAKE_C_FLAGS_DEBUG
|
||||||
|
${CMAKE_C_FLAGS_DEBUG}
|
||||||
)
|
)
|
||||||
SET (
|
string (REPLACE
|
||||||
CMAKE_CXX_FLAGS_RELEASE
|
"/MDd"
|
||||||
"${CMAKE_CXX_FLAGS_RELEASE} /MT"
|
"/MTd"
|
||||||
CACHE STRING "MSVC MT flags " FORCE
|
CMAKE_C_FLAGS_RELEASE
|
||||||
|
${CMAKE_C_FLAGS_RELEASE}
|
||||||
)
|
)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,14 @@
|
||||||
# (To distribute this file outside of CMake, substitute the full
|
# (To distribute this file outside of CMake, substitute the full
|
||||||
# License text for the above reference.)
|
# License text for the above reference.)
|
||||||
|
|
||||||
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
|
set(SDL2_ARCH_64 TRUE)
|
||||||
|
set(SDL2_PROCESSOR_ARCH "x64")
|
||||||
|
else()
|
||||||
|
set(SDL2_ARCH_64 FALSE)
|
||||||
|
set(SDL2_PROCESSOR_ARCH "x86")
|
||||||
|
endif(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
|
|
||||||
SET(SDL2_SEARCH_PATHS
|
SET(SDL2_SEARCH_PATHS
|
||||||
~/Library/Frameworks
|
~/Library/Frameworks
|
||||||
/Library/Frameworks
|
/Library/Frameworks
|
||||||
|
@ -87,7 +95,7 @@ FIND_LIBRARY(SDL2_LIBRARY_TEMP
|
||||||
NAMES SDL2
|
NAMES SDL2
|
||||||
HINTS
|
HINTS
|
||||||
$ENV{SDL2DIR}
|
$ENV{SDL2DIR}
|
||||||
PATH_SUFFIXES lib64 lib
|
PATH_SUFFIXES lib64 lib lib/${SDL2_PROCESSOR_ARCH}
|
||||||
PATHS ${SDL2_SEARCH_PATHS} ${SDL2_INCLUDE_DIR}/../..
|
PATHS ${SDL2_SEARCH_PATHS} ${SDL2_INCLUDE_DIR}/../..
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -101,7 +109,7 @@ IF(NOT SDL2_BUILDING_LIBRARY)
|
||||||
NAMES SDL2main
|
NAMES SDL2main
|
||||||
HINTS
|
HINTS
|
||||||
$ENV{SDL2DIR}
|
$ENV{SDL2DIR}
|
||||||
PATH_SUFFIXES lib64 lib
|
PATH_SUFFIXES lib64 lib lib/${SDL2_PROCESSOR_ARCH}
|
||||||
PATHS ${SDL2_SEARCH_PATHS}
|
PATHS ${SDL2_SEARCH_PATHS}
|
||||||
)
|
)
|
||||||
ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
|
ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
|
||||||
|
|
|
@ -28,6 +28,14 @@
|
||||||
# See the License for more information.
|
# See the License for more information.
|
||||||
#=============================================================================
|
#=============================================================================
|
||||||
|
|
||||||
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
|
set(SDL2_ARCH_64 TRUE)
|
||||||
|
set(SDL2_PROCESSOR_ARCH "x64")
|
||||||
|
else()
|
||||||
|
set(SDL2_ARCH_64 FALSE)
|
||||||
|
set(SDL2_PROCESSOR_ARCH "x86")
|
||||||
|
endif(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
|
|
||||||
if(NOT SDL2_TTF_INCLUDE_DIR AND SDL2TTF_INCLUDE_DIR)
|
if(NOT SDL2_TTF_INCLUDE_DIR AND SDL2TTF_INCLUDE_DIR)
|
||||||
set(SDL2_TTF_INCLUDE_DIR ${SDL2TTF_INCLUDE_DIR} CACHE PATH "directory cache
|
set(SDL2_TTF_INCLUDE_DIR ${SDL2TTF_INCLUDE_DIR} CACHE PATH "directory cache
|
||||||
entry initialized from old variable name")
|
entry initialized from old variable name")
|
||||||
|
@ -48,7 +56,7 @@ find_library(SDL2_TTF_LIBRARY
|
||||||
HINTS
|
HINTS
|
||||||
ENV SDLTTFDIR
|
ENV SDLTTFDIR
|
||||||
ENV SDLDIR
|
ENV SDLDIR
|
||||||
PATH_SUFFIXES lib
|
PATH_SUFFIXES lib lib/${SDL2_PROCESSOR_ARCH}
|
||||||
)
|
)
|
||||||
|
|
||||||
if(SDL2_TTF_INCLUDE_DIR AND EXISTS "${SDL2_TTF_INCLUDE_DIR}/SDL_ttf.h")
|
if(SDL2_TTF_INCLUDE_DIR AND EXISTS "${SDL2_TTF_INCLUDE_DIR}/SDL_ttf.h")
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
c4811ed Fixes checksumtool output again
|
||||||
|
eceb241 Removes useless text from checksumtool output
|
||||||
|
cea891f Move checksum configuration to CMakeLists.txt and config.h
|
||||||
|
8e28230 Fixes release notes
|
||||||
|
53703f1 Patch version raised to 1
|
||||||
|
ce182ad Updates checksums
|
||||||
|
ebfe271 Fixes compile error and some graphical issues
|
||||||
|
2ae6ada Completes locked room generation
|
||||||
|
18987e2 Incomplete monster key fixes
|
||||||
|
59a1e81 Implementation of keys. Completely untested
|
||||||
|
1065216 Include all files in pack files
|
||||||
|
68533f0 Remove memory leaks from map destruction
|
||||||
|
38dc3de Merge branch 'dev' of github.com:liquidityc/breakhack into dev
|
||||||
|
beda4f6 Reduces fairy frequency
|
||||||
|
e50d40f Adds doors and greater chance of walls
|
||||||
|
0983bd1 Fixes a weird issue with missing code
|
||||||
|
184b42f Fixes door logic
|
||||||
|
e42e024 Adds some door logic
|
||||||
|
756afba Separates walls from regular tiles
|
||||||
|
40a20e9 Adapts fopen/fopen_s to WIN32/GCC compile
|
||||||
|
af930f6 Fixes win compiler warnings
|
||||||
|
c4fd16d Updated dll checksums for windows build
|
||||||
|
f840b28 Adds mediocre crack protection
|
||||||
|
7fbeaa3 Introduced base structure for doors in maps
|
||||||
|
3e43c30 Adds funny casting to avoid pedantic ISO C warning
|
||||||
|
fd3a625 Adds monster bloodlust
|
||||||
|
d749861 Make jumbled rooms more likely
|
||||||
|
7ab5ece Nicer wall decorations on interior walls
|
||||||
|
8c9622d Shopkeeper now has bodyguards next time you meet after kiling him
|
||||||
|
af0c616 Adds juice
|
||||||
|
46fbdc1 Fixed jumble layout logic
|
||||||
|
b40c54a Layouts can now be jumbled with each other
|
||||||
|
8f20f36 Lighting on wall layouts and aggro shopkeepers
|
||||||
|
3ba33d8 Adds light tiles to layout files and a shopkeeper
|
||||||
|
447c1a7 Monster shopkeeper logic
|
||||||
|
7e1dffb Shops implemented
|
||||||
|
6009aa1 Merge branch 'dev' into shops
|
||||||
|
9b4a7b6 Removes crazy old bug that never presented itself before
|
||||||
|
63812fb More wall layouts and cordinated walls
|
||||||
|
c6a022e Moved text sprite logic to sprite_util
|
||||||
|
06ca6c3 Not finnished yet, commit
|
||||||
|
bab5fd7 Merge branch 'dev' into shops
|
||||||
|
68f4409 Add amt sprite to all items where value != 0
|
||||||
|
959fae1 Add value sprite to items.
|
||||||
|
ca41520 Wall layouts added to regular build
|
||||||
|
88f4703 Some more fence layouts
|
||||||
|
486c1bb Merge branch 'dev' into shops
|
||||||
|
206f95f Fences and walls in layout files
|
||||||
|
1c4e600 Wall layout data
|
||||||
|
57a1688 Merge branch 'dev' into shops
|
||||||
|
13ca11c Begins refactoring of layout parser to accomodate more layout details
|
||||||
|
33efba8 Merge branch 'dev' into shops
|
||||||
|
5d61a91 Split pit layout logic into separate file
|
||||||
|
6542e4f Moves item update to its own function
|
||||||
|
7b47c6a Completes buyable items
|
||||||
|
16d9035 Merge branch 'dev' into shops
|
||||||
|
4054c37 Ignore vscode_build dir
|
||||||
|
ad227f1 A start to "priced" items
|
||||||
|
37ba189 Suppress cppcheck issues
|
||||||
|
645a02c Ignore .vscode folder
|
|
@ -0,0 +1,6 @@
|
||||||
|
c2b8fd4 Adds key pickup SFX
|
||||||
|
7a59d15 Don't add walls to crumbling rooms before lvl 4
|
||||||
|
c9fde8d Updated releasenotes
|
||||||
|
c4811ed Fixes checksumtool output again
|
||||||
|
eceb241 Removes useless text from checksumtool output
|
||||||
|
cea891f Move checksum configuration to CMakeLists.txt and config.h
|
|
@ -0,0 +1,40 @@
|
||||||
|
392edd8 Updates blink tooltip to include item pickups.
|
||||||
|
6584981 remove unnecessary pickup
|
||||||
|
d2cf797 Mage blink skill pickup items in the path #60
|
||||||
|
78e9413 Fix : Missing with vampiric blow doesn't seem to trigger a 'Dodge' action text #59
|
||||||
|
af957eb Disables mouse square rendering for all classes
|
||||||
|
1d988d7 Fixes working explosions and artifacts
|
||||||
|
68f4e15 Fixes returning daggers and resets erupt attack
|
||||||
|
7f232be A beginning to the new exploding artifacts
|
||||||
|
12aff9a Fixes erupt so it has a base push of 1
|
||||||
|
2dc25c9 Adds the DAGGER_MAGNET artifact
|
||||||
|
5e67ca7 Removes stun from backstab skill
|
||||||
|
cac3fea Altered the vampiric blow icon slightly
|
||||||
|
9ed80ac Removes erupt test code
|
||||||
|
05cbce0 Adds vampiric blow icon
|
||||||
|
6c135c6 Adds gui display for held keys
|
||||||
|
fb031e2 Bumps version
|
||||||
|
b861e6e Fixes SENTINEL monsters from ignoring forced fear
|
||||||
|
046551a Changes ERUPT to cause fear instead of bleeding
|
||||||
|
8fb1bbc Fixes bug with erupt pushing direction
|
||||||
|
35164a9 Introduces vampiric blow
|
||||||
|
dd3e84d Makes critical hits cause bleeding
|
||||||
|
8f21e8b Prevents skill radius from impacting push back range
|
||||||
|
2b74316 Updates erupt tooltip to mention push back
|
||||||
|
7ddaab8 Make erupt always push back 1 tile without any artifacts
|
||||||
|
43ca8f4 Fixes #58 - Game crash with AOE attacks
|
||||||
|
ef5cd4e Adds PUSH_BACK and SKILL_RADIUS effects to erupt skill
|
||||||
|
b00e607 Start with debug gold
|
||||||
|
67e29d6 Added the SKILL_RADIUS artifact (not used yet)
|
||||||
|
81e7df1 Adds skill icons for the two mage skills
|
||||||
|
18effa2 Rogue backstab skill now triggers bleeding as well
|
||||||
|
c043ad0 Implements the erupt skill
|
||||||
|
223a3b0 Implements the blink skill
|
||||||
|
2ca78e2 Adds monster bleed damage every turn
|
||||||
|
0476d4d Introduces particle emitters on monsters
|
||||||
|
826cbe1 A quick start to the Mage
|
||||||
|
fcc6527 Minor fix
|
||||||
|
b409b76 Improved build instruction structure
|
||||||
|
b075390 React to PR feedback
|
||||||
|
86e6f66 Adds Windows compilation instructions
|
||||||
|
c0a4a4e Make ninja builds smoother
|
|
@ -0,0 +1,2 @@
|
||||||
|
6d323ca Adds steam achievements and LB for the Mage class
|
||||||
|
9aefed0 Adds an dev env setup script
|
|
@ -0,0 +1 @@
|
||||||
|
4edeb17 Fixes cross save problems due to architecture differences
|
|
@ -0,0 +1 @@
|
||||||
|
e636ec1 Don't delete saves from other architectures on death
|
|
@ -0,0 +1,12 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
mkdir -p _build/debug
|
||||||
|
mkdir -p _build/release
|
||||||
|
|
||||||
|
cd _build/debug
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Debug ../..
|
||||||
|
cd -
|
||||||
|
|
||||||
|
cd _build/release
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Release ../..
|
||||||
|
cd -
|
|
@ -0,0 +1,33 @@
|
||||||
|
cmake_minimum_required(VERSION 3.1)
|
||||||
|
project(checksum C)
|
||||||
|
|
||||||
|
if (NOT CMAKE_BUILD_TYPE)
|
||||||
|
set(CMAKE_BUILD_TYPE Release)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
|
||||||
|
add_executable(checksumtool
|
||||||
|
src/checksum.c
|
||||||
|
)
|
||||||
|
target_compile_definitions(checksumtool PUBLIC EXECUTABLE=1)
|
||||||
|
|
||||||
|
add_library(checksum
|
||||||
|
src/checksum.c
|
||||||
|
)
|
||||||
|
|
||||||
|
IF ( MSVC )
|
||||||
|
MESSAGE ( STATUS "Setting MSVC MT switches")
|
||||||
|
string (REPLACE
|
||||||
|
"/MDd"
|
||||||
|
"/MTd"
|
||||||
|
CMAKE_C_FLAGS_DEBUG
|
||||||
|
${CMAKE_C_FLAGS_DEBUG}
|
||||||
|
)
|
||||||
|
string (REPLACE
|
||||||
|
"/MDd"
|
||||||
|
"/MTd"
|
||||||
|
CMAKE_C_FLAGS_RELEASE
|
||||||
|
${CMAKE_C_FLAGS_RELEASE}
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
** CHECKSUM.C - Compute the checksum of a file
|
||||||
|
**
|
||||||
|
** public somain demo by Bob Stout
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "checksum.h"
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
checksum(void *buffer, size_t len, unsigned int seed)
|
||||||
|
{
|
||||||
|
unsigned char *buf = (unsigned char *)buffer;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < len; ++i)
|
||||||
|
seed += (unsigned int)(*buf++);
|
||||||
|
return seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
checksum_fp(FILE *fp)
|
||||||
|
{
|
||||||
|
unsigned int seed = 0;
|
||||||
|
char buf[4096];
|
||||||
|
|
||||||
|
size_t len;
|
||||||
|
do {
|
||||||
|
len = fread(buf, sizeof(char), sizeof(buf), fp);
|
||||||
|
seed = checksum(buf, len, seed);
|
||||||
|
} while (len > 0);
|
||||||
|
|
||||||
|
return seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef EXECUTABLE
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
const char *file;
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
printf("You need to provide an input file\n");
|
||||||
|
printf("Example: %s <file>", argv[0]);
|
||||||
|
}
|
||||||
|
file = argv[1];
|
||||||
|
|
||||||
|
if (NULL == (fp = fopen(file, "rb")))
|
||||||
|
{
|
||||||
|
printf("Unable to open %s for reading\n", file);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%#x\n", checksum_fp(fp));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* BreakHack - A dungeone crawler RPG
|
||||||
|
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
checksum(void *buffer, size_t len, unsigned int seed);
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
checksum_fp(FILE *fp);
|
|
@ -0,0 +1,406 @@
|
||||||
|
local random = map_random
|
||||||
|
local pits = {}
|
||||||
|
local walls = {}
|
||||||
|
local fences = {}
|
||||||
|
local lights = {}
|
||||||
|
local doors = {}
|
||||||
|
local walldecor = {}
|
||||||
|
local chest
|
||||||
|
|
||||||
|
local function readLayoutFile(file)
|
||||||
|
local layoutfile = read_file(file)
|
||||||
|
|
||||||
|
local cleanData = ""
|
||||||
|
for i=1, #layoutfile do
|
||||||
|
local c = layoutfile:sub(i+1, i+1)
|
||||||
|
if c ~= " " and c ~= "\n" and c ~= "\r" then
|
||||||
|
cleanData = cleanData .. c
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local matrix = {}
|
||||||
|
for i=0, #cleanData-1 do
|
||||||
|
local c = cleanData:sub(i, i)
|
||||||
|
local col = i % 16
|
||||||
|
local row = (i - col)/16
|
||||||
|
local layout = 1 + (row - (row % 12))/12
|
||||||
|
local row = row % 12
|
||||||
|
if not matrix[layout] then matrix[layout] = {} end
|
||||||
|
if not matrix[layout][col] then matrix[layout][col] = {} end
|
||||||
|
matrix[layout][col][row] = c
|
||||||
|
end
|
||||||
|
|
||||||
|
return matrix;
|
||||||
|
end
|
||||||
|
|
||||||
|
local function has_value(list, char)
|
||||||
|
for _, value in ipairs(list) do
|
||||||
|
if value == char then return true end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getTileStateFor(matrix, i, j, c)
|
||||||
|
local charList
|
||||||
|
if type(c) == "string" then
|
||||||
|
charList = { c }
|
||||||
|
else
|
||||||
|
charList = c
|
||||||
|
end
|
||||||
|
local above = has_value(charList, matrix[i][j-1])
|
||||||
|
local below = has_value(charList, matrix[i][j+1])
|
||||||
|
local left = has_value(charList, matrix[i-1][j])
|
||||||
|
local right = has_value(charList, matrix[i+1][j])
|
||||||
|
|
||||||
|
local above_left = has_value(charList, matrix[i-1][j-1])
|
||||||
|
local above_right = has_value(charList, matrix[i+1][j-1])
|
||||||
|
local below_left = has_value(charList, matrix[i-1][j+1])
|
||||||
|
local below_right = has_value(charList, matrix[i+1][j+1])
|
||||||
|
|
||||||
|
return above, below, left, right, above_left, above_right, below_left, below_right
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getRandomWallDecorFrom(wallDecorations)
|
||||||
|
return wallDecorations[random(#wallDecorations)]
|
||||||
|
end
|
||||||
|
|
||||||
|
local function setBlockTile(room, matrix, i, j, tiles, char, decor)
|
||||||
|
local above, below, left, right, above_left, above_right, below_left, below_right = getTileStateFor(matrix, i, j, char);
|
||||||
|
|
||||||
|
room.decor[i][j] = nil
|
||||||
|
local tile = nil
|
||||||
|
local decorTile = nil
|
||||||
|
if above and below and left and right then
|
||||||
|
tile = tiles.cross
|
||||||
|
elseif not above and below and left and right then
|
||||||
|
tile = tiles.top_t
|
||||||
|
elseif not below and above and left and right then
|
||||||
|
tile = tiles.bottom_t
|
||||||
|
decorTile = getRandomWallDecorFrom(walldecor.bottom_t)
|
||||||
|
elseif not left and above and below and right then
|
||||||
|
tile = tiles.left_t
|
||||||
|
decorTile = getRandomWallDecorFrom(walldecor.left_t)
|
||||||
|
elseif not right and above and below and left then
|
||||||
|
tile = tiles.right_t
|
||||||
|
decorTile = getRandomWallDecorFrom(walldecor.right_t)
|
||||||
|
elseif not above and not left and right and below then
|
||||||
|
tile = tiles.topleft
|
||||||
|
decorTile = getRandomWallDecorFrom(walldecor.topleft)
|
||||||
|
elseif not above and not right and left and below then
|
||||||
|
tile = tiles.topright
|
||||||
|
decorTile = getRandomWallDecorFrom(walldecor.topright)
|
||||||
|
elseif not below and not left and above and right then
|
||||||
|
tile = tiles.bottomleft
|
||||||
|
decorTile = getRandomWallDecorFrom(walldecor.bottomleft)
|
||||||
|
elseif not below and not right and above and left then
|
||||||
|
tile = tiles.bottomright
|
||||||
|
decorTile = getRandomWallDecorFrom(walldecor.bottomright)
|
||||||
|
elseif not left and not right and below then
|
||||||
|
tile = tiles.left
|
||||||
|
decorTile = getRandomWallDecorFrom(walldecor.left)
|
||||||
|
elseif not above and not below and (left or right) then
|
||||||
|
tile = tiles.top
|
||||||
|
decorTile = getRandomWallDecorFrom(walldecor.top)
|
||||||
|
else
|
||||||
|
tile = tiles.single
|
||||||
|
decorTile = getRandomWallDecorFrom(walldecor.single)
|
||||||
|
end
|
||||||
|
|
||||||
|
room.walls[i][j] = tile
|
||||||
|
if random(8) == 1 and decor then
|
||||||
|
room.decor[i][j] = decorTile
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function setPitTile(room, matrix, i, j)
|
||||||
|
local above, below, left, right, above_left, above_right, below_left, below_right = getTileStateFor(matrix, i, j, "p");
|
||||||
|
|
||||||
|
room.decor[i][j] = nil
|
||||||
|
if not above_left and not above_right and left and right and above then
|
||||||
|
room.tiles[i][j] = pits.innermid
|
||||||
|
elseif not above_left and left and above then
|
||||||
|
room.tiles[i][j] = pits.innerleft
|
||||||
|
elseif not above_right and right and above then
|
||||||
|
room.tiles[i][j] = pits.innerright
|
||||||
|
elseif not left and not above and not right then
|
||||||
|
room.tiles[i][j] = pits.topcrevice
|
||||||
|
elseif not left and not right then
|
||||||
|
room.tiles[i][j] = pits.bottomcrevice
|
||||||
|
elseif not left and not above then
|
||||||
|
room.tiles[i][j] = pits.topleft
|
||||||
|
elseif not right and not above then
|
||||||
|
room.tiles[i][j] = pits.topright
|
||||||
|
elseif not left then
|
||||||
|
room.tiles[i][j] = pits.left
|
||||||
|
elseif not right then
|
||||||
|
room.tiles[i][j] = pits.right
|
||||||
|
elseif not above then
|
||||||
|
room.tiles[i][j] = pits.top
|
||||||
|
else
|
||||||
|
room.tiles[i][j] = pits.center
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function getDoor(matrix, i, j, topDoor, leftDoor)
|
||||||
|
local above, below, left, right, above_left, above_right, below_left, below_right = getTileStateFor(matrix, i, j, { "#", "\"", "/"});
|
||||||
|
if above and below then
|
||||||
|
return leftDoor
|
||||||
|
else
|
||||||
|
return topDoor
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local module = {}
|
||||||
|
function module.load_textures(map, wall_xoffset, wall_yoffset)
|
||||||
|
local t_pit0 = add_texture(map, "Objects/Pit0.png")
|
||||||
|
local t_pit1 = add_texture(map, "Objects/Pit1.png")
|
||||||
|
local t_wall = add_texture(map, "Objects/Wall.png")
|
||||||
|
local t_fence = add_texture(map, "Objects/Fence.png")
|
||||||
|
local t_decor0 = add_texture(map, "Objects/Decor0.png")
|
||||||
|
local t_decor1 = add_texture(map, "Objects/Decor1.png")
|
||||||
|
local t_door0 = add_texture(map, "Objects/Door0.png")
|
||||||
|
local t_door1 = add_texture(map, "Objects/Door1.png")
|
||||||
|
|
||||||
|
local yo = (random(5) + random(3)) * (16 * 2)
|
||||||
|
pits = {
|
||||||
|
center = { t_pit0, t_pit1, 16, yo + 16, false, false, false, true },
|
||||||
|
top = { t_pit0, t_pit1, 16, yo, false, false, false, true },
|
||||||
|
left = { t_pit0, t_pit1, 0, yo + 16, false, false, false, true },
|
||||||
|
right = { t_pit0, t_pit1, 32, yo + 16, false, false, false, true },
|
||||||
|
topleft = { t_pit0, t_pit1, 0, yo, false, false, false, true },
|
||||||
|
topright = { t_pit0, t_pit1, 32, yo, false, false, false, true },
|
||||||
|
innerleft = { t_pit0, t_pit1, 80, yo, false, false, false, true },
|
||||||
|
innermid = { t_pit0, t_pit1, 96, yo, false, false, false, true },
|
||||||
|
innerright = { t_pit0, t_pit1, 112, yo, false, false, false, true },
|
||||||
|
topcrevice = { t_pit0, t_pit1, 64, yo, false, false, false, true },
|
||||||
|
bottomcrevice = { t_pit0, t_pit1, 64, yo + 16, false, false, false, true },
|
||||||
|
}
|
||||||
|
|
||||||
|
local xo = wall_xoffset
|
||||||
|
yo = wall_yoffset
|
||||||
|
walls = {
|
||||||
|
topleft = { t_wall, nil, xo + 0, yo, true },
|
||||||
|
top = { t_wall, nil, xo + 16, yo, true },
|
||||||
|
single = { t_wall, nil, xo + 16, yo + 16, true },
|
||||||
|
topright = { t_wall, nil, xo + 32, yo, true },
|
||||||
|
left = { t_wall, nil, xo + 0, yo + 16, true },
|
||||||
|
bottomleft = { t_wall, nil, xo + 0, yo + 32, true },
|
||||||
|
bottomright = { t_wall, nil, xo + 32, yo + 32, true },
|
||||||
|
center = { t_wall, nil, xo + 48, yo, true },
|
||||||
|
top_t = { t_wall, nil, xo + 64, yo, true },
|
||||||
|
left_t = { t_wall, nil, xo + 48, yo + 16, true },
|
||||||
|
cross = { t_wall, nil, xo + 64, yo + 16, true },
|
||||||
|
right_t = { t_wall, nil, xo + 80, yo + 16, true },
|
||||||
|
bottom_t = { t_wall, nil, xo + 64, yo + 32, true },
|
||||||
|
}
|
||||||
|
|
||||||
|
yo = 48 * random(3)
|
||||||
|
fences = {
|
||||||
|
topleft = { t_fence, nil, 0, yo, true },
|
||||||
|
top = { t_fence, nil, 16, yo, true },
|
||||||
|
single = { t_fence, nil, 0, yo + 16, true },
|
||||||
|
topright = { t_fence, nil, 32, yo, true },
|
||||||
|
left = { t_fence, nil, 0, yo + 16, true },
|
||||||
|
bottomleft = { t_fence, nil, 0, yo + 32, true },
|
||||||
|
bottomright = { t_fence, nil, 32, yo + 32, true },
|
||||||
|
center = { t_fence, nil, 48, yo, true },
|
||||||
|
top_t = { t_fence, nil, 64, yo, true },
|
||||||
|
left_t = { t_fence, nil, 48, yo + 16, true },
|
||||||
|
cross = { t_fence, nil, 64, yo + 16, true },
|
||||||
|
right_t = { t_fence, nil, 80, yo + 16, true },
|
||||||
|
bottom_t = { t_fence, nil, 64, yo + 32, true },
|
||||||
|
}
|
||||||
|
|
||||||
|
doors = {
|
||||||
|
door_top_nolock = { t_door0, t_door1, 0, 0, true },
|
||||||
|
door_left_nolock = { t_door0, t_door1, 16, 0, true },
|
||||||
|
door_top_silverlock = { t_door0, t_door1, 32, 0, true, false, false, false, 1 },
|
||||||
|
door_left_silverlock = { t_door0, t_door1, 48, 0, true, false, false, false, 1 },
|
||||||
|
door_top_goldlock = { t_door0, t_door1, 64, 0, true, false, false, false, 2 },
|
||||||
|
door_left_goldlock = { t_door0, t_door1, 80, 0, true, false, false, false, 2 },
|
||||||
|
gate_top_nolock = { t_door0, t_door1, 0, 32, true },
|
||||||
|
gate_left_nolock = { t_door0, t_door1, 16, 32, true },
|
||||||
|
gate_top_silverlock = { t_door0, t_door1, 32, 32, true, false, false, false, 1 },
|
||||||
|
gate_left_silverlock = { t_door0, t_door1, 48, 32, true, false, false, false, 1 },
|
||||||
|
gate_top_goldlock = { t_door0, t_door1, 64, 32, true, false, false, false, 2 },
|
||||||
|
gate_left_goldlock = { t_door0, t_door1, 80, 32, true, false, false, false, 2 },
|
||||||
|
}
|
||||||
|
|
||||||
|
lights = {
|
||||||
|
candle0 = { t_decor0, t_decor1, 3 * 16, 8 * 16, true, true },
|
||||||
|
candle1 = { t_decor0, t_decor1, 1 * 16, 8 * 16, true, true },
|
||||||
|
candle2 = { t_decor0, t_decor1, 5 * 16, 8 * 16, true, false },
|
||||||
|
}
|
||||||
|
|
||||||
|
walldecor = {
|
||||||
|
topleft = {
|
||||||
|
{ t_decor0, nil, 2 * 16, 2 * 16, false },
|
||||||
|
{ t_decor0, nil, 6 * 16, 2 * 16, false },
|
||||||
|
{ t_decor0, nil, 7 * 16, 2 * 16, false },
|
||||||
|
},
|
||||||
|
top = {
|
||||||
|
{ t_decor0, nil, 0 * 16, 2 * 16, false },
|
||||||
|
{ t_decor0, nil, 1 * 16, 2 * 16, false },
|
||||||
|
{ t_decor0, nil, 4 * 16, 2 * 16, false },
|
||||||
|
{ t_decor0, nil, 5 * 16, 2 * 16, false },
|
||||||
|
},
|
||||||
|
single = {
|
||||||
|
{ t_decor0, nil, 0 * 16, 2 * 16, false },
|
||||||
|
{ t_decor0, nil, 1 * 16, 2 * 16, false },
|
||||||
|
{ t_decor0, nil, 4 * 16, 2 * 16, false },
|
||||||
|
{ t_decor0, nil, 5 * 16, 2 * 16, false },
|
||||||
|
},
|
||||||
|
topright = {
|
||||||
|
{ t_decor0, nil, 3 * 16, 2 * 16, false },
|
||||||
|
},
|
||||||
|
left = {
|
||||||
|
{ t_decor0, nil, 2 * 16, 2 * 16, false },
|
||||||
|
{ t_decor0, nil, 3 * 16, 2 * 16, false },
|
||||||
|
{ t_decor0, nil, 6 * 16, 2 * 16, false },
|
||||||
|
{ t_decor0, nil, 7 * 16, 2 * 16, false },
|
||||||
|
},
|
||||||
|
bottomleft = {
|
||||||
|
{ t_decor0, nil, 0 * 16, 2 * 16, false },
|
||||||
|
{ t_decor0, nil, 1 * 16, 2 * 16, false },
|
||||||
|
{ t_decor0, nil, 2 * 16, 2 * 16, false },
|
||||||
|
{ t_decor0, nil, 4 * 16, 2 * 16, false },
|
||||||
|
{ t_decor0, nil, 5 * 16, 2 * 16, false },
|
||||||
|
{ t_decor0, nil, 6 * 16, 2 * 16, false },
|
||||||
|
{ t_decor0, nil, 7 * 16, 2 * 16, false },
|
||||||
|
},
|
||||||
|
bottomright = {
|
||||||
|
{ t_decor0, nil, 0 * 16, 2 * 16, false },
|
||||||
|
{ t_decor0, nil, 1 * 16, 2 * 16, false },
|
||||||
|
{ t_decor0, nil, 3 * 16, 2 * 16, false },
|
||||||
|
{ t_decor0, nil, 4 * 16, 2 * 16, false },
|
||||||
|
{ t_decor0, nil, 5 * 16, 2 * 16, false },
|
||||||
|
},
|
||||||
|
left_t = {
|
||||||
|
{ t_decor0, nil, 2 * 16, 2 * 16, false },
|
||||||
|
{ t_decor0, nil, 6 * 16, 2 * 16, false },
|
||||||
|
{ t_decor0, nil, 7 * 16, 2 * 16, false },
|
||||||
|
},
|
||||||
|
right_t = {
|
||||||
|
{ t_decor0, nil, 3 * 16, 2 * 16, false },
|
||||||
|
},
|
||||||
|
bottom_t = {
|
||||||
|
{ t_decor0, nil, 0 * 16, 2 * 16, false },
|
||||||
|
{ t_decor0, nil, 1 * 16, 2 * 16, false },
|
||||||
|
{ t_decor0, nil, 4 * 16, 2 * 16, false },
|
||||||
|
{ t_decor0, nil, 5 * 16, 2 * 16, false },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
chest = { "Items/Chest0.png", "Items/Chest1.png", 16, 0}
|
||||||
|
end
|
||||||
|
|
||||||
|
function createJumbleLayout(matrix)
|
||||||
|
local room1 = matrix[random(#matrix)]
|
||||||
|
local room2 = matrix[random(#matrix)]
|
||||||
|
local room3 = matrix[random(#matrix)]
|
||||||
|
local room4 = matrix[random(#matrix)]
|
||||||
|
|
||||||
|
local room = {}
|
||||||
|
for i=0,15 do
|
||||||
|
for j=0,12 do
|
||||||
|
if not room[i] then room[i] = {} end
|
||||||
|
if not room[i][j] then room[i][j] = {} end
|
||||||
|
if i < 7 then
|
||||||
|
if j < 6 then
|
||||||
|
room[i][j] = room1[i][j]
|
||||||
|
else
|
||||||
|
room[i][j] = room2[i][j]
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if j < 6 then
|
||||||
|
room[i][j] = room3[i][j]
|
||||||
|
else
|
||||||
|
room[i][j] = room4[i][j]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return room
|
||||||
|
end
|
||||||
|
|
||||||
|
function draw_layout_to_room(room, matrix, roomx, roomy)
|
||||||
|
local wallTypes = {"#", "\"", "/", "d", "g", "S", "G"}
|
||||||
|
|
||||||
|
for i=2,13 do
|
||||||
|
for j=2,10 do
|
||||||
|
if matrix[i][j] == "p" then
|
||||||
|
setPitTile(room, matrix, i, j);
|
||||||
|
elseif matrix[i][j] == "#" then
|
||||||
|
setBlockTile(room, matrix, i, j, walls, wallTypes, false)
|
||||||
|
elseif matrix[i][j] == "\"" then
|
||||||
|
setBlockTile(room, matrix, i, j, walls, wallTypes, false)
|
||||||
|
room.decor[i][j] = lights.candle1
|
||||||
|
elseif matrix[i][j] == "/" then
|
||||||
|
setBlockTile(room, matrix, i, j, walls, wallTypes, false)
|
||||||
|
if random(2) == 1 then
|
||||||
|
room.decor[i][j] = lights.candle1
|
||||||
|
else
|
||||||
|
room.decor[i][j] = lights.candle2
|
||||||
|
end
|
||||||
|
elseif matrix[i][j] == "f" then
|
||||||
|
setBlockTile(room, matrix, i, j, fences, "f", true)
|
||||||
|
elseif matrix[i][j] == "a" then
|
||||||
|
create_shop_artifact(map, (roomx*512) + i*32, (roomy * 384) + j*32)
|
||||||
|
elseif matrix[i][j] == "l" then
|
||||||
|
room.decor[i][j] = lights.candle0
|
||||||
|
elseif matrix[i][j] == "c" then
|
||||||
|
room.chests[i][j] = chest
|
||||||
|
elseif matrix[i][j] == "d" then
|
||||||
|
room.doors[i][j] = getDoor(matrix, i, j, doors.door_top_nolock, doors.door_left_nolock)
|
||||||
|
elseif matrix[i][j] == "S" then
|
||||||
|
room.doors[i][j] = getDoor(matrix, i, j, doors.door_top_silverlock, doors.door_left_silverlock)
|
||||||
|
elseif matrix[i][j] == "G" then
|
||||||
|
room.doors[i][j] = getDoor(matrix, i, j, doors.door_top_goldlock, doors.door_left_goldlock)
|
||||||
|
elseif matrix[i][j] == "g" then
|
||||||
|
room.doors[i][j] = getDoor(matrix, i, j, doors.gate_top_nolock, doors.gate_left_nolock)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function pickALayout(matrix)
|
||||||
|
-- Chose a random layout
|
||||||
|
if random(3) == 1 then
|
||||||
|
return matrix[random(#matrix)]
|
||||||
|
else
|
||||||
|
return createJumbleLayout(matrix)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function module.add_walls_to_room(room)
|
||||||
|
if random(2) == 1 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
draw_layout_to_room(room, pickALayout(readLayoutFile("walllayouts.dat")))
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function module.add_pits_to_room(room)
|
||||||
|
if CURRENT_LEVEL < 2 or random(5) ~= 1 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
draw_layout_to_room(room, pickALayout(readLayoutFile("pitlayouts.dat")))
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function module.add_shop_layout(room, roomx, roomy)
|
||||||
|
local matrix = readLayoutFile("shoplayouts.dat")
|
||||||
|
draw_layout_to_room(room, matrix[random(#matrix)], roomx, roomy)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function module.add_locked_room_layout(room, roomx, roomy)
|
||||||
|
local matrix = readLayoutFile("lockedroomlayouts.dat")
|
||||||
|
draw_layout_to_room(room, matrix[random(#matrix)], roomx, roomy)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return module
|
|
@ -0,0 +1,90 @@
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
++"#####G####"++
|
||||||
|
++#-c--c--c--#++
|
||||||
|
++#----------#++
|
||||||
|
++#-c--c--c--#++
|
||||||
|
++G----------G++
|
||||||
|
++#-c--c--c--#++
|
||||||
|
++#----------#++
|
||||||
|
++"#####G####"++
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
++"#####S####"++
|
||||||
|
++#-c--c--c--#++
|
||||||
|
++#----------#++
|
||||||
|
++#-c--c--c--#++
|
||||||
|
++S----------S++
|
||||||
|
++#-c--c--c--#++
|
||||||
|
++#----------#++
|
||||||
|
++"#####S####"++
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
++/####-#####/++
|
||||||
|
++#--c#-#c---#++
|
||||||
|
++S---#-#----G++
|
||||||
|
++#####-######++
|
||||||
|
++------------++
|
||||||
|
++#####-######++
|
||||||
|
++S--c#-#c---G++
|
||||||
|
++/####-#####/++
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
++----#S#-----++
|
||||||
|
++----#c#-----++
|
||||||
|
++----#c#-----++
|
||||||
|
++----#c#-----++
|
||||||
|
++----###-----++
|
||||||
|
++------------++
|
||||||
|
++------------++
|
||||||
|
++------------++
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
++------------++
|
||||||
|
++------------++
|
||||||
|
++------------++
|
||||||
|
++---###S##---++
|
||||||
|
++---#cccc#---++
|
||||||
|
++---######---++
|
||||||
|
++------------++
|
||||||
|
++------------++
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
++----#G#-----++
|
||||||
|
++----#c#-----++
|
||||||
|
++----#c#-----++
|
||||||
|
++----#c#-----++
|
||||||
|
++----###-----++
|
||||||
|
++------------++
|
||||||
|
++------------++
|
||||||
|
++------------++
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
++------------++
|
||||||
|
++------------++
|
||||||
|
++------------++
|
||||||
|
++---###G##---++
|
||||||
|
++---#cccc#---++
|
||||||
|
++---######---++
|
||||||
|
++------------++
|
||||||
|
++------------++
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
|
@ -14,6 +14,8 @@ local LEFT = 2
|
||||||
local RIGHT = 3
|
local RIGHT = 3
|
||||||
local DOWN = 4
|
local DOWN = 4
|
||||||
|
|
||||||
|
local lockedDoorsAdded = false
|
||||||
|
|
||||||
-- BEGIN FUNCTIONS
|
-- BEGIN FUNCTIONS
|
||||||
local function matrix_coverage (matrix)
|
local function matrix_coverage (matrix)
|
||||||
local cov = 0
|
local cov = 0
|
||||||
|
@ -49,9 +51,11 @@ local function generate_path ()
|
||||||
local direction = 0
|
local direction = 0
|
||||||
local lastDirection = 0
|
local lastDirection = 0
|
||||||
local coridoor_count = 0
|
local coridoor_count = 0
|
||||||
|
local shopLevel = CURRENT_LEVEL % 4 == 0
|
||||||
local bossLevel = CURRENT_LEVEL % 5 == 0
|
local bossLevel = CURRENT_LEVEL % 5 == 0
|
||||||
if QUICK_MODE then
|
if QUICK_MODE then
|
||||||
bossLevel = CURRENT_LEVEL % 3 == 0
|
bossLevel = CURRENT_LEVEL % 3 == 0
|
||||||
|
shopLevel = CURRENT_LEVEL % 2 == 0
|
||||||
end
|
end
|
||||||
local coverage = 8 + CURRENT_LEVEL
|
local coverage = 8 + CURRENT_LEVEL
|
||||||
if bossLevel or CURRENT_LEVEL == 1 then
|
if bossLevel or CURRENT_LEVEL == 1 then
|
||||||
|
@ -59,6 +63,11 @@ local function generate_path ()
|
||||||
end
|
end
|
||||||
if ARCADE_MODE then
|
if ARCADE_MODE then
|
||||||
coverage = 40
|
coverage = 40
|
||||||
|
shopLevel = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if shopLevel then
|
||||||
|
coverage = coverage + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Create the first room
|
-- Create the first room
|
||||||
|
@ -114,17 +123,33 @@ local function generate_path ()
|
||||||
|
|
||||||
local roomCount = 0
|
local roomCount = 0
|
||||||
local bossAdded = false
|
local bossAdded = false
|
||||||
|
local shopAdded = false
|
||||||
|
|
||||||
-- Build all the rooms
|
-- Build all the rooms
|
||||||
for i=1,10 do
|
for i=1,10 do
|
||||||
for j=1,10 do
|
for j=1,10 do
|
||||||
room = map_matrix[i][j]
|
room = map_matrix[i][j]
|
||||||
if room then
|
if room then
|
||||||
|
if roomCount > 4 and shopLevel and not shopAdded and not room.goal then
|
||||||
|
room.type = "shop"
|
||||||
|
shopAdded = true
|
||||||
|
elseif random(8) == 1 and not room.goal then
|
||||||
|
room.type = "locked"
|
||||||
|
lockedDoorsAdded = true
|
||||||
|
end
|
||||||
roomCount = roomCount + 1
|
roomCount = roomCount + 1
|
||||||
room_builder.build_room(room)
|
room_builder.build_room(room, i-1, j-1)
|
||||||
monster_gen.add_monsters_to_room(room, i-1, j-1)
|
if room.type ~= "shop" then
|
||||||
trap_gen.add_traps_to_room(room, i-1, j-1)
|
monster_gen.add_monsters_to_room(room, i-1, j-1)
|
||||||
chest_gen.add_chests_to_room(room, i-1, j-1)
|
trap_gen.add_traps_to_room(room, i-1, j-1)
|
||||||
|
chest_gen.add_chests_to_room(room, i-1, j-1)
|
||||||
|
else
|
||||||
|
monster_gen.add_shopkeeper_to_room(room, i-1, j-1)
|
||||||
|
if PlayerData.shopOwnerKiller then
|
||||||
|
monster_gen.add_bodyguard_to_room(room, i-1, j-1)
|
||||||
|
monster_gen.add_bodyguard_to_room(room, i-1, j-1)
|
||||||
|
end
|
||||||
|
end
|
||||||
if roomCount > 3 and bossLevel and not bossAdded then
|
if roomCount > 3 and bossLevel and not bossAdded then
|
||||||
bossAdded = true
|
bossAdded = true
|
||||||
monster_gen.add_boss_to_room(room, i-1, j-1)
|
monster_gen.add_boss_to_room(room, i-1, j-1)
|
||||||
|
@ -157,4 +182,8 @@ for i=1,10 do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if lockedDoorsAdded then
|
||||||
|
add_keybearers(map)
|
||||||
|
end
|
||||||
-- END SCRIPT
|
-- END SCRIPT
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
-- FUNCTIONS
|
-- FUNCTIONS
|
||||||
local random = map_random
|
local random = map_random
|
||||||
|
local layoutparser = require "layoutparser"
|
||||||
|
|
||||||
-- CONSTANTS
|
-- CONSTANTS
|
||||||
local UP = 1
|
local UP = 1
|
||||||
|
@ -28,18 +29,10 @@ local wall = {
|
||||||
horizontal = nil
|
horizontal = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
local pits = {
|
|
||||||
center = nil,
|
|
||||||
top = nil,
|
|
||||||
left = nil,
|
|
||||||
right = nil,
|
|
||||||
topleft = nil,
|
|
||||||
topright = nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
local special = { level_exit = nil }
|
local special = { level_exit = nil }
|
||||||
|
|
||||||
local floorDecor = { }
|
local floorDecor = { }
|
||||||
|
local blockingFloorDecor = { }
|
||||||
local lightDecor = { }
|
local lightDecor = { }
|
||||||
|
|
||||||
local function load_decor_textures()
|
local function load_decor_textures()
|
||||||
|
@ -49,9 +42,9 @@ local function load_decor_textures()
|
||||||
-- Skulls
|
-- Skulls
|
||||||
table.insert(floorDecor, { td0, td1, 0, 12 * 16, false, false })
|
table.insert(floorDecor, { td0, td1, 0, 12 * 16, false, false })
|
||||||
table.insert(floorDecor, { td0, td1, 32, 12 * 16, false, false })
|
table.insert(floorDecor, { td0, td1, 32, 12 * 16, false, false })
|
||||||
table.insert(floorDecor, { td0, td1, 64, 12 * 16, false, true })
|
|
||||||
table.insert(floorDecor, { td0, td1, 0, 13 * 16, false, false })
|
table.insert(floorDecor, { td0, td1, 0, 13 * 16, false, false })
|
||||||
table.insert(floorDecor, { td0, td1, 32, 13 * 16, false, false })
|
table.insert(floorDecor, { td0, td1, 32, 13 * 16, false, false })
|
||||||
|
table.insert(floorDecor, { td0, td1, 64, 12 * 16, false, true })
|
||||||
table.insert(floorDecor, { td0, td1, 64, 13 * 16, false, true })
|
table.insert(floorDecor, { td0, td1, 64, 13 * 16, false, true })
|
||||||
|
|
||||||
-- Bones
|
-- Bones
|
||||||
|
@ -60,42 +53,6 @@ local function load_decor_textures()
|
||||||
table.insert(floorDecor, { td0, td1, 16, 13 * 16, false, false })
|
table.insert(floorDecor, { td0, td1, 16, 13 * 16, false, false })
|
||||||
table.insert(floorDecor, { td0, td1, 48, 13 * 16, false, false })
|
table.insert(floorDecor, { td0, td1, 48, 13 * 16, false, false })
|
||||||
|
|
||||||
-- Urns
|
|
||||||
--table.insert(floorDecor, { td0, td1, 0 * 16, 48, true, false })
|
|
||||||
--table.insert(floorDecor, { td0, td1, 1 * 16, 48, true, false })
|
|
||||||
--table.insert(floorDecor, { td0, td1, 2 * 16, 48, true, false })
|
|
||||||
--table.insert(floorDecor, { td0, td1, 3 * 16, 48, true, false })
|
|
||||||
--table.insert(floorDecor, { td0, td1, 4 * 16, 48, true, false })
|
|
||||||
--table.insert(floorDecor, { td0, td1, 5 * 16, 48, true, false })
|
|
||||||
--table.insert(floorDecor, { td0, td1, 6 * 16, 48, false, false })
|
|
||||||
--table.insert(floorDecor, { td0, td1, 7 * 16, 48, false, false })
|
|
||||||
|
|
||||||
-- Racks
|
|
||||||
--table.insert(floorDecor, { td0, td1, 0 * 16, 11 * 16, true, false })
|
|
||||||
--table.insert(floorDecor, { td0, td1, 1 * 16, 11 * 16, true, false })
|
|
||||||
--table.insert(floorDecor, { td0, td1, 2 * 16, 11 * 16, true, false })
|
|
||||||
--table.insert(floorDecor, { td0, td1, 3 * 16, 11 * 16, true, false })
|
|
||||||
--table.insert(floorDecor, { td0, td1, 4 * 16, 11 * 16, true, false })
|
|
||||||
--table.insert(floorDecor, { td0, td1, 5 * 16, 11 * 16, true, false })
|
|
||||||
--table.insert(floorDecor, { td0, td1, 6 * 16, 11 * 16, true, false })
|
|
||||||
|
|
||||||
-- Headstones
|
|
||||||
table.insert(floorDecor, { td0, td1, 0 * 16, 17 * 16, true, false })
|
|
||||||
table.insert(floorDecor, { td0, td1, 1 * 16, 17 * 16, true, false })
|
|
||||||
table.insert(floorDecor, { td0, td1, 2 * 16, 17 * 16, true, false })
|
|
||||||
table.insert(floorDecor, { td0, td1, 3 * 16, 17 * 16, true, false })
|
|
||||||
table.insert(floorDecor, { td0, td1, 4 * 16, 17 * 16, true, false })
|
|
||||||
table.insert(floorDecor, { td0, td1, 0 * 16, 18 * 16, true, false })
|
|
||||||
table.insert(floorDecor, { td0, td1, 1 * 16, 18 * 16, true, false })
|
|
||||||
table.insert(floorDecor, { td0, td1, 2 * 16, 18 * 16, true, false })
|
|
||||||
table.insert(floorDecor, { td0, td1, 3 * 16, 18 * 16, true, false })
|
|
||||||
table.insert(floorDecor, { td0, td1, 4 * 16, 18 * 16, true, false })
|
|
||||||
|
|
||||||
-- Altars
|
|
||||||
table.insert(floorDecor, { td0, td1, 0 * 16, 20 * 16, true, false })
|
|
||||||
table.insert(floorDecor, { td0, td1, 1 * 16, 20 * 16, true, false })
|
|
||||||
table.insert(floorDecor, { td0, td1, 2 * 16, 20 * 16, true, false })
|
|
||||||
|
|
||||||
-- Webs
|
-- Webs
|
||||||
--table.insert(floorDecor, { td0, td1, 0 * 16, 19 * 16, false })
|
--table.insert(floorDecor, { td0, td1, 0 * 16, 19 * 16, false })
|
||||||
--table.insert(floorDecor, { td0, td1, 1 * 16, 19 * 16, false })
|
--table.insert(floorDecor, { td0, td1, 1 * 16, 19 * 16, false })
|
||||||
|
@ -103,9 +60,47 @@ local function load_decor_textures()
|
||||||
--table.insert(floorDecor, { td0, td1, 3 * 16, 19 * 16, false })
|
--table.insert(floorDecor, { td0, td1, 3 * 16, 19 * 16, false })
|
||||||
--table.insert(floorDecor, { td0, td1, 4 * 16, 19 * 16, false })
|
--table.insert(floorDecor, { td0, td1, 4 * 16, 19 * 16, false })
|
||||||
|
|
||||||
|
-- Urns
|
||||||
|
table.insert(floorDecor, { td0, td1, 6 * 16, 48, false, false })
|
||||||
|
table.insert(floorDecor, { td0, td1, 7 * 16, 48, false, false })
|
||||||
|
|
||||||
|
-- Urns
|
||||||
|
--table.insert(blockingFloorDecor, { td0, td1, 0 * 16, 48, true, false })
|
||||||
|
--table.insert(blockingFloorDecor, { td0, td1, 1 * 16, 48, true, false })
|
||||||
|
--table.insert(blockingFloorDecor, { td0, td1, 2 * 16, 48, true, false })
|
||||||
|
--table.insert(blockingFloorDecor, { td0, td1, 3 * 16, 48, true, false })
|
||||||
|
--table.insert(blockingFloorDecor, { td0, td1, 4 * 16, 48, true, false })
|
||||||
|
--table.insert(blockingFloorDecor, { td0, td1, 5 * 16, 48, true, false })
|
||||||
|
|
||||||
|
-- Racks
|
||||||
|
--table.insert(blockingFloorDecor, { td0, td1, 0 * 16, 11 * 16, true, false })
|
||||||
|
--table.insert(blockingFloorDecor, { td0, td1, 1 * 16, 11 * 16, true, false })
|
||||||
|
--table.insert(blockingFloorDecor, { td0, td1, 2 * 16, 11 * 16, true, false })
|
||||||
|
--table.insert(blockingFloorDecor, { td0, td1, 3 * 16, 11 * 16, true, false })
|
||||||
|
--table.insert(blockingFloorDecor, { td0, td1, 4 * 16, 11 * 16, true, false })
|
||||||
|
--table.insert(blockingFloorDecor, { td0, td1, 5 * 16, 11 * 16, true, false })
|
||||||
|
--table.insert(blockingFloorDecor, { td0, td1, 6 * 16, 11 * 16, true, false })
|
||||||
|
|
||||||
|
-- Headstones
|
||||||
|
table.insert(blockingFloorDecor, { td0, td1, 0 * 16, 17 * 16, true, false })
|
||||||
|
table.insert(blockingFloorDecor, { td0, td1, 1 * 16, 17 * 16, true, false })
|
||||||
|
table.insert(blockingFloorDecor, { td0, td1, 2 * 16, 17 * 16, true, false })
|
||||||
|
table.insert(blockingFloorDecor, { td0, td1, 3 * 16, 17 * 16, true, false })
|
||||||
|
table.insert(blockingFloorDecor, { td0, td1, 4 * 16, 17 * 16, true, false })
|
||||||
|
table.insert(blockingFloorDecor, { td0, td1, 0 * 16, 18 * 16, true, false })
|
||||||
|
table.insert(blockingFloorDecor, { td0, td1, 1 * 16, 18 * 16, true, false })
|
||||||
|
table.insert(blockingFloorDecor, { td0, td1, 2 * 16, 18 * 16, true, false })
|
||||||
|
table.insert(blockingFloorDecor, { td0, td1, 3 * 16, 18 * 16, true, false })
|
||||||
|
table.insert(blockingFloorDecor, { td0, td1, 4 * 16, 18 * 16, true, false })
|
||||||
|
|
||||||
|
-- Altars
|
||||||
|
table.insert(blockingFloorDecor, { td0, td1, 0 * 16, 20 * 16, true, false })
|
||||||
|
table.insert(blockingFloorDecor, { td0, td1, 1 * 16, 20 * 16, true, false })
|
||||||
|
table.insert(blockingFloorDecor, { td0, td1, 2 * 16, 20 * 16, true, false })
|
||||||
|
|
||||||
-- Statues
|
-- Statues
|
||||||
--table.insert(floorDecor, { td0, td1, 3 * 16, 20 * 16, true })
|
--table.insert(blockingFloorDecor, { td0, td1, 3 * 16, 20 * 16, true })
|
||||||
--table.insert(floorDecor, { td0, td1, 4 * 16, 20 * 16, true })
|
--table.insert(blockingFloorDecor, { td0, td1, 4 * 16, 20 * 16, true })
|
||||||
|
|
||||||
lightDecor.candle0 = { td0, td1, 0, 8 * 16, false, true }
|
lightDecor.candle0 = { td0, td1, 0, 8 * 16, false, true }
|
||||||
lightDecor.candle1 = { td0, td1, 16, 8 * 16, false, true }
|
lightDecor.candle1 = { td0, td1, 16, 8 * 16, false, true }
|
||||||
|
@ -126,100 +121,71 @@ local function repack(data)
|
||||||
isCollider = data[5] or false,
|
isCollider = data[5] or false,
|
||||||
isLightSource = data[6] or false,
|
isLightSource = data[6] or false,
|
||||||
isLevelExit = data[7] or false,
|
isLevelExit = data[7] or false,
|
||||||
isLethal = data[8] or false
|
isLethal = data[8] or false,
|
||||||
|
lockType = data[9] or 0
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
local function add_random_decor_to_room(room)
|
local function room_tile_available(room, rx, ry)
|
||||||
local decor_count = random(8)
|
return not room.chests[rx][ry]
|
||||||
for i=1,decor_count do
|
and not room.traps[rx][ry]
|
||||||
x = random(11) + 1
|
and not room.walls[rx][ry]
|
||||||
y = random(8) + 1
|
and not room.doors[rx][ry]
|
||||||
if not room.decor[x][y] then
|
and not room.monsters[rx][ry]
|
||||||
room.decor[x][y] = floorDecor[random(#floorDecor)]
|
and not room.decor[rx][ry]
|
||||||
end
|
and (room.tiles[rx][ry]
|
||||||
end
|
and not room.tiles[rx][ry][5]
|
||||||
|
and not room.tiles[rx][ry][7]
|
||||||
if random(2) == 1 then
|
and not room.tiles[rx][ry][8])
|
||||||
room.decor[4][3] = lightDecor.candle2
|
|
||||||
end
|
|
||||||
if random(2) == 1 then
|
|
||||||
room.decor[11][3] = lightDecor.candle2
|
|
||||||
end
|
|
||||||
if random(2) == 1 then
|
|
||||||
room.decor[4][9] = lightDecor.candle2
|
|
||||||
end
|
|
||||||
if random(2) == 1 then
|
|
||||||
room.decor[11][9] = lightDecor.candle2
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function add_pits_to_room(room)
|
|
||||||
|
|
||||||
if CURRENT_LEVEL < 2 or random(5) ~= 1 then
|
local function add_random_decor_to_room(room, blockingDecor)
|
||||||
return false
|
local decor_count = random(8)
|
||||||
|
if blockingDecor then
|
||||||
|
decor_count = random(4)
|
||||||
end
|
end
|
||||||
|
for i=1,decor_count do
|
||||||
local pitdata = read_file("pitlayouts.dat")
|
local success = false
|
||||||
|
while not success do
|
||||||
local cleanData = ""
|
x = random(11) + 1
|
||||||
for i=1, #pitdata do
|
y = random(8) + 1
|
||||||
local c = pitdata:sub(i+1, i+1)
|
if room_tile_available(room, x, y) then
|
||||||
if c == "#" or c == "-" then
|
room.decor[x][y] = floorDecor[random(#floorDecor)]
|
||||||
cleanData = cleanData .. c
|
success = true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local matrix = {}
|
if blockingDecor then
|
||||||
for i=0, #cleanData-1 do
|
decor_count = random(4)
|
||||||
local c = cleanData:sub(i, i)
|
for i=1,decor_count do
|
||||||
local col = i % 16
|
local success = false
|
||||||
local row = (i - col)/16
|
while not success do
|
||||||
local layout = 1 + (row - (row % 12))/12
|
x = random(11) + 1
|
||||||
local row = row % 12
|
y = random(8) + 1
|
||||||
if not matrix[layout] then matrix[layout] = {} end
|
if room_tile_available(room, x, y) then
|
||||||
if not matrix[layout][col] then matrix[layout][col] = {} end
|
room.decor[x][y] = blockingFloorDecor[random(#blockingFloorDecor)]
|
||||||
if c == "#" then
|
success = true
|
||||||
matrix[layout][col][row] = true
|
|
||||||
else
|
|
||||||
matrix[layout][col][row] = false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Chose a random layout
|
|
||||||
matrix = matrix[random(#matrix)]
|
|
||||||
for i=2,13 do
|
|
||||||
for j=2,10 do
|
|
||||||
if matrix[i][j] then
|
|
||||||
room.decor[i][j] = nil
|
|
||||||
if not matrix[i-1][j-1] and not matrix[i+1][j-1] and matrix[i-1][j] and matrix[i+1][j] and matrix[i][j-1] then
|
|
||||||
room.tiles[i][j] = pits.innermid
|
|
||||||
elseif not matrix[i-1][j-1] and matrix[i-1][j] and matrix[i][j-1] then
|
|
||||||
room.tiles[i][j] = pits.innerleft
|
|
||||||
elseif not matrix[i+1][j-1] and matrix[i+1][j] and matrix[i][j-1] then
|
|
||||||
room.tiles[i][j] = pits.innerright
|
|
||||||
elseif not matrix[i-1][j] and not matrix[i][j-1] and not matrix[i+1][j] then
|
|
||||||
room.tiles[i][j] = pits.topcrevice
|
|
||||||
elseif not matrix[i-1][j] and not matrix[i+1][j] then
|
|
||||||
room.tiles[i][j] = pits.bottomcrevice
|
|
||||||
elseif not matrix[i-1][j] and not matrix[i][j-1] then
|
|
||||||
room.tiles[i][j] = pits.topleft
|
|
||||||
elseif not matrix[i+1][j] and not matrix[i][j-1] then
|
|
||||||
room.tiles[i][j] = pits.topright
|
|
||||||
elseif not matrix[i-1][j] then
|
|
||||||
room.tiles[i][j] = pits.left
|
|
||||||
elseif not matrix[i+1][j] then
|
|
||||||
room.tiles[i][j] = pits.right
|
|
||||||
elseif not matrix[i][j-1] then
|
|
||||||
room.tiles[i][j] = pits.top
|
|
||||||
else
|
|
||||||
room.tiles[i][j] = pits.center
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return true
|
if blockingDecor then
|
||||||
|
if random(2) == 1 and room_tile_available(room, 4, 3) then
|
||||||
|
room.decor[4][3] = lightDecor.candle2
|
||||||
|
end
|
||||||
|
if random(2) == 1 and room_tile_available(room, 11, 3) then
|
||||||
|
room.decor[11][3] = lightDecor.candle2
|
||||||
|
end
|
||||||
|
if random(2) == 1 and room_tile_available(room, 4, 9) then
|
||||||
|
room.decor[4][9] = lightDecor.candle2
|
||||||
|
end
|
||||||
|
if random(2) == 1 and room_tile_available(room, 11, 9) then
|
||||||
|
room.decor[11][9] = lightDecor.candle2
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function add_tiles_to_room (room, singletile)
|
local function add_tiles_to_room (room, singletile)
|
||||||
|
@ -245,6 +211,8 @@ local function add_tiles_to_room (room, singletile)
|
||||||
else
|
else
|
||||||
room.tiles[i][j] = singletile and floor.single or floor.center
|
room.tiles[i][j] = singletile and floor.single or floor.center
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
room.tiles[i][j] = floor.single
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -254,17 +222,17 @@ local function add_walls_to_room (room)
|
||||||
for i=0,15 do
|
for i=0,15 do
|
||||||
for j=0,11 do
|
for j=0,11 do
|
||||||
if (i == 0 and j == 0) then
|
if (i == 0 and j == 0) then
|
||||||
room.tiles[i][j] = wall.topleft
|
room.walls[i][j] = wall.topleft
|
||||||
elseif (i == 15 and j == 0) then
|
elseif (i == 15 and j == 0) then
|
||||||
room.tiles[i][j] = wall.topright
|
room.walls[i][j] = wall.topright
|
||||||
elseif (i == 0 and j == 11) then
|
elseif (i == 0 and j == 11) then
|
||||||
room.tiles[i][j] = wall.bottomleft
|
room.walls[i][j] = wall.bottomleft
|
||||||
elseif (i == 15 and j == 11) then
|
elseif (i == 15 and j == 11) then
|
||||||
room.tiles[i][j] = wall.bottomright
|
room.walls[i][j] = wall.bottomright
|
||||||
elseif (i == 0 or i == 15) then
|
elseif (i == 0 or i == 15) then
|
||||||
room.tiles[i][j] = wall.vertical
|
room.walls[i][j] = wall.vertical
|
||||||
elseif (j == 0 or j == 11) then
|
elseif (j == 0 or j == 11) then
|
||||||
room.tiles[i][j] = wall.horizontal
|
room.walls[i][j] = wall.horizontal
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -272,10 +240,12 @@ end
|
||||||
|
|
||||||
local function build_vert_center_coridoor(room, offset)
|
local function build_vert_center_coridoor(room, offset)
|
||||||
for i=0,4 do
|
for i=0,4 do
|
||||||
room.tiles[6][offset+i] = wall.vertical
|
room.walls[6][offset+i] = wall.vertical
|
||||||
room.tiles[7][offset+i] = floor.center
|
room.tiles[7][offset+i] = floor.center
|
||||||
room.tiles[8][offset+i] = floor.center
|
room.tiles[8][offset+i] = floor.center
|
||||||
room.tiles[9][offset+i] = wall.vertical
|
room.walls[7][offset+i] = nil
|
||||||
|
room.walls[8][offset+i] = nil
|
||||||
|
room.walls[9][offset+i] = wall.vertical
|
||||||
end
|
end
|
||||||
if random(2) == 1 then
|
if random(2) == 1 then
|
||||||
room.decor[6][offset+2] = lightDecor.candle1
|
room.decor[6][offset+2] = lightDecor.candle1
|
||||||
|
@ -287,10 +257,12 @@ end
|
||||||
|
|
||||||
local function build_horiz_center_coridoor(room, offset)
|
local function build_horiz_center_coridoor(room, offset)
|
||||||
for i=0,6 do
|
for i=0,6 do
|
||||||
room.tiles[offset+i][4] = wall.horizontal
|
room.walls[offset+i][4] = wall.horizontal
|
||||||
room.tiles[offset+i][5] = floor.center
|
room.tiles[offset+i][5] = floor.center
|
||||||
room.tiles[offset+i][6] = floor.center
|
room.tiles[offset+i][6] = floor.center
|
||||||
room.tiles[offset+i][7] = wall.horizontal
|
room.walls[offset+i][5] = nil
|
||||||
|
room.walls[offset+i][6] = nil
|
||||||
|
room.walls[offset+i][7] = wall.horizontal
|
||||||
end
|
end
|
||||||
if random(2) == 1 then
|
if random(2) == 1 then
|
||||||
room.decor[offset+3][4] = lightDecor.candle1
|
room.decor[offset+3][4] = lightDecor.candle1
|
||||||
|
@ -303,32 +275,32 @@ end
|
||||||
local function build_center_corner_walls(room, exits)
|
local function build_center_corner_walls(room, exits)
|
||||||
if exits.down then
|
if exits.down then
|
||||||
if exits.left then
|
if exits.left then
|
||||||
room.tiles[6][7] = wall.topright
|
room.walls[6][7] = wall.topright
|
||||||
end
|
end
|
||||||
if exits.right then
|
if exits.right then
|
||||||
room.tiles[9][7] = wall.topleft
|
room.walls[9][7] = wall.topleft
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if not exits.left then
|
if not exits.left then
|
||||||
room.tiles[6][7] = wall.bottomleft
|
room.walls[6][7] = wall.bottomleft
|
||||||
end
|
end
|
||||||
if not exits.right then
|
if not exits.right then
|
||||||
room.tiles[9][7] = wall.bottomright
|
room.walls[9][7] = wall.bottomright
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if exits.up then
|
if exits.up then
|
||||||
if exits.left then
|
if exits.left then
|
||||||
room.tiles[6][4] = wall.bottomright
|
room.walls[6][4] = wall.bottomright
|
||||||
end
|
end
|
||||||
if exits.right then
|
if exits.right then
|
||||||
room.tiles[9][4] = wall.bottomleft
|
room.walls[9][4] = wall.bottomleft
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if not exits.left then
|
if not exits.left then
|
||||||
room.tiles[6][4] = wall.topleft
|
room.walls[6][4] = wall.topleft
|
||||||
end
|
end
|
||||||
if not exits.right then
|
if not exits.right then
|
||||||
room.tiles[9][4] = wall.topright
|
room.walls[9][4] = wall.topright
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -336,25 +308,33 @@ end
|
||||||
local function add_exits_to_room(room)
|
local function add_exits_to_room(room)
|
||||||
for _,direction in ipairs(room.exits) do
|
for _,direction in ipairs(room.exits) do
|
||||||
if direction == UP then
|
if direction == UP then
|
||||||
room.tiles[6][0] = wall.bottomright
|
room.walls[6][0] = wall.bottomright
|
||||||
room.tiles[7][0] = floor.singleleft
|
room.tiles[7][0] = floor.singleleft
|
||||||
room.tiles[8][0] = floor.singleright
|
room.tiles[8][0] = floor.singleright
|
||||||
room.tiles[9][0] = wall.bottomleft
|
room.walls[7][0] = nil
|
||||||
|
room.walls[8][0] = nil
|
||||||
|
room.walls[9][0] = wall.bottomleft
|
||||||
elseif direction == LEFT then
|
elseif direction == LEFT then
|
||||||
room.tiles[0][4] = wall.bottomright
|
room.walls[0][4] = wall.bottomright
|
||||||
room.tiles[0][5] = floor.singletop
|
room.tiles[0][5] = floor.singletop
|
||||||
room.tiles[0][6] = floor.singlebottom
|
room.tiles[0][6] = floor.singlebottom
|
||||||
room.tiles[0][7] = wall.topright
|
room.walls[0][5] = nil
|
||||||
|
room.walls[0][6] = nil
|
||||||
|
room.walls[0][7] = wall.topright
|
||||||
elseif direction == RIGHT then
|
elseif direction == RIGHT then
|
||||||
room.tiles[15][4] = wall.bottomleft
|
room.walls[15][4] = wall.bottomleft
|
||||||
room.tiles[15][5] = floor.singletop
|
room.tiles[15][5] = floor.singletop
|
||||||
room.tiles[15][6] = floor.singlebottom
|
room.tiles[15][6] = floor.singlebottom
|
||||||
room.tiles[15][7] = wall.topleft
|
room.walls[15][5] = nil
|
||||||
|
room.walls[15][6] = nil
|
||||||
|
room.walls[15][7] = wall.topleft
|
||||||
elseif direction == DOWN then
|
elseif direction == DOWN then
|
||||||
room.tiles[6][11] = wall.topright
|
room.walls[6][11] = wall.topright
|
||||||
room.tiles[7][11] = floor.singleleft
|
room.tiles[7][11] = floor.singleleft
|
||||||
room.tiles[8][11] = floor.singleright
|
room.tiles[8][11] = floor.singleright
|
||||||
room.tiles[9][11] = wall.topleft
|
room.walls[7][11] = nil
|
||||||
|
room.walls[8][11] = nil
|
||||||
|
room.walls[9][11] = wall.topleft
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -376,18 +356,19 @@ local function build_coridoor_room(room)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Fill the center
|
-- Fill the center
|
||||||
room.tiles[6][5] = wall.vertical
|
|
||||||
room.tiles[6][6] = wall.vertical
|
|
||||||
room.tiles[7][4] = wall.horizontal
|
|
||||||
room.tiles[7][5] = floor.center
|
room.tiles[7][5] = floor.center
|
||||||
room.tiles[7][6] = floor.center
|
room.tiles[7][6] = floor.center
|
||||||
room.tiles[7][7] = wall.horizontal
|
|
||||||
room.tiles[8][4] = wall.horizontal
|
|
||||||
room.tiles[8][5] = floor.center
|
room.tiles[8][5] = floor.center
|
||||||
room.tiles[8][6] = floor.center
|
room.tiles[8][6] = floor.center
|
||||||
room.tiles[8][7] = wall.horizontal
|
|
||||||
room.tiles[9][5] = wall.vertical
|
room.walls[6][5] = wall.vertical
|
||||||
room.tiles[9][6] = wall.vertical
|
room.walls[6][6] = wall.vertical
|
||||||
|
room.walls[7][4] = wall.horizontal
|
||||||
|
room.walls[7][7] = wall.horizontal
|
||||||
|
room.walls[8][4] = wall.horizontal
|
||||||
|
room.walls[8][7] = wall.horizontal
|
||||||
|
room.walls[9][5] = wall.vertical
|
||||||
|
room.walls[9][6] = wall.vertical
|
||||||
|
|
||||||
-- Build the coridoors
|
-- Build the coridoors
|
||||||
if exits.down then build_vert_center_coridoor(room, 7) end
|
if exits.down then build_vert_center_coridoor(room, 7) end
|
||||||
|
@ -398,19 +379,8 @@ local function build_coridoor_room(room)
|
||||||
build_center_corner_walls(room, exits)
|
build_center_corner_walls(room, exits)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function room_tile_available(room, rx, ry)
|
|
||||||
return not room.chests[rx][ry]
|
|
||||||
and not room.traps[rx][ry]
|
|
||||||
and not room.monsters[rx][ry]
|
|
||||||
and not room.decor[rx][ry]
|
|
||||||
and (room.tiles[rx][ry]
|
|
||||||
and not room.tiles[rx][ry][5]
|
|
||||||
and not room.tiles[rx][ry][7]
|
|
||||||
and not room.tiles[rx][ry][8])
|
|
||||||
end
|
|
||||||
|
|
||||||
local function add_level_exit(room)
|
local function add_level_exit(room)
|
||||||
success = false
|
local success = false
|
||||||
while not success do
|
while not success do
|
||||||
x = random(14)
|
x = random(14)
|
||||||
y = random(10)
|
y = random(10)
|
||||||
|
@ -421,14 +391,39 @@ local function add_level_exit(room)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function build_normal_room(room)
|
local function build_shop_room(room, roomx, roomy)
|
||||||
local crumbling = (CURRENT_LEVEL > 3 or QUICK_MODE) and random(8) == 1
|
add_tiles_to_room(room, false)
|
||||||
|
|
||||||
add_tiles_to_room(room, crumbling)
|
|
||||||
add_random_decor_to_room(room)
|
|
||||||
add_walls_to_room(room)
|
add_walls_to_room(room)
|
||||||
add_exits_to_room(room)
|
add_exits_to_room(room)
|
||||||
local pitsAdded = crumbling or add_pits_to_room(room)
|
layoutparser.add_shop_layout(room, roomx, roomy)
|
||||||
|
return room
|
||||||
|
end
|
||||||
|
|
||||||
|
local function build_locked_room(room, roomx, roomy)
|
||||||
|
add_tiles_to_room(room, false)
|
||||||
|
add_walls_to_room(room)
|
||||||
|
add_exits_to_room(room)
|
||||||
|
layoutparser.add_locked_room_layout(room, roomx, roomy)
|
||||||
|
return room
|
||||||
|
end
|
||||||
|
|
||||||
|
local function build_normal_room(room)
|
||||||
|
local crumbling = (CURRENT_LEVEL > 3 or QUICK_MODE) and random(8) == 1
|
||||||
|
local pitsAdded = false;
|
||||||
|
local interiorWallsAdded = false
|
||||||
|
|
||||||
|
add_tiles_to_room(room, crumbling)
|
||||||
|
add_walls_to_room(room)
|
||||||
|
add_exits_to_room(room)
|
||||||
|
|
||||||
|
if not crumbling then
|
||||||
|
pitsAdded = layoutparser.add_pits_to_room(room)
|
||||||
|
end
|
||||||
|
if not pitsAdded and (not crumbling or CURRENT_LEVEL > 3) then
|
||||||
|
interiorWallsAdded = layoutparser.add_walls_to_room(room)
|
||||||
|
end
|
||||||
|
|
||||||
|
add_random_decor_to_room(room, not interiorWallsAdded)
|
||||||
|
|
||||||
if room.goal then
|
if room.goal then
|
||||||
add_level_exit(room)
|
add_level_exit(room)
|
||||||
|
@ -440,7 +435,7 @@ local function build_normal_room(room)
|
||||||
elseif (CURRENT_LEVEL > 3 or QUICK_MODE) and random(8) == 1 then
|
elseif (CURRENT_LEVEL > 3 or QUICK_MODE) and random(8) == 1 then
|
||||||
room.modifier.type = "FIRE"
|
room.modifier.type = "FIRE"
|
||||||
room.modifier.arg = ""
|
room.modifier.arg = ""
|
||||||
elseif ((not pitsAdded and (CURRENT_LEVEL > 1 or QUICK_MODE)) or CURRENT_LEVEL > 3) and random(8) == 1 then
|
elseif ((not pitsAdded and not crumbling and (CURRENT_LEVEL > 1 or QUICK_MODE)) or CURRENT_LEVEL > 3) and random(8) == 1 then
|
||||||
directions = { "LEFT", "RIGHT", "UP", "DOWN" }
|
directions = { "LEFT", "RIGHT", "UP", "DOWN" }
|
||||||
room.modifier.type = "WINDY"
|
room.modifier.type = "WINDY"
|
||||||
room.modifier.arg = directions[random(#directions)]
|
room.modifier.arg = directions[random(#directions)]
|
||||||
|
@ -478,6 +473,8 @@ function module.create_empty_room()
|
||||||
path_dir = 0,
|
path_dir = 0,
|
||||||
type = "room",
|
type = "room",
|
||||||
tiles = {},
|
tiles = {},
|
||||||
|
walls = {},
|
||||||
|
doors = {},
|
||||||
decor = {},
|
decor = {},
|
||||||
modifier = {
|
modifier = {
|
||||||
type = nil,
|
type = nil,
|
||||||
|
@ -489,12 +486,16 @@ function module.create_empty_room()
|
||||||
}
|
}
|
||||||
for i=0,15 do
|
for i=0,15 do
|
||||||
room.tiles[i] = {}
|
room.tiles[i] = {}
|
||||||
|
room.walls[i] = {}
|
||||||
|
room.doors[i] = {}
|
||||||
room.decor[i] = {}
|
room.decor[i] = {}
|
||||||
room.monsters[i] = {}
|
room.monsters[i] = {}
|
||||||
room.traps[i] = {}
|
room.traps[i] = {}
|
||||||
room.chests[i] = {}
|
room.chests[i] = {}
|
||||||
for j=0,11 do
|
for j=0,11 do
|
||||||
room.tiles[i][j] = nil
|
room.tiles[i][j] = nil
|
||||||
|
room.walls[i][j] = nil
|
||||||
|
room.doors[i][j] = nil
|
||||||
room.decor[i][j] = nil
|
room.decor[i][j] = nil
|
||||||
room.monsters[i][j] = nil
|
room.monsters[i][j] = nil
|
||||||
room.traps[i][j] = nil
|
room.traps[i][j] = nil
|
||||||
|
@ -504,11 +505,16 @@ function module.create_empty_room()
|
||||||
return room
|
return room
|
||||||
end
|
end
|
||||||
|
|
||||||
function module.build_room(room)
|
function module.build_room(room, roomx, roomy)
|
||||||
if room.type == "coridoor" then
|
if room.type == "coridoor" then
|
||||||
build_coridoor_room(room)
|
build_coridoor_room(room)
|
||||||
|
elseif room.type == "shop" then
|
||||||
|
build_shop_room(room, roomx, roomy)
|
||||||
|
elseif room.type == "locked" then
|
||||||
|
build_locked_room(room, roomx, roomy)
|
||||||
else
|
else
|
||||||
build_normal_room(room)
|
build_normal_room(room)
|
||||||
|
--build_locked_room(room, roomx, roomy)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -518,6 +524,12 @@ function module.load_room(map, room)
|
||||||
if room.tiles[i][j] then
|
if room.tiles[i][j] then
|
||||||
add_tile(map, i, j, repack(room.tiles[i][j]))
|
add_tile(map, i, j, repack(room.tiles[i][j]))
|
||||||
end
|
end
|
||||||
|
if room.walls[i][j] then
|
||||||
|
add_wall(map, i, j, repack(room.walls[i][j]))
|
||||||
|
end
|
||||||
|
if room.doors[i][j] then
|
||||||
|
add_door(map, i, j, repack(room.doors[i][j]))
|
||||||
|
end
|
||||||
if room.decor[i][j] then
|
if room.decor[i][j] then
|
||||||
add_decoration(map, i, j, repack(room.decor[i][j]))
|
add_decoration(map, i, j, repack(room.decor[i][j]))
|
||||||
end
|
end
|
||||||
|
@ -531,15 +543,16 @@ end
|
||||||
function module.load_textures(map)
|
function module.load_textures(map)
|
||||||
t_floor = add_texture(map, "Objects/Floor.png")
|
t_floor = add_texture(map, "Objects/Floor.png")
|
||||||
t_wall = add_texture(map, "Objects/Wall.png")
|
t_wall = add_texture(map, "Objects/Wall.png")
|
||||||
t_pit0 = add_texture(map, "Objects/Pit0.png")
|
|
||||||
t_pit1 = add_texture(map, "Objects/Pit1.png")
|
|
||||||
|
|
||||||
local seed = get_random_seed(CURRENT_LEVEL);
|
local seed = get_random_seed(CURRENT_LEVEL);
|
||||||
info("Map room random seed: " .. seed)
|
info("Map room random seed: " .. seed)
|
||||||
map_randomseed(seed)
|
map_randomseed(seed)
|
||||||
|
|
||||||
local xo = (random(3) - 1) * 112
|
local xo = (random(3) - 1) * 112
|
||||||
local yo = (random(8)) * 48
|
local yo = (random(8)) * 48
|
||||||
|
|
||||||
|
layoutparser.load_textures(map, xo, yo)
|
||||||
|
|
||||||
floor.center = { t_floor, -1, xo + 16, yo + 16, false }
|
floor.center = { t_floor, -1, xo + 16, yo + 16, false }
|
||||||
floor.top = { t_floor, -1, xo + 16, yo + 0, false }
|
floor.top = { t_floor, -1, xo + 16, yo + 0, false }
|
||||||
floor.bottom = { t_floor, -1, xo + 16, yo + 32, false }
|
floor.bottom = { t_floor, -1, xo + 16, yo + 32, false }
|
||||||
|
@ -555,19 +568,6 @@ function module.load_textures(map)
|
||||||
floor.singleright = { t_floor, -1, xo + 96, yo + 16, false }
|
floor.singleright = { t_floor, -1, xo + 96, yo + 16, false }
|
||||||
floor.single = { t_floor, -1, xo + 80, yo + 0, false }
|
floor.single = { t_floor, -1, xo + 80, yo + 0, false }
|
||||||
|
|
||||||
local pit_yo = (random(5) + random(3)) * (16 * 2)
|
|
||||||
pits.topleft = { t_pit0, t_pit1, 0, pit_yo, false, false, false, true }
|
|
||||||
pits.top = { t_pit0, t_pit1, 16, pit_yo, false, false, false, true }
|
|
||||||
pits.topright = { t_pit0, t_pit1, 32, pit_yo, false, false, false, true }
|
|
||||||
pits.left = { t_pit0, t_pit1, 0, pit_yo + 16, false, false, false, true }
|
|
||||||
pits.center = { t_pit0, t_pit1, 16, pit_yo + 16, false, false, false, true }
|
|
||||||
pits.right = { t_pit0, t_pit1, 32, pit_yo + 16, false, false, false, true }
|
|
||||||
pits.innerleft = { t_pit0, t_pit1, 80, pit_yo, false, false, false, true }
|
|
||||||
pits.innermid = { t_pit0, t_pit1, 96, pit_yo, false, false, false, true }
|
|
||||||
pits.innerright = { t_pit0, t_pit1, 112, pit_yo, false, false, false, true }
|
|
||||||
pits.topcrevice = { t_pit0, t_pit1, 64, pit_yo, false, false, false, true }
|
|
||||||
pits.bottomcrevice = { t_pit0, t_pit1, 64, pit_yo + 16, false, false, false, true }
|
|
||||||
|
|
||||||
wall.topleft = { t_wall, -1, xo + 0, yo + 0, true }
|
wall.topleft = { t_wall, -1, xo + 0, yo + 0, true }
|
||||||
wall.topright = { t_wall, -1, xo + 32, yo + 0, true }
|
wall.topright = { t_wall, -1, xo + 32, yo + 0, true }
|
||||||
wall.bottomleft = { t_wall, -1, xo + 0, yo + 32, true }
|
wall.bottomleft = { t_wall, -1, xo + 0, yo + 32, true }
|
||||||
|
|
|
@ -9,7 +9,7 @@ room_builder.load_textures(map)
|
||||||
|
|
||||||
set_current_room(map, 0, 0)
|
set_current_room(map, 0, 0)
|
||||||
local room = room_builder.create_empty_room()
|
local room = room_builder.create_empty_room()
|
||||||
room_builder.build_room(room)
|
room_builder.build_room(room, 0, 0)
|
||||||
room_builder.add_full_lighting(room)
|
room_builder.add_full_lighting(room)
|
||||||
monster_gen.add_monsters_to_room(room, 0, 0)
|
monster_gen.add_monsters_to_room(room, 0, 0)
|
||||||
trap_gen.add_traps_to_room(room, 0, 0)
|
trap_gen.add_traps_to_room(room, 0, 0)
|
||||||
|
|
|
@ -106,7 +106,14 @@ local stats = {
|
||||||
atk = 0,
|
atk = 0,
|
||||||
def = 0,
|
def = 0,
|
||||||
speed = 1
|
speed = 1
|
||||||
}
|
},
|
||||||
|
shopkeeper = {
|
||||||
|
hp = 200,
|
||||||
|
dmg = 10,
|
||||||
|
atk = 2,
|
||||||
|
def = 0,
|
||||||
|
speed = 1
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
local function concat(table1, table2)
|
local function concat(table1, table2)
|
||||||
|
@ -162,6 +169,18 @@ for i=1,#misc do
|
||||||
misc[i] = concat({ texturePaths.misc0, texturePaths.misc1 }, misc[i])
|
misc[i] = concat({ texturePaths.misc0, texturePaths.misc1 }, misc[i])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local fairies = {
|
||||||
|
{ stats.misc, 0, 48, "A Fairy", behaviour.pacifist },
|
||||||
|
{ stats.misc, 16, 48, "A Fairy", behaviour.pacifist },
|
||||||
|
{ stats.misc, 32, 48, "A Fairy", behaviour.pacifist },
|
||||||
|
{ stats.misc, 48, 48, "A Fairy", behaviour.pacifist },
|
||||||
|
{ stats.misc, 64, 48, "A Fairy", behaviour.pacifist },
|
||||||
|
{ stats.misc, 80, 48, "A Fairy", behaviour.pacifist },
|
||||||
|
}
|
||||||
|
for i=1,#fairies do
|
||||||
|
fairies[i] = concat({ texturePaths.humanoid0, texturePaths.humanoid1 }, fairies[i])
|
||||||
|
end
|
||||||
|
|
||||||
local reanimated = {
|
local reanimated = {
|
||||||
{ stats.undead, 0, 32, "A Skeleton", behaviour.normal },
|
{ stats.undead, 0, 32, "A Skeleton", behaviour.normal },
|
||||||
{ stats.undead, 48, 32, "A Black Skeleton", behaviour.normal },
|
{ stats.undead, 48, 32, "A Black Skeleton", behaviour.normal },
|
||||||
|
@ -270,6 +289,31 @@ for i=1,#eastereggs do
|
||||||
eastereggs[i] = concat({ texturePaths.player0, texturePaths.player1 }, eastereggs[i])
|
eastereggs[i] = concat({ texturePaths.player0, texturePaths.player1 }, eastereggs[i])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local shopkeeperBehaviour = behaviour.passive
|
||||||
|
if PlayerData.shopOwnerKiller then
|
||||||
|
shopkeeperBehaviour = behaviour.hostile
|
||||||
|
end
|
||||||
|
|
||||||
|
local shopkeeper = {
|
||||||
|
texturePaths.humanoid0,
|
||||||
|
texturePaths.humanoid1,
|
||||||
|
stats.shopkeeper,
|
||||||
|
16,
|
||||||
|
12*16,
|
||||||
|
"The Trader",
|
||||||
|
shopkeeperBehaviour
|
||||||
|
}
|
||||||
|
|
||||||
|
local bodyguard = {
|
||||||
|
texturePaths.humanoid0,
|
||||||
|
texturePaths.humanoid1,
|
||||||
|
stats.orc,
|
||||||
|
32,
|
||||||
|
12*16,
|
||||||
|
"A Bodyguard",
|
||||||
|
behaviour.hostile
|
||||||
|
}
|
||||||
|
|
||||||
-- Add Platino
|
-- Add Platino
|
||||||
table.insert(eastereggs, {
|
table.insert(eastereggs, {
|
||||||
texturePaths.reptile0,
|
texturePaths.reptile0,
|
||||||
|
@ -327,6 +371,7 @@ if(CURRENT_LEVEL > 0) then
|
||||||
end
|
end
|
||||||
|
|
||||||
local addSpecialInLevel = random(100) == 1
|
local addSpecialInLevel = random(100) == 1
|
||||||
|
local addFairyToLevel = random(3) == 1;
|
||||||
|
|
||||||
local function add_monster_to_tile(room, roomx, roomy, rx, ry, monster)
|
local function add_monster_to_tile(room, roomx, roomy, rx, ry, monster)
|
||||||
local x = (roomx * 512) + rx * 32
|
local x = (roomx * 512) + rx * 32
|
||||||
|
@ -339,7 +384,8 @@ local function add_monster_to_tile(room, roomx, roomy, rx, ry, monster)
|
||||||
end
|
end
|
||||||
|
|
||||||
function module.add_monsters_to_room(room, roomx, roomy)
|
function module.add_monsters_to_room(room, roomx, roomy)
|
||||||
local addSpecial = addSpecialInLevel and random(5) == 1
|
local addSpecial = addSpecialInLevel and random(2) == 1
|
||||||
|
local addFairy = random(4) == 1
|
||||||
local count = random(3)
|
local count = random(3)
|
||||||
if (CURRENT_LEVEL > 3) then
|
if (CURRENT_LEVEL > 3) then
|
||||||
count = random(4)
|
count = random(4)
|
||||||
|
@ -354,6 +400,9 @@ function module.add_monsters_to_room(room, roomx, roomy)
|
||||||
addSpecialInLevel = false
|
addSpecialInLevel = false
|
||||||
addSpecial = false
|
addSpecial = false
|
||||||
add_monster_to_tile(room, roomx, roomy, rx, ry, eastereggs[random(#eastereggs)])
|
add_monster_to_tile(room, roomx, roomy, rx, ry, eastereggs[random(#eastereggs)])
|
||||||
|
elseif addFairyToLevel and addFairy then
|
||||||
|
addFairyToLevel = false
|
||||||
|
add_monster_to_tile(room, roomx, roomy, rx, ry, fairies[random(#fairies)])
|
||||||
else
|
else
|
||||||
add_monster_to_tile(room, roomx, roomy, rx, ry, enemies[random(#enemies)])
|
add_monster_to_tile(room, roomx, roomy, rx, ry, enemies[random(#enemies)])
|
||||||
end
|
end
|
||||||
|
@ -384,6 +433,42 @@ function module.add_boss_to_room(room, roomx, roomy)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function module.add_shopkeeper_to_room(room, roomx, roomy)
|
||||||
|
local success = false
|
||||||
|
while not success do
|
||||||
|
local rx = random(13) + 1
|
||||||
|
local ry = random(9) + 1
|
||||||
|
if room_builder.is_tile_avilable(room, rx, ry) then
|
||||||
|
local x = (roomx * 512) + rx * 32
|
||||||
|
local y = (roomy * 384) + ry * 32
|
||||||
|
room.monsters[rx][ry] = {
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
shopkeeper
|
||||||
|
}
|
||||||
|
success = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function module.add_bodyguard_to_room(room, roomx, roomy)
|
||||||
|
local success = false
|
||||||
|
while not success do
|
||||||
|
local rx = random(13) + 1
|
||||||
|
local ry = random(9) + 1
|
||||||
|
if room_builder.is_tile_avilable(room, rx, ry) then
|
||||||
|
local x = (roomx * 512) + rx * 32
|
||||||
|
local y = (roomy * 384) + ry * 32
|
||||||
|
room.monsters[rx][ry] = {
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
bodyguard
|
||||||
|
}
|
||||||
|
success = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function module.load_monsters(map, monsters)
|
function module.load_monsters(map, monsters)
|
||||||
for i=0,15 do
|
for i=0,15 do
|
||||||
for j=0,11 do
|
for j=0,11 do
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
--##--------##--
|
--pp--------pp--
|
||||||
--##--####--##--
|
--pp--pppp--pp--
|
||||||
-------##-------
|
-------pp-------
|
||||||
-------##-------
|
-------pp-------
|
||||||
-------##-------
|
-------pp-------
|
||||||
-------##-------
|
-------pp-------
|
||||||
--##--####--##--
|
--pp--pppp--pp--
|
||||||
--##--------##--
|
--pp--------pp--
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
|
@ -15,11 +15,11 @@
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
-----##-##------
|
-----pp-pp------
|
||||||
-----##-##------
|
-----pp-pp------
|
||||||
----------------
|
----------------
|
||||||
-----##-##------
|
-----pp-pp------
|
||||||
-----##-##------
|
-----pp-pp------
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
|
@ -27,12 +27,12 @@
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
--############--
|
--pppppppppppp--
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
--############--
|
--pppppppppppp--
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
|
@ -40,194 +40,194 @@
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
--############--
|
--pppppppppppp--
|
||||||
----------------
|
----------------
|
||||||
--############--
|
--pppppppppppp--
|
||||||
--############--
|
--pppppppppppp--
|
||||||
----------------
|
----------------
|
||||||
--############--
|
--pppppppppppp--
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
--############--
|
--pppppppppppp--
|
||||||
--############--
|
--pppppppppppp--
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
--############--
|
--pppppppppppp--
|
||||||
--############--
|
--pppppppppppp--
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
-------#--------
|
-------p--------
|
||||||
------###-------
|
------ppp-------
|
||||||
-------#--------
|
-------p--------
|
||||||
------###-------
|
------ppp-------
|
||||||
------###-------
|
------ppp-------
|
||||||
-------#--------
|
-------p--------
|
||||||
------###-------
|
------ppp-------
|
||||||
-------#--------
|
-------p--------
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
--############--
|
--pppppppppppp--
|
||||||
--#----------#--
|
--p----------p--
|
||||||
--#----------#--
|
--p----------p--
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
--#----------#--
|
--p----------p--
|
||||||
--#----------#--
|
--p----------p--
|
||||||
--############--
|
--pppppppppppp--
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
--############--
|
--pppppppppppp--
|
||||||
--#----------#--
|
--p----------p--
|
||||||
--#-########-#--
|
--p-pppppppp-p--
|
||||||
----#-----------
|
----p-----------
|
||||||
-----------#----
|
-----------p----
|
||||||
--#-########-#--
|
--p-pppppppp-p--
|
||||||
--#----------#--
|
--p----------p--
|
||||||
--############--
|
--pppppppppppp--
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
--############--
|
--pppppppppppp--
|
||||||
--#----------#--
|
--p----------p--
|
||||||
--#-###-####-#--
|
--p-ppp-pppp-p--
|
||||||
----###---##----
|
----ppp---pp----
|
||||||
----#####-##----
|
----ppppp-pp----
|
||||||
--#-#####-##-#--
|
--p-ppppp-pp-p--
|
||||||
--#----------#--
|
--p----------p--
|
||||||
--############--
|
--pppppppppppp--
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
--##--------##--
|
--pp--------pp--
|
||||||
--##--------##--
|
--pp--------pp--
|
||||||
----------------
|
----------------
|
||||||
-------##-------
|
-------pp-------
|
||||||
-------##-------
|
-------pp-------
|
||||||
--#----------#--
|
--p----------p--
|
||||||
--#----------#--
|
--p----------p--
|
||||||
--############--
|
--pppppppppppp--
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
--##--------##--
|
--pp--------pp--
|
||||||
--##--------##--
|
--pp--------pp--
|
||||||
----------------
|
----------------
|
||||||
-------##-------
|
-------pp-------
|
||||||
-------##-------
|
-------pp-------
|
||||||
----------------
|
----------------
|
||||||
--##--------##--
|
--pp--------pp--
|
||||||
--##--------##--
|
--pp--------pp--
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
--##--------##--
|
--pp--------pp--
|
||||||
--##--------##--
|
--pp--------pp--
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
--##--------##--
|
--pp--------pp--
|
||||||
--##--------##--
|
--pp--------pp--
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
--##---##---##--
|
--pp---pp---pp--
|
||||||
--##---##---##--
|
--pp---pp---pp--
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
--##---##---##--
|
--pp---pp---pp--
|
||||||
--##---##---##--
|
--pp---pp---pp--
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
--##---##---##--
|
--pp---pp---pp--
|
||||||
--##---##---##--
|
--pp---pp---pp--
|
||||||
----------------
|
----------------
|
||||||
--##---##---##--
|
--pp---pp---pp--
|
||||||
--##---##---##--
|
--pp---pp---pp--
|
||||||
----------------
|
----------------
|
||||||
--##---##---##--
|
--pp---pp---pp--
|
||||||
--##---##---##--
|
--pp---pp---pp--
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
---#----#----#--
|
---p----p----p--
|
||||||
--##---##---##--
|
--pp---pp---pp--
|
||||||
----------------
|
----------------
|
||||||
---#----#----#--
|
---p----p----p--
|
||||||
--##---##---##--
|
--pp---pp---pp--
|
||||||
----------------
|
----------------
|
||||||
---#----#----#--
|
---p----p----p--
|
||||||
--##---##---##--
|
--pp---pp---pp--
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
--##---##---##--
|
--pp---pp---pp--
|
||||||
--#----------#--
|
--p----------p--
|
||||||
----------------
|
----------------
|
||||||
--#----##----#--
|
--p----pp----p--
|
||||||
--#----##----#--
|
--p----pp----p--
|
||||||
----------------
|
----------------
|
||||||
--#----------#--
|
--p----------p--
|
||||||
--##---##---##--
|
--pp---pp---pp--
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
--##---##---##--
|
--pp---pp---pp--
|
||||||
--#----------#--
|
--p----------p--
|
||||||
----------------
|
----------------
|
||||||
--#----------#--
|
--p----------p--
|
||||||
--#----------#--
|
--p----------p--
|
||||||
----------------
|
----------------
|
||||||
--#----------#--
|
--p----------p--
|
||||||
--##---##---##--
|
--pp---pp---pp--
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
--##---##---##--
|
--pp---pp---pp--
|
||||||
--#----------#--
|
--p----------p--
|
||||||
-----##--##-----
|
-----pp--pp-----
|
||||||
--#--#----#--#--
|
--p--p----p--p--
|
||||||
--#--#----#--#--
|
--p--p----p--p--
|
||||||
-----##--##-----
|
-----pp--pp-----
|
||||||
--#----------#--
|
--p----------p--
|
||||||
--##---##---##--
|
--pp---pp---pp--
|
||||||
----------------
|
----------------
|
||||||
----------------
|
----------------
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
++##ffffffff##++
|
||||||
|
++#"--------"#++
|
||||||
|
++f---a--a---f++
|
||||||
|
++-----------f++
|
||||||
|
++-----------f++
|
||||||
|
++f---a--a---f++
|
||||||
|
++#"--------"#++
|
||||||
|
++##ffffffff##++
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
++ffff----ffff++
|
||||||
|
++fppf-a--fppf++
|
||||||
|
++ffff--l-ffff++
|
||||||
|
++------a-----++
|
||||||
|
++------------++
|
||||||
|
++ffff-a--ffff++
|
||||||
|
++fppf-l--fppf++
|
||||||
|
++ffff--a-ffff++
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
++###########"++
|
||||||
|
++#----------#++
|
||||||
|
++#-####"###-#++
|
||||||
|
++--#aa--aa#-#++
|
||||||
|
++--#--------#++
|
||||||
|
++#-####"###-#++
|
||||||
|
++#----------#++
|
||||||
|
++"###########++
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
++--pppppppp--++
|
||||||
|
++--pffffffp--++
|
||||||
|
++--pfl--afp--++
|
||||||
|
++-------afp--++
|
||||||
|
++-------afp--++
|
||||||
|
++--pfl--afp--++
|
||||||
|
++--pffffffp--++
|
||||||
|
++--pppppppp--++
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
++pppppppppppp++
|
||||||
|
++ppffffffffpp++
|
||||||
|
++fffa----afff++
|
||||||
|
++------l-----++
|
||||||
|
++-----l------++
|
||||||
|
++fffa----afff++
|
||||||
|
++ppffffffffpp++
|
||||||
|
++pppppppppppp++
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
|
@ -0,0 +1,90 @@
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
++/#--------#/++
|
||||||
|
++##--------##++
|
||||||
|
++------------++
|
||||||
|
++------------++
|
||||||
|
++------------++
|
||||||
|
++------------++
|
||||||
|
++##--------##++
|
||||||
|
++/#--------#/++
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
++#--#-#-#-#-#++
|
||||||
|
++---c--------++
|
||||||
|
++/-#-#-#-#--/++
|
||||||
|
++-------c----++
|
||||||
|
++/--#-#-#-#-/++
|
||||||
|
++------------++
|
||||||
|
++--#-#-#-#---++
|
||||||
|
++#-########-#++
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
++############++
|
||||||
|
++#----------#++
|
||||||
|
++#-/#######-#++
|
||||||
|
++--#------#-#++
|
||||||
|
++--d--cc--d-#++
|
||||||
|
++#-/#######-#++
|
||||||
|
++#----------#++
|
||||||
|
++############++
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
++/#--------#/++
|
||||||
|
++##-ffffdf-##++
|
||||||
|
++---f--c-f---++
|
||||||
|
++---f----f---++
|
||||||
|
++---f-c--f---++
|
||||||
|
++---f----f---++
|
||||||
|
++##-fdffff-##++
|
||||||
|
++/#--------#/++
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
++/#ffffffff#/++
|
||||||
|
++#----------#++
|
||||||
|
++---######---++
|
||||||
|
++---d----#---++
|
||||||
|
++---#-cc-d---++
|
||||||
|
++---######---++
|
||||||
|
++#----------#++
|
||||||
|
++/#ffffffff#/++
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
++/##########/++
|
||||||
|
++d-----d----d++
|
||||||
|
++#c----#---c#++
|
||||||
|
++############++
|
||||||
|
++#----#-----#++
|
||||||
|
++#-c--d--c--#++
|
||||||
|
++d----#-----d++
|
||||||
|
++/##########/++
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
||||||
|
++/####-#####/++
|
||||||
|
++#--c#-#c---#++
|
||||||
|
++d---#-#----d++
|
||||||
|
++#####-######++
|
||||||
|
++------------++
|
||||||
|
++#####-######++
|
||||||
|
++d--c#-#c---d++
|
||||||
|
++/####-#####/++
|
||||||
|
++++++++++++++++
|
||||||
|
++++++++++++++++
|
|
@ -9,7 +9,7 @@
|
||||||
# compile, using preprocessor checks for platform-specific bits instead of
|
# compile, using preprocessor checks for platform-specific bits instead of
|
||||||
# testing in here.
|
# testing in here.
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 2.8.4)
|
cmake_minimum_required(VERSION 3.6)
|
||||||
|
|
||||||
project(PhysicsFS)
|
project(PhysicsFS)
|
||||||
set(PHYSFS_VERSION 3.0.1)
|
set(PHYSFS_VERSION 3.0.1)
|
||||||
|
|
Binary file not shown.
|
@ -47,7 +47,7 @@ actiontext_render(ActionText *t, Camera *cam)
|
||||||
if (t->dead)
|
if (t->dead)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!t->dead && !timer_started(t->timer))
|
if (!timer_started(t->timer))
|
||||||
timer_start(t->timer);
|
timer_start(t->timer);
|
||||||
|
|
||||||
if (timer_get_ticks(t->timer) < 500) {
|
if (timer_get_ticks(t->timer) < 500) {
|
||||||
|
|
|
@ -32,7 +32,7 @@ actiontextbuilder_init(SDL_Renderer *renderer)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
actiontextbuilder_create_text(const char *msg, SDL_Color color, Position *p)
|
actiontextbuilder_create_text(const char *msg, SDL_Color color, const Position *p)
|
||||||
{
|
{
|
||||||
assert (gRenderer != NULL);
|
assert (gRenderer != NULL);
|
||||||
Sprite *sprite = sprite_create();
|
Sprite *sprite = sprite_create();
|
||||||
|
|
|
@ -34,7 +34,7 @@ void
|
||||||
actiontextbuilder_render(Camera*);
|
actiontextbuilder_render(Camera*);
|
||||||
|
|
||||||
void
|
void
|
||||||
actiontextbuilder_create_text(const char *msg, SDL_Color, Position*);
|
actiontextbuilder_create_text(const char *msg, SDL_Color, const Position*);
|
||||||
|
|
||||||
void
|
void
|
||||||
actiontextbuilder_close(void);
|
actiontextbuilder_close(void);
|
||||||
|
|
|
@ -86,7 +86,7 @@ animation_render(Animation *animation, Camera *camera)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
animation_set_frames(Animation *animation, AnimationClip clips[])
|
animation_set_frames(Animation *animation, const AnimationClip clips[])
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < animation->clipCount; i++) {
|
for (size_t i = 0; i < animation->clipCount; i++) {
|
||||||
animation->clips[i] = clips[i];
|
animation->clips[i] = clips[i];
|
||||||
|
|
|
@ -53,7 +53,7 @@ void
|
||||||
animation_load_texture(Animation *, const char *path, SDL_Renderer*);
|
animation_load_texture(Animation *, const char *path, SDL_Renderer*);
|
||||||
|
|
||||||
void
|
void
|
||||||
animation_set_frames(Animation*, AnimationClip clips[]);
|
animation_set_frames(Animation*, const AnimationClip clips[]);
|
||||||
|
|
||||||
void
|
void
|
||||||
animation_run(Animation*);
|
animation_run(Animation*);
|
||||||
|
|
154
src/artifact.c
154
src/artifact.c
|
@ -22,6 +22,7 @@
|
||||||
#include "particle_engine.h"
|
#include "particle_engine.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
|
#include "sprite_util.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
artifact_set_effect(Artifact *a, MagicalEffect effect)
|
artifact_set_effect(Artifact *a, MagicalEffect effect)
|
||||||
|
@ -64,6 +65,21 @@ artifact_set_effect(Artifact *a, MagicalEffect effect)
|
||||||
a->info.name = "Shadow cloak";
|
a->info.name = "Shadow cloak";
|
||||||
a->info.desc = "You feel more in phase with the world";
|
a->info.desc = "You feel more in phase with the world";
|
||||||
break;
|
break;
|
||||||
|
case SKILL_RADIUS:
|
||||||
|
a->info.name = "Magic wand";
|
||||||
|
a->info.desc = "Your magic has greater reach";
|
||||||
|
break;
|
||||||
|
case DAGGER_BOUNCE:
|
||||||
|
a->info.name = "Magnet";
|
||||||
|
a->info.desc = "You are attractive to daggers";
|
||||||
|
break;
|
||||||
|
case EXPLOSIVE_KILLS:
|
||||||
|
a->info.name = "Stick of dynamite";
|
||||||
|
a->info.desc = "You are an explosive slayer";
|
||||||
|
break;
|
||||||
|
case VOLATILE_DAGGERS:
|
||||||
|
a->info.name = "Glowing dagger";
|
||||||
|
a->info.desc = "Your daggers are volatile";
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -77,7 +93,10 @@ static int WarriorArtifacts[] = {
|
||||||
PUSH_BACK, // 4
|
PUSH_BACK, // 4
|
||||||
FEAR_INDUCING, // 5
|
FEAR_INDUCING, // 5
|
||||||
INCREASED_STUN, // 6
|
INCREASED_STUN, // 6
|
||||||
CHARGE_THROUGH // 7
|
DAGGER_BOUNCE, // 7
|
||||||
|
EXPLOSIVE_KILLS, // 8
|
||||||
|
VOLATILE_DAGGERS, // 9
|
||||||
|
CHARGE_THROUGH // 10
|
||||||
};
|
};
|
||||||
|
|
||||||
static int RogueArtifacts[] = {
|
static int RogueArtifacts[] = {
|
||||||
|
@ -88,31 +107,109 @@ static int RogueArtifacts[] = {
|
||||||
PUSH_BACK, // 4
|
PUSH_BACK, // 4
|
||||||
FEAR_INDUCING, // 5
|
FEAR_INDUCING, // 5
|
||||||
INCREASED_STUN, // 6
|
INCREASED_STUN, // 6
|
||||||
PHASE_IMPROVEMENT // 7
|
DAGGER_BOUNCE, // 7
|
||||||
|
EXPLOSIVE_KILLS, // 8
|
||||||
|
VOLATILE_DAGGERS, // 9
|
||||||
|
PHASE_IMPROVEMENT // 10
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int MageArtifacts[] = {
|
||||||
|
IMPROVED_HEARING, // 0
|
||||||
|
TRAP_AVOIDANCE, // 1
|
||||||
|
PIERCING_DAGGERS, // 2
|
||||||
|
DAGGER_RECOVERY, // 3
|
||||||
|
PUSH_BACK, // 4
|
||||||
|
FEAR_INDUCING, // 5
|
||||||
|
INCREASED_STUN, // 6
|
||||||
|
DAGGER_BOUNCE, // 7
|
||||||
|
EXPLOSIVE_KILLS, // 8
|
||||||
|
VOLATILE_DAGGERS, // 9
|
||||||
|
SKILL_RADIUS // 10
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Not in play yet */
|
||||||
|
static int PaladinArtifacts[] = {
|
||||||
|
IMPROVED_HEARING, // 0
|
||||||
|
TRAP_AVOIDANCE, // 1
|
||||||
|
PIERCING_DAGGERS, // 2
|
||||||
|
DAGGER_RECOVERY, // 3
|
||||||
|
PUSH_BACK, // 4
|
||||||
|
FEAR_INDUCING, // 5
|
||||||
|
INCREASED_STUN, // 6
|
||||||
|
DAGGER_BOUNCE, // 7
|
||||||
|
EXPLOSIVE_KILLS, // 8
|
||||||
|
VOLATILE_DAGGERS, // 9
|
||||||
|
SKILL_RADIUS // 10
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Not in play yet */
|
||||||
|
static int EngineerArtifacts[] = {
|
||||||
|
IMPROVED_HEARING, // 0
|
||||||
|
TRAP_AVOIDANCE, // 1
|
||||||
|
PIERCING_DAGGERS, // 2
|
||||||
|
DAGGER_RECOVERY, // 3
|
||||||
|
PUSH_BACK, // 4
|
||||||
|
FEAR_INDUCING, // 5
|
||||||
|
INCREASED_STUN, // 6
|
||||||
|
DAGGER_BOUNCE, // 7
|
||||||
|
EXPLOSIVE_KILLS, // 8
|
||||||
|
VOLATILE_DAGGERS, // 9
|
||||||
|
PHASE_IMPROVEMENT // 10
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_level_sprite(Artifact *a)
|
||||||
|
{
|
||||||
|
Sprite *sprite = sprite_util_create_text_sprite("GUI/SDS_8x8.ttf",
|
||||||
|
8,
|
||||||
|
C_BLUE,
|
||||||
|
C_BLACK,
|
||||||
|
"%u",
|
||||||
|
a->level);
|
||||||
|
sprite->pos = a->sprite->pos;
|
||||||
|
sprite->offset = POS(32 - sprite->dim.width, 32 - sprite->dim.height);
|
||||||
|
a->levelSprite = sprite;
|
||||||
|
}
|
||||||
|
|
||||||
Artifact *
|
Artifact *
|
||||||
artifact_create_random(Player *p, Uint8 level)
|
artifact_create_random(Player *p, Uint8 level)
|
||||||
{
|
{
|
||||||
int option = -1;
|
int option = get_random(9);
|
||||||
if (p->stats.lvl >= 4)
|
|
||||||
option = get_random(7);
|
|
||||||
else if (p->stats.lvl >= 3)
|
|
||||||
option = get_random(6);
|
|
||||||
else
|
|
||||||
option = get_random(5);
|
|
||||||
|
|
||||||
int * artifactPool = NULL;
|
int * artifactPool = NULL;
|
||||||
if (p->class == ROGUE)
|
if (p->class == ROGUE)
|
||||||
artifactPool = RogueArtifacts;
|
artifactPool = RogueArtifacts;
|
||||||
|
else if (p->class == MAGE)
|
||||||
|
artifactPool = MageArtifacts;
|
||||||
|
else if (p->class == PALADIN)
|
||||||
|
artifactPool = PaladinArtifacts;
|
||||||
|
else if (p->class == ENGINEER)
|
||||||
|
artifactPool = EngineerArtifacts;
|
||||||
else
|
else
|
||||||
artifactPool = WarriorArtifacts;
|
artifactPool = WarriorArtifacts;
|
||||||
|
|
||||||
Artifact *a = artifact_create(artifactPool[option]);
|
Artifact *a = artifact_create(artifactPool[option]);
|
||||||
a->level = level;
|
a->level = level;
|
||||||
|
if (level > 1)
|
||||||
|
add_level_sprite(a);
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
artifact_add_price(Artifact *a, unsigned int price)
|
||||||
|
{
|
||||||
|
|
||||||
|
Sprite *sprite = sprite_util_create_text_sprite("GUI/SDS_8x8.ttf",
|
||||||
|
8,
|
||||||
|
C_YELLOW,
|
||||||
|
C_BLACK,
|
||||||
|
"$%u",
|
||||||
|
price);
|
||||||
|
sprite->pos = a->sprite->pos;
|
||||||
|
a->price = price;
|
||||||
|
a->priceSprite = sprite;
|
||||||
|
}
|
||||||
|
|
||||||
Sprite *
|
Sprite *
|
||||||
artifact_sprite_for(MagicalEffect effect)
|
artifact_sprite_for(MagicalEffect effect)
|
||||||
{
|
{
|
||||||
|
@ -164,6 +261,26 @@ artifact_sprite_for(MagicalEffect effect)
|
||||||
sprite_set_texture(sprite, t, 0);
|
sprite_set_texture(sprite, t, 0);
|
||||||
sprite->clip = CLIP16(1*16, 5*16);
|
sprite->clip = CLIP16(1*16, 5*16);
|
||||||
break;
|
break;
|
||||||
|
case SKILL_RADIUS:
|
||||||
|
t = texturecache_add("Items/Wand.png");
|
||||||
|
sprite_set_texture(sprite, t, 0);
|
||||||
|
sprite->clip = CLIP16(2*16, 0);
|
||||||
|
break;
|
||||||
|
case DAGGER_BOUNCE:
|
||||||
|
t = texturecache_add("Extras/Artifacts.png");
|
||||||
|
sprite_set_texture(sprite, t, 0);
|
||||||
|
sprite->clip = CLIP16(0, 0);
|
||||||
|
break;
|
||||||
|
case EXPLOSIVE_KILLS:
|
||||||
|
t = texturecache_add("Extras/Artifacts.png");
|
||||||
|
sprite_set_texture(sprite, t, 0);
|
||||||
|
sprite->clip = CLIP16(32, 0);
|
||||||
|
break;
|
||||||
|
case VOLATILE_DAGGERS:
|
||||||
|
t = texturecache_add("Extras/Artifacts.png");
|
||||||
|
sprite_set_texture(sprite, t, 0);
|
||||||
|
sprite->clip = CLIP16(16, 0);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -175,15 +292,18 @@ artifact_create(MagicalEffect effect)
|
||||||
{
|
{
|
||||||
Artifact *a = ec_malloc(sizeof(Artifact));
|
Artifact *a = ec_malloc(sizeof(Artifact));
|
||||||
a->sprite = artifact_sprite_for(effect);
|
a->sprite = artifact_sprite_for(effect);
|
||||||
|
a->priceSprite = NULL;
|
||||||
|
a->levelSprite = NULL;
|
||||||
a->sprite->dim = GAME_DIMENSION;
|
a->sprite->dim = GAME_DIMENSION;
|
||||||
a->collected = false;
|
a->collected = false;
|
||||||
a->level = 1;
|
a->level = 1;
|
||||||
|
a->price = 0;
|
||||||
artifact_set_effect(a, effect);
|
artifact_set_effect(a, effect);
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
Artifact *
|
Artifact *
|
||||||
artifact_copy(Artifact *a)
|
artifact_copy(const Artifact *a)
|
||||||
{
|
{
|
||||||
Artifact *new = ec_malloc(sizeof(Artifact));
|
Artifact *new = ec_malloc(sizeof(Artifact));
|
||||||
*new = *a;
|
*new = *a;
|
||||||
|
@ -197,12 +317,24 @@ artifact_render(Artifact *a, Camera *cam)
|
||||||
Position pos = a->sprite->pos;
|
Position pos = a->sprite->pos;
|
||||||
pos.x += 4;
|
pos.x += 4;
|
||||||
pos.y += 4;
|
pos.y += 4;
|
||||||
particle_engine_sparkle(pos, (Dimension) { 24, 24 }, C_PURPLE, false);
|
particle_engine_sparkle(pos, DIM(24, 24), C_PURPLE, false);
|
||||||
|
if (a->priceSprite) {
|
||||||
|
a->priceSprite->pos = a->sprite->pos;
|
||||||
|
sprite_render(a->priceSprite, cam);
|
||||||
|
}
|
||||||
|
if (a->levelSprite) {
|
||||||
|
a->levelSprite->pos = a->sprite->pos;
|
||||||
|
sprite_render(a->levelSprite, cam);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
artifact_destroy(Artifact *a)
|
artifact_destroy(Artifact *a)
|
||||||
{
|
{
|
||||||
sprite_destroy(a->sprite);
|
sprite_destroy(a->sprite);
|
||||||
|
if (a->priceSprite)
|
||||||
|
sprite_destroy(a->priceSprite);
|
||||||
|
if (a->levelSprite)
|
||||||
|
sprite_destroy(a->levelSprite);
|
||||||
free(a);
|
free(a);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,10 @@ typedef enum MagicalEffect {
|
||||||
INCREASED_STUN,
|
INCREASED_STUN,
|
||||||
CHARGE_THROUGH,
|
CHARGE_THROUGH,
|
||||||
PHASE_IMPROVEMENT,
|
PHASE_IMPROVEMENT,
|
||||||
|
SKILL_RADIUS,
|
||||||
|
DAGGER_BOUNCE,
|
||||||
|
EXPLOSIVE_KILLS,
|
||||||
|
VOLATILE_DAGGERS,
|
||||||
LAST_ARTIFACT_EFFECT // Sentinel
|
LAST_ARTIFACT_EFFECT // Sentinel
|
||||||
} MagicalEffect;
|
} MagicalEffect;
|
||||||
|
|
||||||
|
@ -40,10 +44,13 @@ typedef struct ArtifactInfo {
|
||||||
|
|
||||||
typedef struct Artifact {
|
typedef struct Artifact {
|
||||||
Sprite *sprite;
|
Sprite *sprite;
|
||||||
|
Sprite *priceSprite;
|
||||||
|
Sprite *levelSprite;
|
||||||
MagicalEffect effect;
|
MagicalEffect effect;
|
||||||
ArtifactInfo info;
|
ArtifactInfo info;
|
||||||
bool collected;
|
bool collected;
|
||||||
int level;
|
int level;
|
||||||
|
unsigned int price;
|
||||||
} Artifact;
|
} Artifact;
|
||||||
|
|
||||||
Sprite *
|
Sprite *
|
||||||
|
@ -52,11 +59,14 @@ artifact_sprite_for(MagicalEffect);
|
||||||
Artifact *
|
Artifact *
|
||||||
artifact_create_random(Player*, Uint8 level);
|
artifact_create_random(Player*, Uint8 level);
|
||||||
|
|
||||||
|
void
|
||||||
|
artifact_add_price(Artifact*, unsigned int price);
|
||||||
|
|
||||||
Artifact *
|
Artifact *
|
||||||
artifact_create(MagicalEffect);
|
artifact_create(MagicalEffect);
|
||||||
|
|
||||||
Artifact *
|
Artifact *
|
||||||
artifact_copy(Artifact*);
|
artifact_copy(const Artifact*);
|
||||||
|
|
||||||
void
|
void
|
||||||
artifact_render(Artifact*, Camera*);
|
artifact_render(Artifact*, Camera*);
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* BreakHack - A dungeone crawler RPG
|
||||||
|
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CONFIG_H_
|
||||||
|
#define CONFIG_H_
|
||||||
|
|
||||||
|
// #cmakedefine _WIN32 ${WIN32}
|
||||||
|
|
||||||
|
#define GAME_TITLE "BreakHack"
|
||||||
|
#define MAJOR_VERSION 4
|
||||||
|
#define MINOR_VERSION 0
|
||||||
|
#define PATCH_VERSION 3
|
||||||
|
#define RELEASE_TYPE ""
|
||||||
|
|
||||||
|
|
||||||
|
/* Checksums */
|
||||||
|
#define SO_LIBSTEAM_CHECKSUM 0x1f5786b
|
||||||
|
#define DLL_LIBSTEAM_CHECKSUM 0x18dba28
|
||||||
|
|
||||||
|
#endif // CONFIG_H_
|
||||||
|
|
|
@ -27,4 +27,9 @@
|
||||||
#define PATCH_VERSION @breakhack_PATCH_VERSION@
|
#define PATCH_VERSION @breakhack_PATCH_VERSION@
|
||||||
#define RELEASE_TYPE "@breakhack_RELEASE_TYPE@"
|
#define RELEASE_TYPE "@breakhack_RELEASE_TYPE@"
|
||||||
|
|
||||||
|
|
||||||
|
/* Checksums */
|
||||||
|
#define SO_LIBSTEAM_CHECKSUM @breakhack_STEAMAPI_SO_CHECKSUM@
|
||||||
|
#define DLL_LIBSTEAM_CHECKSUM @breakhack_STEAMAPI_DLL_CHECKSUM@
|
||||||
|
|
||||||
#endif // CONFIG_H_
|
#endif // CONFIG_H_
|
||||||
|
|
|
@ -67,9 +67,11 @@
|
||||||
#define C_RED (SDL_Color) { 255, 0, 0, 255 }
|
#define C_RED (SDL_Color) { 255, 0, 0, 255 }
|
||||||
#define C_GREEN (SDL_Color) { 0, 255, 0, 255 }
|
#define C_GREEN (SDL_Color) { 0, 255, 0, 255 }
|
||||||
#define C_BLUE (SDL_Color) { 60, 134, 252, 255 }
|
#define C_BLUE (SDL_Color) { 60, 134, 252, 255 }
|
||||||
|
#define C_LIGHTBLUE (SDL_Color) { 143, 178, 234, 255 }
|
||||||
#define C_YELLOW (SDL_Color) { 255, 255, 0, 255 }
|
#define C_YELLOW (SDL_Color) { 255, 255, 0, 255 }
|
||||||
#define C_BLACK (SDL_Color) { 0, 0, 0, 255 }
|
#define C_BLACK (SDL_Color) { 0, 0, 0, 255 }
|
||||||
#define C_PURPLE (SDL_Color) { 137, 16, 229, 255 }
|
#define C_PURPLE (SDL_Color) { 137, 16, 229, 255 }
|
||||||
|
#define C_GREY (SDL_Color) { 89, 89, 89, 255 }
|
||||||
|
|
||||||
// MSVC seems to have min/max defined.
|
// MSVC seems to have min/max defined.
|
||||||
// Haven't looked into it further.
|
// Haven't looked into it further.
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* BreakHack - A dungeone crawler RPG
|
||||||
|
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef enum DoorLockType {
|
||||||
|
LOCK_NONE,
|
||||||
|
LOCK_SILVER,
|
||||||
|
LOCK_GOLD
|
||||||
|
} DoorLockType;
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* BreakHack - A dungeone crawler RPG
|
||||||
|
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gui.h"
|
||||||
|
#include "monster.h"
|
||||||
|
#include "roommatrix.h"
|
||||||
|
#include "effect_util.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
effect_damage_surroundings(Position *pos,
|
||||||
|
RoomMatrix *rm,
|
||||||
|
Player *player,
|
||||||
|
Stats *attackerStats,
|
||||||
|
unsigned int radius,
|
||||||
|
unsigned int pushRadius,
|
||||||
|
bool damagePlayer)
|
||||||
|
{
|
||||||
|
Position roomPos = position_to_matrix_coords(pos);
|
||||||
|
for (Sint32 i = -radius; i <= (Sint32) radius; ++i) {
|
||||||
|
for (Sint32 j = -radius; j <= (Sint32) radius; ++j) {
|
||||||
|
if (i == 0 && j == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Position matrixPos = POS(roomPos.x + i, roomPos.y + j);
|
||||||
|
if (!position_in_roommatrix(&matrixPos))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
RoomSpace *r = &rm->spaces[matrixPos.x][matrixPos.y];
|
||||||
|
if (r->monster) {
|
||||||
|
CombatResult result = stats_fight(attackerStats, &r->monster->stats);
|
||||||
|
monster_hit(r->monster, result.dmg, result.critical);
|
||||||
|
gui_log("%s takes %d damage from the explosion", r->monster->label, result.dmg);
|
||||||
|
|
||||||
|
Vector2d dir = vector2d_to_direction(&VEC2D((float) i, (float) j));
|
||||||
|
for (unsigned int k = 0; k < pushRadius; ++k) {
|
||||||
|
monster_push(r->monster,
|
||||||
|
player,
|
||||||
|
rm,
|
||||||
|
dir);
|
||||||
|
}
|
||||||
|
} else if (r->player && damagePlayer) {
|
||||||
|
CombatResult result = stats_fight(attackerStats, &r->player->stats);
|
||||||
|
player_hit(r->player, result.dmg);
|
||||||
|
gui_log("You take %d damage from the explosion", result.dmg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* BreakHack - A dungeone crawler RPG
|
||||||
|
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "roommatrix.h"
|
||||||
|
#include "position.h"
|
||||||
|
#include "stats.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
effect_damage_surroundings(Position *pos,
|
||||||
|
RoomMatrix *rm,
|
||||||
|
Player *player,
|
||||||
|
Stats *attackerStats,
|
||||||
|
unsigned int radius,
|
||||||
|
unsigned int pushRadius,
|
||||||
|
bool damagePlayer);
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* BreakHack - A dungeone crawler RPG
|
||||||
|
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "event.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "linkedlist.h"
|
||||||
|
|
||||||
|
static LinkedList *callbacks = NULL;
|
||||||
|
|
||||||
|
void
|
||||||
|
event_register_listener(EventCallback cb)
|
||||||
|
{
|
||||||
|
// Cast a pointer to a pointer to avoid -wpedantic iso warning
|
||||||
|
linkedlist_append(&callbacks, *(void**)(&cb));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
event_clear_listeners(void)
|
||||||
|
{
|
||||||
|
while (callbacks)
|
||||||
|
linkedlist_pop(&callbacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
event_trigger(Event *event)
|
||||||
|
{
|
||||||
|
LinkedList *cbs = callbacks;
|
||||||
|
while (cbs) {
|
||||||
|
// Reverse the cast from the register (-pedantic ISO warning)
|
||||||
|
(*(EventCallback*)(&cbs->data))(event);
|
||||||
|
cbs = cbs->next;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* BreakHack - A dungeone crawler RPG
|
||||||
|
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "player.h"
|
||||||
|
|
||||||
|
typedef enum EventType {
|
||||||
|
MONSTER_KILLED_EVENT
|
||||||
|
} EventType;
|
||||||
|
|
||||||
|
typedef struct MonsterKilledEvent {
|
||||||
|
EventType *type;
|
||||||
|
Player *player;
|
||||||
|
Monster *monster;
|
||||||
|
} MonsterKilledEvent;
|
||||||
|
|
||||||
|
typedef union Event {
|
||||||
|
EventType type;
|
||||||
|
MonsterKilledEvent monsterKilled;
|
||||||
|
} Event;
|
||||||
|
|
||||||
|
typedef void (*EventCallback)(Event*);
|
||||||
|
|
||||||
|
void
|
||||||
|
event_register_listener(EventCallback cb);
|
||||||
|
|
||||||
|
void
|
||||||
|
event_clear_listeners(void);
|
||||||
|
|
||||||
|
void
|
||||||
|
event_trigger(Event *event);
|
70
src/gui.c
70
src/gui.c
|
@ -112,21 +112,21 @@ init_sprites(Gui *gui, Camera *cam)
|
||||||
linkedlist_append(&gui->sprites, create_xp_sprite(
|
linkedlist_append(&gui->sprites, create_xp_sprite(
|
||||||
t,
|
t,
|
||||||
(SDL_Rect) { 6 * 16, 0, 16, 16 },
|
(SDL_Rect) { 6 * 16, 0, 16, 16 },
|
||||||
(Position) { 16, POS_Y_XPBAR }
|
POS(16, POS_Y_XPBAR)
|
||||||
));
|
));
|
||||||
|
|
||||||
// Right end
|
// Right end
|
||||||
linkedlist_append(&gui->sprites, create_xp_sprite(
|
linkedlist_append(&gui->sprites, create_xp_sprite(
|
||||||
t,
|
t,
|
||||||
(SDL_Rect) { 8 * 16, 0, 16, 16 },
|
(SDL_Rect) { 8 * 16, 0, 16, 16 },
|
||||||
(Position) { 16 + (16 * 7), POS_Y_XPBAR }
|
POS(16 + (16 * 7), POS_Y_XPBAR)
|
||||||
));
|
));
|
||||||
|
|
||||||
for (i = 1; i < 7; ++i) {
|
for (i = 1; i < 7; ++i) {
|
||||||
linkedlist_append(&gui->sprites, create_xp_sprite(
|
linkedlist_append(&gui->sprites, create_xp_sprite(
|
||||||
t,
|
t,
|
||||||
(SDL_Rect) { 7 * 16, 0, 16, 16 },
|
(SDL_Rect) { 7 * 16, 0, 16, 16 },
|
||||||
(Position) { 16 + (i * 16), POS_Y_XPBAR }
|
POS(16 + (i * 16), POS_Y_XPBAR)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ init_sprites(Gui *gui, Camera *cam)
|
||||||
linkedlist_append(&gui->xp_bar, create_xp_sprite(
|
linkedlist_append(&gui->xp_bar, create_xp_sprite(
|
||||||
t,
|
t,
|
||||||
(SDL_Rect) { 6 * 16, 4 * 16, 16, 16 },
|
(SDL_Rect) { 6 * 16, 4 * 16, 16, 16 },
|
||||||
(Position) { 16 + (i * 16), POS_Y_XPBAR }
|
POS(16 + (i * 16), POS_Y_XPBAR)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ init_sprites(Gui *gui, Camera *cam)
|
||||||
s->fixed = true;
|
s->fixed = true;
|
||||||
sprite_set_texture(s, t, 0);
|
sprite_set_texture(s, t, 0);
|
||||||
s->clip = CLIP16(0, 0);
|
s->clip = CLIP16(0, 0);
|
||||||
s->pos = (Position) { 16, POS_Y_COLLECTABLES };
|
s->pos = POS(16, POS_Y_COLLECTABLES);
|
||||||
linkedlist_append(&gui->sprites, s);
|
linkedlist_append(&gui->sprites, s);
|
||||||
|
|
||||||
t = texturecache_add("Items/Money.png");
|
t = texturecache_add("Items/Money.png");
|
||||||
|
@ -152,7 +152,7 @@ init_sprites(Gui *gui, Camera *cam)
|
||||||
s->fixed = true;
|
s->fixed = true;
|
||||||
sprite_set_texture(s, t, 0);
|
sprite_set_texture(s, t, 0);
|
||||||
s->clip = CLIP16(16, 16);
|
s->clip = CLIP16(16, 16);
|
||||||
s->pos = (Position) { 16, POS_Y_COLLECTABLES + 16 };
|
s->pos = POS(16, POS_Y_COLLECTABLES + 16);
|
||||||
linkedlist_append(&gui->sprites, s);
|
linkedlist_append(&gui->sprites, s);
|
||||||
|
|
||||||
t = texturecache_add("Items/ShortWep.png");
|
t = texturecache_add("Items/ShortWep.png");
|
||||||
|
@ -160,9 +160,25 @@ init_sprites(Gui *gui, Camera *cam)
|
||||||
s->fixed = true;
|
s->fixed = true;
|
||||||
sprite_set_texture(s, t, 0);
|
sprite_set_texture(s, t, 0);
|
||||||
s->clip = CLIP16(0, 0);
|
s->clip = CLIP16(0, 0);
|
||||||
s->pos = (Position) { 16, POS_Y_COLLECTABLES + 32 };
|
s->pos = POS(16, POS_Y_COLLECTABLES + 32);
|
||||||
linkedlist_append(&gui->sprites, s);
|
linkedlist_append(&gui->sprites, s);
|
||||||
|
|
||||||
|
t = texturecache_add("Extras/Keys.png");
|
||||||
|
s = sprite_create();
|
||||||
|
s->fixed = true;
|
||||||
|
sprite_set_texture(s, t, 0);
|
||||||
|
s->clip = CLIP16(0, 0);
|
||||||
|
s->pos = POS(58, POS_Y_XPBAR + 15 + (3*14));
|
||||||
|
gui->silverKey = s;
|
||||||
|
|
||||||
|
t = texturecache_add("Extras/Keys.png");
|
||||||
|
s = sprite_create();
|
||||||
|
s->fixed = true;
|
||||||
|
sprite_set_texture(s, t, 0);
|
||||||
|
s->clip = CLIP16(16, 0);
|
||||||
|
s->pos = POS(74, POS_Y_XPBAR + 15 + (3*14));
|
||||||
|
gui->goldKey = s;
|
||||||
|
|
||||||
gui->statsFrame = gui_util_create_frame_sprite(RIGHT_GUI_WIDTH/16,
|
gui->statsFrame = gui_util_create_frame_sprite(RIGHT_GUI_WIDTH/16,
|
||||||
STATS_GUI_HEIGHT/16,
|
STATS_GUI_HEIGHT/16,
|
||||||
cam);
|
cam);
|
||||||
|
@ -173,6 +189,10 @@ init_sprites(Gui *gui, Camera *cam)
|
||||||
gui->miniMapFrame = gui_util_create_frame_sprite(RIGHT_GUI_WIDTH/16,
|
gui->miniMapFrame = gui_util_create_frame_sprite(RIGHT_GUI_WIDTH/16,
|
||||||
MINIMAP_GUI_HEIGHT/16,
|
MINIMAP_GUI_HEIGHT/16,
|
||||||
cam);
|
cam);
|
||||||
|
|
||||||
|
|
||||||
|
texture_load_from_text(gui->labels[KEY_LABEL]->textures[0], "Keys:", C_WHITE, C_BLACK, cam->renderer);
|
||||||
|
gui->labels[KEY_LABEL]->dim = gui->labels[KEY_LABEL]->textures[0]->dim;
|
||||||
}
|
}
|
||||||
|
|
||||||
Gui*
|
Gui*
|
||||||
|
@ -197,28 +217,33 @@ gui_create(Camera *cam)
|
||||||
texture_load_font(gui->event_message, "GUI/SDS_8x8.ttf", EVENT_MESSAGE_FONT_SIZE, 2);
|
texture_load_font(gui->event_message, "GUI/SDS_8x8.ttf", EVENT_MESSAGE_FONT_SIZE, 2);
|
||||||
gui->event_message_timer = _timer_create();
|
gui->event_message_timer = _timer_create();
|
||||||
|
|
||||||
gui->labels[CURRENT_XP_LABEL] = create_label_sprite((Position) { 16, POS_Y_XPBAR + 18 });
|
gui->labels[CURRENT_XP_LABEL] = create_label_sprite(POS(16, POS_Y_XPBAR + 18));
|
||||||
gui->labels[LEVEL_LABEL] = create_label_sprite((Position) { 16, POS_Y_XPBAR + 18 + 14 });
|
gui->labels[LEVEL_LABEL] = create_label_sprite(POS(16, POS_Y_XPBAR + 18 + 14));
|
||||||
gui->labels[DUNGEON_LEVEL_LABEL] =
|
gui->labels[DUNGEON_LEVEL_LABEL] =
|
||||||
create_label_sprite((Position) {
|
create_label_sprite(POS(
|
||||||
16,
|
16,
|
||||||
POS_Y_XPBAR + 18 + (2*14)
|
POS_Y_XPBAR + 18 + (2*14)
|
||||||
});
|
));
|
||||||
|
gui->labels[KEY_LABEL] =
|
||||||
|
create_label_sprite(POS(
|
||||||
|
16,
|
||||||
|
POS_Y_XPBAR + 18 + (3*14)
|
||||||
|
));
|
||||||
gui->labels[HEALTH_POTION_LABEL] =
|
gui->labels[HEALTH_POTION_LABEL] =
|
||||||
create_label_sprite((Position) {
|
create_label_sprite(POS(
|
||||||
32,
|
32,
|
||||||
POS_Y_COLLECTABLES + 5
|
POS_Y_COLLECTABLES + 5
|
||||||
});
|
));
|
||||||
gui->labels[GOLD_LABEL] =
|
gui->labels[GOLD_LABEL] =
|
||||||
create_label_sprite((Position) {
|
create_label_sprite(POS(
|
||||||
32,
|
32,
|
||||||
POS_Y_COLLECTABLES + 16 + 5
|
POS_Y_COLLECTABLES + 16 + 5
|
||||||
});
|
));
|
||||||
gui->labels[DAGGER_LABEL] =
|
gui->labels[DAGGER_LABEL] =
|
||||||
create_label_sprite((Position) {
|
create_label_sprite(POS(
|
||||||
32,
|
32,
|
||||||
POS_Y_COLLECTABLES + 32 + 5
|
POS_Y_COLLECTABLES + 32 + 5
|
||||||
});
|
));
|
||||||
|
|
||||||
gui_malloc_log();
|
gui_malloc_log();
|
||||||
gui_malloc_eventmessages();
|
gui_malloc_eventmessages();
|
||||||
|
@ -251,7 +276,7 @@ set_max_health(Gui *gui, int max)
|
||||||
sprite->fixed = true;
|
sprite->fixed = true;
|
||||||
sprite->animate = false;
|
sprite->animate = false;
|
||||||
sprite->clip = (SDL_Rect) { 0, 16, 16, 16 };
|
sprite->clip = (SDL_Rect) { 0, 16, 16, 16 };
|
||||||
sprite->pos = (Position) { 16 + (i%8)*16, 16 + ((i-(i%8))/8)*16 };
|
sprite->pos = POS(16 + (i%8)*16, 16 + ((i-(i%8))/8)*16);
|
||||||
sprite_set_texture(sprite, texture0, 0);
|
sprite_set_texture(sprite, texture0, 0);
|
||||||
sprite_set_texture(sprite, texture1, 1);
|
sprite_set_texture(sprite, texture1, 1);
|
||||||
linkedlist_append(&gui->health, sprite);
|
linkedlist_append(&gui->health, sprite);
|
||||||
|
@ -392,6 +417,10 @@ gui_update_player_stats(Gui *gui, Player *player, Map *map, SDL_Renderer *render
|
||||||
gui->labels[LEVEL_LABEL]->dim = gui->labels[LEVEL_LABEL]->textures[0]->dim;
|
gui->labels[LEVEL_LABEL]->dim = gui->labels[LEVEL_LABEL]->textures[0]->dim;
|
||||||
last_level = data.level;
|
last_level = data.level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gui->silverKey->hidden = !(player->equipment.keys & LOCK_SILVER);
|
||||||
|
gui->goldKey->hidden = !(player->equipment.keys & LOCK_GOLD);
|
||||||
|
gui->goldKey->pos.x = gui->silverKey->hidden ? 58 : 74;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -410,6 +439,8 @@ gui_render_panel(Gui *gui, Camera *cam)
|
||||||
sprite_render(s, cam);
|
sprite_render(s, cam);
|
||||||
item = item->next;
|
item = item->next;
|
||||||
}
|
}
|
||||||
|
sprite_render(gui->silverKey, cam);
|
||||||
|
sprite_render(gui->goldKey, cam);
|
||||||
item = gui->sprites;
|
item = gui->sprites;
|
||||||
while (item != NULL) {
|
while (item != NULL) {
|
||||||
Sprite *s = item->data;
|
Sprite *s = item->data;
|
||||||
|
@ -622,5 +653,8 @@ gui_destroy(Gui *gui)
|
||||||
for (int i = 0; i < LABEL_COUNT; ++i)
|
for (int i = 0; i < LABEL_COUNT; ++i)
|
||||||
sprite_destroy(gui->labels[i]);
|
sprite_destroy(gui->labels[i]);
|
||||||
|
|
||||||
|
sprite_destroy(gui->silverKey);
|
||||||
|
sprite_destroy(gui->goldKey);
|
||||||
|
|
||||||
free(gui);
|
free(gui);
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ typedef enum Label_e {
|
||||||
CURRENT_XP_LABEL,
|
CURRENT_XP_LABEL,
|
||||||
GOLD_LABEL,
|
GOLD_LABEL,
|
||||||
DUNGEON_LEVEL_LABEL,
|
DUNGEON_LEVEL_LABEL,
|
||||||
|
KEY_LABEL,
|
||||||
HEALTH_POTION_LABEL,
|
HEALTH_POTION_LABEL,
|
||||||
DAGGER_LABEL,
|
DAGGER_LABEL,
|
||||||
LABEL_COUNT
|
LABEL_COUNT
|
||||||
|
@ -51,6 +52,8 @@ typedef struct Gui {
|
||||||
Sprite *miniMapFrame;
|
Sprite *miniMapFrame;
|
||||||
Sprite *labels[LABEL_COUNT];
|
Sprite *labels[LABEL_COUNT];
|
||||||
Sprite *activeTooltip;
|
Sprite *activeTooltip;
|
||||||
|
Sprite *goldKey;
|
||||||
|
Sprite *silverKey;
|
||||||
Texture *log_lines[LOG_LINES_COUNT];
|
Texture *log_lines[LOG_LINES_COUNT];
|
||||||
Texture *event_message;
|
Texture *event_message;
|
||||||
Timer *event_message_timer;
|
Timer *event_message_timer;
|
||||||
|
|
|
@ -97,7 +97,7 @@ hiscore_init(void)
|
||||||
static void
|
static void
|
||||||
save_hiscore(double gold, int lvl, int dlvl)
|
save_hiscore(double gold, int lvl, int dlvl)
|
||||||
{
|
{
|
||||||
const char *query = "INSERT INTO hiscore(gold, playerLevel, dungeonLevel) values (?, ?, ?)";
|
const char *query = "INSERT INTO hiscore(time, gold, playerLevel, dungeonLevel) values (datetime('now','+8 years'), ?, ?, ?)";
|
||||||
sqlite3_stmt *stmt = db_prepare(db, query);
|
sqlite3_stmt *stmt = db_prepare(db, query);
|
||||||
|
|
||||||
debug("Saving high score: %dg %dpl %dl",
|
debug("Saving high score: %dg %dpl %dl",
|
||||||
|
|
36
src/item.c
36
src/item.c
|
@ -21,31 +21,57 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "mixer.h"
|
#include "mixer.h"
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
|
#include "actiontextbuilder.h"
|
||||||
|
|
||||||
Item *
|
Item *
|
||||||
item_create(void)
|
item_create(void)
|
||||||
{
|
{
|
||||||
Item *item = ec_malloc(sizeof(Item));
|
Item *item = ec_malloc(sizeof(Item));
|
||||||
item->sprite = NULL;
|
item->sprite = NULL;
|
||||||
|
item->subsprites = NULL;
|
||||||
item->collected = false;
|
item->collected = false;
|
||||||
item->openable = false;
|
item->openable = false;
|
||||||
item->opened = false;
|
item->opened = false;
|
||||||
m_strcpy(item->label, 50, "");
|
m_strcpy(item->label, 50, "");
|
||||||
|
item->price = 0.0;
|
||||||
item->value = 0.0;
|
item->value = 0.0;
|
||||||
item->items = NULL;
|
item->items = NULL;
|
||||||
item->effect = NULL;
|
item->effect = NULL;
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
item_update(Item *item)
|
||||||
|
{
|
||||||
|
LinkedList *subsprites = item->subsprites;
|
||||||
|
while (subsprites != NULL) {
|
||||||
|
Sprite *sprite = subsprites->data;
|
||||||
|
sprite->pos = item->sprite->pos;
|
||||||
|
sprite->pos.x += 15 - sprite->dim.width / 2;
|
||||||
|
subsprites = subsprites->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
item_render(Item *item, Camera *cam)
|
item_render(Item *item, Camera *cam)
|
||||||
{
|
{
|
||||||
sprite_render(item->sprite, cam);
|
sprite_render(item->sprite, cam);
|
||||||
|
|
||||||
|
LinkedList *subsprites = item->subsprites;
|
||||||
|
while (subsprites != NULL) {
|
||||||
|
sprite_render(subsprites->data, cam);
|
||||||
|
subsprites = subsprites->next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
item_collected(Item *item, Player *player)
|
item_collected(Item *item, Player *player)
|
||||||
{
|
{
|
||||||
|
if (item->price > player->gold){
|
||||||
|
gui_log("You don't have enough gold to buy %s", item->label);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (item->collected || item->opened)
|
if (item->collected || item->opened)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -60,6 +86,13 @@ item_collected(Item *item, Player *player)
|
||||||
gui_log("You find nothing inside");
|
gui_log("You find nothing inside");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (item->price) {
|
||||||
|
player->gold -= item->price;
|
||||||
|
char costLabel[10];
|
||||||
|
m_sprintf(costLabel, 10, "-$%.0f", item->price);
|
||||||
|
actiontextbuilder_create_text(costLabel, C_YELLOW, &player->sprite->pos);
|
||||||
|
}
|
||||||
|
|
||||||
if (item->effect != NULL)
|
if (item->effect != NULL)
|
||||||
item->effect(item, player);
|
item->effect(item, player);
|
||||||
|
|
||||||
|
@ -76,6 +109,9 @@ item_destroy(Item *item)
|
||||||
if (item->sprite)
|
if (item->sprite)
|
||||||
sprite_destroy(item->sprite);
|
sprite_destroy(item->sprite);
|
||||||
|
|
||||||
|
while (item->subsprites != NULL)
|
||||||
|
sprite_destroy(linkedlist_pop(&item->subsprites));
|
||||||
|
|
||||||
while (item->items != NULL)
|
while (item->items != NULL)
|
||||||
item_destroy(linkedlist_pop(&item->items));
|
item_destroy(linkedlist_pop(&item->items));
|
||||||
|
|
||||||
|
|
|
@ -29,10 +29,12 @@
|
||||||
|
|
||||||
typedef struct Item_t {
|
typedef struct Item_t {
|
||||||
Sprite *sprite;
|
Sprite *sprite;
|
||||||
|
LinkedList *subsprites;
|
||||||
bool collected;
|
bool collected;
|
||||||
bool openable;
|
bool openable;
|
||||||
bool opened;
|
bool opened;
|
||||||
char label[50];
|
char label[50];
|
||||||
|
double price;
|
||||||
double value;
|
double value;
|
||||||
LinkedList *items;
|
LinkedList *items;
|
||||||
void (*effect)(struct Item_t *, Player *);
|
void (*effect)(struct Item_t *, Player *);
|
||||||
|
@ -44,6 +46,9 @@ item_create(void);
|
||||||
void
|
void
|
||||||
item_collected(Item*, Player*);
|
item_collected(Item*, Player*);
|
||||||
|
|
||||||
|
void
|
||||||
|
item_update(Item*);
|
||||||
|
|
||||||
void
|
void
|
||||||
item_render(Item*, Camera*);
|
item_render(Item*, Camera*);
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "item_builder.h"
|
#include "item_builder.h"
|
||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
|
@ -27,6 +28,8 @@
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
#include "texturecache.h"
|
#include "texturecache.h"
|
||||||
#include "sprite.h"
|
#include "sprite.h"
|
||||||
|
#include "sprite_util.h"
|
||||||
|
#include "map.h"
|
||||||
|
|
||||||
static ItemBuilder *builder = NULL;
|
static ItemBuilder *builder = NULL;
|
||||||
|
|
||||||
|
@ -108,29 +111,13 @@ pickup_gold(Item *item, Player *player)
|
||||||
gui_log("You pick up %s", &item->label);
|
gui_log("You pick up %s", &item->label);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Item *
|
Item *
|
||||||
create_treasure(int current_level)
|
item_builder_build_treasure(Treasure type, double goldAmt)
|
||||||
{
|
{
|
||||||
double amt;
|
double amt = goldAmt;
|
||||||
char label[50] = "";
|
char label[50] = "";
|
||||||
unsigned int highest_treasure;
|
|
||||||
unsigned int value;
|
|
||||||
|
|
||||||
amt = (unsigned int) 1 + get_random(5*current_level) % 40;
|
|
||||||
amt = amt == 0 ? 1 : amt;
|
|
||||||
|
|
||||||
if (current_level > 9) {
|
|
||||||
highest_treasure = PLATINUM;
|
|
||||||
} else if (current_level > 3) {
|
|
||||||
highest_treasure = GOLD;
|
|
||||||
} else {
|
|
||||||
highest_treasure = SILVER;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = get_random(highest_treasure);
|
|
||||||
|
|
||||||
SDL_Rect clip = CLIP16(0, 0);
|
SDL_Rect clip = CLIP16(0, 0);
|
||||||
switch (value) {
|
switch (type) {
|
||||||
case COPPER:
|
case COPPER:
|
||||||
m_sprintf(label, 50, "%.0f copper", amt);
|
m_sprintf(label, 50, "%.0f copper", amt);
|
||||||
amt /= 100;
|
amt /= 100;
|
||||||
|
@ -165,6 +152,71 @@ create_treasure(int current_level)
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pickup_silver_key(Item *item, Player *player)
|
||||||
|
{
|
||||||
|
gui_log("You pickup %s", item->label);
|
||||||
|
mixer_play_effect(KEY_PICKUP);
|
||||||
|
player->equipment.keys |= LOCK_SILVER;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pickup_gold_key(Item *item, Player *player)
|
||||||
|
{
|
||||||
|
gui_log("You pickup %s", item->label);
|
||||||
|
mixer_play_effect(KEY_PICKUP);
|
||||||
|
player->equipment.keys |= LOCK_GOLD;
|
||||||
|
}
|
||||||
|
|
||||||
|
Item *
|
||||||
|
item_builder_build_key(unsigned int type)
|
||||||
|
{
|
||||||
|
char label[20];
|
||||||
|
Item *item;
|
||||||
|
switch (type) {
|
||||||
|
case 1:
|
||||||
|
m_sprintf(label, 20, "a silver key");
|
||||||
|
item = create_item("Extras/Keys.png",
|
||||||
|
NULL,
|
||||||
|
CLIP16(0, 0),
|
||||||
|
&pickup_silver_key);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
m_sprintf(label, 20, "a gold key");
|
||||||
|
item = create_item("Extras/Keys.png",
|
||||||
|
NULL,
|
||||||
|
CLIP16(16, 0),
|
||||||
|
&pickup_gold_key);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fatal("Bad keytype provided");
|
||||||
|
}
|
||||||
|
|
||||||
|
m_strcpy(item->label, 20, label);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Item *
|
||||||
|
create_treasure(int current_level)
|
||||||
|
{
|
||||||
|
double amt;
|
||||||
|
unsigned int highest_treasure;
|
||||||
|
unsigned int value;
|
||||||
|
|
||||||
|
amt = (unsigned int) 1 + get_random(5*current_level) % 40;
|
||||||
|
|
||||||
|
if (current_level > 9) {
|
||||||
|
highest_treasure = PLATINUM;
|
||||||
|
} else if (current_level > 3) {
|
||||||
|
highest_treasure = GOLD;
|
||||||
|
} else {
|
||||||
|
highest_treasure = SILVER;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = get_random(highest_treasure);
|
||||||
|
return item_builder_build_treasure((Treasure) value, amt);
|
||||||
|
}
|
||||||
|
|
||||||
Item *
|
Item *
|
||||||
item_builder_build_item(ItemKey key, int level)
|
item_builder_build_item(ItemKey key, int level)
|
||||||
{
|
{
|
||||||
|
@ -205,6 +257,18 @@ item_builder_build_item(ItemKey key, int level)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (item->value != 1) {
|
||||||
|
Sprite *valueSprite = sprite_util_create_text_sprite("GUI/SDS_8x8.ttf",
|
||||||
|
8,
|
||||||
|
C_BLUE,
|
||||||
|
C_BLACK,
|
||||||
|
"%g",
|
||||||
|
item->value);
|
||||||
|
valueSprite->offset.x = item->sprite->dim.width - valueSprite->dim.width;
|
||||||
|
valueSprite->offset.y = item->sprite->dim.height - valueSprite->dim.height;
|
||||||
|
linkedlist_append(&item->subsprites, valueSprite);
|
||||||
|
}
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,12 @@ item_builder_build_sack(void);
|
||||||
Item *
|
Item *
|
||||||
item_builder_build_container(const char *path0, const char *path1, SDL_Rect clip);
|
item_builder_build_container(const char *path0, const char *path1, SDL_Rect clip);
|
||||||
|
|
||||||
|
Item *
|
||||||
|
item_builder_build_treasure(Treasure type, double goldAmt);
|
||||||
|
|
||||||
|
Item *
|
||||||
|
item_builder_build_key(unsigned int type);
|
||||||
|
|
||||||
void
|
void
|
||||||
item_builder_close(void);
|
item_builder_close(void);
|
||||||
|
|
||||||
|
|
|
@ -142,3 +142,4 @@ unsigned int linkedlist_size(LinkedList *head)
|
||||||
}
|
}
|
||||||
return 1 + linkedlist_size(head->next);
|
return 1 + linkedlist_size(head->next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,3 +44,4 @@ void linkedlist_destroy(LinkedList **head);
|
||||||
unsigned int linkedlist_size(LinkedList *head);
|
unsigned int linkedlist_size(LinkedList *head);
|
||||||
|
|
||||||
#endif // LINKEDLIST_H_
|
#endif // LINKEDLIST_H_
|
||||||
|
|
||||||
|
|
235
src/main.c
235
src/main.c
|
@ -55,18 +55,31 @@
|
||||||
#include "tooltip.h"
|
#include "tooltip.h"
|
||||||
#include "gamecontroller.h"
|
#include "gamecontroller.h"
|
||||||
#include "time.h"
|
#include "time.h"
|
||||||
|
#include "sprite_util.h"
|
||||||
|
#include "event.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "save.h"
|
||||||
|
|
||||||
#ifdef STEAM_BUILD
|
#ifdef STEAM_BUILD
|
||||||
|
#include "checksum.h"
|
||||||
#include "steam/steamworks_api_wrapper.h"
|
#include "steam/steamworks_api_wrapper.h"
|
||||||
#endif // STEAM_BUILD
|
#endif // STEAM_BUILD
|
||||||
|
|
||||||
|
#if defined(__amigaos4__)
|
||||||
|
#define USED __attribute__((used))
|
||||||
|
#define VSTRING "BreakHack 4.0.3r2 (04.07.2023)"
|
||||||
|
#define VERSTAG "\0$VER: " VSTRING
|
||||||
|
static const char *stack USED = "$STACK:102400";
|
||||||
|
static const char *version USED = VERSTAG;
|
||||||
|
#endif
|
||||||
|
|
||||||
static char *artifacts_tooltip[] = {
|
static char *artifacts_tooltip[] = {
|
||||||
"CONGRATULATIONS!", "",
|
"CONGRATULATIONS!", "",
|
||||||
"",
|
"",
|
||||||
" You just picked up your first artifact!", "",
|
" You just picked up your first artifact!", "",
|
||||||
"",
|
"",
|
||||||
" Your current artifacts and corresponding level are", "",
|
" Your current artifacts and corresponding level are", "",
|
||||||
" listed next to your skills." "",
|
" listed next to your skills.", "",
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
" Artifacts have mystical effects that improve your offensive", "",
|
" Artifacts have mystical effects that improve your offensive", "",
|
||||||
|
@ -90,8 +103,8 @@ static char *skills_tooltip[] = {
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
" SKILL INFO: SHIFT + <N>", "",
|
" SKILL INFO: SHIFT + <N>", "",
|
||||||
" Where <N> is the number corresponding to the skill", "",
|
" Where <N> is the number corresponding to", "",
|
||||||
" Eg. 1, 2, 3, 4, 5", "",
|
" the skill, i.e. 1, 2, 3, 4, 5", "",
|
||||||
"",
|
"",
|
||||||
" DISABLE TOOLTIPS: CTRL + D", "",
|
" DISABLE TOOLTIPS: CTRL + D", "",
|
||||||
"",
|
"",
|
||||||
|
@ -233,7 +246,7 @@ bool initSDL(void)
|
||||||
m_sprintf(title_buffer, 100, "%s %d.%d.%d %s", GAME_TITLE, MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION, RELEASE_TYPE);
|
m_sprintf(title_buffer, 100, "%s %d.%d.%d %s", GAME_TITLE, MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION, RELEASE_TYPE);
|
||||||
gWindow = SDL_CreateWindow(title_buffer,
|
gWindow = SDL_CreateWindow(title_buffer,
|
||||||
SDL_WINDOWPOS_UNDEFINED,
|
SDL_WINDOWPOS_UNDEFINED,
|
||||||
SDL_WINDOWPOS_UNDEFINED,
|
SDL_WINDOWPOS_UNDEFINED,
|
||||||
(int)(SCREEN_WIDTH * renderScale),
|
(int)(SCREEN_WIDTH * renderScale),
|
||||||
(int)(SCREEN_HEIGHT * renderScale),
|
(int)(SCREEN_HEIGHT * renderScale),
|
||||||
SDL_WINDOW_SHOWN);
|
SDL_WINDOW_SHOWN);
|
||||||
|
@ -268,7 +281,7 @@ bool initSDL(void)
|
||||||
debug("Disabling text input");
|
debug("Disabling text input");
|
||||||
SDL_StopTextInput();
|
SDL_StopTextInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,6 +321,7 @@ initGame(void)
|
||||||
initViewports(0);
|
initViewports(0);
|
||||||
input_init(&input);
|
input_init(&input);
|
||||||
texturecache_init(gRenderer);
|
texturecache_init(gRenderer);
|
||||||
|
sprite_util_init(gRenderer);
|
||||||
gCamera = camera_create(gRenderer);
|
gCamera = camera_create(gRenderer);
|
||||||
gRoomMatrix = roommatrix_create();
|
gRoomMatrix = roommatrix_create();
|
||||||
gGui = gui_create(gCamera);
|
gGui = gui_create(gCamera);
|
||||||
|
@ -400,6 +414,8 @@ on_character_select(const char *str)
|
||||||
playerClass = WARRIOR;
|
playerClass = WARRIOR;
|
||||||
else if (strcmp(str, "rogue") == 0)
|
else if (strcmp(str, "rogue") == 0)
|
||||||
playerClass = ROGUE;
|
playerClass = ROGUE;
|
||||||
|
else if (strcmp(str, "mage") == 0)
|
||||||
|
playerClass = MAGE;
|
||||||
|
|
||||||
startGame();
|
startGame();
|
||||||
}
|
}
|
||||||
|
@ -413,6 +429,56 @@ goToCharacterMenu(void *unused)
|
||||||
gGameState = CHARACTER_MENU;
|
gGameState = CHARACTER_MENU;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
choose_music(void)
|
||||||
|
{
|
||||||
|
if (cLevel > (unsigned int) (quickGame ? 11 : 19)) {
|
||||||
|
mixer_play_music(BOSS_MUSIC0);
|
||||||
|
} else if (cLevel % (quickGame ? 3 : 5) == 0) {
|
||||||
|
gui_log("You sense something powerful in the vicinity");
|
||||||
|
mixer_play_music(BOSS_MUSIC0);
|
||||||
|
} else {
|
||||||
|
mixer_play_music(GAME_MUSIC0 + get_random(2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
continueGame(void *unused)
|
||||||
|
{
|
||||||
|
(void) unused;
|
||||||
|
const Save *save = save_get();
|
||||||
|
quickGame = save->quickGame;
|
||||||
|
arcadeGame = save->arcadeGame;
|
||||||
|
|
||||||
|
playerClass = save->player_class;
|
||||||
|
cLevel = save->map_level;
|
||||||
|
set_random_seed(save->seed);
|
||||||
|
debug("Loading seed: %d", save->seed);
|
||||||
|
debug("Loading map level: %d", save->map_level);
|
||||||
|
|
||||||
|
gGameState = PLAYING;
|
||||||
|
if (gPlayer)
|
||||||
|
player_destroy(gPlayer);
|
||||||
|
gPlayer = player_create(playerClass, gCamera);
|
||||||
|
|
||||||
|
// Load player from save
|
||||||
|
gPlayer->daggers = save->player_daggers;
|
||||||
|
gPlayer->xp = save->player_xp;
|
||||||
|
gPlayer->stateData = save->player_state;
|
||||||
|
gPlayer->stats = save->player_stats;
|
||||||
|
gPlayer->stat_data = save->player_player_stats;
|
||||||
|
gPlayer->potion_sips = save->player_potion_sips;
|
||||||
|
gPlayer->equipment = save->player_equipment;
|
||||||
|
gPlayer->gold = save->player_gold;
|
||||||
|
|
||||||
|
choose_music();
|
||||||
|
resetGame();
|
||||||
|
skillbar_reset(gSkillBar);
|
||||||
|
gui_clear_message_log();
|
||||||
|
gui_log("The Dungeon Crawl continues!");
|
||||||
|
gui_event_message("Welcome back!");
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
startRegularGame(void *unused)
|
startRegularGame(void *unused)
|
||||||
{
|
{
|
||||||
|
@ -452,6 +518,7 @@ static void
|
||||||
goToMainMenu(void *unused)
|
goToMainMenu(void *unused)
|
||||||
{
|
{
|
||||||
UNUSED(unused);
|
UNUSED(unused);
|
||||||
|
save_load();
|
||||||
gui_clear_message_log();
|
gui_clear_message_log();
|
||||||
gGameState = MENU;
|
gGameState = MENU;
|
||||||
menu_destroy(inGameMenu);
|
menu_destroy(inGameMenu);
|
||||||
|
@ -467,37 +534,47 @@ static void
|
||||||
goToGameSelectMenu(void *unused)
|
goToGameSelectMenu(void *unused)
|
||||||
{
|
{
|
||||||
UNUSED(unused);
|
UNUSED(unused);
|
||||||
static TEXT_MENU_ITEM menuItems[] = {
|
int item_count = 3;
|
||||||
{
|
|
||||||
"STANDARD GAME",
|
|
||||||
"Standard 20 level game, recommended for new players",
|
|
||||||
startRegularGame
|
|
||||||
},
|
|
||||||
#ifdef STEAM_BUILD
|
#ifdef STEAM_BUILD
|
||||||
{
|
item_count += 1;
|
||||||
"WEEKLY CHALLENGE",
|
|
||||||
"Quick game with weekly leaderboards at breakhack.net",
|
|
||||||
startWeeklyGame
|
|
||||||
},
|
|
||||||
#endif
|
#endif
|
||||||
{
|
if (save_exists()) {
|
||||||
"QUICK GAME",
|
item_count += 1;
|
||||||
"Shorter 12 level game, with more action earlier in the game",
|
}
|
||||||
startQuickGame
|
TEXT_MENU_ITEM *menuItems = ec_malloc(item_count * sizeof(TEXT_MENU_ITEM));
|
||||||
},
|
int i = 0;
|
||||||
{
|
if (save_exists()) {
|
||||||
"ARCADE GAME",
|
menuItems[i++] = (TEXT_MENU_ITEM) {
|
||||||
"One big level with lots of action",
|
"CONTINUE",
|
||||||
startArcadeGame
|
"Continue your last session",
|
||||||
}
|
continueGame,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
menuItems[i++] = (TEXT_MENU_ITEM) {
|
||||||
|
"STANDARD GAME",
|
||||||
|
"Standard 20 level game, recommended for new players",
|
||||||
|
startRegularGame
|
||||||
|
};
|
||||||
|
#ifdef STEAM_BUILD
|
||||||
|
menuItems[i++] = (TEXT_MENU_ITEM) {
|
||||||
|
"WEEKLY CHALLENGE",
|
||||||
|
"Quick game with weekly leaderboards at breakhack.net",
|
||||||
|
startWeeklyGame
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
menuItems[i++] = (TEXT_MENU_ITEM) {
|
||||||
|
"QUICK GAME",
|
||||||
|
"Shorter 12 level game, with more action earlier in the game",
|
||||||
|
startQuickGame
|
||||||
|
};
|
||||||
|
menuItems[i++] = (TEXT_MENU_ITEM) {
|
||||||
|
"ARCADE GAME",
|
||||||
|
"One big level with lots of action",
|
||||||
|
startArcadeGame
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef STEAM_BUILD
|
menu_create_text_menu(&gameSelectMenu, menuItems, item_count, gRenderer);
|
||||||
int count = 4;
|
free(menuItems);
|
||||||
#else
|
|
||||||
int count = 3;
|
|
||||||
#endif
|
|
||||||
menu_create_text_menu(&gameSelectMenu, &menuItems[0], count, gRenderer);
|
|
||||||
gGameState = GAME_SELECT;
|
gGameState = GAME_SELECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -634,16 +711,31 @@ resetGame(void)
|
||||||
mode = ARCADE;
|
mode = ARCADE;
|
||||||
|
|
||||||
info("Building new map");
|
info("Building new map");
|
||||||
gMap = map_lua_generator_run(cLevel, mode, gRenderer);
|
gMap = map_lua_generator_run(cLevel, mode, gPlayer, gRenderer);
|
||||||
|
|
||||||
gPlayer->sprite->pos = (Position) {
|
player_reset_on_levelchange(gPlayer);
|
||||||
TILE_DIMENSION, TILE_DIMENSION };
|
|
||||||
|
|
||||||
map_set_current_room(gMap, &gPlayer->sprite->pos);
|
map_set_current_room(gMap, &gPlayer->sprite->pos);
|
||||||
camera_follow_position(gCamera, &gPlayer->sprite->pos);
|
camera_follow_position(gCamera, &gPlayer->sprite->pos);
|
||||||
repopulate_roommatrix();
|
repopulate_roommatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_event_callback(Event *event)
|
||||||
|
{
|
||||||
|
if (event->type == MONSTER_KILLED_EVENT) {
|
||||||
|
if (strcmp(event->monsterKilled.monster->label, "A Fairy") == 0) {
|
||||||
|
LinkedList *monsters = gMap->monsters;
|
||||||
|
while (monsters) {
|
||||||
|
Monster *monster = monsters->data;
|
||||||
|
monsters = monsters->next;
|
||||||
|
if (position_in_room(&monster->sprite->pos, &gMap->currentRoom))
|
||||||
|
monster_set_bloodlust(monster, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
init(void)
|
init(void)
|
||||||
{
|
{
|
||||||
|
@ -666,7 +758,10 @@ init(void)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event_register_listener(on_event_callback);
|
||||||
|
|
||||||
settings_init();
|
settings_init();
|
||||||
|
save_init();
|
||||||
hiscore_init();
|
hiscore_init();
|
||||||
initMainMenu();
|
initMainMenu();
|
||||||
|
|
||||||
|
@ -827,7 +922,7 @@ end_game_details(void)
|
||||||
{
|
{
|
||||||
gui_log("You earned %.2f gold", gPlayer->gold);
|
gui_log("You earned %.2f gold", gPlayer->gold);
|
||||||
gui_event_message("You earned %.2f gold", gPlayer->gold);
|
gui_event_message("You earned %.2f gold", gPlayer->gold);
|
||||||
|
|
||||||
if (hiscore_get_top_gold() < gPlayer->gold) {
|
if (hiscore_get_top_gold() < gPlayer->gold) {
|
||||||
gui_event_message("NEW HIGHSCORE");
|
gui_event_message("NEW HIGHSCORE");
|
||||||
gui_log("NEW HIGHSCORE");
|
gui_log("NEW HIGHSCORE");
|
||||||
|
@ -850,17 +945,17 @@ check_next_level(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (tile->levelExit) {
|
if (tile->levelExit) {
|
||||||
mixer_play_effect(NEXT_LEVEL);
|
|
||||||
++cLevel;
|
++cLevel;
|
||||||
if (cLevel > (quickGame ? 11 : 19)) {
|
if (!weeklyGame) {
|
||||||
mixer_play_music(BOSS_MUSIC0);
|
save_save(get_random_seed(),
|
||||||
} else if (cLevel % (quickGame ? 3 : 5) == 0) {
|
cLevel,
|
||||||
gui_log("You sense something powerful in the vicinity");
|
quickGame,
|
||||||
mixer_play_music(BOSS_MUSIC0);
|
arcadeGame,
|
||||||
} else {
|
gPlayer);
|
||||||
mixer_play_music(GAME_MUSIC0 + get_random(2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mixer_play_effect(NEXT_LEVEL);
|
||||||
|
choose_music();
|
||||||
if (!gameCompleted()) {
|
if (!gameCompleted()) {
|
||||||
resetGame();
|
resetGame();
|
||||||
}
|
}
|
||||||
|
@ -1002,9 +1097,6 @@ render_game(void)
|
||||||
|
|
||||||
map_render_top_layer(gMap, gRoomMatrix, gCamera);
|
map_render_top_layer(gMap, gRoomMatrix, gCamera);
|
||||||
|
|
||||||
if (gPlayer->class == MAGE || gPlayer->class == PALADIN)
|
|
||||||
roommatrix_render_mouse_square(gRoomMatrix, gCamera);
|
|
||||||
|
|
||||||
roommatrix_render_lightmap(gRoomMatrix, gCamera);
|
roommatrix_render_lightmap(gRoomMatrix, gCamera);
|
||||||
actiontextbuilder_render(gCamera);
|
actiontextbuilder_render(gCamera);
|
||||||
gui_render_event_message(gGui, gCamera);
|
gui_render_event_message(gGui, gCamera);
|
||||||
|
@ -1065,10 +1157,13 @@ register_scores(void)
|
||||||
steam_set_achievement(ROGUE_LIKE);
|
steam_set_achievement(ROGUE_LIKE);
|
||||||
steam_register_rogue_score((int) gPlayer->gold,
|
steam_register_rogue_score((int) gPlayer->gold,
|
||||||
(int32_t*) &details, 1);
|
(int32_t*) &details, 1);
|
||||||
}
|
} else if (gPlayer->class == WARRIOR) {
|
||||||
else if (gPlayer->class == WARRIOR) {
|
|
||||||
steam_register_warrior_score((int) gPlayer->gold,
|
steam_register_warrior_score((int) gPlayer->gold,
|
||||||
(int32_t*) &details, 1);
|
(int32_t*) &details, 1);
|
||||||
|
} else if (gPlayer->class == MAGE) {
|
||||||
|
steam_set_achievement(MAGICAL);
|
||||||
|
steam_register_mage_score((int) gPlayer->gold,
|
||||||
|
(int32_t*) &details, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1092,6 +1187,7 @@ run_game(void)
|
||||||
camera_shake(VECTOR2D_RIGHT, 800);
|
camera_shake(VECTOR2D_RIGHT, 800);
|
||||||
gui_log("The dungeon consumed you");
|
gui_log("The dungeon consumed you");
|
||||||
gui_event_message("You died!");
|
gui_event_message("You died!");
|
||||||
|
save_clear();
|
||||||
end_game_details();
|
end_game_details();
|
||||||
mixer_play_effect(SPLAT);
|
mixer_play_effect(SPLAT);
|
||||||
gGameState = GAME_OVER;
|
gGameState = GAME_OVER;
|
||||||
|
@ -1325,12 +1421,14 @@ void close(void)
|
||||||
texturecache_close();
|
texturecache_close();
|
||||||
settings_close();
|
settings_close();
|
||||||
hiscore_close();
|
hiscore_close();
|
||||||
|
save_close();
|
||||||
|
|
||||||
#ifdef STEAM_BUILD
|
#ifdef STEAM_BUILD
|
||||||
steam_shutdown();
|
steam_shutdown();
|
||||||
#endif // STEAM_BUILD
|
#endif // STEAM_BUILD
|
||||||
|
|
||||||
gamecontroller_close();
|
gamecontroller_close();
|
||||||
|
event_clear_listeners();
|
||||||
SDL_DestroyRenderer(gRenderer);
|
SDL_DestroyRenderer(gRenderer);
|
||||||
SDL_DestroyWindow(gWindow);
|
SDL_DestroyWindow(gWindow);
|
||||||
gWindow = NULL;
|
gWindow = NULL;
|
||||||
|
@ -1339,12 +1437,46 @@ void close(void)
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef STEAM_BUILD
|
||||||
|
static void
|
||||||
|
validate_lib_checksum(void)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
#ifdef WIN32
|
||||||
|
const char *file = "./steam_api.dll";
|
||||||
|
unsigned int expected = DLL_LIBSTEAM_CHECKSUM;
|
||||||
|
fopen_s(&fp, file, "rb");
|
||||||
|
#else // WIN32
|
||||||
|
const char *file = "./libsteam_api.so";
|
||||||
|
unsigned int expected = SO_LIBSTEAM_CHECKSUM;
|
||||||
|
fp = fopen(file, "rb");
|
||||||
|
#endif // WIN32
|
||||||
|
|
||||||
|
if (!fp) {
|
||||||
|
fatal("Unable to open %s for reading\n", file);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned calculated = checksum_fp(fp);
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
if (calculated != expected) {
|
||||||
|
fatal("Checksum validation failiure: %#x != %#x", calculated, expected);
|
||||||
|
} else {
|
||||||
|
info("Checksum validated: %#x", calculated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // STEAM_BUILD
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
UNUSED(argc);
|
UNUSED(argc);
|
||||||
|
|
||||||
|
#ifdef STEAM_BUILD
|
||||||
|
validate_lib_checksum();
|
||||||
|
#endif // STEAM_BUILD
|
||||||
|
|
||||||
PHYSFS_init(argv[0]);
|
PHYSFS_init(argv[0]);
|
||||||
#ifndef DEBUG
|
#if !defined(DEBUG) && !defined(__amigaos4__)
|
||||||
PHYSFS_mount("assets.pack", NULL, 0);
|
PHYSFS_mount("assets.pack", NULL, 0);
|
||||||
PHYSFS_mount("data.pack", NULL, 0);
|
PHYSFS_mount("data.pack", NULL, 0);
|
||||||
#else
|
#else
|
||||||
|
@ -1360,7 +1492,7 @@ int main(int argc, char *argv[])
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (settings_get()->fullscreen_enabled) {
|
if (settings_get()->fullscreen_enabled) {
|
||||||
// Game starts in windowed mode so this will
|
// Game starts in windowed mode so this will
|
||||||
// change to fullscreen
|
// change to fullscreen
|
||||||
toggle_fullscreen();
|
toggle_fullscreen();
|
||||||
}
|
}
|
||||||
|
@ -1370,3 +1502,4 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
120
src/map.c
120
src/map.c
|
@ -26,6 +26,7 @@
|
||||||
#include "particle_engine.h"
|
#include "particle_engine.h"
|
||||||
#include "update_data.h"
|
#include "update_data.h"
|
||||||
#include "trap.h"
|
#include "trap.h"
|
||||||
|
#include "mixer.h"
|
||||||
|
|
||||||
static Room*
|
static Room*
|
||||||
create_room(void)
|
create_room(void)
|
||||||
|
@ -35,12 +36,15 @@ create_room(void)
|
||||||
|
|
||||||
room = ec_malloc(sizeof(Room));
|
room = ec_malloc(sizeof(Room));
|
||||||
room->modifier.type = RMOD_TYPE_NONE;
|
room->modifier.type = RMOD_TYPE_NONE;
|
||||||
|
room->visited = false;
|
||||||
|
room->lockTypes = 0;
|
||||||
for (i=0; i < MAP_ROOM_WIDTH; ++i) {
|
for (i=0; i < MAP_ROOM_WIDTH; ++i) {
|
||||||
for (j=0; j < MAP_ROOM_HEIGHT; ++j) {
|
for (j=0; j < MAP_ROOM_HEIGHT; ++j) {
|
||||||
room->tiles[i][j] = NULL;
|
room->tiles[i][j] = NULL;
|
||||||
|
room->walls[i][j] = NULL;
|
||||||
room->decorations[i][j] = NULL;
|
room->decorations[i][j] = NULL;
|
||||||
room->traps[i][j] = NULL;
|
room->traps[i][j] = NULL;
|
||||||
room->visited = false;
|
room->doors[i][j] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return room;
|
return room;
|
||||||
|
@ -60,6 +64,7 @@ map_create(void)
|
||||||
map->currentRoom = (Position) { 0, 0 };
|
map->currentRoom = (Position) { 0, 0 };
|
||||||
map->monsterMoveTimer = _timer_create();
|
map->monsterMoveTimer = _timer_create();
|
||||||
map->level = 1;
|
map->level = 1;
|
||||||
|
map->lockTypes = 0;
|
||||||
|
|
||||||
for (i=0; i < MAP_H_ROOM_COUNT; ++i) {
|
for (i=0; i < MAP_H_ROOM_COUNT; ++i) {
|
||||||
for (j=0; j < MAP_V_ROOM_COUNT; ++j) {
|
for (j=0; j < MAP_V_ROOM_COUNT; ++j) {
|
||||||
|
@ -81,6 +86,8 @@ map_create_tile(void)
|
||||||
tile->lethal = false;
|
tile->lethal = false;
|
||||||
tile->lightsource = false;
|
tile->lightsource = false;
|
||||||
tile->levelExit = false;
|
tile->levelExit = false;
|
||||||
|
tile->door = false;
|
||||||
|
tile->lockType = LOCK_NONE;
|
||||||
return tile;
|
return tile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,37 +99,9 @@ map_tile_destroy(MapTile *tile)
|
||||||
free(tile);
|
free(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
map_add_tile(Map *map, Position *tile_pos, MapTile *tile)
|
switch_tile(Map *map, Position *tile_pos, MapTile *tile, MapTile **oldTile)
|
||||||
{
|
{
|
||||||
const Position *cr = &map->currentRoom;
|
|
||||||
Room *room = map->rooms[cr->x][cr->y];
|
|
||||||
MapTile **oldTile = &room->tiles[tile_pos->x][tile_pos->y];
|
|
||||||
|
|
||||||
// Set the tile sprites position to match tile pos
|
|
||||||
tile->sprite->pos = POS(tile_pos->x * TILE_DIMENSION + (map->currentRoom.x * GAME_VIEW_WIDTH),
|
|
||||||
tile_pos->y * TILE_DIMENSION + (map->currentRoom.y * GAME_VIEW_HEIGHT));
|
|
||||||
|
|
||||||
// If this is the level exit then clear the decoration if one exists
|
|
||||||
if (tile->levelExit && room->decorations[tile_pos->x][tile_pos->y]) {
|
|
||||||
MapTile **decoration = &room->decorations[tile_pos->x][tile_pos->y];
|
|
||||||
map_tile_destroy(*decoration);
|
|
||||||
*decoration = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear possible tile
|
|
||||||
if (*oldTile != NULL) {
|
|
||||||
map_tile_destroy(*oldTile);
|
|
||||||
*oldTile = NULL;
|
|
||||||
}
|
|
||||||
*oldTile = tile;
|
|
||||||
}
|
|
||||||
|
|
||||||
void map_add_decoration(Map *map, Position *tile_pos, MapTile *tile)
|
|
||||||
{
|
|
||||||
const Position *cr = &map->currentRoom;
|
|
||||||
MapTile **oldTile = &map->rooms[cr->x][cr->y]->decorations[tile_pos->x][tile_pos->y];
|
|
||||||
|
|
||||||
// Set the decoration sprites position to match tile pos
|
// Set the decoration sprites position to match tile pos
|
||||||
tile->sprite->pos = POS(tile_pos->x * TILE_DIMENSION + (map->currentRoom.x * GAME_VIEW_WIDTH),
|
tile->sprite->pos = POS(tile_pos->x * TILE_DIMENSION + (map->currentRoom.x * GAME_VIEW_WIDTH),
|
||||||
tile_pos->y * TILE_DIMENSION + (map->currentRoom.y * GAME_VIEW_HEIGHT));
|
tile_pos->y * TILE_DIMENSION + (map->currentRoom.y * GAME_VIEW_HEIGHT));
|
||||||
|
@ -134,6 +113,50 @@ void map_add_decoration(Map *map, Position *tile_pos, MapTile *tile)
|
||||||
*oldTile = tile;
|
*oldTile = tile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
map_add_tile(Map *map, Position *tile_pos, MapTile *tile)
|
||||||
|
{
|
||||||
|
const Position *cr = &map->currentRoom;
|
||||||
|
Room *room = map->rooms[cr->x][cr->y];
|
||||||
|
switch_tile(map, tile_pos, tile, &room->tiles[tile_pos->x][tile_pos->y]);
|
||||||
|
|
||||||
|
// If this is the level exit then clear the decoration if one exists
|
||||||
|
if (tile->levelExit && room->decorations[tile_pos->x][tile_pos->y]) {
|
||||||
|
MapTile **decoration = &room->decorations[tile_pos->x][tile_pos->y];
|
||||||
|
map_tile_destroy(*decoration);
|
||||||
|
*decoration = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
map_add_wall(Map *map, Position *tile_pos, MapTile *tile)
|
||||||
|
{
|
||||||
|
const Position *cr = &map->currentRoom;
|
||||||
|
Room *room = map->rooms[cr->x][cr->y];
|
||||||
|
switch_tile(map, tile_pos, tile, &room->walls[tile_pos->x][tile_pos->y]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void map_add_decoration(Map *map, Position *tile_pos, MapTile *tile)
|
||||||
|
{
|
||||||
|
const Position *cr = &map->currentRoom;
|
||||||
|
Room *room = map->rooms[cr->x][cr->y];
|
||||||
|
switch_tile(map, tile_pos, tile, &room->decorations[tile_pos->x][tile_pos->y]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
map_add_door(Map *map, Position *tile_pos, MapTile *tile)
|
||||||
|
{
|
||||||
|
const Position *cr = &map->currentRoom;
|
||||||
|
Room *room = map->rooms[cr->x][cr->y];
|
||||||
|
switch_tile(map, tile_pos, tile, &room->doors[tile_pos->x][tile_pos->y]);
|
||||||
|
tile->door = true;
|
||||||
|
tile->sprite->texture_index = 0;
|
||||||
|
tile->sprite->animate = false;
|
||||||
|
|
||||||
|
map->lockTypes |= tile->lockType;
|
||||||
|
room->lockTypes |= tile->lockType;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
map_add_trap(Map *map, Position *pos, Trap *trap)
|
map_add_trap(Map *map, Position *pos, Trap *trap)
|
||||||
{
|
{
|
||||||
|
@ -295,6 +318,12 @@ map_update(UpdateData *data)
|
||||||
sprite_update(room->tiles[i][j]->sprite, data);
|
sprite_update(room->tiles[i][j]->sprite, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LinkedList *items = map->items;
|
||||||
|
while (items) {
|
||||||
|
item_update(items->data);
|
||||||
|
items = items->next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void map_render(Map *map, Camera *cam)
|
void map_render(Map *map, Camera *cam)
|
||||||
|
@ -306,6 +335,8 @@ void map_render(Map *map, Camera *cam)
|
||||||
for (i=0; i < MAP_ROOM_WIDTH; ++i) {
|
for (i=0; i < MAP_ROOM_WIDTH; ++i) {
|
||||||
for (j=0; j < MAP_ROOM_HEIGHT; ++j) {
|
for (j=0; j < MAP_ROOM_HEIGHT; ++j) {
|
||||||
map_tile_render(room->tiles[i][j], cam);
|
map_tile_render(room->tiles[i][j], cam);
|
||||||
|
map_tile_render(room->walls[i][j], cam);
|
||||||
|
map_tile_render(room->doors[i][j], cam);
|
||||||
map_tile_render(room->decorations[i][j], cam);
|
map_tile_render(room->decorations[i][j], cam);
|
||||||
|
|
||||||
if (room->traps[i][j])
|
if (room->traps[i][j])
|
||||||
|
@ -398,6 +429,12 @@ void map_room_destroy(Room *room)
|
||||||
if (room->tiles[i][j]) {
|
if (room->tiles[i][j]) {
|
||||||
map_tile_destroy(room->tiles[i][j]);
|
map_tile_destroy(room->tiles[i][j]);
|
||||||
}
|
}
|
||||||
|
if (room->doors[i][j]) {
|
||||||
|
map_tile_destroy(room->doors[i][j]);
|
||||||
|
}
|
||||||
|
if (room->walls[i][j]) {
|
||||||
|
map_tile_destroy(room->walls[i][j]);
|
||||||
|
}
|
||||||
if (room->decorations[i][j]) {
|
if (room->decorations[i][j]) {
|
||||||
map_tile_destroy(room->decorations[i][j]);
|
map_tile_destroy(room->decorations[i][j]);
|
||||||
}
|
}
|
||||||
|
@ -412,10 +449,29 @@ void map_room_destroy(Room *room)
|
||||||
void
|
void
|
||||||
map_trigger_tile_fall(MapTile *tile)
|
map_trigger_tile_fall(MapTile *tile)
|
||||||
{
|
{
|
||||||
|
if (tile->sprite->state != SPRITE_STATE_FALLING && tile->sprite->state != SPRITE_STATE_PLUMMETED)
|
||||||
|
particle_engine_dust_puff(tile->sprite->pos, tile->sprite->dim);
|
||||||
|
|
||||||
tile->sprite->state = SPRITE_STATE_FALLING;
|
tile->sprite->state = SPRITE_STATE_FALLING;
|
||||||
tile->lethal = true;
|
tile->lethal = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
map_open_door(MapTile *tile, Player *player)
|
||||||
|
{
|
||||||
|
if (tile->lockType == LOCK_NONE || tile->lockType & player->equipment.keys) {
|
||||||
|
// Open the door
|
||||||
|
if (tile->lockType != LOCK_NONE)
|
||||||
|
gui_log("You unlocked a door!");
|
||||||
|
|
||||||
|
mixer_play_effect(DOOR_OPEN);
|
||||||
|
tile->sprite->texture_index = 1;
|
||||||
|
tile->collider = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
map_destroy(Map *map)
|
map_destroy(Map *map)
|
||||||
{
|
{
|
||||||
|
@ -439,7 +495,7 @@ map_destroy(Map *map)
|
||||||
artifact_destroy(linkedlist_pop(&map->artifacts));
|
artifact_destroy(linkedlist_pop(&map->artifacts));
|
||||||
|
|
||||||
while (map->objects != NULL)
|
while (map->objects != NULL)
|
||||||
artifact_destroy(linkedlist_pop(&map->objects));
|
object_destroy(linkedlist_pop(&map->objects));
|
||||||
|
|
||||||
timer_destroy(map->monsterMoveTimer);
|
timer_destroy(map->monsterMoveTimer);
|
||||||
free(map);
|
free(map);
|
||||||
|
|
16
src/map.h
16
src/map.h
|
@ -32,6 +32,7 @@
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "map_room_modifiers.h"
|
#include "map_room_modifiers.h"
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
|
#include "doorlocktype.h"
|
||||||
|
|
||||||
typedef struct UpdateData UpdateData;
|
typedef struct UpdateData UpdateData;
|
||||||
typedef struct Trap Trap;
|
typedef struct Trap Trap;
|
||||||
|
@ -42,14 +43,19 @@ typedef struct MapTile_t {
|
||||||
bool lethal;
|
bool lethal;
|
||||||
bool lightsource;
|
bool lightsource;
|
||||||
bool levelExit;
|
bool levelExit;
|
||||||
|
bool door;
|
||||||
|
DoorLockType lockType;
|
||||||
} MapTile;
|
} MapTile;
|
||||||
|
|
||||||
typedef struct Room_t {
|
typedef struct Room_t {
|
||||||
MapTile* tiles[MAP_ROOM_WIDTH][MAP_ROOM_HEIGHT];
|
MapTile* tiles[MAP_ROOM_WIDTH][MAP_ROOM_HEIGHT];
|
||||||
|
MapTile* walls[MAP_ROOM_WIDTH][MAP_ROOM_HEIGHT];
|
||||||
MapTile* decorations[MAP_ROOM_WIDTH][MAP_ROOM_HEIGHT];
|
MapTile* decorations[MAP_ROOM_WIDTH][MAP_ROOM_HEIGHT];
|
||||||
|
MapTile* doors[MAP_ROOM_WIDTH][MAP_ROOM_HEIGHT];
|
||||||
Trap* traps[MAP_ROOM_WIDTH][MAP_ROOM_HEIGHT];
|
Trap* traps[MAP_ROOM_WIDTH][MAP_ROOM_HEIGHT];
|
||||||
RoomModifierData modifier;
|
RoomModifierData modifier;
|
||||||
bool visited;
|
bool visited;
|
||||||
|
unsigned int lockTypes;
|
||||||
} Room;
|
} Room;
|
||||||
|
|
||||||
typedef struct Map_t {
|
typedef struct Map_t {
|
||||||
|
@ -62,6 +68,7 @@ typedef struct Map_t {
|
||||||
Position currentRoom;
|
Position currentRoom;
|
||||||
Timer *monsterMoveTimer;
|
Timer *monsterMoveTimer;
|
||||||
int level;
|
int level;
|
||||||
|
unsigned int lockTypes;
|
||||||
} Map;
|
} Map;
|
||||||
|
|
||||||
Map*
|
Map*
|
||||||
|
@ -76,9 +83,15 @@ map_add_texture(Map*, const char *path, SDL_Renderer*);
|
||||||
void
|
void
|
||||||
map_add_tile(Map *map, Position *tile_pos, MapTile*);
|
map_add_tile(Map *map, Position *tile_pos, MapTile*);
|
||||||
|
|
||||||
|
void
|
||||||
|
map_add_wall(Map *map, Position *tile_pos, MapTile*);
|
||||||
|
|
||||||
void
|
void
|
||||||
map_add_decoration(Map *map, Position *tile_pos, MapTile*);
|
map_add_decoration(Map *map, Position *tile_pos, MapTile*);
|
||||||
|
|
||||||
|
void
|
||||||
|
map_add_door(Map *map, Position *tile_pos, MapTile*);
|
||||||
|
|
||||||
void
|
void
|
||||||
map_add_trap(Map*, Position*, Trap*);
|
map_add_trap(Map*, Position*, Trap*);
|
||||||
|
|
||||||
|
@ -112,6 +125,9 @@ map_set_current_room(Map*, Position*);
|
||||||
void
|
void
|
||||||
map_trigger_tile_fall(MapTile *tile);
|
map_trigger_tile_fall(MapTile *tile);
|
||||||
|
|
||||||
|
bool
|
||||||
|
map_open_door(MapTile *tile, Player *player);
|
||||||
|
|
||||||
void
|
void
|
||||||
map_destroy(Map*);
|
map_destroy(Map*);
|
||||||
|
|
||||||
|
|
153
src/map_lua.c
153
src/map_lua.c
|
@ -37,6 +37,7 @@
|
||||||
#include "item_builder.h"
|
#include "item_builder.h"
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
#include "bh_random.h"
|
#include "bh_random.h"
|
||||||
|
#include "artifact.h"
|
||||||
|
|
||||||
static
|
static
|
||||||
lua_State* load_lua_state(void)
|
lua_State* load_lua_state(void)
|
||||||
|
@ -94,6 +95,18 @@ SDL_Renderer* luaL_checksdlrenderer(lua_State *L)
|
||||||
return renderer;
|
return renderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Player*
|
||||||
|
luaL_checkplayer(lua_State *L)
|
||||||
|
{
|
||||||
|
Player *player;
|
||||||
|
lua_getglobal(L, "_game_player");
|
||||||
|
if (!lua_islightuserdata(L, -1))
|
||||||
|
fatal("in luaL_checkplayer(), pointer lost in lua script");
|
||||||
|
|
||||||
|
player = lua_touserdata(L, -1);
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
l_map_set_current_room_modifier(lua_State *L)
|
l_map_set_current_room_modifier(lua_State *L)
|
||||||
{
|
{
|
||||||
|
@ -169,6 +182,7 @@ extract_tile_data(lua_State *L,
|
||||||
int tile_x, tile_y;
|
int tile_x, tile_y;
|
||||||
int t_index0, t_index1, tile_clip_x, tile_clip_y;
|
int t_index0, t_index1, tile_clip_x, tile_clip_y;
|
||||||
bool collider, lightsource, levelExit, lethal;
|
bool collider, lightsource, levelExit, lethal;
|
||||||
|
int lockType;
|
||||||
|
|
||||||
map = luaL_checkmap(L, 1);
|
map = luaL_checkmap(L, 1);
|
||||||
tile_x = (int) luaL_checkinteger(L, 2);
|
tile_x = (int) luaL_checkinteger(L, 2);
|
||||||
|
@ -187,18 +201,20 @@ extract_tile_data(lua_State *L,
|
||||||
lua_getfield(L, 4, "isLightSource");
|
lua_getfield(L, 4, "isLightSource");
|
||||||
lua_getfield(L, 4, "isLevelExit");
|
lua_getfield(L, 4, "isLevelExit");
|
||||||
lua_getfield(L, 4, "isLethal");
|
lua_getfield(L, 4, "isLethal");
|
||||||
|
lua_getfield(L, 4, "lockType");
|
||||||
|
|
||||||
t_index0 = (int) luaL_checkinteger(L, -8);
|
t_index0 = (int) luaL_checkinteger(L, -9);
|
||||||
t_index1 = (int) luaL_checkinteger(L, -7);
|
t_index1 = (int) luaL_checkinteger(L, -8);
|
||||||
tile_clip_x = (int) luaL_checkinteger(L, -6);
|
tile_clip_x = (int) luaL_checkinteger(L, -7);
|
||||||
tile_clip_y = (int) luaL_checkinteger(L, -5);
|
tile_clip_y = (int) luaL_checkinteger(L, -6);
|
||||||
collider = lua_toboolean(L, -4);
|
collider = lua_toboolean(L, -5);
|
||||||
lightsource = lua_toboolean(L, -3);
|
lightsource = lua_toboolean(L, -4);
|
||||||
levelExit = lua_toboolean(L, -2);
|
levelExit = lua_toboolean(L, -3);
|
||||||
lethal = lua_toboolean(L, -1);
|
lethal = lua_toboolean(L, -2);
|
||||||
|
lockType = (int) luaL_checkinteger(L, -1);
|
||||||
|
|
||||||
// Clear the stack
|
// Clear the stack
|
||||||
lua_pop(L, 8);
|
lua_pop(L, 9);
|
||||||
|
|
||||||
Position tilePos = (Position) { tile_x, tile_y };
|
Position tilePos = (Position) { tile_x, tile_y };
|
||||||
SDL_Rect clip = (SDL_Rect) { tile_clip_x, tile_clip_y, 16, 16 };
|
SDL_Rect clip = (SDL_Rect) { tile_clip_x, tile_clip_y, 16, 16 };
|
||||||
|
@ -214,6 +230,7 @@ extract_tile_data(lua_State *L,
|
||||||
tile->lightsource = lightsource;
|
tile->lightsource = lightsource;
|
||||||
tile->levelExit = levelExit;
|
tile->levelExit = levelExit;
|
||||||
tile->lethal = lethal;
|
tile->lethal = lethal;
|
||||||
|
tile->lockType = lockType;
|
||||||
|
|
||||||
f_add_tile(map, &tilePos, tile);
|
f_add_tile(map, &tilePos, tile);
|
||||||
}
|
}
|
||||||
|
@ -258,6 +275,20 @@ l_add_tile(lua_State *L)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
l_add_wall(lua_State *L)
|
||||||
|
{
|
||||||
|
extract_tile_data(L, &map_add_wall);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
l_add_door(lua_State *L)
|
||||||
|
{
|
||||||
|
extract_tile_data(L, &map_add_door);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
l_add_decoration(lua_State *L)
|
l_add_decoration(lua_State *L)
|
||||||
{
|
{
|
||||||
|
@ -359,6 +390,52 @@ l_add_chest(lua_State *L)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
monster_is_in_room_with_locktype(Map *map, Monster *m, DoorLockType lockType)
|
||||||
|
{
|
||||||
|
Position roomPos = position_to_room_coords(&m->sprite->pos);
|
||||||
|
Room *room = map->rooms[roomPos.x][roomPos.y];
|
||||||
|
return room->lockTypes & lockType;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_keybearer_to_map(Map *map, int keyType)
|
||||||
|
{
|
||||||
|
for (size_t tries = 0; tries < 10; tries++) {
|
||||||
|
unsigned int max = linkedlist_size(map->monsters);
|
||||||
|
unsigned int index = bh_map_rand() % max;
|
||||||
|
|
||||||
|
Monster *m = linkedlist_get(&map->monsters, index);
|
||||||
|
if (!m)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (m->items.keyType != LOCK_NONE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!monster_is_in_room_with_locktype(map, m, keyType)) {
|
||||||
|
debug("Adding key %d to monster '%s' (%u)", keyType, m->label, index);
|
||||||
|
m->items.keyType = keyType;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
debug("Looking for another monster to be the keybearer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error("Failed to find a suitable keybearer (%d)", keyType);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
l_add_key_to_random_monsters(lua_State *L)
|
||||||
|
{
|
||||||
|
Map *map = luaL_checkmap(L, 1);
|
||||||
|
if (map->lockTypes & LOCK_GOLD)
|
||||||
|
add_keybearer_to_map(map, LOCK_GOLD);
|
||||||
|
if (map->lockTypes & LOCK_SILVER)
|
||||||
|
add_keybearer_to_map(map, LOCK_SILVER);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
l_add_monster(lua_State *L)
|
l_add_monster(lua_State *L)
|
||||||
{
|
{
|
||||||
|
@ -404,6 +481,7 @@ l_add_monster(lua_State *L)
|
||||||
|
|
||||||
lua_pop(L, 8);
|
lua_pop(L, 8);
|
||||||
|
|
||||||
|
// Make sure traders stay hostile if you've killed one
|
||||||
monster = monster_create();
|
monster = monster_create();
|
||||||
monster->sprite->clip = (SDL_Rect) { clip_x, clip_y, 16, 16 };
|
monster->sprite->clip = (SDL_Rect) { clip_x, clip_y, 16, 16 };
|
||||||
monster_update_pos(monster, (Position) { x, y });
|
monster_update_pos(monster, (Position) { x, y });
|
||||||
|
@ -492,8 +570,40 @@ l_get_random(lua_State *L)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
l_create_shop_artifact(lua_State *L)
|
||||||
|
{
|
||||||
|
Player *player = luaL_checkplayer(L);
|
||||||
|
|
||||||
|
if (player == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Map *map = luaL_checkmap(L, 1);
|
||||||
|
int x = (int) luaL_checkinteger(L, 2);
|
||||||
|
int y = (int) luaL_checkinteger(L, 3);
|
||||||
|
|
||||||
|
Artifact *a = artifact_create_random(player, 2);
|
||||||
|
a->sprite->pos = POS(x, y);
|
||||||
|
artifact_add_price(a, 100);
|
||||||
|
|
||||||
|
linkedlist_append(&map->artifacts, a);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
build_player_state_table(lua_State *L, Player *player)
|
||||||
|
{
|
||||||
|
lua_createtable(L, 0, 1);
|
||||||
|
lua_pushboolean(L, player ? player->stateData.shopOwnerKiller : false);
|
||||||
|
lua_setfield(L, -2, "shopOwnerKiller");
|
||||||
|
lua_pushnumber(L, player ? player->stats.lvl : 1);
|
||||||
|
lua_setfield(L, -2, "level");
|
||||||
|
lua_setglobal(L, "PlayerData");
|
||||||
|
}
|
||||||
|
|
||||||
static Map*
|
static Map*
|
||||||
generate_map(unsigned int level, const char *file, GameMode gameMode, SDL_Renderer *renderer)
|
generate_map(unsigned int level, const char *file, GameMode gameMode, Player *player, SDL_Renderer *renderer)
|
||||||
{
|
{
|
||||||
int status, result;
|
int status, result;
|
||||||
|
|
||||||
|
@ -512,9 +622,17 @@ generate_map(unsigned int level, const char *file, GameMode gameMode, SDL_Render
|
||||||
}
|
}
|
||||||
|
|
||||||
// Present stuff to lua
|
// Present stuff to lua
|
||||||
|
build_player_state_table(L, player);
|
||||||
|
|
||||||
lua_pushlightuserdata(L, renderer);
|
lua_pushlightuserdata(L, renderer);
|
||||||
lua_setglobal(L, "_sdl_renderer");
|
lua_setglobal(L, "_sdl_renderer");
|
||||||
|
|
||||||
|
lua_pushlightuserdata(L, player);
|
||||||
|
lua_setglobal(L, "_game_player");
|
||||||
|
|
||||||
|
lua_pushcfunction(L, l_create_shop_artifact);
|
||||||
|
lua_setglobal(L, "create_shop_artifact");
|
||||||
|
|
||||||
lua_pushcfunction(L, l_create_map);
|
lua_pushcfunction(L, l_create_map);
|
||||||
lua_setglobal(L, "create_map");
|
lua_setglobal(L, "create_map");
|
||||||
|
|
||||||
|
@ -524,6 +642,12 @@ generate_map(unsigned int level, const char *file, GameMode gameMode, SDL_Render
|
||||||
lua_pushcfunction(L, l_add_tile);
|
lua_pushcfunction(L, l_add_tile);
|
||||||
lua_setglobal(L, "add_tile");
|
lua_setglobal(L, "add_tile");
|
||||||
|
|
||||||
|
lua_pushcfunction(L, l_add_wall);
|
||||||
|
lua_setglobal(L, "add_wall");
|
||||||
|
|
||||||
|
lua_pushcfunction(L, l_add_door);
|
||||||
|
lua_setglobal(L, "add_door");
|
||||||
|
|
||||||
lua_pushcfunction(L, l_add_decoration);
|
lua_pushcfunction(L, l_add_decoration);
|
||||||
lua_setglobal(L, "add_decoration");
|
lua_setglobal(L, "add_decoration");
|
||||||
|
|
||||||
|
@ -548,6 +672,9 @@ generate_map(unsigned int level, const char *file, GameMode gameMode, SDL_Render
|
||||||
lua_pushcfunction(L, l_add_monster);
|
lua_pushcfunction(L, l_add_monster);
|
||||||
lua_setglobal(L, "add_monster");
|
lua_setglobal(L, "add_monster");
|
||||||
|
|
||||||
|
lua_pushcfunction(L, l_add_key_to_random_monsters);
|
||||||
|
lua_setglobal(L, "add_keybearers");
|
||||||
|
|
||||||
lua_pushcfunction(L, l_get_random_seed);
|
lua_pushcfunction(L, l_get_random_seed);
|
||||||
lua_setglobal(L, "get_random_seed");
|
lua_setglobal(L, "get_random_seed");
|
||||||
|
|
||||||
|
@ -594,13 +721,13 @@ generate_map(unsigned int level, const char *file, GameMode gameMode, SDL_Render
|
||||||
Map* map_lua_generator_single_room__run(unsigned int level, SDL_Renderer *renderer)
|
Map* map_lua_generator_single_room__run(unsigned int level, SDL_Renderer *renderer)
|
||||||
{
|
{
|
||||||
char file[] = "menumapgen.lua";
|
char file[] = "menumapgen.lua";
|
||||||
return generate_map(level, file, REGULAR, renderer);
|
return generate_map(level, file, REGULAR, NULL, renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map* map_lua_generator_run(unsigned int level, GameMode gameMode, SDL_Renderer *renderer)
|
Map* map_lua_generator_run(unsigned int level, GameMode gameMode, Player *player, SDL_Renderer *renderer)
|
||||||
{
|
{
|
||||||
char file[] = "mapgen.lua";
|
char file[] = "mapgen.lua";
|
||||||
return generate_map(level, file, gameMode, renderer);
|
return generate_map(level, file, gameMode, player, renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
|
|
||||||
Map* map_lua_generator_run(unsigned int level, GameMode gameMode, SDL_Renderer *renderer);
|
Map* map_lua_generator_run(unsigned int level, GameMode gameMode, Player *player, SDL_Renderer *renderer);
|
||||||
Map* map_lua_generator_single_room__run(unsigned int level, SDL_Renderer *renderer);
|
Map* map_lua_generator_single_room__run(unsigned int level, SDL_Renderer *renderer);
|
||||||
|
|
||||||
#endif // MAP_LUA_H_
|
#endif // MAP_LUA_H_
|
||||||
|
|
15
src/menu.c
15
src/menu.c
|
@ -106,22 +106,25 @@ menu_create_character_selector(void (*onCharacterSelect)(const char *), Camera *
|
||||||
{
|
{
|
||||||
const char *spriteSheets[] = {
|
const char *spriteSheets[] = {
|
||||||
"Commissions/Warrior.png",
|
"Commissions/Warrior.png",
|
||||||
"Commissions/Rogue.png"
|
"Commissions/Rogue.png",
|
||||||
|
"Commissions/Mage.png"
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *callbackData[] = {
|
static const char *callbackData[] = {
|
||||||
"warrior",
|
"warrior",
|
||||||
"rogue"
|
"rogue",
|
||||||
|
"mage"
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *descriptions[] = {
|
static char *descriptions[] = {
|
||||||
"Play as the warrior",
|
"Play as the warrior",
|
||||||
"Play as the rogue",
|
"Play as the rogue",
|
||||||
|
"Play as the mage"
|
||||||
};
|
};
|
||||||
|
|
||||||
Menu *menu = menu_create();
|
Menu *menu = menu_create();
|
||||||
int xoffset = 224;
|
int xoffset = 168;
|
||||||
for (size_t i = 0; i < 2; ++i) {
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
Sprite *s1 = sprite_create();
|
Sprite *s1 = sprite_create();
|
||||||
sprite_set_texture(s1, texturecache_add(spriteSheets[i]), 0);
|
sprite_set_texture(s1, texturecache_add(spriteSheets[i]), 0);
|
||||||
s1->clip = CLIP16(0, 48);
|
s1->clip = CLIP16(0, 48);
|
||||||
|
@ -139,7 +142,7 @@ menu_create_character_selector(void (*onCharacterSelect)(const char *), Camera *
|
||||||
menu_item_add(menu, s1, s2, (void (*)(void *)) onCharacterSelect);
|
menu_item_add(menu, s1, s2, (void (*)(void *)) onCharacterSelect);
|
||||||
MenuItem *item = linkedlist_get(&menu->items, (Uint32) i);
|
MenuItem *item = linkedlist_get(&menu->items, (Uint32) i);
|
||||||
item->button->usrdata = callbackData[i];
|
item->button->usrdata = callbackData[i];
|
||||||
xoffset += 224;
|
xoffset += 168;
|
||||||
|
|
||||||
linkedlist_append(&menu->descriptions, descriptions[i]);
|
linkedlist_append(&menu->descriptions, descriptions[i]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,8 +26,8 @@
|
||||||
#include "sprite.h"
|
#include "sprite.h"
|
||||||
|
|
||||||
typedef struct TEXT_MENU_ITEM {
|
typedef struct TEXT_MENU_ITEM {
|
||||||
char label[20];
|
char *label;
|
||||||
char description[100];
|
char *description;
|
||||||
void (*callback)(void*);
|
void (*callback)(void*);
|
||||||
} TEXT_MENU_ITEM;
|
} TEXT_MENU_ITEM;
|
||||||
|
|
||||||
|
|
|
@ -88,6 +88,11 @@ load_effects(void)
|
||||||
effects[FADE_IN] = load_effect("Sounds/FX/fade_in.wav");
|
effects[FADE_IN] = load_effect("Sounds/FX/fade_in.wav");
|
||||||
effects[FADE_OUT] = load_effect("Sounds/FX/fade_out.wav");
|
effects[FADE_OUT] = load_effect("Sounds/FX/fade_out.wav");
|
||||||
effects[BURST] = load_effect("Sounds/FX/burst.wav");
|
effects[BURST] = load_effect("Sounds/FX/burst.wav");
|
||||||
|
effects[DOOR_OPEN] = load_effect("Sounds/FX/door_open.wav");
|
||||||
|
effects[KEY_PICKUP] = load_effect("Sounds/FX/key_pickup.wav");
|
||||||
|
effects[BLINK_EFFECT] = load_effect("Sounds/FX/blink.wav");
|
||||||
|
effects[BLAST_EFFECT] = load_effect("Sounds/FX/blast.wav");
|
||||||
|
effects[EXPLOSION_EFFECT] = load_effect("Sounds/FX/explosion.wav");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -109,7 +114,7 @@ mixer_toggle_sound(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
mixer_toggle_music(GameState *state)
|
mixer_toggle_music(const GameState *state)
|
||||||
{
|
{
|
||||||
Settings *settings = settings_get();
|
Settings *settings = settings_get();
|
||||||
settings->music_enabled = !settings->music_enabled;
|
settings->music_enabled = !settings->music_enabled;
|
||||||
|
|
|
@ -64,6 +64,11 @@ typedef enum Fx_t {
|
||||||
FADE_IN,
|
FADE_IN,
|
||||||
FADE_OUT,
|
FADE_OUT,
|
||||||
BURST,
|
BURST,
|
||||||
|
DOOR_OPEN,
|
||||||
|
KEY_PICKUP,
|
||||||
|
BLINK_EFFECT,
|
||||||
|
BLAST_EFFECT,
|
||||||
|
EXPLOSION_EFFECT,
|
||||||
LAST_EFFECT
|
LAST_EFFECT
|
||||||
} Fx;
|
} Fx;
|
||||||
|
|
||||||
|
@ -74,7 +79,7 @@ bool
|
||||||
mixer_toggle_sound(void);
|
mixer_toggle_sound(void);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
mixer_toggle_music(GameState*);
|
mixer_toggle_music(const GameState*);
|
||||||
|
|
||||||
void
|
void
|
||||||
mixer_play_effect(Fx fx);
|
mixer_play_effect(Fx fx);
|
||||||
|
|
158
src/monster.c
158
src/monster.c
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "monster.h"
|
#include "monster.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
@ -127,15 +128,20 @@ damage_surroundings(Monster *m, RoomMatrix *rm)
|
||||||
for (Sint32 j = -1; j <= 1; ++j) {
|
for (Sint32 j = -1; j <= 1; ++j) {
|
||||||
if (i == 0 && j == 0)
|
if (i == 0 && j == 0)
|
||||||
continue;
|
continue;
|
||||||
RoomSpace *r = &rm->spaces[roomPos.x + i][roomPos.y + j];
|
|
||||||
|
Position matrixPos = POS(roomPos.x + i, roomPos.y + j);
|
||||||
|
if (!position_in_roommatrix(&matrixPos))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
RoomSpace *r = &rm->spaces[matrixPos.x][matrixPos.y];
|
||||||
if (r->monster) {
|
if (r->monster) {
|
||||||
int dmg = stats_fight(&m->stats, &r->monster->stats);
|
CombatResult result = stats_fight(&m->stats, &r->monster->stats);
|
||||||
monster_hit(r->monster, dmg);
|
monster_hit(r->monster, result.dmg, result.critical);
|
||||||
gui_log("%s takes %d damage from the explosion", r->monster->label, dmg);
|
gui_log("%s takes %d damage from the explosion", r->monster->label, result.dmg);
|
||||||
} else if (r->player) {
|
} else if (r->player) {
|
||||||
int dmg = stats_fight(&m->stats, &r->player->stats);
|
CombatResult result = stats_fight(&m->stats, &r->player->stats);
|
||||||
player_hit(r->player, dmg);
|
player_hit(r->player, result.dmg);
|
||||||
gui_log("You take %d damage from the explosion", dmg);
|
gui_log("You take %d damage from the explosion", result.dmg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -208,6 +214,9 @@ handle_sentinel_behaviour(Monster *m, RoomMatrix *rm)
|
||||||
static void
|
static void
|
||||||
monster_behaviour_check(Monster *m, RoomMatrix *rm)
|
monster_behaviour_check(Monster *m, RoomMatrix *rm)
|
||||||
{
|
{
|
||||||
|
if (m->state.stepsSinceChange < m->state.forceCount)
|
||||||
|
return;
|
||||||
|
|
||||||
switch (m->behaviour) {
|
switch (m->behaviour) {
|
||||||
case GUERILLA:
|
case GUERILLA:
|
||||||
case SORCERER:
|
case SORCERER:
|
||||||
|
@ -232,6 +241,24 @@ monster_behaviour_check(Monster *m, RoomMatrix *rm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
create_emitters(Monster *m)
|
||||||
|
{
|
||||||
|
// Bloodlust
|
||||||
|
ParticleEmitter *emitter = particle_emitter_create();
|
||||||
|
emitter->timestep = 0;
|
||||||
|
emitter->enabled = false;
|
||||||
|
emitter->particle_func = particle_engine_bloodlust;
|
||||||
|
m->emitters.bloodlust = emitter;
|
||||||
|
|
||||||
|
emitter = particle_emitter_create();
|
||||||
|
emitter->timestep = 1000;
|
||||||
|
emitter->enabled = false;
|
||||||
|
emitter->particle_func = particle_engine_bleed;
|
||||||
|
m->emitters.bleed = emitter;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Monster*
|
Monster*
|
||||||
monster_create(void)
|
monster_create(void)
|
||||||
{
|
{
|
||||||
|
@ -264,7 +291,9 @@ monster_create(void)
|
||||||
m->stateIndicator.shownOnPlayerRoomEnter = false;
|
m->stateIndicator.shownOnPlayerRoomEnter = false;
|
||||||
m->state.forceCount = 0;
|
m->state.forceCount = 0;
|
||||||
m->boss = false;
|
m->boss = false;
|
||||||
|
m->items.keyType = LOCK_NONE;
|
||||||
monster_set_behaviour(m, NORMAL);
|
monster_set_behaviour(m, NORMAL);
|
||||||
|
create_emitters(m);
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
@ -288,14 +317,14 @@ has_collided(Monster *monster, RoomMatrix *matrix, Vector2d direction)
|
||||||
RoomSpace *space = roommatrix_get_space_for(matrix, &monster->sprite->pos);
|
RoomSpace *space = roommatrix_get_space_for(matrix, &monster->sprite->pos);
|
||||||
|
|
||||||
if (space->player && monster->state.current == AGRESSIVE) {
|
if (space->player && monster->state.current == AGRESSIVE) {
|
||||||
unsigned int dmg = stats_fight(&monster->stats,
|
CombatResult result = stats_fight(&monster->stats,
|
||||||
&space->player->stats);
|
&space->player->stats);
|
||||||
|
|
||||||
player_hit(space->player, dmg);
|
player_hit(space->player, result.dmg);
|
||||||
|
|
||||||
if (dmg > 0) {
|
if (result.dmg > 0) {
|
||||||
gui_log("%s hit you for %u damage",
|
gui_log("%s hit you for %u damage",
|
||||||
monster->label, dmg);
|
monster->label, result.dmg);
|
||||||
camera_shake(direction, 300);
|
camera_shake(direction, 300);
|
||||||
} else {
|
} else {
|
||||||
gui_log("%s missed you", monster->label);
|
gui_log("%s missed you", monster->label);
|
||||||
|
@ -445,7 +474,7 @@ monster_coward_walk(Monster *m, RoomMatrix *rm)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_monster_move(Monster *m, Position *origPos, Map *map, RoomMatrix *rm)
|
on_monster_move(Monster *m, const Position *origPos, Map *map, RoomMatrix *rm)
|
||||||
{
|
{
|
||||||
Position currentTilePos = position_to_matrix_coords(&m->sprite->pos);
|
Position currentTilePos = position_to_matrix_coords(&m->sprite->pos);
|
||||||
Player *player = rm->spaces[rm->playerRoomPos.x][rm->playerRoomPos.y].player;
|
Player *player = rm->spaces[rm->playerRoomPos.x][rm->playerRoomPos.y].player;
|
||||||
|
@ -530,9 +559,23 @@ monster_perform_aoe_attack(Monster *m, RoomMatrix *rm)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
apply_bleed_damage(Player *p, Monster *m)
|
||||||
|
{
|
||||||
|
if (!m->emitters.bleed->enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint32_t dmg = m->stats.lvl * 2;
|
||||||
|
monster_hit(m, dmg, false);
|
||||||
|
m->stats.hp -= dmg;
|
||||||
|
player_monster_kill_check(p, m);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
monster_move(Monster *m, RoomMatrix *rm, Map *map)
|
monster_move(Monster *m, RoomMatrix *rm, Map *map)
|
||||||
{
|
{
|
||||||
|
apply_bleed_damage(roommatrix_get_player(rm), m);
|
||||||
|
|
||||||
Player *player = roommatrix_get_player(rm);
|
Player *player = roommatrix_get_player(rm);
|
||||||
if (player && player->phase_count)
|
if (player && player->phase_count)
|
||||||
return true;
|
return true;
|
||||||
|
@ -583,6 +626,19 @@ monster_reset_steps(Monster *m)
|
||||||
m->steps = 0;
|
m->steps = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_emitters(Monster *m)
|
||||||
|
{
|
||||||
|
Position pos = m->sprite->pos;
|
||||||
|
pos.x += 6;
|
||||||
|
pos.y += 6;
|
||||||
|
particle_emitter_update(m->emitters.bloodlust, pos, DIM(20, 20));
|
||||||
|
|
||||||
|
pos.x += 5;
|
||||||
|
pos.y += 5;
|
||||||
|
particle_emitter_update(m->emitters.bleed, pos, DIM(10, 10));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
monster_update(Monster *m, UpdateData *data)
|
monster_update(Monster *m, UpdateData *data)
|
||||||
{
|
{
|
||||||
|
@ -590,6 +646,7 @@ monster_update(Monster *m, UpdateData *data)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sprite_update(m->sprite, data);
|
sprite_update(m->sprite, data);
|
||||||
|
update_emitters(m);
|
||||||
|
|
||||||
if (m->sprite->state == SPRITE_STATE_PLUMMETED) {
|
if (m->sprite->state == SPRITE_STATE_PLUMMETED) {
|
||||||
m->stats.hp = 0;
|
m->stats.hp = 0;
|
||||||
|
@ -631,7 +688,7 @@ monster_update(Monster *m, UpdateData *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
monster_hit(Monster *monster, unsigned int dmg)
|
monster_hit(Monster *monster, unsigned int dmg, bool critical)
|
||||||
{
|
{
|
||||||
if (dmg > 0) {
|
if (dmg > 0) {
|
||||||
Position p = monster->sprite->pos;
|
Position p = monster->sprite->pos;
|
||||||
|
@ -649,6 +706,9 @@ monster_hit(Monster *monster, unsigned int dmg)
|
||||||
C_YELLOW,
|
C_YELLOW,
|
||||||
&monster->sprite->pos);
|
&monster->sprite->pos);
|
||||||
}
|
}
|
||||||
|
if (critical)
|
||||||
|
monster_set_bleeding(monster);
|
||||||
|
|
||||||
monster_behaviour_check_post_hit(monster);
|
monster_behaviour_check_post_hit(monster);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -690,6 +750,24 @@ monster_drop_loot(Monster *monster, Map *map, Player *player)
|
||||||
linkedlist_append(&map->items, treasure);
|
linkedlist_append(&map->items, treasure);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (monster->items.keyType != LOCK_NONE) {
|
||||||
|
Item *key = item_builder_build_key(monster->items.keyType);
|
||||||
|
key->sprite->pos = monsterTilePos;
|
||||||
|
linkedlist_append(&map->items, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(monster->label, "The Trader") == 0) {
|
||||||
|
Item *treasure = item_builder_build_treasure(PLATINUM, 10 * monster->stats.lvl);
|
||||||
|
treasure->sprite->pos = monsterTilePos;
|
||||||
|
linkedlist_append(&map->items, treasure);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(monster->label, "A Fairy") == 0) {
|
||||||
|
Item *treasure = item_builder_build_treasure(PLATINUM, 3 * monster->stats.lvl);
|
||||||
|
treasure->sprite->pos = monsterTilePos;
|
||||||
|
linkedlist_append(&map->items, treasure);
|
||||||
|
}
|
||||||
|
|
||||||
if (monster->stats.lvl > 2 && get_random(29) == 0) {
|
if (monster->stats.lvl > 2 && get_random(29) == 0) {
|
||||||
Artifact *a = artifact_create_random(player, 1);
|
Artifact *a = artifact_create_random(player, 1);
|
||||||
a->sprite->pos = monsterTilePos;
|
a->sprite->pos = monsterTilePos;
|
||||||
|
@ -723,15 +801,15 @@ monster_drop_loot(Monster *monster, Map *map, Player *player)
|
||||||
gui_log("%s dropped something", monster->label);
|
gui_log("%s dropped something", monster->label);
|
||||||
|
|
||||||
if (item_count == 1) {
|
if (item_count == 1) {
|
||||||
linkedlist_append(&map->items, items[0]);
|
linkedlist_push(&map->items, items[0]);
|
||||||
} else {
|
} else {
|
||||||
Item *container = item_builder_build_sack();
|
Item *container = item_builder_build_sack();
|
||||||
container->sprite->pos = monsterTilePos;
|
container->sprite->pos = monsterTilePos;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
for (i = 0; i < item_count; ++i) {
|
for (i = 0; i < item_count; ++i) {
|
||||||
linkedlist_append(&container->items, items[i]);
|
linkedlist_push(&container->items, items[i]);
|
||||||
}
|
}
|
||||||
linkedlist_append(&map->items, container);
|
linkedlist_push(&map->items, container);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -741,6 +819,8 @@ monster_render(Monster *m, Camera *cam)
|
||||||
if (m->stats.hp <= 0)
|
if (m->stats.hp <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
particle_emitter_render(m->emitters.bloodlust);
|
||||||
|
particle_emitter_render(m->emitters.bleed);
|
||||||
sprite_render(m->sprite, cam);
|
sprite_render(m->sprite, cam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -804,7 +884,7 @@ monster_push(Monster *m, Player *p, RoomMatrix *rm, Vector2d direction)
|
||||||
if (space->trap) {
|
if (space->trap) {
|
||||||
int dmg = space->trap->damage * 3;
|
int dmg = space->trap->damage * 3;
|
||||||
m->stats.hp -= dmg;
|
m->stats.hp -= dmg;
|
||||||
monster_hit(m, dmg);
|
monster_hit(m, dmg, false);
|
||||||
gui_log("%s takes %d damage from a trap", m->label, dmg);
|
gui_log("%s takes %d damage from a trap", m->label, dmg);
|
||||||
} else if (space->damaging) {
|
} else if (space->damaging) {
|
||||||
LinkedList *objects = space->objects;
|
LinkedList *objects = space->objects;
|
||||||
|
@ -814,7 +894,7 @@ monster_push(Monster *m, Player *p, RoomMatrix *rm, Vector2d direction)
|
||||||
if (!o->damage)
|
if (!o->damage)
|
||||||
return;
|
return;
|
||||||
m->stats.hp -= o->damage * 3;
|
m->stats.hp -= o->damage * 3;
|
||||||
monster_hit(m, o->damage * 3);
|
monster_hit(m, o->damage * 3, false);
|
||||||
}
|
}
|
||||||
} else if (has_collided(m, rm, direction)) {
|
} else if (has_collided(m, rm, direction)) {
|
||||||
m->sprite->pos.x -= TILE_DIMENSION * (int) direction.x;
|
m->sprite->pos.x -= TILE_DIMENSION * (int) direction.x;
|
||||||
|
@ -825,6 +905,42 @@ monster_push(Monster *m, Player *p, RoomMatrix *rm, Vector2d direction)
|
||||||
player_monster_kill_check(p, m);
|
player_monster_kill_check(p, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
monster_set_bloodlust(Monster *m, bool bloodlust)
|
||||||
|
{
|
||||||
|
if (m->emitters.bloodlust->enabled == bloodlust || m->stats.hp <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m->emitters.bloodlust->enabled = bloodlust;
|
||||||
|
if (bloodlust) {
|
||||||
|
gui_log("%s rages with bloodlust", m->label);
|
||||||
|
monster_set_behaviour(m, HOSTILE);
|
||||||
|
m->stats.advantage = true;
|
||||||
|
m->stats.atk += 2;
|
||||||
|
m->stats.def += 2;
|
||||||
|
m->stats.dmg += 2;
|
||||||
|
m->stats.hp += 10;
|
||||||
|
m->stats.maxhp += 10;
|
||||||
|
} else {
|
||||||
|
gui_log("%s calms down from it's bloodlust", m->label);
|
||||||
|
monster_set_behaviour(m, NORMAL);
|
||||||
|
m->stats.advantage = false;
|
||||||
|
m->stats.atk -= 2;
|
||||||
|
m->stats.def -= 2;
|
||||||
|
m->stats.dmg -= 2;
|
||||||
|
m->stats.hp -= 10;
|
||||||
|
m->stats.maxhp -= 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
monster_set_bleeding(Monster *m)
|
||||||
|
{
|
||||||
|
m->emitters.bleed->enabled = true;
|
||||||
|
gui_log("%s starts bleeding profusely", m->label);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
monster_destroy(Monster *m)
|
monster_destroy(Monster *m)
|
||||||
{
|
{
|
||||||
|
@ -833,6 +949,10 @@ monster_destroy(Monster *m)
|
||||||
free(m->label);
|
free(m->label);
|
||||||
if (m->lclabel)
|
if (m->lclabel)
|
||||||
free(m->lclabel);
|
free(m->lclabel);
|
||||||
|
|
||||||
|
particle_emitter_destroy(m->emitters.bloodlust);
|
||||||
|
particle_emitter_destroy(m->emitters.bleed);
|
||||||
|
|
||||||
sprite_destroy(m->stateIndicator.sprite);
|
sprite_destroy(m->stateIndicator.sprite);
|
||||||
free(m);
|
free(m);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#include "actiontext.h"
|
#include "actiontext.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "linkedlist.h"
|
#include "linkedlist.h"
|
||||||
|
#include "doorlocktype.h"
|
||||||
|
#include "particle_emitter.h"
|
||||||
|
|
||||||
struct UpdateData;
|
struct UpdateData;
|
||||||
|
|
||||||
|
@ -63,6 +65,15 @@ typedef struct MonsterStateIndicator {
|
||||||
int displayCount;
|
int displayCount;
|
||||||
} MonsterStateIndicator;
|
} MonsterStateIndicator;
|
||||||
|
|
||||||
|
typedef struct MonsterItems {
|
||||||
|
enum DoorLockType keyType;
|
||||||
|
} MonsterItems;
|
||||||
|
|
||||||
|
typedef struct ParticleEmitters {
|
||||||
|
ParticleEmitter *bloodlust;
|
||||||
|
ParticleEmitter *bleed;
|
||||||
|
} ParticleEmitters;
|
||||||
|
|
||||||
typedef struct Monster {
|
typedef struct Monster {
|
||||||
char *label;
|
char *label;
|
||||||
char *lclabel;
|
char *lclabel;
|
||||||
|
@ -71,6 +82,8 @@ typedef struct Monster {
|
||||||
State state;
|
State state;
|
||||||
MonsterStateIndicator stateIndicator;
|
MonsterStateIndicator stateIndicator;
|
||||||
MonsterBehaviour behaviour;
|
MonsterBehaviour behaviour;
|
||||||
|
MonsterItems items;
|
||||||
|
ParticleEmitters emitters;
|
||||||
unsigned int steps;
|
unsigned int steps;
|
||||||
bool boss;
|
bool boss;
|
||||||
} Monster;
|
} Monster;
|
||||||
|
@ -90,7 +103,7 @@ void
|
||||||
monster_render_top_layer(Monster*, RoomMatrix*, Camera*);
|
monster_render_top_layer(Monster*, RoomMatrix*, Camera*);
|
||||||
|
|
||||||
void
|
void
|
||||||
monster_hit(Monster*, unsigned int dmg);
|
monster_hit(Monster*, unsigned int dmg, bool critical);
|
||||||
|
|
||||||
void
|
void
|
||||||
monster_update_stats_for_level(Monster*, unsigned int level);
|
monster_update_stats_for_level(Monster*, unsigned int level);
|
||||||
|
@ -113,6 +126,12 @@ monster_push(Monster *, Player *, RoomMatrix*, Vector2d dir);
|
||||||
void
|
void
|
||||||
monster_reset_steps(Monster *m);
|
monster_reset_steps(Monster *m);
|
||||||
|
|
||||||
|
void
|
||||||
|
monster_set_bloodlust(Monster*, bool bloodlust);
|
||||||
|
|
||||||
|
void
|
||||||
|
monster_set_bleeding(Monster*);
|
||||||
|
|
||||||
void
|
void
|
||||||
monster_destroy(Monster*);
|
monster_destroy(Monster*);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
#include "particle_emitter.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
ParticleEmitter *
|
||||||
|
particle_emitter_create(void)
|
||||||
|
{
|
||||||
|
ParticleEmitter *emitter = ec_malloc(sizeof(ParticleEmitter));
|
||||||
|
emitter->pos = POS(0, 0);
|
||||||
|
emitter->dim = DIM(32, 32);
|
||||||
|
emitter->particle_func = NULL;
|
||||||
|
emitter->timer = _timer_create();
|
||||||
|
emitter->timestep = 1;
|
||||||
|
emitter->enabled = false;
|
||||||
|
return emitter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
particle_emitter_render(ParticleEmitter *emitter)
|
||||||
|
{
|
||||||
|
if (!emitter->enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!timer_started(emitter->timer)) {
|
||||||
|
timer_start(emitter->timer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timer_get_ticks(emitter->timer) < emitter->timestep)
|
||||||
|
return;
|
||||||
|
|
||||||
|
timer_stop(emitter->timer);
|
||||||
|
timer_start(emitter->timer);
|
||||||
|
|
||||||
|
if (emitter->particle_func)
|
||||||
|
emitter->particle_func(emitter->pos, emitter->dim);
|
||||||
|
else
|
||||||
|
error("Particle emitter missing particle_func");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
particle_emitter_update(ParticleEmitter *emitter, Position pos, Dimension dim)
|
||||||
|
{
|
||||||
|
emitter->pos = pos;
|
||||||
|
emitter->dim = dim;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
particle_emitter_destroy(ParticleEmitter *emitter)
|
||||||
|
{
|
||||||
|
timer_destroy(emitter->timer);
|
||||||
|
emitter->timer = NULL;
|
||||||
|
free(emitter);
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* BreakHack - A dungeone crawler RPG
|
||||||
|
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "timer.h"
|
||||||
|
#include "position.h"
|
||||||
|
#include "dimension.h"
|
||||||
|
|
||||||
|
typedef struct ParticleEmitter {
|
||||||
|
unsigned int timestep;
|
||||||
|
Timer *timer;
|
||||||
|
Position pos;
|
||||||
|
Dimension dim;
|
||||||
|
void (*particle_func)(Position, Dimension);
|
||||||
|
bool enabled;
|
||||||
|
} ParticleEmitter;
|
||||||
|
|
||||||
|
ParticleEmitter *
|
||||||
|
particle_emitter_create(void);
|
||||||
|
|
||||||
|
void
|
||||||
|
particle_emitter_render(ParticleEmitter*);
|
||||||
|
|
||||||
|
void
|
||||||
|
particle_emitter_update(ParticleEmitter*, Position, Dimension);
|
||||||
|
|
||||||
|
void
|
||||||
|
particle_emitter_destroy(ParticleEmitter*);
|
|
@ -100,6 +100,12 @@ particle_engine_init(void)
|
||||||
engine->global_particles = linkedlist_create();
|
engine->global_particles = linkedlist_create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
particle_engine_bleed(Position pos, Dimension dim)
|
||||||
|
{
|
||||||
|
particle_engine_bloodspray(pos, dim, 10);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
particle_engine_bloodspray(Position pos, Dimension dim, unsigned int count)
|
particle_engine_bloodspray(Position pos, Dimension dim, unsigned int count)
|
||||||
{
|
{
|
||||||
|
@ -181,6 +187,13 @@ particle_engine_fire_explosion(Position pos, Dimension dim)
|
||||||
create_explosion(pos, dim, 3, C_YELLOW, C_YELLOW, C_RED);
|
create_explosion(pos, dim, 3, C_YELLOW, C_YELLOW, C_RED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
particle_engine_blink(Position pos, Dimension dim)
|
||||||
|
{
|
||||||
|
check_engine();
|
||||||
|
create_explosion(pos, dim, 3, (SDL_Color) { 0, 0, 255, 255 }, C_BLUE, C_LIGHTBLUE);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
particle_engine_eldritch_explosion(Position pos, Dimension dim)
|
particle_engine_eldritch_explosion(Position pos, Dimension dim)
|
||||||
{
|
{
|
||||||
|
@ -188,6 +201,38 @@ particle_engine_eldritch_explosion(Position pos, Dimension dim)
|
||||||
create_explosion(pos, dim, 1, C_GREEN);
|
create_explosion(pos, dim, 1, C_GREEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
particle_engine_dust_puff(Position pos, Dimension dim)
|
||||||
|
{
|
||||||
|
check_engine();
|
||||||
|
for (unsigned int i = 0; i < 50; ++i) {
|
||||||
|
int x, y, xv, yv, w, h;
|
||||||
|
unsigned int lt;
|
||||||
|
Particle *p;
|
||||||
|
|
||||||
|
x = get_random(dim.width) + pos.x;
|
||||||
|
y = get_random(dim.height) + pos.y;
|
||||||
|
|
||||||
|
xv = get_random(200) - 100;
|
||||||
|
yv = get_random(200) - 100;
|
||||||
|
|
||||||
|
lt = get_random(10) + 10;
|
||||||
|
|
||||||
|
w = get_random(3);
|
||||||
|
h = get_random(3);
|
||||||
|
|
||||||
|
p = create_rect_particle();
|
||||||
|
p->particle.rect.pos = (Position) { x, y };
|
||||||
|
p->particle.rect.dim = (Dimension) { w, h };
|
||||||
|
p->velocity = (Vector2d) { (float) xv, (float) yv };
|
||||||
|
p->movetime = lt;
|
||||||
|
p->lifetime = lt;
|
||||||
|
p->color = C_GREY;
|
||||||
|
p->blend_mode = SDL_BLENDMODE_BLEND;
|
||||||
|
linkedlist_append(&engine->game_particles, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
particle_engine_speed_lines(Position pos, Dimension dim, bool horizontal)
|
particle_engine_speed_lines(Position pos, Dimension dim, bool horizontal)
|
||||||
{
|
{
|
||||||
|
@ -222,6 +267,12 @@ particle_engine_speed_lines(Position pos, Dimension dim, bool horizontal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
particle_engine_bloodlust(Position pos, Dimension dim)
|
||||||
|
{
|
||||||
|
particle_engine_sparkle(pos, dim, C_RED, false);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
particle_engine_sparkle(Position pos, Dimension dim, SDL_Color color, bool global)
|
particle_engine_sparkle(Position pos, Dimension dim, SDL_Color color, bool global)
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,18 +28,30 @@
|
||||||
void
|
void
|
||||||
particle_engine_init(void);
|
particle_engine_init(void);
|
||||||
|
|
||||||
|
void
|
||||||
|
particle_engine_bleed(Position pos, Dimension dim);
|
||||||
|
|
||||||
void
|
void
|
||||||
particle_engine_bloodspray(Position, Dimension, unsigned int count);
|
particle_engine_bloodspray(Position, Dimension, unsigned int count);
|
||||||
|
|
||||||
void
|
void
|
||||||
particle_engine_fire_explosion(Position, Dimension);
|
particle_engine_fire_explosion(Position, Dimension);
|
||||||
|
|
||||||
|
void
|
||||||
|
particle_engine_blink(Position, Dimension);
|
||||||
|
|
||||||
void
|
void
|
||||||
particle_engine_eldritch_explosion(Position, Dimension);
|
particle_engine_eldritch_explosion(Position, Dimension);
|
||||||
|
|
||||||
|
void
|
||||||
|
particle_engine_dust_puff(Position, Dimension);
|
||||||
|
|
||||||
void
|
void
|
||||||
particle_engine_speed_lines(Position, Dimension, bool horizontal);
|
particle_engine_speed_lines(Position, Dimension, bool horizontal);
|
||||||
|
|
||||||
|
void
|
||||||
|
particle_engine_bloodlust(Position, Dimension);
|
||||||
|
|
||||||
void
|
void
|
||||||
particle_engine_sparkle(Position, Dimension, SDL_Color, bool global);
|
particle_engine_sparkle(Position, Dimension, SDL_Color, bool global);
|
||||||
|
|
||||||
|
|
87
src/player.c
87
src/player.c
|
@ -36,13 +36,15 @@
|
||||||
#include "animation.h"
|
#include "animation.h"
|
||||||
#include "trap.h"
|
#include "trap.h"
|
||||||
#include "gamecontroller.h"
|
#include "gamecontroller.h"
|
||||||
|
#include "event.h"
|
||||||
|
#include "effect_util.h"
|
||||||
|
|
||||||
#ifdef STEAM_BUILD
|
#ifdef STEAM_BUILD
|
||||||
#include "steam/steamworks_api_wrapper.h"
|
#include "steam/steamworks_api_wrapper.h"
|
||||||
#endif // STEAM_BUILD
|
#endif // STEAM_BUILD
|
||||||
|
|
||||||
#define ENGINEER_STATS { 12, 12, 5, 7, 2, 2, 1, false, false }
|
#define ENGINEER_STATS { 12, 12, 5, 7, 2, 1, 1, false, false }
|
||||||
#define MAGE_STATS { 12, 12, 5, 7, 1, 2, 1, false, false }
|
#define MAGE_STATS { 12, 12, 5, 7, 1, 1, 1, false, false }
|
||||||
#define PALADIN_STATS { 12, 12, 8, 9, 3, 1, 1, false, false }
|
#define PALADIN_STATS { 12, 12, 8, 9, 3, 1, 1, false, false }
|
||||||
#define ROGUE_STATS { 9, 9, 6, 9, 4, 2, 1, false, false }
|
#define ROGUE_STATS { 9, 9, 6, 9, 4, 2, 1, false, false }
|
||||||
#define WARRIOR_STATS { 12, 12, 8, 9, 3, 1, 1, false, false }
|
#define WARRIOR_STATS { 12, 12, 8, 9, 3, 1, 1, false, false }
|
||||||
|
@ -132,16 +134,16 @@ on_monster_collision(Player *player,
|
||||||
RoomMatrix *matrix,
|
RoomMatrix *matrix,
|
||||||
Vector2d direction)
|
Vector2d direction)
|
||||||
{
|
{
|
||||||
unsigned int hit = stats_fight(&player->stats,
|
CombatResult result = stats_fight(&player->stats,
|
||||||
&monster->stats);
|
&monster->stats);
|
||||||
|
|
||||||
mixer_play_effect(SWING0 + get_random(2));
|
mixer_play_effect(SWING0 + get_random(2));
|
||||||
monster_hit(monster, hit);
|
monster_hit(monster, result.dmg, result.critical);
|
||||||
animation_run(player->swordAnimation);
|
animation_run(player->swordAnimation);
|
||||||
|
|
||||||
if (hit > 0) {
|
if (result.dmg > 0) {
|
||||||
gui_log("You hit %s for %u damage",
|
gui_log("You hit %s for %u damage",
|
||||||
monster->lclabel, hit);
|
monster->lclabel, result.dmg);
|
||||||
player->stat_data.hits += 1;
|
player->stat_data.hits += 1;
|
||||||
mixer_play_effect(SWORD_HIT);
|
mixer_play_effect(SWORD_HIT);
|
||||||
} else {
|
} else {
|
||||||
|
@ -149,6 +151,17 @@ on_monster_collision(Player *player,
|
||||||
player->stat_data.misses += 1;
|
player->stat_data.misses += 1;
|
||||||
}
|
}
|
||||||
player_monster_kill_check(player, monster);
|
player_monster_kill_check(player, monster);
|
||||||
|
if (monster->stats.hp <= 0 && (player_has_artifact(player, EXPLOSIVE_KILLS))) {
|
||||||
|
mixer_play_effect(EXPLOSION_EFFECT);
|
||||||
|
particle_engine_fire_explosion(monster->sprite->pos, DIM(32, 32));
|
||||||
|
effect_damage_surroundings(&monster->sprite->pos,
|
||||||
|
matrix,
|
||||||
|
player,
|
||||||
|
&player->stats,
|
||||||
|
player_has_artifact(player, EXPLOSIVE_KILLS),
|
||||||
|
0,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
if (monster->stats.hp > 0) {
|
if (monster->stats.hp > 0) {
|
||||||
if (get_random(10) < player_has_artifact(player, PUSH_BACK)) {
|
if (get_random(10) < player_has_artifact(player, PUSH_BACK)) {
|
||||||
|
@ -238,17 +251,22 @@ has_collided(Player *player, RoomMatrix *matrix, Vector2d direction)
|
||||||
gamecontroller_rumble(0.30f, 100);
|
gamecontroller_rumble(0.30f, 100);
|
||||||
if (space->monster) {
|
if (space->monster) {
|
||||||
on_monster_collision(player, space->monster, matrix, direction);
|
on_monster_collision(player, space->monster, matrix, direction);
|
||||||
|
} else if (space->door && map_open_door(space->door, player)) {
|
||||||
|
// Door opened, pass
|
||||||
} else {
|
} else {
|
||||||
mixer_play_effect(BONK);
|
mixer_play_effect(BONK);
|
||||||
camera_shake(direction, 100);
|
camera_shake(direction, 100);
|
||||||
gui_log("Ouch! There is something in the way");
|
if (space->door)
|
||||||
|
gui_log("Ouch! That door seems to be locked");
|
||||||
|
else
|
||||||
|
gui_log("Ouch! There is something in the way");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
player_collect_items(player, space);
|
player_collect_items(player, space);
|
||||||
player_pickup_artifacts(player, space);
|
player_pickup_artifacts(player, space);
|
||||||
|
|
||||||
// If not phased or phase will end this turn, react to traps and pits
|
// If not phased or phase will end this turn, react to traps and pits
|
||||||
if (!player->phase_count || (player->phase_count == 1 && player->stats.speed == (player->stat_data.steps + 1))) {
|
if (!player->phase_count || (player->phase_count == 1 && player->stats.speed == (player->stat_data.steps + 1))) {
|
||||||
player_interact_objects(player, space);
|
player_interact_objects(player, space);
|
||||||
|
@ -320,7 +338,7 @@ move(Player *player, RoomMatrix *matrix, Vector2d direction)
|
||||||
lastSpace->trap == NULL &&
|
lastSpace->trap == NULL &&
|
||||||
lastSpace->objects == NULL &&
|
lastSpace->objects == NULL &&
|
||||||
lastSpace->items == NULL
|
lastSpace->items == NULL
|
||||||
)
|
)
|
||||||
map_trigger_tile_fall(lastSpace->tile);
|
map_trigger_tile_fall(lastSpace->tile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -328,8 +346,13 @@ move(Player *player, RoomMatrix *matrix, Vector2d direction)
|
||||||
void
|
void
|
||||||
player_sip_health(Player *player)
|
player_sip_health(Player *player)
|
||||||
{
|
{
|
||||||
if (player->potion_sips > 0) {
|
bool hasSips = player->class == MAGE ?
|
||||||
|
player->potion_sips > 1 : player->potion_sips > 0;
|
||||||
|
|
||||||
|
if (hasSips) {
|
||||||
--player->potion_sips;
|
--player->potion_sips;
|
||||||
|
if (player->class == MAGE)
|
||||||
|
--player->potion_sips;
|
||||||
++player->stats.hp;
|
++player->stats.hp;
|
||||||
mixer_play_effect(BUBBLE0 + get_random(2));
|
mixer_play_effect(BUBBLE0 + get_random(2));
|
||||||
gui_log("You take a sip from a health potion");
|
gui_log("You take a sip from a health potion");
|
||||||
|
@ -498,8 +521,10 @@ player_create(class_t class, Camera *cam)
|
||||||
player->sprite = sprite_create();
|
player->sprite = sprite_create();
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
player->daggers = 10;
|
player->daggers = 10;
|
||||||
|
player->gold = 500;
|
||||||
#else
|
#else
|
||||||
player->daggers = 0;
|
player->daggers = 0;
|
||||||
|
player->gold = 0;
|
||||||
#endif
|
#endif
|
||||||
player->stat_data.total_steps = 0;
|
player->stat_data.total_steps = 0;
|
||||||
player->stat_data.steps = 0;
|
player->stat_data.steps = 0;
|
||||||
|
@ -507,7 +532,6 @@ player_create(class_t class, Camera *cam)
|
||||||
player->stat_data.kills = 0;
|
player->stat_data.kills = 0;
|
||||||
player->stat_data.misses = 0;
|
player->stat_data.misses = 0;
|
||||||
player->xp = 0;
|
player->xp = 0;
|
||||||
player->gold = 0;
|
|
||||||
player->potion_sips = 0;
|
player->potion_sips = 0;
|
||||||
player->phase_count = 0;
|
player->phase_count = 0;
|
||||||
player->class = class;
|
player->class = class;
|
||||||
|
@ -516,6 +540,8 @@ player_create(class_t class, Camera *cam)
|
||||||
player->animationTimer = _timer_create();
|
player->animationTimer = _timer_create();
|
||||||
player->swordAnimation = animation_create(5);
|
player->swordAnimation = animation_create(5);
|
||||||
player->equipment.hasArtifacts = false;
|
player->equipment.hasArtifacts = false;
|
||||||
|
player->equipment.keys = 0;
|
||||||
|
player->stateData.shopOwnerKiller = false;
|
||||||
|
|
||||||
build_sword_animation(player, cam->renderer);
|
build_sword_animation(player, cam->renderer);
|
||||||
|
|
||||||
|
@ -534,6 +560,9 @@ player_create(class_t class, Camera *cam)
|
||||||
case MAGE:
|
case MAGE:
|
||||||
m_strcpy(asset, 100, "Commissions/Mage.png");
|
m_strcpy(asset, 100, "Commissions/Mage.png");
|
||||||
player->stats = (Stats) MAGE_STATS;
|
player->stats = (Stats) MAGE_STATS;
|
||||||
|
player->skills[0] = skill_create(VAMPIRIC_BLOW, cam);
|
||||||
|
player->skills[1] = skill_create(ERUPT, cam);
|
||||||
|
player->skills[2] = skill_create(BLINK, cam);
|
||||||
break;
|
break;
|
||||||
case PALADIN:
|
case PALADIN:
|
||||||
m_strcpy(asset, 100, "Commissions/Paladin.png");
|
m_strcpy(asset, 100, "Commissions/Paladin.png");
|
||||||
|
@ -545,7 +574,6 @@ player_create(class_t class, Camera *cam)
|
||||||
player->skills[0] = skill_create(BACKSTAB, cam);
|
player->skills[0] = skill_create(BACKSTAB, cam);
|
||||||
player->skills[1] = skill_create(TRIP, cam);
|
player->skills[1] = skill_create(TRIP, cam);
|
||||||
player->skills[2] = skill_create(PHASE, cam);
|
player->skills[2] = skill_create(PHASE, cam);
|
||||||
player->skills[3] = skill_create(DAGGER_THROW, cam);
|
|
||||||
player->daggers = 10;
|
player->daggers = 10;
|
||||||
break;
|
break;
|
||||||
case WARRIOR:
|
case WARRIOR:
|
||||||
|
@ -554,10 +582,10 @@ player_create(class_t class, Camera *cam)
|
||||||
player->skills[0] = skill_create(FLURRY, cam);
|
player->skills[0] = skill_create(FLURRY, cam);
|
||||||
player->skills[1] = skill_create(BASH, cam);
|
player->skills[1] = skill_create(BASH, cam);
|
||||||
player->skills[2] = skill_create(CHARGE, cam);
|
player->skills[2] = skill_create(CHARGE, cam);
|
||||||
player->skills[3] = skill_create(DAGGER_THROW, cam);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
player->skills[3] = skill_create(DAGGER_THROW, cam);
|
||||||
player->skills[4] = skill_create(SIP_HEALTH, cam);
|
player->skills[4] = skill_create(SIP_HEALTH, cam);
|
||||||
|
|
||||||
sprite_load_texture(player->sprite, asset, 0, cam->renderer);
|
sprite_load_texture(player->sprite, asset, 0, cam->renderer);
|
||||||
|
@ -568,7 +596,16 @@ player_create(class_t class, Camera *cam)
|
||||||
return player;
|
return player;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExperienceData player_get_xp_data(Player *p)
|
void
|
||||||
|
player_reset_on_levelchange(Player *player)
|
||||||
|
{
|
||||||
|
player->sprite->pos = (Position) {
|
||||||
|
TILE_DIMENSION, TILE_DIMENSION };
|
||||||
|
player->equipment.keys = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExperienceData
|
||||||
|
player_get_xp_data(Player *p)
|
||||||
{
|
{
|
||||||
ExperienceData data;
|
ExperienceData data;
|
||||||
data.previousLevel = next_level_threshold(p->stats.lvl - 1);
|
data.previousLevel = next_level_threshold(p->stats.lvl - 1);
|
||||||
|
@ -606,6 +643,15 @@ player_monster_kill_check(Player *player, Monster *monster)
|
||||||
else if (strcmp("Ti, the Mage", monster->label) == 0)
|
else if (strcmp("Ti, the Mage", monster->label) == 0)
|
||||||
steam_set_achievement(BUGGCREATOR);
|
steam_set_achievement(BUGGCREATOR);
|
||||||
#endif // STEAM_BUILD
|
#endif // STEAM_BUILD
|
||||||
|
if (strcmp("The Trader", monster->label) == 0) {
|
||||||
|
player->stateData.shopOwnerKiller = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Event event;
|
||||||
|
event.type = MONSTER_KILLED_EVENT;
|
||||||
|
event.monsterKilled.monster = monster;
|
||||||
|
event.monsterKilled.player = player;
|
||||||
|
event_trigger(&event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -750,9 +796,20 @@ player_has_artifact(Player *p, MagicalEffect effect)
|
||||||
void
|
void
|
||||||
player_add_artifact(Player *p, Artifact *a)
|
player_add_artifact(Player *p, Artifact *a)
|
||||||
{
|
{
|
||||||
|
if (a->price > p->gold) {
|
||||||
|
gui_log("You don't have enough gold to buy a %s",
|
||||||
|
a->info.name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (a->collected)
|
if (a->collected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (a->price) {
|
||||||
|
gui_log("You pay %d gold for %s", a->price, a->info.name);
|
||||||
|
p->gold -= a->price;
|
||||||
|
}
|
||||||
|
|
||||||
mixer_play_effect(MAGIC_PICKUP);
|
mixer_play_effect(MAGIC_PICKUP);
|
||||||
a->collected = true;
|
a->collected = true;
|
||||||
|
|
||||||
|
|
|
@ -60,8 +60,13 @@ typedef struct ArtifactData {
|
||||||
typedef struct PlayerEquipment {
|
typedef struct PlayerEquipment {
|
||||||
ArtifactData artifacts[LAST_ARTIFACT_EFFECT];
|
ArtifactData artifacts[LAST_ARTIFACT_EFFECT];
|
||||||
bool hasArtifacts;
|
bool hasArtifacts;
|
||||||
|
Uint32 keys;
|
||||||
} PlayerEquipment;
|
} PlayerEquipment;
|
||||||
|
|
||||||
|
typedef struct PlayerStateData {
|
||||||
|
bool shopOwnerKiller;
|
||||||
|
} PlayerStateData;
|
||||||
|
|
||||||
typedef struct Player {
|
typedef struct Player {
|
||||||
Sprite *sprite;
|
Sprite *sprite;
|
||||||
Stats stats;
|
Stats stats;
|
||||||
|
@ -78,11 +83,15 @@ typedef struct Player {
|
||||||
Timer *animationTimer;
|
Timer *animationTimer;
|
||||||
Animation *swordAnimation;
|
Animation *swordAnimation;
|
||||||
PlayerEquipment equipment;
|
PlayerEquipment equipment;
|
||||||
|
PlayerStateData stateData;
|
||||||
} Player;
|
} Player;
|
||||||
|
|
||||||
Player*
|
Player*
|
||||||
player_create(class_t, Camera*);
|
player_create(class_t, Camera*);
|
||||||
|
|
||||||
|
void
|
||||||
|
player_reset_on_levelchange(Player *player);
|
||||||
|
|
||||||
ExperienceData
|
ExperienceData
|
||||||
player_get_xp_data(Player*);
|
player_get_xp_data(Player*);
|
||||||
|
|
||||||
|
|
|
@ -109,3 +109,9 @@ position_to_tile_pos(const Position *p)
|
||||||
p->y - (p->y % TILE_DIMENSION)
|
p->y - (p->y % TILE_DIMENSION)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Position
|
||||||
|
position_add(const Position *a, const Position *b)
|
||||||
|
{
|
||||||
|
return POS(a->x + b->x, a->y + b->y);
|
||||||
|
}
|
||||||
|
|
|
@ -71,4 +71,10 @@ position_in_roommatrix(const Position*);
|
||||||
Position
|
Position
|
||||||
position_to_tile_pos(const Position*);
|
position_to_tile_pos(const Position*);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add two positions
|
||||||
|
*/
|
||||||
|
Position
|
||||||
|
position_add(const Position*, const Position*);
|
||||||
|
|
||||||
#endif // POSITION_H_
|
#endif // POSITION_H_
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
#include "item_builder.h"
|
#include "item_builder.h"
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
#include "update_data.h"
|
#include "update_data.h"
|
||||||
|
#include "effect_util.h"
|
||||||
|
#include "particle_engine.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
onDaggerRender(Sprite *s)
|
onDaggerRender(Sprite *s)
|
||||||
|
@ -49,6 +51,7 @@ projectile_dagger_create(void)
|
||||||
p->sprite->dim = (Dimension) { 32, 32 };
|
p->sprite->dim = (Dimension) { 32, 32 };
|
||||||
p->sprite->rotationPoint = (SDL_Point) { 16, 16 };
|
p->sprite->rotationPoint = (SDL_Point) { 16, 16 };
|
||||||
p->collisionCount = 0;
|
p->collisionCount = 0;
|
||||||
|
p->bounceCount = 0;
|
||||||
memset(&p->processedSpaces,
|
memset(&p->processedSpaces,
|
||||||
false,
|
false,
|
||||||
sizeof(p->processedSpaces[0][0]) * MAP_ROOM_WIDTH * MAP_ROOM_HEIGHT);
|
sizeof(p->processedSpaces[0][0]) * MAP_ROOM_WIDTH * MAP_ROOM_HEIGHT);
|
||||||
|
@ -86,6 +89,30 @@ get_projectile_pos_for(Projectile *p)
|
||||||
return projectilePos;
|
return projectilePos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clear_processed_spaces(Projectile *p)
|
||||||
|
{
|
||||||
|
memset(&p->processedSpaces,
|
||||||
|
false,
|
||||||
|
sizeof(p->processedSpaces[0][0]) * MAP_ROOM_WIDTH * MAP_ROOM_HEIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
perform_dagger_explosion(Player *player, RoomMatrix *rm, Position *collisionPos)
|
||||||
|
{
|
||||||
|
if (player_has_artifact(player, VOLATILE_DAGGERS)) {
|
||||||
|
mixer_play_effect(EXPLOSION_EFFECT);
|
||||||
|
particle_engine_fire_explosion(*collisionPos, DIM(32, 32));
|
||||||
|
effect_damage_surroundings(collisionPos,
|
||||||
|
rm,
|
||||||
|
player,
|
||||||
|
&player->stats,
|
||||||
|
player_has_artifact(player, VOLATILE_DAGGERS),
|
||||||
|
0,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
projectile_update(Projectile *p, UpdateData *data)
|
projectile_update(Projectile *p, UpdateData *data)
|
||||||
{
|
{
|
||||||
|
@ -119,17 +146,23 @@ projectile_update(Projectile *p, UpdateData *data)
|
||||||
if (space->monster) {
|
if (space->monster) {
|
||||||
Stats tmpStats = data->player->stats;
|
Stats tmpStats = data->player->stats;
|
||||||
tmpStats.dmg *= 2;
|
tmpStats.dmg *= 2;
|
||||||
Uint32 dmg = stats_fight(&tmpStats, &space->monster->stats);
|
CombatResult result = stats_fight(&tmpStats, &space->monster->stats);
|
||||||
if (dmg > 0) {
|
if (result.dmg > 0) {
|
||||||
gui_log("Your dagger pierced %s for %u damage", space->monster->lclabel, dmg);
|
gui_log("Your dagger pierced %s for %u damage", space->monster->lclabel, result.dmg);
|
||||||
data->player->stat_data.hits += 1;
|
data->player->stat_data.hits += 1;
|
||||||
|
perform_dagger_explosion(data->player, data->matrix, &collisionPos);
|
||||||
} else {
|
} else {
|
||||||
gui_log("%s dodged your dagger", space->monster->label);
|
gui_log("%s dodged your dagger", space->monster->label);
|
||||||
}
|
}
|
||||||
monster_hit(space->monster, dmg);
|
monster_hit(space->monster, result.dmg, result.critical);
|
||||||
player_monster_kill_check(data->player, space->monster);
|
player_monster_kill_check(data->player, space->monster);
|
||||||
alive = player_has_artifact(data->player, PIERCING_DAGGERS) > p->collisionCount;
|
alive = player_has_artifact(data->player, PIERCING_DAGGERS) > p->collisionCount;
|
||||||
projectilePos = space->monster->sprite->pos;
|
projectilePos = space->monster->sprite->pos;
|
||||||
|
} else {
|
||||||
|
p->bounceCount += 1;
|
||||||
|
vector2d_reverse(&p->velocity);
|
||||||
|
clear_processed_spaces(p);
|
||||||
|
alive = p->bounceCount <= player_has_artifact(data->player, DAGGER_BOUNCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
mixer_play_effect(SWORD_HIT);
|
mixer_play_effect(SWORD_HIT);
|
||||||
|
|
|
@ -36,6 +36,7 @@ typedef struct Projectile {
|
||||||
Timer *lifetime;
|
Timer *lifetime;
|
||||||
bool alive;
|
bool alive;
|
||||||
Uint32 collisionCount;
|
Uint32 collisionCount;
|
||||||
|
Uint32 bounceCount;
|
||||||
bool processedSpaces[MAP_ROOM_WIDTH][MAP_ROOM_HEIGHT];
|
bool processedSpaces[MAP_ROOM_WIDTH][MAP_ROOM_HEIGHT];
|
||||||
void (*onRender)(struct Projectile*);
|
void (*onRender)(struct Projectile*);
|
||||||
} Projectile;
|
} Projectile;
|
||||||
|
|
|
@ -47,6 +47,8 @@ roommatrix_reset(RoomMatrix *m)
|
||||||
space->player = NULL;
|
space->player = NULL;
|
||||||
space->trap = NULL;
|
space->trap = NULL;
|
||||||
space->tile = NULL;
|
space->tile = NULL;
|
||||||
|
space->wall = NULL;
|
||||||
|
space->door = NULL;
|
||||||
space->decoration = NULL;
|
space->decoration = NULL;
|
||||||
while (space->items != NULL)
|
while (space->items != NULL)
|
||||||
linkedlist_pop(&space->items);
|
linkedlist_pop(&space->items);
|
||||||
|
@ -126,6 +128,20 @@ void roommatrix_populate_from_map(RoomMatrix *rm, Map *m)
|
||||||
space->lethal =
|
space->lethal =
|
||||||
r->tiles[i][j]->lethal;
|
r->tiles[i][j]->lethal;
|
||||||
}
|
}
|
||||||
|
if (r->walls[i][j]) {
|
||||||
|
space->wall = r->walls[i][j];
|
||||||
|
space->occupied =
|
||||||
|
r->walls[i][j]->collider;
|
||||||
|
space->lightsource =
|
||||||
|
r->walls[i][j]->lightsource;
|
||||||
|
}
|
||||||
|
if (r->doors[i][j]) {
|
||||||
|
space->door = r->doors[i][j];
|
||||||
|
space->occupied =
|
||||||
|
r->doors[i][j]->collider;
|
||||||
|
space->lightsource =
|
||||||
|
r->doors[i][j]->lightsource;
|
||||||
|
}
|
||||||
if (r->decorations[i][j]) {
|
if (r->decorations[i][j]) {
|
||||||
space->decoration = r->decorations[i][j];
|
space->decoration = r->decorations[i][j];
|
||||||
space->occupied |=
|
space->occupied |=
|
||||||
|
|
|
@ -15,9 +15,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
#pragma once
|
||||||
#ifndef ROOMMATRIX_H_
|
|
||||||
#define ROOMMATRIX_H_
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
|
@ -45,6 +43,8 @@ typedef struct RoomSpace {
|
||||||
bool damaging;
|
bool damaging;
|
||||||
int light;
|
int light;
|
||||||
MapTile *tile;
|
MapTile *tile;
|
||||||
|
MapTile *wall;
|
||||||
|
MapTile *door;
|
||||||
MapTile *decoration;
|
MapTile *decoration;
|
||||||
Monster *monster;
|
Monster *monster;
|
||||||
Player *player;
|
Player *player;
|
||||||
|
@ -85,6 +85,9 @@ roommatrix_render_lightmap(RoomMatrix*, Camera*);
|
||||||
RoomSpace*
|
RoomSpace*
|
||||||
roommatrix_get_space_for(RoomMatrix*, const Position *p);
|
roommatrix_get_space_for(RoomMatrix*, const Position *p);
|
||||||
|
|
||||||
|
Player *
|
||||||
|
roommatrix_get_player(RoomMatrix*);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void
|
void
|
||||||
roommatrix_render_debug(RoomMatrix*, Camera*);
|
roommatrix_render_debug(RoomMatrix*, Camera*);
|
||||||
|
@ -92,8 +95,3 @@ roommatrix_render_debug(RoomMatrix*, Camera*);
|
||||||
|
|
||||||
void
|
void
|
||||||
roommatrix_destroy(RoomMatrix*);
|
roommatrix_destroy(RoomMatrix*);
|
||||||
|
|
||||||
Player *
|
|
||||||
roommatrix_get_player(RoomMatrix*);
|
|
||||||
|
|
||||||
#endif // ROOMMATRIX_H_
|
|
||||||
|
|
|
@ -0,0 +1,166 @@
|
||||||
|
/*
|
||||||
|
* BreakHack - A dungeone crawler RPG
|
||||||
|
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "save.h"
|
||||||
|
#include "sqlite3.h"
|
||||||
|
#include "db.h"
|
||||||
|
#include "defines.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
static sqlite3 *db = NULL;
|
||||||
|
static bool loaded = false;
|
||||||
|
static Save save;
|
||||||
|
|
||||||
|
static
|
||||||
|
DbQuery MIGRATE_COMMAND = {
|
||||||
|
"CREATE TABLE IF NOT EXISTS saves("
|
||||||
|
"major_version INTEGER, "
|
||||||
|
"minor_version INTEGER, "
|
||||||
|
"patch_version INTEGER, "
|
||||||
|
"arch INTEGER, "
|
||||||
|
"save BLOB)",
|
||||||
|
NULL, NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static
|
||||||
|
DbQuery CLEAR_SAVE = {
|
||||||
|
"DELETE FROM saves "
|
||||||
|
#ifdef _WIN32
|
||||||
|
"WHERE arch = 1",
|
||||||
|
#else // _WIN32
|
||||||
|
"WHERE arch = 2",
|
||||||
|
#endif // _WIN32
|
||||||
|
NULL,
|
||||||
|
NULL };
|
||||||
|
|
||||||
|
static void
|
||||||
|
create_table(void)
|
||||||
|
{
|
||||||
|
db_execute(db, &MIGRATE_COMMAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
save_load(void)
|
||||||
|
{
|
||||||
|
debug("Loading save");
|
||||||
|
const char *query =
|
||||||
|
"SELECT save FROM saves "
|
||||||
|
"WHERE major_version = ? "
|
||||||
|
"AND minor_version = ? "
|
||||||
|
"AND patch_version = ? "
|
||||||
|
#ifdef _WIN32
|
||||||
|
"AND arch = 1 "
|
||||||
|
#else // _WIN32
|
||||||
|
"AND arch = 2 "
|
||||||
|
#endif // _WIN32
|
||||||
|
"LIMIT 1";
|
||||||
|
|
||||||
|
sqlite3_stmt *stmt = db_prepare(db, query);
|
||||||
|
sqlite3_bind_int(stmt, 1, MAJOR_VERSION);
|
||||||
|
sqlite3_bind_int(stmt, 2, MINOR_VERSION);
|
||||||
|
sqlite3_bind_int(stmt, 3, PATCH_VERSION);
|
||||||
|
if (SQLITE_ROW == sqlite3_step(stmt)) {
|
||||||
|
int size = sqlite3_column_bytes(stmt, 0);
|
||||||
|
debug("Reading save bytes: %d", size);
|
||||||
|
memcpy(&save, sqlite3_column_blob(stmt, 0), size);
|
||||||
|
loaded = true;
|
||||||
|
} else {
|
||||||
|
loaded = false;
|
||||||
|
}
|
||||||
|
sqlite3_finalize(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
save_init(void)
|
||||||
|
{
|
||||||
|
if (!db_open(DB_FILE, &db)) {
|
||||||
|
db_close(&db);
|
||||||
|
fatal("Exiting");
|
||||||
|
}
|
||||||
|
create_table();
|
||||||
|
save_load();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Save *
|
||||||
|
save_get(void)
|
||||||
|
{
|
||||||
|
return &save;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
save_exists(void)
|
||||||
|
{
|
||||||
|
return loaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
save_save(unsigned int seed,
|
||||||
|
unsigned int map_level,
|
||||||
|
bool quickGame,
|
||||||
|
bool arcadeGame,
|
||||||
|
Player *player)
|
||||||
|
{
|
||||||
|
debug("Saving game, Seed: %d, Map level: %d", seed, map_level);
|
||||||
|
save_clear();
|
||||||
|
|
||||||
|
save.seed = seed;
|
||||||
|
save.map_level = map_level;
|
||||||
|
save.quickGame = quickGame;
|
||||||
|
save.arcadeGame = arcadeGame;
|
||||||
|
save.player_stats = player->stats;
|
||||||
|
save.player_daggers = player->daggers;
|
||||||
|
save.player_gold = player->gold;
|
||||||
|
save.player_xp = player->xp;
|
||||||
|
save.player_potion_sips = player->potion_sips;
|
||||||
|
save.player_player_stats = player->stat_data;
|
||||||
|
save.player_state = player->stateData;
|
||||||
|
save.player_class = player->class;
|
||||||
|
save.player_equipment = player->equipment;
|
||||||
|
|
||||||
|
const char *query =
|
||||||
|
"INSERT INTO saves"
|
||||||
|
"(major_version, minor_version, patch_version, arch, save) "
|
||||||
|
"VALUES(?, ?, ?, ?, ?)";
|
||||||
|
|
||||||
|
sqlite3_stmt *stmt = db_prepare(db, query);
|
||||||
|
sqlite3_bind_int(stmt, 1, MAJOR_VERSION);
|
||||||
|
sqlite3_bind_int(stmt, 2, MINOR_VERSION);
|
||||||
|
sqlite3_bind_int(stmt, 3, PATCH_VERSION);
|
||||||
|
#ifdef _WIN32
|
||||||
|
sqlite3_bind_int(stmt, 4, 1);
|
||||||
|
#else // _WIN32
|
||||||
|
sqlite3_bind_int(stmt, 4, 2);
|
||||||
|
#endif // _WIN32
|
||||||
|
sqlite3_bind_blob(stmt, 5, &save, sizeof(Save), SQLITE_STATIC);
|
||||||
|
sqlite3_step(stmt);
|
||||||
|
sqlite3_finalize(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
save_clear(void)
|
||||||
|
{
|
||||||
|
db_execute(db, &CLEAR_SAVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
save_close(void)
|
||||||
|
{
|
||||||
|
db_close(&db);
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* BreakHack - A dungeone crawler RPG
|
||||||
|
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#ifndef SAVE_H_
|
||||||
|
#define SAVE_H_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "player.h"
|
||||||
|
#include "artifact.h"
|
||||||
|
|
||||||
|
typedef struct Save {
|
||||||
|
int seed;
|
||||||
|
bool quickGame;
|
||||||
|
bool arcadeGame;
|
||||||
|
unsigned int map_level;
|
||||||
|
unsigned int player_daggers;
|
||||||
|
unsigned int player_xp;
|
||||||
|
unsigned int player_potion_sips;
|
||||||
|
unsigned int potion_sips;
|
||||||
|
Stats player_stats;
|
||||||
|
PlayerStatData player_player_stats;
|
||||||
|
double player_gold;
|
||||||
|
PlayerStateData player_state;
|
||||||
|
class_t player_class;
|
||||||
|
PlayerEquipment player_equipment;
|
||||||
|
} Save;
|
||||||
|
|
||||||
|
void
|
||||||
|
save_init(void);
|
||||||
|
|
||||||
|
void
|
||||||
|
save_load(void);
|
||||||
|
|
||||||
|
const Save *
|
||||||
|
save_get(void);
|
||||||
|
|
||||||
|
bool
|
||||||
|
save_exists(void);
|
||||||
|
|
||||||
|
void
|
||||||
|
save_save(unsigned int seed,
|
||||||
|
unsigned int map_level,
|
||||||
|
bool quickGame,
|
||||||
|
bool arcadeGame,
|
||||||
|
Player *player);
|
||||||
|
|
||||||
|
void
|
||||||
|
save_clear(void);
|
||||||
|
|
||||||
|
void
|
||||||
|
save_close(void);
|
||||||
|
|
||||||
|
#endif // SAVE_H_
|
|
@ -69,8 +69,13 @@ screen_create_credits(SDL_Renderer *renderer)
|
||||||
linkedlist_push(&screen->sprites, credit_txt("liquidityc.github.io", C_WHITE, x + columnOffset, y, renderer));
|
linkedlist_push(&screen->sprites, credit_txt("liquidityc.github.io", C_WHITE, x + columnOffset, y, renderer));
|
||||||
y += 20;
|
y += 20;
|
||||||
linkedlist_push(&screen->sprites, credit_txt("@LiquidityC", C_WHITE, x + columnOffset, y, renderer));
|
linkedlist_push(&screen->sprites, credit_txt("@LiquidityC", C_WHITE, x + columnOffset, y, renderer));
|
||||||
|
y += 20;
|
||||||
|
linkedlist_push(&screen->sprites, credit_txt("AmigaOS 4", C_YELLOW, x, y, renderer));
|
||||||
|
y += 20;
|
||||||
|
linkedlist_push(&screen->sprites, credit_txt("port:", C_YELLOW, x, y, renderer));
|
||||||
|
linkedlist_push(&screen->sprites, credit_txt("George Sokianos", C_WHITE, x + columnOffset, y, renderer));
|
||||||
|
|
||||||
y += 60;
|
y += 40;
|
||||||
linkedlist_push(&screen->sprites, credit_txt(" - Graphics -", C_BLUE, x, y, renderer));
|
linkedlist_push(&screen->sprites, credit_txt(" - Graphics -", C_BLUE, x, y, renderer));
|
||||||
y += 30;
|
y += 30;
|
||||||
linkedlist_push(&screen->sprites, credit_txt("Tileset:", C_YELLOW, x, y, renderer));
|
linkedlist_push(&screen->sprites, credit_txt("Tileset:", C_YELLOW, x, y, renderer));
|
||||||
|
@ -209,3 +214,4 @@ screen_destroy(Screen *screen)
|
||||||
sprite_destroy(linkedlist_pop(&screen->sprites));
|
sprite_destroy(linkedlist_pop(&screen->sprites));
|
||||||
free(screen);
|
free(screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
323
src/skill.c
323
src/skill.c
|
@ -36,6 +36,8 @@
|
||||||
#include "artifact.h"
|
#include "artifact.h"
|
||||||
#include "trap.h"
|
#include "trap.h"
|
||||||
#include "tooltip.h"
|
#include "tooltip.h"
|
||||||
|
#include "actiontextbuilder.h"
|
||||||
|
#include "effect_util.h"
|
||||||
|
|
||||||
static char *flurry_tooltip[] = {
|
static char *flurry_tooltip[] = {
|
||||||
"FLURRY", "",
|
"FLURRY", "",
|
||||||
|
@ -55,6 +57,25 @@ static char *flurry_tooltip[] = {
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static char *vampiric_blow_tooltip[] = {
|
||||||
|
"VAMPIRIC BLOW", "",
|
||||||
|
"",
|
||||||
|
" Hits an adjecant enemy with a vampiric blow.", "",
|
||||||
|
" Upon hitting you will siphon life from the target", "",
|
||||||
|
" and cause the target to bleed.", "",
|
||||||
|
"",
|
||||||
|
"COOLDOWN:", "",
|
||||||
|
" 5 turns", "",
|
||||||
|
"",
|
||||||
|
"USAGE:", "",
|
||||||
|
" activate the skill (press ", "1", ")", "",
|
||||||
|
" followed by a direction (left, right, up or down)", "",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"Press ", "ESC", " to close", "", "",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
static char *bash_tooltip[] = {
|
static char *bash_tooltip[] = {
|
||||||
"BASH", "",
|
"BASH", "",
|
||||||
"",
|
"",
|
||||||
|
@ -156,6 +177,43 @@ static char *charge_tooltip[] = {
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static char *blink_tooltip[] = {
|
||||||
|
"BLINK", "",
|
||||||
|
"",
|
||||||
|
" You blink in a chosen direction into the first obstructing", "",
|
||||||
|
" object picking up items in your path. Monsters will not", "",
|
||||||
|
" obstruct your blink.", "",
|
||||||
|
"",
|
||||||
|
"COOLDOWN:", "",
|
||||||
|
" 4 turns", "",
|
||||||
|
"",
|
||||||
|
"USAGE:",
|
||||||
|
" activate the skill (press ", "3", ")", "",
|
||||||
|
" followed by a direction (left, right, up or down)", "",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"Press ", "ESC", " to close", "",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static char *erupt_tooltip[] = {
|
||||||
|
"ERUPT", "",
|
||||||
|
"",
|
||||||
|
" You erupt in a magical explosion damaging monsters", "",
|
||||||
|
" around you pushing them back and causing fear", "",
|
||||||
|
" for 3 turns.", "",
|
||||||
|
"",
|
||||||
|
"COOLDOWN:", "",
|
||||||
|
" 3 turns", "",
|
||||||
|
"",
|
||||||
|
"USAGE:",
|
||||||
|
" Erupt (press ", "2", ")", "",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"Press ", "ESC", " to close", "",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
static char *dagger_tooltip[] = {
|
static char *dagger_tooltip[] = {
|
||||||
"THROW DAGGER", "",
|
"THROW DAGGER", "",
|
||||||
"",
|
"",
|
||||||
|
@ -266,6 +324,73 @@ check_skill_validity(Position *playerPos, Position *targetPos, SkillData *data)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
vampiric_blow_skill(Skill *skill, SkillData *data)
|
||||||
|
{
|
||||||
|
UNUSED (skill);
|
||||||
|
|
||||||
|
Position playerPos, targetPos;
|
||||||
|
Player *player = data->player;
|
||||||
|
if (!check_skill_validity(&playerPos, &targetPos, data)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
animation_run(player->swordAnimation);
|
||||||
|
Monster *monster = data->matrix->spaces[targetPos.x][targetPos.y].monster;
|
||||||
|
mixer_play_effect(SWING0);
|
||||||
|
if (monster) {
|
||||||
|
gui_log("You attack %s with a vampiric blow", monster->lclabel);
|
||||||
|
player->stats.advantage = true;
|
||||||
|
CombatResult result = stats_fight(&player->stats, &monster->stats);
|
||||||
|
player->stats.advantage = false;
|
||||||
|
|
||||||
|
monster_hit(monster, result.dmg, result.critical);
|
||||||
|
|
||||||
|
if (result.dmg) {
|
||||||
|
mixer_play_effect(SWORD_HIT);
|
||||||
|
monster_set_bleeding(monster);
|
||||||
|
|
||||||
|
unsigned int gain = player->stats.lvl * 3;
|
||||||
|
gain = min(gain, (unsigned int) player->stats.maxhp - player->stats.hp);
|
||||||
|
if (gain > 0) {
|
||||||
|
gui_log("You gain %u health", gain);
|
||||||
|
char msg[4];
|
||||||
|
m_sprintf(msg, 4, "+%u", gain);
|
||||||
|
actiontextbuilder_create_text(msg,
|
||||||
|
C_GREEN,
|
||||||
|
&player->sprite->pos);
|
||||||
|
player->stats.hp += gain;
|
||||||
|
player->stats.hp = min(player->stats.maxhp,
|
||||||
|
player->stats.hp);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
gui_log("You missed %s", monster->lclabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
gui_log("You swing at thin air with a vampiric blow");
|
||||||
|
}
|
||||||
|
player_monster_kill_check(data->player, monster);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Skill *
|
||||||
|
create_vampiric_blow(void)
|
||||||
|
{
|
||||||
|
Texture *t = texturecache_add("Extras/Skills.png");
|
||||||
|
Sprite *s = sprite_create();
|
||||||
|
sprite_set_texture(s, t, 0);
|
||||||
|
s->dim = GAME_DIMENSION;
|
||||||
|
s->clip = CLIP32(0, 64);
|
||||||
|
s->fixed = true;
|
||||||
|
Skill *skill = create_default("Vampiric blow", s);
|
||||||
|
skill->levelcap = 2;
|
||||||
|
skill->use = vampiric_blow_skill;
|
||||||
|
skill->resetTime = 5;
|
||||||
|
return skill;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
skill_use_flurry(Skill *skill, SkillData *data)
|
skill_use_flurry(Skill *skill, SkillData *data)
|
||||||
{
|
{
|
||||||
|
@ -284,12 +409,12 @@ skill_use_flurry(Skill *skill, SkillData *data)
|
||||||
unsigned int hitCount = 0;
|
unsigned int hitCount = 0;
|
||||||
for (size_t i = 0; i < 3; ++i) {
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
unsigned int originalHp = monster->stats.hp;
|
unsigned int originalHp = monster->stats.hp;
|
||||||
unsigned int dmg = stats_fight(&data->player->stats, &monster->stats);
|
CombatResult result = stats_fight(&data->player->stats, &monster->stats);
|
||||||
if (dmg > 0 && originalHp > 0) {
|
if (result.dmg > 0 && originalHp > 0) {
|
||||||
gui_log("You hit for %u damage", dmg);
|
gui_log("You hit for %u damage", result.dmg);
|
||||||
hitCount++;
|
hitCount++;
|
||||||
}
|
}
|
||||||
monster_hit(monster, dmg);
|
monster_hit(monster, result.dmg, result.critical);
|
||||||
}
|
}
|
||||||
if (hitCount == 1) {
|
if (hitCount == 1) {
|
||||||
mixer_play_effect(SWORD_HIT);
|
mixer_play_effect(SWORD_HIT);
|
||||||
|
@ -298,9 +423,6 @@ skill_use_flurry(Skill *skill, SkillData *data)
|
||||||
} else if (hitCount == 3) {
|
} else if (hitCount == 3) {
|
||||||
mixer_play_effect(TRIPPLE_SWORD_HIT);
|
mixer_play_effect(TRIPPLE_SWORD_HIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
data->player->stat_data.hits += hitCount;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
gui_log("You swing at thin air with a flurry of strikes");
|
gui_log("You swing at thin air with a flurry of strikes");
|
||||||
}
|
}
|
||||||
|
@ -401,20 +523,19 @@ skill_bash(Skill *skill, SkillData *data)
|
||||||
mixer_play_effect(SWING0);
|
mixer_play_effect(SWING0);
|
||||||
if (monster) {
|
if (monster) {
|
||||||
gui_log("You bash %s with your shield", monster->lclabel);
|
gui_log("You bash %s with your shield", monster->lclabel);
|
||||||
unsigned int dmg = stats_fight(&data->player->stats, &monster->stats);
|
CombatResult result = stats_fight(&data->player->stats, &monster->stats);
|
||||||
if (dmg > 0) {
|
if (result.dmg > 0) {
|
||||||
gui_log("You hit for %u damage", dmg);
|
gui_log("You hit for %u damage", result.dmg);
|
||||||
if (monster->stats.hp > 0) {
|
if (monster->stats.hp > 0) {
|
||||||
gui_log("%s seems dazed and confused", monster->label);
|
gui_log("%s seems dazed and confused", monster->label);
|
||||||
monster_set_state(monster, STUNNED,
|
monster_set_state(monster, STUNNED,
|
||||||
(Uint8) (3 + player_has_artifact(data->player, INCREASED_STUN)));
|
(Uint8) (3 + player_has_artifact(data->player, INCREASED_STUN)));
|
||||||
}
|
}
|
||||||
mixer_play_effect(SLAM);
|
mixer_play_effect(SLAM);
|
||||||
data->player->stat_data.hits += 1;
|
|
||||||
} else {
|
} else {
|
||||||
gui_log("You missed %s", monster->lclabel);
|
gui_log("You missed %s", monster->lclabel);
|
||||||
}
|
}
|
||||||
monster_hit(monster, dmg);
|
monster_hit(monster, result.dmg, result.critical);
|
||||||
} else {
|
} else {
|
||||||
gui_log("You bash your shield at nothing");
|
gui_log("You bash your shield at nothing");
|
||||||
}
|
}
|
||||||
|
@ -456,13 +577,13 @@ skill_trip(Skill *skill, SkillData *data)
|
||||||
mixer_play_effect(SWING0 + get_random(2));
|
mixer_play_effect(SWING0 + get_random(2));
|
||||||
animation_run(data->player->swordAnimation);
|
animation_run(data->player->swordAnimation);
|
||||||
if (space->monster) {
|
if (space->monster) {
|
||||||
int dmg = stats_fight(&data->player->stats, &space->monster->stats);
|
CombatResult result = stats_fight(&data->player->stats, &space->monster->stats);
|
||||||
if (dmg)
|
if (result.dmg)
|
||||||
mixer_play_effect(SWORD_HIT);
|
mixer_play_effect(SWORD_HIT);
|
||||||
gui_log("You trip %s causing it to fall away from you", space->monster->lclabel);
|
gui_log("You trip %s causing it to fall away from you", space->monster->lclabel);
|
||||||
monster_hit(space->monster, dmg);
|
monster_hit(space->monster, result.dmg, result.critical);
|
||||||
player_monster_kill_check(data->player, space->monster);
|
player_monster_kill_check(data->player, space->monster);
|
||||||
if (dmg && space->monster->stats.hp > 0) {
|
if (result.dmg && space->monster->stats.hp > 0) {
|
||||||
Uint32 pushCount = 1 + player_has_artifact(data->player, PUSH_BACK);
|
Uint32 pushCount = 1 + player_has_artifact(data->player, PUSH_BACK);
|
||||||
for (Uint32 i = 0; i < pushCount; ++i) {
|
for (Uint32 i = 0; i < pushCount; ++i) {
|
||||||
monster_push(space->monster, data->player, data->matrix, data->direction);
|
monster_push(space->monster, data->player, data->matrix, data->direction);
|
||||||
|
@ -529,13 +650,13 @@ skill_backstab(Skill *skill, SkillData *data)
|
||||||
monster_push(m, data->player, data->matrix, reverseDirection);
|
monster_push(m, data->player, data->matrix, reverseDirection);
|
||||||
|
|
||||||
m->stats.disadvantage = true;
|
m->stats.disadvantage = true;
|
||||||
int dmg = stats_fight(&data->player->stats, &m->stats);
|
CombatResult result = stats_fight(&data->player->stats, &m->stats);
|
||||||
m->stats.disadvantage = false;
|
m->stats.disadvantage = false;
|
||||||
monster_hit(m, dmg);
|
monster_hit(m, result.dmg, result.critical);
|
||||||
player_monster_kill_check(data->player, m);
|
player_monster_kill_check(data->player, m);
|
||||||
if (dmg) {
|
if (result.dmg) {
|
||||||
mixer_play_effect(SWORD_HIT);
|
mixer_play_effect(SWORD_HIT);
|
||||||
monster_set_state(m, STUNNED, (Uint8)(2 + player_has_artifact(data->player, INCREASED_STUN)));
|
monster_set_bleeding(m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,7 +716,9 @@ create_phase(void)
|
||||||
static bool
|
static bool
|
||||||
skill_sip_health_available(Player *player)
|
skill_sip_health_available(Player *player)
|
||||||
{
|
{
|
||||||
return player->potion_sips > 0 && player->stats.hp != player->stats.maxhp;
|
bool hasSips = player->class == MAGE ?
|
||||||
|
player->potion_sips > 1 : player->potion_sips > 0;
|
||||||
|
return hasSips > 0 && player->stats.hp != player->stats.maxhp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -644,13 +767,12 @@ skill_charge_check_path(SkillData *data,
|
||||||
Stats tmpStats = player->stats;
|
Stats tmpStats = player->stats;
|
||||||
tmpStats.dmg *= steps > 0 ? steps : 1;
|
tmpStats.dmg *= steps > 0 ? steps : 1;
|
||||||
mixer_play_effect(SWING0 + get_random(2));
|
mixer_play_effect(SWING0 + get_random(2));
|
||||||
unsigned int dmg = stats_fight(&tmpStats, &monster->stats);
|
CombatResult result = stats_fight(&tmpStats, &monster->stats);
|
||||||
if (dmg > 0) {
|
if (result.dmg > 0) {
|
||||||
gui_log("You charged %s for %u damage", monster->lclabel, dmg);
|
gui_log("You charged %s for %u damage", monster->lclabel, result.dmg);
|
||||||
mixer_play_effect(SWORD_HIT);
|
mixer_play_effect(SWORD_HIT);
|
||||||
data->player->stat_data.hits += 1;
|
|
||||||
}
|
}
|
||||||
monster_hit(monster, dmg);
|
monster_hit(monster, result.dmg, result.critical);
|
||||||
player_monster_kill_check(data->player, monster);
|
player_monster_kill_check(data->player, monster);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,6 +874,143 @@ create_charge(void)
|
||||||
return skill;
|
return skill;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
skill_blink(Skill *skill, SkillData *data)
|
||||||
|
{
|
||||||
|
UNUSED(skill);
|
||||||
|
|
||||||
|
Player *player = data->player;
|
||||||
|
RoomMatrix *matrix = data->matrix;
|
||||||
|
|
||||||
|
Position playerStartPos = position_to_matrix_coords(&player->sprite->pos);
|
||||||
|
Position destination = playerStartPos;
|
||||||
|
|
||||||
|
// Find collider
|
||||||
|
destination.x += (int) data->direction.x;
|
||||||
|
destination.y += (int) data->direction.y;
|
||||||
|
Position lastAvailableDest = playerStartPos;
|
||||||
|
while (position_in_roommatrix(&destination))
|
||||||
|
{
|
||||||
|
RoomSpace *space = &matrix->spaces[destination.x][destination.y];
|
||||||
|
|
||||||
|
if (space->occupied) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!space->monster) {
|
||||||
|
lastAvailableDest = destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
perform_pickups_for_space(space, player);
|
||||||
|
destination.x += (int) data->direction.x;
|
||||||
|
destination.y += (int) data->direction.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
destination = lastAvailableDest;
|
||||||
|
|
||||||
|
// Move player
|
||||||
|
Position playerOriginPos = player->sprite->pos;
|
||||||
|
Sint32 xdiff = destination.x - playerStartPos.x;
|
||||||
|
Sint32 ydiff = destination.y - playerStartPos.y;
|
||||||
|
player->sprite->pos.x += xdiff * TILE_DIMENSION;
|
||||||
|
player->sprite->pos.y += ydiff * TILE_DIMENSION;
|
||||||
|
Position playerDestinationPos = player->sprite->pos;
|
||||||
|
player_turn(data->player, &data->direction);
|
||||||
|
|
||||||
|
particle_engine_blink(playerOriginPos, DIM(32, 32));
|
||||||
|
particle_engine_blink(playerDestinationPos, DIM(32, 32));
|
||||||
|
mixer_play_effect(BLINK_EFFECT);
|
||||||
|
|
||||||
|
Position lastTilePos = position_to_matrix_coords(&playerDestinationPos);
|
||||||
|
RoomSpace *destSpace = &matrix->spaces[lastTilePos.x][lastTilePos.y];
|
||||||
|
|
||||||
|
handle_space_effects(destSpace, player);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Skill *
|
||||||
|
create_blink(void)
|
||||||
|
{
|
||||||
|
Texture *t = texturecache_add("Extras/Skills.png");
|
||||||
|
Sprite *s = sprite_create();
|
||||||
|
sprite_set_texture(s, t, 0);
|
||||||
|
s->dim = GAME_DIMENSION;
|
||||||
|
s->clip = CLIP32(64, 64);
|
||||||
|
s->fixed = true;
|
||||||
|
Skill *skill = create_default("Blink", s);
|
||||||
|
skill->levelcap = 3;
|
||||||
|
skill->use = skill_blink;
|
||||||
|
skill->resetTime = 4;
|
||||||
|
return skill;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
skill_erupt(Skill *skill, SkillData *data)
|
||||||
|
{
|
||||||
|
UNUSED(skill);
|
||||||
|
|
||||||
|
Player *player = data->player;
|
||||||
|
RoomMatrix *rm = data->matrix;
|
||||||
|
|
||||||
|
gui_log("You erupt in a magical explosion");
|
||||||
|
particle_engine_eldritch_explosion(player->sprite->pos, DIM(32, 32));
|
||||||
|
mixer_play_effect(BLAST_EFFECT);
|
||||||
|
|
||||||
|
Position playerMPos = position_to_matrix_coords(&player->sprite->pos);
|
||||||
|
int range = player_has_artifact(player, SKILL_RADIUS);
|
||||||
|
for (Sint32 i = -1 - range; i <= 1 + range; ++i) {
|
||||||
|
for (Sint32 j = -1 - range; j <= 1 + range; ++j) {
|
||||||
|
|
||||||
|
if (i == 0 && j == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Position matrixPos = POS(playerMPos.x + i, playerMPos.y + j);
|
||||||
|
if (!position_in_roommatrix(&matrixPos))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
RoomSpace *r = &rm->spaces[matrixPos.x][matrixPos.y];
|
||||||
|
if (r->monster) {
|
||||||
|
player->stats.advantage = true;
|
||||||
|
CombatResult result = stats_fight(&player->stats, &r->monster->stats);
|
||||||
|
player->stats.advantage = false;
|
||||||
|
monster_hit(r->monster, result.dmg, result.critical);
|
||||||
|
gui_log("%s takes %d damage from the explosion", r->monster->label, result.dmg);
|
||||||
|
monster_set_state(r->monster, SCARED, 3);
|
||||||
|
|
||||||
|
int lvl = 1 + player_has_artifact(player, PUSH_BACK);
|
||||||
|
Vector2d dir = vector2d_to_direction(&VEC2D((float) i, (float) j));
|
||||||
|
for (int k = 0; k < lvl; ++k) {
|
||||||
|
if (r->monster->stats.hp > 0)
|
||||||
|
monster_push(r->monster,
|
||||||
|
player,
|
||||||
|
rm,
|
||||||
|
dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Skill *
|
||||||
|
create_erupt(void)
|
||||||
|
{
|
||||||
|
Texture *t = texturecache_add("Extras/Skills.png");
|
||||||
|
Sprite *s = sprite_create();
|
||||||
|
sprite_set_texture(s, t, 0);
|
||||||
|
s->dim = GAME_DIMENSION;
|
||||||
|
s->clip = CLIP32(32, 64);
|
||||||
|
s->fixed = true;
|
||||||
|
Skill *skill = create_default("Erupt", s);
|
||||||
|
skill->levelcap = 3;
|
||||||
|
skill->use = skill_erupt;
|
||||||
|
skill->instantUse = true;
|
||||||
|
skill->resetTime = 3;
|
||||||
|
return skill;
|
||||||
|
}
|
||||||
|
|
||||||
Skill*
|
Skill*
|
||||||
skill_create(enum SkillType t, Camera *cam)
|
skill_create(enum SkillType t, Camera *cam)
|
||||||
{
|
{
|
||||||
|
@ -761,6 +1020,10 @@ skill_create(enum SkillType t, Camera *cam)
|
||||||
skill = create_flurry();
|
skill = create_flurry();
|
||||||
skill->tooltip = tooltip_create(flurry_tooltip, cam);
|
skill->tooltip = tooltip_create(flurry_tooltip, cam);
|
||||||
break;
|
break;
|
||||||
|
case VAMPIRIC_BLOW:
|
||||||
|
skill = create_vampiric_blow();
|
||||||
|
skill->tooltip = tooltip_create(vampiric_blow_tooltip, cam);
|
||||||
|
break;
|
||||||
case SIP_HEALTH:
|
case SIP_HEALTH:
|
||||||
skill = create_sip_health();
|
skill = create_sip_health();
|
||||||
skill->tooltip = tooltip_create(health_tooltip, cam);
|
skill->tooltip = tooltip_create(health_tooltip, cam);
|
||||||
|
@ -769,6 +1032,14 @@ skill_create(enum SkillType t, Camera *cam)
|
||||||
skill = create_charge();
|
skill = create_charge();
|
||||||
skill->tooltip = tooltip_create(charge_tooltip, cam);
|
skill->tooltip = tooltip_create(charge_tooltip, cam);
|
||||||
break;
|
break;
|
||||||
|
case BLINK:
|
||||||
|
skill = create_blink();
|
||||||
|
skill->tooltip = tooltip_create(blink_tooltip, cam);
|
||||||
|
break;
|
||||||
|
case ERUPT:
|
||||||
|
skill = create_erupt();
|
||||||
|
skill->tooltip = tooltip_create(erupt_tooltip, cam);
|
||||||
|
break;
|
||||||
case DAGGER_THROW:
|
case DAGGER_THROW:
|
||||||
skill = create_throw_dagger();
|
skill = create_throw_dagger();
|
||||||
skill->tooltip = tooltip_create(dagger_tooltip, cam);
|
skill->tooltip = tooltip_create(dagger_tooltip, cam);
|
||||||
|
|
|
@ -35,7 +35,10 @@ enum SkillType {
|
||||||
SIP_HEALTH,
|
SIP_HEALTH,
|
||||||
BACKSTAB,
|
BACKSTAB,
|
||||||
TRIP,
|
TRIP,
|
||||||
PHASE
|
PHASE,
|
||||||
|
BLINK,
|
||||||
|
ERUPT,
|
||||||
|
VAMPIRIC_BLOW
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct SkillData_t {
|
typedef struct SkillData_t {
|
||||||
|
|
|
@ -64,7 +64,7 @@ load_texture(SkillBar *bar, const char *path, SDL_Renderer *renderer)
|
||||||
s->dim = (Dimension) { 8, 8 };
|
s->dim = (Dimension) { 8, 8 };
|
||||||
s->fixed = true;
|
s->fixed = true;
|
||||||
sprite_load_text_texture(s, "GUI/SDS_8x8.ttf", 0, 8, 0);
|
sprite_load_text_texture(s, "GUI/SDS_8x8.ttf", 0, 8, 0);
|
||||||
m_sprintf(buffer, 4, "%u", i + 1 < 10 ? i + 1 : 0);
|
m_sprintf(buffer, 4, "%u", i + 1);
|
||||||
texture_load_from_text(s->textures[0], buffer, C_YELLOW, C_BLACK, renderer);
|
texture_load_from_text(s->textures[0], buffer, C_YELLOW, C_BLACK, renderer);
|
||||||
linkedlist_append(&bar->sprites, s);
|
linkedlist_append(&bar->sprites, s);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,8 @@ sprite_create_default(void)
|
||||||
s->textures[1] = NULL;
|
s->textures[1] = NULL;
|
||||||
s->clip = (SDL_Rect) { 0, 0, 0, 0 };
|
s->clip = (SDL_Rect) { 0, 0, 0, 0 };
|
||||||
s->destroyTextures = false;
|
s->destroyTextures = false;
|
||||||
s->pos = (Position) { 0, 0 };
|
s->pos = POS(0, 0);
|
||||||
|
s->offset = POS(0, 0);
|
||||||
s->dim = DEFAULT_DIMENSION;
|
s->dim = DEFAULT_DIMENSION;
|
||||||
s->angle = 0;
|
s->angle = 0;
|
||||||
s->rotationPoint = (SDL_Point) { 0, 0 };
|
s->rotationPoint = (SDL_Point) { 0, 0 };
|
||||||
|
@ -169,6 +170,8 @@ sprite_render(Sprite *s, Camera *cam)
|
||||||
else
|
else
|
||||||
cameraPos = s->pos;
|
cameraPos = s->pos;
|
||||||
|
|
||||||
|
cameraPos = position_add(&cameraPos, &s->offset);
|
||||||
|
|
||||||
SDL_Rect box = {
|
SDL_Rect box = {
|
||||||
cameraPos.x, cameraPos.y, s->dim.width, s->dim.height
|
cameraPos.x, cameraPos.y, s->dim.width, s->dim.height
|
||||||
};
|
};
|
||||||
|
|
|
@ -41,6 +41,7 @@ typedef struct Sprite {
|
||||||
SDL_Rect clip;
|
SDL_Rect clip;
|
||||||
bool destroyTextures;
|
bool destroyTextures;
|
||||||
Position pos;
|
Position pos;
|
||||||
|
Position offset;
|
||||||
Dimension dim;
|
Dimension dim;
|
||||||
double angle;
|
double angle;
|
||||||
SDL_Point rotationPoint;
|
SDL_Point rotationPoint;
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* BreakHack - A dungeone crawler RPG
|
||||||
|
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sprite_util.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
SDL_Renderer *renderer;
|
||||||
|
} utilData;
|
||||||
|
|
||||||
|
void
|
||||||
|
sprite_util_init(SDL_Renderer *renderer)
|
||||||
|
{
|
||||||
|
utilData.renderer = renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
Sprite *
|
||||||
|
sprite_util_create_text_sprite(const char *fontPath,
|
||||||
|
int size,
|
||||||
|
SDL_Color fg,
|
||||||
|
SDL_Color outline,
|
||||||
|
const char *fmt,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
Sprite *sprite = sprite_create();
|
||||||
|
|
||||||
|
sprite_load_text_texture(sprite, fontPath, 0, size, 1);
|
||||||
|
char priceLabel[10];
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
m_vsprintf(priceLabel, 10, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
texture_load_from_text(sprite->textures[0],
|
||||||
|
priceLabel,
|
||||||
|
fg,
|
||||||
|
outline,
|
||||||
|
utilData.renderer);
|
||||||
|
|
||||||
|
sprite->dim = sprite->textures[0]->dim;
|
||||||
|
|
||||||
|
return sprite;
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue