Compare commits
384 commits
version-0.
...
master
Author | SHA1 | Date | |
---|---|---|---|
![]() |
0afaa20c1d | ||
![]() |
7207d53885 | ||
![]() |
ed33a36bca | ||
![]() |
29ab9721af | ||
![]() |
a2192e25eb | ||
![]() |
fe37aa11df | ||
![]() |
f03a3a31a8 | ||
![]() |
40b2d7f45d | ||
![]() |
9c5bad5959 | ||
![]() |
ba5fc73127 | ||
![]() |
ca3b04b895 | ||
![]() |
0c8cb197c2 | ||
![]() |
a11e7de14e | ||
![]() |
759f93cae0 | ||
![]() |
9faad5f263 | ||
![]() |
d822cb3438 | ||
![]() |
f98cc543f6 | ||
![]() |
4365aa4bfc | ||
![]() |
fc678c6b42 | ||
![]() |
e92fd2b6f3 | ||
![]() |
c894f6e094 | ||
![]() |
63eaea3536 | ||
![]() |
4a2d8770d9 | ||
![]() |
b4569622a0 | ||
![]() |
4bf9a9177f | ||
![]() |
fc8e65f4d6 | ||
![]() |
586343a614 | ||
![]() |
7ffa6025ce | ||
![]() |
a20d701096 | ||
![]() |
c46927ea10 | ||
![]() |
a83ee77eea | ||
![]() |
5aca2fb56a | ||
![]() |
564f9842a2 | ||
![]() |
d5ff57e025 | ||
![]() |
81e25f73bb | ||
![]() |
644ff6edc0 | ||
![]() |
097879440d | ||
![]() |
b839fb6463 | ||
![]() |
ae1a48deed | ||
![]() |
25a143cf22 | ||
![]() |
20fa95bd93 | ||
![]() |
a86912705c | ||
![]() |
ad0069e899 | ||
![]() |
42575ef1f5 | ||
![]() |
f19c1dbb20 | ||
![]() |
e03a63f9fb | ||
![]() |
48e28ee636 | ||
![]() |
b9209beddd | ||
![]() |
8594568ff4 | ||
![]() |
521180b086 | ||
![]() |
05d54ff661 | ||
![]() |
f84b63f0e6 | ||
![]() |
97fe02d99d | ||
![]() |
0d889cd0ff | ||
![]() |
b9656013b0 | ||
![]() |
fc4eacadb0 | ||
![]() |
9bf6926dc3 | ||
![]() |
077f0e84ea | ||
![]() |
a4a4389281 | ||
![]() |
9c02fb846b | ||
![]() |
694ee210d6 | ||
![]() |
1788b8fb28 | ||
![]() |
23ead1f0ca | ||
![]() |
f26189c696 | ||
![]() |
b193bab148 | ||
![]() |
569d04725a | ||
![]() |
e51fb8627c | ||
![]() |
be3eef7082 | ||
![]() |
d6326c9e41 | ||
![]() |
fd53f92fe6 | ||
![]() |
d93bc1615c | ||
![]() |
86ddfc460f | ||
![]() |
ff7111b006 | ||
![]() |
b311713064 | ||
![]() |
6f91533950 | ||
![]() |
2997dc363b | ||
![]() |
d264760405 | ||
![]() |
2802a44ba4 | ||
![]() |
aa72cfe4a4 | ||
![]() |
3b81959aa9 | ||
![]() |
973495b687 | ||
![]() |
379060b8c7 | ||
![]() |
f4fa50a413 | ||
![]() |
48a7f72411 | ||
![]() |
0272ba8540 | ||
![]() |
75646619b3 | ||
![]() |
dca38397e7 | ||
![]() |
0d1eacdc5c | ||
![]() |
72ecca8c82 | ||
![]() |
a3f82139e9 | ||
![]() |
dd541ae59d | ||
![]() |
d9219a8c64 | ||
![]() |
3b06105813 | ||
![]() |
5db3d1a306 | ||
![]() |
5e01eb29a9 | ||
![]() |
b2a6262964 | ||
![]() |
b16ca3fd65 | ||
![]() |
b2d0b0ee4c | ||
![]() |
2c011079a8 | ||
![]() |
cfefffe1cc | ||
![]() |
40611d4d54 | ||
![]() |
04b3cf3f16 | ||
![]() |
d6e2b64140 | ||
![]() |
dbc2000434 | ||
![]() |
056b0b307b | ||
![]() |
f64b202ee7 | ||
![]() |
601f3331ed | ||
![]() |
cd89625c96 | ||
![]() |
265e53e05a | ||
![]() |
af3568154a | ||
![]() |
1baf90a776 | ||
![]() |
a26f0b0c0a | ||
![]() |
584c4e9f67 | ||
![]() |
87e69bebde | ||
![]() |
970905fcd5 | ||
![]() |
2421a33bb0 | ||
![]() |
784f753e72 | ||
![]() |
8c8d6dc9e7 | ||
![]() |
6576164fad | ||
![]() |
b6d1ae2700 | ||
![]() |
efdb0cb119 | ||
![]() |
8bbafc4d10 | ||
![]() |
0d79ce35b3 | ||
![]() |
a418b48e94 | ||
![]() |
b28b76ee2d | ||
![]() |
cad51f4908 | ||
![]() |
ab1a415b55 | ||
![]() |
75c28cd764 | ||
![]() |
b603ef5a3f | ||
![]() |
6a0725e401 | ||
![]() |
02c42eb042 | ||
![]() |
6437bd3b54 | ||
![]() |
7602fb0b31 | ||
![]() |
57d69015c2 | ||
![]() |
769530b45c | ||
![]() |
b0204772c7 | ||
![]() |
19682fd0bc | ||
![]() |
ea92dcc3c4 | ||
![]() |
fcd1bc589c | ||
![]() |
f668ff6b7a | ||
![]() |
689bb150c6 | ||
![]() |
6ff1919587 | ||
![]() |
f559b5a39d | ||
![]() |
6a72d1160f | ||
![]() |
fb064ffbf1 | ||
![]() |
3c5021e4c9 | ||
![]() |
e0588847fa | ||
![]() |
2c6565c40a | ||
![]() |
812407c3df | ||
![]() |
a0eff927b6 | ||
![]() |
119b3ed11d | ||
![]() |
68e50342e5 | ||
![]() |
87459d41bb | ||
![]() |
dfd3118d04 | ||
![]() |
029a0f86ae | ||
![]() |
ca74b817e5 | ||
![]() |
cd02507023 | ||
![]() |
d99d9a68c8 | ||
![]() |
7fc32b0248 | ||
![]() |
9468990f76 | ||
![]() |
82ee8f68f7 | ||
![]() |
1ab708c4eb | ||
![]() |
06a843f169 | ||
![]() |
af933c827a | ||
![]() |
7db64b73c5 | ||
![]() |
7b0bac4f59 | ||
![]() |
2aa4f0a2e8 | ||
![]() |
2458f01ebd | ||
![]() |
86eabed3db | ||
![]() |
38159a5f84 | ||
![]() |
d6c5a89251 | ||
![]() |
4a48910273 | ||
![]() |
e01e697535 | ||
![]() |
be7b86a913 | ||
![]() |
570b70ab0c | ||
![]() |
7a551cf83a | ||
![]() |
343f3a246f | ||
![]() |
0d6a71b06f | ||
![]() |
2a6b892e7f | ||
![]() |
4b0d76bbcc | ||
![]() |
3e0adf0c22 | ||
![]() |
47c219b86e | ||
![]() |
e1c2869d1c | ||
![]() |
461ad03d27 | ||
![]() |
842aac3127 | ||
![]() |
94385b195d | ||
![]() |
c509162be1 | ||
![]() |
5aa54d875f | ||
![]() |
0674908e49 | ||
![]() |
5c47a0151c | ||
![]() |
4b34de2109 | ||
![]() |
f208ca946e | ||
![]() |
ab391aaa97 | ||
![]() |
b8d2d1870d | ||
![]() |
e8199a973c | ||
![]() |
d2a5dfa713 | ||
![]() |
e45de2a2cf | ||
![]() |
dc8648016d | ||
![]() |
3dc70c3af6 | ||
![]() |
74a1801069 | ||
![]() |
cdd58ee21a | ||
![]() |
31df3fe7a3 | ||
![]() |
dd463d7d6e | ||
![]() |
931d9493d2 | ||
![]() |
e015652f4c | ||
![]() |
8453e7c3b9 | ||
![]() |
af2947c50a | ||
![]() |
5cb74151f5 | ||
![]() |
3a745d492a | ||
![]() |
ea9f6bf383 | ||
![]() |
f45dbe8c48 | ||
![]() |
96a585220b | ||
![]() |
c0d668fb0b | ||
![]() |
9dcc2036aa | ||
![]() |
e361984c40 | ||
![]() |
90c37fe4c9 | ||
![]() |
4eaf3c35d6 | ||
![]() |
5f1a453fb4 | ||
![]() |
20f03731e5 | ||
![]() |
37715f05a5 | ||
![]() |
33cd490ed3 | ||
![]() |
c97648ab3a | ||
![]() |
ac252bf09d | ||
![]() |
a0b785cb2a | ||
![]() |
0f8e61797f | ||
![]() |
7a0b2f988d | ||
![]() |
6cbfcf993e | ||
![]() |
0eb245d113 | ||
![]() |
d6e64dd06b | ||
![]() |
a2246d2b71 | ||
![]() |
bed5ce22d2 | ||
![]() |
cc44c9d37a | ||
![]() |
dfc6aa08e9 | ||
![]() |
8545b8cf1d | ||
![]() |
8a3046e141 | ||
![]() |
74a8599977 | ||
![]() |
7c90eb6da1 | ||
![]() |
abea6da2e0 | ||
![]() |
1780a758b3 | ||
![]() |
20176cf54a | ||
![]() |
4e7f837240 | ||
![]() |
438bd8ab8a | ||
![]() |
82ce3cb6be | ||
![]() |
70d27b9a95 | ||
![]() |
78ba83e916 | ||
![]() |
c4ed26184b | ||
![]() |
edf10c976a | ||
![]() |
bac552c3d7 | ||
![]() |
dab0e092e6 | ||
![]() |
6269d10807 | ||
![]() |
8a1f42c0f1 | ||
![]() |
d1bd6b7c45 | ||
![]() |
2ceab51c40 | ||
![]() |
14619558fa | ||
![]() |
9d55b2954a | ||
![]() |
1a9e068d02 | ||
![]() |
bc557652ba | ||
![]() |
c8a8d2b1af | ||
![]() |
292711f91f | ||
![]() |
ad1d08ca96 | ||
![]() |
dac9b1b3de | ||
![]() |
1ab5fa4291 | ||
![]() |
4c03fe1ed3 | ||
![]() |
bc31750d9c | ||
![]() |
8aeac5397a | ||
![]() |
2fb1687997 | ||
![]() |
eb350698aa | ||
![]() |
e0d7744eeb | ||
![]() |
5aa9bcb655 | ||
![]() |
c51d46aeb8 | ||
![]() |
57e8774fad | ||
![]() |
eb709930f5 | ||
![]() |
30997cbff5 | ||
![]() |
ebb69dd589 | ||
![]() |
00c28f47eb | ||
![]() |
a70f11646a | ||
![]() |
31b35b43eb | ||
![]() |
17d30e2ed2 | ||
![]() |
5d924c764f | ||
![]() |
a342c53b02 | ||
![]() |
43435509f6 | ||
![]() |
bf8a2dc0c5 | ||
![]() |
58981fd8ed | ||
![]() |
787be78a69 | ||
![]() |
bec8fe0a13 | ||
![]() |
1b4f55804c | ||
![]() |
5ffa3b0d1e | ||
![]() |
467a26628c | ||
![]() |
137dcc1f30 | ||
![]() |
57e042e786 | ||
![]() |
2ecef8d9f9 | ||
![]() |
7186c2ecb0 | ||
![]() |
84a5f06dac | ||
![]() |
19b9a4affd | ||
![]() |
08bc48df3d | ||
![]() |
766b20f3f8 | ||
![]() |
edee3ac0c9 | ||
![]() |
35ced58cc9 | ||
![]() |
a5b8e411e3 | ||
![]() |
80b4faf940 | ||
![]() |
576110ea44 | ||
![]() |
724d3edb61 | ||
![]() |
b5d93399d5 | ||
![]() |
d7e9944e58 | ||
![]() |
e11a374d26 | ||
![]() |
5a3b567fd1 | ||
![]() |
0e2f213871 | ||
![]() |
ca328e10dc | ||
![]() |
e6a8a8b338 | ||
![]() |
c7c48658bd | ||
![]() |
1f90367f51 | ||
![]() |
e18aeaf05c | ||
![]() |
b832bbd78a | ||
![]() |
6d73c87c4e | ||
![]() |
07ce8a4148 | ||
![]() |
4f090159ab | ||
![]() |
b6c1eba1b3 | ||
![]() |
c1aba2d5c8 | ||
![]() |
c014e65c13 | ||
![]() |
52f45e1d45 | ||
![]() |
862d8b4d81 | ||
![]() |
6fa7b0a418 | ||
![]() |
0ebc60793a | ||
![]() |
922fbeba0e | ||
![]() |
72951f308f | ||
![]() |
47c6bfd531 | ||
![]() |
da273cbee6 | ||
![]() |
5af9a6664e | ||
![]() |
d7ff7d6acf | ||
![]() |
6fe343d82d | ||
![]() |
322797f787 | ||
![]() |
193d97eb48 | ||
![]() |
2e79cf8781 | ||
![]() |
2b57552152 | ||
![]() |
6c9016eb0f | ||
![]() |
acbf384e2a | ||
![]() |
a53f81715d | ||
![]() |
8b3573b01d | ||
![]() |
1aa6674e42 | ||
![]() |
0a40135f5d | ||
![]() |
65c9e4b0c6 | ||
![]() |
263b7741f6 | ||
![]() |
f1cc9f86c1 | ||
![]() |
a6d83db20c | ||
![]() |
2baa044695 | ||
![]() |
5ed8196c80 | ||
![]() |
0efb17371b | ||
![]() |
d3158291f7 | ||
![]() |
113a4a3b3e | ||
![]() |
c4611c0138 | ||
![]() |
1d2968f826 | ||
![]() |
49531ba148 | ||
![]() |
8368d2e751 | ||
![]() |
15bb69624b | ||
![]() |
eeea3c794f | ||
![]() |
7984540c0c | ||
![]() |
63f032ff12 | ||
![]() |
75db188dc6 | ||
![]() |
c4e01775bc | ||
![]() |
00f76dfb34 | ||
![]() |
2815375836 | ||
![]() |
db5a371766 | ||
![]() |
f3e157a0f7 | ||
![]() |
ad71631809 | ||
![]() |
77f2e94515 | ||
![]() |
ee804581a8 | ||
![]() |
0623170dbc | ||
![]() |
d15c9b12fd | ||
![]() |
ff81c78d13 | ||
![]() |
fc66d221d4 | ||
![]() |
3f83d3f0bb | ||
![]() |
b2c1b220ac | ||
![]() |
a079f882df | ||
![]() |
9d6dc2f5dd | ||
![]() |
3d8a2d4342 | ||
![]() |
01525388ec | ||
![]() |
2992193447 | ||
![]() |
15c2efc415 | ||
![]() |
a34e2cd475 | ||
![]() |
a34becdaeb | ||
![]() |
73b0600039 | ||
![]() |
b68fd249ca | ||
![]() |
b7948f8154 | ||
![]() |
e1f9942da3 |
2
.gitignore
vendored
|
@ -27,3 +27,5 @@ backup
|
|||
*.dll
|
||||
*.world
|
||||
coverage
|
||||
coverage/*
|
||||
.venv
|
||||
|
|
|
@ -1 +1 @@
|
|||
set makeprg=meson\ compile\ -C\ .
|
||||
set makeprg=make\ -f\ ../Makefile\ build
|
||||
|
|
49
Makefile
|
@ -1,47 +1,72 @@
|
|||
ROOT_DIR := $(dir $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||
|
||||
all: build test
|
||||
|
||||
reset:
|
||||
ifeq '$(OS)' 'Windows_NT'
|
||||
powershell -executionpolicy bypass .\scripts\reset_build.ps1
|
||||
else
|
||||
sh -x ./scripts/reset_build.sh
|
||||
endif
|
||||
|
||||
%.cpp : %.rl
|
||||
ragel -o $@ $<
|
||||
ragel -I $(ROOT_DIR) -G1 -o $@ $<
|
||||
|
||||
build: ansi_parser.cpp lel_parser.cpp
|
||||
meson compile -j 10 -C builddir
|
||||
%.dot: %.rl
|
||||
ragel -Vp -I $(ROOT_DIR) -o $@ $<
|
||||
|
||||
%.png: %.dot
|
||||
dot -Tpng $< -o $@
|
||||
|
||||
build:
|
||||
meson compile -j 10 -C $(ROOT_DIR)/builddir
|
||||
|
||||
asset_build:
|
||||
./builddir/icongen
|
||||
|
||||
release_build:
|
||||
meson --wipe builddir -Db_ndebug=true --buildtype release
|
||||
meson compile -j 10 -C builddir
|
||||
|
||||
debug_build:
|
||||
meson setup --wipe builddir --buildtype debug
|
||||
meson setup --wipe builddir -Db_ndebug=true --buildtype debugoptimized
|
||||
meson compile -j 10 -C builddir
|
||||
|
||||
tracy_build:
|
||||
meson setup --wipe builddir --buildtype debugoptimized -Dtracy_enable=true -Dtracy:on_demand=true
|
||||
meson compile -j 10 -C builddir
|
||||
|
||||
test: build
|
||||
./builddir/runtests
|
||||
test:
|
||||
./builddir/runtests -d yes
|
||||
|
||||
run: build test
|
||||
ifeq '$(OS)' 'Windows_NT'
|
||||
powershell "cp ./builddir/zedcaster.exe ."
|
||||
./zedcaster
|
||||
else
|
||||
./builddir/zedcaster
|
||||
endif
|
||||
|
||||
debug: build
|
||||
gdb --nx -x .gdbinit --ex run --args builddir/zedcaster.exe
|
||||
gdb --nx -x .gdbinit --ex run --args builddir/zedcaster
|
||||
|
||||
debug_run: build
|
||||
gdb --nx -x .gdbinit --batch --ex run --ex bt --ex q --args builddir/zedcaster.exe
|
||||
gdb --nx -x .gdbinit --batch --ex run --ex bt --ex q --args builddir/zedcaster
|
||||
|
||||
debug_walk: build
|
||||
gdb --nx -x .gdbinit --batch --ex run --ex bt --ex q --args builddir/zedcaster.exe t
|
||||
debug_walk: build test
|
||||
gdb --nx -x .gdbinit --batch --ex run --ex bt --ex q --args builddir/zedcaster t
|
||||
|
||||
clean:
|
||||
meson compile --clean -C builddir
|
||||
|
||||
debug_test: build
|
||||
gdb --nx -x .gdbinit --ex run --args builddir/runtests.exe -e
|
||||
gdb --nx -x .gdbinit --ex run --ex bt --ex q --args builddir/runtests -e
|
||||
|
||||
win_installer:
|
||||
powershell 'start "C:\Program Files (x86)\solicus\InstallForge\bin\ifbuilderenvx86.exe" win_installer.ifp'
|
||||
powershell 'start "C:\Program Files (x86)\solicus\InstallForge\bin\ifbuilderenvx86.exe" scripts\win_installer.ifp'
|
||||
|
||||
coverage_report:
|
||||
powershell 'scripts/coverage_report.ps1'
|
||||
|
||||
money:
|
||||
scc --exclude-dir subprojects
|
||||
|
|
17
README.md
|
@ -42,8 +42,9 @@ See? That's how Free Speech works. You don't need a LICENSE.
|
|||
On all platforms you'll need these components:
|
||||
|
||||
* [Meson](https://mesonbuild.com/) -- which needs Python.
|
||||
* C++ Compiler -- Tested with Clang and G++. You can use my [Windows C++ Setup Guide](https://git.learnjsthehardway.com/learn-code-the-hard-way/lcthw-windows-installers) which features an automated installer for Windows.
|
||||
* C++ Compiler -- Tested with Clang and GCC 14.2.0. You can use my [Windows C++ Setup Guide](https://git.learnjsthehardway.com/learn-code-the-hard-way/lcthw-windows-installers) which features an automated installer for Windows.
|
||||
* [GNU make](https://www.gnu.org/software/make/) -- For the convenience Makefile. On Windows you should have this if you used my setup scripts. Otherwise `winget install ezwinports.make` will set you up.
|
||||
* [Ninja](https://ninja-build.org/) -- Meson uses this to do builds on most systems.
|
||||
* [git](https://git-scm.com/) -- Which should be on almost every platform, and is installed by default with my Windows setup scripts.
|
||||
|
||||
### Windows Instructions
|
||||
|
@ -88,7 +89,7 @@ cd raycaster
|
|||
# first compile takes a while
|
||||
make
|
||||
|
||||
./builddir/raycaster
|
||||
./builddir/zedcaster
|
||||
```
|
||||
|
||||
You don't need `make run` because Linux and OSX are sane operating systems that don't lock every
|
||||
|
@ -127,6 +128,18 @@ I would also like statistics that show it's better, not just your word.
|
|||
|
||||
It's early so probably a bunch of bugs.
|
||||
|
||||
## Linux Build Notes
|
||||
|
||||
Libraries Needed:
|
||||
|
||||
* libxi-dev
|
||||
* libfreetype-dev
|
||||
|
||||
It uses c++ so you may need to install a libg++ or libc++ for your system. Usually this is all you
|
||||
need:
|
||||
|
||||
apt install build-essential
|
||||
|
||||
## OSX Build Notes
|
||||
|
||||
* Quite a bad experience. Need to install Python, cmake, meson, and ninja all which are in homebrew but if you don't use homebrew then this is a problem.
|
||||
|
|
212
ai.cpp
Normal file
|
@ -0,0 +1,212 @@
|
|||
#include "dbc.hpp"
|
||||
#include "ai.hpp"
|
||||
|
||||
namespace ai {
|
||||
using namespace nlohmann;
|
||||
using namespace dbc;
|
||||
|
||||
static AIManager AIMGR;
|
||||
static bool initialized = false;
|
||||
|
||||
inline void validate_profile(nlohmann::json& profile) {
|
||||
for(auto& [name_key, value] : profile.items()) {
|
||||
check(value < STATE_MAX,
|
||||
fmt::format("profile field {} has value {} greater than STATE_MAX {}", (std::string)name_key, (int)value, STATE_MAX));
|
||||
}
|
||||
}
|
||||
|
||||
Action config_action(AIProfile& profile, nlohmann::json& config) {
|
||||
check(config.contains("name"), "config_action: action config missing name");
|
||||
check(config.contains("cost"), "config_action: action config missing cost");
|
||||
|
||||
Action result(config["name"], config["cost"]);
|
||||
|
||||
check(config.contains("needs"),
|
||||
fmt::format("config_action: no 'needs' field", result.name));
|
||||
check(config.contains("effects"),
|
||||
fmt::format("config_action: no 'effects' field", result.name));
|
||||
|
||||
for(auto& [name_key, value] : config["needs"].items()) {
|
||||
check(profile.contains(name_key), fmt::format("config_action({}): profile does not have need named {}", result.name, name_key));
|
||||
result.needs(profile.at(name_key), bool(value));
|
||||
}
|
||||
|
||||
for(auto& [name_key, value] : config["effects"].items()) {
|
||||
check(profile.contains(name_key), fmt::format("config_action({}): profile does not have effect named {}", result.name, name_key));
|
||||
|
||||
result.effect(profile.at(name_key), bool(value));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
State config_state(AIProfile& profile, nlohmann::json& config) {
|
||||
State result;
|
||||
|
||||
for(auto& [name_key, value] : config.items()) {
|
||||
check(profile.contains(name_key), fmt::format("config_state: profile does not have name {}", name_key));
|
||||
|
||||
int name_id = profile.at(name_key);
|
||||
result[name_id] = bool(value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is only used in tests so I can load different fixtures.
|
||||
*/
|
||||
void reset() {
|
||||
initialized = false;
|
||||
AIMGR.actions.clear();
|
||||
AIMGR.states.clear();
|
||||
AIMGR.scripts.clear();
|
||||
AIMGR.profile = json({});
|
||||
}
|
||||
|
||||
void init(std::string config_path) {
|
||||
if(!initialized) {
|
||||
Config config(config_path);
|
||||
|
||||
// profile specifies what keys (bitset indexes) are allowed
|
||||
// and how they map to the bitset of State
|
||||
validate_profile(config["profile"]);
|
||||
|
||||
// relies on json conversion?
|
||||
AIMGR.profile = config["profile"];
|
||||
|
||||
// load all actions
|
||||
auto& actions = config["actions"];
|
||||
for(auto& action_vars : actions) {
|
||||
auto the_action = config_action(AIMGR.profile, action_vars);
|
||||
AIMGR.actions.insert_or_assign(the_action.name, the_action);
|
||||
}
|
||||
|
||||
// load all states
|
||||
auto& states = config["states"];
|
||||
for(auto& [name, state_vars] : states.items()) {
|
||||
auto the_state = config_state(AIMGR.profile, state_vars);
|
||||
AIMGR.states.insert_or_assign(name, the_state);
|
||||
}
|
||||
|
||||
auto& scripts = config["scripts"];
|
||||
for(auto& [script_name, action_names] : scripts.items()) {
|
||||
std::vector<Action> the_script;
|
||||
|
||||
for(auto name : action_names) {
|
||||
check(AIMGR.actions.contains(name),
|
||||
fmt::format("ai::init(): script {} uses action {} that doesn't exist",
|
||||
(std::string)script_name, (std::string)name));
|
||||
|
||||
the_script.push_back(AIMGR.actions.at(name));
|
||||
}
|
||||
|
||||
AIMGR.scripts.insert_or_assign(script_name, the_script);
|
||||
}
|
||||
initialized = true;
|
||||
} else {
|
||||
dbc::sentinel("DOUBLE INIT: AI manager should only be intialized once if not in tests.");
|
||||
}
|
||||
}
|
||||
|
||||
void check_valid_action(std::string name, std::string msg) {
|
||||
dbc::check(AIMGR.actions.contains(name),
|
||||
fmt::format("{} tried to access action that doesn't exist {}",
|
||||
msg, name));
|
||||
}
|
||||
|
||||
State load_state(std::string state_name) {
|
||||
check(initialized, "you forgot to initialize the AI first.");
|
||||
check(AIMGR.states.contains(state_name), fmt::format(
|
||||
"ai::load_state({}): state does not exist in config",
|
||||
state_name));
|
||||
|
||||
return AIMGR.states.at(state_name);
|
||||
}
|
||||
|
||||
Action load_action(std::string action_name) {
|
||||
check(initialized, "you forgot to initialize the AI first.");
|
||||
check(AIMGR.states.contains(action_name), fmt::format(
|
||||
"ai::load_action({}): action does not exist in config",
|
||||
action_name));
|
||||
return AIMGR.actions.at(action_name);
|
||||
}
|
||||
|
||||
std::vector<Action> load_script(std::string script_name) {
|
||||
check(AIMGR.scripts.contains(script_name), fmt::format(
|
||||
"ai::load_script(): no script named {} configured", script_name));
|
||||
return AIMGR.scripts.at(script_name);
|
||||
}
|
||||
|
||||
ActionPlan plan(std::string script_name, State start, State goal) {
|
||||
// BUG: could probably memoize here, since:
|
||||
// same script+same start+same goal will/should produce the same results
|
||||
|
||||
check(initialized, "you forgot to initialize the AI first.");
|
||||
auto script = load_script(script_name);
|
||||
return plan_actions(script, start, goal);
|
||||
}
|
||||
|
||||
int state_id(std::string name) {
|
||||
check(AIMGR.profile.contains(name), fmt::format(
|
||||
"ai::state_id({}): id is not configured in profile",
|
||||
name));
|
||||
return AIMGR.profile.at(name);
|
||||
}
|
||||
|
||||
void set(State& state, std::string name, bool value) {
|
||||
// resort by best fit
|
||||
state.set(state_id(name), value);
|
||||
}
|
||||
|
||||
bool test(State state, std::string name) {
|
||||
return state.test(state_id(name));
|
||||
}
|
||||
|
||||
void EntityAI::fit_sort() {
|
||||
if(active()) {
|
||||
std::sort(plan.script.begin(), plan.script.end(),
|
||||
[&](auto& l, auto& r) {
|
||||
int l_cost = l.cost + ai::distance_to_goal(start, goal);
|
||||
int r_cost = r.cost + ai::distance_to_goal(start, goal);
|
||||
return l_cost < r_cost;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
std::string& EntityAI::wants_to() {
|
||||
return plan.script[0].name;
|
||||
}
|
||||
|
||||
bool EntityAI::wants_to(std::string name) {
|
||||
ai::check_valid_action(name, "EntityAI::wants_to");
|
||||
return plan.script.size() > 0 && plan.script[0].name == name;
|
||||
}
|
||||
|
||||
bool EntityAI::active() {
|
||||
if(plan.script.size() == 1) {
|
||||
return plan.script[0] != FINAL_ACTION;
|
||||
} else {
|
||||
return plan.script.size() != 0;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityAI::set_state(std::string name, bool setting) {
|
||||
fit_sort();
|
||||
ai::set(start, name, setting);
|
||||
}
|
||||
|
||||
bool EntityAI::get_state(std::string name) {
|
||||
return ai::test(start, name);
|
||||
}
|
||||
|
||||
void EntityAI::update() {
|
||||
plan = ai::plan(script, start, goal);
|
||||
fit_sort();
|
||||
}
|
||||
|
||||
AIProfile* profile() {
|
||||
return &AIMGR.profile;
|
||||
}
|
||||
|
||||
}
|
65
ai.hpp
Normal file
|
@ -0,0 +1,65 @@
|
|||
#pragma once
|
||||
#include <vector>
|
||||
#include "matrix.hpp"
|
||||
#include <bitset>
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include "config.hpp"
|
||||
#include "goap.hpp"
|
||||
|
||||
namespace ai {
|
||||
struct EntityAI {
|
||||
std::string script;
|
||||
ai::State start;
|
||||
ai::State goal;
|
||||
ai::ActionPlan plan;
|
||||
|
||||
EntityAI(std::string script, ai::State start, ai::State goal) :
|
||||
script(script), start(start), goal(goal)
|
||||
{
|
||||
}
|
||||
|
||||
EntityAI() {};
|
||||
|
||||
bool wants_to(std::string name);
|
||||
std::string& wants_to();
|
||||
void fit_sort();
|
||||
|
||||
bool active();
|
||||
|
||||
void set_state(std::string name, bool setting);
|
||||
bool get_state(std::string name);
|
||||
|
||||
void update();
|
||||
|
||||
void dump();
|
||||
std::string to_string();
|
||||
};
|
||||
|
||||
struct AIManager {
|
||||
AIProfile profile;
|
||||
std::unordered_map<std::string, Action> actions;
|
||||
std::unordered_map<std::string, State> states;
|
||||
std::unordered_map<std::string, std::vector<Action>> scripts;
|
||||
};
|
||||
|
||||
/* This is really only used in test to load different fixtures. */
|
||||
void reset();
|
||||
void init(std::string config_path);
|
||||
|
||||
Action config_action(AIProfile& profile, nlohmann::json& config);
|
||||
State config_state(AIProfile& profile, nlohmann::json& config);
|
||||
|
||||
int state_id(std::string name);
|
||||
State load_state(std::string state_name);
|
||||
Action load_action(std::string action_name);
|
||||
std::vector<Action> load_script(std::string script_name);
|
||||
|
||||
void set(State& state, std::string name, bool value=true);
|
||||
bool test(State state, std::string name);
|
||||
ActionPlan plan(std::string script_name, State start, State goal);
|
||||
|
||||
/* Mostly used for debugging and validation. */
|
||||
void check_valid_action(std::string name, std::string msg);
|
||||
}
|
74
ai_debug.cpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
#include "ai.hpp"
|
||||
#include "ai_debug.hpp"
|
||||
|
||||
namespace ai {
|
||||
|
||||
/*
|
||||
* Yeah this is weird but it's only to debug things like
|
||||
* the preconditions which are weirdly done.
|
||||
*/
|
||||
void dump_only(State state, bool matching, bool show_as) {
|
||||
AIProfile* profile = ai::profile();
|
||||
for(auto& [name, name_id] : *profile) {
|
||||
if(state.test(name_id) == matching) {
|
||||
fmt::println("\t{}={}", name, show_as);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dump_state(State state) {
|
||||
AIProfile* profile = ai::profile();
|
||||
for(auto& [name, name_id] : *profile) {
|
||||
fmt::println("\t{}={}", name,
|
||||
state.test(name_id));
|
||||
}
|
||||
}
|
||||
|
||||
void dump_action(Action& action) {
|
||||
fmt::println(" --ACTION: {}, cost={}", action.name, action.cost);
|
||||
|
||||
fmt::println(" PRECONDS:");
|
||||
dump_only(action.$positive_preconds, true, true);
|
||||
dump_only(action.$negative_preconds, true, false);
|
||||
|
||||
fmt::println(" EFFECTS:");
|
||||
dump_only(action.$positive_effects, true, true);
|
||||
dump_only(action.$negative_effects, true, false);
|
||||
}
|
||||
|
||||
State dump_script(std::string msg, State start, Script& script) {
|
||||
fmt::println("--SCRIPT DUMP: {}", msg);
|
||||
fmt::println("# STATE BEFORE:");
|
||||
dump_state(start);
|
||||
fmt::print("% ACTIONS PLANNED:");
|
||||
for(auto& action : script) {
|
||||
fmt::print("{} ", action.name);
|
||||
}
|
||||
fmt::print("\n");
|
||||
|
||||
for(auto& action : script) {
|
||||
dump_action(action);
|
||||
|
||||
start = action.apply_effect(start);
|
||||
fmt::println(" ## STATE AFTER:");
|
||||
dump_state(start);
|
||||
}
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
void EntityAI::dump() {
|
||||
dump_script(script, start, plan.script);
|
||||
}
|
||||
|
||||
std::string EntityAI::to_string() {
|
||||
AIProfile* profile = ai::profile();
|
||||
std::string result = wants_to();
|
||||
|
||||
for(auto& [name, name_id] : *profile) {
|
||||
result += fmt::format("\n{}={}", name, start.test(name_id));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
10
ai_debug.hpp
Normal file
|
@ -0,0 +1,10 @@
|
|||
#pragma once
|
||||
#include "goap.hpp"
|
||||
|
||||
namespace ai {
|
||||
AIProfile* profile();
|
||||
void dump_only(State state, bool matching, bool show_as);
|
||||
void dump_state(State state);
|
||||
void dump_action(Action& action);
|
||||
State dump_script(std::string msg, State start, Script& script);
|
||||
}
|
117
animation.cpp
Normal file
|
@ -0,0 +1,117 @@
|
|||
#include "animation.hpp"
|
||||
|
||||
namespace components {
|
||||
void Animation::play() {
|
||||
if(!playing) {
|
||||
current = 0;
|
||||
subframe = 0.0f;
|
||||
playing = true;
|
||||
}
|
||||
}
|
||||
|
||||
float Animation::twitching() {
|
||||
float tick = ease::sine(float(frames) / subframe * ease_rate);
|
||||
|
||||
switch(easing) {
|
||||
case ease::NONE:
|
||||
return 0.0;
|
||||
case ease::SINE:
|
||||
return tick;
|
||||
case ease::OUT_CIRC:
|
||||
return ease::out_circ(tick);
|
||||
case ease::OUT_BOUNCE:
|
||||
return ease::sine(ease::out_bounce(tick));
|
||||
case ease::IN_OUT_BACK:
|
||||
return ease::sine(ease::in_out_back(tick));
|
||||
default:
|
||||
dbc::sentinel(
|
||||
fmt::format("Invalid easing {} given to animation",
|
||||
int(easing)));
|
||||
}
|
||||
}
|
||||
|
||||
void Animation::step(sf::Vector2f& scale_out, sf::Vector2f& pos_out, sf::IntRect& rect_out) {
|
||||
if(playing && current < frames) {
|
||||
float tick = twitching();
|
||||
scale_out.x = std::lerp(scale_out.x, scale_out.x + scale, tick);
|
||||
scale_out.y = std::lerp(scale_out.y, scale_out.y + scale, tick);
|
||||
|
||||
if(stationary) {
|
||||
pos_out.y = pos_out.y - (pos_out.y * scale_out.y - pos_out.y);
|
||||
}
|
||||
|
||||
if(!simple) {
|
||||
rect_out.position.x += current * frame_width;
|
||||
}
|
||||
|
||||
subframe += speed;
|
||||
current = int(subframe);
|
||||
} else if(!looped) {
|
||||
playing = false;
|
||||
current = frames - 1;
|
||||
subframe = float(frames - 1);
|
||||
|
||||
if(!simple) {
|
||||
rect_out.position.x += current * frame_width;
|
||||
}
|
||||
} else {
|
||||
playing = false;
|
||||
current = 0;
|
||||
subframe = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace animation {
|
||||
using namespace components;
|
||||
using namespace textures;
|
||||
|
||||
static AnimationManager MGR;
|
||||
static bool initialized = false;
|
||||
|
||||
bool apply(Animation& anim, SpriteTexture& target) {
|
||||
auto size = target.texture->getSize();
|
||||
anim.frame_width = int(size.x) / (unsigned int)anim.frames;
|
||||
sf::IntRect rect{{0,0}, {anim.frame_width, int(size.y)}};
|
||||
sf::Vector2f scale{1.0, 1.0};
|
||||
sf::Vector2f pos{0, 0};
|
||||
|
||||
anim.step(scale, pos, rect);
|
||||
|
||||
target.sprite->setTextureRect(rect);
|
||||
target.sprite->setPosition(pos);
|
||||
target.sprite->setScale(scale);
|
||||
|
||||
return anim.playing;
|
||||
}
|
||||
|
||||
void rotate(sf::Sprite& target, float degrees) {
|
||||
target.rotate(sf::degrees(degrees));
|
||||
}
|
||||
|
||||
void center(sf::Sprite& target, sf::Vector2f pos) {
|
||||
auto bounds = target.getLocalBounds();
|
||||
target.setPosition({pos.x + bounds.size.x / 2,
|
||||
pos.y + bounds.size.y / 2});
|
||||
target.setOrigin({bounds.size.x / 2, bounds.size.y / 2});
|
||||
}
|
||||
|
||||
void init() {
|
||||
if(!initialized) {
|
||||
Config config("assets/animations.json");
|
||||
|
||||
for(auto& [name, data] : config.json().items()) {
|
||||
auto anim = components::convert<Animation>(data);
|
||||
MGR.animations.insert_or_assign(name, anim);
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
Animation load(std::string name) {
|
||||
dbc::check(initialized, "You forgot to initialize animation.");
|
||||
return MGR.animations.at(name);
|
||||
}
|
||||
}
|
17
animation.hpp
Normal file
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
#include "components.hpp"
|
||||
#include "textures.hpp"
|
||||
#include "easings.hpp"
|
||||
|
||||
namespace animation {
|
||||
struct AnimationManager {
|
||||
std::unordered_map<std::string, components::Animation> animations;
|
||||
};
|
||||
|
||||
bool apply(components::Animation& anim, textures::SpriteTexture& target);
|
||||
void rotate(sf::Sprite& target, float degrees);
|
||||
void center(sf::Sprite& target, sf::Vector2f pos);
|
||||
|
||||
void init();
|
||||
components::Animation load(std::string name);
|
||||
}
|
376
ansi_parser.cpp
|
@ -1,376 +0,0 @@
|
|||
|
||||
#line 1 "ansi_parser.rl"
|
||||
#include <fmt/core.h>
|
||||
#include <string_view>
|
||||
#include "dbc.hpp"
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include "ansi_parser.hpp"
|
||||
#include <iostream>
|
||||
|
||||
using namespace fmt;
|
||||
|
||||
|
||||
#line 122 "ansi_parser.rl"
|
||||
|
||||
|
||||
|
||||
#line 13 "ansi_parser.cpp"
|
||||
static const char _ansi_parser_actions[] = {
|
||||
0, 1, 0, 1, 3, 1, 4, 1,
|
||||
5, 1, 6, 1, 7, 1, 8, 1,
|
||||
9, 1, 10, 1, 11, 1, 15, 1,
|
||||
16, 2, 1, 12, 2, 1, 13, 2,
|
||||
6, 7, 2, 16, 5, 3, 1, 14,
|
||||
2
|
||||
};
|
||||
|
||||
static const char _ansi_parser_key_offsets[] = {
|
||||
0, 0, 1, 2, 11, 12, 14, 17,
|
||||
18, 22, 23, 27, 28, 29, 30, 31,
|
||||
33, 36, 38, 41, 43, 46, 47, 50,
|
||||
51, 52, 53, 54, 55
|
||||
};
|
||||
|
||||
static const int _ansi_parser_trans_keys[] = {
|
||||
27, 91, 48, 49, 50, 51, 52, 55,
|
||||
57, 53, 54, 109, 48, 109, 34, 48,
|
||||
55, 109, 50, 52, 55, 109, 109, 49,
|
||||
56, 57, 109, 109, 59, 50, 59, 48,
|
||||
57, 59, 48, 57, 48, 57, 59, 48,
|
||||
57, 48, 57, 109, 48, 57, 109, 56,
|
||||
57, 109, 59, 50, 109, 109, 27, 27,
|
||||
0
|
||||
};
|
||||
|
||||
static const char _ansi_parser_single_lengths[] = {
|
||||
0, 1, 1, 7, 1, 2, 3, 1,
|
||||
4, 1, 4, 1, 1, 1, 1, 0,
|
||||
1, 0, 1, 0, 1, 1, 3, 1,
|
||||
1, 1, 1, 1, 1
|
||||
};
|
||||
|
||||
static const char _ansi_parser_range_lengths[] = {
|
||||
0, 0, 0, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 1,
|
||||
1, 1, 1, 1, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
static const char _ansi_parser_index_offsets[] = {
|
||||
0, 0, 2, 4, 13, 15, 18, 22,
|
||||
24, 29, 31, 36, 38, 40, 42, 44,
|
||||
46, 49, 51, 54, 56, 59, 61, 65,
|
||||
67, 69, 71, 73, 75
|
||||
};
|
||||
|
||||
static const char _ansi_parser_trans_targs[] = {
|
||||
2, 1, 3, 0, 4, 5, 8, 10,
|
||||
22, 26, 6, 7, 0, 28, 0, 6,
|
||||
28, 0, 7, 7, 7, 0, 28, 0,
|
||||
7, 7, 9, 28, 0, 28, 0, 11,
|
||||
12, 21, 28, 0, 28, 0, 13, 0,
|
||||
14, 0, 15, 0, 16, 0, 17, 16,
|
||||
0, 18, 0, 19, 18, 0, 20, 0,
|
||||
28, 20, 0, 28, 0, 23, 25, 28,
|
||||
0, 24, 0, 14, 0, 28, 0, 28,
|
||||
0, 2, 1, 2, 1, 0
|
||||
};
|
||||
|
||||
static const char _ansi_parser_trans_actions[] = {
|
||||
0, 7, 0, 0, 21, 21, 21, 21,
|
||||
21, 21, 21, 21, 0, 31, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 17, 0, 15, 0, 0,
|
||||
0, 0, 0, 0, 19, 0, 0, 0,
|
||||
3, 0, 0, 0, 1, 0, 25, 0,
|
||||
0, 1, 0, 28, 0, 0, 1, 0,
|
||||
37, 0, 0, 9, 0, 0, 0, 0,
|
||||
0, 0, 0, 5, 0, 11, 0, 13,
|
||||
0, 0, 7, 23, 34, 0
|
||||
};
|
||||
|
||||
static const char _ansi_parser_eof_actions[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 23
|
||||
};
|
||||
|
||||
static const int ansi_parser_start = 27;
|
||||
static const int ansi_parser_first_final = 27;
|
||||
static const int ansi_parser_error = 0;
|
||||
|
||||
static const int ansi_parser_en_main = 27;
|
||||
|
||||
|
||||
#line 125 "ansi_parser.rl"
|
||||
|
||||
#include <ftxui/screen/terminal.hpp>
|
||||
|
||||
ANSIParser::ANSIParser(sf::Color default_fg, sf::Color default_bg) :
|
||||
$default_fg(default_fg),
|
||||
$default_bg(default_bg)
|
||||
{
|
||||
}
|
||||
|
||||
bool ANSIParser::parse(std::wstring_view codes, ColorCB color_cb, WriteCB write_cb) {
|
||||
const wchar_t *start = nullptr;
|
||||
int cs = 0;
|
||||
unsigned int value = 0;
|
||||
const wchar_t *p = codes.data();
|
||||
const wchar_t *pe = p + codes.size();
|
||||
const wchar_t *eof = pe;
|
||||
sf::Color bgcolor($default_bg);
|
||||
sf::Color color($default_fg);
|
||||
sf::Color* target = &color;
|
||||
|
||||
|
||||
#line 120 "ansi_parser.cpp"
|
||||
{
|
||||
cs = ansi_parser_start;
|
||||
}
|
||||
|
||||
#line 146 "ansi_parser.rl"
|
||||
|
||||
#line 123 "ansi_parser.cpp"
|
||||
{
|
||||
int _klen;
|
||||
unsigned int _trans;
|
||||
const char *_acts;
|
||||
unsigned int _nacts;
|
||||
const int *_keys;
|
||||
|
||||
if ( p == pe )
|
||||
goto _test_eof;
|
||||
if ( cs == 0 )
|
||||
goto _out;
|
||||
_resume:
|
||||
_keys = _ansi_parser_trans_keys + _ansi_parser_key_offsets[cs];
|
||||
_trans = _ansi_parser_index_offsets[cs];
|
||||
|
||||
_klen = _ansi_parser_single_lengths[cs];
|
||||
if ( _klen > 0 ) {
|
||||
const int *_lower = _keys;
|
||||
const int *_mid;
|
||||
const int *_upper = _keys + _klen - 1;
|
||||
while (1) {
|
||||
if ( _upper < _lower )
|
||||
break;
|
||||
|
||||
_mid = _lower + ((_upper-_lower) >> 1);
|
||||
if ( (*p) < *_mid )
|
||||
_upper = _mid - 1;
|
||||
else if ( (*p) > *_mid )
|
||||
_lower = _mid + 1;
|
||||
else {
|
||||
_trans += (unsigned int)(_mid - _keys);
|
||||
goto _match;
|
||||
}
|
||||
}
|
||||
_keys += _klen;
|
||||
_trans += _klen;
|
||||
}
|
||||
|
||||
_klen = _ansi_parser_range_lengths[cs];
|
||||
if ( _klen > 0 ) {
|
||||
const int *_lower = _keys;
|
||||
const int *_mid;
|
||||
const int *_upper = _keys + (_klen<<1) - 2;
|
||||
while (1) {
|
||||
if ( _upper < _lower )
|
||||
break;
|
||||
|
||||
_mid = _lower + (((_upper-_lower) >> 1) & ~1);
|
||||
if ( (*p) < _mid[0] )
|
||||
_upper = _mid - 2;
|
||||
else if ( (*p) > _mid[1] )
|
||||
_lower = _mid + 2;
|
||||
else {
|
||||
_trans += (unsigned int)((_mid - _keys)>>1);
|
||||
goto _match;
|
||||
}
|
||||
}
|
||||
_trans += _klen;
|
||||
}
|
||||
|
||||
_match:
|
||||
cs = _ansi_parser_trans_targs[_trans];
|
||||
|
||||
if ( _ansi_parser_trans_actions[_trans] == 0 )
|
||||
goto _again;
|
||||
|
||||
_acts = _ansi_parser_actions + _ansi_parser_trans_actions[_trans];
|
||||
_nacts = (unsigned int) *_acts++;
|
||||
while ( _nacts-- > 0 )
|
||||
{
|
||||
switch ( *_acts++ )
|
||||
{
|
||||
case 0:
|
||||
#line 14 "ansi_parser.rl"
|
||||
{
|
||||
start = p;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
#line 18 "ansi_parser.rl"
|
||||
{
|
||||
value = 0;
|
||||
size_t len = p - start;
|
||||
dbc::check(start[0] != '-', "negative numbers not supported");
|
||||
|
||||
switch(len) {
|
||||
case 10: value += (start[len-10] - '0') * 1000000000; [[fallthrough]];
|
||||
case 9: value += (start[len- 9] - '0') * 100000000; [[fallthrough]];
|
||||
case 8: value += (start[len- 8] - '0') * 10000000; [[fallthrough]];
|
||||
case 7: value += (start[len- 7] - '0') * 1000000; [[fallthrough]];
|
||||
case 6: value += (start[len- 6] - '0') * 100000; [[fallthrough]];
|
||||
case 5: value += (start[len- 5] - '0') * 10000; [[fallthrough]];
|
||||
case 4: value += (start[len- 4] - '0') * 1000; [[fallthrough]];
|
||||
case 3: value += (start[len- 3] - '0') * 100; [[fallthrough]];
|
||||
case 2: value += (start[len- 2] - '0') * 10; [[fallthrough]];
|
||||
case 1: value += (start[len- 1] - '0');
|
||||
break;
|
||||
default:
|
||||
dbc::sentinel("can't process > 10 digits");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
#line 40 "ansi_parser.rl"
|
||||
{
|
||||
color_cb(color, bgcolor);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
#line 43 "ansi_parser.rl"
|
||||
{
|
||||
target = &color;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
#line 46 "ansi_parser.rl"
|
||||
{
|
||||
target = &bgcolor;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
#line 50 "ansi_parser.rl"
|
||||
{
|
||||
write_cb((*p));
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
#line 54 "ansi_parser.rl"
|
||||
{
|
||||
color = $default_fg;
|
||||
color_cb(color, bgcolor);
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
#line 58 "ansi_parser.rl"
|
||||
{
|
||||
bgcolor = $default_bg;
|
||||
color_cb(color, bgcolor);
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
#line 62 "ansi_parser.rl"
|
||||
{
|
||||
color = $default_bg;
|
||||
bgcolor = $default_fg;
|
||||
color_cb(color, bgcolor);
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
#line 67 "ansi_parser.rl"
|
||||
{
|
||||
color = $default_fg;
|
||||
bgcolor = $default_bg;
|
||||
color_cb(color, bgcolor);
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
#line 72 "ansi_parser.rl"
|
||||
{
|
||||
color = sf::Color(100,100,100);
|
||||
color_cb(color, bgcolor);
|
||||
}
|
||||
break;
|
||||
case 11:
|
||||
#line 76 "ansi_parser.rl"
|
||||
{
|
||||
color = sf::Color::Red;
|
||||
color_cb(color, bgcolor);
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
#line 81 "ansi_parser.rl"
|
||||
{ target->r = value; }
|
||||
break;
|
||||
case 13:
|
||||
#line 82 "ansi_parser.rl"
|
||||
{ target->g = value; }
|
||||
break;
|
||||
case 14:
|
||||
#line 83 "ansi_parser.rl"
|
||||
{ target->b = value; }
|
||||
break;
|
||||
case 15:
|
||||
#line 84 "ansi_parser.rl"
|
||||
{ value = 0; }
|
||||
break;
|
||||
case 16:
|
||||
#line 85 "ansi_parser.rl"
|
||||
{}
|
||||
break;
|
||||
#line 296 "ansi_parser.cpp"
|
||||
}
|
||||
}
|
||||
|
||||
_again:
|
||||
if ( cs == 0 )
|
||||
goto _out;
|
||||
if ( ++p != pe )
|
||||
goto _resume;
|
||||
_test_eof: {}
|
||||
if ( p == eof )
|
||||
{
|
||||
const char *__acts = _ansi_parser_actions + _ansi_parser_eof_actions[cs];
|
||||
unsigned int __nacts = (unsigned int) *__acts++;
|
||||
while ( __nacts-- > 0 ) {
|
||||
switch ( *__acts++ ) {
|
||||
case 16:
|
||||
#line 85 "ansi_parser.rl"
|
||||
{}
|
||||
break;
|
||||
#line 314 "ansi_parser.cpp"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_out: {}
|
||||
}
|
||||
|
||||
#line 147 "ansi_parser.rl"
|
||||
|
||||
bool good = pe - p == 0;
|
||||
|
||||
if(!good) {
|
||||
p -= 10;
|
||||
// dear cthuhlu, save me from the pain that is wstring
|
||||
for(int i = 0; i < 100; i++) {
|
||||
try {
|
||||
print("{}", p[i] == 0x1B ? '^' : char(p[i]));
|
||||
} catch(...) {
|
||||
print("?=", int(p[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(void)ansi_parser_first_final;
|
||||
(void)ansi_parser_error;
|
||||
(void)ansi_parser_en_main;
|
||||
|
||||
|
||||
return good;
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
#pragma once
|
||||
#include <string_view>
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <codecvt>
|
||||
#include <functional>
|
||||
|
||||
typedef std::function<void(sf::Color bgcolor, sf::Color color)> ColorCB;
|
||||
|
||||
typedef std::function<void(wchar_t ch)> WriteCB;
|
||||
|
||||
class ANSIParser {
|
||||
sf::Color $default_fg;
|
||||
sf::Color $default_bg;
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> $converter;
|
||||
|
||||
public:
|
||||
ANSIParser(sf::Color default_fg, sf::Color default_bg);
|
||||
|
||||
// disable copying
|
||||
ANSIParser(ANSIParser& ap) = delete;
|
||||
|
||||
bool parse(std::wstring_view codes, ColorCB color_cb, WriteCB write_cb);
|
||||
};
|
167
ansi_parser.rl
|
@ -1,167 +0,0 @@
|
|||
#include <fmt/core.h>
|
||||
#include <string_view>
|
||||
#include "dbc.hpp"
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include "ansi_parser.hpp"
|
||||
#include <iostream>
|
||||
|
||||
using namespace fmt;
|
||||
|
||||
%%{
|
||||
machine ansi_parser;
|
||||
alphtype int;
|
||||
|
||||
action tstart {
|
||||
start = fpc;
|
||||
}
|
||||
|
||||
action number {
|
||||
value = 0;
|
||||
size_t len = fpc - start;
|
||||
dbc::check(start[0] != '-', "negative numbers not supported");
|
||||
|
||||
switch(len) {
|
||||
case 10: value += (start[len-10] - '0') * 1000000000; [[fallthrough]];
|
||||
case 9: value += (start[len- 9] - '0') * 100000000; [[fallthrough]];
|
||||
case 8: value += (start[len- 8] - '0') * 10000000; [[fallthrough]];
|
||||
case 7: value += (start[len- 7] - '0') * 1000000; [[fallthrough]];
|
||||
case 6: value += (start[len- 6] - '0') * 100000; [[fallthrough]];
|
||||
case 5: value += (start[len- 5] - '0') * 10000; [[fallthrough]];
|
||||
case 4: value += (start[len- 4] - '0') * 1000; [[fallthrough]];
|
||||
case 3: value += (start[len- 3] - '0') * 100; [[fallthrough]];
|
||||
case 2: value += (start[len- 2] - '0') * 10; [[fallthrough]];
|
||||
case 1: value += (start[len- 1] - '0');
|
||||
break;
|
||||
default:
|
||||
dbc::sentinel("can't process > 10 digits");
|
||||
}
|
||||
}
|
||||
|
||||
action color_out {
|
||||
color_cb(color, bgcolor);
|
||||
}
|
||||
action is_fg {
|
||||
target = &color;
|
||||
}
|
||||
action is_bg {
|
||||
target = &bgcolor;
|
||||
}
|
||||
|
||||
action out {
|
||||
write_cb(fc);
|
||||
}
|
||||
|
||||
action reset_fg {
|
||||
color = $default_fg;
|
||||
color_cb(color, bgcolor);
|
||||
}
|
||||
action reset_bg {
|
||||
bgcolor = $default_bg;
|
||||
color_cb(color, bgcolor);
|
||||
}
|
||||
action invert {
|
||||
color = $default_bg;
|
||||
bgcolor = $default_fg;
|
||||
color_cb(color, bgcolor);
|
||||
}
|
||||
action reset_invert {
|
||||
color = $default_fg;
|
||||
bgcolor = $default_bg;
|
||||
color_cb(color, bgcolor);
|
||||
}
|
||||
action half_bright {
|
||||
color = sf::Color(100,100,100);
|
||||
color_cb(color, bgcolor);
|
||||
}
|
||||
action red_text {
|
||||
color = sf::Color::Red;
|
||||
color_cb(color, bgcolor);
|
||||
}
|
||||
|
||||
action red { target->r = value; }
|
||||
action blue { target->g = value; }
|
||||
action green { target->b = value; }
|
||||
action start { value = 0; }
|
||||
action end {}
|
||||
action log { println("command {}", (char)fc); }
|
||||
|
||||
ESC = 0x1B;
|
||||
start = ESC "[";
|
||||
fg = "38;" %is_fg;
|
||||
bg = "48;" %is_bg;
|
||||
reset = ("39" %reset_fg | "49" %reset_bg);
|
||||
num = digit+ >tstart %number;
|
||||
color256 = "5;";
|
||||
color24b = "2;";
|
||||
|
||||
ansi = (
|
||||
start %start
|
||||
(
|
||||
reset |
|
||||
"0" %reset_fg %reset_bg |
|
||||
"1" |
|
||||
"2" %half_bright |
|
||||
"3" |
|
||||
"4" |
|
||||
"5" |
|
||||
"6" |
|
||||
"7" %invert |
|
||||
"31" %red_text |
|
||||
"22" |
|
||||
"24" |
|
||||
"27" %reset_invert |
|
||||
"9" ["0"-"7"] |
|
||||
"10" ["0"-"7"] |
|
||||
(fg|bg) (color24b num %red ";" num %blue ";" num %green ) %color_out
|
||||
) "m" %end
|
||||
);
|
||||
|
||||
other = (any+ @out -- ESC)*;
|
||||
|
||||
main := (other :> ansi)**;
|
||||
}%%
|
||||
|
||||
%% write data;
|
||||
|
||||
#include <ftxui/screen/terminal.hpp>
|
||||
|
||||
ANSIParser::ANSIParser(sf::Color default_fg, sf::Color default_bg) :
|
||||
$default_fg(default_fg),
|
||||
$default_bg(default_bg)
|
||||
{
|
||||
}
|
||||
|
||||
bool ANSIParser::parse(std::wstring_view codes, ColorCB color_cb, WriteCB write_cb) {
|
||||
const wchar_t *start = nullptr;
|
||||
int cs = 0;
|
||||
unsigned int value = 0;
|
||||
const wchar_t *p = codes.data();
|
||||
const wchar_t *pe = p + codes.size();
|
||||
const wchar_t *eof = pe;
|
||||
sf::Color bgcolor($default_bg);
|
||||
sf::Color color($default_fg);
|
||||
sf::Color* target = &color;
|
||||
|
||||
%% write init;
|
||||
%% write exec;
|
||||
|
||||
bool good = pe - p == 0;
|
||||
|
||||
if(!good) {
|
||||
p -= 10;
|
||||
// dear cthuhlu, save me from the pain that is wstring
|
||||
for(int i = 0; i < 100; i++) {
|
||||
try {
|
||||
print("{}", p[i] == 0x1B ? '^' : char(p[i]));
|
||||
} catch(...) {
|
||||
print("?=", int(p[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(void)ansi_parser_first_final;
|
||||
(void)ansi_parser_error;
|
||||
(void)ansi_parser_en_main;
|
||||
|
||||
return good;
|
||||
}
|
140
assets/ai.json
Normal file
|
@ -0,0 +1,140 @@
|
|||
{
|
||||
"profile": {
|
||||
"enemy_found": 0,
|
||||
"enemy_dead": 1,
|
||||
"health_good": 2,
|
||||
"no_more_items": 3,
|
||||
"no_more_enemies": 4,
|
||||
"in_combat": 5,
|
||||
"have_item": 6,
|
||||
"have_healing": 7,
|
||||
"detect_enemy": 8,
|
||||
"tough_personality": 9,
|
||||
"cant_move": 10
|
||||
},
|
||||
"actions": [
|
||||
{
|
||||
"name": "find_enemy",
|
||||
"cost": 5,
|
||||
"needs": {
|
||||
"detect_enemy": true,
|
||||
"in_combat": false,
|
||||
"no_more_enemies": false,
|
||||
"enemy_found": false
|
||||
},
|
||||
"effects": {
|
||||
"in_combat": true,
|
||||
"enemy_found": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "run_away",
|
||||
"cost": 0,
|
||||
"needs": {
|
||||
"tough_personality": false,
|
||||
"in_combat": true,
|
||||
"have_healing": false,
|
||||
"health_good": false,
|
||||
"cant_move": false
|
||||
},
|
||||
"effects": {
|
||||
"in_combat": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "kill_enemy",
|
||||
"cost": 10,
|
||||
"needs": {
|
||||
"no_more_enemies": false,
|
||||
"in_combat": true,
|
||||
"enemy_found": true,
|
||||
"enemy_dead": false
|
||||
},
|
||||
|
||||
"effects": {
|
||||
"enemy_dead": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "collect_items",
|
||||
"cost": 5,
|
||||
"needs": {
|
||||
"no_more_enemies": true,
|
||||
"no_more_items": false
|
||||
},
|
||||
"effects": {
|
||||
"no_more_items": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "find_healing",
|
||||
"cost": 2,
|
||||
"needs": {
|
||||
"have_healing": false,
|
||||
"in_combat": false,
|
||||
"health_good": false
|
||||
},
|
||||
"effects": {
|
||||
"health_good": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "use_healing",
|
||||
"cost": 1,
|
||||
"needs": {
|
||||
"have_item": true,
|
||||
"have_healing": true,
|
||||
"health_good": false
|
||||
},
|
||||
"effects": {
|
||||
"health_good": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"states": {
|
||||
"Host::initial_state": {
|
||||
"enemy_found": false,
|
||||
"enemy_dead": false,
|
||||
"health_good": true,
|
||||
"no_more_items": false,
|
||||
"no_more_enemies": false,
|
||||
"in_combat": false,
|
||||
"have_item": false,
|
||||
"have_healing": false,
|
||||
"detect_enemy": true,
|
||||
"tough_personality": true
|
||||
},
|
||||
"Host::final_state": {
|
||||
"enemy_found": true,
|
||||
"enemy_dead": true,
|
||||
"health_good": true,
|
||||
"no_more_items": true,
|
||||
"in_combat": false,
|
||||
"no_more_enemies": true
|
||||
},
|
||||
"Enemy::initial_state": {
|
||||
"detect_enemy": false,
|
||||
"tough_personality": true,
|
||||
"enemy_found": false,
|
||||
"enemy_dead": false,
|
||||
"health_good": true,
|
||||
"in_combat": false
|
||||
},
|
||||
"Enemy::final_state": {
|
||||
"detect_enemy": true,
|
||||
"enemy_found": true,
|
||||
"enemy_dead": true,
|
||||
"health_good": true
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"Host::actions":
|
||||
["find_enemy",
|
||||
"kill_enemy",
|
||||
"collect_items",
|
||||
"find_healing",
|
||||
"use_healing"],
|
||||
"Enemy::actions":
|
||||
["find_enemy", "run_away", "kill_enemy", "use_healing"]
|
||||
}
|
||||
}
|
12
assets/animations.json
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"ritual_blanket": {
|
||||
"_type": "Animation",
|
||||
"easing": 0,
|
||||
"ease_rate": 0.5,
|
||||
"scale": 1.0,
|
||||
"simple": false,
|
||||
"frames": 3,
|
||||
"speed": 0.2,
|
||||
"stationary": true
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 117 KiB |
Before Width: | Height: | Size: 107 KiB |
Before Width: | Height: | Size: 82 KiB |
|
@ -3,7 +3,7 @@
|
|||
"components": [
|
||||
{"_type": "BossFight",
|
||||
"background": "boss_fight_background",
|
||||
"stage": false,
|
||||
"stage": null,
|
||||
"weapon_sound": "Sword_Hit_2"
|
||||
},
|
||||
{"_type": "Combat", "hp": 20, "max_hp": 20, "damage": 20, "dead": false},
|
||||
|
@ -24,7 +24,7 @@
|
|||
"components": [
|
||||
{"_type": "BossFight",
|
||||
"background": "devils_fingers_background",
|
||||
"stage": false,
|
||||
"stage": "devils_fingers_stage",
|
||||
"weapon_sound": "Sword_Hit_2"
|
||||
},
|
||||
{"_type": "Combat", "hp": 20, "max_hp": 20, "damage": 20, "dead": false},
|
||||
|
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 120 KiB |
Before Width: | Height: | Size: 665 KiB After Width: | Height: | Size: 665 KiB |
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 79 KiB |
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 113 KiB |
Before Width: | Height: | Size: 1,011 KiB After Width: | Height: | Size: 1,011 KiB |
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 152 KiB |
Before Width: | Height: | Size: 466 KiB After Width: | Height: | Size: 466 KiB |
Before Width: | Height: | Size: 818 KiB After Width: | Height: | Size: 818 KiB |
Before Width: | Height: | Size: 413 KiB After Width: | Height: | Size: 413 KiB |
Before Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 249 KiB |
Before Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 75 KiB |
|
@ -17,45 +17,233 @@
|
|||
"Marmot_Scream_1": "assets/sounds/Creature_Sounds-Marmot_Scream_1.ogg",
|
||||
"blank": "assets/sounds/blank.ogg",
|
||||
"pickup": "assets/sounds/pickup.ogg",
|
||||
"ambient_1": "assets/sounds/ambient_1.ogg"
|
||||
"ambient_1": "assets/sounds/ambient_1.ogg",
|
||||
"ui_click": "assets/sounds/ui_click.ogg",
|
||||
"ui_hover": "assets/sounds/ui_hover.ogg",
|
||||
"punch_cartoony": "assets/sounds/punch_cartoony.ogg",
|
||||
"electric_shock_01": "assets/sounds/electric_shock_01.ogg",
|
||||
"fireball_01": "assets/sounds/fireball_01.ogg",
|
||||
"hp_status_80": "assets/sounds/hp_status_80.ogg",
|
||||
"hp_status_60": "assets/sounds/hp_status_60.ogg",
|
||||
"hp_status_30": "assets/sounds/hp_status_30.ogg",
|
||||
"hp_status_10": "assets/sounds/hp_status_10.ogg",
|
||||
"hp_status_00": "assets/sounds/hp_status_00.ogg"
|
||||
},
|
||||
"sprites": {
|
||||
"armored_knight": "assets/armored_knight_1-256.png",
|
||||
"sword": "assets/cinqueda_1-512.png",
|
||||
"rat_with_sword": "assets/rat_with_sword-256.png",
|
||||
"rat_king": "assets/rat_king-256.png",
|
||||
"rat_king_boss": "assets/rat_king_2_frame_animation.png",
|
||||
"barrel_small": "assets/wood_barrel_small-256.png",
|
||||
"hanging_brazier": "assets/hanging_brazier-256.png",
|
||||
"torch_pillar": "assets/torch_pillar-256.png",
|
||||
"torch_crappy": "assets/torch_crappy-256.png",
|
||||
"torch_horizontal_floor": "assets/torch_horizontal_floor-256.png",
|
||||
"evil_eye": "assets/evil_eye-sprites.png",
|
||||
"peasant_girl": "assets/undead_peasant-256.png",
|
||||
"grave_stone": "assets/grave_stone-256.png",
|
||||
"floor": "assets/floor_tile_test-256.png",
|
||||
"ceiling": "assets/ceiling_test-256.png",
|
||||
"healing_potion_small": "assets/healing_potion_small-256.png",
|
||||
"well_down": "assets/well_down-256.png",
|
||||
"rope_vines_up": "assets/rope_vines_up-256.png",
|
||||
"tripwire_trap": "assets/tripwire_trap-256.png",
|
||||
"cinqueda": "assets/cinqueda_1-256.png",
|
||||
"left_gui": "assets/left_gui.png",
|
||||
"blood_splatter": "assets/blood_splatter-256.png",
|
||||
"trash_button": "assets/trash_button.png",
|
||||
"axe_ranger": "assets/axe_ranger-256.png",
|
||||
"hairy_spider": "assets/hairy_spider-256.png",
|
||||
"down_the_well": "assets/down_the_well.jpg",
|
||||
"boss_fight_background": "assets/rat_king_boss_fight_background.jpg",
|
||||
"devils_fingers_background": "assets/devils_fingers_background.jpg",
|
||||
"devils_fingers_sprite": "assets/devils_fingers_sprite.png",
|
||||
"devils_fingers_stage": "assets/devils_fingers_stage.png",
|
||||
"tunnel_with_rocks": "assets/tunnel_with_rocks.png",
|
||||
"tunnel_with_rocks_stage": "assets/tunnel_with_rocks_stage.png"
|
||||
"gold_savior":
|
||||
{"path": "assets/sprites/gold_savior.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"armored_knight":
|
||||
{"path": "assets/sprites/armored_knight_1.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"axe_ranger":
|
||||
{"path": "assets/sprites/axe_ranger.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"hairy_spider":
|
||||
{"path": "assets/sprites/hairy_spider.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"rat_with_sword":
|
||||
{"path": "assets/sprites/rat_with_sword.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"rat_king_boss":
|
||||
{"path": "assets/bossfights/rat_king_2_frame_animation.png",
|
||||
"frame_width": 720,
|
||||
"frame_height": 720
|
||||
},
|
||||
"barrel_small":
|
||||
{"path": "assets/items/wood_barrel_small.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"torch_pillar":
|
||||
{"path": "assets/sprites/torch_pillar.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"torch_crappy":
|
||||
{"path": "assets/items/torch_crappy.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"torch_horizontal_floor":
|
||||
{"path": "assets/items/torch_horizontal_floor.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"peasant_girl":
|
||||
{"path": "assets/sprites/peasant_girl_2.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"grave_stone":
|
||||
{"path": "assets/sprites/grave_stone.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"healing_potion_small":
|
||||
{"path": "assets/items/healing_potion_small.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"well_down":
|
||||
{"path": "assets/sprites/well_down.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"rope_vines_up":
|
||||
{"path": "assets/sprites/rope_vines_up.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"tripwire_trap":
|
||||
{"path": "assets/sprites/tripwire_trap.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"boss_fight_background":
|
||||
{"path": "assets/bossfights/rat_king_boss_fight_background.jpg",
|
||||
"frame_width": 1080,
|
||||
"frame_height": 720
|
||||
},
|
||||
"devils_fingers_background":
|
||||
{"path": "assets/bossfights/devils_fingers_background.jpg",
|
||||
"frame_width": 1080,
|
||||
"frame_height": 720
|
||||
},
|
||||
"devils_fingers_sprite":
|
||||
{"path": "assets/bossfights/devils_fingers_sprite.png",
|
||||
"frame_width": 720,
|
||||
"frame_height": 720
|
||||
},
|
||||
"devils_fingers_stage":
|
||||
{"path": "assets/bossfights/devils_fingers_stage.png",
|
||||
"frame_width": 1080,
|
||||
"frame_height": 720
|
||||
},
|
||||
"tunnel_with_rocks":
|
||||
{"path": "assets/bossfights/tunnel_with_rocks.png",
|
||||
"frame_width": 1080,
|
||||
"frame_height": 720
|
||||
},
|
||||
"tunnel_with_rocks_stage":
|
||||
{"path": "assets/bossfights/tunnel_with_rocks_stage.png",
|
||||
"frame_width": 1080,
|
||||
"frame_height": 720
|
||||
},
|
||||
"ritual_crafting_area":
|
||||
{"path": "assets/ui/ritual_crafting_area.png",
|
||||
"frame_width": 380,
|
||||
"frame_height": 720
|
||||
},
|
||||
"full_screen_paper":
|
||||
{"path": "assets/ui/full_screen_paper.png",
|
||||
"frame_width": 1280,
|
||||
"frame_height": 720
|
||||
},
|
||||
"broken_locket":
|
||||
{"path": "assets/items/broken_locket.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"broken_pen_knife":
|
||||
{"path": "assets/items/broken_pen_knife.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"broken_yoyo":
|
||||
{"path": "assets/items/broken_yoyo.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"chess_pawn":
|
||||
{"path": "assets/items/chess_pawn.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"dirty_kerchief":
|
||||
{"path": "assets/items/dirty_kerchief.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"leather_pouch":
|
||||
{"path": "assets/items/leather_pouch.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"mushroom":
|
||||
{"path": "assets/items/mushroom.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"pocket_watch":
|
||||
{"path": "assets/items/pocket_watch.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"rusty_nails":
|
||||
{"path": "assets/items/rusty_nails.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"severed_finger":
|
||||
{"path": "assets/items/severed_finger.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"stone_doll_cursed":
|
||||
{"path": "assets/items/stone_doll_cursed.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"dubious_combination":
|
||||
{"path": "assets/items/dubious_combination.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"dead_body":
|
||||
{"path": "assets/sprites/dead_body.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
},
|
||||
"dead_body_lootable":
|
||||
{"path": "assets/sprites/dead_body_lootable.png",
|
||||
"frame_width": 256,
|
||||
"frame_height": 256
|
||||
}
|
||||
},
|
||||
"worldgen": {
|
||||
"enemy_probability": 80,
|
||||
"empty_room_probability": 10,
|
||||
"enemy_probability": 50,
|
||||
"device_probability": 10
|
||||
},
|
||||
"graphics": {
|
||||
"smooth_textures": false
|
||||
},
|
||||
"compass": {
|
||||
"N": 65514,
|
||||
"NE": 8663,
|
||||
"E": 8594,
|
||||
"SE": 8600,
|
||||
"S": 65516,
|
||||
"SW": 8665,
|
||||
"W": 8592,
|
||||
"NW": 8598
|
||||
},
|
||||
"theme": {
|
||||
"NOTE": "colors are in assets/palette.json",
|
||||
"padding": 3,
|
||||
"border_px": 1,
|
||||
"text_size": 20,
|
||||
"label_size": 20,
|
||||
"font_file_name": "assets/text.otf"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,13 +7,13 @@
|
|||
"inventory_count": 0,
|
||||
"randomized": false,
|
||||
"components": [
|
||||
{"_type": "Tile", "display": "\u2ac5",
|
||||
"foreground": [24, 205, 189],
|
||||
"background": [24, 205, 189]
|
||||
{"_type": "Tile", "display": 6105,
|
||||
"foreground": "devices/fg:stairs_down",
|
||||
"background": "devices/bg:stairs_down"
|
||||
},
|
||||
{"_type": "Device",
|
||||
"config": {"test": true},
|
||||
"events": ["Events::GUI::STAIRS_DOWN"]},
|
||||
"config": {},
|
||||
"events": ["STAIRS_DOWN"]},
|
||||
{"_type": "Sprite", "name": "well_down", "width": 256, "height": 256, "scale": 1.0}
|
||||
]
|
||||
},
|
||||
|
@ -24,13 +24,13 @@
|
|||
"inventory_count": 0,
|
||||
"placement": "fixed",
|
||||
"components": [
|
||||
{"_type": "Tile", "display": "\u2259",
|
||||
"foreground": [24, 205, 189],
|
||||
"background": [24, 205, 189]
|
||||
{"_type": "Tile", "display": 8793,
|
||||
"foreground": "devices/fg:stairs_up",
|
||||
"background": "devices/fg:stairs_up"
|
||||
},
|
||||
{"_type": "Device",
|
||||
"config": {"test": true},
|
||||
"events": ["Events::GUI::STAIRS_UP"]},
|
||||
"config": {},
|
||||
"events": ["STAIRS_UP"]},
|
||||
{"_type": "Sprite", "name": "rope_vines_up", "width": 256, "height": 256, "scale": 1.0}
|
||||
]
|
||||
},
|
||||
|
@ -40,14 +40,66 @@
|
|||
"description": "Watch where you're going.",
|
||||
"inventory_count": 0,
|
||||
"components": [
|
||||
{"_type": "Tile", "display": "\u1ac7",
|
||||
"foreground": [24, 205, 189],
|
||||
"background": [24, 205, 189]
|
||||
{"_type": "Tile", "display": 95,
|
||||
"foreground": "devices/fg:tripwire",
|
||||
"background": "devices/bg:tripwire"
|
||||
},
|
||||
{"_type": "Device",
|
||||
"config": {"test": true},
|
||||
"events": ["Events::GUI::TRAP"]},
|
||||
{"_type": "Device", "config": {}, "events": ["TRAP"]},
|
||||
{"_type": "Sprite", "name": "tripwire_trap", "width": 256, "height": 256, "scale": 1.0}
|
||||
]
|
||||
},
|
||||
"BARREL_SMALL": {
|
||||
"id": "BARREL_SMALL",
|
||||
"name": "Small Barrel",
|
||||
"description": "A small rotten barrel that may hold things.",
|
||||
"components": [
|
||||
{"_type": "Tile", "display": 85,
|
||||
"foreground": "devices/fg:barrel",
|
||||
"background": "devices/bg:barrel"
|
||||
},
|
||||
{"_type": "Device", "config": {}, "events": ["LOOT_CONTAINER"]},
|
||||
{"_type": "Sprite", "name": "barrel_small", "width": 256, "height": 256, "scale": 1.0},
|
||||
{"_type": "Sound", "attack": "pickup", "death": "blank"}
|
||||
]
|
||||
},
|
||||
"GRAVE_STONE": {
|
||||
"id": "GRAVE_STONE",
|
||||
"name": "Grave Stone",
|
||||
"description": "Something died here. Was this your doing?",
|
||||
"components": [
|
||||
{"_type": "Tile", "display": 8687,
|
||||
"foreground": "devices/fg:grave_stone",
|
||||
"background": "devices/bg:grave_stone"
|
||||
},
|
||||
{"_type": "Device", "config": {}, "events": ["LOOT_CONTAINER"]},
|
||||
{"_type": "Sprite", "name": "grave_stone", "width": 256, "height": 256, "scale": 1.0},
|
||||
{"_type": "Sound", "attack": "pickup", "death": "blank"}
|
||||
]
|
||||
},
|
||||
"DEAD_BODY_LOOTABLE": {
|
||||
"id": "DEAD_BODY_LOOTABLE",
|
||||
"name": "Grave Stone",
|
||||
"description": "Something died here. Was this your doing?",
|
||||
"components": [
|
||||
{"_type": "Tile", "display": 1890,
|
||||
"foreground": "devices/fg:dead_body_lootable",
|
||||
"background": "devices/bg:dead_body_lootable"
|
||||
},
|
||||
{"_type": "Device", "config": {}, "events": ["LOOT_CONTAINER"]},
|
||||
{"_type": "Sprite", "name": "dead_body_lootable", "width": 256, "height": 256, "scale": 1.0},
|
||||
{"_type": "Sound", "attack": "pickup", "death": "blank"}
|
||||
]
|
||||
},
|
||||
"DEAD_BODY": {
|
||||
"id": "DEAD_BODY",
|
||||
"name": "Something Dead",
|
||||
"description": "You can't loot this, weirdo.",
|
||||
"components": [
|
||||
{"_type": "Tile", "display": 1939,
|
||||
"foreground": "devices/fg:dead_body",
|
||||
"background": "devices/bg:dead_body"
|
||||
},
|
||||
{"_type": "Sprite", "name": "dead_body", "width": 256, "height": 256, "scale": 1.0}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,24 +2,43 @@
|
|||
"PLAYER_TILE": {
|
||||
"placement": "fixed",
|
||||
"components": [
|
||||
{"_type": "Tile", "display": "\ua66b",
|
||||
"foreground": [255, 200, 125],
|
||||
"background": [30, 20, 75]
|
||||
{"_type": "Tile", "display": 10733,
|
||||
"foreground": "enemies/fg:player",
|
||||
"background": "color:transparent"
|
||||
},
|
||||
{"_type": "Combat", "hp": 200, "max_hp": 200, "damage": 10, "dead": false},
|
||||
{"_type": "Motion", "dx": 0, "dy": 0, "random": false},
|
||||
{"_type": "LightSource", "strength": 45, "radius": 2.0}
|
||||
{"_type": "Collision", "has": true},
|
||||
{"_type": "LightSource", "strength": 35, "radius": 2.0}
|
||||
]
|
||||
},
|
||||
"GOLD_SAVIOR": {
|
||||
"components": [
|
||||
{"_type": "Tile", "display": 42586,
|
||||
"foreground": "enemies/fg:gold_savior",
|
||||
"background": "color:transparent"
|
||||
},
|
||||
{"_type": "Combat", "hp": 20, "max_hp": 20, "damage": 1, "dead": false},
|
||||
{"_type": "Collision", "has": true},
|
||||
{"_type": "Motion", "dx": 0, "dy": 0, "random": false},
|
||||
{"_type": "EnemyConfig", "ai_script": "Enemy::actions", "ai_start_name": "Enemy::initial_state", "ai_goal_name": "Enemy::final_state"},
|
||||
{"_type": "Personality", "hearing_distance": 5, "tough": true},
|
||||
{"_type": "Animation", "easing": 1, "ease_rate": 0.2, "scale": 0.1, "simple": true, "frames": 10, "speed": 0.3, "stationary": false},
|
||||
{"_type": "Sprite", "name": "gold_savior", "width": 256, "height": 256, "width": 256, "height": 256, "scale": 1.0},
|
||||
{"_type": "Sound", "attack": "Sword_Hit_2", "death": "Humanoid_Death_1"}
|
||||
]
|
||||
},
|
||||
"KNIGHT": {
|
||||
"components": [
|
||||
{"_type": "Tile", "display": "\u088d",
|
||||
"foreground": [131, 213, 238],
|
||||
"background": [30, 20, 75]
|
||||
{"_type": "Tile", "display": 2216,
|
||||
"foreground": "enemies/fg:knight",
|
||||
"background": "color:transparent"
|
||||
},
|
||||
{"_type": "Combat", "hp": 20, "max_hp": 20, "damage": 1, "dead": false},
|
||||
{"_type": "Collision", "has": true},
|
||||
{"_type": "Motion", "dx": 0, "dy": 0, "random": false},
|
||||
{"_type": "EnemyConfig", "hearing_distance": 5},
|
||||
{"_type": "EnemyConfig", "ai_script": "Enemy::actions", "ai_start_name": "Enemy::initial_state", "ai_goal_name": "Enemy::final_state"},
|
||||
{"_type": "Personality", "hearing_distance": 5, "tough": true},
|
||||
{"_type": "Animation", "easing": 1, "ease_rate": 0.2, "scale": 0.1, "simple": true, "frames": 10, "speed": 0.3, "stationary": false},
|
||||
{"_type": "Sprite", "name": "armored_knight", "width": 256, "height": 256, "width": 256, "height": 256, "scale": 1.0},
|
||||
{"_type": "Sound", "attack": "Sword_Hit_2", "death": "Humanoid_Death_1"}
|
||||
|
@ -27,41 +46,47 @@
|
|||
},
|
||||
"AXE_RANGER": {
|
||||
"components": [
|
||||
{"_type": "Tile", "display": "\u076a",
|
||||
"foreground": [156, 172, 197],
|
||||
"background": [30, 20, 75]
|
||||
{"_type": "Tile", "display": 1898,
|
||||
"foreground": "enemies/fg:axe_ranger",
|
||||
"background": "color:transparent"
|
||||
},
|
||||
{"_type": "Combat", "hp": 40, "max_hp": 40, "damage": 10, "dead": false},
|
||||
{"_type": "Collision", "has": true},
|
||||
{"_type": "Motion", "dx": 0, "dy": 0, "random": true},
|
||||
{"_type": "EnemyConfig", "hearing_distance": 5},
|
||||
{"_type": "EnemyConfig", "ai_script": "Enemy::actions", "ai_start_name": "Enemy::initial_state", "ai_goal_name": "Enemy::final_state"},
|
||||
{"_type": "Personality", "hearing_distance": 5, "tough": true},
|
||||
{"_type": "Sprite", "name": "axe_ranger", "width": 256, "height": 256, "scale": 1.0},
|
||||
{"_type": "Animation", "easing": 3, "ease_rate": 0.5, "scale": 0.1, "simple": false, "frames": 2, "speed": 0.6, "stationary": false},
|
||||
{"_type": "Animation", "easing": 3, "ease_rate": 0.5, "scale": 0.1, "simple": true, "frames": 1, "speed": 0.6, "stationary": false},
|
||||
{"_type": "Sound", "attack": "Sword_Hit_2", "death": "Ranger_1"}
|
||||
]
|
||||
},
|
||||
"RAT_GIANT": {
|
||||
"components": [
|
||||
{"_type": "Tile", "display": "\u08ac",
|
||||
"foreground": [205, 164, 246],
|
||||
"background": [30, 20, 75]
|
||||
{"_type": "Tile", "display": 2220,
|
||||
"foreground": "enemies/fg:rat_giant",
|
||||
"background": "color:transparent"
|
||||
},
|
||||
{"_type": "Combat", "hp": 20, "max_hp": 20, "damage": 20, "dead": false},
|
||||
{"_type": "Combat", "hp": 50, "max_hp": 50, "damage": 2, "dead": false},
|
||||
{"_type": "Collision", "has": true},
|
||||
{"_type": "Motion", "dx": 0, "dy": 0, "random": false},
|
||||
{"_type": "EnemyConfig", "hearing_distance": 10},
|
||||
{"_type": "Animation", "easing": 3, "ease_rate": 0.5, "scale": 0.1, "simple": true, "frames": 10, "speed": 1.0, "stationary": false},
|
||||
{"_type": "EnemyConfig", "ai_script": "Enemy::actions", "ai_start_name": "Enemy::initial_state", "ai_goal_name": "Enemy::final_state"},
|
||||
{"_type": "Personality", "hearing_distance": 5, "tough": true},
|
||||
{"_type": "Animation", "easing": 3, "ease_rate": 0.5, "scale": 0.1, "simple": true, "frames": 1, "speed": 1.0, "stationary": false},
|
||||
{"_type": "Sprite", "name": "rat_with_sword", "width": 256, "height": 256, "scale": 1.0},
|
||||
{"_type": "Sound", "attack": "Small_Rat", "death": "Creature_Death_1"}
|
||||
]
|
||||
},
|
||||
"SPIDER_GIANT_HAIRY": {
|
||||
"components": [
|
||||
{"_type": "Tile", "display": "\u08ea",
|
||||
"foreground": [205, 164, 246],
|
||||
"background": [30, 20, 75]
|
||||
{"_type": "Tile", "display": 1218,
|
||||
"foreground": "enemies/fg:spider_giant",
|
||||
"background": "color:transparent"
|
||||
},
|
||||
{"_type": "Combat", "hp": 20, "max_hp": 20, "damage": 20, "dead": false},
|
||||
{"_type": "Collision", "has": true},
|
||||
{"_type": "Motion", "dx": 0, "dy": 0, "random": false},
|
||||
{"_type": "EnemyConfig", "hearing_distance": 10},
|
||||
{"_type": "EnemyConfig", "ai_script": "Enemy::actions", "ai_start_name": "Enemy::initial_state", "ai_goal_name": "Enemy::final_state"},
|
||||
{"_type": "Personality", "hearing_distance": 5, "tough": true},
|
||||
{"_type": "Animation", "easing": 2, "ease_rate": 0.5, "scale": 0.1, "simple": true, "frames": 10, "speed": 1.0, "stationary": false},
|
||||
{"_type": "Sprite", "name": "hairy_spider", "width": 256, "height": 256, "scale": 1.0},
|
||||
{"_type": "Sound", "attack": "Spider_1", "death": "Spider_2"}
|
||||
|
|
Before Width: | Height: | Size: 316 KiB |
Before Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 204 KiB |
Before Width: | Height: | Size: 89 KiB |
Before Width: | Height: | Size: 350 KiB |
Before Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 11 KiB |
12
assets/icons.json
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"healing_potion_small":
|
||||
{"path": "assets/icons/healing_potion_small.png",
|
||||
"frame_width": 96,
|
||||
"frame_height": 96
|
||||
},
|
||||
"torch_horizontal_floor":
|
||||
{"path": "assets/icons/torch_horizontal_floor.png",
|
||||
"frame_width": 96,
|
||||
"frame_height": 96
|
||||
}
|
||||
}
|
BIN
assets/icons/healing_potion_small.png
Normal file
After Width: | Height: | Size: 7.5 KiB |
BIN
assets/icons/torch_horizontal_floor.png
Normal file
After Width: | Height: | Size: 5.6 KiB |
|
@ -6,87 +6,27 @@
|
|||
"inventory_count": 1,
|
||||
"components": [
|
||||
{"_type": "LightSource", "strength": 50, "radius": 2.5},
|
||||
{"_type": "Tile", "display": "\u0f08",
|
||||
"foreground": [24, 120, 189],
|
||||
"background": [230,120, 120]
|
||||
{"_type": "Tile", "display": 3848,
|
||||
"foreground": "items/fg:flame",
|
||||
"background": "color:transparent"
|
||||
},
|
||||
{"_type": "Sprite", "name": "torch_horizontal_floor", "width": 256, "height": 256, "scale": 1.0},
|
||||
{"_type": "Sound", "attack": "pickup", "death": "blank"}
|
||||
]
|
||||
},
|
||||
"SWORD_RUSTY": {
|
||||
"id": "SWORD_RUSTY",
|
||||
"name": "Rusty Junk Sword",
|
||||
"description": "A sword left to rot in a deep hole where it acquired a patina of dirt and tetanus. You aren't sure if it's more deadly for you to hold it or for the people you stab with it.",
|
||||
"inventory_count": 1,
|
||||
"components": [
|
||||
{"_type": "Weapon", "damage": 15},
|
||||
{"_type": "Tile", "display": "\u1e37",
|
||||
"foreground": [24, 120, 189],
|
||||
"background": [24, 120, 189]
|
||||
},
|
||||
{"_type": "Sprite", "name": "cinqueda", "width": 256, "height": 256, "scale": 1.0},
|
||||
{"_type": "Sound", "attack": "pickup", "death": "blank"}
|
||||
]
|
||||
},
|
||||
"BARREL_SMALL": {
|
||||
"id": "BARREL_SMALL",
|
||||
"name": "Small Barrel",
|
||||
"description": "A small rotten barrel that may hold things.",
|
||||
"components": [
|
||||
{"_type": "Tile", "display": "\uaaea",
|
||||
"foreground": [150, 100, 189],
|
||||
"background": [150, 100, 189]
|
||||
},
|
||||
{"_type": "Loot", "amount": 10},
|
||||
{"_type": "Sprite", "name": "barrel_small", "width": 256, "height": 256, "scale": 1.0},
|
||||
{"_type": "Sound", "attack": "pickup", "death": "blank"}
|
||||
],
|
||||
"inventory_count": 1
|
||||
},
|
||||
"TORCH_PILLAR": {
|
||||
"id": "TORCH_PILLAR",
|
||||
"name": "Light Hanging from Ceiling",
|
||||
"description": "Light Hanging from Ceiling",
|
||||
"inventory_count": 0,
|
||||
"components": [
|
||||
{"_type": "Tile", "display": "\u077e",
|
||||
"foreground": [24, 205, 210],
|
||||
"background": [24, 205, 210]
|
||||
},
|
||||
{"_type": "LightSource", "strength": 50, "radius": 2.8},
|
||||
{"_type": "Sprite", "name": "torch_pillar", "width": 256, "height": 256, "scale": 1.0},
|
||||
{"_type": "Sound", "attack": "pickup", "death": "blank"}
|
||||
]
|
||||
},
|
||||
"POTION_HEALING_SMALL": {
|
||||
"id": "POTION_HEALING_SMALL",
|
||||
"name": "Small Healing Potion",
|
||||
"description": "A small healing potion.",
|
||||
"inventory_count": 1,
|
||||
"components": [
|
||||
{"_type": "Tile", "display": "\u03eb",
|
||||
"foreground": [255, 205, 189],
|
||||
"background": [255, 205, 189]
|
||||
{"_type": "Tile", "display": 1003,
|
||||
"foreground": "items/fg:potion",
|
||||
"background": "color:transparent"
|
||||
},
|
||||
{"_type": "Curative", "hp": 20},
|
||||
{"_type": "Sprite", "name": "healing_potion_small", "width": 256, "height": 256, "scale": 1.0},
|
||||
{"_type": "Sound", "attack": "pickup", "death": "blank"}
|
||||
]
|
||||
},
|
||||
"GRAVE_STONE": {
|
||||
"id": "GRAVE_STONE",
|
||||
"name": "Grave Stone",
|
||||
"description": "Something died here. Was this your doing?",
|
||||
"inventory_count": 1,
|
||||
"components": [
|
||||
{"_type": "Tile", "display": "\u21ef",
|
||||
"foreground": [32, 123, 164],
|
||||
"background": [24, 205, 189]
|
||||
},
|
||||
{"_type": "Loot", "amount": 10},
|
||||
{"_type": "Sprite", "name": "grave_stone", "width": 256, "height": 256, "scale": 1.0},
|
||||
{"_type": "Sound", "attack": "pickup", "death": "blank"}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
BIN
assets/items/broken_locket.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
assets/items/broken_pen_knife.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
assets/items/broken_yoyo.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
assets/items/chess_pawn.png
Normal file
After Width: | Height: | Size: 8.3 KiB |
BIN
assets/items/cinqueda.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
assets/items/dirty_kerchief.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
assets/items/dubious_combination.png
Normal file
After Width: | Height: | Size: 7.1 KiB |
BIN
assets/items/healing_postion_small.png
Normal file
After Width: | Height: | Size: 7 KiB |
BIN
assets/items/healing_potion_small.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
assets/items/leather_pouch.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
assets/items/mushroom.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
assets/items/pocket_watch.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
assets/items/rusty_nails.png
Normal file
After Width: | Height: | Size: 7.8 KiB |
BIN
assets/items/severed_finger.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
assets/items/stone_doll_cursed.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
assets/items/torch_crappy.png
Normal file
After Width: | Height: | Size: 7.5 KiB |
BIN
assets/items/torch_horizontal_floor.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
assets/items/wood_barrel_small.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 85 KiB |
140
assets/map_tiles.json
Normal file
|
@ -0,0 +1,140 @@
|
|||
[
|
||||
{
|
||||
"centered": false,
|
||||
"display": 35,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"centered": false,
|
||||
"display": 8284,
|
||||
"x": 64,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"centered": false,
|
||||
"display": 11590,
|
||||
"x": 128,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"centered": false,
|
||||
"display": 10899,
|
||||
"x": 192,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"centered": false,
|
||||
"display": 9256,
|
||||
"x": 256,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"centered": false,
|
||||
"display": 9608,
|
||||
"x": 320,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"centered": false,
|
||||
"display": 10747,
|
||||
"x": 384,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"centered": false,
|
||||
"display": 8285,
|
||||
"x": 448,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"centered": true,
|
||||
"display": 1003,
|
||||
"x": 512,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"centered": true,
|
||||
"display": 3848,
|
||||
"x": 576,
|
||||
"y": 0
|
||||
},
|
||||
{
|
||||
"centered": true,
|
||||
"display": 85,
|
||||
"x": 0,
|
||||
"y": 64
|
||||
},
|
||||
{
|
||||
"centered": true,
|
||||
"display": 1939,
|
||||
"x": 64,
|
||||
"y": 64
|
||||
},
|
||||
{
|
||||
"centered": true,
|
||||
"display": 1890,
|
||||
"x": 128,
|
||||
"y": 64
|
||||
},
|
||||
{
|
||||
"centered": true,
|
||||
"display": 8687,
|
||||
"x": 192,
|
||||
"y": 64
|
||||
},
|
||||
{
|
||||
"centered": true,
|
||||
"display": 6105,
|
||||
"x": 256,
|
||||
"y": 64
|
||||
},
|
||||
{
|
||||
"centered": true,
|
||||
"display": 8793,
|
||||
"x": 320,
|
||||
"y": 64
|
||||
},
|
||||
{
|
||||
"centered": true,
|
||||
"display": 95,
|
||||
"x": 384,
|
||||
"y": 64
|
||||
},
|
||||
{
|
||||
"centered": true,
|
||||
"display": 1898,
|
||||
"x": 448,
|
||||
"y": 64
|
||||
},
|
||||
{
|
||||
"centered": true,
|
||||
"display": 42586,
|
||||
"x": 512,
|
||||
"y": 64
|
||||
},
|
||||
{
|
||||
"centered": true,
|
||||
"display": 2216,
|
||||
"x": 576,
|
||||
"y": 64
|
||||
},
|
||||
{
|
||||
"centered": true,
|
||||
"display": 10733,
|
||||
"x": 0,
|
||||
"y": 128
|
||||
},
|
||||
{
|
||||
"centered": true,
|
||||
"display": 2220,
|
||||
"x": 64,
|
||||
"y": 128
|
||||
},
|
||||
{
|
||||
"centered": true,
|
||||
"display": 1218,
|
||||
"x": 128,
|
||||
"y": 128
|
||||
}
|
||||
]
|
BIN
assets/map_tiles.png
Normal file
After Width: | Height: | Size: 9.5 KiB |
81
assets/palette.json
Normal file
|
@ -0,0 +1,81 @@
|
|||
{
|
||||
"color": {
|
||||
"transparent": [100, 100, 100, 100],
|
||||
"BAD": [255, 0, 0]
|
||||
},
|
||||
"gui/theme": {
|
||||
"black": [0, 0, 0, 255],
|
||||
"dark_dark": [10, 10, 10, 255],
|
||||
"dark_mid": [30, 30, 30, 255],
|
||||
"dark_light": [60, 60, 60, 255],
|
||||
"mid": [100, 100, 100, 255],
|
||||
"light_dark": [150, 150, 150, 255],
|
||||
"light_mid": [200, 200, 200, 255],
|
||||
"light_light": [230, 230, 230, 255],
|
||||
"white": [255, 255, 255, 255],
|
||||
"fill_color": "gui/theme:dark_mid",
|
||||
"text_color": "gui/theme:light_light",
|
||||
"bg_color": "gui/theme:mid",
|
||||
"border_color": "gui/theme:dark_dark",
|
||||
"bg_color_dark": "gui/theme:black"
|
||||
},
|
||||
"map/theme": {
|
||||
"black": [0, 0, 0, 255],
|
||||
"dark_dark": [10, 10, 10, 255],
|
||||
"dark_mid": [30, 30, 30, 255],
|
||||
"dark_light": [60, 60, 60, 255],
|
||||
"mid": [100, 100, 100, 255],
|
||||
"light_dark": [150, 150, 150, 255],
|
||||
"light_mid": [200, 200, 200, 255],
|
||||
"light_light": [230, 230, 230, 255],
|
||||
"white": [255, 255, 255, 255]
|
||||
},
|
||||
"items/fg": {
|
||||
"flame": "map/theme:white",
|
||||
"potion": "map/theme:white"
|
||||
},
|
||||
"enemies/fg": {
|
||||
"player": "map/theme:white",
|
||||
"gold_savior": "map/theme:white",
|
||||
"knight": "map/theme:white",
|
||||
"axe_ranger": "map/theme:white",
|
||||
"rat_giant": "map/theme:white",
|
||||
"spider_giant": "map/theme:white"
|
||||
},
|
||||
"tiles/fg": {
|
||||
"floor_tile": "map/theme:mid",
|
||||
"wall_plain": "map/theme:dark_mid",
|
||||
"wall_moss": "map/theme:dark_light",
|
||||
"ceiling_black": "color:transparent",
|
||||
"lava_floor": [200, 100, 100],
|
||||
"gray_stone_floor_light": [40, 60, 180],
|
||||
"wood_wall": "map/theme:dark_mid"
|
||||
},
|
||||
"tiles/bg": {
|
||||
"floor_tile": "map/theme:dark_dark",
|
||||
"wall_plain": "map/theme:dark_dark",
|
||||
"wall_moss": "map/theme:light_dark",
|
||||
"ceiling_black": "color:transparent",
|
||||
"lava_floor": "map/theme:dark_dark",
|
||||
"gray_stone_floor_light": "map/theme:dark_mid",
|
||||
"wood_wall": "map/theme:dark_dark"
|
||||
},
|
||||
"devices/fg": {
|
||||
"stairs_down": [24, 205, 189],
|
||||
"stairs_up": [24, 205, 189],
|
||||
"tripwire": [24, 205, 189],
|
||||
"barrel": [150, 100, 189],
|
||||
"grave_stone": [32, 123, 164],
|
||||
"dead_body": [32, 123, 164],
|
||||
"dead_body_lootable": [32, 123, 164]
|
||||
},
|
||||
"devices/bg": {
|
||||
"stairs_down": [24, 205, 189],
|
||||
"stairs_up": [24, 205, 189],
|
||||
"tripwire": [24, 205, 189],
|
||||
"barrel": [150, 100, 189],
|
||||
"grave_stone": [24, 205, 189],
|
||||
"dead_body": [24, 205, 189],
|
||||
"dead_body_lootable": [24, 205, 189]
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 211 KiB |
Before Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 20 KiB |
202
assets/rituals.json
Normal file
|
@ -0,0 +1,202 @@
|
|||
{
|
||||
"profile": {
|
||||
"has_spikes": 0,
|
||||
"has_magick": 1,
|
||||
"shiny_bauble": 2,
|
||||
"cursed_item": 3,
|
||||
"$does_physical": 4,
|
||||
"$does_magick": 5,
|
||||
"$does_damage": 6,
|
||||
"$user_cursed": 7,
|
||||
"$does_healing": 8,
|
||||
"$damage_boost": 9,
|
||||
"$large_boost": 10,
|
||||
"$is_complete": 11
|
||||
},
|
||||
"actions": [
|
||||
{
|
||||
"name": "pierce_type",
|
||||
"cost": 100,
|
||||
"needs": {
|
||||
"has_spikes": true,
|
||||
"$is_complete": false
|
||||
},
|
||||
"effects": {
|
||||
"$does_physical": true,
|
||||
"$does_damage": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "magick_type",
|
||||
"cost": 100,
|
||||
"needs": {
|
||||
"$is_complete": false,
|
||||
"has_magick": true
|
||||
},
|
||||
"effects": {
|
||||
"$does_magick": true,
|
||||
"$does_damage": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "combined",
|
||||
"cost": 0,
|
||||
"needs": {
|
||||
"$does_damage": true
|
||||
},
|
||||
"effects": {
|
||||
"$is_complete": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "boost_magick",
|
||||
"cost": 0,
|
||||
"needs": {
|
||||
"shiny_bauble": true,
|
||||
"$does_magick": true,
|
||||
"$does_damage": true,
|
||||
"$is_complete": false,
|
||||
"$user_cursed": false
|
||||
},
|
||||
"effects": {
|
||||
"$damage_boost": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "boost_damage_large",
|
||||
"cost": 0,
|
||||
"needs": {
|
||||
"$user_cursed": true,
|
||||
"$is_complete": false,
|
||||
"$does_damage": true
|
||||
},
|
||||
"effects": {
|
||||
"$large_boost": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "curses_user",
|
||||
"cost": 1000,
|
||||
"needs": {
|
||||
"$is_complete": false,
|
||||
"cursed_item": true
|
||||
},
|
||||
"effects": {
|
||||
"$user_cursed": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "heals_user",
|
||||
"cost": 0,
|
||||
"needs": {
|
||||
"cursed_item": true,
|
||||
"$does_damage": false
|
||||
},
|
||||
"effects": {
|
||||
"$does_healing": true,
|
||||
"$is_complete": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"states": {
|
||||
"initial": {
|
||||
"shiny_bauble": false,
|
||||
"cursed_item": false,
|
||||
"has_spikes": false,
|
||||
"has_magick": false,
|
||||
"$user_cursed": false,
|
||||
"$does_damage": false,
|
||||
"$is_complete": false,
|
||||
"$does_healing": false,
|
||||
"$does_magick": false,
|
||||
"$does_physical": false,
|
||||
"$large_boost": false,
|
||||
"$damage_boost": false
|
||||
},
|
||||
"final": {
|
||||
"$user_cursed": true,
|
||||
"$does_damage": true,
|
||||
"$is_complete": true,
|
||||
"$does_healing": true,
|
||||
"$does_magick": true,
|
||||
"$does_physical": true,
|
||||
"$large_boost": true,
|
||||
"$damage_boost": true
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"actions": [
|
||||
"boost_magick",
|
||||
"pierce_type",
|
||||
"magick_type",
|
||||
"heals_user",
|
||||
"curses_user",
|
||||
"boost_damage_large",
|
||||
"combined"
|
||||
]
|
||||
},
|
||||
"effects": {
|
||||
"boost_magick": {
|
||||
"damage": 10,
|
||||
"kind": 2,
|
||||
"element": 2,
|
||||
"probability": 1.0
|
||||
},
|
||||
"pierce_type": {
|
||||
"damage": 11,
|
||||
"kind": 1,
|
||||
"probability": 1.0
|
||||
},
|
||||
"magick_type": {
|
||||
"damage": 12,
|
||||
"kind": 2,
|
||||
"element": 1,
|
||||
"probability": 1.0
|
||||
},
|
||||
"heals_user": {
|
||||
"damage": 13,
|
||||
"probability": 1.0
|
||||
},
|
||||
"curses_user": {
|
||||
"damage": 14,
|
||||
"probability": 0.5
|
||||
},
|
||||
"boost_damage_large": {
|
||||
"damage": 15,
|
||||
"probability": 1.0
|
||||
},
|
||||
"combined": {
|
||||
"damage": 16,
|
||||
"probability": 1.0
|
||||
}
|
||||
},
|
||||
"junk": {
|
||||
"chess_pawn": {
|
||||
"name": "chess_pawn",
|
||||
"provides": ["cursed_item"]
|
||||
},
|
||||
"dirty_kerchief": {
|
||||
"name": "dirty_kerchief",
|
||||
"provides": ["has_magick"]
|
||||
},
|
||||
"mushroom": {
|
||||
"name": "mushroom",
|
||||
"provides": ["has_magick"]
|
||||
},
|
||||
"pocket_watch": {
|
||||
"name": "pocket_watch",
|
||||
"provides": ["shiny_bauble"]
|
||||
},
|
||||
"rusty_nails": {
|
||||
"name": "rusty_nails",
|
||||
"provides": ["has_spikes"]
|
||||
},
|
||||
"severed_finger": {
|
||||
"name": "severed_finger",
|
||||
"provides": ["cursed_item"]
|
||||
}
|
||||
},
|
||||
"starting_junk": [
|
||||
"pocket_watch", "mushroom", "rusty_nails"
|
||||
]
|
||||
}
|
BIN
assets/rituals/broken_locket-128.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
assets/rituals/broken_locket-64.png
Normal file
After Width: | Height: | Size: 8.1 KiB |
BIN
assets/rituals/broken_pen_knife-128.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
assets/rituals/broken_pen_knife-64.png
Normal file
After Width: | Height: | Size: 6.9 KiB |
BIN
assets/rituals/broken_yoyo-128.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
assets/rituals/broken_yoyo-64.png
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
assets/rituals/chess_pawn-128.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
assets/rituals/chess_pawn-64.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
assets/rituals/dirty_kerchief-128.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
assets/rituals/dirty_kerchief-64.png
Normal file
After Width: | Height: | Size: 6.5 KiB |
BIN
assets/rituals/dubious_combination-128.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
assets/rituals/dubious_combination-64.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
assets/rituals/leather_pouch-128.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
assets/rituals/leather_pouch-64.png
Normal file
After Width: | Height: | Size: 5.9 KiB |
BIN
assets/rituals/mushroom-128.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
assets/rituals/mushroom-64.png
Normal file
After Width: | Height: | Size: 6.9 KiB |
BIN
assets/rituals/pocket_watch-128.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
assets/rituals/pocket_watch-64.png
Normal file
After Width: | Height: | Size: 8.9 KiB |
BIN
assets/rituals/rusty_nails-128.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
assets/rituals/rusty_nails-64.png
Normal file
After Width: | Height: | Size: 6.5 KiB |
BIN
assets/rituals/severed_finger-128.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
assets/rituals/severed_finger-64.png
Normal file
After Width: | Height: | Size: 9.2 KiB |
BIN
assets/rituals/stone_doll_cursed-128.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
assets/rituals/stone_doll_cursed-64.png
Normal file
After Width: | Height: | Size: 6.1 KiB |